@skaile/workspaces 6.2.0 → 6.4.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 (300) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/ai-sdk.d.ts +2 -0
  3. package/dist/ai-sdk.js +123 -0
  4. package/dist/ai-sdk.js.map +1 -0
  5. package/dist/app-sdk/index.js +1 -1
  6. package/dist/{asset-feeds-KPKCE64E.js → asset-feeds-UJSYGKCX.js} +20 -20
  7. package/dist/{asset-feeds-KPKCE64E.js.map → asset-feeds-UJSYGKCX.js.map} +1 -1
  8. package/dist/asset-manager/catalog-deployer.js +7 -7
  9. package/dist/asset-manager/index.js +12 -12
  10. package/dist/asset-manager/installer.js +8 -8
  11. package/dist/asset-manager/renderers.js +7 -7
  12. package/dist/asset-manager/src/index.d.ts +42 -15
  13. package/dist/asset-manager/src/index.d.ts.map +1 -1
  14. package/dist/asset-manager/src/install-instances.d.ts +2 -0
  15. package/dist/asset-manager/src/install-instances.d.ts.map +1 -1
  16. package/dist/asset-manager/src/installer.d.ts.map +1 -1
  17. package/dist/bridge/harnesses/claude-sdk.js +13 -12
  18. package/dist/bridge/harnesses/claude-sdk.js.map +1 -1
  19. package/dist/bridge/harnesses/codex.js +12 -11
  20. package/dist/bridge/harnesses/codex.js.map +1 -1
  21. package/dist/bridge/harnesses/continue.js +11 -10
  22. package/dist/bridge/harnesses/continue.js.map +1 -1
  23. package/dist/bridge/harnesses/echo.js +6 -5
  24. package/dist/bridge/harnesses/echo.js.map +1 -1
  25. package/dist/bridge/harnesses/gemini.js +8 -7
  26. package/dist/bridge/harnesses/goose.js +11 -10
  27. package/dist/bridge/harnesses/goose.js.map +1 -1
  28. package/dist/bridge/harnesses/omp.js +8 -7
  29. package/dist/bridge/harnesses/omp.js.map +1 -1
  30. package/dist/bridge/harnesses/opencode.js +11 -10
  31. package/dist/bridge/harnesses/opencode.js.map +1 -1
  32. package/dist/bridge/harnesses/qwen.js +8 -7
  33. package/dist/bridge/harnesses/qwen.js.map +1 -1
  34. package/dist/bridge/index.js +18 -16
  35. package/dist/bridge/src/ai-sdk.d.ts +51 -0
  36. package/dist/bridge/src/ai-sdk.d.ts.map +1 -0
  37. package/dist/bridge/src/harness-model-check.d.ts +11 -7
  38. package/dist/bridge/src/harness-model-check.d.ts.map +1 -1
  39. package/dist/bridge/src/index.d.ts +1 -0
  40. package/dist/bridge/src/index.d.ts.map +1 -1
  41. package/dist/bridge/src/provider-registry-load.d.ts +30 -0
  42. package/dist/bridge/src/provider-registry-load.d.ts.map +1 -0
  43. package/dist/{chunk-7DRFKAJZ.js → chunk-24D7IW5O.js} +8 -7
  44. package/dist/chunk-24D7IW5O.js.map +1 -0
  45. package/dist/{chunk-ITFCWMOY.js → chunk-2WOA3TKK.js} +12 -12
  46. package/dist/chunk-2WOA3TKK.js.map +1 -0
  47. package/dist/{chunk-QPWR3YMY.js → chunk-3ENE6ZOF.js} +4 -4
  48. package/dist/{chunk-QPWR3YMY.js.map → chunk-3ENE6ZOF.js.map} +1 -1
  49. package/dist/{chunk-ICSGNT5P.js → chunk-45KLCFQB.js} +8 -27
  50. package/dist/chunk-45KLCFQB.js.map +1 -0
  51. package/dist/{chunk-Q5RN4PWV.js → chunk-5NHBLKKU.js} +3 -3
  52. package/dist/{chunk-Q5RN4PWV.js.map → chunk-5NHBLKKU.js.map} +1 -1
  53. package/dist/{chunk-RQMIZONH.js → chunk-5T3DTK7A.js} +43 -24
  54. package/dist/chunk-5T3DTK7A.js.map +1 -0
  55. package/dist/{chunk-X37JUNEW.js → chunk-6UP2EDFN.js} +4 -313
  56. package/dist/chunk-6UP2EDFN.js.map +1 -0
  57. package/dist/{chunk-KJSC2ZD6.js → chunk-6WQGJF65.js} +18 -6
  58. package/dist/chunk-6WQGJF65.js.map +1 -0
  59. package/dist/{chunk-BOT64P3U.js → chunk-6X3GDPCB.js} +4 -3
  60. package/dist/chunk-6X3GDPCB.js.map +1 -0
  61. package/dist/{chunk-T2VBPVWZ.js → chunk-76WSWPOB.js} +15 -7
  62. package/dist/{chunk-T2VBPVWZ.js.map → chunk-76WSWPOB.js.map} +1 -1
  63. package/dist/{chunk-BRK5QZKI.js → chunk-ABVWUM2E.js} +27 -17
  64. package/dist/chunk-ABVWUM2E.js.map +1 -0
  65. package/dist/{chunk-MM4YO3EL.js → chunk-ACBL7X62.js} +3 -3
  66. package/dist/{chunk-MM4YO3EL.js.map → chunk-ACBL7X62.js.map} +1 -1
  67. package/dist/{chunk-VUJXZDCY.js → chunk-BOS7P2Y4.js} +3 -3
  68. package/dist/{chunk-VUJXZDCY.js.map → chunk-BOS7P2Y4.js.map} +1 -1
  69. package/dist/{chunk-PNUM7GUY.js → chunk-BUU2DLPC.js} +3 -3
  70. package/dist/{chunk-PNUM7GUY.js.map → chunk-BUU2DLPC.js.map} +1 -1
  71. package/dist/{chunk-BEYNH2LS.js → chunk-BX7PSWJA.js} +4 -4
  72. package/dist/{chunk-BEYNH2LS.js.map → chunk-BX7PSWJA.js.map} +1 -1
  73. package/dist/{chunk-URCJIV7T.js → chunk-C7TQARGC.js} +3 -3
  74. package/dist/{chunk-URCJIV7T.js.map → chunk-C7TQARGC.js.map} +1 -1
  75. package/dist/{chunk-E5NQRHEB.js → chunk-CK3CJSRY.js} +3 -3
  76. package/dist/{chunk-E5NQRHEB.js.map → chunk-CK3CJSRY.js.map} +1 -1
  77. package/dist/{chunk-GF5JXQIZ.js → chunk-DCJ4BION.js} +2 -2
  78. package/dist/{chunk-GF5JXQIZ.js.map → chunk-DCJ4BION.js.map} +1 -1
  79. package/dist/{chunk-5LQ62LNT.js → chunk-DF5WJC3Q.js} +4 -4
  80. package/dist/{chunk-5LQ62LNT.js.map → chunk-DF5WJC3Q.js.map} +1 -1
  81. package/dist/{chunk-QK7AG5AV.js → chunk-E237FGGX.js} +4 -4
  82. package/dist/{chunk-QK7AG5AV.js.map → chunk-E237FGGX.js.map} +1 -1
  83. package/dist/{chunk-K3R2UKG7.js → chunk-EXRQKOY6.js} +12 -12
  84. package/dist/{chunk-K3R2UKG7.js.map → chunk-EXRQKOY6.js.map} +1 -1
  85. package/dist/chunk-G63KOHFS.js +32 -0
  86. package/dist/chunk-G63KOHFS.js.map +1 -0
  87. package/dist/{chunk-6CYKTHNT.js → chunk-GBXQFJ4G.js} +8 -8
  88. package/dist/{chunk-6CYKTHNT.js.map → chunk-GBXQFJ4G.js.map} +1 -1
  89. package/dist/{chunk-6GWSDPBP.js → chunk-GTMANMBZ.js} +3 -3
  90. package/dist/{chunk-6GWSDPBP.js.map → chunk-GTMANMBZ.js.map} +1 -1
  91. package/dist/{chunk-JJJ2G4K2.js → chunk-HSF665NV.js} +5 -5
  92. package/dist/{chunk-JJJ2G4K2.js.map → chunk-HSF665NV.js.map} +1 -1
  93. package/dist/{chunk-I7LC5TDY.js → chunk-HTGTNN2B.js} +3 -3
  94. package/dist/{chunk-I7LC5TDY.js.map → chunk-HTGTNN2B.js.map} +1 -1
  95. package/dist/{chunk-PMWRM4EJ.js → chunk-HXZ3FQQN.js} +14 -14
  96. package/dist/{chunk-PMWRM4EJ.js.map → chunk-HXZ3FQQN.js.map} +1 -1
  97. package/dist/{chunk-2XM3ZH36.js → chunk-IYZAJ2J2.js} +16 -13
  98. package/dist/chunk-IYZAJ2J2.js.map +1 -0
  99. package/dist/{chunk-3HACK2Z7.js → chunk-IZV3HDVG.js} +5 -5
  100. package/dist/{chunk-3HACK2Z7.js.map → chunk-IZV3HDVG.js.map} +1 -1
  101. package/dist/{chunk-U673DB5U.js → chunk-JSWMRYLM.js} +4 -3
  102. package/dist/chunk-JSWMRYLM.js.map +1 -0
  103. package/dist/{chunk-TSTRH4SM.js → chunk-L45IHRDH.js} +3 -3
  104. package/dist/{chunk-TSTRH4SM.js.map → chunk-L45IHRDH.js.map} +1 -1
  105. package/dist/{chunk-27SXN33H.js → chunk-L4OYPFLB.js} +3 -3
  106. package/dist/{chunk-27SXN33H.js.map → chunk-L4OYPFLB.js.map} +1 -1
  107. package/dist/{chunk-QIHL3YPL.js → chunk-O7KAQQAI.js} +4 -4
  108. package/dist/{chunk-QIHL3YPL.js.map → chunk-O7KAQQAI.js.map} +1 -1
  109. package/dist/{chunk-Z3IRZBXB.js → chunk-P7EL7QRD.js} +14 -14
  110. package/dist/{chunk-Z3IRZBXB.js.map → chunk-P7EL7QRD.js.map} +1 -1
  111. package/dist/{chunk-QXKUFROW.js → chunk-PTBX55QF.js} +4 -4
  112. package/dist/{chunk-QXKUFROW.js.map → chunk-PTBX55QF.js.map} +1 -1
  113. package/dist/{chunk-5JPW27BI.js → chunk-Q4XWCVFA.js} +7 -7
  114. package/dist/{chunk-5JPW27BI.js.map → chunk-Q4XWCVFA.js.map} +1 -1
  115. package/dist/chunk-QJQQNBVT.js +315 -0
  116. package/dist/chunk-QJQQNBVT.js.map +1 -0
  117. package/dist/{chunk-M4OG2YN4.js → chunk-QSIFEHSN.js} +3 -3
  118. package/dist/{chunk-M4OG2YN4.js.map → chunk-QSIFEHSN.js.map} +1 -1
  119. package/dist/{chunk-7Y6S4XLL.js → chunk-RKI35EAN.js} +3 -3
  120. package/dist/{chunk-7Y6S4XLL.js.map → chunk-RKI35EAN.js.map} +1 -1
  121. package/dist/{chunk-OCQNUV4T.js → chunk-SISUT7VR.js} +7 -7
  122. package/dist/{chunk-OCQNUV4T.js.map → chunk-SISUT7VR.js.map} +1 -1
  123. package/dist/{chunk-7H6XRCPG.js → chunk-TDKZL5ZC.js} +3 -3
  124. package/dist/{chunk-7H6XRCPG.js.map → chunk-TDKZL5ZC.js.map} +1 -1
  125. package/dist/{chunk-LRBP3234.js → chunk-TF5CWJQZ.js} +5 -5
  126. package/dist/{chunk-LRBP3234.js.map → chunk-TF5CWJQZ.js.map} +1 -1
  127. package/dist/{chunk-PKBLJI23.js → chunk-TGB4E5Z6.js} +188 -52
  128. package/dist/chunk-TGB4E5Z6.js.map +1 -0
  129. package/dist/{chunk-KB56WBQ3.js → chunk-TPQKFX6X.js} +4 -4
  130. package/dist/{chunk-KB56WBQ3.js.map → chunk-TPQKFX6X.js.map} +1 -1
  131. package/dist/{chunk-TZERN27L.js → chunk-U3SXCVR7.js} +3 -3
  132. package/dist/{chunk-TZERN27L.js.map → chunk-U3SXCVR7.js.map} +1 -1
  133. package/dist/{chunk-KPKGWXUJ.js → chunk-U6S5CXKB.js} +3 -3
  134. package/dist/{chunk-KPKGWXUJ.js.map → chunk-U6S5CXKB.js.map} +1 -1
  135. package/dist/{chunk-JFLQICIU.js → chunk-UAOHR6AL.js} +4 -4
  136. package/dist/{chunk-JFLQICIU.js.map → chunk-UAOHR6AL.js.map} +1 -1
  137. package/dist/{chunk-KXJMQTOU.js → chunk-UBLZALKP.js} +3 -3
  138. package/dist/{chunk-KXJMQTOU.js.map → chunk-UBLZALKP.js.map} +1 -1
  139. package/dist/{chunk-BIRW3HOG.js → chunk-UUKCPPTQ.js} +3 -3
  140. package/dist/{chunk-BIRW3HOG.js.map → chunk-UUKCPPTQ.js.map} +1 -1
  141. package/dist/{chunk-BY5WIRCU.js → chunk-UVTN4O7N.js} +42 -17
  142. package/dist/chunk-UVTN4O7N.js.map +1 -0
  143. package/dist/{chunk-COAFAYBS.js → chunk-V4OXHEWY.js} +3 -3
  144. package/dist/{chunk-COAFAYBS.js.map → chunk-V4OXHEWY.js.map} +1 -1
  145. package/dist/{chunk-SJNZ4WPA.js → chunk-VSCLUPGZ.js} +31 -28
  146. package/dist/chunk-VSCLUPGZ.js.map +1 -0
  147. package/dist/{chunk-JMIKGAUA.js → chunk-VV2DJT4I.js} +15 -5
  148. package/dist/chunk-VV2DJT4I.js.map +1 -0
  149. package/dist/{chunk-JCPD4QRM.js → chunk-VZU67OKK.js} +2 -2
  150. package/dist/{chunk-JCPD4QRM.js.map → chunk-VZU67OKK.js.map} +1 -1
  151. package/dist/{chunk-MAZ3UXJK.js → chunk-WENTJ5KP.js} +4 -4
  152. package/dist/{chunk-MAZ3UXJK.js.map → chunk-WENTJ5KP.js.map} +1 -1
  153. package/dist/{chunk-ZWJCRHP3.js → chunk-YFGXYQW4.js} +3 -3
  154. package/dist/{chunk-ZWJCRHP3.js.map → chunk-YFGXYQW4.js.map} +1 -1
  155. package/dist/{chunk-S2H3RBK7.js → chunk-YJNE4V2M.js} +16 -9
  156. package/dist/chunk-YJNE4V2M.js.map +1 -0
  157. package/dist/{chunk-PJJSBZZP.js → chunk-ZWCGJYR7.js} +3 -3
  158. package/dist/{chunk-PJJSBZZP.js.map → chunk-ZWCGJYR7.js.map} +1 -1
  159. package/dist/{claude-code-BBMNVH2J.js → claude-code-UBT4ZME7.js} +4 -4
  160. package/dist/{claude-code-BBMNVH2J.js.map → claude-code-UBT4ZME7.js.map} +1 -1
  161. package/dist/cli/index.js +107 -91
  162. package/dist/cli/index.js.map +1 -1
  163. package/dist/cli/src/commands/library-cmd.d.ts.map +1 -1
  164. package/dist/cli/src/commands/library-index.d.ts.map +1 -1
  165. package/dist/cli/src/commands/plugin-registry-cmd.d.ts.map +1 -1
  166. package/dist/cli/src/commands/preset-cmd.d.ts.map +1 -1
  167. package/dist/cli/src/commands/providers.d.ts.map +1 -1
  168. package/dist/cli/src/helpers.d.ts +10 -2
  169. package/dist/cli/src/helpers.d.ts.map +1 -1
  170. package/dist/cli/src/plugin-store/index.d.ts +1 -1
  171. package/dist/cli/src/plugin-store/index.d.ts.map +1 -1
  172. package/dist/cli/src/plugin-store/reconcile.d.ts.map +1 -1
  173. package/dist/cli/src/plugin-store/spec.d.ts +19 -14
  174. package/dist/cli/src/plugin-store/spec.d.ts.map +1 -1
  175. package/dist/cli/src/setup.d.ts.map +1 -1
  176. package/dist/connectors/config.js +4 -4
  177. package/dist/connectors/index.js +22 -20
  178. package/dist/{connectors-47EM6C2P.js → connectors-4WH32NK2.js} +25 -23
  179. package/dist/{connectors-47EM6C2P.js.map → connectors-4WH32NK2.js.map} +1 -1
  180. package/dist/connectors-shared/index.js +2 -2
  181. package/dist/core/index.js +6 -6
  182. package/dist/core/manifest.js +1 -1
  183. package/dist/core/publish-manifest.js +2 -2
  184. package/dist/core/runtime-assets.js +4 -4
  185. package/dist/core/src/index.d.ts +1 -1
  186. package/dist/core/src/index.d.ts.map +1 -1
  187. package/dist/core/src/lock.d.ts.map +1 -1
  188. package/dist/core/src/manifest.d.ts +9 -3
  189. package/dist/core/src/manifest.d.ts.map +1 -1
  190. package/dist/core/src/workspace-config.d.ts +15 -0
  191. package/dist/core/src/workspace-config.d.ts.map +1 -1
  192. package/dist/core/src/workspace-yaml-editor.d.ts.map +1 -1
  193. package/dist/core/workspace-config.js +3 -3
  194. package/dist/deploy/index.js +6 -6
  195. package/dist/discovery/index.js +3 -3
  196. package/dist/{ensure-sources-K5EFNC3L.js → ensure-sources-UC2RBYMP.js} +27 -25
  197. package/dist/ensure-sources-UC2RBYMP.js.map +1 -0
  198. package/dist/factory-assets/connectors/box.js +22 -20
  199. package/dist/factory-assets/connectors/deploy.js +22 -20
  200. package/dist/factory-assets/connectors/devserver.js +22 -20
  201. package/dist/factory-assets/connectors/flow/adapter.js +22 -20
  202. package/dist/factory-assets/connectors/flow/engine.js +7 -7
  203. package/dist/factory-assets/connectors/flow/run-flow.js +24 -22
  204. package/dist/factory-assets/connectors/flow.js +22 -20
  205. package/dist/factory-assets/connectors/git.js +22 -20
  206. package/dist/factory-assets/connectors/gmail.js +22 -20
  207. package/dist/factory-assets/connectors/googledrive.js +22 -20
  208. package/dist/factory-assets/connectors/local.js +22 -20
  209. package/dist/factory-assets/connectors/mattermost.js +22 -20
  210. package/dist/factory-assets/connectors/memory.js +22 -20
  211. package/dist/factory-assets/connectors/minio.js +22 -20
  212. package/dist/factory-assets/connectors/postgres.js +22 -20
  213. package/dist/factory-assets/connectors/s3.js +22 -20
  214. package/dist/factory-assets/connectors/sharepoint.js +22 -20
  215. package/dist/factory-assets/connectors/sqlite.js +22 -20
  216. package/dist/factory-assets/connectors/static-server.js +22 -20
  217. package/dist/factory-assets/connectors/tunnel.js +22 -20
  218. package/dist/factory-assets/connectors/webdav.js +22 -20
  219. package/dist/factory-assets/connectors/xstate-store.js +22 -20
  220. package/dist/factory-assets/connectors/xstate.js +22 -20
  221. package/dist/{flows-KLBNSKLO.js → flows-LYTKNGKE.js} +11 -11
  222. package/dist/{flows-KLBNSKLO.js.map → flows-LYTKNGKE.js.map} +1 -1
  223. package/dist/{helpers-LUSV2ICC.js → helpers-SSSKT5XK.js} +27 -25
  224. package/dist/{helpers-LUSV2ICC.js.map → helpers-SSSKT5XK.js.map} +1 -1
  225. package/dist/library/index.js +9 -9
  226. package/dist/library/install.js +3 -3
  227. package/dist/{library-publish-XMRCKRNR.js → library-publish-GQMNTAKK.js} +52 -50
  228. package/dist/library-publish-GQMNTAKK.js.map +1 -0
  229. package/dist/model-endpoint/index.js +10 -9
  230. package/dist/open-library-XGUCUJYE.js +58 -0
  231. package/dist/{open-library-XBR46DJL.js.map → open-library-XGUCUJYE.js.map} +1 -1
  232. package/dist/{open-registry-W562DCDL.js → open-registry-DIFEPDF6.js} +13 -13
  233. package/dist/{open-registry-W562DCDL.js.map → open-registry-DIFEPDF6.js.map} +1 -1
  234. package/dist/{paths-2AZXB3QL.js → paths-G4GFJLE2.js} +9 -9
  235. package/dist/{paths-2AZXB3QL.js.map → paths-G4GFJLE2.js.map} +1 -1
  236. package/dist/{plugin-store-36SIL4TV.js → plugin-store-BBLDFD3L.js} +9 -9
  237. package/dist/{plugin-store-36SIL4TV.js.map → plugin-store-BBLDFD3L.js.map} +1 -1
  238. package/dist/{project-D7GN7WLS.js → project-LB745WVZ.js} +48 -46
  239. package/dist/{project-D7GN7WLS.js.map → project-LB745WVZ.js.map} +1 -1
  240. package/dist/resolver/index.js +7 -7
  241. package/dist/runner/index.js +38 -36
  242. package/dist/runner/src/capability-roundtrip.d.ts +4 -1
  243. package/dist/runner/src/capability-roundtrip.d.ts.map +1 -1
  244. package/dist/sdk/asset-manager.js +12 -12
  245. package/dist/sdk/bridge.js +18 -16
  246. package/dist/sdk/core.js +6 -6
  247. package/dist/sdk/flow.js +7 -7
  248. package/dist/sdk/index.js +38 -36
  249. package/dist/sdk/index.js.map +1 -1
  250. package/dist/sdk/resolver.js +7 -7
  251. package/dist/sdk/runner.js +38 -36
  252. package/dist/sdk/session.js +2 -2
  253. package/dist/sdk/transport/ws/server.js +7 -7
  254. package/dist/sdk/transport/ws.js +7 -7
  255. package/dist/sdk/transport.js +7 -7
  256. package/dist/sdk/types.js +1 -1
  257. package/dist/{serve-preflight-CGA5G3AE.js → serve-preflight-NPWI4MV6.js} +28 -26
  258. package/dist/serve-preflight-NPWI4MV6.js.map +1 -0
  259. package/dist/session/index.js +2 -2
  260. package/dist/{setup-IBDNJAOU.js → setup-X6ZYH2MW.js} +33 -28
  261. package/dist/setup-X6ZYH2MW.js.map +1 -0
  262. package/dist/{skills-CTTO7SZK.js → skills-62PXDBPJ.js} +12 -12
  263. package/dist/{skills-CTTO7SZK.js.map → skills-62PXDBPJ.js.map} +1 -1
  264. package/dist/{source-2DJ5KNOI.js → source-LAYCTRHP.js} +48 -46
  265. package/dist/{source-2DJ5KNOI.js.map → source-LAYCTRHP.js.map} +1 -1
  266. package/dist/{source-manifest-publish-IYWUMUCY.js → source-manifest-publish-3S6PJ25W.js} +50 -48
  267. package/dist/source-manifest-publish-3S6PJ25W.js.map +1 -0
  268. package/dist/transport/index.js +7 -7
  269. package/dist/transport/ws/server.js +7 -7
  270. package/dist/transport/ws.js +7 -7
  271. package/dist/tui/index.js +38 -36
  272. package/dist/tui/index.js.map +1 -1
  273. package/dist/types/index.js +1 -1
  274. package/dist/types/src/capabilities.d.ts +9 -1
  275. package/dist/types/src/capabilities.d.ts.map +1 -1
  276. package/dist/workspace-plugin/adapters/mcp.js +29 -27
  277. package/dist/workspace-plugin/adapters/omp.js +14 -14
  278. package/dist/workspace-plugin/index.js +1 -1
  279. package/package.json +27 -1
  280. package/dist/chunk-2XM3ZH36.js.map +0 -1
  281. package/dist/chunk-7DRFKAJZ.js.map +0 -1
  282. package/dist/chunk-BOT64P3U.js.map +0 -1
  283. package/dist/chunk-BRK5QZKI.js.map +0 -1
  284. package/dist/chunk-BY5WIRCU.js.map +0 -1
  285. package/dist/chunk-ICSGNT5P.js.map +0 -1
  286. package/dist/chunk-ITFCWMOY.js.map +0 -1
  287. package/dist/chunk-JMIKGAUA.js.map +0 -1
  288. package/dist/chunk-KJSC2ZD6.js.map +0 -1
  289. package/dist/chunk-PKBLJI23.js.map +0 -1
  290. package/dist/chunk-RQMIZONH.js.map +0 -1
  291. package/dist/chunk-S2H3RBK7.js.map +0 -1
  292. package/dist/chunk-SJNZ4WPA.js.map +0 -1
  293. package/dist/chunk-U673DB5U.js.map +0 -1
  294. package/dist/chunk-X37JUNEW.js.map +0 -1
  295. package/dist/ensure-sources-K5EFNC3L.js.map +0 -1
  296. package/dist/library-publish-XMRCKRNR.js.map +0 -1
  297. package/dist/open-library-XBR46DJL.js +0 -56
  298. package/dist/serve-preflight-CGA5G3AE.js.map +0 -1
  299. package/dist/setup-IBDNJAOU.js.map +0 -1
  300. package/dist/source-manifest-publish-IYWUMUCY.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../bridge/src/harness-capabilities.ts","../bridge/src/provider-materialize/credential-env.ts","../bridge/src/registry.ts"],"names":[],"mappings":"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","file":"chunk-QJQQNBVT.js","sourcesContent":["/**\n * What the runner may ask of a harness, by harness id.\n *\n * Deliberately light: this module imports no harness, no SDK and no `zod`, so a\n * runner file that only needs a capability can import it without loading the\n * harness graph. The plugin-registry singleton is read through its `internal`\n * module (the same file `@skaile/workspaces/plugin-registry` re-exports, so one\n * instance under the bundler's shared chunks), not through the package index,\n * which pulls in the deploy helpers and their `zod` schemas.\n *\n * @docLink packages/bridge/api-reference#registry\n */\n\nimport { pluginRegistry } from \"../../plugin-registry/src/internal.js\";\nimport type { HarnessCapabilities } from \"@skaile/workspaces/types\";\n\n/**\n * Capabilities of a harness that declares none: it recomposes its tools per\n * turn like every bridge harness that is not an in-process SDK, and has no\n * managed session, credentials file or transcript-file resume.\n */\nconst GENERIC_HARNESS_CAPABILITIES: HarnessCapabilities = {\n inProcessMcpServers: false,\n liveToolUpdates: true,\n managedSession: false,\n claudeCodeCredentials: false,\n resumeNeedsTranscript: false,\n};\n\n/**\n * Declared capabilities of the built-in harnesses that differ from nothing.\n * `BUILTIN_HARNESS_CATALOG` rows point at these entries, so `listHarnesses()` and\n * {@link harnessCapabilities} read one table. A built-in absent here (echo,\n * gemini, qwen, opencode, goose, continue) takes the generic defaults.\n */\nexport const BUILTIN_HARNESS_CAPABILITIES = {\n // Recomposes its tools per turn, so a hot-plugged MCP server is live.\n omp: {\n inProcessMcpServers: false,\n liveToolUpdates: true,\n managedSession: false,\n claudeCodeCredentials: false,\n resumeNeedsTranscript: false,\n },\n // The SDK takes in-process server instances and bakes its tool set at\n // creation; it reads Claude's `~/.claude` credentials and JSONL transcripts.\n \"claude-sdk\": {\n inProcessMcpServers: true,\n liveToolUpdates: false,\n managedSession: false,\n claudeCodeCredentials: true,\n resumeNeedsTranscript: true,\n },\n // Standalone SDK recomposes its tools per turn. A host-managed session\n // (native app-server) refreshes its own native tool snapshot instead.\n codex: {\n inProcessMcpServers: false,\n liveToolUpdates: true,\n managedSession: true,\n claudeCodeCredentials: false,\n resumeNeedsTranscript: false,\n },\n} as const satisfies Record<string, HarnessCapabilities>;\n\n/**\n * Resolve what the runner may ask of a harness, by harness id, without loading\n * its module. Built-ins read {@link BUILTIN_HARNESS_CAPABILITIES}; a third-party\n * harness reads its registered `HarnessTarget`; an unknown or absent id gets the\n * generic defaults. Fields a harness omits take the generic default too.\n *\n * This is the one place the runner learns harness facts — it never compares an\n * id against `\"claude-sdk\"`, `\"codex\"` or `\"omp\"`.\n *\n * @param id - Harness id (e.g. a session's `harnessType`); `undefined` resolves to the defaults.\n * @docLink packages/bridge/api-reference#registry\n */\nexport function harnessCapabilities(id: string | undefined): HarnessCapabilities {\n const declared = id\n ? Object.hasOwn(BUILTIN_HARNESS_CAPABILITIES, id)\n ? BUILTIN_HARNESS_CAPABILITIES[id as keyof typeof BUILTIN_HARNESS_CAPABILITIES]\n : pluginRegistry.get(\"harness\", id)?.capabilities\n : undefined;\n return { ...GENERIC_HARNESS_CAPABILITIES, ...declared };\n}\n\n/**\n * Whether a hot-plugged MCP server reaches the agent's next turn without a\n * harness restart. A host-managed session refreshes its native tool snapshot\n * itself, so it never takes live updates, whatever the standalone harness does.\n *\n * @param id - Harness id of the live session.\n * @param managed - Whether the session is host-managed (`managedCodex`).\n * @docLink packages/bridge/api-reference#registry\n */\nexport function supportsLiveToolUpdates(id: string | undefined, managed = false): boolean {\n const caps = harnessCapabilities(id);\n return caps.liveToolUpdates && !(managed && caps.managedSession);\n}\n","/**\n * Credential delivery for harness adapters — the one naming rule (§2.3).\n *\n * Every adapter that hands a registry entry's secret to a child process, and\n * every renderer that has to *name* that secret in a config file it writes\n * (omp's `models.yml` `apiKey:`, Codex's `env_key`, OpenCode's `{env:…}`),\n * agrees on one env-var name per entry: `SKAILE_AIP_<UPPER_ID>_KEY`. The name\n * goes in the file, the value goes in the child environment — a rendered\n * config never contains a secret.\n *\n * The platform's secret-env allowlist is a prefix rule on exactly that name,\n * and forge-common delivers the same names when it spawns `skaile serve`, so\n * the transform below is a cross-repo contract: uppercase, every character\n * outside `[A-Za-z0-9]` mapped to `_` (registry ids are `[a-z0-9][a-z0-9_-]*`,\n * so in practice only `-`).\n *\n * Alongside the canonical name, {@link registryCredentialEnv} also sets the\n * *conventional* carrier a CLI already reads (`ANTHROPIC_API_KEY`,\n * `GEMINI_API_KEY`, `GROQ_API_KEY`, …) so a catalog-preset entry works in a\n * harness that has no per-endpoint config file yet.\n *\n * @see PROVIDER-CONFIG-PLAN.md §1.4, §2.3\n */\n\nimport {\n type AIProviderEntry,\n type AIProviderRegistry,\n isEntryEnabled,\n type MergedAIProviderRegistry,\n parseCredentialRef,\n registryEntries,\n} from \"@skaile/workspaces/core/provider-registry\";\nimport { resolveCredential } from \"@skaile/workspaces/core/provider-registry-credentials\";\nimport { AI_PROVIDER_PRESETS } from \"../provider-catalog.js\";\n\n/** Options shared by every registry-shaped credential resolution. */\nexport interface RegistryCredentialOptions {\n /** Restrict resolution to one entry — the provider half of a `modelRef`. */\n providerId?: string;\n /** Environment `env:` refs resolve against. Defaults to `process.env`. */\n env?: Record<string, string | undefined>;\n /** Control-plane secrets keyed by config id, for `platform:` refs. */\n secrets?: Record<string, string>;\n /** Run `cmd:` references. Default `true`. */\n allowCommand?: boolean;\n}\n\n/** Prefix of the canonical per-entry credential variable. */\nexport const PROVIDER_CREDENTIAL_ENV_PREFIX = \"SKAILE_AIP_\";\n\n/** Suffix of the canonical per-entry credential variable. */\nexport const PROVIDER_CREDENTIAL_ENV_SUFFIX = \"_KEY\";\n\n/**\n * The env-var name that carries a registry entry's credential:\n * `anthropic` → `SKAILE_AIP_ANTHROPIC_KEY`, `my-gw.eu` → `SKAILE_AIP_MY_GW_EU_KEY`.\n *\n * Pure: no environment, no registry, no I/O. Renderers call it per entry while\n * emitting a config file, adapters call it while assembling a child env, and\n * the platform allowlist matches the prefix.\n */\nexport function providerCredentialEnvName(providerId: string): string {\n const slug = providerId.replace(/[^A-Za-z0-9]/g, \"_\").toUpperCase();\n return `${PROVIDER_CREDENTIAL_ENV_PREFIX}${slug}${PROVIDER_CREDENTIAL_ENV_SUFFIX}`;\n}\n\n/**\n * The env var a harness already looks for on its own, when the entry names one.\n *\n * The catalog preset's conventional carrier wins (`GEMINI_API_KEY` for\n * `google`), because that is the name the vendor's own CLI reads; otherwise an\n * `env:NAME` credential reference is taken at face value — the operator named\n * that variable, so the child gets it under the same name. `cmd:`, `platform:`\n * and `keyring:` refs have no conventional carrier and return `undefined`.\n */\nexport function conventionalCredentialEnvName(entry: AIProviderEntry): string | undefined {\n const preset = entry.preset ? AI_PROVIDER_PRESETS[entry.preset] : undefined;\n if (preset?.credential.env) return preset.credential.env;\n const ref = entry.credential?.ref ? parseCredentialRef(entry.credential.ref) : undefined;\n return ref?.form === \"env\" ? ref.name : undefined;\n}\n\n/**\n * Resolve one entry's credential to its value, or `undefined` when there is\n * none to hand over (`kind: none`, an ambient `sigv4`/`google_adc` chain, an\n * unset variable, a reserved `keyring:` ref).\n */\nexport function resolveEntryCredential(\n entry: AIProviderEntry,\n options: RegistryCredentialOptions = {},\n): string | undefined {\n return resolveCredential(entry, {\n ...(options.env ? { env: options.env } : {}),\n ...(options.secrets ? { secrets: options.secrets } : {}),\n ...(options.allowCommand === undefined ? {} : { allowCommand: options.allowCommand }),\n }).value;\n}\n\n/**\n * One entry's credential value, including the one the session boundary\n * already resolved for it.\n *\n * A `platform:<configId>` reference is resolved by the runner — it holds the\n * `session_init` secrets map, the harness does not — and materialized into the\n * child environment under {@link providerCredentialEnvName}. So when the\n * reference itself yields nothing, that carrier is consulted: it is the same\n * secret, delivered one step earlier.\n */\nexport function entryCredentialValue(\n providerId: string,\n entry: AIProviderEntry,\n options: RegistryCredentialOptions = {},\n): string | undefined {\n return (\n resolveEntryCredential(entry, options) ?? options.env?.[providerCredentialEnvName(providerId)]\n );\n}\n\n/** One enabled entry whose credential is declared but cannot be resolved. */\nexport interface UnresolvedProviderCredential {\n providerId: string;\n /** Why it does not resolve, e.g. `environment variable ANTHROPIC_API_KEY is not set`. */\n reason: string;\n}\n\n/**\n * The enabled LLM/embed entries that name a credential this process cannot\n * resolve (the variable is unset, the command fails). A harness must not be\n * handed such an entry: the child would send an empty key and fail with a 401\n * instead of using its own login. Entries with no credential, an ambient\n * signing chain, or a value the session boundary already delivered under\n * {@link providerCredentialEnvName} are fine.\n */\nexport function unresolvedProviderCredentials(\n registry: AIProviderRegistry | MergedAIProviderRegistry,\n options: RegistryCredentialOptions = {},\n): UnresolvedProviderCredential[] {\n const out: UnresolvedProviderCredential[] = [];\n for (const [id, entry] of registryEntries(registry)) {\n if (entry.kind !== \"llm\" && entry.kind !== \"embed\") continue;\n if (!isEntryEnabled(entry)) continue;\n if (options.providerId && id !== options.providerId) continue;\n const resolved = resolveCredential(entry, {\n ...(options.env ? { env: options.env } : {}),\n ...(options.secrets ? { secrets: options.secrets } : {}),\n ...(options.allowCommand === undefined ? {} : { allowCommand: options.allowCommand }),\n });\n if (!resolved.error) continue;\n if (options.env?.[providerCredentialEnvName(id)]) continue;\n out.push({ providerId: id, reason: resolved.error });\n }\n return out;\n}\n\n/** Options for {@link entryCredentialEnv} / {@link registryCredentialEnv}. */\nexport interface RegistryCredentialEnvOptions extends RegistryCredentialOptions {\n /**\n * Also set the harness-conventional carrier\n * ({@link conventionalCredentialEnvName}). Default `true`. Set `false` for a\n * harness that reads every endpoint out of a rendered config file and must\n * not inherit a vendor default from a neighbouring entry.\n */\n aliases?: boolean;\n}\n\n/**\n * The credential variables one entry contributes: always\n * `SKAILE_AIP_<ID>_KEY`, plus the conventional carrier unless `aliases` is\n * `false`. Empty when the entry has no resolvable secret.\n */\nexport function entryCredentialEnv(\n providerId: string,\n entry: AIProviderEntry,\n options: RegistryCredentialEnvOptions = {},\n): Record<string, string> {\n const value = resolveEntryCredential(entry, options);\n if (!value) return {};\n const out: Record<string, string> = { [providerCredentialEnvName(providerId)]: value };\n if (options.aliases !== false) {\n const alias = conventionalCredentialEnvName(entry);\n if (alias) out[alias] = value;\n }\n return out;\n}\n\n/**\n * Every enabled entry's credential, as a child-process environment fragment.\n *\n * One canonical `SKAILE_AIP_<ID>_KEY` per entry whose credential resolves; the\n * conventional carriers are added underneath, first entry in registry order\n * winning a collision (registry order is highest-precedence layer first, so\n * the alias follows the same precedence the selector does). Entries whose\n * credential cannot be resolved contribute nothing.\n */\nexport function registryCredentialEnv(\n registry: AIProviderRegistry | MergedAIProviderRegistry,\n options: RegistryCredentialEnvOptions = {},\n): Record<string, string> {\n const canonical: Record<string, string> = {};\n const aliases: Record<string, string> = {};\n for (const [id, entry] of registryEntries(registry)) {\n if (options.providerId && id !== options.providerId) continue;\n if (!isEntryEnabled(entry)) continue;\n const value = resolveEntryCredential(entry, options);\n if (!value) continue;\n canonical[providerCredentialEnvName(id)] = value;\n if (options.aliases === false) continue;\n const alias = conventionalCredentialEnvName(entry);\n if (alias && aliases[alias] === undefined) aliases[alias] = value;\n }\n return { ...aliases, ...canonical };\n}\n","import type {\n AIProviderRegistry,\n AIProviderSurface,\n MergedAIProviderRegistry,\n} from \"@skaile/workspaces/core/provider-registry\";\nimport type { HarnessContext } from \"@skaile/workspaces/plugin-registry\";\nimport { type PluginRegistry, pluginRegistry } from \"@skaile/workspaces/plugin-registry\";\nimport type { ModelEntry } from \"./models.js\";\nimport type { RegistryCredentialOptions } from \"./provider-materialize/credential-env.js\";\nimport { BUILTIN_HARNESS_CAPABILITIES } from \"./harness-capabilities.js\";\nimport type { AgentConfig, AgentHarness, HarnessInfo } from \"./types.js\";\n\n// Build-time harness gating. `bun build --compile --define:__INCLUDE_*__=...`\n// folds these to literal booleans so an excluded harness module and\n// its SDK are dead-code-stripped from the binary. Under tsup / vitest / bun\n// run-on-source no `--define` runs and the `typeof` guard defaults to `true` —\n// every harness is available (the SDKs stay optional peers).\ndeclare const __INCLUDE_CLAUDE_SDK__: boolean;\ndeclare const __INCLUDE_CODEX__: boolean;\nconst INCLUDE_CLAUDE_SDK =\n typeof __INCLUDE_CLAUDE_SDK__ === \"undefined\" ? true : __INCLUDE_CLAUDE_SDK__;\nconst INCLUDE_CODEX = typeof __INCLUDE_CODEX__ === \"undefined\" ? true : __INCLUDE_CODEX__;\n\n/**\n * Every wire surface omp can speak — it is the harness the `surface` enum was\n * lifted from, so its list is the enum.\n */\nconst OMP_SURFACES = [\n \"anthropic-messages\",\n \"openai-completions\",\n \"openai-responses\",\n \"openai-codex-responses\",\n \"azure-openai-responses\",\n \"bedrock-converse-stream\",\n \"google-generative-ai\",\n \"google-vertex\",\n] as const satisfies readonly AIProviderSurface[];\n\n/**\n * Static capability metadata for every built-in harness.\n *\n * Pure data — this object imports no harness module and references no harness\n * SDK. {@link listHarnesses} returns it (merged with any third-party harnesses)\n * so selection UIs can enumerate every harness without loading a single\n * harness module. The matching harness module's `HarnessTarget` is registered\n * into the plugin registry by {@link registerBuiltinHarnesses}.\n *\n * `surfaces` and `providerPlurality` are the harness-capability declaration\n * the AI provider registry resolves against (plan §2.3): which wire protocols\n * a harness can be pointed at, and how many registry entries it can use at\n * once. The platform's resolver filters candidate entries on `surfaces`\n * instead of matching vendor names.\n *\n * @docLink packages/bridge/api-reference#registry\n */\nexport const BUILTIN_HARNESS_CATALOG: Record<string, HarnessInfo> = {\n omp: {\n id: \"omp\",\n name: \"omp (oh-my-pi)\",\n modelAgnostic: true,\n supportsInBandAbort: true,\n surfaces: OMP_SURFACES,\n // omp renders the whole registry as its own `models.yml`, so every entry\n // stays selectable and roles / per-subagent models resolve across them.\n providerPlurality: \"registry\",\n capabilities: BUILTIN_HARNESS_CAPABILITIES.omp,\n },\n \"claude-sdk\": {\n id: \"claude-sdk\",\n name: \"Claude Agent SDK\",\n modelAgnostic: false,\n supportsInBandAbort: true,\n // Anthropic's own API, plus the two clouds the SDK addresses natively.\n // Foundry is `anthropic-messages` at a different host, not a surface.\n surfaces: [\"anthropic-messages\", \"bedrock-converse-stream\", \"google-vertex\"],\n providerPlurality: \"single\",\n capabilities: BUILTIN_HARNESS_CAPABILITIES[\"claude-sdk\"],\n },\n codex: {\n id: \"codex\",\n name: \"OpenAI Codex\",\n modelAgnostic: false,\n supportsInBandAbort: true,\n // Codex's `wire_api` is `responses` or `chat`; its subscription transport\n // is the codex-specific responses flavour.\n surfaces: [\"openai-codex-responses\", \"openai-responses\", \"openai-completions\"],\n providerPlurality: \"single\",\n capabilities: BUILTIN_HARNESS_CAPABILITIES.codex,\n },\n echo: {\n id: \"echo\",\n name: \"Echo (E2E mock)\",\n modelAgnostic: true,\n supportsInBandAbort: false,\n // Deterministic mock: it never opens a connection, so it speaks no wire\n // surface and no registry entry can be dispatched to it.\n surfaces: [],\n providerPlurality: \"single\",\n },\n gemini: {\n id: \"gemini\",\n name: \"Gemini CLI\",\n modelAgnostic: false,\n supportsInBandAbort: false,\n surfaces: [\"google-generative-ai\"],\n providerPlurality: \"single\",\n },\n qwen: {\n id: \"qwen\",\n name: \"Qwen Code\",\n modelAgnostic: true,\n supportsInBandAbort: false,\n // Driven entirely through OPENAI_BASE_URL / OPENAI_API_KEY.\n surfaces: [\"openai-completions\"],\n providerPlurality: \"single\",\n },\n opencode: {\n id: \"opencode\",\n name: \"OpenCode\",\n modelAgnostic: true,\n supportsInBandAbort: false,\n surfaces: [\n \"anthropic-messages\",\n \"openai-completions\",\n \"openai-responses\",\n \"google-generative-ai\",\n ],\n providerPlurality: \"credentials-n\",\n },\n goose: {\n id: \"goose\",\n name: \"Goose\",\n modelAgnostic: true,\n supportsInBandAbort: false,\n surfaces: [\n \"anthropic-messages\",\n \"openai-completions\",\n \"google-generative-ai\",\n \"bedrock-converse-stream\",\n ],\n providerPlurality: \"credentials-n\",\n },\n continue: {\n id: \"continue\",\n name: \"Continue CLI\",\n modelAgnostic: true,\n supportsInBandAbort: false,\n surfaces: [\"anthropic-messages\", \"openai-completions\", \"google-generative-ai\"],\n providerPlurality: \"credentials-n\",\n },\n};\n\nlet _harnessesRegistered = false;\n\n/**\n * Register every built-in harness's `HarnessTarget` into the plugin registry.\n *\n * This is the single id → module map in bridge core. Every specifier is a\n * literal string so `bun --compile` can statically bundle the harness module\n * (and, transitively, its SDK). The in-process-SDK harnesses (`claude-sdk`,\n * `codex`) are wrapped in build-constant guards so an excluded harness's\n * `await import` folds to dead code in the compiled binary. `omp` and `echo`\n * carry no SDK weight and are always available.\n *\n * **Static import discipline.** Every `import()` specifier below must be a\n * string literal — never aliased through a variable. Indirection defeats\n * `bun --compile`'s static analysis and silently drops the module from the\n * binary.\n *\n * Idempotent: guarded by a module flag so a second call is a no-op (a duplicate\n * `register` would otherwise throw `RegistrationError`).\n *\n * @docLink packages/bridge/api-reference#registry\n */\nexport async function registerBuiltinHarnesses(\n registry: PluginRegistry = pluginRegistry,\n): Promise<void> {\n if (registry === pluginRegistry && _harnessesRegistered) return;\n\n if (!registry.get(\"harness\", \"omp\")) {\n const m = await import(\"@skaile/workspaces/harnesses/omp\");\n registry.register(\"harness\", m.ompHarnessTarget);\n }\n if (!registry.get(\"harness\", \"echo\")) {\n const m = await import(\"@skaile/workspaces/harnesses/echo\");\n registry.register(\"harness\", m.echoHarnessTarget);\n }\n if (INCLUDE_CLAUDE_SDK && !registry.get(\"harness\", \"claude-sdk\")) {\n const m = await import(\"@skaile/workspaces/harnesses/claude-sdk\");\n registry.register(\"harness\", m.claudeSdkHarnessTarget);\n }\n if (INCLUDE_CODEX && !registry.get(\"harness\", \"codex\")) {\n const m = await import(\"@skaile/workspaces/harnesses/codex\");\n registry.register(\"harness\", m.codexHarnessTarget);\n }\n // Subprocess CLI harnesses spawn an external binary the user installs\n // separately — no bundled SDK to dead-code-strip, so (like omp/echo) they\n // carry no build constant and are always registered.\n if (!registry.get(\"harness\", \"gemini\")) {\n const m = await import(\"@skaile/workspaces/harnesses/gemini\");\n registry.register(\"harness\", m.geminiHarnessTarget);\n }\n if (!registry.get(\"harness\", \"qwen\")) {\n const m = await import(\"@skaile/workspaces/harnesses/qwen\");\n registry.register(\"harness\", m.qwenHarnessTarget);\n }\n if (!registry.get(\"harness\", \"opencode\")) {\n const m = await import(\"@skaile/workspaces/harnesses/opencode\");\n registry.register(\"harness\", m.opencodeHarnessTarget);\n }\n if (!registry.get(\"harness\", \"goose\")) {\n const m = await import(\"@skaile/workspaces/harnesses/goose\");\n registry.register(\"harness\", m.gooseHarnessTarget);\n }\n if (!registry.get(\"harness\", \"continue\")) {\n const m = await import(\"@skaile/workspaces/harnesses/continue\");\n registry.register(\"harness\", m.continueHarnessTarget);\n }\n\n if (registry === pluginRegistry) _harnessesRegistered = true;\n}\n\n/**\n * Creates a new harness instance for the given harness id.\n *\n * Ensures the built-in harness targets are registered (idempotent), then looks\n * up the target in the plugin registry and calls its `create()`. The returned\n * harness has not been started yet — call `harness.start()` before sending\n * prompts.\n *\n * @param id - Registered harness identifier (e.g. `\"omp\"`, `\"claude-sdk\"`).\n * @param config - Configuration forwarded to the harness constructor.\n * @param ctx - Optional harness context (logger / abort signal). Defaults to `{}`.\n * @returns A freshly constructed (not yet started) {@link AgentHarness}.\n * @throws {Error} When `id` is a known harness excluded from this build, or\n * when `id` does not match any registered harness at all.\n * @docLink packages/bridge/api-reference#registry\n */\nexport async function createHarness(\n id: string,\n config: AgentConfig,\n ctx?: HarnessContext,\n): Promise<AgentHarness> {\n const target = await resolveHarnessTarget(id);\n return target.create(config, ctx ?? {});\n}\n\n/**\n * Resolve a registered harness target by id, ensuring the built-ins are\n * registered first. Throws the canonical \"not bundled\" / \"unknown harness\"\n * errors so every caller (`createHarness`, `listModelsForHarness`) reports an\n * unrecognized id the same way instead of silently degrading.\n *\n * @throws {Error} When `id` is a known harness excluded from this build, or\n * when `id` does not match any registered harness at all.\n */\nasync function resolveHarnessTarget(id: string) {\n await registerBuiltinHarnesses();\n const target = pluginRegistry.get(\"harness\", id);\n if (!target) {\n if (id in BUILTIN_HARNESS_CATALOG) {\n throw new Error(`Agent harness \"${id}\" is not bundled in this build.`);\n }\n throw new Error(\n `Unknown agent harness: \"${id}\". Available: ${listHarnesses()\n .map((d) => d.id)\n .join(\", \")}`,\n );\n }\n return target;\n}\n\n/**\n * Returns the capability metadata for every available harness.\n *\n * Enumerates every built-in harness from {@link BUILTIN_HARNESS_CATALOG} without\n * loading a single harness module or harness SDK, then merges in any third-party\n * harness targets registered into the plugin registry that are not already in\n * the catalog. Use this to populate harness selection UIs.\n *\n * @returns Array of {@link HarnessInfo} objects, one per available harness.\n * @docLink packages/bridge/api-reference#registry\n */\nexport function listHarnesses(): HarnessInfo[] {\n const merged = new Map<string, HarnessInfo>();\n for (const info of Object.values(BUILTIN_HARNESS_CATALOG)) {\n merged.set(info.id, info);\n }\n for (const meta of pluginRegistry.list(\"harness\")) {\n if (!merged.has(meta.id)) {\n // Third-party harnesses carry no HarnessInfo row; read the capability flags\n // off the registered target (defaulting to conservative false) so a\n // model-agnostic / in-band-abort harness can still advertise them.\n const target = pluginRegistry.get(\"harness\", meta.id);\n merged.set(meta.id, {\n id: meta.id,\n name: meta.displayName,\n modelAgnostic: target?.modelAgnostic ?? false,\n supportsInBandAbort: target?.supportsInBandAbort ?? false,\n // Left absent when the target declares nothing: \"speaks no surface\" and\n // \"did not say\" are different claims, and the platform resolver must be\n // able to tell them apart before it filters a harness out.\n ...(target?.surfaces ? { surfaces: target.surfaces } : {}),\n ...(target?.providerPlurality ? { providerPlurality: target.providerPlurality } : {}),\n ...(target?.capabilities ? { capabilities: target.capabilities } : {}),\n });\n }\n }\n return [...merged.values()];\n}\n\n/**\n * List models available to a specific harness without starting a full agent session.\n *\n * Ensures the built-in harness targets are registered (idempotent), then\n * delegates to the target's optional `listModels()`. Throws on an unknown /\n * not-bundled id (same contract as {@link createHarness}); returns `[]` only\n * when the target exists but exposes no `listModels`.\n *\n * @param harnessId - Registered harness id (e.g. `\"omp\"`, `\"claude-sdk\"`, `\"codex\"`).\n * @param registry - The AI provider registry to discover against — either the\n * bare `id → entry` map or a merged view. Each entry names its credential by\n * reference, resolved through `options` and delivered to the throwaway\n * harness as `SKAILE_AIP_<ID>_KEY` environment entries.\n * @param options - Which entry to restrict to, and where `env:` / `platform:`\n * references resolve from. Defaults to the whole registry against\n * `process.env`.\n * @throws {Error} When `harnessId` is unknown or excluded from this build.\n * @docLink packages/bridge/api-reference#registry\n */\nexport async function listModelsForHarness(\n harnessId: string,\n registry: AIProviderRegistry | MergedAIProviderRegistry,\n options?: RegistryCredentialOptions,\n): Promise<ModelEntry[]> {\n const target = await resolveHarnessTarget(harnessId);\n return (await target.listModels?.(registry, options)) ?? [];\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { registryCredentialEnv } from './chunk-X37JUNEW.js';
1
+ import { registryCredentialEnv } from './chunk-QJQQNBVT.js';
2
2
  import { mergeRegistries } from './chunk-RXGPFAMN.js';
3
3
  import { createLogger } from './chunk-BOFL7GIF.js';
4
4
  import { EventEmitter } from 'events';
@@ -269,5 +269,5 @@ var AgentHarness = class extends EventEmitter {
269
269
  };
270
270
 
271
271
  export { AGENT_EFFORT_LEVELS, AgentHarness, TOOL_ALLOWLIST_UNSUPPORTED, getBridgeLogger, registryHarnessConfig, toAgentEffort, toMergedRegistry };
272
- //# sourceMappingURL=chunk-M4OG2YN4.js.map
273
- //# sourceMappingURL=chunk-M4OG2YN4.js.map
272
+ //# sourceMappingURL=chunk-QSIFEHSN.js.map
273
+ //# sourceMappingURL=chunk-QSIFEHSN.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../bridge/src/logger.ts","../bridge/src/provider-registry-derive.ts","../bridge/src/types.ts"],"names":[],"mappings":"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","file":"chunk-M4OG2YN4.js","sourcesContent":["/**\n * Bridge-layer logger factory.\n *\n * Each harness creates its own Logger via `getBridgeLogger(subkind)` at\n * construction time. Falls back to an off-mode Logger (stdout only) when\n * no LogStore is registered — see @skaile/workspaces/core/logging for details.\n */\n\nimport { createLogger } from \"@skaile/workspaces/core/logging\";\nimport type { Logger } from \"@skaile/workspaces/types\";\n\n/**\n * Construct a bridge-scoped Logger for a given harness subkind.\n *\n * Creates a `Logger` with `kind: \"bridge\"` and the specified `subkind`. Falls back to\n * an off-mode Logger (stdout only) when no `LogStore` is registered — see\n * `@skaile/workspaces/core/logging` for details. Each harness calls this once at construction\n * time; never re-construct per call.\n *\n * @param subkind - Harness id, e.g. `\"claude-sdk\"`, `\"omp\"`, `\"echo\"`, `\"codex\"`.\n * @returns A `Logger` scoped to `bridge:<subkind>`.\n * @docLink packages/bridge/api-reference#logger\n */\nexport function getBridgeLogger(subkind: string): Logger {\n return createLogger({ kind: \"bridge\", subkind });\n}\n","/**\n * The two shaping helpers every registry consumer needs.\n *\n * The legacy provider axis — `provider` / `cloud` / `cloud_config` /\n * `cloudSecrets` — is gone from the runtime, and so is the user-local\n * `settings.json` `apiKeys{}` map: a session carries an AI provider registry\n * and a model selector, nothing else. Credentials are named by a\n * `credential.ref` and resolved into the child environment; no literal secret\n * ever enters an entry.\n */\n\nimport {\n type AIProviderLayerId,\n type AIProviderRegistry,\n type MergedAIProviderRegistry,\n mergeRegistries,\n} from \"@skaile/workspaces/core/provider-registry\";\nimport {\n type RegistryCredentialOptions,\n registryCredentialEnv,\n} from \"./provider-materialize/credential-env.js\";\n\n/** Turn any registry shape into the merged view, without re-merging one. */\nexport function toMergedRegistry(\n registry: AIProviderRegistry | MergedAIProviderRegistry,\n layer: AIProviderLayerId = \"session\",\n): MergedAIProviderRegistry {\n if (Array.isArray((registry as MergedAIProviderRegistry).order)) {\n return registry as MergedAIProviderRegistry;\n }\n return mergeRegistries([{ layer, providers: registry as AIProviderRegistry }]);\n}\n\n/**\n * The `AgentConfig` slice a `HarnessTarget.listModels` closure builds its\n * throwaway harness from: the registry, the selector when the caller named one\n * entry, and the credentials as a child-environment fragment.\n *\n * The credentials have to ride `env`, not a side channel: a `platform:` or\n * `cmd:` reference resolves where the *caller* stands, and this process's own\n * environment cannot see it. `registryCredentialEnv` writes each one under\n * `SKAILE_AIP_<ID>_KEY`, which is the carrier every harness already consults.\n */\nexport function registryHarnessConfig(\n registry: AIProviderRegistry | MergedAIProviderRegistry,\n options: RegistryCredentialOptions = {},\n): { registry: MergedAIProviderRegistry; env: Record<string, string>; modelRef?: string } {\n const merged = toMergedRegistry(registry, \"runtime\");\n return {\n registry: merged,\n env: registryCredentialEnv(merged, options),\n ...(options.providerId ? { modelRef: options.providerId } : {}),\n };\n}\n","import { EventEmitter } from \"node:events\";\nimport type { Span, TelemetryProvider, Trace } from \"@skaile/workspaces/telemetry\";\nimport type {\n AgentPromptInput,\n Capability,\n CredentialMint,\n CodexCredentialDelivery,\n ContextUsageDetail,\n HarnessContextReport,\n HarnessInfo,\n ErrorRetryReason,\n CodexSubscriptionRefreshInput,\n CodexSubscriptionRefreshResult,\n FlowExecution,\n ModelTokenUsage,\n RenderInvokedEvent,\n TokenUsage,\n} from \"@skaile/workspaces/types\";\nimport type { CodexServerRequestHandlers } from \"./codex-app-server.js\";\nexport type { AgentPromptInput } from \"@skaile/workspaces/types\";\nimport type { MergedAIProviderRegistry } from \"@skaile/workspaces/core/provider-registry\";\nimport type { ModelEntry } from \"./models.js\";\n\n/**\n * Test-only hook injected by the runner so a no-LLM harness (the echo harness's\n * scripted-flow mode) can read flow state and drive flow-adapter mutations\n * without an SDK/MCP round-trip. The runner wires this in `createActiveFlow`\n * from the active FlowAdapter + handle.\n *\n * This is an internal runner↔harness interface — NOT part of any wire\n * protocol or flow contract. Production harnesses ignore it.\n *\n * @see packages/bridge/harnesses/echo — scripted-flow mode\n * @since 3.6.0\n */\nexport interface FlowTestHarnessHook {\n /** Current flow execution snapshot, or `null` when no flow is active. */\n getState(): FlowExecution | null;\n /**\n * Execute a flow-adapter operation (`start_node`, `request_approval`,\n * `complete_node`, `request_input`, `skip_node`, `fail_node`, …). Returns\n * the adapter's JSON string result (or rejects on an illegal transition).\n */\n execute(op: string, args: Record<string, unknown>): Promise<string>;\n /**\n * Node IDs marked as mandatory approval gates. The scripted policy resolves\n * `auto` to `request_approval` for these even in autonomous mode, so hosts\n * can drive a mandatory gate deterministically. Optional — absent hooks\n * behave as if no node is mandatory.\n */\n mandatoryGates?(): string[];\n}\n\n/**\n * Minimal LLM tool descriptor used by the capability dispatch path. Mirrors\n * the runner's `LLMTool` shape so harnesses can consume registry output without\n * importing `@skaile/workspaces/runner` (which would create a circular dep).\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/bridge/concepts#bridge-capability-tool\n */\nexport interface BridgeCapabilityTool {\n /** Capability name; used as the LLM-visible tool name. */\n name: string;\n /** Human/LLM-readable description. */\n description: string;\n /** JSON Schema for the tool's input parameters. */\n parameters: Record<string, unknown>;\n}\n\n/**\n * Render-cap event emission callback used by the bridge when the LLM invokes\n * a capability that carries a `render` spec. The runner provides the actual\n * sink (transport.send / sendEvent); the bridge only emits.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/bridge/concepts#bridge-render-emit\n */\nexport type BridgeRenderEmit = (event: RenderInvokedEvent) => void;\n\n/**\n * Text-event emission callback for render-capability fallbacks. When a\n * `RenderCapability` carries `render.fallback` and the LLM invokes it, the\n * bridge substitutes `{{prop}}` placeholders (top-level keys of `props`,\n * optional dotted-path traversal `{{user.name}}`) and pushes the rendered\n * string through this callback so clients without a render layer still see\n * a textual representation. No-op when `fallback` is absent.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/bridge/concepts#bridge-text-emit\n */\nexport type BridgeTextEmit = (text: string) => void;\n\n/**\n * Bundle of capability dispatch hooks. Registered into the harness via\n * `AgentConfig.capabilities`; the harness routes registered LLM tool calls\n * back into `invoke()` instead of using its native dispatch path.\n *\n * The runner constructs this from a `CapabilityRegistry` instance and threads\n * it through `createAgentSession()`. Harnesses that don't yet implement\n * capability dispatch ignore the field — legacy v1 paths stay intact.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/bridge/concepts#bridge-capability-hooks\n */\nexport interface BridgeCapabilityHooks {\n /** Build the LLM tool descriptor list from the registry. Called per turn so registration changes take effect. */\n composeTools(): BridgeCapabilityTool[];\n /** Resolve a wire-format Capability descriptor by name. Used by the bridge to inspect `fireAndForget` / `render`. */\n resolve(name: string): Capability | null;\n /**\n * Validate input + dispatch through the registry. Logging is wired by the\n * registry.\n *\n * `callId` is the per-dispatch id minted by `dispatchCapability`. It MUST be\n * unique per process (never a harness/provider tool-call id, which only the\n * model backend keeps unique): it is the `render_invoked.callId`, the\n * registry's log correlation id, the handler's `ctx.callId` and — for client\n * capabilities — the `capability_invoked.callId` keying the runner's pending\n * map, so a reused id would let a late `capability_result` for a timed-out\n * call resolve a later call. Callers without one omit it and the registry\n * generates a fresh id.\n */\n invoke(name: string, input: unknown, signal?: AbortSignal, callId?: string): Promise<unknown>;\n /** Subscribe to registry changes; callback carries no credentials or tool payloads. */\n onToolsChanged?(listener: () => void): () => void;\n /** Emit a render-invoked event. The runner forwards via the WebSocket transport. */\n emitRender?: BridgeRenderEmit;\n /** Emit a text fallback for render capabilities with `render.fallback`. */\n emitText?: BridgeTextEmit;\n /** Session id passed through to the runner's per-handler logger. */\n sessionId: string;\n}\n\n/**\n * Static metadata for a registered agent harness (the coding-agent product it drives).\n *\n * Declared once in `@skaile/workspaces/types` — it is protocol surface (the\n * platform reads `surfaces` to decide which AI provider registry entries a\n * harness can serve) and was previously duplicated here field-for-field.\n *\n * Returned by {@link listHarnesses} and exposed on every {@link AgentHarness}\n * instance via `harnessInfo`.\n *\n * @docLink packages/bridge/concepts#harness-info\n */\nexport type { HarnessInfo };\n\n/** Closed, passive managed-MCP observations. Counts saturate at 512. */\nexport interface CodexNativeMcpDiagnostics {\n startupBeforeTurn: \"unknown\" | \"starting\" | \"ready\" | \"failed\" | \"cancelled\";\n startupAtEnd: CodexNativeMcpDiagnostics[\"startupBeforeTurn\"];\n toolsListBeforeTurn: number;\n toolsListTotal: number;\n toolsCallTotal: number;\n nativeMcpToolItemCount: number;\n}\n\n/** Trusted session-local tool transport; fulfilled only after required tools are ready. */\nexport interface CodexToolTransport {\n mcpServers: Record<string, Record<string, unknown>>;\n /** Trusted runner server eligible for human native consent; must name its configured entry. */\n approvalServerName?: string;\n onServerRequest?: CodexServerRequestHandlers;\n /** Revalidate the required live inventory before starting each turn. */\n validate?(): Promise<void>;\n /** Rebuild the native generation at idle when its advertised inventory is stale. */\n needsReload?(): boolean;\n instructions?: string;\n /** Restrict model calls to the active turn and abort outstanding calls when it ends. */\n beginTurn?(signal: AbortSignal): void;\n /** Trusted private server binding and passive request-handler counters; never performs I/O. */\n diagnostics?: {\n serverName: string;\n requestCounts(): { toolsListTotal: number; toolsCallTotal: number };\n };\n dispose(): Promise<void>;\n}\n\n/** Explicit managed instance inputs; none are inferred from ambient developer state. */\nexport interface CodexManagedRuntimeOptions {\n executable: string;\n /** Optional launcher arguments, for the caller-owned executable wrapper. */\n executableArgs?: string[];\n /** Private local filesystem state; the host must fence old native processes before reuse. */\n privateDirectory: string;\n /** Host-owned private mount containing every parent/child instance; denied to native tools. */\n privateRoot: string;\n environment: Record<string, string>;\n credential: CodexCredentialDelivery;\n instructionFiles?: string[];\n skillsDirectory?: string;\n prepareTools(signal: AbortSignal): Promise<CodexToolTransport>;\n /**\n * Passive snapshots before/after turns, plus final local counts after successful transport closure.\n * No final snapshot is emitted on uncertain cleanup or a failed final counter read. Earlier snapshots\n * are not proof of completed cleanup. Sink failures never affect native execution or cleanup.\n */\n onNativeMcpDiagnostics?(value: Readonly<CodexNativeMcpDiagnostics>): void | Promise<void>;\n refreshCredential?: (\n input: CodexSubscriptionRefreshInput,\n signal: AbortSignal,\n ) => Promise<CodexSubscriptionRefreshResult>;\n requestTimeoutMs?: number;\n turnTimeoutMs?: number;\n /** Maximum native turns admitted by this instance; reserved for disposable one-turn children. */\n nativeTurnBudget?: 1;\n /** Human interaction deadline, bounded separately from ordinary RPCs. */\n interactionTimeoutMs?: number;\n}\n\n/**\n * Codex-specific tuning options passed through `HarnessOptions.codex`.\n *\n * @remarks These are forwarded verbatim to the Codex harness and have no effect on other harnesses.\n * @docLink packages/bridge/concepts#codex-harness-options\n */\nexport interface CodexHarnessOptions {\n /** Omission retains the standalone SDK path; managed mode always requires App Server inputs. */\n authSource?: \"local\" | \"managed\";\n managedRuntime?: CodexManagedRuntimeOptions;\n /** Controls whether Codex may auto-apply edits without user approval. */\n approvalPolicy?: \"never\" | \"on-request\" | \"on-failure\" | \"untrusted\";\n /** Filesystem sandbox level for the Codex process. */\n sandboxMode?: \"read-only\" | \"workspace-write\" | \"danger-full-access\";\n /** Reasoning budget passed to the model. */\n reasoningEffort?: \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\n /** When `true`, the Codex sandbox is allowed to make outbound network requests. */\n networkAccessEnabled?: boolean;\n /** Extra directories made accessible to the Codex sandbox in addition to `cwd`. */\n additionalDirectories?: string[];\n}\n\n/**\n * omp-specific options passed through `HarnessOptions.omp`.\n *\n * They govern the session-private agent directory the omp adapter renders the\n * provider registry into (`omp-models-yml.ts`); every one of them has a\n * working default, so a caller that sets none still gets a correct session.\n *\n * @remarks Forwarded verbatim to the omp harness; no effect on other harnesses.\n * @see PROVIDER-CONFIG-PLAN.md §2.3\n */\nexport interface OmpHarnessOptions {\n /**\n * Explicit session-private agent directory for `PI_CODING_AGENT_DIR`.\n * Defaults to `<cwd>/.omp/agent-home/<sessionId>`.\n */\n agentHome?: string;\n /**\n * Inherit the developer's own omp state (auth store, blobs, extensions) by\n * symlinking {@link OmpHarnessOptions.userAgentDir} into the session\n * directory. Defaults to *on when that directory exists*, which is exactly\n * the standalone case: a platform container has none, so its session starts\n * empty. Set `false` to force an empty session directory regardless.\n */\n seedUserAgentDir?: boolean;\n /** Seed source. Defaults to `~/.omp/agent`. */\n userAgentDir?: string;\n}\n\n/**\n * Harness-specific configuration bag.\n *\n * Fields are keyed by harness ID so that callers can pass harness-specific options\n * through the common {@link AgentConfig} without breaking other harnesses.\n *\n * @docLink packages/bridge/concepts#harness-options\n */\nexport interface HarnessOptions {\n /** Codex-specific options. Ignored by all other harnesses. */\n codex?: CodexHarnessOptions;\n /** omp-specific options. Ignored by all other harnesses. */\n omp?: OmpHarnessOptions;\n}\n\n/**\n * What the harness tells the host about a turn blocked by an upstream usage\n * limit. Everything but `configId` is best-effort: the SDK reports the limit\n * window only on its structured telemetry, not on the error result text.\n *\n * @see AgentConfig.onLimitBlocked\n * @category Configuration\n * @since 3.9.0\n */\nexport interface LimitBlockedContext {\n /** The AI provider config the blocked turn ran on (`\"\"` when unmediated). */\n configId: string;\n /** Upstream limit window (`five_hour`, `seven_day`, …) when reported. */\n limitType?: string;\n /** Epoch seconds at which the limit window resets, when reported. */\n resetsAt?: number;\n /** Fraction of the limit window consumed (0–1) when reported. */\n utilization?: number;\n}\n\n/**\n * The host's verdict on a limit-blocked turn. `switched: true` is a promise\n * that a different seat's credential is already on disk — the harness acts on it\n * by respawning the CLI and replaying the prompt, so returning it without\n * having rewritten the credential file would just replay onto the dead seat.\n *\n * @see AgentConfig.onLimitBlocked\n * @category Configuration\n * @since 3.9.0\n */\nexport interface LimitFailoverResult {\n /** Whether the session was repointed at a different AI provider config. */\n switched: boolean;\n /** The config id now in effect. Informational — used for logs. */\n configId?: string;\n /**\n * Why no switch happened: `same-config`, `standalone`,\n * `platform-omitted-config-id` (the mint succeeded but named no seat, so a\n * re-resolution is indistinguishable from none), or a `CredentialMint`\n * failure code. Diagnostic only — the harness branches on `switched`.\n */\n reason?: string;\n}\n\n/**\n * One observed AI-provider rejection, reported to the host for per-seat health\n * attribution. Fire-and-forget — see {@link AgentConfig.onProviderResponse}.\n *\n * @category Configuration\n * @since 3.9.0\n */\nexport interface ProviderResponseObservation {\n /** 401 — the credential was rejected. 429 — an upstream rate/session limit. */\n status: 401 | 429;\n /** The AI provider config the observation is attributed to, when known. */\n configId?: string;\n /** Upstream limit window (`five_hour`, `seven_day`, …) when reported. */\n limitType?: string;\n /** Fraction of the limit window consumed (0–1) when reported. */\n utilization?: number;\n /** Epoch seconds at which the limit window resets, when reported. */\n resetsAt?: number;\n /**\n * What the 429 was, when the harness recognised something narrower than a\n * usage limit. `long-context-entitlement`: the account may not use a long\n * (1M) context window; the seat is not out of quota. Diagnostic only — the\n * harness still treats the rejection as before.\n */\n cause?: ProviderResponseCause;\n}\n\n/**\n * Why a 429 {@link ProviderResponseObservation} was rejected, when the harness\n * recognised it. Consumers must tolerate values they do not know.\n *\n * @category Configuration\n * @since 4.11.0\n */\nexport type ProviderResponseCause = \"long-context-entitlement\";\n\n/**\n * One upstream quota-window reading, reported to the host for every SDK\n * `rate_limit_event` — allowed, warning or rejected alike. Fire-and-forget —\n * see {@link AgentConfig.onProviderQuota}.\n *\n * @category Configuration\n * @since 4.1.0\n */\nexport interface ProviderQuotaObservation {\n /** The AI provider config the reading is attributed to, when known. */\n configId?: string;\n /** Upstream window, verbatim (`five_hour`, `seven_day`, or a future value). */\n window: string;\n /** Upstream status, verbatim (`allowed`, `allowed_warning`, `rejected`, …). */\n status: string;\n /** Fraction of the window consumed (0–1); the SDK reports it on warnings and rejections only. */\n utilization?: number;\n /** Epoch seconds at which the window resets, when reported. */\n resetsAt?: number;\n}\n\n/**\n * Reasoning effort levels a host may set. The platform sends all five, the\n * Agent SDK accepts all five, omp has a same-named thinking level for each, and\n * managed codex passes the value to its app server.\n *\n * @since 4.22.0\n */\nexport const AGENT_EFFORT_LEVELS = [\"low\", \"medium\", \"high\", \"xhigh\", \"max\"] as const;\nexport type AgentEffort = (typeof AGENT_EFFORT_LEVELS)[number];\n\n/**\n * Narrow a free-form effort (the wire `agentConfig.effort`, a `skaile.yaml`\n * default) to an {@link AgentEffort}; anything else gives `undefined`, so an\n * unknown value never reaches a harness.\n */\nexport function toAgentEffort(value: unknown): AgentEffort | undefined {\n return isAgentEffort(value) ? value : undefined;\n}\n\nfunction isAgentEffort(value: unknown): value is AgentEffort {\n return (AGENT_EFFORT_LEVELS as readonly unknown[]).includes(value);\n}\n\n/**\n * Configuration passed to a harness when it is created via {@link createHarness}.\n *\n * All fields are shared across harnesses; harness-specific behaviour is documented\n * per field. Fields that are silently ignored by a harness are marked accordingly.\n *\n * @docLink packages/bridge/concepts#agent-config\n */\nexport interface AgentConfig {\n /** Absolute path to the working directory the agent operates in. */\n cwd: string;\n /**\n * LLM model identifier (e.g. `\"claude-sonnet-4-5\"`, `\"gpt-4o\"`).\n *\n * The unscoped fallback: {@link AgentConfig.modelRef} is what a session\n * normally carries, and this is what a harness falls back to when no\n * registry entry resolved one.\n */\n model?: string;\n /**\n * The AI provider registry for this session — every endpoint the harness may\n * address, already merged across the catalog / user / workspace / runtime /\n * control-plane layers and in registry order.\n *\n * This is the *only* provider surface a harness reads. Entries reference\n * their credential (`credential.ref`) and never carry the secret itself;\n * the value reaches the child under `SKAILE_AIP_<ID>_KEY`\n * (`provider-materialize/credential-env.ts`), which the session boundary\n * puts in {@link AgentConfig.env}.\n *\n * Absent (or empty) means no endpoint was configured at all — the harness\n * then falls back to whatever native auth it can discover on its own (a\n * `claude` OAuth login, `codex login`, an ambient vendor key).\n */\n registry?: MergedAIProviderRegistry;\n /**\n * Model selector resolved against {@link AgentConfig.registry}:\n * `\"<providerId>/<modelId>\"`, a bare `\"<modelId>\"` (first registry entry\n * that maps it wins), or `\"@role\"`. Absent when no model was configured at\n * all — the harness then applies its own default, exactly as it does for an\n * absent `model`.\n */\n modelRef?: string;\n /**\n * The `skaile.yaml` `roles` table — role name → model selector\n * (`{default: \"anthropic/opus\", smol: \"groq/llama-3.1-8b\"}`, §9.8). It is\n * what `\"@role\"` in {@link AgentConfig.modelRef} expands through, and what\n * a harness that supports per-role models materializes natively: omp renders\n * it as `modelRoles` in its session-private `config.yml`, so `@smol` inside\n * the session reaches a different provider than `@default`.\n *\n * Resolution is lenient: a role naming an entry this registry does not have\n * is a warning, never a failure.\n */\n roles?: Record<string, string>;\n /**\n * Additional environment variables merged into the child process\n * environment. The session boundary delivers resolved registry credentials\n * here as `SKAILE_AIP_<ID>_KEY` entries; anything else the caller sets is\n * merged over the harness's own allowlist, never instead of it.\n */\n env?: Record<string, string>;\n /** Inline system prompt — written to .omp/system.md and passed via --append-system-prompt (omp harness) */\n systemPrompt?: string;\n /** Path to project .omp/ directory (PI_CODING_AGENT_DIR for omp harness) */\n agentDir?: string;\n /** SSH key path — injected as GIT_SSH_COMMAND */\n sshKeyPath?: string;\n /** Pre-assign a UUID as the session ID for a new session (claude-sdk: passed as sessionId option) */\n sessionId?: string;\n /** Resume this specific past session by UUID instead of starting fresh (claude-sdk: passed as resume option) */\n resumeSessionId?: string;\n /** Maximum agentic turns per query (claude-sdk: passed as maxTurns option) */\n maxTurns?: number;\n /**\n * Whether the agent may act on its own (`auto`, the default) or has to be approved per tool\n * call (`interactive`); the `agents.<id>.permissions.permission_mode` of the instance.\n *\n * - claude-sdk: `auto` runs under the SDK's `bypassPermissions`; `interactive` runs under\n * `default`, and a call the SDK does not auto-allow (a shell command, a file edit, an MCP\n * tool) pauses the turn on a `question` event with an `approval` card (`Approve once` /\n * `Deny`) answered through `answerQuestion`. With {@link AgentConfig.unattended} the call is\n * refused instead.\n * - codex (standalone SDK path): `interactive` sets `approvalPolicy: \"on-request\"` instead of\n * `never`, unless `harnessOptions.codex.approvalPolicy` is set. The standalone SDK path has no\n * way to show an approval card, so codex refuses a command that needs to leave its sandbox\n * instead of asking; nothing is ever approved. A managed codex session keeps the host's own\n * policy.\n * - omp, echo and the subprocess CLI harnesses (gemini, qwen, opencode, goose, continue): ignored.\n */\n permissionMode?: \"auto\" | \"interactive\";\n /**\n * The session has no one to answer a question (a nested `agent.run` role session, a\n * single-shot `skaile run` without a terminal). With `permissionMode: \"interactive\"` a tool\n * call that needs approval is then refused (claude-sdk) instead of waiting for a reply.\n */\n unattended?: boolean;\n /** Agent name — selects a deployed sub-agent definition as the main agent identity.\n * claude-sdk: passed as `agent` option to query() → reads .claude/agents/<name>.md natively.\n * omp: ignored (omp uses agentDir/PI_CODING_AGENT_DIR instead). */\n agentName?: string;\n /** In-process SDK MCP servers for custom tool injection (Claude SDK only, ignored by other harnesses) */\n mcpServers?: Record<string, unknown>;\n /** Tool restrictions from agent.yaml — applied to the main agent session */\n tools?: {\n /** Tool names that the agent is allowed to invoke. An empty array means no restriction. */\n allowed?: string[];\n /** Tool names that the agent is explicitly forbidden from invoking. */\n denied?: string[];\n };\n /** Thinking mode for Claude models: adaptive (Claude decides), enabled (always think), disabled (no thinking). */\n thinking?: \"adaptive\" | \"enabled\" | \"disabled\";\n /** Reasoning effort level; each harness maps it to its own scale (see {@link AgentEffort}). */\n effort?: AgentEffort;\n /** Harness-specific configuration bag. */\n harnessOptions?: HarnessOptions;\n /**\n * Protocol v2 capability dispatch hooks. When present, the harness uses the\n * registry as the source of LLM tool definitions and routes invocations\n * through `capabilities.invoke()`. Absent → legacy v1 path (existing\n * mcpServers / native dispatch).\n *\n * @since 2.0.0\n */\n capabilities?: BridgeCapabilityHooks;\n /**\n * The platform's `AIProviderConfig.id` for the AI credential currently\n * provisioned into this harness. The runner reads this off `AgentConfig`\n * during 401 mediation and passes it as `configId` in\n * `request_access_token { kind: 'ai-credentials' }`. The harness itself\n * does not consume this field — only the runner uses it.\n *\n * Set by the platform agent-gateway in `ConfigureCommandV2` for mediated\n * sessions. Standalone runners (CLI / forge / Claude plugin) leave it\n * undefined; the runner falls back to surfacing the auth error to the\n * user without mediating.\n *\n * Spec: `_devlog/specs/2026-05-07-unified-credential-mediation.md`\n * § \"Wire `aiProviderConfigId` end-to-end\".\n *\n * @since 3.3.0\n */\n aiProviderConfigId?: string;\n /**\n * Optional callback invoked by the harness when the underlying agent\n * surfaces an `authentication_error`. In Protocol v3 the runner mediates\n * the refresh via the `host.refresh_credential` capability and returns a\n * typed {@link CredentialMint}. The harness inspects the discriminator:\n *\n * - `mint.ok === true`: a fresh credential is now provisioned. The\n * harness re-attempts the in-flight prompt once.\n * - `mint.ok === false`: refresh failed (`code` carries a stable reason\n * such as `revoked`, `not-configured`, `provider-error`,\n * `backend-error`). The harness surfaces the original `AuthError` to\n * the caller.\n *\n * `args.configId` carries the platform `AIProviderConfig.id` the harness\n * was provisioned with (mirrors {@link AgentConfig.aiProviderConfigId}).\n * The runner uses it to scope the refresh to the correct AI credential.\n *\n * When omitted, the harness throws `AuthError` immediately as before\n * (standalone CLI / forge mode — there is no platform mediator to ask).\n *\n * Centralising auth-retry inside the harness means every consumer of\n * `harness.prompt(...)` (serve handler, compaction orchestrator, flow\n * orchestrator, …) gets self-healing for free — there is no per-call-site\n * wrapping.\n *\n * Spec: `_devlog/specs/2026-05-10-deterministic-session-bootstrap.md`\n * § \"host.refresh_credential capability\".\n *\n * @since 3.4.0\n */\n onAuthError?: (args: { configId: string }) => Promise<CredentialMint>;\n /**\n * Optional callback invoked by the harness when a turn is blocked by an\n * upstream **usage limit** rather than a bad credential — the subscription\n * five-hour / seven-day ceiling, or any `rate_limit` the classifier\n * recognises. Called at most once per logical turn, and only after the\n * blocked attempt has already failed, so it never runs mid-turn.\n *\n * The runner implements it by asking the platform to re-resolve the seat:\n *\n * - `switched: true` — the session was repointed at a DIFFERENT AI\n * provider config and `.credentials.json` was rewritten. The harness\n * drops its query (forcing a fresh CLI spawn, which is what clears a\n * resident CLI's cached \"blocked until <reset>\" state — a hot file\n * rewrite alone does not) and replays the prompt once.\n * - `switched: false` — no alternative seat was available. The harness\n * surfaces the original limit error unchanged.\n *\n * Left unset by standalone runners (CLI / forge / Claude plugin): there is\n * no platform mediator to re-resolve a seat, so the limit error surfaces\n * exactly as it does today.\n *\n * Companion to {@link onAuthError}: that one covers 401s, this one covers\n * the rejection path, which previously reached no failover at all\n * (skaile-ai/workspaces#567, skaile-ai/platform#2976).\n *\n * @since 3.9.0\n */\n onLimitBlocked?: (ctx: LimitBlockedContext) => Promise<LimitFailoverResult>;\n /**\n * Optional fire-and-forget hook invoked when the harness observes a 401 or a\n * 429 / subscription-limit rejection from the AI provider. The runner\n * forwards it to the platform as a `provider_response_seen` event so the\n * owning `AIProviderConfig`'s live health counters can be bumped — the cron\n * health probe only samples auth, never capacity\n * (skaile-ai/workspaces#368, skaile-ai/platform#3539).\n *\n * Never awaited and never retried; the harness swallows a throwing\n * implementation so telemetry can never fail a turn.\n *\n * @since 3.9.0\n */\n onProviderResponse?: (observation: ProviderResponseObservation) => void;\n /**\n * Optional fire-and-forget hook invoked for every upstream quota-window\n * reading (claude-sdk `rate_limit_event`), not only rejections. The runner\n * forwards it as `provider_quota_observed`, which is the only quota signal\n * the platform has for a seat whose token cannot read the OAuth usage\n * endpoint (a `claude setup-token` seat).\n *\n * Never awaited and never retried; the harness swallows a throwing\n * implementation so telemetry can never fail a turn. Unlike\n * {@link onProviderResponse} it fires on every event, so dedupe at the host.\n *\n * @since 4.1.0\n */\n onProviderQuota?: (observation: ProviderQuotaObservation) => void;\n /**\n * Test-only flow harness hook. When present, the echo harness's scripted-flow\n * mode uses it to advance flow nodes deterministically (no LLM). The runner\n * injects it in `createActiveFlow`; every other harness ignores it.\n *\n * @see FlowTestHarnessHook\n * @since 3.6.0\n */\n flowTestHarness?: FlowTestHarnessHook;\n}\n\n/**\n * A single message in an agent conversation.\n *\n * Emitted as part of {@link AgentEvent} variants (`message_start`, `message_update`, `message_end`).\n *\n * @docLink packages/bridge/concepts#agent-message\n */\nexport interface AgentMessage {\n /** Originator of the message. */\n role: \"user\" | \"assistant\" | \"tool\";\n /** Message body — either a plain string or a list of typed content blocks. */\n content: string | ContentBlock[];\n /** Tool invocations made by the assistant in this message. */\n toolCalls?: ToolCall[];\n /** For `role === \"tool\"`: the name of the tool whose result this message carries. */\n toolName?: string;\n /** For `role === \"tool\"`: `true` when the tool returned an error. */\n isError?: boolean;\n /** Optional structured payload for tool results. */\n data?: unknown;\n /**\n * Set when a subagent produced this message: the id of the tool use that\n * runs the subagent. Absent on main-thread messages.\n */\n parentToolUseId?: string;\n}\n\n/**\n * A typed block within an {@link AgentMessage}'s content array.\n *\n * Mirrors the Anthropic content block schema but is harness-agnostic.\n *\n * @docLink packages/bridge/concepts#content-block\n */\nexport interface ContentBlock {\n /** Block discriminant. */\n type: \"text\" | \"tool_use\" | \"tool_result\" | \"thinking\";\n /** Present for `text` and `thinking` blocks. */\n text?: string;\n /** Tool use / tool result correlation ID. */\n id?: string;\n /** Tool name (present on `tool_use` blocks). */\n name?: string;\n /** Tool input arguments (present on `tool_use` blocks). */\n input?: any;\n /** Serialised tool result content (present on `tool_result` blocks). */\n content?: string;\n}\n\n/**\n * A single tool invocation made by the agent within a message.\n *\n * @docLink packages/bridge/concepts#tool-call\n */\nexport interface ToolCall {\n /** Correlation ID used to match the call with its result. */\n id: string;\n /** Name of the tool being invoked. */\n name: string;\n /** Arguments passed to the tool. */\n input: any;\n}\n\n/**\n * Error classification for agent failures.\n *\n * Used to determine whether a failure is retryable and to surface actionable\n * hints to the user. See `bridge/CLAUDE.md` for the full category-to-behaviour matrix.\n *\n * @see AgentError\n * @docLink packages/bridge/concepts#error-category\n */\nexport type ErrorCategory =\n | \"auth\"\n | \"account\"\n | \"rate_limit\"\n | \"model\"\n | \"network\"\n | \"config\"\n | \"process\"\n | \"validation\"\n | \"unknown\";\n\n/**\n * Structured error payload emitted inside the `error` {@link AgentEvent}.\n *\n * Consumers should inspect `retryable` before deciding to surface a retry button,\n * and `hint` to provide an actionable message to the user.\n *\n * @docLink packages/bridge/concepts#agent-error\n */\nexport interface AgentError {\n /** Human-readable error description. */\n message: string;\n /** Coarse failure classification used for retry logic and telemetry. */\n category: ErrorCategory;\n /** HTTP status code if the error originated from an API response. */\n statusCode?: number;\n /** `true` when the caller may safely retry the same operation. */\n retryable: boolean;\n /** Short actionable advice suitable for display in the UI. */\n hint?: string;\n}\n\n/**\n * Metadata for a slash command exposed by the active agent runtime.\n *\n * @docLink packages/bridge/concepts#slash-command-info\n */\nexport interface SlashCommandInfo {\n /** Command name without the leading slash (e.g. `\"compact\"`). */\n name: string;\n /** One-line description shown in command pickers. */\n description: string;\n /** Placeholder text describing what argument the command expects. */\n argumentHint?: string;\n}\n\n/**\n * Discriminated union of all events emitted by a harness on the `'agent-event'` channel.\n *\n * @remarks\n * Consumers listen via `harness.on('agent-event', (event: AgentEvent) => ...)`.\n * The `[k: string]: any` index signature on most variants allows harnesses to attach\n * harness-specific fields (e.g. `_textDelta`) without breaking the union.\n *\n * @docLink packages/bridge/concepts#agent-event\n */\nexport type AgentEvent =\n | { type: \"message_start\"; message: AgentMessage; [k: string]: any }\n | { type: \"message_update\"; message: AgentMessage; [k: string]: any }\n | { type: \"message_end\"; message: AgentMessage; [k: string]: any }\n /**\n * Takes back `text`, the unfinished tail of streamed `_textDelta`s, before the\n * harness replays an abandoned attempt. Always a suffix of what was streamed\n * since the last completed assistant message; see `TextRetractEvent` in the types package.\n */\n | { type: \"message_retract\"; text: string; [k: string]: any }\n | { type: \"turn_end\"; toolResults?: AgentMessage[]; [k: string]: any }\n | { type: \"agent_end\"; [k: string]: any }\n /** A background task started in the running turn; see `BackgroundTaskStartedEvent`. */\n | { type: \"background_task_started\"; taskId: string; [k: string]: any }\n /** A turn the harness was not prompted for began; see `SelfTurnStartedEvent`. */\n | { type: \"self_turn_started\"; taskIds: string[]; [k: string]: any }\n | {\n type: \"result\";\n subtype: string;\n summary?: string;\n costUsd?: number;\n /** Per-turn token usage when the harness tracks it. Added in 3.1.0. */\n tokens?: TokenUsage;\n /** Per-turn usage keyed by model, subagent calls included. Added in 3.11.0. */\n modelUsage?: Record<string, ModelTokenUsage>;\n /** Prompt size of the turn's last main-thread API call. Added in 3.11.0. */\n contextTokens?: number;\n /** Context window of the main model, in tokens. Added in 3.11.0. */\n contextWindow?: number;\n errors?: string[];\n [k: string]: any;\n }\n | {\n type: \"error\";\n error: string;\n detail?: AgentError;\n fatal?: boolean;\n /** Set (with `fatal: false`) when the harness replays the prompt in place; see `ErrorEvent.retrying`. */\n retrying?: boolean;\n retryReason?: ErrorRetryReason;\n /** Usage of a failed provider turn, when reported. */\n tokens?: TokenUsage;\n /** Failed-turn usage keyed by the actual model. */\n modelUsage?: Record<string, ModelTokenUsage>;\n contextTokens?: number;\n contextWindow?: number;\n [k: string]: any;\n }\n | {\n type: \"tool_call\";\n name?: string;\n tool?: { name: string };\n /** Set when a subagent made the call. */\n parentToolUseId?: string;\n [k: string]: any;\n }\n | { type: \"tool_execution_end\"; toolName?: string; parentToolUseId?: string; [k: string]: any }\n | { type: \"commands_available\"; commands: SlashCommandInfo[] }\n | { type: \"session_info\"; harnessSessionId: string; sessionFile?: string }\n | { type: \"ui_render\"; [k: string]: any }\n | { type: \"ui_render_update\"; [k: string]: any }\n | { type: \"ui_clear\"; [k: string]: any }\n // Phase 3 (resume cascade) — harness-emitted resume outcome.\n | {\n type: \"resume_failed\";\n resumeSessionId: string;\n reason:\n | \"signature_mismatch\"\n | \"model_mismatch\"\n | \"jsonl_lost\"\n | \"jsonl_poisoned\"\n | \"native_state_unavailable\";\n [k: string]: any;\n };\n\n/** The settings a live reconfigure may change. */\nexport type ReconfigurePatch = Partial<Pick<AgentConfig, \"model\" | \"thinking\" | \"effort\">>;\n\n/**\n * What a harness now holds for the fields of an accepted reconfigure. `modelRef`\n * is the registry selector the model was scoped to; it is absent when the\n * session has none. A host remembers exactly this, never the raw patch.\n */\nexport interface ReconfigureApplied {\n model?: string;\n modelRef?: string;\n thinking?: AgentConfig[\"thinking\"];\n effort?: AgentConfig[\"effort\"];\n}\n\n/**\n * Result of `AgentHarness.reconfigure()`. `ok: true` means effective from the\n * next turn (live switch, query recycle or respawn); a harness that cannot\n * promise that answers `ok: false` instead.\n *\n * - `not_supported`: the harness cannot change settings live.\n * - `model_not_on_provider`: the session's AI provider entry does not list the\n * model (`providerId` names the entry).\n * - `rejected`: the running process refused the change; the harness config is\n * unchanged.\n *\n * @category Bridge\n */\nexport type ReconfigureOutcome =\n | { ok: true; applied: ReconfigureApplied }\n | {\n ok: false;\n code: \"not_supported\" | \"model_not_on_provider\" | \"rejected\";\n message: string;\n providerId?: string;\n };\n\n/**\n * A reconfigure the harness answered `ok` (it landed mid-turn) and then refused\n * at the next turn boundary. The harness already rolled its config back;\n * `requested` is what was asked, `restored` what it holds again. Emitted as the\n * harness event `'reconfigure-rollback'`.\n */\nexport interface ReconfigureRollback {\n message: string;\n requested: ReconfigureApplied;\n restored: ReconfigureApplied;\n}\n\n/** Rejection message of a harness asked to run a turn under a tool allowlist it cannot enforce. */\nexport const TOOL_ALLOWLIST_UNSUPPORTED = \"This agent harness cannot enforce a tool allowlist\";\n\n/**\n * Abstract base class for agent harnesses.\n *\n * Wraps an LLM coding agent behind a single `prompt()` interface.\n * All harnesses emit `'agent-event'` with {@link AgentEvent} payloads.\n *\n * @remarks\n * Subclasses must implement `start`, `prompt`, `abort`, `kill`, and `isRunning`.\n * Implementations should never emit an event name other than `'agent-event'` as\n * the public streaming channel — internal events (`'ready'`, `'exit'`, etc.) are\n * harness-private. The one other public event is `'reconfigure-rollback'` (a\n * {@link ReconfigureRollback}): a live reconfigure the harness had accepted and\n * then refused at the turn boundary, already rolled back in the harness.\n *\n * @example\n * ```ts\n * const harness = createHarness('omp', config);\n * harness.on('agent-event', (event) => console.log(event.type));\n * await harness.start();\n * await harness.prompt('Refactor the auth module');\n * harness.kill();\n * ```\n *\n * @docLink packages/bridge/concepts#agent-harness\n */\nexport abstract class AgentHarness extends EventEmitter {\n /** Static metadata describing this harness's capabilities. */\n abstract readonly harnessInfo: HarnessInfo;\n\n /**\n * Initialises the harness — spawns the child process (omp) or loads\n * the SDK module (claude-sdk). Resolves when the harness is ready to accept\n * prompts. Idempotent: calling `start()` on an already-running harness is a no-op.\n *\n * @throws {Error} When the harness binary is missing or the SDK cannot be loaded.\n */\n abstract start(): Promise<void>;\n\n /**\n * Sends a user message to the agent and resolves when the agent's turn completes\n * (i.e. after the `agent_end` event has been emitted).\n *\n * @param message - Plain-text user prompt to send to the agent.\n * @throws {Error} When the harness is not running or the underlying coding agent reports a fatal error.\n */\n abstract prompt(message: string): Promise<void>;\n\n /**\n * Preserve text-only callers; harnesses must explicitly support attachments.\n * A `toolAllowlist` is refused here: only a harness that overrides\n * {@link enforcesToolAllowlist} may run a restricted turn.\n */\n promptInput(input: AgentPromptInput): Promise<void> {\n if (input.toolAllowlist !== undefined)\n return Promise.reject(new Error(TOOL_ALLOWLIST_UNSUPPORTED));\n if (input.attachments?.length) return Promise.reject(new Error(\"Structured input unsupported\"));\n return this.prompt(input.text);\n }\n\n /**\n * Whether {@link promptInput} enforces `AgentPromptInput.toolAllowlist` for\n * the whole turn, subagents included. A harness that answers `false` must\n * reject an input carrying one; the runner refuses such a prompt before it\n * reaches the harness.\n */\n get enforcesToolAllowlist(): boolean {\n return false;\n }\n\n /**\n * The names in `allowlist` this harness does not recognize as a tool it could\n * offer. The runner refuses a prompt whose allowlist names any, rather than\n * guess. A harness that does not enforce allowlists recognizes none.\n */\n unknownAllowlistedTools(allowlist: readonly string[]): string[] {\n return [...allowlist];\n }\n\n /** Managed replies never fall back to a new prompt after a request has settled. */\n get acceptsReplyAsPrompt(): boolean {\n return true;\n }\n\n /**\n * Sends an in-band abort signal to the agent, requesting it to stop the current\n * turn without terminating the process. The harness remains usable after `abort()`.\n *\n * @remarks Only meaningful when `harnessInfo.supportsInBandAbort` is `true`.\n * For other harnesses, prefer `kill()` followed by creating a new harness instance.\n */\n abstract abort(): Promise<void>;\n\n /**\n * Terminates the agent harness immediately (SIGTERM for subprocess harnesses,\n * `close()` for in-process harnesses). The harness instance must not be reused\n * after `kill()`.\n */\n abstract kill(): void;\n\n /** Stop the harness and await owned process/state cleanup when the harness supports it. */\n async dispose(): Promise<void> {\n this.kill();\n }\n\n /** `true` when the harness is alive and able to accept new prompts. */\n abstract get isRunning(): boolean;\n\n /** Optional provider-native session/thread identifier for resume support. */\n get runtimeSessionId(): string | undefined {\n return undefined;\n }\n\n /** Slash commands discovered from the agent runtime. Override in harnesses that support introspection. */\n getSlashCommands(): SlashCommandInfo[] {\n return [];\n }\n\n // ── Interactive questions (AskUserQuestion) ──────────────────────────────\n\n /**\n * `true` while the harness is paused on an interactive question and waiting\n * for the user's answer rather than a new prompt. The runner routes a\n * `reply` command to {@link answerQuestion} instead of {@link prompt} when\n * this returns `true`. Harnesses without interactive-question support return\n * `false` (the default), so a `reply` falls back to `prompt`.\n */\n hasPendingQuestion(): boolean {\n return false;\n }\n\n /**\n * Deliver the user's answer to the question the harness is currently paused\n * on. This resumes the in-flight turn — it does NOT start a new one. When a\n * single tool call asks several questions, the harness resolves the underlying\n * call only once every sub-question has an answer.\n *\n * @param answer - The user's reply text (an option label, free text, or for\n * multi-select a comma-joined list).\n * @param question - The sub-question this answers, verbatim from the\n * `question` event that asked it. Supply it whenever the host lets the user\n * answer out of order — without it the answer fills the next unanswered\n * slot in order, which silently mismatches a non-sequential reply.\n * @returns `true` when the answer was consumed by a pending question; `false`\n * when no question was pending (caller should treat the reply as a prompt).\n */\n answerQuestion(answer: string, question?: string, requestId?: string): boolean {\n void requestId;\n void answer;\n void question;\n return false;\n }\n\n /**\n * Apply this harness's rule for a new prompt that meets a pending question,\n * ahead of the prompt itself. The runner queues a prompt behind the turn in\n * flight, so a turn paused on a question would otherwise hold that prompt\n * until the user answered. Harnesses whose `prompt()` cancels the question\n * (claude-sdk, omp) do the same here; the default keeps the question.\n */\n supersedePendingQuestion(): void {\n // No-op: a harness without this rule keeps the question pending.\n }\n\n // ── Live reconfiguration ────────────────────────────────────────────────\n\n /**\n * Live-update harness configuration. `ok: true` means effective from the next\n * turn: the next turn runs on the new settings, by live switch, query recycle\n * or respawn, and the host needs no restart. A turn in progress finishes on\n * the old settings. Only model/thinking/effort are reconfigurable mid-session.\n *\n * Harnesses that can honour that promise build a `ReconfigureLedger` and\n * delegate to it; it owns the model scope rule, ordering, drift and rollback.\n * The base implementation answers `not_supported`.\n */\n reconfigure(patch: ReconfigurePatch): Promise<ReconfigureOutcome> {\n const fields = Object.keys(patch).join(\", \");\n return Promise.resolve({\n ok: false,\n code: \"not_supported\",\n message: `The ${this.harnessInfo.id} harness cannot change ${fields} live; the change applies when the session next starts.`,\n });\n }\n\n /**\n * Returns the model identifier currently configured on this harness.\n * Subclasses that store config locally should override this.\n */\n getModel(): string | undefined {\n return undefined;\n }\n\n // ── Compaction support ──────────────────────────────────────────────────\n\n /**\n * `Date.now()` of the harness's most recent sign of life, counting messages\n * that emit no `agent-event` (thinking deltas, rate-limit telemetry, API\n * retries). A stall check reads it alongside the events it sees. `null` when\n * the harness does not track it.\n */\n lastActivityAt(): number | null {\n return null;\n }\n\n /**\n * Returns the token usage from the most recent completed turn.\n * Returns `null` if usage data is unavailable (e.g. harness doesn't track it).\n *\n * Widened in 3.1.0 to return the full `TokenUsage` shape (input / output /\n * cache-read / cache-creation / reasoning). All fields are optional so\n * harnesses can populate just what their provider reports. Existing callers\n * that read only `inputTokens` / `outputTokens` keep working — those fields\n * are still present and carry the same semantics as before.\n */\n getTokenUsage(): TokenUsage | null {\n return null;\n }\n\n /**\n * Prompt tokens occupying the context window as of the most recent API\n * request — i.e. how full the context actually is right now.\n *\n * Deliberately NOT the same number as {@link getTokenUsage}, whose usage is\n * cumulative over every API call in the turn and therefore overstates the\n * context by 10-40x on any multi-tool turn. Callers measuring context fill\n * (compaction thresholds) must prefer this; callers billing a turn\n * (usage ledgers, the `finished` event) must keep using `getTokenUsage()`.\n *\n * Returns `null` both when the harness cannot report a per-call figure at all\n * and when it can but has no reading yet. Falling back to `getTokenUsage()`\n * is safe in either case only because a harness clears the two in lockstep: no\n * reading means no API call landed, so there is no cumulative usage to\n * overstate. A harness implementing this must preserve that invariant.\n */\n getContextTokens(): number | null {\n return null;\n }\n\n /**\n * Returns the model's context window size in tokens.\n * Returns `null` if unknown.\n */\n getContextWindow(): number | null {\n return null;\n }\n\n /**\n * What the harness can measure natively about its context window, in the\n * neutral {@link HarnessContextReport} shape, or `null` when it measures\n * nothing beyond {@link getContextTokens} / {@link getContextWindow}.\n *\n * `detail: \"full\"` (the default) may be expensive — claude-sdk issues\n * `count_tokens` requests — so the runner asks for it only when a host\n * requests a measured breakdown; `\"summary\"` must make no provider call and\n * is what the per-turn snapshot uses. Implementations must not throw for\n * \"unsupported\"; a rejection means the measurement itself failed and the\n * runner falls back to estimates.\n */\n async getContextUsageReport(_opts?: {\n detail?: ContextUsageDetail;\n }): Promise<HarnessContextReport | null> {\n return null;\n }\n\n /**\n * Returns the list of models available to this harness without starting a session.\n * Harnesses that can enumerate their own models override this method.\n * Returns an empty array by default.\n */\n async listModels(): Promise<ModelEntry[]> {\n return [];\n }\n\n /**\n * Closes the current conversation session and prepares for a fresh start.\n * The next `prompt()` call will begin a new session without prior history.\n * The harness remains usable after `resetSession()`.\n */\n abstract resetSession(): Promise<void>;\n\n // ── Telemetry ─────────────────────────────────────────────────────────────\n\n protected _telemetry?: TelemetryProvider;\n protected _activeTrace?: Trace;\n protected _activeTurnSpan?: Span;\n private _turnStartTime?: number;\n\n /**\n * Attach a telemetry provider and active trace to this harness.\n * Called by the runner after creating the harness but before start().\n */\n setTelemetry(provider: TelemetryProvider, trace: Trace): void {\n this._telemetry = provider;\n this._activeTrace = trace;\n }\n\n /**\n * Begin a turn span. Called by the runner before prompt().\n * Pass a parent span (e.g. the turn span from the orchestrator) for nesting.\n * Returns the span so the runner can annotate it further.\n */\n beginTurnSpan(\n parent?: Trace | Span,\n attrs?: Record<string, string | number | boolean>,\n ): Span | undefined {\n if (!this._telemetry || !this._activeTrace) return undefined;\n this._turnStartTime = Date.now();\n this._activeTurnSpan = this._telemetry.startSpan(parent ?? this._activeTrace, {\n name: \"llm_generation\",\n kind: \"llm_generation\",\n attributes: attrs,\n });\n return this._activeTurnSpan;\n }\n\n /**\n * End the current turn span with generation data.\n * Called by the runner after agent_end. Model and provider are passed\n * explicitly — the harness base class does not access config directly.\n */\n endTurnSpan(result?: {\n model?: string;\n provider?: string;\n inputTokens?: number;\n outputTokens?: number;\n stopReason?: string;\n error?: string;\n }): void {\n if (!this._telemetry || !this._activeTurnSpan) return;\n const durationMs = this._turnStartTime ? Date.now() - this._turnStartTime : 0;\n\n if (result?.inputTokens !== undefined || result?.outputTokens !== undefined) {\n this._telemetry.logGeneration(this._activeTurnSpan, {\n model: result?.model ?? \"unknown\",\n provider: result?.provider ?? \"unknown\",\n inputTokens: result.inputTokens,\n outputTokens: result.outputTokens,\n durationMs,\n stopReason: result.stopReason,\n });\n }\n\n this._telemetry.endSpan(this._activeTurnSpan, {\n status: result?.error ? \"error\" : \"ok\",\n error: result?.error,\n attributes: { \"skaile.turn.duration_ms\": durationMs },\n });\n\n this._activeTurnSpan = undefined;\n this._turnStartTime = undefined;\n }\n}\n\n/**\n * Factory function signature registered in the harness registry.\n *\n * @param config - Configuration for the new harness instance.\n * @returns A freshly constructed (not yet started) {@link AgentHarness}.\n * @docLink packages/bridge/concepts#harness-factory\n */\nexport type HarnessFactory = (config: AgentConfig) => AgentHarness;\n"]}
1
+ {"version":3,"sources":["../bridge/src/logger.ts","../bridge/src/provider-registry-derive.ts","../bridge/src/types.ts"],"names":[],"mappings":"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","file":"chunk-QSIFEHSN.js","sourcesContent":["/**\n * Bridge-layer logger factory.\n *\n * Each harness creates its own Logger via `getBridgeLogger(subkind)` at\n * construction time. Falls back to an off-mode Logger (stdout only) when\n * no LogStore is registered — see @skaile/workspaces/core/logging for details.\n */\n\nimport { createLogger } from \"@skaile/workspaces/core/logging\";\nimport type { Logger } from \"@skaile/workspaces/types\";\n\n/**\n * Construct a bridge-scoped Logger for a given harness subkind.\n *\n * Creates a `Logger` with `kind: \"bridge\"` and the specified `subkind`. Falls back to\n * an off-mode Logger (stdout only) when no `LogStore` is registered — see\n * `@skaile/workspaces/core/logging` for details. Each harness calls this once at construction\n * time; never re-construct per call.\n *\n * @param subkind - Harness id, e.g. `\"claude-sdk\"`, `\"omp\"`, `\"echo\"`, `\"codex\"`.\n * @returns A `Logger` scoped to `bridge:<subkind>`.\n * @docLink packages/bridge/api-reference#logger\n */\nexport function getBridgeLogger(subkind: string): Logger {\n return createLogger({ kind: \"bridge\", subkind });\n}\n","/**\n * The two shaping helpers every registry consumer needs.\n *\n * The legacy provider axis — `provider` / `cloud` / `cloud_config` /\n * `cloudSecrets` — is gone from the runtime, and so is the user-local\n * `settings.json` `apiKeys{}` map: a session carries an AI provider registry\n * and a model selector, nothing else. Credentials are named by a\n * `credential.ref` and resolved into the child environment; no literal secret\n * ever enters an entry.\n */\n\nimport {\n type AIProviderLayerId,\n type AIProviderRegistry,\n type MergedAIProviderRegistry,\n mergeRegistries,\n} from \"@skaile/workspaces/core/provider-registry\";\nimport {\n type RegistryCredentialOptions,\n registryCredentialEnv,\n} from \"./provider-materialize/credential-env.js\";\n\n/** Turn any registry shape into the merged view, without re-merging one. */\nexport function toMergedRegistry(\n registry: AIProviderRegistry | MergedAIProviderRegistry,\n layer: AIProviderLayerId = \"session\",\n): MergedAIProviderRegistry {\n if (Array.isArray((registry as MergedAIProviderRegistry).order)) {\n return registry as MergedAIProviderRegistry;\n }\n return mergeRegistries([{ layer, providers: registry as AIProviderRegistry }]);\n}\n\n/**\n * The `AgentConfig` slice a `HarnessTarget.listModels` closure builds its\n * throwaway harness from: the registry, the selector when the caller named one\n * entry, and the credentials as a child-environment fragment.\n *\n * The credentials have to ride `env`, not a side channel: a `platform:` or\n * `cmd:` reference resolves where the *caller* stands, and this process's own\n * environment cannot see it. `registryCredentialEnv` writes each one under\n * `SKAILE_AIP_<ID>_KEY`, which is the carrier every harness already consults.\n */\nexport function registryHarnessConfig(\n registry: AIProviderRegistry | MergedAIProviderRegistry,\n options: RegistryCredentialOptions = {},\n): { registry: MergedAIProviderRegistry; env: Record<string, string>; modelRef?: string } {\n const merged = toMergedRegistry(registry, \"runtime\");\n return {\n registry: merged,\n env: registryCredentialEnv(merged, options),\n ...(options.providerId ? { modelRef: options.providerId } : {}),\n };\n}\n","import { EventEmitter } from \"node:events\";\nimport type { Span, TelemetryProvider, Trace } from \"@skaile/workspaces/telemetry\";\nimport type {\n AgentPromptInput,\n Capability,\n CredentialMint,\n CodexCredentialDelivery,\n ContextUsageDetail,\n HarnessContextReport,\n HarnessInfo,\n ErrorRetryReason,\n CodexSubscriptionRefreshInput,\n CodexSubscriptionRefreshResult,\n FlowExecution,\n ModelTokenUsage,\n RenderInvokedEvent,\n TokenUsage,\n} from \"@skaile/workspaces/types\";\nimport type { CodexServerRequestHandlers } from \"./codex-app-server.js\";\nexport type { AgentPromptInput } from \"@skaile/workspaces/types\";\nimport type { MergedAIProviderRegistry } from \"@skaile/workspaces/core/provider-registry\";\nimport type { ModelEntry } from \"./models.js\";\n\n/**\n * Test-only hook injected by the runner so a no-LLM harness (the echo harness's\n * scripted-flow mode) can read flow state and drive flow-adapter mutations\n * without an SDK/MCP round-trip. The runner wires this in `createActiveFlow`\n * from the active FlowAdapter + handle.\n *\n * This is an internal runner↔harness interface — NOT part of any wire\n * protocol or flow contract. Production harnesses ignore it.\n *\n * @see packages/bridge/harnesses/echo — scripted-flow mode\n * @since 3.6.0\n */\nexport interface FlowTestHarnessHook {\n /** Current flow execution snapshot, or `null` when no flow is active. */\n getState(): FlowExecution | null;\n /**\n * Execute a flow-adapter operation (`start_node`, `request_approval`,\n * `complete_node`, `request_input`, `skip_node`, `fail_node`, …). Returns\n * the adapter's JSON string result (or rejects on an illegal transition).\n */\n execute(op: string, args: Record<string, unknown>): Promise<string>;\n /**\n * Node IDs marked as mandatory approval gates. The scripted policy resolves\n * `auto` to `request_approval` for these even in autonomous mode, so hosts\n * can drive a mandatory gate deterministically. Optional — absent hooks\n * behave as if no node is mandatory.\n */\n mandatoryGates?(): string[];\n}\n\n/**\n * Minimal LLM tool descriptor used by the capability dispatch path. Mirrors\n * the runner's `LLMTool` shape so harnesses can consume registry output without\n * importing `@skaile/workspaces/runner` (which would create a circular dep).\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/bridge/concepts#bridge-capability-tool\n */\nexport interface BridgeCapabilityTool {\n /** Capability name; used as the LLM-visible tool name. */\n name: string;\n /** Human/LLM-readable description. */\n description: string;\n /** JSON Schema for the tool's input parameters. */\n parameters: Record<string, unknown>;\n}\n\n/**\n * Render-cap event emission callback used by the bridge when the LLM invokes\n * a capability that carries a `render` spec. The runner provides the actual\n * sink (transport.send / sendEvent); the bridge only emits.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/bridge/concepts#bridge-render-emit\n */\nexport type BridgeRenderEmit = (event: RenderInvokedEvent) => void;\n\n/**\n * Text-event emission callback for render-capability fallbacks. When a\n * `RenderCapability` carries `render.fallback` and the LLM invokes it, the\n * bridge substitutes `{{prop}}` placeholders (top-level keys of `props`,\n * optional dotted-path traversal `{{user.name}}`) and pushes the rendered\n * string through this callback so clients without a render layer still see\n * a textual representation. No-op when `fallback` is absent.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/bridge/concepts#bridge-text-emit\n */\nexport type BridgeTextEmit = (text: string) => void;\n\n/**\n * Bundle of capability dispatch hooks. Registered into the harness via\n * `AgentConfig.capabilities`; the harness routes registered LLM tool calls\n * back into `invoke()` instead of using its native dispatch path.\n *\n * The runner constructs this from a `CapabilityRegistry` instance and threads\n * it through `createAgentSession()`. Harnesses that don't yet implement\n * capability dispatch ignore the field — legacy v1 paths stay intact.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/bridge/concepts#bridge-capability-hooks\n */\nexport interface BridgeCapabilityHooks {\n /** Build the LLM tool descriptor list from the registry. Called per turn so registration changes take effect. */\n composeTools(): BridgeCapabilityTool[];\n /** Resolve a wire-format Capability descriptor by name. Used by the bridge to inspect `fireAndForget` / `render`. */\n resolve(name: string): Capability | null;\n /**\n * Validate input + dispatch through the registry. Logging is wired by the\n * registry.\n *\n * `callId` is the per-dispatch id minted by `dispatchCapability`. It MUST be\n * unique per process (never a harness/provider tool-call id, which only the\n * model backend keeps unique): it is the `render_invoked.callId`, the\n * registry's log correlation id, the handler's `ctx.callId` and — for client\n * capabilities — the `capability_invoked.callId` keying the runner's pending\n * map, so a reused id would let a late `capability_result` for a timed-out\n * call resolve a later call. Callers without one omit it and the registry\n * generates a fresh id.\n */\n invoke(name: string, input: unknown, signal?: AbortSignal, callId?: string): Promise<unknown>;\n /** Subscribe to registry changes; callback carries no credentials or tool payloads. */\n onToolsChanged?(listener: () => void): () => void;\n /** Emit a render-invoked event. The runner forwards via the WebSocket transport. */\n emitRender?: BridgeRenderEmit;\n /** Emit a text fallback for render capabilities with `render.fallback`. */\n emitText?: BridgeTextEmit;\n /** Session id passed through to the runner's per-handler logger. */\n sessionId: string;\n}\n\n/**\n * Static metadata for a registered agent harness (the coding-agent product it drives).\n *\n * Declared once in `@skaile/workspaces/types` — it is protocol surface (the\n * platform reads `surfaces` to decide which AI provider registry entries a\n * harness can serve) and was previously duplicated here field-for-field.\n *\n * Returned by {@link listHarnesses} and exposed on every {@link AgentHarness}\n * instance via `harnessInfo`.\n *\n * @docLink packages/bridge/concepts#harness-info\n */\nexport type { HarnessInfo };\n\n/** Closed, passive managed-MCP observations. Counts saturate at 512. */\nexport interface CodexNativeMcpDiagnostics {\n startupBeforeTurn: \"unknown\" | \"starting\" | \"ready\" | \"failed\" | \"cancelled\";\n startupAtEnd: CodexNativeMcpDiagnostics[\"startupBeforeTurn\"];\n toolsListBeforeTurn: number;\n toolsListTotal: number;\n toolsCallTotal: number;\n nativeMcpToolItemCount: number;\n}\n\n/** Trusted session-local tool transport; fulfilled only after required tools are ready. */\nexport interface CodexToolTransport {\n mcpServers: Record<string, Record<string, unknown>>;\n /** Trusted runner server eligible for human native consent; must name its configured entry. */\n approvalServerName?: string;\n onServerRequest?: CodexServerRequestHandlers;\n /** Revalidate the required live inventory before starting each turn. */\n validate?(): Promise<void>;\n /** Rebuild the native generation at idle when its advertised inventory is stale. */\n needsReload?(): boolean;\n instructions?: string;\n /** Restrict model calls to the active turn and abort outstanding calls when it ends. */\n beginTurn?(signal: AbortSignal): void;\n /** Trusted private server binding and passive request-handler counters; never performs I/O. */\n diagnostics?: {\n serverName: string;\n requestCounts(): { toolsListTotal: number; toolsCallTotal: number };\n };\n dispose(): Promise<void>;\n}\n\n/** Explicit managed instance inputs; none are inferred from ambient developer state. */\nexport interface CodexManagedRuntimeOptions {\n executable: string;\n /** Optional launcher arguments, for the caller-owned executable wrapper. */\n executableArgs?: string[];\n /** Private local filesystem state; the host must fence old native processes before reuse. */\n privateDirectory: string;\n /** Host-owned private mount containing every parent/child instance; denied to native tools. */\n privateRoot: string;\n environment: Record<string, string>;\n credential: CodexCredentialDelivery;\n instructionFiles?: string[];\n skillsDirectory?: string;\n prepareTools(signal: AbortSignal): Promise<CodexToolTransport>;\n /**\n * Passive snapshots before/after turns, plus final local counts after successful transport closure.\n * No final snapshot is emitted on uncertain cleanup or a failed final counter read. Earlier snapshots\n * are not proof of completed cleanup. Sink failures never affect native execution or cleanup.\n */\n onNativeMcpDiagnostics?(value: Readonly<CodexNativeMcpDiagnostics>): void | Promise<void>;\n refreshCredential?: (\n input: CodexSubscriptionRefreshInput,\n signal: AbortSignal,\n ) => Promise<CodexSubscriptionRefreshResult>;\n requestTimeoutMs?: number;\n turnTimeoutMs?: number;\n /** Maximum native turns admitted by this instance; reserved for disposable one-turn children. */\n nativeTurnBudget?: 1;\n /** Human interaction deadline, bounded separately from ordinary RPCs. */\n interactionTimeoutMs?: number;\n}\n\n/**\n * Codex-specific tuning options passed through `HarnessOptions.codex`.\n *\n * @remarks These are forwarded verbatim to the Codex harness and have no effect on other harnesses.\n * @docLink packages/bridge/concepts#codex-harness-options\n */\nexport interface CodexHarnessOptions {\n /** Omission retains the standalone SDK path; managed mode always requires App Server inputs. */\n authSource?: \"local\" | \"managed\";\n managedRuntime?: CodexManagedRuntimeOptions;\n /** Controls whether Codex may auto-apply edits without user approval. */\n approvalPolicy?: \"never\" | \"on-request\" | \"on-failure\" | \"untrusted\";\n /** Filesystem sandbox level for the Codex process. */\n sandboxMode?: \"read-only\" | \"workspace-write\" | \"danger-full-access\";\n /** Reasoning budget passed to the model. */\n reasoningEffort?: \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\n /** When `true`, the Codex sandbox is allowed to make outbound network requests. */\n networkAccessEnabled?: boolean;\n /** Extra directories made accessible to the Codex sandbox in addition to `cwd`. */\n additionalDirectories?: string[];\n}\n\n/**\n * omp-specific options passed through `HarnessOptions.omp`.\n *\n * They govern the session-private agent directory the omp adapter renders the\n * provider registry into (`omp-models-yml.ts`); every one of them has a\n * working default, so a caller that sets none still gets a correct session.\n *\n * @remarks Forwarded verbatim to the omp harness; no effect on other harnesses.\n * @see PROVIDER-CONFIG-PLAN.md §2.3\n */\nexport interface OmpHarnessOptions {\n /**\n * Explicit session-private agent directory for `PI_CODING_AGENT_DIR`.\n * Defaults to `<cwd>/.omp/agent-home/<sessionId>`.\n */\n agentHome?: string;\n /**\n * Inherit the developer's own omp state (auth store, blobs, extensions) by\n * symlinking {@link OmpHarnessOptions.userAgentDir} into the session\n * directory. Defaults to *on when that directory exists*, which is exactly\n * the standalone case: a platform container has none, so its session starts\n * empty. Set `false` to force an empty session directory regardless.\n */\n seedUserAgentDir?: boolean;\n /** Seed source. Defaults to `~/.omp/agent`. */\n userAgentDir?: string;\n}\n\n/**\n * Harness-specific configuration bag.\n *\n * Fields are keyed by harness ID so that callers can pass harness-specific options\n * through the common {@link AgentConfig} without breaking other harnesses.\n *\n * @docLink packages/bridge/concepts#harness-options\n */\nexport interface HarnessOptions {\n /** Codex-specific options. Ignored by all other harnesses. */\n codex?: CodexHarnessOptions;\n /** omp-specific options. Ignored by all other harnesses. */\n omp?: OmpHarnessOptions;\n}\n\n/**\n * What the harness tells the host about a turn blocked by an upstream usage\n * limit. Everything but `configId` is best-effort: the SDK reports the limit\n * window only on its structured telemetry, not on the error result text.\n *\n * @see AgentConfig.onLimitBlocked\n * @category Configuration\n * @since 3.9.0\n */\nexport interface LimitBlockedContext {\n /** The AI provider config the blocked turn ran on (`\"\"` when unmediated). */\n configId: string;\n /** Upstream limit window (`five_hour`, `seven_day`, …) when reported. */\n limitType?: string;\n /** Epoch seconds at which the limit window resets, when reported. */\n resetsAt?: number;\n /** Fraction of the limit window consumed (0–1) when reported. */\n utilization?: number;\n}\n\n/**\n * The host's verdict on a limit-blocked turn. `switched: true` is a promise\n * that a different seat's credential is already on disk — the harness acts on it\n * by respawning the CLI and replaying the prompt, so returning it without\n * having rewritten the credential file would just replay onto the dead seat.\n *\n * @see AgentConfig.onLimitBlocked\n * @category Configuration\n * @since 3.9.0\n */\nexport interface LimitFailoverResult {\n /** Whether the session was repointed at a different AI provider config. */\n switched: boolean;\n /** The config id now in effect. Informational — used for logs. */\n configId?: string;\n /**\n * Why no switch happened: `same-config`, `standalone`,\n * `platform-omitted-config-id` (the mint succeeded but named no seat, so a\n * re-resolution is indistinguishable from none), or a `CredentialMint`\n * failure code. Diagnostic only — the harness branches on `switched`.\n */\n reason?: string;\n}\n\n/**\n * One observed AI-provider rejection, reported to the host for per-seat health\n * attribution. Fire-and-forget — see {@link AgentConfig.onProviderResponse}.\n *\n * @category Configuration\n * @since 3.9.0\n */\nexport interface ProviderResponseObservation {\n /** 401 — the credential was rejected. 429 — an upstream rate/session limit. */\n status: 401 | 429;\n /** The AI provider config the observation is attributed to, when known. */\n configId?: string;\n /** Upstream limit window (`five_hour`, `seven_day`, …) when reported. */\n limitType?: string;\n /** Fraction of the limit window consumed (0–1) when reported. */\n utilization?: number;\n /** Epoch seconds at which the limit window resets, when reported. */\n resetsAt?: number;\n /**\n * What the 429 was, when the harness recognised something narrower than a\n * usage limit. `long-context-entitlement`: the account may not use a long\n * (1M) context window; the seat is not out of quota. Diagnostic only — the\n * harness still treats the rejection as before.\n */\n cause?: ProviderResponseCause;\n}\n\n/**\n * Why a 429 {@link ProviderResponseObservation} was rejected, when the harness\n * recognised it. Consumers must tolerate values they do not know.\n *\n * @category Configuration\n * @since 4.11.0\n */\nexport type ProviderResponseCause = \"long-context-entitlement\";\n\n/**\n * One upstream quota-window reading, reported to the host for every SDK\n * `rate_limit_event` — allowed, warning or rejected alike. Fire-and-forget —\n * see {@link AgentConfig.onProviderQuota}.\n *\n * @category Configuration\n * @since 4.1.0\n */\nexport interface ProviderQuotaObservation {\n /** The AI provider config the reading is attributed to, when known. */\n configId?: string;\n /** Upstream window, verbatim (`five_hour`, `seven_day`, or a future value). */\n window: string;\n /** Upstream status, verbatim (`allowed`, `allowed_warning`, `rejected`, …). */\n status: string;\n /** Fraction of the window consumed (0–1); the SDK reports it on warnings and rejections only. */\n utilization?: number;\n /** Epoch seconds at which the window resets, when reported. */\n resetsAt?: number;\n}\n\n/**\n * Reasoning effort levels a host may set. The platform sends all five, the\n * Agent SDK accepts all five, omp has a same-named thinking level for each, and\n * managed codex passes the value to its app server.\n *\n * @since 4.22.0\n */\nexport const AGENT_EFFORT_LEVELS = [\"low\", \"medium\", \"high\", \"xhigh\", \"max\"] as const;\nexport type AgentEffort = (typeof AGENT_EFFORT_LEVELS)[number];\n\n/**\n * Narrow a free-form effort (the wire `agentConfig.effort`, a `skaile.yaml`\n * default) to an {@link AgentEffort}; anything else gives `undefined`, so an\n * unknown value never reaches a harness.\n */\nexport function toAgentEffort(value: unknown): AgentEffort | undefined {\n return isAgentEffort(value) ? value : undefined;\n}\n\nfunction isAgentEffort(value: unknown): value is AgentEffort {\n return (AGENT_EFFORT_LEVELS as readonly unknown[]).includes(value);\n}\n\n/**\n * Configuration passed to a harness when it is created via {@link createHarness}.\n *\n * All fields are shared across harnesses; harness-specific behaviour is documented\n * per field. Fields that are silently ignored by a harness are marked accordingly.\n *\n * @docLink packages/bridge/concepts#agent-config\n */\nexport interface AgentConfig {\n /** Absolute path to the working directory the agent operates in. */\n cwd: string;\n /**\n * LLM model identifier (e.g. `\"claude-sonnet-4-5\"`, `\"gpt-4o\"`).\n *\n * The unscoped fallback: {@link AgentConfig.modelRef} is what a session\n * normally carries, and this is what a harness falls back to when no\n * registry entry resolved one.\n */\n model?: string;\n /**\n * The AI provider registry for this session — every endpoint the harness may\n * address, already merged across the catalog / user / workspace / runtime /\n * control-plane layers and in registry order.\n *\n * This is the *only* provider surface a harness reads. Entries reference\n * their credential (`credential.ref`) and never carry the secret itself;\n * the value reaches the child under `SKAILE_AIP_<ID>_KEY`\n * (`provider-materialize/credential-env.ts`), which the session boundary\n * puts in {@link AgentConfig.env}.\n *\n * Absent (or empty) means no endpoint was configured at all — the harness\n * then falls back to whatever native auth it can discover on its own (a\n * `claude` OAuth login, `codex login`, an ambient vendor key).\n */\n registry?: MergedAIProviderRegistry;\n /**\n * Model selector resolved against {@link AgentConfig.registry}:\n * `\"<providerId>/<modelId>\"`, a bare `\"<modelId>\"` (first registry entry\n * that maps it wins), or `\"@role\"`. Absent when no model was configured at\n * all — the harness then applies its own default, exactly as it does for an\n * absent `model`.\n */\n modelRef?: string;\n /**\n * The `skaile.yaml` `roles` table — role name → model selector\n * (`{default: \"anthropic/opus\", smol: \"groq/llama-3.1-8b\"}`, §9.8). It is\n * what `\"@role\"` in {@link AgentConfig.modelRef} expands through, and what\n * a harness that supports per-role models materializes natively: omp renders\n * it as `modelRoles` in its session-private `config.yml`, so `@smol` inside\n * the session reaches a different provider than `@default`.\n *\n * Resolution is lenient: a role naming an entry this registry does not have\n * is a warning, never a failure.\n */\n roles?: Record<string, string>;\n /**\n * Additional environment variables merged into the child process\n * environment. The session boundary delivers resolved registry credentials\n * here as `SKAILE_AIP_<ID>_KEY` entries; anything else the caller sets is\n * merged over the harness's own allowlist, never instead of it.\n */\n env?: Record<string, string>;\n /** Inline system prompt — written to .omp/system.md and passed via --append-system-prompt (omp harness) */\n systemPrompt?: string;\n /** Path to project .omp/ directory (PI_CODING_AGENT_DIR for omp harness) */\n agentDir?: string;\n /** SSH key path — injected as GIT_SSH_COMMAND */\n sshKeyPath?: string;\n /** Pre-assign a UUID as the session ID for a new session (claude-sdk: passed as sessionId option) */\n sessionId?: string;\n /** Resume this specific past session by UUID instead of starting fresh (claude-sdk: passed as resume option) */\n resumeSessionId?: string;\n /** Maximum agentic turns per query (claude-sdk: passed as maxTurns option) */\n maxTurns?: number;\n /**\n * Whether the agent may act on its own (`auto`, the default) or has to be approved per tool\n * call (`interactive`); the `agents.<id>.permissions.permission_mode` of the instance.\n *\n * - claude-sdk: `auto` runs under the SDK's `bypassPermissions`; `interactive` runs under\n * `default`, and a call the SDK does not auto-allow (a shell command, a file edit, an MCP\n * tool) pauses the turn on a `question` event with an `approval` card (`Approve once` /\n * `Deny`) answered through `answerQuestion`. With {@link AgentConfig.unattended} the call is\n * refused instead.\n * - codex (standalone SDK path): `interactive` sets `approvalPolicy: \"on-request\"` instead of\n * `never`, unless `harnessOptions.codex.approvalPolicy` is set. The standalone SDK path has no\n * way to show an approval card, so codex refuses a command that needs to leave its sandbox\n * instead of asking; nothing is ever approved. A managed codex session keeps the host's own\n * policy.\n * - omp, echo and the subprocess CLI harnesses (gemini, qwen, opencode, goose, continue): ignored.\n */\n permissionMode?: \"auto\" | \"interactive\";\n /**\n * The session has no one to answer a question (a nested `agent.run` role session, a\n * single-shot `skaile run` without a terminal). With `permissionMode: \"interactive\"` a tool\n * call that needs approval is then refused (claude-sdk) instead of waiting for a reply.\n */\n unattended?: boolean;\n /** Agent name — selects a deployed sub-agent definition as the main agent identity.\n * claude-sdk: passed as `agent` option to query() → reads .claude/agents/<name>.md natively.\n * omp: ignored (omp uses agentDir/PI_CODING_AGENT_DIR instead). */\n agentName?: string;\n /** In-process SDK MCP servers for custom tool injection (Claude SDK only, ignored by other harnesses) */\n mcpServers?: Record<string, unknown>;\n /** Tool restrictions from agent.yaml — applied to the main agent session */\n tools?: {\n /** Tool names that the agent is allowed to invoke. An empty array means no restriction. */\n allowed?: string[];\n /** Tool names that the agent is explicitly forbidden from invoking. */\n denied?: string[];\n };\n /** Thinking mode for Claude models: adaptive (Claude decides), enabled (always think), disabled (no thinking). */\n thinking?: \"adaptive\" | \"enabled\" | \"disabled\";\n /** Reasoning effort level; each harness maps it to its own scale (see {@link AgentEffort}). */\n effort?: AgentEffort;\n /** Harness-specific configuration bag. */\n harnessOptions?: HarnessOptions;\n /**\n * Protocol v2 capability dispatch hooks. When present, the harness uses the\n * registry as the source of LLM tool definitions and routes invocations\n * through `capabilities.invoke()`. Absent → legacy v1 path (existing\n * mcpServers / native dispatch).\n *\n * @since 2.0.0\n */\n capabilities?: BridgeCapabilityHooks;\n /**\n * The platform's `AIProviderConfig.id` for the AI credential currently\n * provisioned into this harness. The runner reads this off `AgentConfig`\n * during 401 mediation and passes it as `configId` in\n * `request_access_token { kind: 'ai-credentials' }`. The harness itself\n * does not consume this field — only the runner uses it.\n *\n * Set by the platform agent-gateway in `ConfigureCommandV2` for mediated\n * sessions. Standalone runners (CLI / forge / Claude plugin) leave it\n * undefined; the runner falls back to surfacing the auth error to the\n * user without mediating.\n *\n * Spec: `_devlog/specs/2026-05-07-unified-credential-mediation.md`\n * § \"Wire `aiProviderConfigId` end-to-end\".\n *\n * @since 3.3.0\n */\n aiProviderConfigId?: string;\n /**\n * Optional callback invoked by the harness when the underlying agent\n * surfaces an `authentication_error`. In Protocol v3 the runner mediates\n * the refresh via the `host.refresh_credential` capability and returns a\n * typed {@link CredentialMint}. The harness inspects the discriminator:\n *\n * - `mint.ok === true`: a fresh credential is now provisioned. The\n * harness re-attempts the in-flight prompt once.\n * - `mint.ok === false`: refresh failed (`code` carries a stable reason\n * such as `revoked`, `not-configured`, `provider-error`,\n * `backend-error`). The harness surfaces the original `AuthError` to\n * the caller.\n *\n * `args.configId` carries the platform `AIProviderConfig.id` the harness\n * was provisioned with (mirrors {@link AgentConfig.aiProviderConfigId}).\n * The runner uses it to scope the refresh to the correct AI credential.\n *\n * When omitted, the harness throws `AuthError` immediately as before\n * (standalone CLI / forge mode — there is no platform mediator to ask).\n *\n * Centralising auth-retry inside the harness means every consumer of\n * `harness.prompt(...)` (serve handler, compaction orchestrator, flow\n * orchestrator, …) gets self-healing for free — there is no per-call-site\n * wrapping.\n *\n * Spec: `_devlog/specs/2026-05-10-deterministic-session-bootstrap.md`\n * § \"host.refresh_credential capability\".\n *\n * @since 3.4.0\n */\n onAuthError?: (args: { configId: string }) => Promise<CredentialMint>;\n /**\n * Optional callback invoked by the harness when a turn is blocked by an\n * upstream **usage limit** rather than a bad credential — the subscription\n * five-hour / seven-day ceiling, or any `rate_limit` the classifier\n * recognises. Called at most once per logical turn, and only after the\n * blocked attempt has already failed, so it never runs mid-turn.\n *\n * The runner implements it by asking the platform to re-resolve the seat:\n *\n * - `switched: true` — the session was repointed at a DIFFERENT AI\n * provider config and `.credentials.json` was rewritten. The harness\n * drops its query (forcing a fresh CLI spawn, which is what clears a\n * resident CLI's cached \"blocked until <reset>\" state — a hot file\n * rewrite alone does not) and replays the prompt once.\n * - `switched: false` — no alternative seat was available. The harness\n * surfaces the original limit error unchanged.\n *\n * Left unset by standalone runners (CLI / forge / Claude plugin): there is\n * no platform mediator to re-resolve a seat, so the limit error surfaces\n * exactly as it does today.\n *\n * Companion to {@link onAuthError}: that one covers 401s, this one covers\n * the rejection path, which previously reached no failover at all\n * (skaile-ai/workspaces#567, skaile-ai/platform#2976).\n *\n * @since 3.9.0\n */\n onLimitBlocked?: (ctx: LimitBlockedContext) => Promise<LimitFailoverResult>;\n /**\n * Optional fire-and-forget hook invoked when the harness observes a 401 or a\n * 429 / subscription-limit rejection from the AI provider. The runner\n * forwards it to the platform as a `provider_response_seen` event so the\n * owning `AIProviderConfig`'s live health counters can be bumped — the cron\n * health probe only samples auth, never capacity\n * (skaile-ai/workspaces#368, skaile-ai/platform#3539).\n *\n * Never awaited and never retried; the harness swallows a throwing\n * implementation so telemetry can never fail a turn.\n *\n * @since 3.9.0\n */\n onProviderResponse?: (observation: ProviderResponseObservation) => void;\n /**\n * Optional fire-and-forget hook invoked for every upstream quota-window\n * reading (claude-sdk `rate_limit_event`), not only rejections. The runner\n * forwards it as `provider_quota_observed`, which is the only quota signal\n * the platform has for a seat whose token cannot read the OAuth usage\n * endpoint (a `claude setup-token` seat).\n *\n * Never awaited and never retried; the harness swallows a throwing\n * implementation so telemetry can never fail a turn. Unlike\n * {@link onProviderResponse} it fires on every event, so dedupe at the host.\n *\n * @since 4.1.0\n */\n onProviderQuota?: (observation: ProviderQuotaObservation) => void;\n /**\n * Test-only flow harness hook. When present, the echo harness's scripted-flow\n * mode uses it to advance flow nodes deterministically (no LLM). The runner\n * injects it in `createActiveFlow`; every other harness ignores it.\n *\n * @see FlowTestHarnessHook\n * @since 3.6.0\n */\n flowTestHarness?: FlowTestHarnessHook;\n}\n\n/**\n * A single message in an agent conversation.\n *\n * Emitted as part of {@link AgentEvent} variants (`message_start`, `message_update`, `message_end`).\n *\n * @docLink packages/bridge/concepts#agent-message\n */\nexport interface AgentMessage {\n /** Originator of the message. */\n role: \"user\" | \"assistant\" | \"tool\";\n /** Message body — either a plain string or a list of typed content blocks. */\n content: string | ContentBlock[];\n /** Tool invocations made by the assistant in this message. */\n toolCalls?: ToolCall[];\n /** For `role === \"tool\"`: the name of the tool whose result this message carries. */\n toolName?: string;\n /** For `role === \"tool\"`: `true` when the tool returned an error. */\n isError?: boolean;\n /** Optional structured payload for tool results. */\n data?: unknown;\n /**\n * Set when a subagent produced this message: the id of the tool use that\n * runs the subagent. Absent on main-thread messages.\n */\n parentToolUseId?: string;\n}\n\n/**\n * A typed block within an {@link AgentMessage}'s content array.\n *\n * Mirrors the Anthropic content block schema but is harness-agnostic.\n *\n * @docLink packages/bridge/concepts#content-block\n */\nexport interface ContentBlock {\n /** Block discriminant. */\n type: \"text\" | \"tool_use\" | \"tool_result\" | \"thinking\";\n /** Present for `text` and `thinking` blocks. */\n text?: string;\n /** Tool use / tool result correlation ID. */\n id?: string;\n /** Tool name (present on `tool_use` blocks). */\n name?: string;\n /** Tool input arguments (present on `tool_use` blocks). */\n input?: any;\n /** Serialised tool result content (present on `tool_result` blocks). */\n content?: string;\n}\n\n/**\n * A single tool invocation made by the agent within a message.\n *\n * @docLink packages/bridge/concepts#tool-call\n */\nexport interface ToolCall {\n /** Correlation ID used to match the call with its result. */\n id: string;\n /** Name of the tool being invoked. */\n name: string;\n /** Arguments passed to the tool. */\n input: any;\n}\n\n/**\n * Error classification for agent failures.\n *\n * Used to determine whether a failure is retryable and to surface actionable\n * hints to the user. See `bridge/CLAUDE.md` for the full category-to-behaviour matrix.\n *\n * @see AgentError\n * @docLink packages/bridge/concepts#error-category\n */\nexport type ErrorCategory =\n | \"auth\"\n | \"account\"\n | \"rate_limit\"\n | \"model\"\n | \"network\"\n | \"config\"\n | \"process\"\n | \"validation\"\n | \"unknown\";\n\n/**\n * Structured error payload emitted inside the `error` {@link AgentEvent}.\n *\n * Consumers should inspect `retryable` before deciding to surface a retry button,\n * and `hint` to provide an actionable message to the user.\n *\n * @docLink packages/bridge/concepts#agent-error\n */\nexport interface AgentError {\n /** Human-readable error description. */\n message: string;\n /** Coarse failure classification used for retry logic and telemetry. */\n category: ErrorCategory;\n /** HTTP status code if the error originated from an API response. */\n statusCode?: number;\n /** `true` when the caller may safely retry the same operation. */\n retryable: boolean;\n /** Short actionable advice suitable for display in the UI. */\n hint?: string;\n}\n\n/**\n * Metadata for a slash command exposed by the active agent runtime.\n *\n * @docLink packages/bridge/concepts#slash-command-info\n */\nexport interface SlashCommandInfo {\n /** Command name without the leading slash (e.g. `\"compact\"`). */\n name: string;\n /** One-line description shown in command pickers. */\n description: string;\n /** Placeholder text describing what argument the command expects. */\n argumentHint?: string;\n}\n\n/**\n * Discriminated union of all events emitted by a harness on the `'agent-event'` channel.\n *\n * @remarks\n * Consumers listen via `harness.on('agent-event', (event: AgentEvent) => ...)`.\n * The `[k: string]: any` index signature on most variants allows harnesses to attach\n * harness-specific fields (e.g. `_textDelta`) without breaking the union.\n *\n * @docLink packages/bridge/concepts#agent-event\n */\nexport type AgentEvent =\n | { type: \"message_start\"; message: AgentMessage; [k: string]: any }\n | { type: \"message_update\"; message: AgentMessage; [k: string]: any }\n | { type: \"message_end\"; message: AgentMessage; [k: string]: any }\n /**\n * Takes back `text`, the unfinished tail of streamed `_textDelta`s, before the\n * harness replays an abandoned attempt. Always a suffix of what was streamed\n * since the last completed assistant message; see `TextRetractEvent` in the types package.\n */\n | { type: \"message_retract\"; text: string; [k: string]: any }\n | { type: \"turn_end\"; toolResults?: AgentMessage[]; [k: string]: any }\n | { type: \"agent_end\"; [k: string]: any }\n /** A background task started in the running turn; see `BackgroundTaskStartedEvent`. */\n | { type: \"background_task_started\"; taskId: string; [k: string]: any }\n /** A turn the harness was not prompted for began; see `SelfTurnStartedEvent`. */\n | { type: \"self_turn_started\"; taskIds: string[]; [k: string]: any }\n | {\n type: \"result\";\n subtype: string;\n summary?: string;\n costUsd?: number;\n /** Per-turn token usage when the harness tracks it. Added in 3.1.0. */\n tokens?: TokenUsage;\n /** Per-turn usage keyed by model, subagent calls included. Added in 3.11.0. */\n modelUsage?: Record<string, ModelTokenUsage>;\n /** Prompt size of the turn's last main-thread API call. Added in 3.11.0. */\n contextTokens?: number;\n /** Context window of the main model, in tokens. Added in 3.11.0. */\n contextWindow?: number;\n errors?: string[];\n [k: string]: any;\n }\n | {\n type: \"error\";\n error: string;\n detail?: AgentError;\n fatal?: boolean;\n /** Set (with `fatal: false`) when the harness replays the prompt in place; see `ErrorEvent.retrying`. */\n retrying?: boolean;\n retryReason?: ErrorRetryReason;\n /** Usage of a failed provider turn, when reported. */\n tokens?: TokenUsage;\n /** Failed-turn usage keyed by the actual model. */\n modelUsage?: Record<string, ModelTokenUsage>;\n contextTokens?: number;\n contextWindow?: number;\n [k: string]: any;\n }\n | {\n type: \"tool_call\";\n name?: string;\n tool?: { name: string };\n /** Set when a subagent made the call. */\n parentToolUseId?: string;\n [k: string]: any;\n }\n | { type: \"tool_execution_end\"; toolName?: string; parentToolUseId?: string; [k: string]: any }\n | { type: \"commands_available\"; commands: SlashCommandInfo[] }\n | { type: \"session_info\"; harnessSessionId: string; sessionFile?: string }\n | { type: \"ui_render\"; [k: string]: any }\n | { type: \"ui_render_update\"; [k: string]: any }\n | { type: \"ui_clear\"; [k: string]: any }\n // Phase 3 (resume cascade) — harness-emitted resume outcome.\n | {\n type: \"resume_failed\";\n resumeSessionId: string;\n reason:\n | \"signature_mismatch\"\n | \"model_mismatch\"\n | \"jsonl_lost\"\n | \"jsonl_poisoned\"\n | \"native_state_unavailable\";\n [k: string]: any;\n };\n\n/** The settings a live reconfigure may change. */\nexport type ReconfigurePatch = Partial<Pick<AgentConfig, \"model\" | \"thinking\" | \"effort\">>;\n\n/**\n * What a harness now holds for the fields of an accepted reconfigure. `modelRef`\n * is the registry selector the model was scoped to; it is absent when the\n * session has none. A host remembers exactly this, never the raw patch.\n */\nexport interface ReconfigureApplied {\n model?: string;\n modelRef?: string;\n thinking?: AgentConfig[\"thinking\"];\n effort?: AgentConfig[\"effort\"];\n}\n\n/**\n * Result of `AgentHarness.reconfigure()`. `ok: true` means effective from the\n * next turn (live switch, query recycle or respawn); a harness that cannot\n * promise that answers `ok: false` instead.\n *\n * - `not_supported`: the harness cannot change settings live.\n * - `model_not_on_provider`: the session's AI provider entry does not list the\n * model (`providerId` names the entry).\n * - `rejected`: the running process refused the change; the harness config is\n * unchanged.\n *\n * @category Bridge\n */\nexport type ReconfigureOutcome =\n | { ok: true; applied: ReconfigureApplied }\n | {\n ok: false;\n code: \"not_supported\" | \"model_not_on_provider\" | \"rejected\";\n message: string;\n providerId?: string;\n };\n\n/**\n * A reconfigure the harness answered `ok` (it landed mid-turn) and then refused\n * at the next turn boundary. The harness already rolled its config back;\n * `requested` is what was asked, `restored` what it holds again. Emitted as the\n * harness event `'reconfigure-rollback'`.\n */\nexport interface ReconfigureRollback {\n message: string;\n requested: ReconfigureApplied;\n restored: ReconfigureApplied;\n}\n\n/** Rejection message of a harness asked to run a turn under a tool allowlist it cannot enforce. */\nexport const TOOL_ALLOWLIST_UNSUPPORTED = \"This agent harness cannot enforce a tool allowlist\";\n\n/**\n * Abstract base class for agent harnesses.\n *\n * Wraps an LLM coding agent behind a single `prompt()` interface.\n * All harnesses emit `'agent-event'` with {@link AgentEvent} payloads.\n *\n * @remarks\n * Subclasses must implement `start`, `prompt`, `abort`, `kill`, and `isRunning`.\n * Implementations should never emit an event name other than `'agent-event'` as\n * the public streaming channel — internal events (`'ready'`, `'exit'`, etc.) are\n * harness-private. The one other public event is `'reconfigure-rollback'` (a\n * {@link ReconfigureRollback}): a live reconfigure the harness had accepted and\n * then refused at the turn boundary, already rolled back in the harness.\n *\n * @example\n * ```ts\n * const harness = createHarness('omp', config);\n * harness.on('agent-event', (event) => console.log(event.type));\n * await harness.start();\n * await harness.prompt('Refactor the auth module');\n * harness.kill();\n * ```\n *\n * @docLink packages/bridge/concepts#agent-harness\n */\nexport abstract class AgentHarness extends EventEmitter {\n /** Static metadata describing this harness's capabilities. */\n abstract readonly harnessInfo: HarnessInfo;\n\n /**\n * Initialises the harness — spawns the child process (omp) or loads\n * the SDK module (claude-sdk). Resolves when the harness is ready to accept\n * prompts. Idempotent: calling `start()` on an already-running harness is a no-op.\n *\n * @throws {Error} When the harness binary is missing or the SDK cannot be loaded.\n */\n abstract start(): Promise<void>;\n\n /**\n * Sends a user message to the agent and resolves when the agent's turn completes\n * (i.e. after the `agent_end` event has been emitted).\n *\n * @param message - Plain-text user prompt to send to the agent.\n * @throws {Error} When the harness is not running or the underlying coding agent reports a fatal error.\n */\n abstract prompt(message: string): Promise<void>;\n\n /**\n * Preserve text-only callers; harnesses must explicitly support attachments.\n * A `toolAllowlist` is refused here: only a harness that overrides\n * {@link enforcesToolAllowlist} may run a restricted turn.\n */\n promptInput(input: AgentPromptInput): Promise<void> {\n if (input.toolAllowlist !== undefined)\n return Promise.reject(new Error(TOOL_ALLOWLIST_UNSUPPORTED));\n if (input.attachments?.length) return Promise.reject(new Error(\"Structured input unsupported\"));\n return this.prompt(input.text);\n }\n\n /**\n * Whether {@link promptInput} enforces `AgentPromptInput.toolAllowlist` for\n * the whole turn, subagents included. A harness that answers `false` must\n * reject an input carrying one; the runner refuses such a prompt before it\n * reaches the harness.\n */\n get enforcesToolAllowlist(): boolean {\n return false;\n }\n\n /**\n * The names in `allowlist` this harness does not recognize as a tool it could\n * offer. The runner refuses a prompt whose allowlist names any, rather than\n * guess. A harness that does not enforce allowlists recognizes none.\n */\n unknownAllowlistedTools(allowlist: readonly string[]): string[] {\n return [...allowlist];\n }\n\n /** Managed replies never fall back to a new prompt after a request has settled. */\n get acceptsReplyAsPrompt(): boolean {\n return true;\n }\n\n /**\n * Sends an in-band abort signal to the agent, requesting it to stop the current\n * turn without terminating the process. The harness remains usable after `abort()`.\n *\n * @remarks Only meaningful when `harnessInfo.supportsInBandAbort` is `true`.\n * For other harnesses, prefer `kill()` followed by creating a new harness instance.\n */\n abstract abort(): Promise<void>;\n\n /**\n * Terminates the agent harness immediately (SIGTERM for subprocess harnesses,\n * `close()` for in-process harnesses). The harness instance must not be reused\n * after `kill()`.\n */\n abstract kill(): void;\n\n /** Stop the harness and await owned process/state cleanup when the harness supports it. */\n async dispose(): Promise<void> {\n this.kill();\n }\n\n /** `true` when the harness is alive and able to accept new prompts. */\n abstract get isRunning(): boolean;\n\n /** Optional provider-native session/thread identifier for resume support. */\n get runtimeSessionId(): string | undefined {\n return undefined;\n }\n\n /** Slash commands discovered from the agent runtime. Override in harnesses that support introspection. */\n getSlashCommands(): SlashCommandInfo[] {\n return [];\n }\n\n // ── Interactive questions (AskUserQuestion) ──────────────────────────────\n\n /**\n * `true` while the harness is paused on an interactive question and waiting\n * for the user's answer rather than a new prompt. The runner routes a\n * `reply` command to {@link answerQuestion} instead of {@link prompt} when\n * this returns `true`. Harnesses without interactive-question support return\n * `false` (the default), so a `reply` falls back to `prompt`.\n */\n hasPendingQuestion(): boolean {\n return false;\n }\n\n /**\n * Deliver the user's answer to the question the harness is currently paused\n * on. This resumes the in-flight turn — it does NOT start a new one. When a\n * single tool call asks several questions, the harness resolves the underlying\n * call only once every sub-question has an answer.\n *\n * @param answer - The user's reply text (an option label, free text, or for\n * multi-select a comma-joined list).\n * @param question - The sub-question this answers, verbatim from the\n * `question` event that asked it. Supply it whenever the host lets the user\n * answer out of order — without it the answer fills the next unanswered\n * slot in order, which silently mismatches a non-sequential reply.\n * @returns `true` when the answer was consumed by a pending question; `false`\n * when no question was pending (caller should treat the reply as a prompt).\n */\n answerQuestion(answer: string, question?: string, requestId?: string): boolean {\n void requestId;\n void answer;\n void question;\n return false;\n }\n\n /**\n * Apply this harness's rule for a new prompt that meets a pending question,\n * ahead of the prompt itself. The runner queues a prompt behind the turn in\n * flight, so a turn paused on a question would otherwise hold that prompt\n * until the user answered. Harnesses whose `prompt()` cancels the question\n * (claude-sdk, omp) do the same here; the default keeps the question.\n */\n supersedePendingQuestion(): void {\n // No-op: a harness without this rule keeps the question pending.\n }\n\n // ── Live reconfiguration ────────────────────────────────────────────────\n\n /**\n * Live-update harness configuration. `ok: true` means effective from the next\n * turn: the next turn runs on the new settings, by live switch, query recycle\n * or respawn, and the host needs no restart. A turn in progress finishes on\n * the old settings. Only model/thinking/effort are reconfigurable mid-session.\n *\n * Harnesses that can honour that promise build a `ReconfigureLedger` and\n * delegate to it; it owns the model scope rule, ordering, drift and rollback.\n * The base implementation answers `not_supported`.\n */\n reconfigure(patch: ReconfigurePatch): Promise<ReconfigureOutcome> {\n const fields = Object.keys(patch).join(\", \");\n return Promise.resolve({\n ok: false,\n code: \"not_supported\",\n message: `The ${this.harnessInfo.id} harness cannot change ${fields} live; the change applies when the session next starts.`,\n });\n }\n\n /**\n * Returns the model identifier currently configured on this harness.\n * Subclasses that store config locally should override this.\n */\n getModel(): string | undefined {\n return undefined;\n }\n\n // ── Compaction support ──────────────────────────────────────────────────\n\n /**\n * `Date.now()` of the harness's most recent sign of life, counting messages\n * that emit no `agent-event` (thinking deltas, rate-limit telemetry, API\n * retries). A stall check reads it alongside the events it sees. `null` when\n * the harness does not track it.\n */\n lastActivityAt(): number | null {\n return null;\n }\n\n /**\n * Returns the token usage from the most recent completed turn.\n * Returns `null` if usage data is unavailable (e.g. harness doesn't track it).\n *\n * Widened in 3.1.0 to return the full `TokenUsage` shape (input / output /\n * cache-read / cache-creation / reasoning). All fields are optional so\n * harnesses can populate just what their provider reports. Existing callers\n * that read only `inputTokens` / `outputTokens` keep working — those fields\n * are still present and carry the same semantics as before.\n */\n getTokenUsage(): TokenUsage | null {\n return null;\n }\n\n /**\n * Prompt tokens occupying the context window as of the most recent API\n * request — i.e. how full the context actually is right now.\n *\n * Deliberately NOT the same number as {@link getTokenUsage}, whose usage is\n * cumulative over every API call in the turn and therefore overstates the\n * context by 10-40x on any multi-tool turn. Callers measuring context fill\n * (compaction thresholds) must prefer this; callers billing a turn\n * (usage ledgers, the `finished` event) must keep using `getTokenUsage()`.\n *\n * Returns `null` both when the harness cannot report a per-call figure at all\n * and when it can but has no reading yet. Falling back to `getTokenUsage()`\n * is safe in either case only because a harness clears the two in lockstep: no\n * reading means no API call landed, so there is no cumulative usage to\n * overstate. A harness implementing this must preserve that invariant.\n */\n getContextTokens(): number | null {\n return null;\n }\n\n /**\n * Returns the model's context window size in tokens.\n * Returns `null` if unknown.\n */\n getContextWindow(): number | null {\n return null;\n }\n\n /**\n * What the harness can measure natively about its context window, in the\n * neutral {@link HarnessContextReport} shape, or `null` when it measures\n * nothing beyond {@link getContextTokens} / {@link getContextWindow}.\n *\n * `detail: \"full\"` (the default) may be expensive — claude-sdk issues\n * `count_tokens` requests — so the runner asks for it only when a host\n * requests a measured breakdown; `\"summary\"` must make no provider call and\n * is what the per-turn snapshot uses. Implementations must not throw for\n * \"unsupported\"; a rejection means the measurement itself failed and the\n * runner falls back to estimates.\n */\n async getContextUsageReport(_opts?: {\n detail?: ContextUsageDetail;\n }): Promise<HarnessContextReport | null> {\n return null;\n }\n\n /**\n * Returns the list of models available to this harness without starting a session.\n * Harnesses that can enumerate their own models override this method.\n * Returns an empty array by default.\n */\n async listModels(): Promise<ModelEntry[]> {\n return [];\n }\n\n /**\n * Closes the current conversation session and prepares for a fresh start.\n * The next `prompt()` call will begin a new session without prior history.\n * The harness remains usable after `resetSession()`.\n */\n abstract resetSession(): Promise<void>;\n\n // ── Telemetry ─────────────────────────────────────────────────────────────\n\n protected _telemetry?: TelemetryProvider;\n protected _activeTrace?: Trace;\n protected _activeTurnSpan?: Span;\n private _turnStartTime?: number;\n\n /**\n * Attach a telemetry provider and active trace to this harness.\n * Called by the runner after creating the harness but before start().\n */\n setTelemetry(provider: TelemetryProvider, trace: Trace): void {\n this._telemetry = provider;\n this._activeTrace = trace;\n }\n\n /**\n * Begin a turn span. Called by the runner before prompt().\n * Pass a parent span (e.g. the turn span from the orchestrator) for nesting.\n * Returns the span so the runner can annotate it further.\n */\n beginTurnSpan(\n parent?: Trace | Span,\n attrs?: Record<string, string | number | boolean>,\n ): Span | undefined {\n if (!this._telemetry || !this._activeTrace) return undefined;\n this._turnStartTime = Date.now();\n this._activeTurnSpan = this._telemetry.startSpan(parent ?? this._activeTrace, {\n name: \"llm_generation\",\n kind: \"llm_generation\",\n attributes: attrs,\n });\n return this._activeTurnSpan;\n }\n\n /**\n * End the current turn span with generation data.\n * Called by the runner after agent_end. Model and provider are passed\n * explicitly — the harness base class does not access config directly.\n */\n endTurnSpan(result?: {\n model?: string;\n provider?: string;\n inputTokens?: number;\n outputTokens?: number;\n stopReason?: string;\n error?: string;\n }): void {\n if (!this._telemetry || !this._activeTurnSpan) return;\n const durationMs = this._turnStartTime ? Date.now() - this._turnStartTime : 0;\n\n if (result?.inputTokens !== undefined || result?.outputTokens !== undefined) {\n this._telemetry.logGeneration(this._activeTurnSpan, {\n model: result?.model ?? \"unknown\",\n provider: result?.provider ?? \"unknown\",\n inputTokens: result.inputTokens,\n outputTokens: result.outputTokens,\n durationMs,\n stopReason: result.stopReason,\n });\n }\n\n this._telemetry.endSpan(this._activeTurnSpan, {\n status: result?.error ? \"error\" : \"ok\",\n error: result?.error,\n attributes: { \"skaile.turn.duration_ms\": durationMs },\n });\n\n this._activeTurnSpan = undefined;\n this._turnStartTime = undefined;\n }\n}\n\n/**\n * Factory function signature registered in the harness registry.\n *\n * @param config - Configuration for the new harness instance.\n * @returns A freshly constructed (not yet started) {@link AgentHarness}.\n * @docLink packages/bridge/concepts#harness-factory\n */\nexport type HarnessFactory = (config: AgentConfig) => AgentHarness;\n"]}
@@ -1,4 +1,4 @@
1
- import { getStoreConfig, getStoreToken, storeFetch } from './chunk-KB56WBQ3.js';
1
+ import { getStoreConfig, getStoreToken, storeFetch } from './chunk-TPQKFX6X.js';
2
2
 
3
3
  // cli/src/store-publisher.ts
4
4
  function makeHttpPublisherClient(config = getStoreConfig(), timeoutMs = 2e4) {
@@ -25,5 +25,5 @@ function makeHttpPublisherClient(config = getStoreConfig(), timeoutMs = 2e4) {
25
25
  }
26
26
 
27
27
  export { makeHttpPublisherClient };
28
- //# sourceMappingURL=chunk-7Y6S4XLL.js.map
29
- //# sourceMappingURL=chunk-7Y6S4XLL.js.map
28
+ //# sourceMappingURL=chunk-RKI35EAN.js.map
29
+ //# sourceMappingURL=chunk-RKI35EAN.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../cli/src/store-publisher.ts"],"names":[],"mappings":";;;AA+FO,SAAS,uBAAA,CACd,MAAA,GAAsB,cAAA,EAAe,EACrC,YAAY,GAAA,EACK;AAGjB,EAAA,MAAM,IAAA,GAAO,OACX,IAAA,EACA,IAAA,KACe;AACf,IAAA,MAAM,GAAA,GAAM,MAAM,aAAA,EAAc;AAChC,IAAA,OAAO,UAAA,CAAc,EAAE,GAAG,MAAA,EAAQ,GAAA,EAAI,EAAG,IAAA,EAAM,EAAE,SAAA,EAAW,GAAG,IAAA,EAAM,CAAA;AAAA,EACvE,CAAA;AACA,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,MAAM,IAAA,CAAK,YAAY,CAAA;AAAA,IAC3B,UAAA,EAAY,CAAC,IAAA,KAAS,IAAA,CAAK,mBAAmB,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,CAAA;AAAA,IACtE,WAAA,EAAa,MAAM,IAAA,CAAK,iBAAiB,CAAA;AAAA,IACzC,UAAA,EAAY,CAAC,EAAA,KAAO,IAAA,CAAK,CAAA,gBAAA,EAAmB,EAAE,CAAA,KAAA,CAAA,EAAS,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,IAAI,CAAA;AAAA,IACnF,QAAQ,CAAC,KAAA,KAAU,IAAA,CAAK,CAAA,aAAA,EAAgB,KAAK,CAAA,CAAE,CAAA;AAAA,IAC/C,kBAAkB,CAAC,EAAA,KAAO,IAAA,CAAK,CAAA,gBAAA,EAAmB,EAAE,CAAA,WAAA,CAAa,CAAA;AAAA,IACjE,cAAc,CAAC,EAAA,KAAO,IAAA,CAAK,CAAA,eAAA,EAAkB,EAAE,CAAA,QAAA,CAAU,CAAA;AAAA,IACzD,YAAA,EAAc,CAAC,EAAA,EAAI,IAAA,EAAM,WACvB,IAAA,CAAK,CAAA,eAAA,EAAkB,EAAE,CAAA,QAAA,CAAA,EAAY;AAAA,MACnC,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA;AAAA,MACA,GAAI,SAAS,EAAE,MAAA,EAAQ,EAAE,MAAA,EAAQ,GAAA,EAAI,EAAE,GAAI;AAAC,KAC7C,CAAA;AAAA,IACH,cAAA,EAAgB,CAAC,EAAA,KAAO,IAAA,CAAK,CAAA,eAAA,EAAkB,EAAE,CAAA,UAAA,CAAA,EAAc,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,IAAI,CAAA;AAAA,IAC3F,qBAAA,EAAuB,CAAC,EAAA,KACtB,IAAA,CAAK,sBAAsB,kBAAA,CAAmB,EAAE,CAAC,CAAA,aAAA,CAAe;AAAA,GACpE;AACF","file":"chunk-7Y6S4XLL.js","sourcesContent":["/**\n * Typed REST client for the AI Asset Store **publisher** surface — the\n * curator-publish flow (`skaile source manifest publish` / `yank`). Thin\n * wrappers over {@link storeFetch}; every method maps 1:1 to an `/api/v1/…`\n * endpoint. The {@link PublisherClient} interface is injectable so the\n * orchestration in `commands/source-manifest-publish.ts` can be unit-tested\n * against a fake without a live store.\n *\n * @docLink cli/dev-guide#store-publisher\n */\n\nimport { getStoreConfig, getStoreToken, type StoreConfig, storeFetch } from \"./store-client.ts\";\n\n/**\n * The publisher REST surface used by the curator-publish flow. Kept minimal —\n * only the endpoints `runPublish` / `runYank` actually call. Response shapes\n * are narrowed to the fields the orchestration reads (the server returns more).\n */\nexport interface PublisherClient {\n /**\n * Identity of the caller. `username` is the Keycloak login (personal-tier\n * namespace); `githubLogin` is the verified GitHub handle when connected —\n * the namespace to publish under when it differs from the login.\n */\n me(): Promise<{ username: string; githubLogin?: string | null }>;\n /** Register (or re-register) a source; returns the created/existing row id. */\n sourcesAdd(body: {\n url: string;\n ref: string;\n sidecarUrl?: string;\n sidecarRef?: string;\n /**\n * Target publisher namespace (the manifest's `publisher`). When it differs\n * from the caller's login username, the store resolves the CLAIMED Publisher\n * for it (the store must already have the claim). Omitted → the store\n * defaults to `@<username>` (personal).\n */\n namespace?: string;\n }): Promise<{ id: string }>;\n /** List sources — used to recover an id when `sourcesAdd` rejects a dup url. */\n sourcesList(): Promise<Array<{ id: string; url: string }>>;\n /** Kick off a source sync; returns the async job id to poll. */\n sourceSync(id: string): Promise<{ jobId: string }>;\n /** Poll a job's terminal status + per-item results. */\n jobGet(\n jobId: string,\n ): Promise<{ status: string; items?: Array<{ label: string; status: string; error?: string }> }>;\n /** Discovered publishable candidates for a synced source. */\n sourceCandidates(id: string): Promise<\n Array<{\n id: string;\n name: string;\n version: string;\n kind: string;\n published: boolean;\n assetRoot: string;\n }>\n >;\n /** Per-asset preview — the discovered file set + resolved candidate metadata. */\n assetPreview(id: string): Promise<{\n discoveredFiles: string[];\n candidate: { name: string; version: string; kind: string; publisherNamespace: string };\n }>;\n /**\n * Publish one asset. `dryRun` returns the would-be `{ manifest }` without\n * launching a job; the normal path returns `{ jobId }`.\n */\n assetPublish(\n id: string,\n body: { ref: string; files: string[] },\n dryRun?: boolean,\n ): Promise<{ jobId?: string; manifest?: unknown }>;\n /** Retract a published asset. Response body is ignored. */\n assetUnpublish(id: string): Promise<unknown>;\n /**\n * Read-only \"can I publish under `@<ns>` right now, and if not, what's the\n * path?\" probe. Backs the `publish --dry-run` namespace status line; its\n * `message` is store-authored and meant to be surfaced verbatim.\n */\n namespaceAvailability(ns: string): Promise<{\n namespace: string;\n status: \"owned-by-you\" | \"claimable-by-you\" | \"reserved\" | \"available\";\n claimMethod?: string;\n message: string;\n }>;\n}\n\n/**\n * Construct the real HTTP-backed {@link PublisherClient}. Every call carries a\n * longer timeout than the default store client because publish/sync trigger\n * server-side clone work.\n *\n * @param config - Store connection config; defaults to {@link getStoreConfig}.\n * @param timeoutMs - Per-request abort timeout (default 20s).\n */\nexport function makeHttpPublisherClient(\n config: StoreConfig = getStoreConfig(),\n timeoutMs = 20_000,\n): PublisherClient {\n // Acquire a fresh Keycloak token per call (device-flow session in\n // ~/.skaile/auth.json, refreshed on demand) rather than a static config.jwt.\n const call = async <T>(\n path: string,\n opts?: { method?: string; body?: unknown; params?: Record<string, string> },\n ): Promise<T> => {\n const jwt = await getStoreToken();\n return storeFetch<T>({ ...config, jwt }, path, { timeoutMs, ...opts });\n };\n return {\n me: () => call(\"/api/v1/me\"),\n sourcesAdd: (body) => call(\"/api/v1/sources\", { method: \"POST\", body }),\n sourcesList: () => call(\"/api/v1/sources\"),\n sourceSync: (id) => call(`/api/v1/sources/${id}/sync`, { method: \"POST\", body: {} }),\n jobGet: (jobId) => call(`/api/v1/jobs/${jobId}`),\n sourceCandidates: (id) => call(`/api/v1/sources/${id}/candidates`),\n assetPreview: (id) => call(`/api/v1/assets/${id}/preview`),\n assetPublish: (id, body, dryRun) =>\n call(`/api/v1/assets/${id}/publish`, {\n method: \"POST\",\n body,\n ...(dryRun ? { params: { dryRun: \"1\" } } : {}),\n }),\n assetUnpublish: (id) => call(`/api/v1/assets/${id}/unpublish`, { method: \"POST\", body: {} }),\n namespaceAvailability: (ns) =>\n call(`/api/v1/namespaces/${encodeURIComponent(ns)}/availability`),\n };\n}\n"]}
1
+ {"version":3,"sources":["../cli/src/store-publisher.ts"],"names":[],"mappings":";;;AA+FO,SAAS,uBAAA,CACd,MAAA,GAAsB,cAAA,EAAe,EACrC,YAAY,GAAA,EACK;AAGjB,EAAA,MAAM,IAAA,GAAO,OACX,IAAA,EACA,IAAA,KACe;AACf,IAAA,MAAM,GAAA,GAAM,MAAM,aAAA,EAAc;AAChC,IAAA,OAAO,UAAA,CAAc,EAAE,GAAG,MAAA,EAAQ,GAAA,EAAI,EAAG,IAAA,EAAM,EAAE,SAAA,EAAW,GAAG,IAAA,EAAM,CAAA;AAAA,EACvE,CAAA;AACA,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,MAAM,IAAA,CAAK,YAAY,CAAA;AAAA,IAC3B,UAAA,EAAY,CAAC,IAAA,KAAS,IAAA,CAAK,mBAAmB,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,CAAA;AAAA,IACtE,WAAA,EAAa,MAAM,IAAA,CAAK,iBAAiB,CAAA;AAAA,IACzC,UAAA,EAAY,CAAC,EAAA,KAAO,IAAA,CAAK,CAAA,gBAAA,EAAmB,EAAE,CAAA,KAAA,CAAA,EAAS,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,IAAI,CAAA;AAAA,IACnF,QAAQ,CAAC,KAAA,KAAU,IAAA,CAAK,CAAA,aAAA,EAAgB,KAAK,CAAA,CAAE,CAAA;AAAA,IAC/C,kBAAkB,CAAC,EAAA,KAAO,IAAA,CAAK,CAAA,gBAAA,EAAmB,EAAE,CAAA,WAAA,CAAa,CAAA;AAAA,IACjE,cAAc,CAAC,EAAA,KAAO,IAAA,CAAK,CAAA,eAAA,EAAkB,EAAE,CAAA,QAAA,CAAU,CAAA;AAAA,IACzD,YAAA,EAAc,CAAC,EAAA,EAAI,IAAA,EAAM,WACvB,IAAA,CAAK,CAAA,eAAA,EAAkB,EAAE,CAAA,QAAA,CAAA,EAAY;AAAA,MACnC,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA;AAAA,MACA,GAAI,SAAS,EAAE,MAAA,EAAQ,EAAE,MAAA,EAAQ,GAAA,EAAI,EAAE,GAAI;AAAC,KAC7C,CAAA;AAAA,IACH,cAAA,EAAgB,CAAC,EAAA,KAAO,IAAA,CAAK,CAAA,eAAA,EAAkB,EAAE,CAAA,UAAA,CAAA,EAAc,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,IAAI,CAAA;AAAA,IAC3F,qBAAA,EAAuB,CAAC,EAAA,KACtB,IAAA,CAAK,sBAAsB,kBAAA,CAAmB,EAAE,CAAC,CAAA,aAAA,CAAe;AAAA,GACpE;AACF","file":"chunk-RKI35EAN.js","sourcesContent":["/**\n * Typed REST client for the AI Asset Store **publisher** surface — the\n * curator-publish flow (`skaile source manifest publish` / `yank`). Thin\n * wrappers over {@link storeFetch}; every method maps 1:1 to an `/api/v1/…`\n * endpoint. The {@link PublisherClient} interface is injectable so the\n * orchestration in `commands/source-manifest-publish.ts` can be unit-tested\n * against a fake without a live store.\n *\n * @docLink cli/dev-guide#store-publisher\n */\n\nimport { getStoreConfig, getStoreToken, type StoreConfig, storeFetch } from \"./store-client.ts\";\n\n/**\n * The publisher REST surface used by the curator-publish flow. Kept minimal —\n * only the endpoints `runPublish` / `runYank` actually call. Response shapes\n * are narrowed to the fields the orchestration reads (the server returns more).\n */\nexport interface PublisherClient {\n /**\n * Identity of the caller. `username` is the Keycloak login (personal-tier\n * namespace); `githubLogin` is the verified GitHub handle when connected —\n * the namespace to publish under when it differs from the login.\n */\n me(): Promise<{ username: string; githubLogin?: string | null }>;\n /** Register (or re-register) a source; returns the created/existing row id. */\n sourcesAdd(body: {\n url: string;\n ref: string;\n sidecarUrl?: string;\n sidecarRef?: string;\n /**\n * Target publisher namespace (the manifest's `publisher`). When it differs\n * from the caller's login username, the store resolves the CLAIMED Publisher\n * for it (the store must already have the claim). Omitted → the store\n * defaults to `@<username>` (personal).\n */\n namespace?: string;\n }): Promise<{ id: string }>;\n /** List sources — used to recover an id when `sourcesAdd` rejects a dup url. */\n sourcesList(): Promise<Array<{ id: string; url: string }>>;\n /** Kick off a source sync; returns the async job id to poll. */\n sourceSync(id: string): Promise<{ jobId: string }>;\n /** Poll a job's terminal status + per-item results. */\n jobGet(\n jobId: string,\n ): Promise<{ status: string; items?: Array<{ label: string; status: string; error?: string }> }>;\n /** Discovered publishable candidates for a synced source. */\n sourceCandidates(id: string): Promise<\n Array<{\n id: string;\n name: string;\n version: string;\n kind: string;\n published: boolean;\n assetRoot: string;\n }>\n >;\n /** Per-asset preview — the discovered file set + resolved candidate metadata. */\n assetPreview(id: string): Promise<{\n discoveredFiles: string[];\n candidate: { name: string; version: string; kind: string; publisherNamespace: string };\n }>;\n /**\n * Publish one asset. `dryRun` returns the would-be `{ manifest }` without\n * launching a job; the normal path returns `{ jobId }`.\n */\n assetPublish(\n id: string,\n body: { ref: string; files: string[] },\n dryRun?: boolean,\n ): Promise<{ jobId?: string; manifest?: unknown }>;\n /** Retract a published asset. Response body is ignored. */\n assetUnpublish(id: string): Promise<unknown>;\n /**\n * Read-only \"can I publish under `@<ns>` right now, and if not, what's the\n * path?\" probe. Backs the `publish --dry-run` namespace status line; its\n * `message` is store-authored and meant to be surfaced verbatim.\n */\n namespaceAvailability(ns: string): Promise<{\n namespace: string;\n status: \"owned-by-you\" | \"claimable-by-you\" | \"reserved\" | \"available\";\n claimMethod?: string;\n message: string;\n }>;\n}\n\n/**\n * Construct the real HTTP-backed {@link PublisherClient}. Every call carries a\n * longer timeout than the default store client because publish/sync trigger\n * server-side clone work.\n *\n * @param config - Store connection config; defaults to {@link getStoreConfig}.\n * @param timeoutMs - Per-request abort timeout (default 20s).\n */\nexport function makeHttpPublisherClient(\n config: StoreConfig = getStoreConfig(),\n timeoutMs = 20_000,\n): PublisherClient {\n // Acquire a fresh Keycloak token per call (device-flow session in\n // ~/.skaile/auth.json, refreshed on demand) rather than a static config.jwt.\n const call = async <T>(\n path: string,\n opts?: { method?: string; body?: unknown; params?: Record<string, string> },\n ): Promise<T> => {\n const jwt = await getStoreToken();\n return storeFetch<T>({ ...config, jwt }, path, { timeoutMs, ...opts });\n };\n return {\n me: () => call(\"/api/v1/me\"),\n sourcesAdd: (body) => call(\"/api/v1/sources\", { method: \"POST\", body }),\n sourcesList: () => call(\"/api/v1/sources\"),\n sourceSync: (id) => call(`/api/v1/sources/${id}/sync`, { method: \"POST\", body: {} }),\n jobGet: (jobId) => call(`/api/v1/jobs/${jobId}`),\n sourceCandidates: (id) => call(`/api/v1/sources/${id}/candidates`),\n assetPreview: (id) => call(`/api/v1/assets/${id}/preview`),\n assetPublish: (id, body, dryRun) =>\n call(`/api/v1/assets/${id}/publish`, {\n method: \"POST\",\n body,\n ...(dryRun ? { params: { dryRun: \"1\" } } : {}),\n }),\n assetUnpublish: (id) => call(`/api/v1/assets/${id}/unpublish`, { method: \"POST\", body: {} }),\n namespaceAvailability: (ns) =>\n call(`/api/v1/namespaces/${encodeURIComponent(ns)}/availability`),\n };\n}\n"]}
@@ -1,10 +1,10 @@
1
- import { mountList, mountSync, mountStatus, mountRead, connectorList, connectorRead, connectorWrite, connectorSearch, connectorExec, connectorLoadSkill, connectorDescribe } from './chunk-ZWJCRHP3.js';
2
- import { flowList, flowShow, flowListSessions, flowGetSession, flowFindFlowForSession } from './chunk-Q5RN4PWV.js';
1
+ import { mountList, mountSync, mountStatus, mountRead, connectorList, connectorRead, connectorWrite, connectorSearch, connectorExec, connectorLoadSkill, connectorDescribe } from './chunk-YFGXYQW4.js';
2
+ import { flowList, flowShow, flowListSessions, flowGetSession, flowFindFlowForSession } from './chunk-5NHBLKKU.js';
3
3
  import { sessionList, sessionGet } from './chunk-WYZXSJBK.js';
4
- import { skillList, skillShow, skillSearch, skillCheckRequirements, skillGetPreamble } from './chunk-QK7AG5AV.js';
4
+ import { skillList, skillShow, skillSearch, skillCheckRequirements, skillGetPreamble } from './chunk-E237FGGX.js';
5
5
  import { workspaceValidate, workspaceInfo, workspaceTestSecret, workspaceReload } from './chunk-KW37WNXY.js';
6
- import { withActivityLabelDefs } from './chunk-JCPD4QRM.js';
7
- import { loadHarnessSdk } from './chunk-BRK5QZKI.js';
6
+ import { withActivityLabelDefs } from './chunk-VZU67OKK.js';
7
+ import { loadHarnessSdk } from './chunk-ABVWUM2E.js';
8
8
  import { DEFAULT_HARNESS_ID } from './chunk-C5HFK34M.js';
9
9
  import * as zNS from 'zod';
10
10
 
@@ -251,5 +251,5 @@ async function runMcpServerStdio(plugin) {
251
251
  }
252
252
 
253
253
  export { buildWorkspaceMcpServer, buildWorkspaceMcpStdioServer, buildWorkspaceToolDefs, runMcpServerStdio };
254
- //# sourceMappingURL=chunk-OCQNUV4T.js.map
255
- //# sourceMappingURL=chunk-OCQNUV4T.js.map
254
+ //# sourceMappingURL=chunk-SISUT7VR.js.map
255
+ //# sourceMappingURL=chunk-SISUT7VR.js.map