@skaile/workspaces 6.6.0 → 6.8.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 (381) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/ai-sdk.js +10 -17
  3. package/dist/ai-sdk.js.map +1 -1
  4. package/dist/app-sdk/index.js +1 -1
  5. package/dist/{asset-feeds-WQ6YQPHV.js → asset-feeds-NU5UOO5F.js} +18 -18
  6. package/dist/{asset-feeds-WQ6YQPHV.js.map → asset-feeds-NU5UOO5F.js.map} +1 -1
  7. package/dist/asset-manager/catalog-deployer.js +4 -4
  8. package/dist/asset-manager/index.js +10 -10
  9. package/dist/asset-manager/installer.js +6 -6
  10. package/dist/asset-manager/renderers.js +5 -5
  11. package/dist/asset-manager/src/index.d.ts +89 -15
  12. package/dist/asset-manager/src/index.d.ts.map +1 -1
  13. package/dist/asset-manager/src/install-agent.d.ts +22 -1
  14. package/dist/asset-manager/src/install-agent.d.ts.map +1 -1
  15. package/dist/asset-manager/src/install-instances.d.ts +30 -1
  16. package/dist/asset-manager/src/install-instances.d.ts.map +1 -1
  17. package/dist/asset-manager/src/installer.d.ts +12 -0
  18. package/dist/asset-manager/src/installer.d.ts.map +1 -1
  19. package/dist/asset-manager/src/renderers.d.ts.map +1 -1
  20. package/dist/bridge/harnesses/claude-sdk.js +34 -20
  21. package/dist/bridge/harnesses/claude-sdk.js.map +1 -1
  22. package/dist/bridge/harnesses/codex.js +9 -8
  23. package/dist/bridge/harnesses/codex.js.map +1 -1
  24. package/dist/bridge/harnesses/continue.js +11 -9
  25. package/dist/bridge/harnesses/continue.js.map +1 -1
  26. package/dist/bridge/harnesses/echo.js +5 -4
  27. package/dist/bridge/harnesses/echo.js.map +1 -1
  28. package/dist/bridge/harnesses/gemini.js +8 -6
  29. package/dist/bridge/harnesses/goose.js +11 -9
  30. package/dist/bridge/harnesses/goose.js.map +1 -1
  31. package/dist/bridge/harnesses/omp.js +9 -7
  32. package/dist/bridge/harnesses/omp.js.map +1 -1
  33. package/dist/bridge/harnesses/opencode.js +11 -9
  34. package/dist/bridge/harnesses/opencode.js.map +1 -1
  35. package/dist/bridge/harnesses/qwen.js +9 -7
  36. package/dist/bridge/harnesses/qwen.js.map +1 -1
  37. package/dist/bridge/index.js +17 -15
  38. package/dist/bridge/src/ai-sdk.d.ts.map +1 -1
  39. package/dist/bridge/src/claude-sdk-surface.d.ts +2 -1
  40. package/dist/bridge/src/claude-sdk-surface.d.ts.map +1 -1
  41. package/dist/bridge/src/harness-binaries.d.ts +21 -0
  42. package/dist/bridge/src/harness-binaries.d.ts.map +1 -0
  43. package/dist/bridge/src/harness-model-check.d.ts +22 -6
  44. package/dist/bridge/src/harness-model-check.d.ts.map +1 -1
  45. package/dist/bridge/src/harnesses/claude-sdk.d.ts.map +1 -1
  46. package/dist/bridge/src/harnesses/claude-self-turns.d.ts.map +1 -1
  47. package/dist/bridge/src/harnesses/continue.d.ts.map +1 -1
  48. package/dist/bridge/src/harnesses/gemini.d.ts.map +1 -1
  49. package/dist/bridge/src/harnesses/goose.d.ts.map +1 -1
  50. package/dist/bridge/src/harnesses/omp-models-yml.d.ts.map +1 -1
  51. package/dist/bridge/src/harnesses/omp.d.ts.map +1 -1
  52. package/dist/bridge/src/harnesses/opencode.d.ts.map +1 -1
  53. package/dist/bridge/src/harnesses/qwen.d.ts.map +1 -1
  54. package/dist/bridge/src/index.d.ts +2 -1
  55. package/dist/bridge/src/index.d.ts.map +1 -1
  56. package/dist/bridge/src/types.d.ts +11 -0
  57. package/dist/bridge/src/types.d.ts.map +1 -1
  58. package/dist/{chunk-LBJ4M5J2.js → chunk-237BMOZW.js} +4 -4
  59. package/dist/{chunk-LBJ4M5J2.js.map → chunk-237BMOZW.js.map} +1 -1
  60. package/dist/{chunk-XYCYGN3Q.js → chunk-2I5HNM7K.js} +79 -20
  61. package/dist/chunk-2I5HNM7K.js.map +1 -0
  62. package/dist/{chunk-MXI3XWV6.js → chunk-3HSLJAMJ.js} +4 -4
  63. package/dist/{chunk-MXI3XWV6.js.map → chunk-3HSLJAMJ.js.map} +1 -1
  64. package/dist/{chunk-SCRYXAHH.js → chunk-3NJFPGEB.js} +6 -6
  65. package/dist/{chunk-SCRYXAHH.js.map → chunk-3NJFPGEB.js.map} +1 -1
  66. package/dist/{chunk-RHCEX2EV.js → chunk-3QX2X77G.js} +3 -3
  67. package/dist/{chunk-RHCEX2EV.js.map → chunk-3QX2X77G.js.map} +1 -1
  68. package/dist/{chunk-DS6UUCFG.js → chunk-4CD2R4MJ.js} +5 -4
  69. package/dist/chunk-4CD2R4MJ.js.map +1 -0
  70. package/dist/{chunk-7I5PNB2G.js → chunk-5TLMHB2U.js} +3 -3
  71. package/dist/{chunk-7I5PNB2G.js.map → chunk-5TLMHB2U.js.map} +1 -1
  72. package/dist/{chunk-KSH5CFQS.js → chunk-6PVRP3LW.js} +36 -5
  73. package/dist/chunk-6PVRP3LW.js.map +1 -0
  74. package/dist/{chunk-BSMW3PX2.js → chunk-6UP2EDFN.js} +4 -313
  75. package/dist/chunk-6UP2EDFN.js.map +1 -0
  76. package/dist/{chunk-U3UDOX6I.js → chunk-6ZM5X2XW.js} +6 -4
  77. package/dist/chunk-6ZM5X2XW.js.map +1 -0
  78. package/dist/{chunk-JRVQV7WC.js → chunk-757G6TTZ.js} +595 -126
  79. package/dist/chunk-757G6TTZ.js.map +1 -0
  80. package/dist/{chunk-G5SYFFMD.js → chunk-7NN3P6VF.js} +22 -5
  81. package/dist/chunk-7NN3P6VF.js.map +1 -0
  82. package/dist/{chunk-7PVGND4J.js → chunk-7YOHUX2M.js} +21 -14
  83. package/dist/chunk-7YOHUX2M.js.map +1 -0
  84. package/dist/{chunk-O7QZI6MQ.js → chunk-BB5EJLKZ.js} +2 -2
  85. package/dist/{chunk-O7QZI6MQ.js.map → chunk-BB5EJLKZ.js.map} +1 -1
  86. package/dist/{chunk-2M3VLKT2.js → chunk-BRPEW3UL.js} +3 -3
  87. package/dist/{chunk-2M3VLKT2.js.map → chunk-BRPEW3UL.js.map} +1 -1
  88. package/dist/{chunk-EPXZQIC6.js → chunk-DFP476EU.js} +8 -4
  89. package/dist/chunk-DFP476EU.js.map +1 -0
  90. package/dist/{chunk-B6N653ZG.js → chunk-DRHJRTAS.js} +6 -6
  91. package/dist/{chunk-B6N653ZG.js.map → chunk-DRHJRTAS.js.map} +1 -1
  92. package/dist/{chunk-4J7JQX4G.js → chunk-E3KABQS3.js} +4 -4
  93. package/dist/{chunk-4J7JQX4G.js.map → chunk-E3KABQS3.js.map} +1 -1
  94. package/dist/{chunk-MMOWIRHP.js → chunk-G44FFUMA.js} +12 -10
  95. package/dist/chunk-G44FFUMA.js.map +1 -0
  96. package/dist/{chunk-JIQUF3X2.js → chunk-G7NMF5WQ.js} +3 -3
  97. package/dist/{chunk-JIQUF3X2.js.map → chunk-G7NMF5WQ.js.map} +1 -1
  98. package/dist/{chunk-HGZN6JLP.js → chunk-HKRME377.js} +4 -4
  99. package/dist/{chunk-HGZN6JLP.js.map → chunk-HKRME377.js.map} +1 -1
  100. package/dist/{chunk-6A6HE5LW.js → chunk-HLAEYFUN.js} +3 -3
  101. package/dist/{chunk-6A6HE5LW.js.map → chunk-HLAEYFUN.js.map} +1 -1
  102. package/dist/{chunk-F4CZQD3T.js → chunk-I6XH46Q6.js} +4 -3
  103. package/dist/chunk-I6XH46Q6.js.map +1 -0
  104. package/dist/{chunk-7SJHSGUV.js → chunk-K6HCOTOZ.js} +16 -15
  105. package/dist/chunk-K6HCOTOZ.js.map +1 -0
  106. package/dist/{chunk-AQNW2FET.js → chunk-K7ZGY2BY.js} +351 -51
  107. package/dist/chunk-K7ZGY2BY.js.map +1 -0
  108. package/dist/{chunk-GTGWRKMJ.js → chunk-KHWGUXSF.js} +6 -6
  109. package/dist/{chunk-GTGWRKMJ.js.map → chunk-KHWGUXSF.js.map} +1 -1
  110. package/dist/{chunk-DI6J2PJB.js → chunk-KO3VSZQP.js} +47 -18
  111. package/dist/chunk-KO3VSZQP.js.map +1 -0
  112. package/dist/{chunk-VXYZ5M7Z.js → chunk-LJ6PLEDU.js} +64 -27
  113. package/dist/chunk-LJ6PLEDU.js.map +1 -0
  114. package/dist/{chunk-SHTXMERQ.js → chunk-LL5GMUQG.js} +10 -8
  115. package/dist/chunk-LL5GMUQG.js.map +1 -0
  116. package/dist/{chunk-TCH5UDKT.js → chunk-NW7Y5SNK.js} +10 -8
  117. package/dist/chunk-NW7Y5SNK.js.map +1 -0
  118. package/dist/{chunk-J4WKNJHO.js → chunk-O5Y7VMVQ.js} +15 -14
  119. package/dist/chunk-O5Y7VMVQ.js.map +1 -0
  120. package/dist/{chunk-6SXSVKQY.js → chunk-O7ADRMCR.js} +63 -14
  121. package/dist/chunk-O7ADRMCR.js.map +1 -0
  122. package/dist/{chunk-WW5NAU6N.js → chunk-ORXV3UB6.js} +3 -3
  123. package/dist/{chunk-WW5NAU6N.js.map → chunk-ORXV3UB6.js.map} +1 -1
  124. package/dist/{chunk-VJRL6ZK6.js → chunk-OSABUEWA.js} +3 -3
  125. package/dist/{chunk-VJRL6ZK6.js.map → chunk-OSABUEWA.js.map} +1 -1
  126. package/dist/{chunk-XD3RYAMR.js → chunk-PMZMG3HC.js} +6 -6
  127. package/dist/{chunk-XD3RYAMR.js.map → chunk-PMZMG3HC.js.map} +1 -1
  128. package/dist/{chunk-J262X4JU.js → chunk-Q6FKWPRO.js} +69 -16
  129. package/dist/chunk-Q6FKWPRO.js.map +1 -0
  130. package/dist/{chunk-E2EC6SAX.js → chunk-QC5BYUED.js} +51 -15
  131. package/dist/chunk-QC5BYUED.js.map +1 -0
  132. package/dist/{chunk-RAU5QPI6.js → chunk-QCR5AE5E.js} +5 -5
  133. package/dist/{chunk-RAU5QPI6.js.map → chunk-QCR5AE5E.js.map} +1 -1
  134. package/dist/{chunk-I5IF3JCG.js → chunk-QGA2OBUJ.js} +3 -3
  135. package/dist/{chunk-I5IF3JCG.js.map → chunk-QGA2OBUJ.js.map} +1 -1
  136. package/dist/{chunk-TUFNY6OD.js → chunk-QW5B3TEO.js} +10 -4
  137. package/dist/chunk-QW5B3TEO.js.map +1 -0
  138. package/dist/{chunk-Z4FERR4U.js → chunk-RDIGVPXX.js} +2 -2
  139. package/dist/{chunk-Z4FERR4U.js.map → chunk-RDIGVPXX.js.map} +1 -1
  140. package/dist/{chunk-SZKCE7EC.js → chunk-REAF7ZFA.js} +5 -5
  141. package/dist/{chunk-SZKCE7EC.js.map → chunk-REAF7ZFA.js.map} +1 -1
  142. package/dist/{chunk-OY22B7E2.js → chunk-SBNUXJ6E.js} +3 -3
  143. package/dist/{chunk-OY22B7E2.js.map → chunk-SBNUXJ6E.js.map} +1 -1
  144. package/dist/chunk-SILFO5RY.js +315 -0
  145. package/dist/chunk-SILFO5RY.js.map +1 -0
  146. package/dist/{chunk-6ARPZHOV.js → chunk-TMJBEGS4.js} +35 -6
  147. package/dist/chunk-TMJBEGS4.js.map +1 -0
  148. package/dist/{chunk-5XHQBCB5.js → chunk-WFK4MUBL.js} +21 -7
  149. package/dist/chunk-WFK4MUBL.js.map +1 -0
  150. package/dist/chunk-WWSRIT3J.js +59 -0
  151. package/dist/chunk-WWSRIT3J.js.map +1 -0
  152. package/dist/{chunk-N2PBAXAA.js → chunk-XCGDRLMH.js} +3 -3
  153. package/dist/{chunk-N2PBAXAA.js.map → chunk-XCGDRLMH.js.map} +1 -1
  154. package/dist/{chunk-YN6N3RBM.js → chunk-XIIIGLSL.js} +47 -11
  155. package/dist/chunk-XIIIGLSL.js.map +1 -0
  156. package/dist/{chunk-65UAC3ZR.js → chunk-Y6LC5PEZ.js} +4 -3
  157. package/dist/chunk-Y6LC5PEZ.js.map +1 -0
  158. package/dist/{chunk-KSUT5KAE.js → chunk-YEOG7CWQ.js} +3 -3
  159. package/dist/{chunk-KSUT5KAE.js.map → chunk-YEOG7CWQ.js.map} +1 -1
  160. package/dist/{chunk-5ETYBC2X.js → chunk-YGP6XEPA.js} +6 -6
  161. package/dist/{chunk-5ETYBC2X.js.map → chunk-YGP6XEPA.js.map} +1 -1
  162. package/dist/{chunk-2TLPC6TQ.js → chunk-YHNPWSSH.js} +41 -19
  163. package/dist/chunk-YHNPWSSH.js.map +1 -0
  164. package/dist/{chunk-6RHWTZPT.js → chunk-YZD7DUEF.js} +3 -3
  165. package/dist/{chunk-6RHWTZPT.js.map → chunk-YZD7DUEF.js.map} +1 -1
  166. package/dist/{chunk-4BFEPZ6J.js → chunk-ZBA4P5TD.js} +3 -3
  167. package/dist/{chunk-4BFEPZ6J.js.map → chunk-ZBA4P5TD.js.map} +1 -1
  168. package/dist/{claude-code-LZH7Y4Y5.js → claude-code-AESK7XO4.js} +4 -4
  169. package/dist/{claude-code-LZH7Y4Y5.js.map → claude-code-AESK7XO4.js.map} +1 -1
  170. package/dist/cli/index.js +474 -198
  171. package/dist/cli/index.js.map +1 -1
  172. package/dist/cli/src/agent-pins.d.ts +9 -3
  173. package/dist/cli/src/agent-pins.d.ts.map +1 -1
  174. package/dist/cli/src/commands/asset-cmd.d.ts +1 -1
  175. package/dist/cli/src/commands/asset-cmd.d.ts.map +1 -1
  176. package/dist/cli/src/commands/cache.d.ts.map +1 -1
  177. package/dist/cli/src/commands/catalog.d.ts +2 -0
  178. package/dist/cli/src/commands/catalog.d.ts.map +1 -1
  179. package/dist/cli/src/commands/config.d.ts.map +1 -1
  180. package/dist/cli/src/commands/harness-preflight.d.ts +38 -0
  181. package/dist/cli/src/commands/harness-preflight.d.ts.map +1 -0
  182. package/dist/cli/src/commands/library-cmd.d.ts.map +1 -1
  183. package/dist/cli/src/commands/library-index.d.ts +16 -0
  184. package/dist/cli/src/commands/library-index.d.ts.map +1 -1
  185. package/dist/cli/src/commands/migrate-assets.d.ts +5 -0
  186. package/dist/cli/src/commands/migrate-assets.d.ts.map +1 -1
  187. package/dist/cli/src/commands/migrate-harness.d.ts +15 -7
  188. package/dist/cli/src/commands/migrate-harness.d.ts.map +1 -1
  189. package/dist/cli/src/commands/migrate.d.ts.map +1 -1
  190. package/dist/cli/src/commands/outdated.d.ts.map +1 -1
  191. package/dist/cli/src/commands/plugin-registry-cmd.d.ts.map +1 -1
  192. package/dist/cli/src/commands/project.d.ts +14 -0
  193. package/dist/cli/src/commands/project.d.ts.map +1 -1
  194. package/dist/cli/src/commands/run.d.ts.map +1 -1
  195. package/dist/cli/src/commands/serve-preflight.d.ts +6 -5
  196. package/dist/cli/src/commands/serve-preflight.d.ts.map +1 -1
  197. package/dist/cli/src/commands/serve.d.ts.map +1 -1
  198. package/dist/cli/src/commands/session.d.ts.map +1 -1
  199. package/dist/cli/src/commands/source.d.ts +11 -0
  200. package/dist/cli/src/commands/source.d.ts.map +1 -1
  201. package/dist/cli/src/commands/update.d.ts.map +1 -1
  202. package/dist/cli/src/commands/validate-instances.d.ts +6 -0
  203. package/dist/cli/src/commands/validate-instances.d.ts.map +1 -1
  204. package/dist/cli/src/commands/validate.d.ts.map +1 -1
  205. package/dist/cli/src/commands/why.d.ts.map +1 -1
  206. package/dist/cli/src/plugin-store/reconcile.d.ts.map +1 -1
  207. package/dist/cli/src/session-hint.d.ts +7 -0
  208. package/dist/cli/src/session-hint.d.ts.map +1 -0
  209. package/dist/connectors/config.js +3 -3
  210. package/dist/connectors/index.js +21 -19
  211. package/dist/connectors/src/managed-gitconfig.d.ts +6 -4
  212. package/dist/connectors/src/managed-gitconfig.d.ts.map +1 -1
  213. package/dist/{connectors-HU5MHSUJ.js → connectors-5ZZRVAPD.js} +24 -22
  214. package/dist/{connectors-HU5MHSUJ.js.map → connectors-5ZZRVAPD.js.map} +1 -1
  215. package/dist/connectors-shared/index.js +2 -2
  216. package/dist/core/index.js +4 -4
  217. package/dist/core/publish-manifest.js +1 -1
  218. package/dist/core/runtime-assets.js +3 -3
  219. package/dist/core/src/agent-instances.d.ts +11 -0
  220. package/dist/core/src/agent-instances.d.ts.map +1 -1
  221. package/dist/core/src/index.d.ts +3 -2
  222. package/dist/core/src/index.d.ts.map +1 -1
  223. package/dist/core/src/publish-manifest.d.ts +20 -6
  224. package/dist/core/src/publish-manifest.d.ts.map +1 -1
  225. package/dist/core/src/repo-manager.d.ts +9 -0
  226. package/dist/core/src/repo-manager.d.ts.map +1 -1
  227. package/dist/core/src/run-state-ignore.d.ts +17 -0
  228. package/dist/core/src/run-state-ignore.d.ts.map +1 -0
  229. package/dist/core/src/workspace-config.d.ts.map +1 -1
  230. package/dist/core/workspace-config.js +2 -2
  231. package/dist/deploy/index.js +4 -4
  232. package/dist/discovery/index.js +2 -2
  233. package/dist/discovery/src/builtin-providers.d.ts.map +1 -1
  234. package/dist/discovery/src/discover-manifest.d.ts.map +1 -1
  235. package/dist/discovery/src/tree-entries.d.ts.map +1 -1
  236. package/dist/{ensure-sources-CAMWJTMR.js → ensure-sources-VLJ7AUUK.js} +26 -24
  237. package/dist/ensure-sources-VLJ7AUUK.js.map +1 -0
  238. package/dist/factory-assets/connectors/box.js +21 -19
  239. package/dist/factory-assets/connectors/deploy.js +21 -19
  240. package/dist/factory-assets/connectors/devserver.js +21 -19
  241. package/dist/factory-assets/connectors/flow/adapter.js +21 -19
  242. package/dist/factory-assets/connectors/flow/contract/schema.d.ts +3 -3
  243. package/dist/factory-assets/connectors/flow/engine/router-settlement.d.ts +2 -0
  244. package/dist/factory-assets/connectors/flow/engine/router-settlement.d.ts.map +1 -1
  245. package/dist/factory-assets/connectors/flow/engine.js +5 -5
  246. package/dist/factory-assets/connectors/flow/run-flow.js +22 -20
  247. package/dist/factory-assets/connectors/flow.js +21 -19
  248. package/dist/factory-assets/connectors/git/CONNECTOR.md +4 -1
  249. package/dist/factory-assets/connectors/git/exec.d.ts.map +1 -1
  250. package/dist/factory-assets/connectors/git.js +21 -19
  251. package/dist/factory-assets/connectors/gmail.js +21 -19
  252. package/dist/factory-assets/connectors/googledrive.js +21 -19
  253. package/dist/factory-assets/connectors/local.js +21 -19
  254. package/dist/factory-assets/connectors/mattermost.js +21 -19
  255. package/dist/factory-assets/connectors/memory.js +21 -19
  256. package/dist/factory-assets/connectors/minio.js +21 -19
  257. package/dist/factory-assets/connectors/postgres.js +21 -19
  258. package/dist/factory-assets/connectors/s3.js +21 -19
  259. package/dist/factory-assets/connectors/sharepoint.js +21 -19
  260. package/dist/factory-assets/connectors/sqlite.js +21 -19
  261. package/dist/factory-assets/connectors/static-server.js +21 -19
  262. package/dist/factory-assets/connectors/tunnel.js +21 -19
  263. package/dist/factory-assets/connectors/webdav.js +21 -19
  264. package/dist/factory-assets/connectors/xstate-store.js +21 -19
  265. package/dist/factory-assets/connectors/xstate.js +21 -19
  266. package/dist/factory-assets/skills/authoring-skaile-assets/SKILL.md +14 -1
  267. package/dist/{flows-GVOVQGQW.js → flows-I6ODIPZZ.js} +7 -7
  268. package/dist/{flows-GVOVQGQW.js.map → flows-I6ODIPZZ.js.map} +1 -1
  269. package/dist/{helpers-WMCCODAV.js → helpers-APXGTZ5A.js} +26 -24
  270. package/dist/{helpers-WMCCODAV.js.map → helpers-APXGTZ5A.js.map} +1 -1
  271. package/dist/library/index.js +7 -7
  272. package/dist/library/install.js +2 -2
  273. package/dist/library/src/manifest-writer.d.ts +5 -0
  274. package/dist/library/src/manifest-writer.d.ts.map +1 -1
  275. package/dist/{library-publish-UQQMHTND.js → library-publish-B5HL4OBE.js} +47 -45
  276. package/dist/library-publish-B5HL4OBE.js.map +1 -0
  277. package/dist/model-endpoint/index.js +8 -7
  278. package/dist/{open-library-OJ4HT2X4.js → open-library-F56D46K7.js} +29 -27
  279. package/dist/{open-library-OJ4HT2X4.js.map → open-library-F56D46K7.js.map} +1 -1
  280. package/dist/{open-registry-LWGIOJDK.js → open-registry-RZW2AFD6.js} +11 -11
  281. package/dist/{open-registry-LWGIOJDK.js.map → open-registry-RZW2AFD6.js.map} +1 -1
  282. package/dist/{paths-FR2752HV.js → paths-RPK5PNZQ.js} +7 -7
  283. package/dist/{paths-FR2752HV.js.map → paths-RPK5PNZQ.js.map} +1 -1
  284. package/dist/{plugin-store-IALJUBN2.js → plugin-store-OJTERUEZ.js} +7 -7
  285. package/dist/{plugin-store-IALJUBN2.js.map → plugin-store-OJTERUEZ.js.map} +1 -1
  286. package/dist/{project-UQFCYHYS.js → project-GLTP6VFV.js} +43 -41
  287. package/dist/{project-UQFCYHYS.js.map → project-GLTP6VFV.js.map} +1 -1
  288. package/dist/resolver/index.js +4 -4
  289. package/dist/runner/index.js +32 -30
  290. package/dist/runner/src/capability-roundtrip.d.ts +8 -7
  291. package/dist/runner/src/capability-roundtrip.d.ts.map +1 -1
  292. package/dist/runner/src/composition/run-snapshot.d.ts +7 -1
  293. package/dist/runner/src/composition/run-snapshot.d.ts.map +1 -1
  294. package/dist/runner/src/serve.d.ts.map +1 -1
  295. package/dist/runner/src/turn-scheduler.d.ts +8 -0
  296. package/dist/runner/src/turn-scheduler.d.ts.map +1 -1
  297. package/dist/runner/src/turn-visibility.d.ts +97 -0
  298. package/dist/runner/src/turn-visibility.d.ts.map +1 -0
  299. package/dist/sdk/asset-manager.js +10 -10
  300. package/dist/sdk/bridge.js +17 -15
  301. package/dist/sdk/core.js +4 -4
  302. package/dist/sdk/flow.js +5 -5
  303. package/dist/sdk/index.js +32 -30
  304. package/dist/sdk/index.js.map +1 -1
  305. package/dist/sdk/resolver.js +4 -4
  306. package/dist/sdk/runner.js +32 -30
  307. package/dist/sdk/session.js +2 -2
  308. package/dist/sdk/transport/ws/server.js +5 -5
  309. package/dist/sdk/transport/ws.js +5 -5
  310. package/dist/sdk/transport.js +5 -5
  311. package/dist/sdk/types.js +1 -1
  312. package/dist/serve-preflight-EHLBSNUE.js +58 -0
  313. package/dist/{serve-preflight-TYEKHC32.js.map → serve-preflight-EHLBSNUE.js.map} +1 -1
  314. package/dist/session/index.js +2 -2
  315. package/dist/session/src/dispatcher.d.ts.map +1 -1
  316. package/dist/{setup-4JV2IMCB.js → setup-PMZLMFCD.js} +27 -25
  317. package/dist/setup-PMZLMFCD.js.map +1 -0
  318. package/dist/{skills-6QTKFMLW.js → skills-KHHW3RZ3.js} +6 -6
  319. package/dist/{skills-6QTKFMLW.js.map → skills-KHHW3RZ3.js.map} +1 -1
  320. package/dist/source-QNSGAM3S.js +88 -0
  321. package/dist/{source-XYMMJVKR.js.map → source-QNSGAM3S.js.map} +1 -1
  322. package/dist/{source-manifest-publish-SZFGGKB4.js → source-manifest-publish-AI725AVE.js} +44 -42
  323. package/dist/source-manifest-publish-AI725AVE.js.map +1 -0
  324. package/dist/transport/index.js +5 -5
  325. package/dist/transport/ws/server.js +5 -5
  326. package/dist/transport/ws.js +5 -5
  327. package/dist/tui/index.js +56 -37
  328. package/dist/tui/index.js.map +1 -1
  329. package/dist/tui/src/repl.d.ts +10 -0
  330. package/dist/tui/src/repl.d.ts.map +1 -1
  331. package/dist/types/index.js +1 -1
  332. package/dist/types/src/capabilities.d.ts +3 -2
  333. package/dist/types/src/capabilities.d.ts.map +1 -1
  334. package/dist/types/src/events.d.ts +11 -10
  335. package/dist/types/src/events.d.ts.map +1 -1
  336. package/dist/types/src/index.d.ts +2 -0
  337. package/dist/types/src/index.d.ts.map +1 -1
  338. package/dist/types/src/manifests/preset.d.ts +5 -5
  339. package/dist/types/src/protocol.d.ts +3 -0
  340. package/dist/types/src/protocol.d.ts.map +1 -1
  341. package/dist/types/src/turn-visibility.d.ts +50 -0
  342. package/dist/types/src/turn-visibility.d.ts.map +1 -0
  343. package/dist/types/src/version.d.ts +18 -5
  344. package/dist/types/src/version.d.ts.map +1 -1
  345. package/dist/workspace-plugin/adapters/mcp.js +24 -22
  346. package/dist/workspace-plugin/adapters/omp.js +14 -14
  347. package/dist/workspace-plugin/index.js +1 -1
  348. package/package.json +1 -1
  349. package/dist/chunk-2TLPC6TQ.js.map +0 -1
  350. package/dist/chunk-5XHQBCB5.js.map +0 -1
  351. package/dist/chunk-65UAC3ZR.js.map +0 -1
  352. package/dist/chunk-6ARPZHOV.js.map +0 -1
  353. package/dist/chunk-6SXSVKQY.js.map +0 -1
  354. package/dist/chunk-7PVGND4J.js.map +0 -1
  355. package/dist/chunk-7SJHSGUV.js.map +0 -1
  356. package/dist/chunk-AQNW2FET.js.map +0 -1
  357. package/dist/chunk-BSMW3PX2.js.map +0 -1
  358. package/dist/chunk-DI6J2PJB.js.map +0 -1
  359. package/dist/chunk-DS6UUCFG.js.map +0 -1
  360. package/dist/chunk-E2EC6SAX.js.map +0 -1
  361. package/dist/chunk-EPXZQIC6.js.map +0 -1
  362. package/dist/chunk-F4CZQD3T.js.map +0 -1
  363. package/dist/chunk-G5SYFFMD.js.map +0 -1
  364. package/dist/chunk-J262X4JU.js.map +0 -1
  365. package/dist/chunk-J4WKNJHO.js.map +0 -1
  366. package/dist/chunk-JRVQV7WC.js.map +0 -1
  367. package/dist/chunk-KSH5CFQS.js.map +0 -1
  368. package/dist/chunk-MMOWIRHP.js.map +0 -1
  369. package/dist/chunk-SHTXMERQ.js.map +0 -1
  370. package/dist/chunk-TCH5UDKT.js.map +0 -1
  371. package/dist/chunk-TUFNY6OD.js.map +0 -1
  372. package/dist/chunk-U3UDOX6I.js.map +0 -1
  373. package/dist/chunk-VXYZ5M7Z.js.map +0 -1
  374. package/dist/chunk-XYCYGN3Q.js.map +0 -1
  375. package/dist/chunk-YN6N3RBM.js.map +0 -1
  376. package/dist/ensure-sources-CAMWJTMR.js.map +0 -1
  377. package/dist/library-publish-UQQMHTND.js.map +0 -1
  378. package/dist/serve-preflight-TYEKHC32.js +0 -56
  379. package/dist/setup-4JV2IMCB.js.map +0 -1
  380. package/dist/source-XYMMJVKR.js +0 -86
  381. package/dist/source-manifest-publish-SZFGGKB4.js.map +0 -1
@@ -124,6 +124,23 @@ var MENTION_GROUPS = ["agent", "humans", "humans_here", "here", "all"];
124
124
  var PLATFORM_BLOCKS_RUNTIME_FEATURE = "platformBlocks.v1";
125
125
  var SESSION_ROOT_CONNECTOR_ID = "@session";
126
126
 
127
+ // types/src/turn-visibility.ts
128
+ var TURN_VISIBILITY_EVENT_TYPES = [
129
+ "text",
130
+ "text_retract",
131
+ "tool_call",
132
+ "tool_result",
133
+ "question",
134
+ "question_reply",
135
+ "error",
136
+ "subagent",
137
+ "finished",
138
+ "custom_message",
139
+ "capability_invoked",
140
+ "render_invoked"
141
+ ];
142
+ var TURN_VISIBILITY_RUNTIME_FEATURE = "turnVisibility.v1";
143
+
127
144
  // types/src/reactions.ts
128
145
  var QUICK_REACTIONS = [
129
146
  "\u{1F44D}",
@@ -222,8 +239,8 @@ function withActivityLabelDefs(defs, z) {
222
239
  }
223
240
 
224
241
  // types/src/version.ts
225
- var PROTOCOL_VERSION = { major: 5, minor: 0, patch: 0 };
226
- var PROTOCOL_VERSION_STRING = "5.0.0";
242
+ var PROTOCOL_VERSION = { major: 5, minor: 1, patch: 0 };
243
+ var PROTOCOL_VERSION_STRING = "5.1.0";
227
244
  var RANGED_WRITE_MIN_PROTOCOL = { major: 4, minor: 15, patch: 0 };
228
245
  function parseVersion(s) {
229
246
  const parts = s.split(".");
@@ -243,6 +260,6 @@ function formatVersion(v) {
243
260
  return `${v.major}.${v.minor}.${v.patch}`;
244
261
  }
245
262
 
246
- export { AGENT_RUN_STATUSES, CONNECTOR_ERROR_KINDS, MENTION_GROUPS, PLATFORM_BLOCKS_RUNTIME_FEATURE, PROTOCOL_VERSION, PROTOCOL_VERSION_STRING, QUICK_REACTIONS, RANGED_WRITE_MIN_PROTOCOL, SESSION_ROOT_CONNECTOR_ID, TERMINAL_AGENT_RUN_STATUSES, TOOL_ACTIVITY_LABEL_DESCRIPTION, TOOL_ACTIVITY_LABEL_MAX_CHARS, TOOL_ACTIVITY_LABEL_PARAM, TOOL_ACTIVITY_PROMPT_SECTION, declaresActivityLabel, deliveryClassOf, formatVersion, isRenderCapability, isUserInvokable, parseVersion, stripActivityLabel, withActivityLabelDefs, withActivityLabelJsonSchema, withActivityLabelShape };
247
- //# sourceMappingURL=chunk-G5SYFFMD.js.map
248
- //# sourceMappingURL=chunk-G5SYFFMD.js.map
263
+ export { AGENT_RUN_STATUSES, CONNECTOR_ERROR_KINDS, MENTION_GROUPS, PLATFORM_BLOCKS_RUNTIME_FEATURE, PROTOCOL_VERSION, PROTOCOL_VERSION_STRING, QUICK_REACTIONS, RANGED_WRITE_MIN_PROTOCOL, SESSION_ROOT_CONNECTOR_ID, TERMINAL_AGENT_RUN_STATUSES, TOOL_ACTIVITY_LABEL_DESCRIPTION, TOOL_ACTIVITY_LABEL_MAX_CHARS, TOOL_ACTIVITY_LABEL_PARAM, TOOL_ACTIVITY_PROMPT_SECTION, TURN_VISIBILITY_EVENT_TYPES, TURN_VISIBILITY_RUNTIME_FEATURE, declaresActivityLabel, deliveryClassOf, formatVersion, isRenderCapability, isUserInvokable, parseVersion, stripActivityLabel, withActivityLabelDefs, withActivityLabelJsonSchema, withActivityLabelShape };
264
+ //# sourceMappingURL=chunk-7NN3P6VF.js.map
265
+ //# sourceMappingURL=chunk-7NN3P6VF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../types/src/agent-lifecycle.ts","../types/src/delivery.ts","../types/src/events.ts","../types/src/mentions.ts","../types/src/protocol.ts","../types/src/turn-visibility.ts","../types/src/reactions.ts","../types/src/capabilities.ts","../types/src/tool-activity.ts","../types/src/version.ts"],"names":[],"mappings":";AAwBO,IAAM,kBAAA,GAAqB;AAAA,EAChC,QAAA;AAAA,EACA,SAAA;AAAA,EACA,kBAAA;AAAA,EACA,kBAAA;AAAA,EACA,WAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF;AAIO,IAAM,2BAAA,GAAyD;AAAA,EACpE,WAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF;;;ACZA,IAAM,cAAA,GAAiB;AAAA,EACrB,IAAA,EAAM,WAAA;AAAA;AAAA;AAAA;AAAA,EAIN,YAAA,EAAc,WAAA;AAAA,EACd,SAAA,EAAW,WAAA;AAAA,EACX,WAAA,EAAa,WAAA;AAAA,EACb,QAAA,EAAU,WAAA;AAAA,EACV,KAAA,EAAO,WAAA;AAAA,EACP,UAAA,EAAY,WAAA;AAAA,EACZ,YAAA,EAAc,WAAA;AAAA,EACd,QAAA,EAAU,WAAA;AAAA,EACV,QAAA,EAAU,WAAA;AAAA,EACV,WAAA,EAAa,WAAA;AAAA,EACb,OAAA,EAAS,WAAA;AAAA,EACT,gBAAA,EAAkB,WAAA;AAAA,EAClB,kBAAA,EAAoB,WAAA;AAAA,EACpB,cAAA,EAAgB,WAAA;AAAA,EAChB,gBAAA,EAAkB,WAAA;AAAA,EAClB,WAAA,EAAa,WAAA;AAAA,EACb,aAAA,EAAe,WAAA;AAAA,EACf,UAAA,EAAY,WAAA;AAAA,EACZ,aAAA,EAAe,WAAA;AAAA,EACf,eAAA,EAAiB,WAAA;AAAA,EACjB,aAAA,EAAe,WAAA;AAAA,EACf,iBAAA,EAAmB,WAAA;AAAA,EACnB,YAAA,EAAc,WAAA;AAAA,EACd,kBAAA,EAAoB,WAAA;AAAA,EACpB,cAAA,EAAgB,WAAA;AAAA,EAChB,cAAA,EAAgB,WAAA;AAAA,EAChB,aAAA,EAAe,WAAA;AAAA,EACf,eAAA,EAAiB,WAAA;AAAA,EACjB,WAAA,EAAa,WAAA;AAAA,EACb,eAAA,EAAiB,WAAA;AAAA,EACjB,cAAA,EAAgB,WAAA;AAAA,EAChB,QAAA,EAAU,WAAA;AAAA,EACV,kBAAA,EAAoB,WAAA;AAAA,EACpB,eAAA,EAAiB,WAAA;AAAA,EACjB,gBAAA,EAAkB,WAAA;AAAA,EAClB,aAAA,EAAe,WAAA;AAAA,EACf,mBAAA,EAAqB,WAAA;AAAA,EACrB,qBAAA,EAAuB,WAAA;AAAA,EACvB,kBAAA,EAAoB,WAAA;AAAA,EACpB,cAAA,EAAgB,WAAA;AAAA,EAChB,aAAA,EAAe,WAAA;AAAA,EACf,qBAAA,EAAuB,WAAA;AAAA,EACvB,gBAAA,EAAkB,WAAA;AAAA,EAClB,qBAAA,EAAuB,WAAA;AAAA,EACvB,sBAAA,EAAwB,WAAA;AAAA,EACxB,aAAA,EAAe,WAAA;AAAA,EACf,sBAAA,EAAwB,WAAA;AAAA,EACxB,uBAAA,EAAyB,WAAA;AAAA,EACzB,MAAA,EAAQ,WAAA;AAAA,EACR,KAAA,EAAO,WAAA;AAAA,EACP,MAAA,EAAQ,WAAA;AAAA,EACR,QAAA,EAAU,WAAA;AAAA,EACV,KAAA,EAAO,WAAA;AAAA,EACP,gBAAA,EAAkB,WAAA;AAAA,EAClB,YAAA,EAAc,WAAA;AAAA,EACd,iBAAA,EAAmB,WAAA;AAAA,EACnB,kBAAA,EAAoB,WAAA;AAAA,EAEpB,MAAA,EAAQ,gBAAA;AAAA,EACR,aAAA,EAAe,gBAAA;AAAA,EACf,MAAA,EAAQ,gBAAA;AAAA,EACR,YAAA,EAAc,gBAAA;AAAA;AAAA,EAEd,cAAA,EAAgB,gBAAA;AAAA;AAAA,EAEhB,sBAAA,EAAwB,gBAAA;AAAA;AAAA;AAAA,EAGxB,oBAAA,EAAsB,gBAAA;AAAA,EACtB,mBAAA,EAAqB,gBAAA;AAAA,EACrB,kBAAA,EAAoB,gBAAA;AAAA,EACpB,YAAA,EAAc,gBAAA;AAAA;AAAA,EAEd,SAAA,EAAW,gBAAA;AAAA;AAAA,EAEX,uBAAA,EAAyB,gBAAA;AAAA,EACzB,iBAAA,EAAmB,gBAAA;AAAA;AAAA,EAGnB,gBAAA,EAAkB,SAAA;AAAA,EAClB,gBAAA,EAAkB,SAAA;AAAA,EAClB,eAAA,EAAiB,SAAA;AAAA;AAAA;AAAA,EAGjB,iBAAA,EAAmB,SAAA;AAAA,EACnB,wBAAA,EAA0B,SAAA;AAAA,EAC1B,yBAAA,EAA2B,SAAA;AAAA,EAC3B,UAAA,EAAY,SAAA;AAAA;AAAA;AAAA,EAGZ,iBAAA,EAAmB;AACrB,CAAA;AAQO,SAAS,gBAAgB,IAAA,EAA6B;AAC3D,EAAA,OAAO,OAAO,MAAA,CAAO,cAAA,EAAgB,IAAI,CAAA,GACpC,cAAA,CAAiD,IAAI,CAAA,GACtD,WAAA;AACN;;;ACyzBO,IAAM,qBAAA,GAAwB,CAAC,YAAA,EAAc,YAAA,EAAc,QAAQ;;;AC96BnE,IAAM,iBAAiB,CAAC,OAAA,EAAS,QAAA,EAAU,aAAA,EAAe,QAAQ,KAAK;;;AC2EvE,IAAM,+BAAA,GAAkC;AAkMxC,IAAM,yBAAA,GAA4B;;;ACvPlC,IAAM,2BAAA,GAA8B;AAAA,EACzC,MAAA;AAAA,EACA,cAAA;AAAA,EACA,WAAA;AAAA,EACA,aAAA;AAAA,EACA,UAAA;AAAA,EACA,gBAAA;AAAA,EACA,OAAA;AAAA,EACA,UAAA;AAAA,EACA,UAAA;AAAA,EACA,gBAAA;AAAA,EACA,oBAAA;AAAA,EACA;AACF;AAUO,IAAM,+BAAA,GAAkC;;;AC9BxC,IAAM,eAAA,GAAkB;AAAA,EAC7B,WAAA;AAAA,EACA,WAAA;AAAA,EACA,QAAA;AAAA,EACA,cAAA;AAAA,EACA,WAAA;AAAA,EACA,WAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF;;;AC8LO,SAAS,mBAAmB,GAAA,EAA0C;AAC3E,EAAA,OAAO,IAAI,MAAA,KAAW,MAAA;AACxB;AAsCO,SAAS,gBAAgB,GAAA,EAA0B;AACxD,EAAA,IAAI,GAAA,CAAI,aAAa,MAAA,EAAW;AAC9B,IAAA,OAAO,GAAA,CAAI,QAAA,CAAS,QAAA,CAAS,MAAM,CAAA;AAAA,EACrC;AACA,EAAA,IAAI,GAAA,CAAI,kBAAkB,MAAA,EAAW;AACnC,IAAA,OAAO,GAAA,CAAI,aAAA;AAAA,EACb;AACA,EAAA,QAAQ,GAAA,CAAI,OAAO,IAAA;AAAM,IACvB,KAAK,WAAA;AAAA,IACL,KAAK,QAAA;AAAA,IACL,KAAK,OAAA;AAAA,IACL,KAAK,MAAA;AAAA,IACL,KAAK,WAAA;AAAA,IACL,KAAK,KAAA;AACH,MAAA,OAAO,KAAA;AAAA,IACT,KAAK,KAAA;AACH,MAAA,OAAO,IAAI,IAAA,KAAS,QAAA;AAAA,IACtB,KAAK,OAAA;AACH,MAAA,OAAO,GAAA,CAAI,IAAA,KAAS,QAAA,IAAY,GAAA,CAAI,IAAA,KAAS,QAAA;AAAA,IAC/C;AACE,MAAA,OAAO,KAAA;AAAA;AAEb;;;ACjRO,IAAM,yBAAA,GAA4B;AAGlC,IAAM,6BAAA,GAAgC;AAGtC,IAAM,+BAAA,GACX;AAKK,IAAM,4BAAA,GAA+B;AAAA,EAC1C,8BAAA;AAAA,EACA,EAAA;AAAA,EACA,+BAA+B,yBAAyB,CAAA,2FAAA,CAAA;AAAA,EACxD,sIAAA;AAAA,EACA,qJAAA;AAAA,EACA;AACF,CAAA,CAAE,KAAK,IAAI;AAOJ,SAAS,sBAAA,CACd,OACA,CAAA,EACyB;AACzB,EAAA,IAAI,MAAA,CAAO,MAAA,CAAO,KAAA,EAAO,yBAAyB,GAAG,OAAO,KAAA;AAC5D,EAAA,OAAO;AAAA,IACL,GAAG,KAAA;AAAA,IACH,CAAC,yBAAyB,GAAG,CAAA,CAAE,QAAO,CAAE,QAAA,EAAS,CAAE,QAAA,CAAS,+BAA+B;AAAA,GAC7F;AACF;AAOO,SAAS,4BACd,MAAA,EACyB;AACzB,EAAA,MAAM,IAAA,GAAO,UAAU,EAAC;AACxB,EAAA,IAAI,qBAAA,CAAsB,IAAI,CAAA,EAAG,OAAO,IAAA;AACxC,EAAA,MAAM,KAAA,GAAS,IAAA,CAAK,UAAA,IAAc,EAAC;AACnC,EAAA,OAAO;AAAA,IACL,GAAG,IAAA;AAAA,IACH,UAAA,EAAY;AAAA,MACV,GAAG,KAAA;AAAA,MACH,CAAC,yBAAyB,GAAG,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,+BAAA;AAAgC;AAC9F,GACF;AACF;AAGO,SAAS,sBAAsB,MAAA,EAA0B;AAC9D,EAAA,IAAI,CAAC,MAAA,IAAU,OAAO,MAAA,KAAW,UAAU,OAAO,KAAA;AAClD,EAAA,MAAM,QAAS,MAAA,CAAmC,UAAA;AAClD,EAAA,OAAO,CAAC,CAAC,KAAA,IAAS,OAAO,UAAU,QAAA,IAAY,MAAA,CAAO,MAAA,CAAO,KAAA,EAAO,yBAAyB,CAAA;AAC/F;AAOO,SAAS,mBAAsB,KAAA,EAAa;AACjD,EAAA,IAAI,CAAC,SAAS,OAAO,KAAA,KAAU,YAAY,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG,OAAO,KAAA;AACxE,EAAA,IAAI,CAAC,MAAA,CAAO,MAAA,CAAO,KAAA,EAAO,yBAAyB,GAAG,OAAO,KAAA;AAC7D,EAAA,MAAM,EAAE,CAAC,yBAAyB,GAAG,MAAA,EAAQ,GAAG,MAAK,GAAI,KAAA;AACzD,EAAA,OAAO,IAAA;AACT;AAOO,SAAS,qBAAA,CAEd,MAAW,CAAA,EAAa;AACxB,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,KAAQ;AACvB,IAAA,IAAI,OAAO,MAAA,CAAO,GAAA,CAAI,WAAA,EAAa,yBAAyB,GAAG,OAAO,GAAA;AACtE,IAAA,OAAO;AAAA,MACL,GAAG,GAAA;AAAA,MACH,WAAA,EAAa,sBAAA,CAAuB,GAAA,CAAI,WAAA,EAAa,CAAC,CAAA;AAAA;AAAA,MAEtD,OAAA,EAAS,CAAC,IAAA,EAAA,GAAkB,IAAA,KACzB,GAAA,CAAI,OAAA;AAAA,QACH,mBAAmB,IAAI,CAAA;AAAA,QACvB,GAAG;AAAA;AACL,KACJ;AAAA,EACF,CAAC,CAAA;AACH;;;AC2UO,IAAM,mBAAoC,EAAE,KAAA,EAAO,GAAG,KAAA,EAAO,CAAA,EAAG,OAAO,CAAA;AAUvE,IAAM,uBAAA,GAA0B;AAiBhC,IAAM,4BAA6C,EAAE,KAAA,EAAO,GAAG,KAAA,EAAO,EAAA,EAAI,OAAO,CAAA;AAmBjF,SAAS,aAAa,CAAA,EAA4B;AACvD,EAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,KAAA,CAAM,GAAG,CAAA;AACzB,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,0BAAA,EAA6B,CAAC,CAAA,gCAAA,CAAkC,CAAA;AAAA,EAClF;AACA,EAAA,MAAM,CAAC,GAAA,EAAK,GAAA,EAAK,GAAG,CAAA,GAAI,KAAA;AACxB,EAAA,MAAM,KAAA,GAAQ,OAAO,GAAG,CAAA;AACxB,EAAA,MAAM,KAAA,GAAQ,OAAO,GAAG,CAAA;AACxB,EAAA,MAAM,KAAA,GAAQ,OAAO,GAAG,CAAA;AACxB,EAAA,IACE,CAAC,OAAO,SAAA,CAAU,KAAK,KACvB,CAAC,MAAA,CAAO,UAAU,KAAK,CAAA,IACvB,CAAC,MAAA,CAAO,SAAA,CAAU,KAAK,CAAA,IACvB,KAAA,GAAQ,KACR,KAAA,GAAQ,CAAA,IACR,QAAQ,CAAA,EACR;AACA,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,0BAAA,EAA6B,CAAC,CAAA,4CAAA,CAA8C,CAAA;AAAA,EAC9F;AACA,EAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,KAAA,EAAM;AAC/B;AAiBO,SAAS,cAAc,CAAA,EAA4B;AACxD,EAAA,OAAO,CAAA,EAAG,EAAE,KAAK,CAAA,CAAA,EAAI,EAAE,KAAK,CAAA,CAAA,EAAI,EAAE,KAAK,CAAA,CAAA;AACzC","file":"chunk-7NN3P6VF.js","sourcesContent":["/**\n * Agent instance and run vocabulary shared by the protocol events and the\n * `agent.*` capabilities.\n *\n * An *instance* is an agent asset bound into a workspace under an id\n * (`skaile.yaml` `agents:`); a *run* is one execution of an instance started\n * through `agent.run`. The run controller that owns the full run record builds\n * on these types.\n *\n * @category Lifecycle\n * @since 4.16.0\n */\n\n/** Lifecycle of an agent instance: a long-running identity or a short-lived callable role. */\nexport type AgentInstanceLifecycleKind = \"standing\" | \"role\";\n\n/** Where an instance's memory blocks live. */\nexport type AgentMemoryScopeKind = \"instance\" | \"user\" | \"workspace\" | \"session\";\n\n/**\n * Status of an `agent.run` run.\n *\n * `queued → running → (waiting_approval | waiting_children)* → succeeded | failed | cancelled`.\n */\nexport const AGENT_RUN_STATUSES = [\n \"queued\",\n \"running\",\n \"waiting_approval\",\n \"waiting_children\",\n \"succeeded\",\n \"failed\",\n \"cancelled\",\n] as const;\nexport type AgentRunStatus = (typeof AGENT_RUN_STATUSES)[number];\n\n/** A status no run leaves again. */\nexport const TERMINAL_AGENT_RUN_STATUSES: readonly AgentRunStatus[] = [\n \"succeeded\",\n \"failed\",\n \"cancelled\",\n];\n\n/**\n * One agent instance of the workspace, as a client renders it in a picker.\n * Carried on `session_init_ack.instances` and returned by `agent.list`.\n *\n * @category Lifecycle\n * @since 4.16.0\n */\nexport type AgentInstanceSummary = {\n /** Instance id (`default` for the primary `agent:`). */\n id: string;\n /** `agents.<id>.ref` as written. */\n ref: string;\n lifecycle: AgentInstanceLifecycleKind;\n description?: string;\n /** SHA-256 of the resolved instance; absent when the instance failed to resolve. */\n revisionHash?: string;\n /** Roles only: which JSON-Schema roots the agent declares. */\n io?: { input: boolean; output: boolean };\n /** `ready` = can be started; `unavailable` = the asset did not resolve (`error` says why). */\n status: \"ready\" | \"unavailable\";\n error?: string;\n};\n\n// ---------------------------------------------------------------------------\n// Host contract: what a host implements behind the three `host.*` capabilities\n// ---------------------------------------------------------------------------\n\n/** Why a call or a run did not succeed. */\nexport type AgentRunFailure = {\n code: string;\n message: string;\n /** Validation problems (JSON-Schema paths) when `code` is `input_invalid` or `output_invalid`. */\n issues?: string[];\n};\n\n/** The state of one run as `agent.run` / `agent.status` / `agent.result` report it. */\nexport type AgentRunReport = {\n runId: string;\n status: AgentRunStatus;\n /** The role's output once `succeeded` (validated against `io.output`). */\n output?: unknown;\n error?: AgentRunFailure;\n /** Set while `status` is `waiting_approval`: decide it with `approval.decide`. */\n approvalId?: string;\n /** Set with `approvalId`: the one operation the approval releases. */\n operationId?: string;\n};\n\n/** A host's answer when a request fails as a domain error (unknown run, not allowed, store error). */\nexport type HostFailure = { ok: false; code: string; message: string; issues?: string[] };\n\n/**\n * Requests the runner sends to `host.agent_run`. The host spawns, tracks,\n * cancels and approves runs; the runner has already checked that the\n * instance exists and that `input` matches the role's `io.input`. The host\n * MUST validate again, enforce `approval: \"required\"` (one approval per\n * operation, replayable once), apply `budget`, and answer every `start` for\n * the same `callId` with the same `runId`.\n */\nexport type HostAgentRunRequest =\n | {\n op: \"start\";\n instanceId: string;\n /** Revision of the resolved instance the runner saw; the host runs that revision or fails. */\n revisionHash?: string;\n input?: unknown;\n /** `sync` answers when the run ends; `async` answers as soon as it is queued. */\n mode: \"sync\" | \"async\";\n budget?: { max_turns?: number; max_tokens?: number };\n /** Capability-dispatch call id; the idempotency key of the start. */\n callId: string;\n callerSessionId: string;\n callerInstanceId: string;\n approval: \"required\" | \"none\";\n }\n | { op: \"status\" | \"cancel\"; runId: string; callerSessionId: string }\n | { op: \"result\"; runId: string; wait: boolean; callerSessionId: string }\n | {\n op: \"decide_approval\";\n approvalId: string;\n decision: \"approve\" | \"deny\";\n callerSessionId: string;\n };\nexport type HostAgentRunReply = AgentRunReport | HostFailure;\n\n/** A memory block as the runner declares it to the host store. */\nexport type HostMemoryBlockRef = { name: string; scope: AgentMemoryScopeKind; maxChars: number };\n\n/**\n * Requests the runner sends to `host.memory_store`. The host owns storage,\n * enforces `maxChars` and scope, and applies its own pending → confirmed policy.\n */\nexport type HostMemoryStoreRequest =\n | { op: \"read\"; instanceId: string; block: HostMemoryBlockRef }\n | { op: \"write\" | \"append\"; instanceId: string; block: HostMemoryBlockRef; content: string }\n | { op: \"list\"; instanceId: string; blocks: HostMemoryBlockRef[] }\n /** Current content of every block, read once when a session is built. */\n | { op: \"snapshot\"; instanceId: string; blocks: HostMemoryBlockRef[] };\nexport type HostMemoryStoreReply =\n | {\n ok: true;\n /** `read`: the block's content. */\n content?: string;\n /** `write` / `append`: the block's size after the change. */\n chars?: number;\n /** `write` / `append`: `pending` when the host holds the change for review. */\n status?: \"confirmed\" | \"pending\";\n /** `list`: sizes of the blocks the host holds. */\n blocks?: Array<{ name: string; chars: number }>;\n /** `snapshot`: block name → content. */\n snapshot?: Record<string, string>;\n }\n | HostFailure;\n\n/** A trigger as the host schedules it. */\nexport type HostTrigger = {\n id: string;\n kind: \"schedule\" | \"webhook\" | \"channel\" | \"event\";\n cron?: string;\n prompt?: string;\n timezone?: string;\n /** `channel` triggers. */\n when?: string;\n /** `event` triggers. */\n event?: string;\n enabled: boolean;\n /** `asset` = the agent asset's default, `workspace` = the instance's `skaile.yaml` entry, `runtime` = added through `trigger.upsert`. */\n source: \"asset\" | \"workspace\" | \"runtime\";\n nextRunAt?: string;\n};\n\n/**\n * Requests the runner sends to `host.trigger_store`. `upsert` and `toggle`\n * carry `approval: \"required\"`: the host MUST gate them behind a user approval.\n */\nexport type HostTriggerStoreRequest =\n | { op: \"list\"; instanceId: string }\n | {\n op: \"upsert\";\n instanceId: string;\n trigger: Omit<HostTrigger, \"source\" | \"nextRunAt\" | \"enabled\"> & { enabled?: boolean };\n approval: \"required\";\n }\n | { op: \"toggle\"; instanceId: string; triggerId: string; enabled: boolean; approval: \"required\" };\nexport type HostTriggerStoreReply =\n | { ok: true; triggers?: HostTrigger[]; trigger?: HostTrigger }\n | HostFailure;\n\n// ---------------------------------------------------------------------------\n// Run record and store: what the run controller persists\n// ---------------------------------------------------------------------------\n\n/** Why a run left `running` for a `queued` that is not its first start. */\nexport type AgentRunResumeReason = \"approval\" | \"children\";\n\n/**\n * One execution of an agent instance, as the run controller records it.\n *\n * `attempt` is 1 for every run in this release; a retrying worker raises it.\n * `sessionId` is the id of the run's own native session and is assigned when\n * the run is created, so a session can be mapped back to its run before it exists.\n *\n * @category Lifecycle\n * @since 4.16.0\n */\nexport type AgentRun = {\n id: string;\n workspaceId: string;\n instanceId: string;\n /** Revision of the resolved instance the run executes; `null` when the host resolves none. */\n revisionHash: string | null;\n /** The actor (user or service) the run is accountable to; set by the host, never by the model. */\n requestedBy: string;\n /** The run at the top of the delegation tree; its own id for a run started outside any run. */\n rootRunId: string;\n /** The run whose session started this one; `null` for a root run. */\n parentRunId: string | null;\n /** Session that dispatched the start; with `callId` the idempotency key of the start. */\n callerSessionId: string | null;\n callId: string | null;\n sessionId: string;\n /** Harness the run executed on; `null` until it is first launched. */\n harness: string | null;\n status: AgentRunStatus;\n attempt: number;\n /** What the next launch of a resumed run delivers; `null` for a run that was not suspended. */\n resumeReason: AgentRunResumeReason | null;\n budget?: { max_turns?: number; max_tokens?: number };\n input: unknown;\n output?: unknown;\n error?: AgentRunFailure;\n createdAt: string;\n /** When the run first reached `running`; `null` while it has never started. */\n startedAt: string | null;\n updatedAt: string;\n};\n\n/** The fields of a run a transition may change. */\nexport type AgentRunPatch = Partial<\n Pick<AgentRun, \"status\" | \"harness\" | \"resumeReason\" | \"startedAt\" | \"output\" | \"error\">\n> & { updatedAt: string };\n\n/** `start` holds the run itself behind an approval; `operation` holds one capability call a running run made. */\nexport type AgentApprovalKind = \"start\" | \"operation\";\n\n/** `pending → approved | denied`, or `pending → expired` when the run ends first. Never leaves a decided state. */\nexport type AgentApprovalState = \"pending\" | \"approved\" | \"denied\" | \"expired\";\n\n/**\n * A persisted approval: the one operation a decision releases.\n *\n * `args` are what executes on approval; `argsHash` (SHA-256 of their canonical\n * JSON) is what a replay is checked against. `result` / `error` are set once the\n * operation ran; `deliveredAt` once the session has been told.\n *\n * @category Lifecycle\n * @since 4.16.0\n */\nexport type AgentApproval = {\n id: string;\n runId: string;\n operationId: string;\n kind: AgentApprovalKind;\n /** Capability name of the held call (`agent.run` for a `start` approval). */\n capability: string;\n /** Capability-dispatch call id of the held call, when the session supplied one. */\n callId: string | null;\n args: unknown;\n argsHash: string;\n state: AgentApprovalState;\n decidedBy: string | null;\n decidedAt: string | null;\n result?: unknown;\n error?: AgentRunFailure;\n executedAt: string | null;\n deliveredAt: string | null;\n createdAt: string;\n};\n\n/** The fields of an approval a decision or its follow-up may change. */\nexport type AgentApprovalPatch = Partial<\n Pick<\n AgentApproval,\n \"state\" | \"decidedBy\" | \"decidedAt\" | \"result\" | \"error\" | \"executedAt\" | \"deliveredAt\"\n >\n>;\n\n/**\n * One row of a run's append-only event log (`agent_run_events`). A host\n * persists these, broadcasts them after they are persisted, and replays\n * those after a sequence cursor to a client that reconnects.\n *\n * @category Lifecycle\n * @since 4.16.0\n */\nexport type AgentRunEvent =\n | {\n type: \"run_state\";\n status: AgentRunStatus;\n /** `null` for the run's creation. */\n previous: AgentRunStatus | null;\n instanceId: string;\n rootRunId: string;\n parentRunId: string | null;\n attempt: number;\n /** Set with `waiting_approval`: the approval the run waits on. */\n approvalId?: string;\n operationId?: string;\n error?: AgentRunFailure;\n }\n | {\n type: \"approval\";\n approvalId: string;\n operationId: string;\n kind: AgentApprovalKind;\n capability: string;\n state: AgentApprovalState;\n decidedBy?: string;\n }\n | {\n type: \"operation_result\";\n approvalId: string;\n operationId: string;\n outcome: \"completed\" | \"failed\";\n };\n\n/** An {@link AgentRunEvent} with the position the store gave it. `seq` counts from 1 within one run. */\nexport type AgentRunEventRecord = {\n runId: string;\n seq: number;\n at: string;\n event: AgentRunEvent;\n};\n\n/** Which runs {@link RunStore.listRuns} returns; every given field must match. */\nexport type AgentRunFilter = {\n rootRunId?: string;\n parentRunId?: string;\n instanceId?: string;\n statuses?: readonly AgentRunStatus[];\n};\n\n/**\n * Where the run controller keeps runs, their event log and approvals. A host\n * with durable storage implements it over its database; {@link\n * createInMemoryRunStore} (`@skaile/workspaces/runner`) is the in-process one\n * for tests and the CLI.\n *\n * The two `transition*` methods are compare-and-set: they apply the patch only\n * if the row is still in an expected state and answer `undefined` otherwise.\n * That is what makes a decision, a cancel and a resume race-safe: of two\n * concurrent attempts exactly one wins.\n *\n * @category Lifecycle\n * @since 4.16.0\n */\nexport interface RunStore {\n /** Insert a run; when its `(callerSessionId, callId)` pair already exists, answer that run with `created: false`. */\n insertRun(run: AgentRun): Promise<{ run: AgentRun; created: boolean }>;\n getRun(id: string): Promise<AgentRun | undefined>;\n /** Apply `patch` if the run's status is one of `from`; answer the updated run, or `undefined` when it was not. */\n transitionRun(\n id: string,\n from: readonly AgentRunStatus[],\n patch: AgentRunPatch,\n ): Promise<AgentRun | undefined>;\n findRunByDispatch(callerSessionId: string, callId: string): Promise<AgentRun | undefined>;\n findRunBySession(sessionId: string): Promise<AgentRun | undefined>;\n listRuns(filter: AgentRunFilter): Promise<AgentRun[]>;\n /** Append to a run's log; the store assigns `seq`. */\n appendEvent(runId: string, event: AgentRunEvent, at: string): Promise<AgentRunEventRecord>;\n listEvents(runId: string, afterSeq?: number): Promise<AgentRunEventRecord[]>;\n insertApproval(approval: AgentApproval): Promise<void>;\n getApproval(id: string): Promise<AgentApproval | undefined>;\n /** The approval a run's held call `callId` produced, if any. */\n findApprovalByCall(runId: string, callId: string): Promise<AgentApproval | undefined>;\n listApprovals(runId: string): Promise<AgentApproval[]>;\n /** Apply `patch` if the approval's state is `from`; answer the updated approval, or `undefined` when it was not. */\n transitionApproval(\n id: string,\n from: AgentApprovalState,\n patch: AgentApprovalPatch,\n ): Promise<AgentApproval | undefined>;\n}\n\n/**\n * What a suspended run's session is told when it resumes. It reaches the\n * model as a host message through the ordinary prompt path.\n *\n * @category Lifecycle\n * @since 4.16.0\n */\nexport type RunHostMessage =\n | {\n type: \"approval_result\";\n operationId: string;\n /** `completed`: the operation ran (`result`); `failed`: it threw (`error`); `denied`: it never ran. */\n status: \"completed\" | \"failed\" | \"denied\";\n result?: unknown;\n error?: AgentRunFailure;\n }\n | {\n type: \"children_finished\";\n children: Array<{\n runId: string;\n instanceId: string;\n status: AgentRunStatus;\n output?: unknown;\n error?: AgentRunFailure;\n }>;\n };\n","/**\n * Delivery class of every type that crosses the session wire.\n *\n * Hosts and the runner decide what to store and whom to tell from this one\n * table. A type added to {@link AgentEvent} or {@link AgentCommand} without an\n * entry here fails to compile, so a new acknowledgement cannot silently be\n * stored as a chat message.\n */\n\nimport type { AgentEvent } from \"./events.js\";\nimport type { AgentCommand } from \"./protocol.js\";\n\n/**\n * What happens to a payload on the session wire.\n *\n * - `persisted`: stored as a chat message, then sent to every subscriber.\n * - `broadcast-only`: sent to every subscriber, never stored.\n * - `private`: neither stored nor sent to subscribers. An event answers one\n * request, and its issuer reads it off the agent client. A command goes to\n * the agent alone.\n */\nexport type DeliveryClass = \"persisted\" | \"broadcast-only\" | \"private\";\n\ntype WireType = AgentEvent[\"type\"] | AgentCommand[\"type\"];\n\n// `satisfies Record<WireType, …>` rejects both a missing and an unknown key.\n// Types shared by an event and a command (`capability_result`, …) have one\n// class for both directions.\nconst DELIVERY_CLASS = {\n text: \"persisted\",\n // Persisted on purpose: a host store that buffers streamed `text` must see\n // the retraction to cut the fragment before commit; unclassified, it would\n // commit the fragment instead.\n text_retract: \"persisted\",\n tool_call: \"persisted\",\n tool_result: \"persisted\",\n question: \"persisted\",\n error: \"persisted\",\n dev_server: \"persisted\",\n file_changed: \"persisted\",\n subagent: \"persisted\",\n finished: \"persisted\",\n a2a_message: \"persisted\",\n handoff: \"persisted\",\n connector_status: \"persisted\",\n lifecycle_complete: \"persisted\",\n reaction_added: \"persisted\",\n reaction_removed: \"persisted\",\n sync_status: \"persisted\",\n secrets_ready: \"persisted\",\n configured: \"persisted\",\n mount_mounted: \"persisted\",\n mount_unmounted: \"persisted\",\n mount_changed: \"persisted\",\n mount_sync_status: \"persisted\",\n debug_result: \"persisted\",\n validation_warning: \"persisted\",\n skills_changed: \"persisted\",\n memory_changed: \"persisted\",\n trigger_fired: \"persisted\",\n flow_breadcrumb: \"persisted\",\n flow_prompt: \"persisted\",\n resource_status: \"persisted\",\n custom_message: \"persisted\",\n snapshot: \"persisted\",\n compaction_attempt: \"persisted\",\n runtime_session: \"persisted\",\n resume_attempted: \"persisted\",\n resume_failed: \"persisted\",\n capability_register: \"persisted\",\n capability_deregister: \"persisted\",\n capability_invoked: \"persisted\",\n render_invoked: \"persisted\",\n protocol_info: \"persisted\",\n incompatible_protocol: \"persisted\",\n session_init_ack: \"persisted\",\n session_init_mismatch: \"persisted\",\n system_prompt_composed: \"persisted\",\n context_usage: \"persisted\",\n provider_response_seen: \"persisted\",\n provider_quota_observed: \"persisted\",\n prompt: \"persisted\",\n reply: \"persisted\",\n cancel: \"persisted\",\n shutdown: \"persisted\",\n debug: \"persisted\",\n connector_config: \"persisted\",\n state_update: \"persisted\",\n get_context_usage: \"persisted\",\n capability_approve: \"persisted\",\n\n status: \"broadcast-only\",\n state_changed: \"broadcast-only\",\n typing: \"broadcast-only\",\n user_message: \"broadcast-only\",\n // The runner's echo of an accepted `reply`; the command is already stored.\n question_reply: \"broadcast-only\",\n // Every client must hear it to mark those prompts \"Not sent\".\n queued_prompts_dropped: \"broadcast-only\",\n // A late refusal of an `ok` reconfigure; every client must hear it to show\n // the restart-required cue.\n reconfigure_rejected: \"broadcast-only\",\n resources_available: \"broadcast-only\",\n commands_available: \"broadcast-only\",\n session_info: \"broadcast-only\",\n // High volume; stored in the per-session log store instead.\n log_entry: \"broadcast-only\",\n // Turn-attribution signals for the host's own bookkeeping, not conversation.\n background_task_started: \"broadcast-only\",\n self_turn_started: \"broadcast-only\",\n\n // Flow and connector RPC are system traffic, not conversation.\n resource_request: \"private\",\n connector_mutate: \"private\",\n connector_query: \"private\",\n // A `resource_response` carries a whole file base64-encoded; sending it to\n // every stream ran a host out of heap.\n resource_response: \"private\",\n connector_query_response: \"private\",\n connector_mutate_response: \"private\",\n prompt_ack: \"private\",\n // The runner answers a host-sent `capability_invoked` with this event on the\n // same wire, though it is not in the `AgentEvent` union.\n capability_result: \"private\",\n} satisfies Record<WireType, DeliveryClass>;\n\n/**\n * The delivery class of a payload `type` read off the wire.\n *\n * A type this build does not know (a newer runner's event) is `persisted`: a\n * host that cannot classify an event keeps it rather than dropping it.\n */\nexport function deliveryClassOf(type: string): DeliveryClass {\n return Object.hasOwn(DELIVERY_CLASS, type)\n ? (DELIVERY_CLASS as Record<string, DeliveryClass>)[type]\n : \"persisted\";\n}\n","/**\n * Agent Events — the unified event stream.\n *\n * These are the real-time events emitted by agent harnesses (bridge, vm-agent)\n * and consumed by runners, gateways, and frontends. Persistent events are\n * wrapped in a {@link Message} envelope by the host's persistence layer.\n */\n\nimport type {\n CapabilityDeregisterEvent,\n CapabilityInvokedEvent,\n CapabilityRegisterEvent,\n RenderInvokedEvent,\n} from \"./capabilities.js\";\nimport type { TurnVisibility } from \"./turn-visibility.js\";\nimport type { AgentMemoryScopeKind, AgentRunStatus } from \"./agent-lifecycle.js\";\nimport type {\n IncompatibleProtocolEvent,\n ProtocolInfoEvent,\n SessionInitAckEvent,\n SessionInitMismatchEvent,\n} from \"./lifecycle.js\";\nimport type { ContextUsageSnapshot } from \"./context-usage.js\";\nimport type { LogEntry } from \"./logging.js\";\n\n// ---------------------------------------------------------------------------\n// Agent event — discriminated union of all event types\n// ---------------------------------------------------------------------------\n\n/**\n * Discriminated union of every event the Skaile agent runtime can emit.\n *\n * Persistent events are wrapped in a `MessageV2` envelope by the host's persistence\n * layer. Transient events are forwarded over the transport but not appended to the\n * message store. Narrow via `event.type` or a `switch` statement.\n *\n * @docLink packages/types/events#agent-event\n */\nexport type AgentEvent =\n | TextEvent\n | TextRetractEvent\n | ToolCallEvent\n | ToolResultEvent\n | QuestionEvent\n | QuestionReplyEvent\n | ErrorEvent\n | StatusEvent\n | DevServerEvent\n | FileChangeEvent\n | SubagentEvent\n | MemoryChangedEvent\n | TriggerFiredEvent\n | FinishedEvent\n | A2AMessageEvent\n | StateChangedEvent\n | HandoffEvent\n | ConnectorResponseEvent\n | ConnectorQueryResponseEvent\n | ConnectorMutateResponseEvent\n | PromptAckEvent\n | ReconfigureRejectedEvent\n | QueuedPromptsDroppedEvent\n | ConnectorsAvailableEvent\n | LifecycleCompleteEvent\n | TypingEvent\n | UserMessageEvent\n | SyncStatusEvent\n | SecretsReadyEvent\n | ConfiguredEvent\n | MountMountedEvent\n | MountUnmountedEvent\n | MountChangedEvent\n | MountSyncStatusEvent\n | DebugResultEvent\n | LogEntryEvent\n | ValidationWarningEvent\n | SkillsChangedEvent\n | CommandsAvailableEvent\n | FlowBreadcrumbEvent\n | FlowPromptEvent\n | SessionInfoEvent\n | ReactionAddedEvent\n | ReactionRemovedEvent\n | ResourceStatusEvent\n | ConnectorStatusEvent\n | CustomMessageEvent\n | SnapshotEvent\n | CompactionAttemptEvent\n | RuntimeSessionEvent\n | ResumeAttemptedEvent\n | ResumeFailedEvent\n // Protocol v2 capability + lifecycle events\n | CapabilityRegisterEvent\n | CapabilityDeregisterEvent\n | CapabilityInvokedEvent\n | RenderInvokedEvent\n | ProtocolInfoEvent\n | IncompatibleProtocolEvent\n // Protocol v3 session_init lifecycle events\n | SessionInitAckEvent\n | SessionInitMismatchEvent\n // Agent prompt composition (system_prompt_composed)\n | SystemPromptComposedEvent\n // Context window breakdown (context_usage)\n | ContextUsageEvent\n // Live AI-provider health telemetry (401 / 429 attribution)\n | ProviderResponseSeenEvent\n // Live AI-provider quota-window readings\n | ProviderQuotaObservedEvent\n // Self-started turns and the background tasks that wake them\n | BackgroundTaskStartedEvent\n | SelfTurnStartedEvent;\n\n/**\n * A text message from the agent to the user.\n *\n * The most common event type, containing plain-text content generated by the agent.\n *\n * @docLink packages/types/events#text-event\n */\nexport type TextEvent = TurnVisibility & {\n type: \"text\";\n content: string;\n};\n\n/**\n * Takes back text the agent already streamed as {@link TextEvent}s.\n *\n * Sent when the harness abandons an attempt mid-message and replays the prompt\n * (a lost-transcript resume, an auth refresh, a seat failover): the replay\n * streams the reply afresh, so the half-message the failed attempt left behind\n * would otherwise sit in front of it. `content` is exactly the text to remove\n * and is always a suffix of what the consumer has accumulated since the last\n * boundary it committed. A consumer that already committed that text (or holds\n * something else) should leave it alone rather than cut unrelated prose.\n *\n * Only unfinished text is ever retracted — a message the model completed is\n * part of the transcript the replay resumes from and stays.\n *\n * @since protocol 4.3.0\n * @docLink packages/types/events#text-retract-event\n */\nexport type TextRetractEvent = TurnVisibility & {\n type: \"text_retract\";\n content: string;\n};\n\n/**\n * A tool call request from the agent.\n *\n * Indicates the agent wants to invoke a tool with the given name and input arguments.\n * The platform should execute the tool and return the result via {@link ToolResultEvent}.\n *\n * @property tool - The name of the tool to invoke (must match a registered tool)\n * @property input - The input arguments to pass to the tool (structure depends on the tool)\n * @property summary - Short technical summary of the tool call (e.g. `$ git status`)\n * @property label - Plain-language description of the call for non-technical\n * users: the agent's own `activity_label` (Bash: `description`), else a\n * derived phrase for built-in tools. Absent when neither is available.\n *\n * @see {@link TextEvent} for plain text messages\n * @see {@link ToolResultEvent} for tool execution results\n * @category Events\n * @since 1.0.0\n * @docLink packages/types/events#tool-call-event\n */\nexport type ToolCallEvent = TurnVisibility & {\n type: \"tool_call\";\n tool: string;\n input: unknown;\n summary: string;\n /** @since 3.24.0 */\n label?: string;\n /**\n * The tool use that runs the subagent which made this call. Absent on the\n * main thread. Such a call runs concurrently with the main reply, so it\n * does not split that reply's text.\n * @since protocol 4.5.0\n */\n parentToolUseId?: string;\n};\n\n/**\n * The result of a tool execution.\n *\n * Contains the output returned by a tool after it has been executed.\n * This event is typically sent by the platform in response to a {@link ToolCallEvent}.\n *\n * @property tool - The name of the tool that was executed\n * @property output - The result data returned by the tool (structure depends on the tool)\n * @property summary - Short human-readable summary of the result\n *\n * @see {@link ToolCallEvent} for the corresponding tool invocation\n * @category Events\n * @since 1.0.0\n * @docLink packages/types/events#tool-result-event\n */\nexport type ToolResultEvent = TurnVisibility & {\n type: \"tool_result\";\n tool: string;\n output: unknown;\n summary: string;\n /**\n * The tool use that runs the subagent this result belongs to. Absent on the main thread.\n * @since protocol 4.5.0\n */\n parentToolUseId?: string;\n};\n\n/**\n * A question posed by the agent to the user.\n *\n * Used when the agent needs clarification or input from the user to proceed.\n * The question may include multiple-choice options to guide the user's response.\n *\n * @property question - The question text to display to the user\n * @property options - Optional array of suggested answers (when provided, user should select one)\n *\n * @see {@link QuestionReplyEvent} for the user's response\n * @category Events\n * @since 1.0.0\n * @docLink packages/types/events#question-event\n */\n/** Durable native approval presentation, never tool identity or permission authority. */\nexport type NativeApprovalDescription = {\n kind: \"command\" | \"file\" | \"permissions\" | \"mcp\";\n details: string[];\n};\n\nexport type QuestionEvent = TurnVisibility & {\n /** Opaque correlated request identity; managed replies must echo it unchanged. */\n requestId?: string;\n /** Fixed Approve once/Deny card; clients must preserve this request's exact identity. */\n approval?: NativeApprovalDescription;\n type: \"question\";\n question: string;\n options?: string[];\n};\n\n/**\n * A question was answered.\n *\n * The runner emits it to every attached client once the paused turn accepted a\n * `reply`, so clients that did not send the reply can drop their question card.\n * It echoes the reply's own `question` / `requestId` when the reply carried\n * them, so a client can tell which of several open questions was answered.\n *\n * @property answer - The user's response text\n * @property question - The sub-question answered, verbatim, when the reply named one (protocol 4.8.0)\n * @property requestId - The answered request's identity, when the reply carried one (protocol 4.8.0)\n *\n * @see {@link QuestionEvent} for the original question\n * @category Events\n * @since 1.0.0\n * @docLink packages/types/events#question-event\n */\nexport type QuestionReplyEvent = TurnVisibility & {\n type: \"question_reply\";\n answer: string;\n question?: string;\n requestId?: string;\n};\n\n/**\n * An error condition encountered during agent execution.\n *\n * Indicates something went wrong during the agent's operation.\n * The severity determines whether execution can continue.\n *\n * @property message - Human-readable description of the error\n * @property fatal - When true, indicates the error is unrecoverable and execution should stop\n *\n * @category Events\n * @since 1.0.0\n * @docLink packages/types/events#error-event\n */\n\nexport type ErrorEvent = TurnVisibility & {\n type: \"error\";\n message: string;\n fatal: boolean;\n category?: ErrorCategory;\n /**\n * Short actionable advice for display to the user. Set by the bridge's\n * error classifier when it recognises the upstream failure mode (e.g.\n * \"Quota exhausted on the configured Anthropic account — try again\n * after the rate-limit window resets\"). Optional.\n */\n hint?: string;\n /**\n * Usage of the turn that ended in this error, present only when the error\n * is a turn result (`error_max_turns`, `error_during_execution`, …) and the\n * harness tracked usage. The provider bills the turn either way; a consumer\n * that ledgers `finished` should ledger these too. Same fields and meaning\n * as on {@link FinishedEvent}. Absent on errors that are not a turn result.\n * Added in 3.12.0.\n */\n costUsd?: number;\n /** Main-thread token usage of the failed turn. See {@link FinishedEvent.tokens}. Added in 3.12.0. */\n tokens?: TokenUsage;\n /** Per-model usage of the failed turn. See {@link FinishedEvent.modelUsage}. Added in 3.12.0. */\n modelUsage?: Record<string, ModelTokenUsage>;\n /** Context fill of the failed turn. See {@link FinishedEvent.contextTokens}. Added in 3.12.0. */\n contextTokens?: number;\n /** Context window of the main model. See {@link FinishedEvent.contextWindow}. Added in 3.12.0. */\n contextWindow?: number;\n /**\n * `true` when the harness is about to replay the same prompt in place, with no\n * `status: idle` / `finished` in between. Such an error does NOT end the turn:\n * the replayed attempt is the same turn, with the same starter, and it ends\n * with its own `finished` or `error`. Always sent with `fatal: false`; absent\n * on every other error. A 4.9 runner never sets it. Added in 4.10.0.\n */\n retrying?: boolean;\n /** Why the prompt is replayed; present only with `retrying`. Added in 4.10.0. */\n retryReason?: ErrorRetryReason;\n /**\n * `true` when the error is the result of a turn the runner did not dispatch\n * (see {@link SelfTurnStartedEvent}). Such an error ends no host-sent turn.\n * A failure surfacing only after that turn's `result` (the process exiting\n * later) arrives unstamped. Added in 4.19.0.\n */\n selfStarted?: true;\n};\n\n/**\n * Why the harness replays a prompt in place after an {@link ErrorEvent}:\n * - `stale_resume`: the resumed transcript was lost; the prompt runs again on\n * a fresh session (a `resume_failed { jsonl_lost }` precedes it harness-side).\n * - `poison_scrub`: the resumed transcript held a block the API rejects; it was\n * repaired on disk and the same session is resumed again.\n *\n * Consumers must accept unknown values: new retry paths add members.\n *\n * @category Events\n * @since 4.10.0\n */\nexport type ErrorRetryReason = \"stale_resume\" | \"poison_scrub\";\n\n/**\n * A status change notification for the agent.\n *\n * Emitted when the agent's execution phase changes (e.g., thinking → working → idle).\n *\n * @see {@link AgentPhase} for available phase values\n * @category Events\n * @since 1.0.0\n * @docLink packages/types/events#supporting-types\n */\nexport type StatusEvent = {\n type: \"status\";\n phase: AgentPhase;\n};\n\n/**\n * Emitted when a dev server (e.g. Vite, Next.js) starts, becomes ready, or crashes.\n *\n * The platform uses this to surface a preview URL in the session UI.\n *\n * @category Events\n * @since 1.0.0\n * @docLink packages/types/events#agent-event\n */\nexport type DevServerEvent = {\n type: \"dev_server\";\n url: string;\n status: \"starting\" | \"ready\" | \"crashed\";\n};\n\n/**\n * A file system change event.\n *\n * Emitted when files are created, edited, deleted, or conflicted.\n *\n * @property type - Always \"file_changed\"\n * @property path - The file path that changed\n * @property action - What happened: create, edit, delete, or conflict\n * @property mountId - Which mount triggered the change, if any\n *\n * @category Events\n * @since 1.0.0\n * @docLink packages/types/events#file-change-event\n */\n\nexport type FileChangeEvent = {\n type: \"file_changed\";\n path: string;\n action: \"create\" | \"edit\" | \"delete\" | \"conflict\";\n /** Which mount triggered the change, if any. */\n mountId?: string;\n};\n\n/**\n * Status update for a subagent dispatched by the primary agent.\n *\n * Emitted when a named subagent starts or finishes execution. On \"finished\",\n * carries structured output with a summary, changed files, and concerns.\n *\n * @docLink packages/types/events#agent-event\n */\nexport type SubagentEvent = TurnVisibility & {\n type: \"subagent\";\n name: string;\n status: \"started\" | \"finished\";\n description: string;\n /** Flow node this subagent is executing (set by orchestrator) */\n nodeId?: string;\n /**\n * Structured output of a harness-native subagent (set on \"finished\"). Unchanged since 1.x;\n * an `agent.run` run carries its output in {@link SubagentEvent.result} instead.\n */\n output?: {\n summary: string;\n filesChanged: string[];\n status: string;\n concerns: string[];\n };\n /**\n * Typed output of an `agent.run` run, validated against the role's `io.output` schema (set on\n * \"finished\" when the run succeeded; since 4.16.0). Absent for a harness-native subagent.\n */\n result?: unknown;\n /** `agent.run` run this event belongs to (since 4.16.0). Absent for a harness-native subagent. */\n runId?: string;\n /** Instance the run executes (since 4.16.0). */\n instanceId?: string;\n /** The input the run was started with (set on \"started\"; since 4.16.0). */\n input?: unknown;\n /** Final status of the run (set on \"finished\"; since 4.16.0). */\n runStatus?: AgentRunStatus;\n /** Why the run did not succeed (set on \"finished\" when `runStatus` is not `succeeded`; since 4.16.0). */\n error?: { code: string; message: string };\n};\n\n/**\n * A memory block of an agent instance changed.\n *\n * Emitted by the runner after a `memory.write` / `memory.append` call the host\n * accepted, and by a host that changes a block by another route (a memory\n * review, a consolidation). The block's content is not part of the event:\n * read it with `memory.read` or from the host's store.\n *\n * @category Events\n * @since 4.16.0\n * @docLink packages/types/events#agent-event\n */\nexport type MemoryChangedEvent = {\n type: \"memory_changed\";\n /** Instance whose block changed. */\n instanceId: string;\n /** Block name, as declared in `memory.blocks`. */\n block: string;\n scope: AgentMemoryScopeKind;\n /** Who made the change: the agent through a capability, a user, or the host itself. */\n by: \"agent\" | \"user\" | \"host\";\n};\n\n/**\n * A trigger of an agent instance fired and started (or queued) a run.\n *\n * The host schedules triggers (`schedule`, `webhook`, `channel`, `event`), so\n * the host emits this event when it delivers the trigger's prompt; the\n * runner defines the shape only. `source` reuses the trigger kinds of the\n * asset (`schedule | webhook | channel | event`).\n *\n * @category Events\n * @since 4.16.0\n * @docLink packages/types/events#agent-event\n */\nexport type TriggerFiredEvent = {\n type: \"trigger_fired\";\n instanceId: string;\n triggerId: string;\n source: \"schedule\" | \"webhook\" | \"channel\" | \"event\";\n};\n\n/**\n * Per-turn token usage reported by a harness.\n *\n * All fields are optional so the type can represent partial data — different\n * providers expose different subsets:\n *\n * | Provider | input | output | cacheRead | cacheCreation | reasoning |\n * |-----------|-------|--------|-----------|---------------|-----------|\n * | Anthropic | y | y | y | y | - |\n * | OpenAI | y* | y | y | - | y |\n *\n * `*` Anthropic's `inputTokens` excludes cached/cache-creation reads (they\n * are reported separately). OpenAI's `inputTokens` is the *total* including\n * cached tokens — consumers that want a strict \"fresh input\" count must\n * subtract `cacheReadTokens` themselves.\n *\n * @category Cost\n * @since 3.1.0\n * @docLink packages/types/events#token-usage\n */\nexport type TokenUsage = {\n /** Input/prompt tokens consumed by the turn (provider-specific semantics — see type docstring). */\n inputTokens?: number;\n /** Output/completion tokens generated by the model. */\n outputTokens?: number;\n /** Tokens served from the provider's prompt cache (Anthropic: cache_read_input_tokens; OpenAI: cached_input_tokens). */\n cacheReadTokens?: number;\n /** Tokens written to the prompt cache for future reads (Anthropic-only — OpenAI does not expose this). */\n cacheCreationTokens?: number;\n /** Reasoning tokens consumed by OpenAI reasoning models (o1, o3, ...). */\n reasoningTokens?: number;\n /** Total tokens for the turn when the provider supplies one. */\n totalTokens?: number;\n};\n\n/**\n * One model's share of a turn, including calls the turn-level `tokens` omit.\n *\n * `TokenUsage` on a `FinishedEvent` describes the main thread only: Claude\n * Code's result `usage` skips every request a Task subagent made, while its\n * reported cost includes them. `FinishedEvent.modelUsage` fills that gap,\n * keyed by model id, so consumers can attribute the whole bill and derive the\n * subagent share as `sum(modelUsage[*]) − tokens`. Field semantics follow\n * `TokenUsage` (Anthropic: disjoint prompt slices). Harnesses emit per-turn\n * figures here even when the provider reports run-cumulative counters.\n *\n * @category Cost\n * @since 3.11.0\n */\nexport type ModelTokenUsage = Pick<\n TokenUsage,\n \"inputTokens\" | \"outputTokens\" | \"cacheReadTokens\" | \"cacheCreationTokens\"\n> & {\n /** Provider-reported cost of this model's calls in the turn, in USD. */\n costUsd?: number;\n /** Context window of this model, in tokens. */\n contextWindow?: number;\n};\n\n/**\n * Emitted when the agent completes a turn.\n *\n * Carries cost / usage data and optionally a custom message payload for dynamic\n * rendering via the v2 capability registry (`customType` + `customData` fields).\n *\n * `costUsd` semantics: this is per-turn cost in USD. Some providers report a\n * run-cumulative figure instead of a per-turn one — the harness is responsible\n * for normalizing it into a per-turn delta before emitting it here. Harnesses\n * that don't surface provider-reported cost emit `0`; consumers distinguishing\n * \"free\" from \"not reported\" should pair `costUsd === 0` with `tokens` being\n * present/absent.\n *\n * @docLink packages/types/events#finished-event\n */\nexport type FinishedEvent = TurnVisibility & {\n type: \"finished\";\n summary: string;\n costUsd: number;\n /**\n * Per-turn token usage when the harness tracks it. Absent for harnesses\n * that do not surface usage (e.g. omp RPC today). Added in 3.1.0.\n */\n tokens?: TokenUsage;\n /**\n * Per-model usage for the turn, subagent calls included, when the harness\n * reports it. See {@link ModelTokenUsage}. Added in 3.11.0.\n */\n modelUsage?: Record<string, ModelTokenUsage>;\n /**\n * Prompt size of the turn's last main-thread API call — the real context\n * fill — when the harness tracks it. `tokens` cannot answer this: it sums\n * every call in the turn. Added in 3.11.0.\n */\n contextTokens?: number;\n /** Context window of the main model, in tokens, when known. Added in 3.11.0. */\n contextWindow?: number;\n /** True when the response was cancelled by the user (partial content). */\n cancelled?: boolean;\n /** Custom message type (e.g. \"gif\") — clients render via a registered dynamic component. */\n customType?: string;\n /** Structured data for custom message types — used as component props. */\n customData?: Record<string, unknown>;\n /**\n * `true` when this ends a turn the runner did not dispatch (see\n * {@link SelfTurnStartedEvent}). A host that pairs `finished` events with the\n * turns it sent must not pair this one with any of them. Added in 4.19.0.\n */\n selfStarted?: true;\n};\n\n/**\n * A background task (a backgrounded shell command, a background subagent, a\n * monitor) started inside the running turn. Emitted while that turn runs, so a\n * host can remember who that turn acts for and credit the turn the task's\n * completion later wakes ({@link SelfTurnStartedEvent}) to the same person.\n *\n * `taskId` is the agent harness's own task id, opaque to the host. Ambient\n * housekeeping tasks the harness starts by itself are not reported. A task that\n * starts in the foreground is reported only once it moves to the background.\n * Transient (broadcast-only). Only the claude-sdk harness emits it today.\n *\n * @category Events\n * @since 4.19.0\n */\nexport type BackgroundTaskStartedEvent = {\n type: \"background_task_started\";\n taskId: string;\n};\n\n/**\n * The agent started a turn the runner did not dispatch: no prompt, reply,\n * flow turn or compaction set it off. Today that is the agent harness waking\n * itself when background work it launched earlier settles. Emitted before any\n * other event of that turn; the turn ends with a `finished` (or `error`)\n * carrying `selfStarted: true`, and sends no `status: idle` of its own.\n * A prompt the host sends while it runs joins it only if the agent takes the\n * prompt inside that turn: its `finished` then carries no `selfStarted` and\n * ends the prompted turn as usual. Otherwise the self-started turn ends with\n * its own stamped `finished`, and the prompted turn ends on the turn that\n * answers the prompt.\n *\n * `taskIds` lists the background tasks ({@link BackgroundTaskStartedEvent})\n * whose completion the harness reported since the previous turn ended, and so\n * whose results this turn reads. Only tasks announced with\n * `background_task_started` are listed. Empty when the runner saw none: the host then\n * cannot tell what woke the agent and must not credit the turn to anyone.\n * Transient (broadcast-only). Only the claude-sdk harness emits it today.\n *\n * @category Events\n * @since 4.19.0\n */\nexport type SelfTurnStartedEvent = {\n type: \"self_turn_started\";\n taskIds: string[];\n};\n\n/**\n * An agent-to-agent (A2A) message exchanged between two linked sessions.\n *\n * Persisted as a `Message` row in BOTH the caller and target session\n * conversations — each side stores its own copy with the matching\n * `direction`. `inbound` is the copy in the receiving session's\n * conversation; `outbound` is the copy in the initiating session's\n * conversation. The two copies share the same `exchangeId`.\n *\n * Hosts (the Skaile platform) write this event into `Message.payload`\n * alongside the dedicated `a2aExchangeId` / `peerSessionId` / `a2aDirection`\n * columns. The chat UI's Network / All views render it as a badged A2A card.\n *\n * @docLink packages/types/events#a2a-message-event\n */\nexport type A2AMessageEvent = {\n type: \"a2a_message\";\n /** `inbound` = this session received it; `outbound` = this session sent it. */\n direction: \"inbound\" | \"outbound\";\n /** The other end of the exchange — the peer session's id. */\n peerSessionId: string;\n /** Human-readable name of the peer session, for UI display. */\n peerName: string;\n /** The A2A exchange this message belongs to (`A2AExchange.id`). */\n exchangeId: string;\n /** The message body — the question, answer, or async message text. */\n text: string;\n};\n\n/**\n * Emitted when a shared state store's snapshot changes.\n *\n * Carries the full serialized state snapshot for the named store (e.g. \"flow\", \"session\").\n * Frontends and the platform gateway subscribe to build reactive state views.\n *\n * @docLink packages/types/events#agent-event\n */\nexport type StateChangedEvent = {\n type: \"state_changed\";\n /** Store identifier, e.g. \"flow\", \"session\" */\n store: string;\n /** Serialized state snapshot */\n state: Record<string, unknown>;\n};\n\n/**\n * Emitted when the orchestrator hands execution off to a specific flow node and skill.\n *\n * Carries the context sources and approximate context size used to curate\n * the handoff prompt so operators can diagnose context-window decisions.\n *\n * @docLink packages/types/events#agent-event\n */\nexport type HandoffEvent = {\n type: \"handoff\";\n /** Flow node being handed off to */\n nodeId: string;\n /** Skill being executed */\n skillId: string;\n /** Node IDs that contributed context to this handoff */\n contextSources: string[];\n /** Approximate size of curated context in characters */\n contextSize: number;\n};\n\n/**\n * Response to a `ConnectorRequestCommand` (wire type: `\"resource_response\"`).\n *\n * Correlates to the originating request via `requestId` and carries the\n * operation result or an error string. The wire `type:` string stays as\n * `\"resource_response\"` for protocol stability.\n *\n * @docLink packages/types/events#agent-event\n */\nexport type ConnectorResponseEvent = {\n type: \"resource_response\";\n /** Correlates to the originating resource_request. */\n requestId: string;\n /** Which connector handled the request. */\n resourceId: string;\n /** Which operation was performed. */\n operation: ConnectorOperation;\n /** Result data — shape depends on the operation. */\n data?: unknown;\n /** Error message if the operation failed. */\n error?: string;\n /** Machine-readable failure class, when the runner knows one. Since protocol 4.2.0. */\n code?: ConnectorResponseFailureCode;\n};\n\n/**\n * Response to a `ConnectorQueryCommand`. Carries the JSON-encoded result of\n * a `ConnectorManager.executeOp` call, correlated by `requestId`.\n *\n * Persistence: transient. Hosts that want to record the query side effects\n * should rely on the runner's structured log stream, not on this event.\n *\n * @docLink packages/types/events#connector-query-response-event\n * @since 2.2.0\n */\nexport type ConnectorQueryResponseEvent = {\n type: \"connector_query_response\";\n /** Correlates to the originating ConnectorQueryCommand. */\n requestId: string;\n /** Whether the underlying executeOp resolved without throwing. */\n ok: boolean;\n /** JSON-encoded executeOp result, when `ok === true`. */\n result?: string;\n /** Error message when `ok === false`. */\n error?: string;\n};\n\n/**\n * Machine-readable failure class carried by {@link ConnectorMutateResponseEvent}.\n * Present iff `ok === false`. Hosts branch on this rather than on the free-text\n * `error` string, which is a runner/adapter message and may change.\n *\n * @category Protocol\n * @since 3.7.0\n * @docLink packages/types/events#connector-mutate-response-event\n */\nexport type ConnectorMutateFailureCode =\n /** The target connector never became available within the readiness wait. */\n | \"connector_unavailable\"\n /** `planFlowMutate` rejected the op (malformed or conflicting payload). */\n | \"rejected\"\n /** The adapter threw — illegal transition, unknown node, read-only violation. */\n | \"op_failed\"\n /** `sessionReady` rejected: the session build failed, the container is unusable. */\n | \"session_unavailable\";\n\n/**\n * Outcome of replaying `payload.pendingDecisions` during a flow `hydrate`.\n *\n * Invariant: every supplied entry that carried a string `nodeId` appears in\n * exactly one of `applied` / `skipped`. A skip is a deliberate structural\n * decision, never a failure — the hydrate itself has already succeeded by the\n * time reconciliation runs. Gotcha: the skip entry deliberately carries only\n * `nodeId` + `reason`; the decision payload is user content and is never echoed.\n *\n * @category Protocol\n * @since 3.7.0\n * @docLink packages/types/events#connector-mutate-response-event\n */\nexport type FlowHydrateReconciliation = {\n /** nodeIds whose pending decision was applied during this hydrate. */\n applied: string[];\n /** nodeIds whose pending decision was deliberately not applied. */\n skipped: Array<{\n nodeId: string;\n reason: \"not_parked\" | \"already_decided\" | \"unknown_node\" | \"payload_invalid\";\n }>;\n};\n\n/**\n * Response to a `ConnectorMutateCommand` that carried a `requestId`.\n *\n * Emission invariant: **exactly one** per command that set `requestId`, on every\n * terminal path (including the paths that previously only logged), and **never**\n * for a command without one — that opt-in is the whole 3.6 back-compat story.\n *\n * Persistence: transient. Like `connector_query_response` this is system RPC,\n * not chat; hosts must keep it out of the message store.\n *\n * @category Protocol\n * @since 3.7.0\n * @docLink packages/types/events#connector-mutate-response-event\n */\nexport type ConnectorMutateResponseEvent = {\n type: \"connector_mutate_response\";\n /** Correlates to the originating ConnectorMutateCommand.requestId. */\n requestId: string;\n /** Whether the mutation was applied. */\n ok: boolean;\n /** JSON-encoded executeOp result, when ok === true and the op returned one. */\n result?: string;\n /** Human-readable failure message when ok === false. */\n error?: string;\n /** Machine-readable failure class. Present iff ok === false. */\n code?: ConnectorMutateFailureCode;\n /**\n * Outcome of `payload.pendingDecisions` reconciliation. Present only for\n * `op === \"hydrate\"` on the flow connector, and only when the host supplied\n * pending decisions. Absent is NOT \"nothing applied\" — it is \"not attempted\".\n */\n reconciled?: FlowHydrateReconciliation;\n};\n\n/**\n * Receipt acknowledgement for a `prompt` command that carried a `messageId`.\n *\n * Emission invariant: **exactly one** per prompt that set `messageId`, emitted\n * as the runner's first act — before the session-readiness gate, the secrets\n * check, and the harness start, each of which can otherwise drop the prompt with\n * no trace. It says \"the frame arrived and was decoded\", nothing about the turn\n * ever running; turn-level supervision is a separate concern.\n *\n * Persistence: transient. System RPC, not chat.\n *\n * @category Protocol\n * @since 3.8.0\n */\nexport type PromptAckEvent = {\n type: \"prompt_ack\";\n /** Echoes the originating `prompt` command's `messageId` verbatim. */\n messageId: string;\n};\n\n/**\n * Chat prompts a `cancel` removed from the runner's prompt queue before they\n * ran. Sent only for a `cancel` that named its `senderId`, and only when at\n * least one prompt was dropped.\n *\n * Only prompts of that sender that were still waiting are dropped. The\n * running turn is aborted, not dropped, and other senders' prompts stay\n * queued and run. Hosts mark the listed prompts \"not sent\".\n *\n * Persistence: transient. Broadcast to every client of the session.\n *\n * @category Protocol\n * @since 4.14.0\n */\nexport type QueuedPromptsDroppedEvent = {\n type: \"queued_prompts_dropped\";\n /** The `cancel` command's `senderId`: the user whose prompts were dropped. */\n senderId: string;\n /** `messageId` of each dropped prompt that carried one, in queue order. */\n messageIds: string[];\n /** Number of dropped prompts, including those without a `messageId`. */\n count: number;\n};\n\n/**\n * A live `runner.reconfigure` the runner answered `ok` and the agent harness\n * then refused. The patch landed while a turn was running, so the capability\n * call could only promise it; the harness refused it at the next turn boundary\n * and the runner already rolled back. A refusal while the session is idle is\n * answered on the capability call (`ok: false`) and emits nothing.\n *\n * The runner drops the patch from what it keeps for a harness recreate before\n * it sends this event, so a recreate (and the next turn) runs on the rolled-back\n * settings. A host maps the event to its restart-required signal for the\n * session: the settings the user asked for are not in effect.\n *\n * Persistence: transient. Broadcast to every client of the session.\n *\n * @category Protocol\n * @since 4.16.0\n */\nexport type ReconfigureRejectedEvent = {\n type: \"reconfigure_rejected\";\n /** The refused settings that had been answered `ok`, in the order model, thinking, effort. */\n fields: Array<\"model\" | \"thinking\" | \"effort\">;\n /** `rejected`: the harness refused the change. `model_not_on_provider`: the model is not on the session's AI provider entry. */\n code: \"rejected\" | \"model_not_on_provider\";\n /** Why the harness refused, in its own words. */\n message: string;\n /** The model the harness runs after the rollback; `null` when it reports none. */\n model: string | null;\n};\n\n/**\n * Emitted after session boot listing all connected mounts and connectors.\n *\n * Consumers use this event to populate the resource explorer and build initial\n * connector status maps. The wire type is `\"resources_available\"`.\n *\n * @docLink packages/types/events#agent-event\n */\nexport type ConnectorsAvailableEvent = {\n type: \"resources_available\";\n /** All connected mounts with their metadata. */\n mounts: MountInfo[];\n /** All connected connectors with their metadata. */\n connectors: ConnectorInfo[];\n /** All runner-managed MCP servers with their metadata. */\n mcp_servers: McpServerInfo[];\n /**\n * `true` when the runner accepts `resource_request` writes and deletes\n * addressed to `SESSION_ROOT_CONNECTOR_ID` (`\"@session\"`), which resolve against the\n * session's own root instead of a mount. Absent on older runners: a host\n * must then keep delivering through the workspace mount.\n */\n sessionRoot?: boolean;\n};\n\n/**\n * Emitted whenever a connector's connection state changes.\n *\n * Transient — not persisted to the message store. Consumed exclusively by\n * `ResourceClient._handleEvent()` in `@skaile/workspaces/store` to maintain the\n * reactive `connectorStatus` map.\n *\n * @docLink packages/types/events#connector-status-event\n */\nexport interface ConnectorStatusEvent {\n type: \"connector_status\";\n /** Matches ConnectorDeclaration.id. */\n connectorId: string;\n /** Current connection state. */\n status: \"connecting\" | \"connected\" | \"error\" | \"disconnected\";\n /** Present when status === \"error\". */\n error?: string;\n /**\n * What kind of failure `error` is, when the runner could tell — present only\n * with status === \"error\". Absent means unclassified, not \"none of the\n * kinds\": most harnesses throw plain errors, and older runners never send it.\n */\n errorKind?: ConnectorErrorKind;\n /** Round-trip latency in milliseconds from the last health check. */\n latencyMs?: number;\n}\n\n/**\n * Where a connector connect failure can be fixed.\n *\n * - `credential` — the credential is missing, refused or unusable; reconnecting\n * the account (or re-provisioning the secret) is the fix.\n * - `repo-state` — the on-disk checkout is in a state the connect cannot work\n * with (e.g. a live `.git/index.lock`); a new credential changes nothing.\n * - `config` — the declaration itself is missing or invalid (no source URL, a\n * bad branch name, a required field that resolves to nothing).\n *\n * Senders set a kind only when the thrown error identifies it structurally;\n * receivers must treat an absent or unknown value as unclassified.\n */\nexport type ConnectorErrorKind = (typeof CONNECTOR_ERROR_KINDS)[number];\n\n/** Every {@link ConnectorErrorKind}, for receivers that validate the wire field. */\nexport const CONNECTOR_ERROR_KINDS = [\"credential\", \"repo-state\", \"config\"] as const;\n\n/**\n * Emitted when a lifecycle phase (hibernate, close, compact) completes across all resources.\n *\n * Carries per-resource results so the platform can surface which resources failed\n * during the phase. The `phase` field identifies which lifecycle stage completed.\n *\n * @docLink packages/types/events#agent-event\n */\nexport type LifecycleCompleteEvent = {\n type: \"lifecycle_complete\";\n /** Which lifecycle phase completed. */\n phase: LifecyclePhase;\n /** Per-resource results. */\n results: LifecycleResult[];\n};\n\n/**\n * Transient — broadcast when a user or agent adds an emoji reaction to a message.\n *\n * Not persisted as a message. Consumed by frontends to update the reaction display in real time.\n *\n * @docLink packages/types/events#reaction-events\n */\nexport type ReactionAddedEvent = {\n type: \"reaction_added\";\n /** ID of the message being reacted to. */\n messageId: string;\n /** Sequence number of the target message (for efficient frontend lookup). */\n messageSeq: number;\n emoji: string;\n userId: string;\n userName: string;\n};\n\n/**\n * Transient — broadcast when a user removes a reaction from a message.\n *\n * Not persisted as a message. Consumed by frontends to update the reaction display in real time.\n *\n * @docLink packages/types/events#reaction-events\n */\nexport type ReactionRemovedEvent = {\n type: \"reaction_removed\";\n messageId: string;\n messageSeq: number;\n emoji: string;\n userId: string;\n};\n\n/**\n * Transient typing indicator — not persisted.\n *\n * Broadcast to all session subscribers when a participant starts or stops typing.\n * Frontends use this to render the \"X is typing...\" indicator.\n *\n * @docLink packages/types/events#typing-user-message-secrets-ready-configured-events\n */\nexport type TypingEvent = {\n type: \"typing\";\n userId: string;\n userName: string;\n isTyping: boolean;\n};\n\n/**\n * Transient echo of a user message broadcast to all session subscribers — not persisted.\n *\n * Carries reply-threading fields so clients can detect parent-message relationships\n * and route mention-style notifications.\n *\n * @docLink packages/types/events#typing-user-message-secrets-ready-configured-events\n */\nexport type UserMessageEvent = {\n type: \"user_message\";\n senderId: string;\n senderName: string;\n content: string;\n /** Set when this user message is a reply to a previous message. */\n parentMessageId?: string;\n /** Sender id of the parent message — lets clients detect \"reply to me\". */\n parentSenderId?: string;\n /** When true, clients should treat this reply as a mention-style notification target. */\n notifyParent?: boolean;\n\n // ---------------------------------------------------------------------------\n // Platform extension fields (multi-user privacy / recipient routing).\n // Added with @skaile/workspaces/types 3.2.0 for platform F-23 (mention recipient\n // suffixes). Framework consumers that don't run multi-user sessions can\n // ignore these — single-user forge apps leave them undefined and the\n // event behaves identically to pre-3.2 envelopes.\n // ---------------------------------------------------------------------------\n\n /**\n * Routing mode of the message envelope.\n * - `\"Public\"` (default when omitted) — broadcast to every session\n * subscriber (humans + agent).\n * - `\"Private\"` — visible only to the sender plus everyone listed in\n * `privateRecipientIds`.\n * - `\"HumansOnly\"` — visible to all human subscribers; the agent is\n * excluded from broadcast and notifications.\n *\n * **Invariant (NOT enforced by the type system):** producers MUST populate\n * a non-empty `privateRecipientIds` whenever this is `\"Private\"`. The\n * shape is intentionally flat (rather than a discriminated union) to\n * keep wire compat with older consumers, but this means TypeScript will\n * not catch violations at the call site. **Persistence-layer\n * implementations MUST validate this invariant on intake** and reject /\n * downgrade / log a violation rather than persist a Private message\n * with no recipients (which would be visible to nobody and effectively\n * lost).\n *\n * Reference platform implementation: `PlatformMessageStore.append`\n * throws on `Private + empty recipientIds` to fail fast.\n */\n visibilityMode?: \"Public\" | \"Private\" | \"HumansOnly\";\n\n /**\n * Recipient list for `visibilityMode: \"Private\"`. Each entry is either a\n * user id (matching the platform's user-id shape) or the sentinel\n * `\"__agent__\"` when the agent itself is an explicit recipient (i.e. the\n * sender wrote `@agent_`).\n *\n * MUST be non-empty when `visibilityMode === \"Private\"` — see the\n * invariant note on `visibilityMode` above.\n *\n * Empty / absent for `Public` and `HumansOnly` — recipient sets in those\n * modes are implicit (everyone / everyone-except-agent).\n */\n privateRecipientIds?: string[];\n};\n\n/**\n * Transient signal that provisioned secrets have been stored and resources initialized.\n *\n * The platform waits for this event after sending a `SecretProvisionCommand` before\n * allowing further session interaction.\n *\n * @docLink packages/types/events#typing-user-message-secrets-ready-configured-events\n */\nexport type SecretsReadyEvent = {\n type: \"secrets_ready\";\n};\n\n/**\n * Transient ACK emitted once the agent has finished processing a `configure`\n * command (shared state stores registered, MCP tools rebuilt, active flows\n * rehydrated). Backends await this before releasing the session so prompts\n * can't race the configure handler and start the harness with stale tools.\n *\n * @docLink packages/types/events#typing-user-message-secrets-ready-configured-events\n */\nexport type ConfiguredEvent = {\n type: \"configured\";\n};\n\n/**\n * Emitted when a mount is successfully attached to the workspace.\n *\n * Carries the mount id, filesystem path, driver name, and access level.\n *\n * @docLink packages/types/events#agent-event\n */\nexport type MountMountedEvent = {\n type: \"mount_mounted\";\n id: string;\n mountPath: string;\n driver: string;\n access: string;\n};\n\n/**\n * Emitted when a mount is detached from the workspace.\n *\n * @docLink packages/types/events#agent-event\n */\nexport type MountUnmountedEvent = {\n type: \"mount_unmounted\";\n id: string;\n};\n\n/**\n * Emitted when a file changes within a mounted source.\n *\n * Similar to `FileChangeEvent` but scoped to a specific mount by `id`.\n *\n * @docLink packages/types/events#agent-event\n */\nexport type MountChangedEvent = {\n type: \"mount_changed\";\n id: string;\n path: string;\n action: \"create\" | \"edit\" | \"delete\" | \"conflict\";\n};\n\n/**\n * Progress update for a mount's initial synchronization phase.\n *\n * Emitted repeatedly during the sync lifecycle (enumerating, stubs_ready,\n * downloading, initial_sync_complete). Carries file counts for progress display.\n *\n * @docLink packages/types/events#agent-event\n */\nexport type MountSyncStatusEvent = {\n type: \"mount_sync_status\";\n id: string;\n phase: SyncStatusPhase;\n totalFiles: number;\n downloadedFiles: number;\n stubFiles: number;\n message: string;\n};\n\n/**\n * Persisted chat event summarizing a flow lifecycle milestone.\n *\n * The gateway diffs each incoming flow state_changed event against the\n * previous snapshot and emits breadcrumbs for user-meaningful transitions\n * — flow start/end, approval requests, input requests, and node failures.\n * Per-node traffic (running/complete/skipped) is NOT emitted as a\n * breadcrumb to keep the chat stream readable; that detail lives on the\n * flow execution panel.\n *\n * Breadcrumbs are persisted via the dispatcher's normal message store path\n * and rendered on the frontend as collapsed cards that expand inline.\n *\n * @docLink packages/types/events#flow-breadcrumb-event\n */\nexport type FlowBreadcrumbEvent = {\n type: \"flow_breadcrumb\";\n kind:\n | \"flow_started\"\n | \"flow_finished\"\n | \"flow_failed\"\n | \"flow_cancelled\"\n | \"approval_pending\"\n | \"input_pending\"\n | \"approval_resolved\"\n | \"input_resolved\"\n | \"node_failed\";\n runId: string;\n flowId: string;\n flowName: string;\n /** Node that triggered this breadcrumb, if the kind is node-scoped. */\n nodeId?: string;\n /** Human-readable node label (from flow definition `data.label`). */\n nodeName?: string;\n /** User ID of the actor that caused the transition (if applicable). */\n actorUserId?: string;\n /** One-line summary for the collapsed card rendering. */\n summary?: string;\n};\n\n/**\n * Persisted chat event carrying the orchestrator prompt for one flow turn.\n *\n * The flow runner reassembles the full `# Flow Execution Context` prompt on\n * every turn and hands it to the agent harness. Without this event a host\n * consuming the stream sees the agent replying to input it cannot read, so the\n * runner emits the prompt verbatim immediately before delivering it — the\n * event therefore always precedes that turn's reply events in the stream.\n *\n * `prompt` is byte-identical to the string given to the harness: never\n * redacted, truncated, or re-rendered. Everything the agent saw — user text,\n * node input, stimulus paragraph — is already inside it, which is why the\n * stimulus is carried only as its kind plus the node it concerns.\n *\n * Emitted for main-agent turns and inline sub-flow turns alike; a sub-flow turn\n * carries the **child** flow's `flowId`/`flowName`. Subprompt nodes run on their\n * own isolated harness and emit nothing here.\n *\n * Persisted via the dispatcher's normal message store path.\n *\n * @docLink packages/types/events#flow-prompt-event\n */\nexport type FlowPromptEvent = {\n type: \"flow_prompt\";\n /** Flow run this turn belongs to. */\n runId: string;\n /** Flow definition id. */\n flowId: string;\n /** Human-readable flow name from the definition, which always carries one. */\n flowName: string;\n /**\n * Why the runner drove this turn. Mirrors the runner's `TurnStimulus[\"kind\"]`,\n * re-declared here because this package must not depend on `factory-assets`.\n */\n stimulus:\n | \"flow_started\"\n | \"approval_received\"\n | \"input_received\"\n | \"retry_requested\"\n | \"user_message\"\n | \"resumed_after_hibernation\"\n | \"cancelled\"\n | \"state_changed\";\n /** Compact stimulus label for logs/telemetry, e.g. `approval_received:review:approved`. */\n stimulusLabel: string;\n /** Node the stimulus concerns, when the stimulus is node-scoped. */\n nodeId?: string;\n /** The verbatim orchestrator prompt handed to the agent harness. */\n prompt: string;\n};\n\n/**\n * The session lifecycle phase being executed. Carried in `LifecycleCompleteEvent.phase`\n * and the `lifecycle` command's `phase` field.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type LifecyclePhase = \"hibernate\" | \"close\" | \"compact\";\n\n/**\n * Per-resource result of a lifecycle phase, carried in `LifecycleCompleteEvent.results`.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type LifecycleResult = {\n id: string;\n ok: boolean;\n error?: string;\n /** Human-readable detail (e.g. commit SHA, branch name). */\n detail?: string;\n /**\n * What the connector can prove about its working copy after the hook ran.\n * Set by the git connector on `hibernate`; absent for other connectors, a\n * fleet-managed git mount, and a hook that threw.\n */\n pushState?: ConnectorPushState;\n};\n\n/**\n * What a connector can prove about its working copy after a lifecycle hook, so\n * a host can decide whether deleting the workspace loses anything. Every doubt\n * answers in the \"keep it\" direction. Carries no URL or credential.\n *\n * Deleting is safe only when `clean` and `onRemote` are both `true`, and the\n * host accepts losing the files `ignoredFiles` reports.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type ConnectorPushState = {\n /**\n * No uncommitted changes, tracked or untracked, after the hook ran. Files a\n * `.gitignore` or `info/exclude` ignores do not count; see `ignoredFiles`.\n */\n clean: boolean;\n /**\n * Every commit reachable from a local branch, a local tag, `HEAD`\n * (detached too) or the stash is reachable from some branch head on the remote. Asked of the remote\n * (`ls-remote`, 10 s bound), never read from local `origin/*` refs. `false`\n * whenever the repo has an initialised submodule. `null` = the remote could\n * not be asked (network, auth, timeout): \"cannot tell\", never \"yes\". A remote\n * reached only through ambient global/system git config (credential helper,\n * ssh or CA settings) always reads `null`: the probe switches that config off.\n * Only the newest stash entry is walked (any stash already makes it `false`),\n * and the HEADs of other linked worktrees (`git worktree add`) are not walked.\n */\n onRemote: boolean | null;\n /**\n * The working tree holds ignored files (build output, `node_modules`, a local\n * `.env`). Deleting the workspace loses them; the host decides whether that\n * matters. `null` when the check failed.\n */\n ignoredFiles: boolean | null;\n /** Full HEAD commit sha, or `null` when the repo has no commit or HEAD is unreadable. */\n head: string | null;\n /** The branch checked out, or `null` when HEAD is detached. */\n branch: string | null;\n};\n\n// ---------------------------------------------------------------------------\n// Mount types\n// ---------------------------------------------------------------------------\n\n/**\n * Metadata for a mounted filesystem source, carried in `ConnectorsAvailableEvent.mounts`.\n *\n * Re-declared here to avoid a dependency on `@skaile/workspaces/connectors`; mirrors the\n * connector package's `MountInfo` type.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type MountInfo = {\n id: string;\n driver: string;\n /** Human-readable connection name; the resource-explorer tab renders this over `id`/`driver` when present. */\n label?: string;\n access: \"read-only\" | \"read-write\";\n mountPath: string;\n mounted: boolean;\n source: string;\n};\n\n// ---------------------------------------------------------------------------\n// Connector types (re-declared here to avoid depending on @skaile/workspaces/connectors)\n// ---------------------------------------------------------------------------\n\n/**\n * Metadata for a runner-managed MCP server, carried in `ConnectorsAvailableEvent.mcp_servers`.\n *\n * `live` indicates whether the active harness session already picked up the server's tools\n * without requiring a restart — false means the tools are registered but not yet active.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type McpServerInfo = {\n id: string;\n transport: \"stdio\" | \"sse\" | \"http\";\n live: boolean;\n toolCount: number;\n};\n\n/**\n * Operations a connector can perform. Used in `ConnectorRequestCommand.operation`\n * and `ConnectorResponseEvent.operation`.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type ConnectorOperation =\n | \"list\"\n | \"read\"\n | \"write\"\n | \"delete\"\n | \"search\"\n /** Create one empty directory on a filesystem mount. Since protocol 4.2.0. */\n | \"mkdir\"\n /** Describe one path on a filesystem mount ({@link ConnectorStat}). Since protocol 4.2.0. */\n | \"stat\"\n /**\n * Write one byte range of a file too large for one message\n * ({@link WriteRangeOptions}). Since protocol 4.15.0.\n */\n | \"write_range\";\n\n/**\n * Machine-readable failure class on a {@link ConnectorResponseEvent}. Hosts\n * branch on this rather than on the free-text `error`.\n *\n * A runner older than protocol 4.2.0 never sets it: it answers an operation it\n * does not know with an `error` starting `Unsupported operation`, so a host\n * feature-detecting a new operation must accept both forms.\n *\n * @category Protocol\n * @since 4.2.0\n * @docLink packages/types/events#supporting-types\n */\nexport type ConnectorResponseFailureCode =\n /** The target (mount, connector or session root) does not serve this operation. */\n | \"unsupported_operation\"\n /** `mkdir` found something already at the path. */\n | \"already_exists\"\n /**\n * A ranged `read` carried an `offset` or `length` that is not a non-negative\n * safe integer (since 4.12.0), or a `write_range` was malformed or out of\n * sequence (since 4.15.0).\n */\n | \"invalid_range\";\n\n/**\n * Options for a filesystem-mount `stat` operation.\n *\n * @category Protocol\n * @since 4.2.0\n * @docLink packages/types/events#supporting-types\n */\nexport type StatOptions = {\n /**\n * For a directory, walk everything below it and report\n * {@link ConnectorStat.totals}. The walk is capped (entries, time, depth); a\n * capped walk answers with `totals.partial: true` instead of failing.\n */\n recursive?: boolean;\n /** Count dotfiles and dot-directories in `totals`. Off by default, like `list`. */\n includeHidden?: boolean;\n /** Lower the runner's entry cap for this walk. Values above the runner's cap are ignored. */\n maxEntries?: number;\n /** Lower the runner's time budget (ms) for this walk. Values above the runner's budget are ignored. */\n timeoutMs?: number;\n};\n\n/**\n * Options for a filesystem-mount `read` operation.\n *\n * A runner older than protocol 4.6.0 ignores them and classifies as usual, so\n * a host asking for `binary` must still treat a `utf-8` answer carrying U+FFFD\n * as lossy rather than re-encode it.\n *\n * @category Protocol\n * @since 4.6.0\n * @docLink packages/types/events#supporting-types\n */\nexport type ReadOptions = {\n /**\n * `\"binary\"` answers base64 for every file instead of decoding text the\n * first 8 KiB of which hold no NUL byte. A text file still loses its\n * trailing NUL pad (see the runner's NUL-tail rule).\n */\n encoding?: \"binary\";\n /**\n * First byte to read. Setting `offset` or `length` makes this a ranged read:\n * the runner reads only that range, never the whole file, answers base64\n * (`encoding: \"binary\"`, no text classification, no NUL-tail strip) and sets\n * {@link ConnectorContent.range}. A non-negative safe integer; an offset at or\n * past the end answers an empty chunk. Because a chunk keeps every byte, a\n * text file reassembled from chunks still carries the trailing NUL pad a\n * whole-file read strips; a host that wants the old result strips the\n * trailing NUL run itself. Since protocol 4.12.0.\n */\n offset?: number;\n /**\n * Bytes to read from `offset`, at most `MOUNT_READ_MAX_CHUNK_BYTES` (8 MiB):\n * a larger value is clamped, and an absent one means that maximum. The answer\n * says how many bytes it holds in `range.length`. Since protocol 4.12.0.\n *\n * A runner older than 4.12.0 ignores both fields and sends the whole file in\n * one frame, so a host must gate ranged reads on the protocol version, and an\n * answer without `range` means the range was not honored.\n */\n length?: number;\n};\n\n/**\n * Where a ranged `read` chunk sits in its file. Present only when the request\n * carried `ReadOptions.offset` or `ReadOptions.length`.\n *\n * @category Protocol\n * @since 4.12.0\n * @docLink packages/types/events#supporting-types\n */\nexport type ConnectorContentRange = {\n /** First byte of the chunk (the requested offset). */\n offset: number;\n /**\n * Bytes in the chunk. Less than requested only at the end of the file; `0`\n * when `offset` is at or past the end, or when the request asked for\n * `length: 0` (a size probe). A chunked reader must ask for a positive length.\n */\n length: number;\n /** Size of the whole file in bytes; the caller is done when `offset + length >= size`. */\n size: number;\n /**\n * The file's modification time (ISO 8601) when this chunk was read. Each\n * chunk opens the file anew, so a caller that sees it change between chunks\n * (or `size` change) knows the file was replaced mid-transfer and should\n * start over. Absent when the filesystem reports no time.\n */\n modifiedAt?: string;\n};\n\n/**\n * Options for a filesystem-mount (or session-root) `write_range` operation:\n * one chunk of a file written in pieces, because the whole file base64-encoded\n * would not fit in one WebSocket message.\n *\n * The chunk is `content.data`, base64 with `encoding: \"binary\"`, at most\n * `MOUNT_WRITE_MAX_CHUNK_BYTES` (8 MiB) of bytes. Chunks go into a hidden\n * partial file next to the target, which is renamed over the target when the\n * last byte arrives: a reader never sees a half-written file, and the target\n * is untouched until then. Chunks must arrive in order and without gaps; each\n * answers a {@link WriteRangeResult}, and a malformed or out-of-sequence chunk\n * fails with `code: \"invalid_range\"`. A retried final chunk whose answer was\n * lost answers `complete: true` when the same runner finished that transfer.\n * A partial file left by an abandoned\n * transfer is removed when a later transfer starts in the same directory more\n * than `WRITE_RANGE_PARTIAL_TTL_MS` (1 h) after its last chunk.\n *\n * A separate operation rather than options on `write`, so a runner older than\n * protocol 4.15.0 refuses it (`code: \"unsupported_operation\"`) instead of\n * writing the first chunk as the whole file. Gate on\n * {@link RANGED_WRITE_MIN_PROTOCOL}.\n *\n * @category Protocol\n * @since 4.15.0\n * @docLink packages/types/events#supporting-types\n */\nexport type WriteRangeOptions = {\n /**\n * Names this transfer; letters, digits, `-` and `_`, at most 64. Two\n * transfers to one path with different ids never share a partial file.\n */\n uploadId: string;\n /**\n * First byte of this chunk. `0` starts (or restarts) the transfer, discarding\n * any earlier partial file for the same `uploadId`; any other offset must\n * equal the bytes already received.\n */\n offset: number;\n /** Size of the whole file in bytes, the same on every chunk. */\n size: number;\n /** Discard the partial file for `uploadId` instead of writing; the target is untouched. */\n abort?: boolean;\n};\n\n/**\n * The answer to a `write_range` chunk.\n *\n * @category Protocol\n * @since 4.15.0\n * @docLink packages/types/events#supporting-types\n */\nexport type WriteRangeResult = {\n /** Bytes received so far, including this chunk: the next chunk's `offset`. */\n received: number;\n /** Size of the whole file, as the request stated it. */\n size: number;\n /** True once the last byte is written and the file is in place at the target path. */\n complete: boolean;\n};\n\n/**\n * Recursive totals for a directory, from a `stat` with `recursive: true`.\n *\n * When `partial` is true the counts are lower bounds (\"at least N files\"):\n * part of the tree was not seen.\n *\n * @category Protocol\n * @since 4.2.0\n * @docLink packages/types/events#supporting-types\n */\nexport type ConnectorStatTotals = {\n /** Files below the directory, at any depth. Symlinks count as files and are not followed. */\n files: number;\n /** Directories below the directory, at any depth, not counting itself. */\n directories: number;\n /** Sum of the counted files' sizes in bytes. */\n bytes: number;\n /** Whether any part of the tree went uncounted: a cap was reached or a folder was unreadable. */\n partial: boolean;\n /**\n * The cap that cut the totals short. `entries` and `time` end the walk and\n * take precedence; `depth` only leaves out the folders below it. Absent when\n * nothing but unreadable folders made the totals partial.\n */\n stoppedBy?: \"entries\" | \"time\" | \"depth\";\n /** Subfolders that could not be read (e.g. permission denied) and were skipped. */\n unreadable?: number;\n};\n\n/**\n * Result of a filesystem-mount `stat` operation.\n *\n * @category Protocol\n * @since 4.2.0\n * @docLink packages/types/events#supporting-types\n */\nexport type ConnectorStat = {\n /** Last path segment; empty for the mount root. */\n name: string;\n /** The requested path, relative to the mount root. */\n path: string;\n type: \"file\" | \"directory\";\n /** File size in bytes. Absent for directories — see `totals`. */\n size?: number;\n /** Last modification time, ISO 8601. */\n modifiedAt?: string;\n /** Creation time, ISO 8601, when the filesystem records one. */\n createdAt?: string;\n /** Present for a directory stat'ed with `recursive: true`. */\n totals?: ConnectorStatTotals;\n};\n\n/**\n * A single entry in a connector directory listing (result of a `list` operation).\n *\n * Re-declared here to avoid a dependency on `@skaile/workspaces/connectors`.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type ConnectorEntry = {\n name: string;\n path: string;\n type: \"file\" | \"directory\" | \"key\" | \"row\" | \"message\";\n size?: number;\n modifiedAt?: string;\n};\n\n/**\n * File or key content returned by a connector `read` operation.\n *\n * Re-declared here to avoid a dependency on `@skaile/workspaces/connectors`.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type ConnectorContent = {\n data: string;\n encoding?: \"utf-8\" | \"binary\";\n contentType?: string;\n metadata?: Record<string, unknown>;\n /** Set on a ranged `read` only (see {@link ReadOptions.offset}). Since protocol 4.12.0. */\n range?: ConnectorContentRange;\n};\n\n/**\n * Metadata for a connected connector, carried in `ConnectorsAvailableEvent.connectors`.\n *\n * Re-declared here to avoid a dependency on `@skaile/workspaces/connectors`; mirrors\n * the connector package's `ConnectorInfo` type.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type ConnectorInfo = {\n id: string;\n driver: string;\n /** Human-readable connection name; the resource-explorer tab renders this over `id`/`driver` when present. */\n label?: string;\n access: \"read-only\" | \"read-write\";\n operations: string[];\n};\n\n/**\n * Options for a connector `list` operation.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type ListOptions = {\n recursive?: boolean;\n glob?: string;\n limit?: number;\n /**\n * Include entries whose name starts with `.`. Off by default: a browsing\n * listing hides dotfiles. A caller materialising a build context from a\n * mount (where `.env.example`, `.npmrc`, ... must survive) opts in.\n *\n * Honored only by the runner's filesystem-mount `list`; connector drivers\n * (tool-face `list`) ignore it. It is not a security boundary: `read`\n * serves any path regardless. With `recursive` it also walks `.git`, whose\n * entries count against the listing cap, so a caller staging a tree should\n * list one directory at a time and prune before descending.\n */\n includeHidden?: boolean;\n};\n\n/**\n * Options for a connector `search` operation.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type SearchOptions = {\n regex?: boolean;\n caseSensitive?: boolean;\n maxResults?: number;\n};\n\n/**\n * Persistent — a custom-typed message emitted by the agent via a capability\n * tool invocation (`platform.custom_message`). The runner's serve layer\n * forwards these so the platform can persist and render them via the\n * dynamic component pipeline.\n *\n * @category Events\n * @since 2.0.0\n * @docLink packages/types/events#agent-event\n */\nexport type CustomMessageEvent = TurnVisibility & {\n type: \"custom_message\";\n /** Plain-text summary (e.g. \"[gif: funny cat]\"). */\n content: string;\n /** Custom message type identifier (e.g. \"gif\"). */\n customType: string;\n /** Structured data — used as component props. */\n customData: Record<string, unknown>;\n};\n\n/**\n * Trigger source for a session compaction. Carried in `SnapshotEvent.trigger`\n * and `CompactionAttemptEvent.trigger`.\n *\n * @docLink packages/types/events#snapshot-event\n */\nexport type CompactionTrigger = \"threshold\" | \"hibernate\" | \"manual\";\n\n/**\n * Persistent — a compacted conversation snapshot produced by the LLM.\n * On session restore, only the last snapshot + subsequent messages are replayed.\n *\n * @docLink packages/types/events#snapshot-event\n */\nexport type SnapshotEvent = {\n type: \"snapshot\";\n /** LLM-generated structured summary of the conversation. */\n summary: string;\n /** What triggered this compaction. */\n trigger: CompactionTrigger;\n /** Seq of previous snapshot (0 if first compaction). */\n coversFromSeq: number;\n /** Last seq this snapshot covers. */\n coversToSeq: number;\n /** Estimated context token count before compaction. */\n tokensBefore: number;\n /** Token count of the summary. */\n tokensAfter: number;\n};\n\n/**\n * Persistent -- emitted on EVERY compaction attempt, success or failure.\n *\n * Replaces the in-process circuit breaker in `CompactionOrchestrator` with\n * an observable, owner-controllable record. The platform gateway listens\n * for this event and inserts a `Compaction` row plus updates the\n * `Session.lastCompactionStatus` companion field.\n *\n * `SnapshotEvent` continues to fire on success-only paths (back-compat\n * until Phase 4); both events ride alongside each other through Phase 4.\n *\n * Spec: `_devlog/specs/2026-05-05-session-resume-restart-design.md`\n *\n * @category Compaction\n * @since 3.1.0\n * @docLink packages/types/events#compaction-attempt-event\n */\nexport type CompactionAttemptEvent = {\n type: \"compaction_attempt\";\n /**\n * Outcome of the attempt:\n * - `success`: completed and validated; eligible for tier-2 resume\n * - `failed`: compaction call returned an error or output failed validation\n * - `partial`: reserved (e.g. streaming compaction emitting partial output)\n * - `dirty`: was success at write time but later flagged\n */\n status: \"success\" | \"failed\" | \"partial\" | \"dirty\";\n /**\n * When `status !== 'success'`, a stable identifier for the failure mode.\n * Standard codes:\n * - `rate_limit | auth | account | timeout | parse_error` (from bridge error classifier)\n * - `empty | too_short | poor_ratio` (from validateCompactionOutput)\n *\n * Note: `auth` covers both real credential failures AND payment-blocked\n * OAuth subscriptions that Anthropic mislabels as auth errors. `account`\n * covers a 401 that recurs after a successful credential refresh (hidden-tier\n * rate limit, billing block, anti-abuse throttle) — the credential is fine.\n * Owners investigate further when a Compaction row shows `auth` or `account`.\n *\n * Read alongside {@link CompactionAttemptEvent.elapsedMs}: `empty` at a\n * near-zero elapsed time is an infrastructure failure, not a model one.\n *\n * `null` on success.\n */\n errorCode: string | null;\n /**\n * Wall-clock ms spent inside the compaction `prompt()` call. An `empty`\n * failure at ~0 ms means the turn was settled by a stale consumer rather\n * than by the model. Optional — absent on events from older runners.\n */\n elapsedMs?: number;\n /**\n * Truncated diagnostic text for a failed attempt — the harness error the\n * classifier saw, or which validation check rejected the output. Absent on\n * success and on events from older runners.\n *\n * The same text is mirrored into {@link CompactionAttemptEvent.summary} so a\n * consumer that only persists `summary` still explains the failure. That is\n * safe because a failed attempt is never restored into a session: restoration\n * requires `status: 'success'` with `validatedAt` set.\n */\n errorMessage?: string;\n /** What triggered this attempt. */\n trigger: CompactionTrigger;\n /** LLM-generated summary text. Empty string on failure. */\n summary: string;\n /** Model name used for the call (e.g. \"claude-sonnet-4\"). null when unknown. */\n model: string | null;\n /** Provider id used for the call (e.g. \"anthropic\"). null when unknown. */\n provider: string | null;\n /** Estimated context size before the compaction call — the whole prompt, cached tokens included (= tokensBefore). */\n inputTokens: number;\n /** Output token count of the summary or 0 on failure (= tokensAfter). */\n outputTokens: number;\n /** Seq of previous successful snapshot (0 if first compaction). */\n coversFromSeq: number;\n /** Last seq this attempt covers (current message seq). */\n coversToSeq: number;\n /**\n * Harness session id at the time of the call (for tier-1 native SDK resume).\n * Captured from `harness.runtimeSessionId`. null when the harness does not\n * expose one (e.g. echo, codex).\n */\n harnessSessionIdAtCompaction: string | null;\n /**\n * Model name at compaction time. Distinct from `model` (which records what\n * was used for THIS compaction call). For tier-1 resume, the wake-time\n * comparison is against the harness's CURRENT model — if mismatch, falls\n * through to tier 2.\n */\n modelAtCompaction: string | null;\n /**\n * Capability registry signature at compaction time. null in Phase 1\n * (the `computeCapabilitySignature` helper ships in Phase 3).\n */\n capabilitySignatureAtCompaction: string | null;\n /**\n * ISO timestamp set when `validateCompactionOutput` passed.\n * `null` when the attempt failed validation OR produced an error.\n */\n validatedAt: string | null;\n};\n\n// ---------------------------------------------------------------------------\n// Resume cascade events (Phase 3 — tier-1 native SDK resume)\n// ---------------------------------------------------------------------------\n\n/**\n * Transient — emitted by the runner when it honors a\n * `AgentReconfigureOptions.resumeSessionId` in a configure command.\n *\n * The runner emits this once it has decided to recreate the harness with\n * the platform-supplied session id (after capability signature validation\n * passes, if `expectedCapabilitySignature` was provided). The platform\n * gateway records the attempt on the {@link Session} so the UI can show\n * \"Resumed via SDK session\" when wake completes.\n *\n * Spec: `_devlog/specs/2026-05-05-session-resume-restart-design.md`\n * § \"Tier 1: native resume plumbing\".\n *\n * @category Resume\n * @since 3.2.0\n * @docLink packages/types/events#resume-attempted-event\n */\nexport type ResumeAttemptedEvent = {\n type: \"resume_attempted\";\n /** Harness session id the runner is resuming. */\n resumeSessionId: string;\n /** Capability signature computed at attempt time (advisory). */\n capabilitySignature: string;\n};\n\n/**\n * Transient — emitted by the runner or harness when a tier-1 native resume\n * could not be honored.\n *\n * Reasons:\n * - `signature_mismatch`: the runner's current capability signature differs\n * from {@link AgentReconfigureOptions.expectedCapabilitySignature}; the\n * runner dropped the {@link AgentReconfigureOptions.resumeSessionId} hint\n * before harness creation.\n * - `model_mismatch`: reserved — wake-time model comparison happens on the\n * platform side; runner does not currently emit this code, but it is\n * reserved for future harness-level checks.\n * - `jsonl_lost`: emitted by the runner when its pre-ack transcript probe\n * found no transcript (it then drops the hint), or by the claude-sdk harness\n * after the SDK reported \"No conversation found with session ID …\" (as a\n * thrown error or an `is_error` result); the harness replays the prompt on a\n * fresh session so the turn still completes.\n * - `jsonl_poisoned`: emitted by the claude-sdk harness after a replayed\n * resume hit a `400 invalid_request_error` from a transcript image block\n * with a wrong `media_type`. The harness repaired the on-disk JSONL\n * transcript in place (correcting media types, stubbing unprocessable\n * images) and retried the resume — conversation context is preserved.\n *\n * - `native_state_unavailable`: managed Codex positively classified unavailable\n * versioned state and completed one fresh same-binding initialization; the host\n * may restore DB history. Unknown native/auth/policy/transport errors are fatal.\n *\n * @category Resume\n * @since 3.2.0\n * @docLink packages/types/events#resume-failed-event\n */\nexport type ResumeFailedEvent = {\n type: \"resume_failed\";\n /** Harness session id the runner attempted to resume (and dropped). */\n resumeSessionId: string;\n /** Stable reason code; see TSDoc above for the enumeration. */\n reason:\n | \"signature_mismatch\"\n | \"model_mismatch\"\n | \"jsonl_lost\"\n | \"jsonl_poisoned\"\n | \"native_state_unavailable\";\n};\n\n/**\n * Emitted by the runner when the harness's SDK session id first becomes known\n * (after the first turn) and whenever it changes thereafter. Carries the\n * tier-1 native-resume token so the platform can persist it on the Session\n * itself — independently of compaction. Without this the resume token is\n * captured ONLY as a side effect of a compaction (see\n * {@link CompactionAttemptEvent}'s `harnessSessionIdAtCompaction`), so a\n * session that never compacts and only auto-hibernates has no stored token\n * and falls through to lossy raw-tail resume on wake even though its JSONL\n * survives on the persistent `.claude` mount.\n *\n * Low frequency: emitted on first-known + change, not per turn. Checked at\n * turn end and after a live `capability_register` / `capability_deregister`,\n * so `capabilitySignature` follows a live push before the next turn finishes.\n * Consumers that do not care ignore it (additive to the union).\n *\n * Spec: platform `_devlog/specs/2026-06-25-tier1-resume-without-compaction.md`.\n *\n * @category Resume\n * @since 3.3.0\n */\nexport type RuntimeSessionEvent = {\n type: \"runtime_session\";\n /** Harness SDK session id, usable as a native `--resume` token. */\n harnessSessionId: string;\n /**\n * Model in effect at emit time. The wake-time tier-1 guard compares this\n * against the harness's current model; mismatch forces tier 2. null when\n * the harness does not expose a model.\n */\n model: string | null;\n /** Capability registry signature at emit time (wake-time signature validation). */\n capabilitySignature: string;\n};\n\n// ---------------------------------------------------------------------------\n// Resource lifecycle events (Phase 2 — dynamic resource management)\n// ---------------------------------------------------------------------------\n\n/**\n * Transient ACK emitted by the runner after processing an add_resource or\n * remove_resource command. The gateway awaits this to confirm the operation\n * completed (or failed) before returning to the caller.\n *\n * @docLink packages/types/events#resource-status-event\n */\nexport type ResourceStatusEvent = {\n type: \"resource_status\";\n resourceId: string;\n status: \"mounting\" | \"active\" | \"error\" | \"removed\";\n mountPath?: string;\n error?: string;\n};\n\n// ---------------------------------------------------------------------------\n// Supporting types\n// ---------------------------------------------------------------------------\n\n/**\n * String union of all `AgentEvent[\"type\"]` discriminators.\n *\n * Useful for declaring event type constants or exhaustive switch coverage checks.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type AgentEventType = AgentEvent[\"type\"];\n\n/**\n * The current execution phase of the agent, carried in `StatusEvent.phase`.\n *\n * `\"cancelling\"` is store-local (never sent by the backend as a `StatusEvent.phase`\n * value): `AgentStore.cancel()` sets it optimistically, and only a later,\n * genuine `status` event carries the phase on to `\"idle\"`.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type AgentPhase = \"thinking\" | \"working\" | \"idle\" | \"compacting\" | \"cancelling\";\n\n/**\n * Classification of an agent error, carried in `ErrorEvent.category`.\n *\n * The bridge's error classifier maps upstream errors to these categories so\n * consumers can apply per-category retry and display policies.\n *\n * @docLink packages/types/events#error-event\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 object used internally when classifying harness errors.\n *\n * Carries the error category, an optional HTTP status code, a retryability flag,\n * and an optional actionable hint for the user.\n *\n * @docLink packages/types/events#error-event\n */\nexport type AgentError = {\n message: string;\n category: ErrorCategory;\n statusCode?: number;\n retryable: boolean;\n hint?: string;\n};\n\n// ── Sync status (transient -- not persisted) ────────────────────────────────\n\n/**\n * Lifecycle phases of a mount's initial sync operation.\n *\n * Carried in `MountSyncStatusEvent.phase` and `SyncStatusEvent.phase`.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type SyncStatusPhase =\n | \"enumerating\"\n | \"stubs_ready\"\n | \"downloading\"\n | \"initial_sync_complete\"\n | \"error\";\n\n/**\n * Legacy alias for `MountSyncStatusEvent` — progress update for a mount sync operation.\n *\n * Carries the mount id, lifecycle phase, and file counts. Prefer `MountSyncStatusEvent`\n * for new code.\n *\n * @docLink packages/types/events#supporting-types\n */\nexport type SyncStatusEvent = {\n type: \"sync_status\";\n mountId: string;\n phase: SyncStatusPhase;\n totalFiles: number;\n downloadedFiles: number;\n stubFiles: number;\n message: string;\n};\n\n/**\n * Transient response to a `DebugCommand` — not persisted.\n *\n * Carries the original query string and the raw diagnostic data returned\n * by the runner's debug handler.\n *\n * @docLink packages/types/events#debug-result-event\n */\nexport type DebugResultEvent = {\n type: \"debug_result\";\n query: string;\n data: unknown;\n};\n\n/**\n * Transient — a single structured log entry from the in-container LogStore.\n * Forwarded by the runner's WsLogSink over the agent transport. The gateway\n * caches a fixed-size ring of these per session for late panel openers.\n * NEVER persisted to the message store — historical reads go through SQLite.\n *\n * @docLink packages/types/events#log-entry-event\n */\nexport type LogEntryEvent = {\n type: \"log_entry\";\n entry: LogEntry;\n};\n\n// ── Asset catalog events (transient — not persisted) ─────────────────────────\n\n/**\n * Transient — emitted when an asset fails schema validation during discovery.\n *\n * Carries the asset name, reason, and an optional suggestion for fixing the issue.\n * Not persisted.\n *\n * @docLink packages/types/events#agent-event\n */\nexport type ValidationWarningEvent = {\n type: \"validation_warning\";\n asset: string;\n reason: string;\n suggestion?: string;\n};\n\n/**\n * Transient — emitted when the skills catalog changes during a session.\n *\n * Carries the list of skills that were added or removed. Not persisted.\n *\n * @docLink packages/types/events#agent-event\n */\nexport type SkillsChangedEvent = {\n type: \"skills_changed\";\n skills: Array<{ name: string; action: string }>;\n};\n\n/**\n * Transient event carrying the agent's discovered slash commands — not persisted.\n *\n * Emitted after the runner discovers the available commands from skills and MCP servers.\n * Frontends use this to populate the slash-command picker.\n *\n * @docLink packages/types/events#commands-available-event\n */\nexport type CommandsAvailableEvent = {\n type: \"commands_available\";\n commands: Array<{\n name: string;\n description: string;\n argumentHint?: string;\n }>;\n};\n\n/**\n * Transient event emitted by the OMP harness after each turn completes.\n * Carries the OMP session ID that can be passed as `resumeSessionId` on the\n * next spawn so OMP restores its full conversation context natively — without\n * needing injected `<conversation_history>` blocks. Not persisted.\n *\n * @docLink packages/types/events#session-info-event\n */\nexport type SessionInfoEvent = {\n type: \"session_info\";\n /** The OMP session identifier (from `get_state` RPC response). */\n harnessSessionId: string;\n /** Absolute path to the JSONL session file written by OMP, if known. */\n sessionFile?: string;\n};\n\n// ---------------------------------------------------------------------------\n// System prompt composition (transient — not persisted)\n// ---------------------------------------------------------------------------\n\n/**\n * One labeled section of the assembled system prompt, as broken down by\n * the runner's session-builder. Single-entry labels (`context`, `prompt`,\n * `home`, `environment`, `resources`, `memory`) appear once; multi-entry labels\n * (`prompt-extensions`, `composition`, `additional`) appear once per\n * source.\n *\n * @since 2026-05\n */\nexport type SystemPromptSection = {\n label:\n | \"context\"\n | \"prompt\"\n | \"home\"\n | \"environment\"\n | \"resources\"\n | \"mcp-guidance\"\n | \"tool-activity\"\n | \"platform-blocks\"\n | \"memory\"\n | \"prompt-extensions\"\n | \"composition\"\n | \"additional\";\n value: string;\n /** File path, block id, or descriptor — present for multi-entry labels. */\n source?: string;\n};\n\n/**\n * Emitted by the runner after every `createAgentSession` call (initial\n * configure + every re-build path: `add_resource`, `remove_resource`,\n * `configure`). Carries the labeled section breakdown of the system\n * prompt the agent will receive. Transient — not persisted.\n *\n * @since 2026-05\n */\nexport type SystemPromptComposedEvent = {\n type: \"system_prompt_composed\";\n sections: SystemPromptSection[];\n /** ISO timestamp when the breakdown was produced. */\n composedAt: string;\n};\n\n/**\n * Transient — a breakdown of what occupies the session's context window.\n *\n * Emitted automatically after every turn (`trigger: \"turn-end\"`) and after a\n * successful compaction (`\"compaction\"`), and exactly once in answer to each\n * `get_context_usage` command, carrying that command's `requestId`\n * (`\"request\"`). Automatic snapshots never ask the provider to count tokens;\n * they reuse the last measured breakdown where one exists and estimate the\n * rest, so every bucket carries its own fidelity.\n *\n * @since protocol 4.7.0\n * @docLink packages/types/events#context-usage-event\n */\nexport type ContextUsageEvent = {\n type: \"context_usage\";\n snapshot: ContextUsageSnapshot;\n /** Correlates to the originating `get_context_usage` command; absent on automatic emissions. */\n requestId?: string;\n /**\n * Set when a requested measurement failed and the snapshot fell back to the\n * estimate-only path. The snapshot is still valid; this only explains its fidelities.\n */\n error?: string;\n};\n\n/**\n * Transient — the runner saw the AI provider reject a live request with a 401\n * (credential) or a 429 / subscription-limit rejection, attributed to the AI\n * provider config the session is pinned to.\n *\n * Exists because the platform's per-config health counters were fed only by a\n * slow sampled cron probe: a seat could be exhausted in live traffic and still\n * read as healthy, because the probe checks auth, not capacity. This is the\n * live signal (skaile-ai/workspaces#368, skaile-ai/platform#3539).\n *\n * Fire-and-forget: the runner never waits for it and never retries it, and a\n * platform with no handler for it broadcasts it harmlessly. Every field beyond\n * `status` is optional, and consumers MUST ignore fields they do not know — the\n * two halves of this signal ship independently.\n *\n * @category Events\n * @since 3.9.0\n */\nexport type ProviderResponseSeenEvent = {\n type: \"provider_response_seen\";\n /** 401 — the credential was rejected. 429 — an upstream rate/session limit. */\n status: 401 | 429;\n /** Platform `AIProviderConfig.id` the session is pinned 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 runner recognised something narrower than a\n * usage limit. `long-context-entitlement`: the account may not use a long\n * (1M) context window, so the seat is not out of quota. Diagnostic only:\n * the runner still fails over and counts the 429 as before. Consumers must\n * ignore values they do not know. Added in 4.11.0.\n */\n cause?: string;\n /** ISO-8601 timestamp of the observation. */\n observedAt: string;\n};\n\n/**\n * Transient — one upstream quota-window reading (claude-sdk `rate_limit_event`),\n * attributed to the AI provider config the session is pinned to. Emitted for\n * every status, not only rejections, and only when the reading changed since\n * the last one the runner sent for that `(configId, window)`.\n *\n * Exists because a `claude setup-token` seat's token cannot read the OAuth\n * usage endpoint, so live traffic is the only place its quota is visible. The\n * upstream reports `utilization` on warnings and rejections only; an `allowed`\n * reading carries the window and its reset, not a percentage.\n *\n * Fire-and-forget, like {@link ProviderResponseSeenEvent}: consumers MUST\n * ignore fields they do not know, and treat `window` / `status` as open sets.\n *\n * @category Events\n * @since 4.1.0\n */\nexport type ProviderQuotaObservedEvent = {\n type: \"provider_quota_observed\";\n /** Platform `AIProviderConfig.id` the session is pinned 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`, or a future value. */\n status: string;\n /** Fraction of the window consumed (0–1), only when the upstream reported it. */\n utilization?: number;\n /** Epoch seconds at which the window resets, only when reported. */\n resetsAt?: number;\n /** ISO-8601 timestamp of the observation. */\n observedAt: string;\n};\n","/**\n * Mentions — types for @-mention support in session messages.\n *\n * A Mention records who was addressed in a message, whether a specific user\n * or a well-known group. Group mentions carry a resolved array of user IDs\n * so consumers can perform membership checks without the resolver.\n */\n\n// ---------------------------------------------------------------------------\n// Groups\n// ---------------------------------------------------------------------------\n\n/**\n * Well-known group mention targets as a `const` array.\n *\n * Use this for validation or exhaustive checks against `MentionGroup`.\n *\n * @docLink packages/types/messages#mention\n */\nexport const MENTION_GROUPS = [\"agent\", \"humans\", \"humans_here\", \"here\", \"all\"] as const;\n\n/**\n * A well-known group that can be `@`-mentioned: `'agent' | 'humans' | 'humans_here' | 'here' | 'all'`.\n *\n * @docLink packages/types/messages#mention\n */\nexport type MentionGroup = (typeof MENTION_GROUPS)[number];\n\n// ---------------------------------------------------------------------------\n// Mention discriminated union\n// ---------------------------------------------------------------------------\n\n/**\n * A parsed `@`-mention in a session message. Records who was addressed — either a\n * specific user or a well-known group — along with the source text position.\n *\n * Group mentions carry a resolved array of user IDs so consumers can perform\n * membership checks without needing the resolver.\n *\n * @docLink packages/types/messages#mention\n */\nexport type Mention =\n | {\n type: \"user\";\n userId: string;\n name: string;\n /** Position of the `@` character in the source text. */\n offset: number;\n /** Length of the full `@token` string including the `@`. */\n length: number;\n }\n | {\n type: \"group\";\n group: MentionGroup;\n /** User IDs resolved at parse time (e.g. all online users for `@here`). */\n resolved: string[];\n /** Position of the `@` character in the source text. */\n offset: number;\n /** Length of the full `@token` string including the `@`. */\n length: number;\n }\n | {\n type: \"custom\";\n /** Consumer-defined mention kind, e.g. \"assistant\". */\n kind: string;\n /** User IDs this mention resolves to (so isMentioned works); may be empty. */\n resolved: string[];\n /** Optional consumer payload, e.g. { sessionId, ownerId }. */\n data?: Record<string, unknown>;\n /** Position of the `@` character in the source text. */\n offset: number;\n /** Length of the full `@token` string including the `@`. */\n length: number;\n };\n","/**\n * Agent Protocol — messages exchanged between agent client and server.\n *\n * AgentCommand: sent toward the agent (client → server)\n * AgentEvent: sent from the agent (server → client) — defined in events.ts\n *\n * Protocol v3 (since `@skaile/workspaces/types@4.0.0`, shipped 2026-05-10) removed\n * the following commands from the {@link AgentCommand} union: `configure` /\n * `ConfigureCommandV2`, `provision_secrets`, `request_access_token`,\n * `add_resource`, `remove_resource`, `set_log_level`, `state_action`,\n * `lifecycle`, `remount_mount`, `compact`, `reconfigure_agent`. Their\n * semantics ride on:\n * - {@link SessionInitCommand} (one deterministic envelope at session\n * start that delivers identity, resolved config, pre-minted credentials,\n * secrets, capabilities, shared state, active flows, resume hints, and\n * logging config), and\n * - `host.*` / `runner.*` capability invocations (bidirectional\n * capability registry).\n *\n * Spec: `_devlog/specs/2026-05-10-deterministic-session-bootstrap.md`.\n */\n\nimport type {\n CapabilityApproveCommand,\n CapabilityDeregisterCommand,\n CapabilityRegisterCommand,\n CapabilityResultCommand,\n} from \"./capabilities.js\";\nimport type {\n ConnectorContent,\n ConnectorOperation,\n ListOptions,\n ReadOptions,\n WriteRangeOptions,\n SearchOptions,\n StatOptions,\n} from \"./events.js\";\nimport type { ReplyRef } from \"./messaging.js\";\nimport type { TurnVisibility } from \"./turn-visibility.js\";\n\n/**\n * Text and scoped attachments; unsupported harnesses must reject attachments explicitly.\n * `toolAllowlist` restricts the tools this one turn may call; a harness that\n * cannot enforce it must reject the input rather than run the turn unrestricted.\n */\nexport interface AgentPromptInput {\n text: string;\n attachments?: Array<\n | { type: \"image\"; path: string }\n | { type: \"file\"; path: string; name: string }\n | { type: \"skill\"; path: string; name: string }\n >;\n toolAllowlist?: string[];\n}\n\n/**\n * The kinds of platform-originated content a prompt can carry. Each renders in\n * its own reserved tag: `<PLATFORM_NOTICE>`, `<SKAILE_RESEARCH>`,\n * `<PLATFORM_RESEARCH_COMPLETE>`.\n *\n * @since 4.18.0\n */\nexport type PlatformBlockKind =\n | \"platform_notice\"\n | \"skaile_research\"\n | \"platform_research_complete\";\n\n/**\n * Platform-originated content riding a `prompt` command. Only the host sets it;\n * nothing a person, peer or webhook writes reaches this field. The runner is the\n * single render point: it puts each block in its reserved tag at the very start\n * of the turn, renders a block id at most once per runner process, and escapes\n * the reserved tag names in every other text it passes to the agent.\n *\n * `attrs` become extra tag attributes; keys that are not plain identifiers are\n * dropped, values are escaped.\n *\n * @since 4.18.0\n */\nexport type PlatformBlock = {\n kind: PlatformBlockKind;\n id: string;\n text: string;\n attrs?: Record<string, string>;\n};\n\n/**\n * Runtime feature a runner lists in `protocol_info.runtimeFeatures` when it\n * renders {@link PlatformBlock}s **and** enforces the per-turn `toolAllowlist`\n * of a `prompt` command. A host attaches neither to a runner that does not\n * announce it. A later addition to either gets a new flag.\n *\n * @since 4.18.0\n */\nexport const PLATFORM_BLOCKS_RUNTIME_FEATURE = \"platformBlocks.v1\";\n\n/**\n * Discriminated union of all commands sent from client to agent server.\n *\n * Narrow via `command.type` or a `switch` statement.\n *\n * @docLink packages/types/protocol-v3#agent-command\n */\nexport type AgentCommand =\n // `messageId` is an opt-in receipt-correlation token (Protocol 3.8). When\n // present the runner MUST emit exactly one `prompt_ack` carrying it back,\n // as the first act of handling the prompt — before any readiness gate that\n // could swallow it. Absent, the prompt is fire-and-forget as in 3.7.\n // `senderId` (4.14) is the user who sent it, the same id as\n // `MessageMeta.senderId`; a `cancel` from that user drops it while it waits.\n // `platformBlocks` and `toolAllowlist` (4.18, runtime feature\n // `platformBlocks.v1`): see PlatformBlock. With a `toolAllowlist` the turn may\n // call only the listed tools; a runner that cannot enforce it, or that does\n // not recognize a listed name, refuses the prompt with a non-fatal `error`.\n // `visibilityMode` and `privateRecipientIds` (5.1, runtime feature\n // `turnVisibility.v1`): a `\"Private\"` prompt's turn output is stamped with\n // both, as TurnVisibility; the host has already resolved the human readers.\n | {\n type: \"prompt\";\n prompt: string;\n attachments?: AgentPromptInput[\"attachments\"];\n replyTo?: ReplyRef;\n messageId?: string;\n senderId?: string;\n platformBlocks?: PlatformBlock[];\n toolAllowlist?: string[];\n visibilityMode?: TurnVisibility[\"visibilityMode\"];\n privateRecipientIds?: string[];\n }\n // `question` binds the answer to the sub-question it belongs to, verbatim from\n // the `question` event that asked it. Omit it and the answer fills the next\n // unanswered slot in order — correct only while the host answers top-down.\n | { type: \"reply\"; answer: string; question?: string; requestId?: string }\n // `senderId` (4.14) is the user who pressed Stop. With it the runner also\n // drops that user's queued prompts and reports them in\n // `queued_prompts_dropped`; without it only the running turn is aborted.\n | { type: \"cancel\"; senderId?: string }\n | { type: \"shutdown\" }\n | ConnectorRequestCommand\n | DebugCommand\n | ConnectorMutateCommand\n | ConnectorQueryCommand\n | ConnectorConfigCommand\n | StateUpdateCommand\n | CustomMessageCommand\n | GetContextUsageCommand\n // Protocol v2 capability commands.\n | CapabilityRegisterCommand\n | CapabilityDeregisterCommand\n | CapabilityResultCommand\n | CapabilityApproveCommand;\n\n// ---------------------------------------------------------------------------\n// Resource declaration types (retained for capability inputs)\n// ---------------------------------------------------------------------------\n\n/**\n * A resource declaration carried by `runner.add_mount` / `runner.add_connector`\n * capability invocations. Mirrors the `skaile.yaml` mount/connector schema\n * but flattened for transport.\n *\n * Used by:\n * - {@link ResolvedSkaileConfig.mounts} / `.connectors` (lifecycle.ts)\n * - `runner.add_mount.input.declaration` / `runner.add_connector.input.declaration`\n *\n * @docLink packages/types/protocol-v3#resource-declaration\n */\nexport type ResourceDeclaration = {\n id: string;\n driver: string;\n source: string;\n target?: string;\n access: \"read-only\" | \"read-write\";\n auth?: string;\n /**\n * Identifier of the `ProviderLink` this resource is bound to when\n * `auth: 'backend'`. Read by the platform credential mediator to dispatch\n * the mint (and re-read by the runner when an `exposeAccessToken` git\n * mount needs to surface a managed-gitconfig credential helper). Optional\n * because not every backend-auth driver is provider-linked, and not every\n * resource uses backend auth.\n */\n providerLinkId?: string;\n options?: Record<string, unknown>;\n};\n\n/**\n * Migration strategy carried by `runner.add_mount.input.migration` when\n * replacing the workspace mount of an empty project.\n *\n * @docLink packages/types/protocol-v3#resource-migration\n */\nexport type ResourceMigration =\n | { strategy: \"replace-workspace\"; targetFolder?: string | null }\n | { strategy: \"none\" };\n\n// ---------------------------------------------------------------------------\n// Generic connector mutation / query (Protocol 2.2 — kept in v3)\n// ---------------------------------------------------------------------------\n//\n// Phase 4 of the flow-connector extraction removed the 6 typed flow commands\n// (`start_flow`, `approve_flow_node`, `provide_flow_input`, `cancel_flow`,\n// `set_flow_autonomous_mode`, `retry_flow_node`) plus the implicit\n// `configure.activeFlows` rehydration. Every removed command is reachable\n// via `connector_mutate` against the `flow` connector — see\n// `MIGRATION-flow-connector.md` for the per-op mapping table.\n\n/**\n * Generic connector mutation. Routes to ConnectorManager.executeOp(id, op, payload).\n * Replaces the typed flow commands in Protocol 2.2 — see\n * MIGRATION-flow-connector.md for the per-op mapping table.\n *\n * @docLink packages/types/protocol-v3#connector-mutate-command\n * @since 2.2.0\n */\nexport type ConnectorMutateCommand = {\n type: \"connector_mutate\";\n /** Target connector id (matches `connectors[].id` in skaile.yaml). */\n id: string;\n /** Operation name as declared by the adapter's describeOperations(). */\n op: string;\n /** Operation arguments. Adapter-specific shape. Optional for nullary ops. */\n payload?: Record<string, unknown>;\n /**\n * Opt-in acknowledgement correlation (Protocol 3.7). When present the runner\n * MUST emit exactly one `connector_mutate_response` carrying this `requestId`.\n * When absent the command is fire-and-forget, byte-identical to 3.6 behaviour.\n */\n requestId?: string;\n};\n\n/**\n * Generic connector read. Same dispatch as connector_mutate but the result\n * is returned to the caller as a `connector_query_response` event correlated\n * by `requestId`. Use for read-only queries that should not kick a turn.\n *\n * @since 2.2.0\n */\nexport type ConnectorQueryCommand = {\n type: \"connector_query\";\n requestId: string;\n id: string;\n op: string;\n payload?: Record<string, unknown>;\n};\n\n/**\n * Ask the runner for a breakdown of the session's context window.\n *\n * Answered by exactly one `context_usage` event carrying the same `requestId`,\n * whatever happens — a failed measurement falls back to an estimate and says so\n * in the event's `error`. `detail: \"measured\"` (the default) asks the harness to\n * count natively where it can; for claude-sdk that includes a `count_tokens`\n * round-trip that uploads the whole conversation, so hosts should request it\n * on demand rather than on a timer. `\"estimated\"` makes no provider call: the\n * harness answers from local estimates (or not at all) and the runner fills the\n * rest. A runner below protocol 4.7 ignores the command.\n *\n * @docLink packages/types/protocol-v3#get-context-usage-command\n * @since 4.7.0\n */\nexport type GetContextUsageCommand = {\n type: \"get_context_usage\";\n requestId: string;\n detail?: \"measured\" | \"estimated\";\n};\n\n/**\n * Query the internal state of a running agent server for diagnostics.\n *\n * @docLink packages/types/protocol-v3#debug-command\n */\nexport type DebugCommand = {\n type: \"debug\";\n query: \"tools\" | \"connectors\" | \"mcp\" | \"config\" | \"state\" | \"commands\";\n args?: Record<string, unknown>;\n};\n\n/**\n * Reserved `ConnectorRequestCommand.connectorId` that addresses the session's\n * own root directory (the runner's project dir, `/skaile` in a container)\n * rather than a mount. Only `write` and `delete` are served, and only for\n * `skaile.yaml`, `.skaile/assets/**` and `.skaile/chat-files/**`. It is never\n * registered as a connector, so the agent's prompt and the\n * `resources_available` lists do not show it. The runner routes this id\n * before any connector lookup, so a connector declared with it is unreachable\n * through `resource_request`.\n */\nexport const SESSION_ROOT_CONNECTOR_ID = \"@session\";\n\n/**\n * Browse or modify connectors from the frontend.\n *\n * The wire `type:` string is `\"resource_request\"` for protocol stability.\n * The server responds with a `ConnectorResponseEvent` correlated by `requestId`.\n *\n * @docLink packages/types/protocol-v3#connector-request-command\n */\nexport type ConnectorRequestCommand = {\n type: \"resource_request\";\n /** UUID for request/response correlation. */\n requestId: string;\n /** Connector ID (e.g. \"docs\", \"project-db\"). */\n connectorId: string;\n /** Operation to perform. */\n operation: ConnectorOperation;\n /** Target path (directory, file, key, etc.). */\n path?: string;\n /** Operation-specific options (ListOptions, SearchOptions, StatOptions, ReadOptions, WriteRangeOptions). */\n options?: ListOptions | SearchOptions | StatOptions | ReadOptions | WriteRangeOptions;\n /** Content payload for write operations. */\n content?: ConnectorContent;\n};\n\n/**\n * Sent by the frontend to add, remove, or refresh connectors at runtime without a session restart.\n *\n * @docLink packages/types/protocol-v3#connector-config-command\n */\nexport interface ConnectorConfigCommand {\n type: \"connector_config\";\n action: \"add\" | \"remove\" | \"refresh\";\n /** Required when action === \"add\". */\n declaration?: {\n id: string;\n driver: string;\n access?: \"read-only\" | \"read-write\";\n options?: Record<string, unknown>;\n };\n /** Required when action === \"remove\". */\n connectorId?: string;\n}\n\n/**\n * Client/component writes shared state to the runtime.\n *\n * Store namespace must start with `\"app\"` or `\"component:\"` when sent from the client.\n *\n * @docLink packages/types/protocol-v3#state-update-command\n */\nexport type StateUpdateCommand = {\n type: \"state_update\";\n /** Store namespace — must start with \"app\" or \"component:\" from client. */\n store: string;\n /** Full state snapshot (replaces previous). */\n state: Record<string, unknown>;\n};\n\n/**\n * User-originated message with a custom type (from input extensions).\n *\n * Unlike a plain `prompt`, a custom message carries structured data\n * (`customType` + `customData`) alongside the text content. The agent\n * receives these on the `finished` event as `customType`/`customData`\n * fields. On the frontend, the custom message is rendered by the\n * matching dynamic component (or its fallback template).\n *\n * @docLink packages/types/protocol-v3#custom-message-command\n */\nexport type CustomMessageCommand = {\n type: \"custom_message\";\n /** Plain-text content (backward-compatible summary). */\n content: string;\n /** Custom message type identifier (e.g. \"gif\"). */\n customType: string;\n /** Structured data for the custom message type. */\n customData: Record<string, unknown>;\n};\n","/**\n * Turn visibility — the visibility a chat turn's output inherits from the\n * prompt that started it (protocol 5.1.0).\n */\n\n/**\n * Visibility a runner stamps on the output events of a turn started by a\n * private prompt, copied from that prompt's `prompt` command.\n *\n * Only `\"Private\"` is ever stamped. Work a private turn started keeps its\n * stamp after the turn ends: a background subagent's tool calls and results\n * (by `parentToolUseId`) and a self-started turn that reads a background task\n * the private turn launched. While background tasks run, a capability call\n * (which carries no `parentToolUseId`) is stamped with the readers the running\n * turn and every running task's launching turn share, or withheld and refused\n * when they share none. A turn started by a Public prompt, and a turn no\n * prompt started (a flow turn, a peer prompt), carries neither field.\n *\n * Once a private turn has run, a content event whose readers the runner cannot\n * establish (an unseen `parentToolUseId`, a self-started turn naming no task it\n * knows) is withheld: dropped, or for `finished` / `error` sent with its\n * content removed. It is never sent Public or with another turn's readers.\n *\n * **Invariant (NOT enforced by the type system):** when `visibilityMode` is\n * `\"Private\"`, `privateRecipientIds` is non-empty and names only humans (the\n * prompt's sender plus its human recipients); the `\"__agent__\"` sentinel is\n * never in it, so the answer is never readable by the agent alone.\n */\nexport type TurnVisibility = {\n /** `\"Private\"` on every output event of a private prompt's turn; absent otherwise. */\n visibilityMode?: \"Public\" | \"Private\" | \"HumansOnly\";\n /** The human readers of the turn's output. Non-empty whenever `visibilityMode` is `\"Private\"`. */\n privateRecipientIds?: string[];\n};\n\n/**\n * The event types a runner stamps with {@link TurnVisibility} while a private\n * prompt's turn runs: the turn's content. Status, file-change and session\n * events stay unstamped, so other members still see that the agent is busy\n * and which files it touched, never what it said.\n */\nexport const TURN_VISIBILITY_EVENT_TYPES = [\n \"text\",\n \"text_retract\",\n \"tool_call\",\n \"tool_result\",\n \"question\",\n \"question_reply\",\n \"error\",\n \"subagent\",\n \"finished\",\n \"custom_message\",\n \"capability_invoked\",\n \"render_invoked\",\n] as const;\n\n/**\n * Runtime feature a runner lists in `protocol_info.runtimeFeatures` when it\n * stamps a private prompt's turn output with {@link TurnVisibility}. An older\n * runner ignores the prompt's visibility fields and sends the answer unstamped,\n * so a host feature-detects on this flag before relying on the stamp.\n *\n * @since 5.1.0\n */\nexport const TURN_VISIBILITY_RUNTIME_FEATURE = \"turnVisibility.v1\";\n","/**\n * Reactions -- emoji reactions on session messages.\n *\n * Any session participant (user or agent) can react to any message.\n * Reactions are persisted in a dedicated DB model and broadcast as\n * transient events for real-time updates.\n */\n\n/**\n * A single emoji reaction on a message, set by any session participant (user or agent).\n *\n * Reactions are persisted in a dedicated DB model and broadcast as transient events\n * for real-time updates.\n *\n * @docLink packages/types/messages#reaction\n */\nexport type Reaction = {\n /** Unicode emoji character (e.g. \"thumbs up\", not \":thumbsup:\"). */\n emoji: string;\n /** ID of the user (or \"agent\" for agent reactions). */\n userId: string;\n /** Display name at reaction time (avoids extra lookups for tooltip rendering). */\n userName: string;\n /** Unix epoch milliseconds. */\n timestamp: number;\n};\n\n/**\n * Quick-access emojis shown in the reaction bar picker.\n *\n * An `as const` array of eight Unicode emoji characters in display order.\n *\n * @docLink packages/types/messages#reaction\n */\nexport const QUICK_REACTIONS = [\n \"\\u{1F44D}\",\n \"\\u{1F440}\",\n \"\\u2705\",\n \"\\u2764\\uFE0F\",\n \"\\u{1F914}\",\n \"\\u{1FAE1}\",\n \"\\u{1F44F}\",\n \"\\u{1F389}\",\n] as const;\n","/**\n * Capability layer — Protocol v2's unified registry of LLM-invokable entry points.\n *\n * A {@link Capability} is a named, schema-typed entry point that the LLM can call\n * during a session. Capabilities are registered into a per-session\n * registry by either side (host platform via `side: 'client'` or runtime via\n * `side: 'agent'`) and routed by the bridge at invocation time.\n *\n * This module defines the wire types only; the runtime registry, the\n * `defineCapability` helper, and the per-handler logger live in\n * `@skaile/workspaces/runner`.\n *\n * @see {@link MessageV2} envelope that carries capability commands and events\n * @see {@link ProtocolVersion} for the version contract\n *\n * @category Capabilities\n * @since 2.0.0\n */\n\nimport type { TurnVisibility } from \"./turn-visibility.js\";\n\n// ---------------------------------------------------------------------------\n// Capability shape\n// ---------------------------------------------------------------------------\n\n/**\n * Visibility scope for a capability. Determines which surfaces the capability\n * appears on and which callers can invoke it.\n *\n * - `'llm'`: registered as an LLM tool, surfaced in the `<CAPABILITIES>` system\n * prompt section. The agent harness can invoke it.\n * - `'user'`: appears in user-facing surfaces — the command palette (cmdK),\n * debug menus, capability lists.\n * - `'runtime'`: invocable only by trusted runner / platform code paths. Never\n * reaches the LLM tool list. Never reaches the command palette. Used for\n * host RPCs (`host.refresh_credential`, `host.audit`, `host.notify_user`,\n * `host.persist_compaction_attempt`) and runner RPCs (`runner.add_mount`,\n * `runner.set_log_level`, `runner.lifecycle`, ...).\n *\n * Multiple audiences are allowed (e.g. `['llm', 'user']`). The default when\n * {@link Capability.audience} is omitted is `['llm', 'user']`, preserving the\n * v2.x default visibility for capabilities that haven't migrated yet.\n *\n * @category Capabilities\n * @since 3.0.0\n * @docLink packages/types/capabilities#capability-audience\n */\nexport type CapabilityAudience = \"llm\" | \"user\" | \"runtime\";\n\n/**\n * Source of truth for who registered a capability. Used for trust enforcement\n * (the bridge rejects mismatches between registering side and origin kind)\n * and for the `capability:<origin>:<name>` log taxonomy.\n *\n * Variants:\n * - `framework`: built-in (e.g. `__capabilities.list`)\n * - `client`: host platform (e.g. `platform.react`)\n * - `agent`: self-registered by the agent runtime\n * - `flow`: injected by an active flow execution\n * - `skill`: from a skill's MCP surface\n * - `mcp`: from a generic MCP server\n * - `connector`: from a connector (e.g. `postgres.query`)\n * - `app`: from an embedded, agent-controllable app (carries the originating\n * `appId`). Handlers run in the app itself — see {@link Capability.side} `'app'`.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/types/capabilities#capability-origin\n */\nexport type CapabilityOrigin =\n | { kind: \"framework\" }\n | { kind: \"client\" }\n | { kind: \"agent\" }\n | { kind: \"flow\"; flowId: string }\n | { kind: \"skill\"; skillId: string }\n | { kind: \"mcp\"; serverId: string }\n | { kind: \"connector\"; connectorId: string }\n | { kind: \"app\"; appId: string };\n\n/**\n * Render contract for a capability that produces a UI surface when invoked.\n *\n * When the LLM invokes a capability whose `render` is set, the bridge emits\n * a {@link RenderInvokedEvent} carrying the capability name and props. The\n * client renders the configured `source` at the chosen `target`. Clients\n * without a render layer can fall back to the markdown `fallback` template.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/types/capabilities#render-spec\n */\nexport type RenderSpec = {\n /** Where the rendered component lives. */\n source: { kind: \"web-component\"; url: string; tagName: string } | { kind: \"iframe\"; url: string };\n /** Render placements supported by the component. */\n targets: (\"chat\" | \"preview\" | \"modal\" | \"input-extension\")[];\n /** Markdown template with `{{prop}}` placeholders for clients without a render layer. */\n fallback?: string;\n /** True when props may be partial during streaming. */\n streaming?: boolean;\n /** Interaction names the rendered component may fire back as state events. */\n interactions?: string[];\n};\n\n/**\n * A named, schema-typed entry point that the LLM can invoke during a session.\n *\n * Capabilities can be declared statically (via `ConfigureCommand.capabilities`)\n * or dynamically (via {@link CapabilityRegisterCommand} /\n * {@link CapabilityRegisterEvent}). They are cached for replay across\n * subscriber reconnects and session hibernation.\n *\n * @example Defining a client-side fire-and-forget tool (uses the runner's\n * `defineCapability` helper, which serializes a {@link Capability} to the wire):\n * ```ts\n * const reactTool = defineCapability({\n * name: 'platform.react',\n * description: 'Acknowledge a user message with a Unicode emoji.',\n * side: 'client',\n * origin: { kind: 'client' },\n * fireAndForget: true,\n * input: z.object({ emoji: z.string(), targetSeq: z.number().optional() }),\n * handler: async ({ emoji, targetSeq }, ctx) => { ... },\n * });\n * ```\n *\n * @see {@link RenderCapability} for capabilities that render UI components\n * @see {@link CapabilityOrigin} for who-registered-it metadata\n * @see {@link isRenderCapability} for the type-guard\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/types/capabilities#capability\n */\nexport type Capability = {\n /** Unique within a session. Convention: namespaced as `<origin>.<name>` (e.g. `platform.react`, `ui.gif`). */\n name: string;\n /**\n * Human-readable label for user-facing surfaces (cmdK action palette,\n * capability menus, debug panels). Falls back to {@link Capability.name}\n * when omitted. Pure presentation — the LLM sees `name`, not `displayName`.\n */\n displayName?: string;\n /** Human/LLM-readable summary. Shown to the LLM as part of tool registration. */\n description: string;\n /** JSON Schema validating the invocation arguments. Authored as Zod, converted at register time. */\n inputSchema: Record<string, unknown>;\n /** Optional return shape. Omit for fire-and-forget effects. */\n outputSchema?: Record<string, unknown>;\n /** Where the handler runs. `client` = host platform, `agent` = runtime/skill/connector, `app` = embedded app. */\n side: \"client\" | \"agent\" | \"app\";\n /** Discriminated tag identifying who registered the capability. Used for trust enforcement and audit. */\n origin: CapabilityOrigin;\n /** Lifetime: `session` survives the whole session, `turn` is dropped at end-of-turn. */\n scope?: \"session\" | \"turn\";\n /** When true, the bridge auto-resolves with `{}` immediately and runs the handler in the background. */\n fireAndForget?: boolean;\n /** When true, the platform shows a confirm UI before dispatch and waits for {@link CapabilityApproveCommand}. */\n requiresApproval?: boolean;\n /** Documentation hint (not enforced) describing whether this is a side-effect, render, or pure query. */\n kind?: \"effect\" | \"render\" | \"query\";\n /**\n * Whether this capability should be exposed in user-facing surfaces (cmdK\n * action palette, capability menus). When omitted, the consumer applies a\n * default per-origin via {@link isUserInvokable}.\n *\n * - `true`: surface in cmdK and capability menus.\n * - `false`: hide from user surfaces (LLM-only or low-level).\n * - `undefined`: defer to {@link isUserInvokable}'s inference rules.\n *\n * @deprecated Set {@link Capability.audience} instead. `userInvokable` is\n * kept as a read-only shim for v2.x consumers and is honoured by\n * {@link isUserInvokable} when {@link Capability.audience} is absent.\n */\n userInvokable?: boolean;\n /**\n * Audience scoping for this capability. See {@link CapabilityAudience} for\n * the meaning of each value and combinations.\n *\n * When omitted, consumers treat the capability as `['llm', 'user']` (the\n * v2.x default). Host RPCs and runner RPCs MUST set this to `['runtime']`\n * so they never leak to the LLM tool list or the user-facing surfaces.\n *\n * @category Capabilities\n * @since 3.0.0\n */\n audience?: CapabilityAudience[];\n /** Appended to the system prompt's `<CAPABILITIES>` section. Use for usage hints the LLM should always see. */\n promptFragment?: string;\n /**\n * Per-capability override for how long the runner waits on the\n * `capability_result` round-trip before timing out. When omitted the\n * runner applies its default (`DEFAULT_CAPABILITY_CALL_TIMEOUT_MS`, 60s).\n *\n * Set this for capabilities that legitimately block far longer than a\n * normal tool call — e.g. `platform.ask_session` suspends the caller's\n * turn until a peer session answers, which can take minutes.\n *\n * @category Capabilities\n * @since 3.3.0\n */\n callTimeoutMs?: number;\n /** Present iff this is a render capability — see {@link RenderCapability}. */\n render?: RenderSpec;\n};\n\n/**\n * A {@link Capability} that produces a UI surface when invoked. The narrowed\n * type guarantees `render` is set, which simplifies frontend lookup.\n *\n * @see {@link isRenderCapability}\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/types/capabilities#render-capability\n */\nexport type RenderCapability = Capability & { render: NonNullable<Capability[\"render\"]> };\n\n/**\n * Type-guard for {@link RenderCapability}. Use after {@link Capability}\n * lookup to narrow the type before reading `render`.\n *\n * @example\n * ```ts\n * for (const cap of registry.list()) {\n * if (isRenderCapability(cap)) console.log(cap.render.targets);\n * }\n * ```\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/types/capabilities#is-render-capability\n */\nexport function isRenderCapability(cap: Capability): cap is RenderCapability {\n return cap.render !== undefined;\n}\n\n/**\n * Decide whether a capability should be surfaced in user-facing actions\n * (cmdK action palette, capability menus).\n *\n * Resolution order (first match wins):\n *\n * 1. {@link Capability.audience} is set — return `audience.includes('user')`.\n * Capabilities scoped to `'runtime'` only never appear in user surfaces.\n * 2. {@link Capability.userInvokable} is set (v2.x shim) — return that value.\n * 3. Default per-origin inference table below.\n *\n * Default-inference rules (when both `audience` and `userInvokable` are\n * omitted):\n * | Origin | Default |\n * | ------------ | ---------------------------------------------------------------------- |\n * | `framework` | `false` (LLM discovery surfaces, e.g. `__capabilities.list`) |\n * | `client` | `false` (platform ack tools — `platform.react`, `platform.pass`) |\n * | `agent` | `false` (agent-defined; assume internal unless flagged) |\n * | `flow` | `false` (per-cap opt-in) |\n * | `connector` | `false` (low-level FS / data ops) |\n * | `mount` | `false` (low-level FS ops) |\n * | `app` | `false` (LLM-only; app authors opt in via `audience: ['llm','user']`) |\n * | `mcp` | `true` if `kind === 'effect'`, else `false` |\n * | `skill` | `true` if `kind` ∈ {`effect`, `render`}, else `false` |\n *\n * @example\n * ```ts\n * for (const cap of capabilities.values()) {\n * if (isUserInvokable(cap)) registerCommandPaletteAction(cap);\n * }\n * ```\n *\n * @category Capabilities\n * @since 2.1.0\n * @docLink packages/types/capabilities#is-user-invokable\n */\nexport function isUserInvokable(cap: Capability): boolean {\n if (cap.audience !== undefined) {\n return cap.audience.includes(\"user\");\n }\n if (cap.userInvokable !== undefined) {\n return cap.userInvokable;\n }\n switch (cap.origin.kind) {\n case \"framework\":\n case \"client\":\n case \"agent\":\n case \"flow\":\n case \"connector\":\n case \"app\":\n return false;\n case \"mcp\":\n return cap.kind === \"effect\";\n case \"skill\":\n return cap.kind === \"effect\" || cap.kind === \"render\";\n default:\n return false;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Capability commands (client → agent)\n// ---------------------------------------------------------------------------\n\n/**\n * Register one or more capabilities mid-session (client → agent).\n *\n * The platform sends this when a new client-side tool becomes available\n * after `configure` has already returned (e.g. a user installs a new\n * extension during the session).\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/types/capabilities#capability-register-command\n */\nexport type CapabilityRegisterCommand = {\n type: \"capability_register\";\n capabilities: Capability[];\n};\n\n/**\n * Deregister capabilities by name (client → agent). Names that are not\n * currently registered are ignored silently.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/types/capabilities#capability-deregister-command\n */\nexport type CapabilityDeregisterCommand = {\n type: \"capability_deregister\";\n names: string[];\n};\n\n/**\n * Return the result of a previously {@link CapabilityInvokedEvent | invoked} client-side\n * capability (client → agent). Bridges that registered the capability with\n * `fireAndForget: true` MAY skip this command; the bridge auto-resolves with `{}`.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/types/capabilities#capability-result-command\n */\nexport type CapabilityResultCommand = {\n type: \"capability_result\";\n /** Correlation token matching the {@link CapabilityInvokedEvent.callId}. */\n callId: string;\n /** Successful result payload, or an error envelope. */\n result: unknown | { error: string };\n};\n\n/**\n * Invoke an **agent-side** capability (client → agent). The host names the\n * capability and supplies its input; the runner answers with a matching\n * {@link CapabilityResultEvent}. The mirror of {@link CapabilityInvokedEvent},\n * which reports the LLM invoking a client-side capability in the opposite\n * direction and shares this discriminant.\n *\n * @category Capabilities\n * @since 3.23.0\n * @docLink packages/types/capabilities#capability-invoke-command\n */\nexport type CapabilityInvokeCommand = {\n type: \"capability_invoked\";\n /** Correlation token the answering {@link CapabilityResultEvent} echoes. */\n callId: string;\n /** Name of the {@link Capability} to invoke. */\n name: string;\n /** Input payload, validated against the capability's schema by the registry. */\n input: unknown;\n};\n\n/**\n * Return the result of a platform-invoked **agent-side** capability\n * (agent → client). The mirror of {@link CapabilityResultCommand}, which\n * carries the same shape in the opposite direction for client-side\n * capabilities; `runner.attach_instance` and its `runner.*` siblings answer\n * with this one.\n *\n * Both directions share the `capability_result` discriminant, so the sender\n * decides which type applies — they are never both valid on one hop.\n *\n * @category Capabilities\n * @since 3.23.0\n * @docLink packages/types/capabilities#capability-result-event\n */\nexport type CapabilityResultEvent = {\n type: \"capability_result\";\n /** Correlation token matching the invoking call. */\n callId: string;\n /**\n * Successful result payload, or a failure. A failed call answers\n * `{ ok: false, code, message, error }` (`error` repeats `message`); a handler's own\n * refusal may omit `error`.\n */\n result: unknown | { error: string } | { ok: false; code: string; message: string };\n};\n\n/**\n * Approve or reject a capability call that was invoked with\n * `requiresApproval: true` (client → agent). The platform shows a confirm\n * UI and forwards the user's decision via this command.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/types/capabilities#capability-approve-command\n */\nexport type CapabilityApproveCommand = {\n type: \"capability_approve\";\n /** Correlation token matching the {@link CapabilityInvokedEvent.callId}. */\n callId: string;\n /** User's decision. */\n decision: \"approved\" | \"rejected\";\n /** Optional rationale stored alongside the decision for audit. */\n feedback?: string;\n /** User ID of the decider (informational — framework enforces no policy). */\n decidedBy: string;\n};\n\n// ---------------------------------------------------------------------------\n// Capability events (agent → client)\n// ---------------------------------------------------------------------------\n\n/**\n * Register one or more capabilities mid-session (agent → client). Mirrors\n * {@link CapabilityRegisterCommand} for the agent-initiated direction; used\n * when the runtime adds a capability after `configure` (e.g. when a flow\n * starts and injects flow-scoped tools).\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/types/capabilities#capability-register-event\n */\nexport type CapabilityRegisterEvent = {\n type: \"capability_register\";\n capabilities: Capability[];\n};\n\n/**\n * Deregister capabilities by name (agent → client).\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/types/capabilities#capability-deregister-event\n */\nexport type CapabilityDeregisterEvent = {\n type: \"capability_deregister\";\n names: string[];\n};\n\n/**\n * Notify the client that a capability has been invoked by the LLM (agent →\n * client). For client-side capabilities the platform's handler runs in\n * response to this event and replies with {@link CapabilityResultCommand}.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/types/capabilities#capability-invoked-event\n */\nexport type CapabilityInvokedEvent = TurnVisibility & {\n type: \"capability_invoked\";\n /** Correlation token for the eventual {@link CapabilityResultCommand}. */\n callId: string;\n /** Name of the invoked {@link Capability}. */\n name: string;\n /** Validated input payload (already conforms to the capability's `inputSchema`). */\n input: unknown;\n /** In v2.0.0 the LLM is the only invoker. */\n invokedBy: \"agent\";\n};\n\n/**\n * Notify the client that a render capability should be drawn (agent →\n * client). Emitted alongside {@link CapabilityInvokedEvent} when the\n * invoked capability's `render` block is populated.\n *\n * Clients without a render layer can fall back to the capability's\n * `render.fallback` markdown template.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/types/capabilities#render-invoked-event\n */\nexport type RenderInvokedEvent = TurnVisibility & {\n type: \"render_invoked\";\n /** Name of the invoked render capability. */\n capabilityName: string;\n /** Props passed to the rendered component (already conforms to `inputSchema`). */\n props: unknown;\n /** Correlation token shared with the matching {@link CapabilityInvokedEvent}. */\n callId: string;\n};\n","/**\n * Agent-authored tool-call activity labels.\n *\n * Every tool the runtime advertises to the model carries one extra optional\n * string parameter, {@link TOOL_ACTIVITY_LABEL_PARAM}, in which the agent\n * describes the call in plain language (\"Reading the Q3 budget spreadsheet\").\n * The normalizer surfaces it as `ToolCallEvent.label` so the chat can show it\n * instead of the raw tool name and arguments.\n *\n * The parameter is added at the ADVERTISE layer only and stripped before the\n * real handler runs. It never enters a capability's registered `inputSchema`,\n * because that schema is hashed into the resume signature.\n *\n * Zod is passed in rather than imported: the Claude SDK and the bridge each\n * bring their own zod instance, and the schema must be built with the one the\n * SDK validates against.\n *\n * @category Tools\n * @since 3.24.0\n */\n\n/** Name of the optional parameter injected into every advertised tool schema. */\nexport const TOOL_ACTIVITY_LABEL_PARAM = \"activity_label\";\n\n/** Longest label the normalizer passes on; longer text is truncated with an ellipsis. */\nexport const TOOL_ACTIVITY_LABEL_MAX_CHARS = 120;\n\n/** LLM-facing description of {@link TOOL_ACTIVITY_LABEL_PARAM}. */\nexport const TOOL_ACTIVITY_LABEL_DESCRIPTION =\n \"Short plain-language description (under ~12 words, present tense) of what this call does, \" +\n \"shown to the user while it runs, e.g. 'Reading the Q3 budget spreadsheet'. \" +\n \"Never include secrets.\";\n\n/** System-prompt guidance telling the agent to fill the label on every call. */\nexport const TOOL_ACTIVITY_PROMPT_SECTION = [\n \"## Tool-call activity labels\",\n \"\",\n `Whenever a tool offers an \\`${TOOL_ACTIVITY_LABEL_PARAM}\\` parameter, always fill it. For the Bash tool, always fill its \\`description\\` parameter.`,\n \"The text is shown to the user while the call runs, in place of the tool's technical details, so write it for a non-technical reader:\",\n \"under ~12 words, present tense, naming the thing being worked on (e.g. 'Reading the Q3 budget spreadsheet', 'Checking which invoices are overdue').\",\n \"Never put secrets, tokens or raw file contents in it.\",\n].join(\"\\n\");\n\n/**\n * Add {@link TOOL_ACTIVITY_LABEL_PARAM} to a zod raw shape (a record of zod\n * fields, as `createSdkMcpServer` accepts). Returns the shape unchanged when\n * the tool already declares a property of that name.\n */\nexport function withActivityLabelShape(\n shape: Record<string, unknown>,\n z: any,\n): Record<string, unknown> {\n if (Object.hasOwn(shape, TOOL_ACTIVITY_LABEL_PARAM)) return shape;\n return {\n ...shape,\n [TOOL_ACTIVITY_LABEL_PARAM]: z.string().optional().describe(TOOL_ACTIVITY_LABEL_DESCRIPTION),\n };\n}\n\n/**\n * Add {@link TOOL_ACTIVITY_LABEL_PARAM} to a JSON Schema object's top-level\n * `properties`. Returns the schema unchanged when it already declares the\n * property.\n */\nexport function withActivityLabelJsonSchema(\n schema: Record<string, unknown> | undefined,\n): Record<string, unknown> {\n const base = schema ?? {};\n if (declaresActivityLabel(base)) return base;\n const props = (base.properties ?? {}) as Record<string, unknown>;\n return {\n ...base,\n properties: {\n ...props,\n [TOOL_ACTIVITY_LABEL_PARAM]: { type: \"string\", description: TOOL_ACTIVITY_LABEL_DESCRIPTION },\n },\n };\n}\n\n/** True when a JSON Schema object itself declares {@link TOOL_ACTIVITY_LABEL_PARAM}. */\nexport function declaresActivityLabel(schema: unknown): boolean {\n if (!schema || typeof schema !== \"object\") return false;\n const props = (schema as Record<string, unknown>).properties;\n return !!props && typeof props === \"object\" && Object.hasOwn(props, TOOL_ACTIVITY_LABEL_PARAM);\n}\n\n/**\n * Remove {@link TOOL_ACTIVITY_LABEL_PARAM} from a tool input before it reaches\n * the handler. Returns a shallow copy; non-object inputs and inputs without\n * the key are returned as-is.\n */\nexport function stripActivityLabel<T>(input: T): T {\n if (!input || typeof input !== \"object\" || Array.isArray(input)) return input;\n if (!Object.hasOwn(input, TOOL_ACTIVITY_LABEL_PARAM)) return input;\n const { [TOOL_ACTIVITY_LABEL_PARAM]: _label, ...rest } = input as Record<string, unknown>;\n return rest as T;\n}\n\n/**\n * Wrap in-process SDK tool defs: advertise {@link TOOL_ACTIVITY_LABEL_PARAM}\n * and strip it before each handler runs. A def that already declares the\n * property is returned untouched — the value is then the tool's own argument.\n */\nexport function withActivityLabelDefs<\n T extends { inputSchema: Record<string, unknown>; handler: (args: any) => unknown },\n>(defs: T[], z: any): T[] {\n return defs.map((def) => {\n if (Object.hasOwn(def.inputSchema, TOOL_ACTIVITY_LABEL_PARAM)) return def;\n return {\n ...def,\n inputSchema: withActivityLabelShape(def.inputSchema, z),\n // Forward the SDK's trailing args (`extra`) untouched.\n handler: (args: unknown, ...rest: unknown[]) =>\n (def.handler as (a: unknown, ...r: unknown[]) => unknown)(\n stripActivityLabel(args),\n ...rest,\n ),\n };\n });\n}\n","/**\n * Protocol versioning primitives for Skaile Agent Protocol v2.\n *\n * The protocol is versioned by a structured {@link ProtocolVersion} record\n * (`major.minor.patch`). The compatibility rule applied at handshake is\n * **major-equality**: a runner emits {@link IncompatibleProtocolEvent} and\n * shuts down when its declared major does not match the platform's announced\n * major. Minor and patch differences ride through transparently because\n * unknown fields are preserved on round-trip (see `MessageMeta` round-trip\n * contract in `messaging.ts`).\n *\n * @category Protocol\n * @since 2.0.0\n */\n\n/**\n * Structured semantic version triple for the agent protocol.\n *\n * @example\n * ```ts\n * const v: ProtocolVersion = { major: 2, minor: 0, patch: 0 };\n * ```\n *\n * @category Protocol\n * @since 2.0.0\n * @docLink packages/types/protocol-v2#protocol-version\n */\nexport type ProtocolVersion = {\n /** Incremented on breaking wire-format changes (field removed, semantics changed, required field added). */\n major: number;\n /** Incremented on additive wire-format changes (new optional fields, new event types). */\n minor: number;\n /** Incremented on bug-fix or doc-only changes that do not affect the wire. */\n patch: number;\n};\n\n/**\n * The protocol version the framework currently speaks. Runners and platforms\n * compare this against the peer's announced version at session boot via\n * `SessionInitCommand.protocolVersion`.\n *\n * @example\n * ```ts\n * import { PROTOCOL_VERSION } from '@skaile/workspaces/types';\n * if (cmd.protocolVersion.major !== PROTOCOL_VERSION.major) {\n * emit({ type: 'incompatible_protocol', agentVersion: PROTOCOL_VERSION, platformVersion: cmd.protocolVersion });\n * }\n * ```\n *\n * @category Protocol\n * @since 3.0.0\n *\n * Changed in 5.1.0:\n * A private prompt's answer stays private. `prompt` gains optional\n * `visibilityMode` and `privateRecipientIds`; for a `\"Private\"` prompt the\n * runner stamps both on every output event of that turn (the types in\n * `TURN_VISIBILITY_EVENT_TYPES`: text, tool calls and results, questions,\n * errors, `finished`, …) and lists `turnVisibility.v1`\n * (`TURN_VISIBILITY_RUNTIME_FEATURE`) in `protocol_info.runtimeFeatures`.\n * Status, file-change and session events stay unstamped. A 5.0 runner ignores\n * the fields and sends the answer unstamped, so a host feature-detects on the\n * flag. While a flow takes chat, the runner refuses a private prompt with a\n * non-fatal `error`: a flow turn coalesces several stimuli, so its output\n * cannot be held to one prompt's readers.\n *\n * Changed in 5.0.0:\n * The agent runtime concept `driver` is renamed `harness` on the wire (breaking,\n * so the major bumps and a 4.x peer is refused by the major-equality check).\n * `runtime_session.driverSessionId`, `session_info.driverSessionId` and\n * `compaction_attempt.driverSessionIdAtCompaction` become `harnessSessionId` and\n * `harnessSessionIdAtCompaction`, `ResolvedAgentConfig.driver` becomes\n * `harness`, and the `no_driver` failure code of a live reconfigure becomes\n * `no_harness`. Connector and mount `driver` fields are unchanged.\n *\n * Changed in 4.19.0:\n * Self-started turns. Two new transient events: `background_task_started`\n * (`taskId`), sent while a turn runs when a background task starts in it, and\n * `self_turn_started` (`taskIds`), sent before any other event of a turn the\n * runner did not dispatch (the agent woke itself when background work\n * settled), listing the tasks whose completion it reads. That turn's\n * `finished` or `error` carries `selfStarted: true`. A host that pairs turn\n * ends with the turns it sent skips a `selfStarted` end. A 4.18 runner sends\n * none of them, so a host must treat their absence as \"origin unknown\".\n *\n * Changed in 4.18.0:\n * Typed platform blocks and a per-turn tool allowlist on the `prompt` command.\n * `prompt` gains optional `platformBlocks` (`PlatformBlock[]`: `kind`, `id`,\n * `text`, `attrs?`) and `toolAllowlist` (`string[]`). The runner renders each\n * block in its reserved tag (`<PLATFORM_NOTICE>`, `<SKAILE_RESEARCH>`,\n * `<PLATFORM_RESEARCH_COMPLETE>`) at the start of the turn, at most once per\n * block id, and escapes those tag names in all other text it passes to the\n * agent. With a `toolAllowlist` the turn may call only the listed tools, its\n * subagents included; a runner that cannot enforce it or does not recognize a\n * listed name refuses the prompt with a non-fatal `error`. The runner lists\n * `platformBlocks.v1` (`PLATFORM_BLOCKS_RUNTIME_FEATURE`) in\n * `protocol_info.runtimeFeatures` on every host, managed or not, and the\n * system-prompt breakdown gains the `\"platform-blocks\"` section label. A host\n * feature-detects on that flag, never on the version: an older runner ignores\n * both fields, so it would run the turn unrestricted.\n *\n * Changed in 4.17.0:\n * New `reconfigure_rejected` event: a live `runner.reconfigure` the runner\n * answered `ok` (it landed while a turn was running) and the agent harness\n * then refused at the turn boundary. It carries `fields`, `code`, `message` and\n * the `model` the harness runs after the rollback; the runner has already\n * dropped the patch from its recreate state. Transient, broadcast to every\n * client. A host maps it to its restart-required signal for that session. A\n * 4.16 runner never sends it, so a host feature-detects on\n * `major > 4 || (major === 4 && minor >= 17)` before it relies on the event to learn a late\n * refusal.\n *\n * Changed in 4.16.0:\n * Agent composition surface. `SubagentEvent` gains optional `runId`,\n * `instanceId`, `input`, `runStatus` and `error` (an `agent.run` run), and its\n * `output` widens to `unknown` (a run reports the role's `io.output` value).\n * Additive events `memory_changed` (`{ instanceId, block, scope, by }`) and\n * `trigger_fired` (`{ instanceId, triggerId, source }`).\n * `session_init_ack` gains optional `instances` (`AgentInstanceSummary[]`).\n * The `host.agent_run` / `host.memory_store` / `host.trigger_store` runtime\n * capabilities a host advertises in `session_init.capabilities` switch on the\n * runner's `agent.*` (`agent.run`, `agent.status`, `agent.cancel`,\n * `agent.result`, `approval.decide`), `memory.*` and `trigger.*` capabilities;\n * `agent.list` and `agent.run` are served in the runner when the host\n * advertises no `host.agent_run`. A 4.15 runner emits none of this; feature-detect\n * on `major > 4 || (major === 4 && minor >= 16)`.\n *\n * Changed in 4.15.0:\n * New `resource_request` operation `write_range` for filesystem mounts and the\n * session root: one chunk (at most 8 MiB) of a file too large for one\n * WebSocket message, with `WriteRangeOptions` `{ uploadId, offset, size,\n * abort? }`. Chunks go into a hidden partial file next to the target, in order\n * and without gaps, and the last one renames it over the target, so a reader\n * never sees a half-written file. Each chunk answers `WriteRangeResult`\n * `{ received, size, complete }`; a malformed or out-of-sequence chunk fails\n * with `code: \"invalid_range\"`. A 4.14 runner refuses the operation with\n * `code: \"unsupported_operation\"`, so a host gates on\n * {@link RANGED_WRITE_MIN_PROTOCOL} and keeps its one-message `write` below.\n *\n * Changed in 4.14.0:\n * `prompt` and `cancel` take an optional `senderId`, the user id of\n * `MessageMeta.senderId`. A `cancel` with a `senderId` aborts the running turn\n * as before and also drops that sender's prompts still waiting in the runner's\n * prompt queue; the runner reports them in the new `queued_prompts_dropped`\n * event. Other senders' queued prompts stay queued, and a prompt without a\n * `senderId` is never dropped. A `cancel` without one keeps 4.13 behaviour. A\n * 4.13 runner ignores both fields and runs every queued prompt after a\n * cancel, so a host must feature-detect on `major > 4 || (major === 4 && minor >= 14)` before\n * it marks prompts as not sent from anything but the event itself.\n *\n * Changed in 4.13.0:\n * `runner.lifecycle` with `phase: \"compact\"` takes an optional `trigger`\n * (`\"manual\"` | `\"hibernate\"`, default `\"manual\"`). `\"hibernate\"` compacts\n * without resetting the harness and without the snapshot turn (\"Continue from\n * where we left off\") that a manual compaction runs, so a pre-hibernate\n * compaction never starts agent work. The input is a strict object, so a 4.12\n * runner refuses the field: a host must feature-detect on\n * `major > 4 || (major === 4 && minor >= 13)` before sending it.\n *\n * Changed in 4.12.0:\n * A filesystem-mount `read` takes optional `ReadOptions.offset` / `length` for\n * a ranged read: the runner reads only that range (at most 8 MiB, a larger\n * `length` is clamped), answers it base64, and sets `ConnectorContent.range`\n * (`offset`, `length`, total `size`, optional `modifiedAt`). A bad offset or length fails with\n * `code: \"invalid_range\"`. A 4.11 runner ignores both fields and sends the\n * whole file in one frame, so a host must feature-detect on\n * `major > 4 || (major === 4 && minor >= 12)` before asking for a range, and must treat an\n * answer without `range` as the whole file.\n *\n * Changed in 4.11.0:\n * `provider_response_seen` gains optional `cause`. `long-context-entitlement`\n * marks a 429 that says the account may not use a long (1M) context window,\n * so the seat is not out of quota. Diagnostic only: the runner fails over and\n * reports the 429 exactly as before. A 4.10 runner never sets it; a host must\n * ignore values it does not know.\n *\n * Changed in 4.10.0:\n * `error` gains optional `retrying` and `retryReason` (`stale_resume` |\n * `poison_scrub`). `retrying: true` (always with `fatal: false`) means the\n * harness replays the same prompt in place, with no `status: idle` in between,\n * so the error does not end the turn and the replay keeps the turn's starter.\n * A 4.9 runner sends such an error unmarked; a host that reads every `error`\n * as a turn end must keep doing so for it.\n *\n * Changed in 4.9.0:\n * New runtime capability `runner.reconfigure` (`{ model?, thinking?, effort? }`,\n * at least one) changes the running agent's model, thinking mode or effort\n * from the next turn, without a restart. It answers `{ ok: true, model }`, or\n * `{ ok: false, code }` with `no_harness` / `not_supported` when the change\n * cannot apply live. A 4.8 runner has no such capability, so a host keeps its\n * apply-on-restart path for it.\n *\n * Changed in 4.8.0:\n * The runner emits `question_reply` to every attached client when a paused\n * turn accepts a `reply`, and the event gains optional `question` and\n * `requestId` echoed from that reply. A 4.7 runner never emits it, so a host\n * must keep clearing a question card on its own `reply` and on `finished`.\n *\n * Changed in 4.7.0:\n * New `get_context_usage` command and `context_usage` event: a provider-neutral\n * breakdown of the context window, emitted after every turn and on request. A\n * 4.6 runner ignores the command and never emits the event, so a host must\n * treat a missing answer as \"unsupported\", not wait on it.\n *\n * Changed in 4.6.0:\n * A filesystem-mount `read` takes optional `ReadOptions`; `encoding: \"binary\"`\n * answers base64 for every file instead of decoding a NUL-free head as text.\n * A 4.5 runner ignores the option, so a host must still refuse a `utf-8`\n * answer carrying U+FFFD rather than re-encode it.\n *\n * Changed in 4.5.0:\n * `tool_call` and `tool_result` gain optional `parentToolUseId`, set when a\n * subagent made the call. Such a call runs alongside the main reply, so a host\n * that treats a tool call as a break in the reply's text should skip tagged\n * ones. A 4.4 runner never sets it and cannot be told apart from a turn with no\n * subagent; feature-detect on `major > 4 || (major === 4 && minor >= 5)`.\n *\n * Changed in 4.4.0:\n * `SystemPromptSection.label` gains `\"home\"`, the `agent.home` block that the\n * runner builds from workspace files. A host that switches exhaustively over the\n * label gains one member; a 4.3 runner never emits it.\n *\n * Changed in 4.3.0:\n * Additive `text_retract` event: the runner takes back the unfinished text of\n * an attempt it is about to replay, as the exact suffix of the `text` it\n * already streamed. A host that buffers or persists streamed text must cut\n * that suffix rather than treat the event as an unknown non-text event (which\n * would commit the fragment). A 4.2 runner never sends it.\n *\n * Changed in 4.2.0:\n * Two additive `resource_request` operations for filesystem mounts: `mkdir`\n * (create one empty directory, parents included; something already at the path\n * fails with `code: \"already_exists\"`) and `stat` (type, size, modified and\n * created time, and with `options.recursive` capped recursive `totals` that\n * report `partial` instead of failing). `resource_response` gains an optional\n * `code` (`ConnectorResponseFailureCode`). A 4.1 runner answers either op with\n * an `error` starting `Unsupported operation` and no `code`; a host must\n * feature-detect on `major > 4 || (major === 4 && minor >= 2)` or accept that error form.\n *\n * Changed in 4.1.0:\n * Additive `provider_quota_observed` event: one upstream quota-window reading\n * (window, status, optional utilization and reset) per change, attributed to\n * the pinned `AIProviderConfig`. A host with no handler broadcasts it\n * harmlessly. A 4.1 host against a 4.0 runner sees none and must not read\n * that as \"no quota used\" (feature-detect on `major > 4 || (major === 4 && minor >= 1)`).\n *\n * Changed in 4.0.0 (breaking):\n * The AI provider registry is the only provider surface on the wire.\n * `ResolvedAgentConfig` **loses** `provider`, `cloud` and `cloudConfig`; what\n * remains is `registry?` (the merged AI provider registry — `id → entry`, or\n * the merged view with registry order and merge provenance) and `modelRef?`\n * (`\"<providerId>/<modelId>\"`, a bare model id, or `\"@role\"`). Registry\n * entries never carry a literal secret: a control-plane-injected credential\n * is named by a `credential.ref` of the form `platform:<configId>` and\n * resolved against the sibling `secrets` map, which the platform keys by the\n * bare config id. A `session_init` whose `resolvedConfig.agentConfig` still\n * carries one of the removed fields is **rejected** with a fatal `error`\n * naming the replacement — silently ignoring them would run the session\n * against a different endpoint than the control plane resolved. Peers\n * negotiate on `major`, so a 3.x platform and a 4.x runner refuse each other\n * at boot rather than degrading.\n *\n * Changed in 3.15.0:\n * Classifier nodes. A new runtime-audience capability, `host.classify`\n * (`HostClassifyInput` → `HostClassifyResult`), which the runner invokes for a\n * classifier-shaped subprompt node, and an optional `classification` on\n * `NodeOutput`. A host without `host.classify` makes every classifier node run on\n * the generative fallback; older peers ignore the new output field.\n *\n * Changed in 3.14.0:\n * Optional `sessionRoot` flag on `resources_available`, advertising the\n * reserved `SESSION_ROOT_CONNECTOR_ID` write target for session-owned files.\n * Older peers ignore the flag and never send the reserved id.\n *\n * Changed in 3.13.0:\n * Optional agent-authored `label` on the `tool_call` event, and a new\n * `\"tool-activity\"` member of `SystemPromptSection.label`. Older peers ignore\n * both; a host that renders `label` can feature-detect it by this minor.\n *\n * Changed in 3.12.0:\n * Optional structured prompt attachments and question/reply requestId correlation.\n * Older peers retain text prompts and ignore unknown optional fields. Managed\n * question hosts must echo requestId; this minor does not advertise or admit the\n * separately gated codex-app-server-v1 runtime.\n *\n * Changed in 3.10.0:\n * Additive rejection cause on the AI-credential refresh input. The\n * `host.refresh_credential` `ai-credentials` input gains an optional\n * `rejection?: CredentialRejection` (`'auth' | 'usage-limit'`), sent only\n * alongside `reason: 'retry-401'` and only from the two runner call sites that\n * genuinely classified the failure — the harness's auth self-heal (`'auth'`) and\n * its usage-limit failover (`'usage-limit'`). `reason: 'retry-401'` collapsed\n * both, so a limit-blocked session on a config that is not opted into\n * `autoActivate` never re-resolved; the field is what lets the platform tell\n * them apart. `auth` asserts only that the rejection was auth-shaped, never\n * that capacity is fine (Anthropic mislabels OAuth quota exhaustion as\n * `authentication_error`); only `usage-limit` is a positive assertion. The\n * connector and MCP refresh paths classify nothing and keep emitting exactly\n * today's bytes. There is no peer-version gate, so a 3.9 peer does receive the\n * key on those two inputs; it is unaffected because nothing was removed or\n * reshaped and it must ignore an unknown key — and an unrecognised value —\n * rather than reject the input, which is also what allows a third rejection\n * later without a major bump. A 3.10 host against a 3.9 runner never sees the\n * field and must not read its absence as \"not a limit\" (feature-detect on\n * `major > 3 || (major === 3 && minor >= 10)`).\n * Spec: skaile-ai/platform#3562.\n *\n * Changed in 3.9.0:\n * Additive live AI-provider-seat signals, all optional under the\n * major-equality rule:\n * - `AgentEvent` gains `provider_response_seen`, emitted when the runner\n * observes a 401 or a 429 / subscription-limit rejection from the AI\n * provider, attributed to the pinned `AIProviderConfig`. A platform with\n * no handler broadcasts it harmlessly; consumers must ignore unknown\n * fields, since the platform half ships independently.\n * - The `CredentialMint` success branch gains an optional `configId` — the\n * seat the platform actually minted for. When it differs from the one the\n * runner asked for, the runner repoints the live session at it. A platform\n * that omits the field produces exactly 3.8 behaviour (no switch is ever\n * detected).\n * - The `credentialRotated` broadcast may carry `entry.data.configId` to\n * move a running session to a different seat rather than merely rotating\n * the token on the current one. Absent → today's re-pull.\n * A 3.8 peer is unaffected: nothing was removed or re-shaped, every addition is\n * opt-in on a field a 3.8 peer never sets. A 3.9 host against a 3.8 runner sees\n * no `provider_response_seen` and must not read that as \"no limits were hit\"\n * (feature-detect on `major > 3 || (major === 3 && minor >= 9)`).\n *\n * Changed in 3.8.0:\n * Additive `prompt` receipt acknowledgement. The `prompt` command gains an\n * optional `messageId`; when set the runner emits exactly one new `prompt_ack`\n * event echoing it, as the first act of handling the frame — before the\n * session-readiness gate, the secrets check and the harness start, each of which\n * could previously drop a prompt with no trace at all. When absent nothing is\n * emitted, so a 3.7 host sees byte-identical behaviour. A 3.8 host against a\n * 3.7 runner gets no ack and must not read that as a lost prompt — feature-detect\n * on `major > 3 || (major === 3 && minor >= 8)`. The ack is receipt-only: it says the frame\n * arrived, never that the turn ran.\n *\n * Changed in 3.7.0:\n * Additive `connector_mutate` acknowledgement + flow-hydrate reconciliation.\n * Three changes, all additive under the major-equality rule:\n * - `ConnectorMutateCommand` gains an optional `requestId`. When set, the\n * runner emits exactly one new `connector_mutate_response` event (with\n * `ok` / `result` / `error` / `code` / `reconciled`) on every terminal path,\n * including the paths that previously only logged. When absent nothing is\n * emitted, so a 3.6 host sees byte-identical behaviour.\n * - `flow.hydrate` accepts an optional `payload.pendingDecisions` —\n * `PendingGateDecision[]` the runner replays against the snapshot in the\n * same invocation that creates the flow connector, reporting the outcome as\n * `reconciled`. A host that omits the key gets today's hydrate.\n * - A flow-targeted mutate whose connector is not yet registered now waits\n * (bounded, `SKAILE_FLOW_MUTATE_CONNECTOR_WAIT_MS`, default 8000 ms) and\n * re-plans instead of failing — a behaviour change on a path that used to\n * fail silently, visible to a 3.6 host only as the op succeeding.\n * A 3.6 peer is unaffected: no symbol was removed or re-shaped, the ack is\n * opt-in on a field a 3.6 host never sets, and unknown fields ride through the\n * round-trip. A 3.7 host against a 3.6 runner sees `requestId` ignored and no\n * response, which it must treat as \"unacknowledged\" (feature-detect on\n * `major > 3 || (major === 3 && minor >= 7)`). Spec: `runner/MIGRATION-flow-connector.md`.\n *\n * Changed in 3.6.0:\n * Additive resolved-agent-config wire field. `ResolvedSkaileConfig` gains an\n * optional `agentConfig?: ResolvedAgentConfig` carrying the platform-resolved\n * harness / model / registry / modelRef / thinking / effort — the\n * same values the platform bakes into the generated skaile.yaml\n * `agent-config.default`. The runner applies it disk-first: any on-disk\n * `agent-config` profile with at least one agent setting disables the wire\n * value outright, so yaml-on-disk (docker-mode) sessions are byte-identical.\n * Additive under the major-equality rule: an older runner ignores the field\n * and an older platform simply omits it.\n *\n * Changed in 3.5.0:\n * Flow-connector host-contract fix (workspaces#379). Three coordinated changes,\n * all additive under the major-equality rule:\n * - `op:\"hydrate\"` on the bare `\"flow\"` connector now auto-creates the\n * `flow:<runId>` connector on a cold container from its `{ state, flow }`\n * payload, so a persisted run rehydrates in one op. A peer that still issues\n * `start` then `hydrate` keeps working unchanged.\n * - The dead `SessionInit.activeFlows` field (never read by the runner) and its\n * `ActiveFlowRehydration` type are removed — wire-compatible (nothing produced\n * or consumed them) but source-breaking for typed hosts, hence the bump.\n * - Malformed / conflicting flow `start` and `hydrate` payloads now fail loudly\n * (warn with a reason) instead of silently falling through.\n * Because the handshake compares only `major`, a 3.4 host and a 3.5 runner\n * interoperate: the auto-create path is opt-in on the payload the host sends, and\n * the removed field was already inert. Spec: `runner/MIGRATION-flow-connector.md`.\n *\n * Changed in 3.4.0:\n * Additive embedded-app capability source. `CapabilityOrigin` gains a\n * `{ kind: 'app'; appId: string }` variant and `Capability.side` gains `'app'`\n * (\"the handler runs in the embedded app\"). Both are additive: a peer that does\n * not understand `origin:'app'` / `side:'app'` never produces or routes them, so\n * they ride through transparently under the major-equality rule. No new message\n * types — `capability_register` / `capability_invoked` / `capability_result` /\n * `capability_approve` / `render_invoked` are reused verbatim. Spec:\n * `_devlog/specs/2026-07-07-app-capability-source.md`.\n *\n * Changed in 3.3.0:\n * Additive agent-to-agent (session-to-session) communication extension.\n * `AgentEvent` gains an `a2a_message` variant carrying cross-session messages\n * (`direction`, `peerSessionId`, `peerName`, `exchangeId`, `text`). `Capability`\n * gains an optional `callTimeoutMs?: number` so a long-running capability call\n * (e.g. a 5-minute `platform.ask_session`) can exceed the default capability-call\n * timeout. Both are additive: a peer that does not understand them ignores the\n * event / falls back to the default timeout, so they ride through transparently\n * under the major-equality rule.\n *\n * Changed in 3.2.0:\n * Additive wake-time resume cascade. `AgentReconfigureOptions` gains optional\n * `resumeSessionId` and `expectedCapabilitySignature` fields driving the tier-1\n * native SDK resume path; `AgentEvent` gains `ResumeAttemptedEvent` and\n * `ResumeFailedEvent`. `FinishedEvent` gains optional `customType` /\n * `customData` for capability-routed custom payloads. All additive — clients\n * that omit the resume hint or ignore the new events keep working unchanged.\n *\n * Changed in 3.1.0:\n * Additive cost / token usage extension. `FinishedEvent` gains an optional\n * `tokens?: TokenUsage` field carrying per-turn input / output / cache-read /\n * cache-creation / reasoning token counts. `AgentHarness.getTokenUsage()` is\n * widened to return the same `TokenUsage` shape (existing consumers reading\n * `inputTokens` / `outputTokens` keep working unchanged). Harnesses that do not\n * surface token usage continue to return `null` / omit the field.\n *\n * Changed in 3.0.0:\n * Major bump for the deterministic session bootstrap rewrite. `ConfigureCommandV2`,\n * `provision_secrets`, `request_access_token`, `add_resource`, `remove_resource`,\n * `set_log_level`, `state_action`, `lifecycle`, `remount_mount`, `compact`, and\n * `reconfigure_agent` are removed from the `AgentCommand` union. Their semantics\n * are reachable through:\n * - `session_init` (one deterministic envelope at session start that delivers\n * identity, resolved config, pre-minted credentials, secrets, capabilities,\n * shared state, active flows, resume hints, and logging config),\n * - `host.refresh_credential` (capability invocation that replaces the\n * refresh-on-401 path of `request_access_token`), and\n * - `runner.*` capabilities (`runner.add_mount`, `runner.add_connector`,\n * `runner.remove_resource`, `runner.update_credential`, `runner.set_log_level`,\n * `runner.set_state`, `runner.lifecycle`, and since 4.9.0 `runner.reconfigure`)\n * invoked by the platform via the\n * bidirectional capability registry.\n *\n * Capabilities gain an `audience: ('llm' | 'user' | 'runtime')[]` field that\n * scopes visibility: host RPCs (`host.*`) and runner RPCs (`runner.*`) are\n * `['runtime']` and never reach the LLM tool list or the user-facing command\n * palette. v2.x capabilities without an explicit `audience` default to\n * `['llm', 'user']`, preserving prior behaviour.\n *\n * Spec: `_devlog/specs/2026-05-10-deterministic-session-bootstrap.md`.\n *\n * @docLink packages/types/protocol-v3#protocol-version\n */\nexport const PROTOCOL_VERSION: ProtocolVersion = { major: 5, minor: 1, patch: 0 };\n\n/**\n * String form of {@link PROTOCOL_VERSION}, kept in lock-step. Useful for\n * `package.json` version fields and HTTP `User-Agent` strings.\n *\n * @category Protocol\n * @since 3.0.0\n * @docLink packages/types/protocol-v3#protocol-version\n */\nexport const PROTOCOL_VERSION_STRING = \"5.1.0\";\n\n/**\n * The first protocol version whose runner serves the `write_range` resource\n * operation. A host compares the runner's announced version against it before\n * splitting a write into chunks: an older runner refuses the operation.\n *\n * @example\n * ```ts\n * const atLeast = (a: ProtocolVersion, b: ProtocolVersion) =>\n * a.major !== b.major ? a.major > b.major : a.minor >= b.minor;\n * const ranged = atLeast(v, RANGED_WRITE_MIN_PROTOCOL);\n * ```\n *\n * @category Protocol\n * @since 4.15.0\n */\nexport const RANGED_WRITE_MIN_PROTOCOL: ProtocolVersion = { major: 4, minor: 15, patch: 0 };\n\n/**\n * Parse a `\"major.minor.patch\"` string into a {@link ProtocolVersion}.\n *\n * @param s - the version string to parse, exactly three dot-separated non-negative integers\n * @returns the parsed protocol version\n * @throws {Error} if the string is not exactly three dot-separated non-negative integers\n *\n * @example\n * ```ts\n * parseVersion('2.0.0'); // { major: 2, minor: 0, patch: 0 }\n * parseVersion('2.1'); // throws\n * ```\n *\n * @category Protocol\n * @since 2.0.0\n * @docLink packages/types/protocol-v2#parse-version\n */\nexport function parseVersion(s: string): ProtocolVersion {\n const parts = s.split(\".\");\n if (parts.length !== 3) {\n throw new Error(`Invalid ProtocolVersion: \"${s}\" (expected \"major.minor.patch\")`);\n }\n const [maj, min, pat] = parts;\n const major = Number(maj);\n const minor = Number(min);\n const patch = Number(pat);\n if (\n !Number.isInteger(major) ||\n !Number.isInteger(minor) ||\n !Number.isInteger(patch) ||\n major < 0 ||\n minor < 0 ||\n patch < 0\n ) {\n throw new Error(`Invalid ProtocolVersion: \"${s}\" (each part must be a non-negative integer)`);\n }\n return { major, minor, patch };\n}\n\n/**\n * Format a {@link ProtocolVersion} record into its `\"major.minor.patch\"` string form.\n *\n * @param v - the protocol version to format\n * @returns the dot-joined string form\n *\n * @example\n * ```ts\n * formatVersion({ major: 2, minor: 0, patch: 0 }); // '2.0.0'\n * ```\n *\n * @category Protocol\n * @since 2.0.0\n * @docLink packages/types/protocol-v2#format-version\n */\nexport function formatVersion(v: ProtocolVersion): string {\n return `${v.major}.${v.minor}.${v.patch}`;\n}\n"]}
@@ -1,10 +1,10 @@
1
- import { loadRegistryView } from './chunk-B6N653ZG.js';
2
- import { agentDefinitionProblem } from './chunk-EPXZQIC6.js';
3
- import { unknownHarnessMessage } from './chunk-SCRYXAHH.js';
4
- import { checkOmpListedModel, checkHarnessModel, checkOmpServeModel } from './chunk-YN6N3RBM.js';
5
- import { loadHarnessSdk, resolveSettings, sdkLookupPlaces, installCommandFor } from './chunk-6ARPZHOV.js';
1
+ import { loadRegistryView } from './chunk-DRHJRTAS.js';
2
+ import { agentDefinitionProblem, instanceRefProblem } from './chunk-DFP476EU.js';
3
+ import { unknownHarnessMessage } from './chunk-3NJFPGEB.js';
4
+ import { checkOmpListedModel, checkHarnessModel, checkOmpServeModel, isUnlistedModel } from './chunk-XIIIGLSL.js';
5
+ import { loadHarnessSdk, resolveSettings, sdkLookupPlaces, installCommandFor } from './chunk-TMJBEGS4.js';
6
6
  import { DEFAULT_HARNESS_ID } from './chunk-C5HFK34M.js';
7
- import { resolveSkWorkspaceConfig, primaryAgentRef } from './chunk-6SXSVKQY.js';
7
+ import { resolveSkWorkspaceConfig, primaryAgentRef } from './chunk-O7ADRMCR.js';
8
8
  import { pickRegistryEntries, registryEntries, isEntryEnabled } from './chunk-RXGPFAMN.js';
9
9
  import { statSync } from 'fs';
10
10
 
@@ -58,9 +58,9 @@ async function checkServeModel(projectDir, overrides, registry = () => loadRegis
58
58
  const input = { registry: narrowed, model: settings.model };
59
59
  const refusal = checkHarnessModel(harness, input) ?? (harness === "omp" ? checkOmpServeModel(input) : void 0);
60
60
  if (refusal) return refusal;
61
- const ownHome = harness === "omp" && !registryEntries(narrowed).some(
61
+ const ownHome = harness === "omp" && (isUnlistedModel(input) || !registryEntries(narrowed).some(
62
62
  ([, entry]) => (entry.kind === "llm" || entry.kind === "embed") && isEntryEnabled(entry)
63
- );
63
+ ));
64
64
  return (ownHome ? await ompListed(settings.model) : void 0) ?? null;
65
65
  }
66
66
  function resolveServeProvider(projectDir, provider, providers, registry = () => loadRegistryView({ projectDir }).merged) {
@@ -96,11 +96,18 @@ async function checkServeHarness(projectDir, harnessOverride) {
96
96
  );
97
97
  return unknownHarnessMessage(settings.harness ?? DEFAULT_HARNESS_ID) ?? null;
98
98
  }
99
- function checkServeAgentDefinition(projectDir) {
100
- const definition = primaryAgentRef(resolveSkWorkspaceConfig(projectDir));
101
- return definition ? agentDefinitionProblem(projectDir, definition) : null;
99
+ function checkServeAgents(projectDir) {
100
+ const config = resolveSkWorkspaceConfig(projectDir);
101
+ const definition = primaryAgentRef(config);
102
+ const definitionProblem = definition ? agentDefinitionProblem(projectDir, definition) : null;
103
+ if (definitionProblem) return definitionProblem;
104
+ for (const [id, instance] of Object.entries(config.agent?.instances ?? {})) {
105
+ const problem = instanceRefProblem(projectDir, id, instance.ref);
106
+ if (problem) return problem;
107
+ }
108
+ return null;
102
109
  }
103
110
 
104
- export { checkHarnessSdk, checkModelEndpointPeer, checkServeAgentDefinition, checkServeHarness, checkServeModel, checkServeProjectDir, resolveServeProvider };
105
- //# sourceMappingURL=chunk-7PVGND4J.js.map
106
- //# sourceMappingURL=chunk-7PVGND4J.js.map
111
+ export { checkHarnessSdk, checkModelEndpointPeer, checkServeAgents, checkServeHarness, checkServeModel, checkServeProjectDir, resolveServeProvider };
112
+ //# sourceMappingURL=chunk-7YOHUX2M.js.map
113
+ //# sourceMappingURL=chunk-7YOHUX2M.js.map