ryco-cli 0.1.14 → 0.1.15

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 (189) hide show
  1. package/dist/{AcpNativeLogging-vLtnq5f1.cjs → AcpNativeLogging-OhEq3XNp.cjs} +1 -1
  2. package/dist/{AcpNativeLogging-D3fe64a6.mjs → AcpNativeLogging-qZgtIa5K.mjs} +2 -2
  3. package/dist/{AzureDevOpsSourceControlProvider-WNUDtsur.mjs → AzureDevOpsSourceControlProvider-B0YsaJyI.mjs} +3 -3
  4. package/dist/{AzureDevOpsSourceControlProvider-BtezW57t.cjs → AzureDevOpsSourceControlProvider-Dyu8KQ_S.cjs} +2 -2
  5. package/dist/{BitbucketSourceControlProvider-BWzNM0jW.cjs → BitbucketSourceControlProvider-3VHGKSl1.cjs} +2 -2
  6. package/dist/{BitbucketSourceControlProvider-tbbUFKz3.mjs → BitbucketSourceControlProvider-B8IPx2Ad.mjs} +3 -3
  7. package/dist/{ClaudeDriver-BTvdJvam.cjs → ClaudeDriver-CBCy0_WX.cjs} +8 -6
  8. package/dist/{ClaudeDriver-CG5ngU5z.mjs → ClaudeDriver-DsW8yDj9.mjs} +9 -7
  9. package/dist/{CodexDriver-CFxwJNXx.cjs → CodexDriver-3TZPgrGk.cjs} +3 -3
  10. package/dist/{CodexDriver-49o7TA-C.mjs → CodexDriver-DLwPz5sk.mjs} +4 -4
  11. package/dist/{CodexTextGeneration-C0t4xcPO.mjs → CodexTextGeneration-D1vV8grr.mjs} +2 -2
  12. package/dist/{CodexTextGeneration-CedcXf9a.cjs → CodexTextGeneration-DLHSW4Mz.cjs} +1 -1
  13. package/dist/{CopilotDriver-B8J_ovCX.cjs → CopilotDriver-C7a8IhyK.cjs} +3 -3
  14. package/dist/{CopilotDriver-Cu1B1skB.mjs → CopilotDriver-DXvGBv-s.mjs} +4 -4
  15. package/dist/{CursorDriver-P_A8uQki.mjs → CursorDriver-CeB_vMKJ.mjs} +4 -4
  16. package/dist/{CursorDriver-zlKHPy1_.cjs → CursorDriver-uNsDetA3.cjs} +3 -3
  17. package/dist/{ForgejoSourceControlProvider-szJ-dvsD.cjs → ForgejoSourceControlProvider-CJLksvL_.cjs} +2 -2
  18. package/dist/{ForgejoSourceControlProvider-DLhJZtq9.mjs → ForgejoSourceControlProvider-Ds0rU_PN.mjs} +3 -3
  19. package/dist/{GitHubSourceControlProvider-D5MQQPCJ.mjs → GitHubSourceControlProvider-C7CJAslU.mjs} +3 -3
  20. package/dist/{GitHubSourceControlProvider-3ofb6HsF.cjs → GitHubSourceControlProvider-CrYNFu8S.cjs} +2 -2
  21. package/dist/{GitLabSourceControlProvider-DkupZH5G.cjs → GitLabSourceControlProvider-jbX5M34A.cjs} +2 -2
  22. package/dist/{GitLabSourceControlProvider-DLkxeob5.mjs → GitLabSourceControlProvider-u-Y-e8PV.mjs} +3 -3
  23. package/dist/{GrokDriver-CTUNclwp.cjs → GrokDriver-BJ00ZiYg.cjs} +3 -3
  24. package/dist/{GrokDriver-D8KoMY76.mjs → GrokDriver-CFgjwnvE.mjs} +4 -4
  25. package/dist/{OpenCodeDriver-pXM8bSct.cjs → OpenCodeDriver-BTxd2Q3Q.cjs} +424 -209
  26. package/dist/{OpenCodeDriver-B7htxutj.mjs → OpenCodeDriver-DNApoGdu.mjs} +424 -209
  27. package/dist/{SourceControlProviderDiscoveryCatalog-Bj_sZfmB.cjs → SourceControlProviderDiscoveryCatalog-CPO3a9_U.cjs} +1 -1
  28. package/dist/{SourceControlProviderDiscoveryCatalog-C6Fn7rZE.mjs → SourceControlProviderDiscoveryCatalog-hXWNwRMn.mjs} +1 -1
  29. package/dist/bin.cjs +226 -43
  30. package/dist/bin.mjs +225 -44
  31. package/dist/client/assets/{AccountSettings-CinnQaX-.js → AccountSettings-Cey-16wq.js} +1 -1
  32. package/dist/client/assets/{AiFocusSettings-UbXOywZg.js → AiFocusSettings-CaHQXDaQ.js} +1 -1
  33. package/dist/client/assets/{AnimatedHeight-DCad8EQ2.js → AnimatedHeight-BC-qaTJY.js} +1 -1
  34. package/dist/client/assets/{AppearanceSettings-CTh8Z8nz.js → AppearanceSettings-B6UaU-_a.js} +1 -1
  35. package/dist/client/assets/{BranchToolbar.logic-37EnknDD.js → BranchToolbar.logic-DILAA3Cz.js} +1 -1
  36. package/dist/client/assets/{ChatRightPanel-DUwLYKbp.js → ChatRightPanel-D-AL07IU.js} +6 -6
  37. package/dist/client/assets/{ChatThreadRouteView-C43W0PEz.js → ChatThreadRouteView-tEo-zoCf.js} +1 -1
  38. package/dist/client/assets/{CommandPaletteDialog-IHOe0hOG.js → CommandPaletteDialog-s7yf5Y2S.js} +1 -1
  39. package/dist/client/assets/{CompositeItem-ClLCuzeJ.js → CompositeItem-97y1QiiT.js} +1 -1
  40. package/dist/client/assets/{CompositeRoot-Bdsr9eHn.js → CompositeRoot-C7Mz4Y_2.js} +1 -1
  41. package/dist/client/assets/{ConnectionsSettings-tmBjGOPj.js → ConnectionsSettings-B0-Hkwof.js} +1 -1
  42. package/dist/client/assets/{DiagnosticsSettings-CbCEgaau.js → DiagnosticsSettings-DX5LH9Bt.js} +1 -1
  43. package/dist/client/assets/{DialogHandle-CitVLvYq.js → DialogHandle-Cl9dQBJp.js} +1 -1
  44. package/dist/client/assets/{DialogPopup-CfaEr9jv.js → DialogPopup-a1M74u16.js} +1 -1
  45. package/dist/client/assets/DialogRoot-C_DO1gtO.js +1 -0
  46. package/dist/client/assets/{DialogTitle-BUkU0qXf.js → DialogTitle-Bk-w3xLJ.js} +1 -1
  47. package/dist/client/assets/{DialogTrigger-CEjWue7M.js → DialogTrigger-D9nkMFu2.js} +1 -1
  48. package/dist/client/assets/{DialogViewport-Cyc_ye5w.js → DialogViewport-tgJz2Lwn.js} +1 -1
  49. package/dist/client/assets/{DraftChatThreadRouteView-BSA67nKa.js → DraftChatThreadRouteView-BU2IGTR6.js} +1 -1
  50. package/dist/client/assets/{ExternalIdentityWeb.logic-BqdBjAua.js → ExternalIdentityWeb.logic-Bn1HigS9.js} +1 -1
  51. package/dist/client/assets/{GlassSurface-B3cq28tB.js → GlassSurface-CDok2tTN.js} +1 -1
  52. package/dist/client/assets/{HostedConnectionControls-S2Wr9fiZ.js → HostedConnectionControls-Cux_sRCM.js} +1 -1
  53. package/dist/client/assets/{HostedHubRoot-DK9zP4tJ.js → HostedHubRoot-CyySCdJV.js} +1 -1
  54. package/dist/client/assets/{HostedNativeAuthorizationRoute-CKnLbCOH.js → HostedNativeAuthorizationRoute-490iDXmk.js} +1 -1
  55. package/dist/client/assets/{HostedRelayTrustNotice-CbF_SOpf.js → HostedRelayTrustNotice-CcDOAwgS.js} +1 -1
  56. package/dist/client/assets/{Icons-DZpTOLIb.js → Icons-BEtED8P8.js} +1 -1
  57. package/dist/client/assets/{IntegrationsSettingsPanel-BdBEGIyL.js → IntegrationsSettingsPanel-BFTAvxtn.js} +1 -1
  58. package/dist/client/assets/{KeybindingsSettings-Bye1H9Sx.js → KeybindingsSettings-VYgbhiZF.js} +1 -1
  59. package/dist/client/assets/{McpServersSettings-D0U0g2q7.js → McpServersSettings-DSDCjoTn.js} +1 -1
  60. package/dist/client/assets/{MobileSheet-BPvuTPR6.js → MobileSheet-BDvnUC5W.js} +1 -1
  61. package/dist/client/assets/{NewWorktreeDialog-C_xJCZWF.js → NewWorktreeDialog-C65Aifeb.js} +1 -1
  62. package/dist/client/assets/{NoActiveThreadState-Cfn_Wwnf.js → NoActiveThreadState-DehHNgAp.js} +1 -1
  63. package/dist/client/assets/{NodeSecuritySettings-DUQNZJqJ.js → NodeSecuritySettings-DW9GJ-kU.js} +1 -1
  64. package/dist/client/assets/{OpinionatedPluginsSettings-D44efcv7.js → OpinionatedPluginsSettings-DbxPOokL.js} +1 -1
  65. package/dist/client/assets/{PhoneGetAppInterstitial-CzduFI4-.js → PhoneGetAppInterstitial-CbyVrtDn.js} +1 -1
  66. package/dist/client/assets/{PhoneGetAppInterstitialBackdrop-CJ44QRCp.js → PhoneGetAppInterstitialBackdrop-BA4R225F.js} +1 -1
  67. package/dist/client/assets/{PhoneHome-BLEJm5TG.js → PhoneHome-c0j_TBEC.js} +1 -1
  68. package/dist/client/assets/{PhoneSettingsSurface-CqetLTIm.js → PhoneSettingsSurface-5LFRIx_5.js} +1 -1
  69. package/dist/client/assets/{ProjectFavicon-DrBXI2cH.js → ProjectFavicon-CeVJCQCy.js} +1 -1
  70. package/dist/client/assets/{ProviderModelPicker-CyID3P1C.js → ProviderModelPicker-MFRYAv_3.js} +1 -1
  71. package/dist/client/assets/{ProviderUpdateLaunchNotification.logic-C6VoLD-w.js → ProviderUpdateLaunchNotification.logic-CywRitn3.js} +1 -1
  72. package/dist/client/assets/{ProvidersSettingsPanel-BHmpXUIM.js → ProvidersSettingsPanel-FYBEqSr_.js} +1 -1
  73. package/dist/client/assets/{RedactedSensitiveText-CZwFEoNn.js → RedactedSensitiveText-BuWSWty8.js} +1 -1
  74. package/dist/client/assets/{RootAppShell-BVXRShhe.js → RootAppShell-5HrP6N8H.js} +2 -2
  75. package/dist/client/assets/{RycoLetterMark-C-fvI9UB.js → RycoLetterMark-CZYntY8t.js} +1 -1
  76. package/dist/client/assets/{SettingsDialog-CnETTu23.js → SettingsDialog-CpwoqGS8.js} +1 -1
  77. package/dist/client/assets/{SettingsPanels-C3HDrmQq.js → SettingsPanels-COWRB29-.js} +1 -1
  78. package/dist/client/assets/{SettingsPanels.editor-DI8Z5rsl.js → SettingsPanels.editor-lbLEbllb.js} +1 -1
  79. package/dist/client/assets/{SourceControlSettings-BG4tsvql.js → SourceControlSettings-DvBNelcO.js} +1 -1
  80. package/dist/client/assets/{StatisticsPage-dy_aYqvS.js → StatisticsPage-DxAKqvVX.js} +1 -1
  81. package/dist/client/assets/{StatisticsPanel-CeRJBu65.js → StatisticsPanel-C0xGLlMA.js} +1 -1
  82. package/dist/client/assets/{StatisticsSettingsLink-ChlwCDG0.js → StatisticsSettingsLink-B7SZerf3.js} +1 -1
  83. package/dist/client/assets/{ThreadStatusIndicators-D-ioX09X.js → ThreadStatusIndicators-CIOM98q2.js} +0 -0
  84. package/dist/client/assets/{ThreadTerminalDrawer-BvGaRxBP.js → ThreadTerminalDrawer-DRelLlEP.js} +1 -1
  85. package/dist/client/assets/{ThreadWorkspacePanel-BAWm7mGl.js → ThreadWorkspacePanel-CktVSliZ.js} +2 -2
  86. package/dist/client/assets/{ToolbarRootContext-k-_m5nCN.js → ToolbarRootContext-B1g8IP6k.js} +1 -1
  87. package/dist/client/assets/{WorkItemsTab-Q2V2EuvK.js → WorkItemsTab-CahU_t_S.js} +1 -1
  88. package/dist/client/assets/{alert-BymbRVPf.js → alert-DomE7dAt.js} +1 -1
  89. package/dist/client/assets/{alert-dialog-Gym8_p4Q.js → alert-dialog-9Jyh0e8u.js} +1 -1
  90. package/dist/client/assets/{authorization-BwQZHweJ.js → authorization-D8lJzXTE.js} +1 -1
  91. package/dist/client/assets/{badge-BQI7J3Sg.js → badge-w43sx8eF.js} +1 -1
  92. package/dist/client/assets/{branding-DqHDcyzW.js → branding-B7DcCXjn.js} +1 -1
  93. package/dist/client/assets/{button-Wf_1nfeu.js → button-DG8WqjNn.js} +1 -1
  94. package/dist/client/assets/{capabilities-BrllgEYz.js → capabilities-B1FHGoov.js} +1 -1
  95. package/dist/client/assets/{chatThreadActions-BGkJmj6T.js → chatThreadActions-BZvyhfKr.js} +1 -1
  96. package/dist/client/assets/{collapsible-GOpRckDq.js → collapsible-EhAEe5S9.js} +1 -1
  97. package/dist/client/assets/{command-Dx5YM54H.js → command-Cyn6yIEa.js} +1 -1
  98. package/dist/client/assets/{composerDraftStore-DC2r8dcu.js → composerDraftStore-TYv9j3vY.js} +2 -2
  99. package/dist/client/assets/{data-list-BSiCZBKn.js → data-list-DTdqWMGN.js} +1 -1
  100. package/dist/client/assets/{desktopUpdateAtoms-DkmoIGr0.js → desktopUpdateAtoms-CPlZiFRm.js} +1 -1
  101. package/dist/client/assets/{desktopWorkspace-Ddm531g5.js → desktopWorkspace-DEZ30LlY.js} +1 -1
  102. package/dist/client/assets/device-CHdXzvhB.js +168 -0
  103. package/dist/client/assets/{dialog-CUxw5AxI.js → dialog-BNmFD6Nh.js} +1 -1
  104. package/dist/client/assets/{draft-input-CpfrGQ1h.js → draft-input-dP7F8odz.js} +1 -1
  105. package/dist/client/assets/{editorPreferences-SOMXdQpi.js → editorPreferences-B4GvqMiF.js} +1 -1
  106. package/dist/client/assets/{empty-D420OZA9.js → empty-Ccxhyvdf.js} +1 -1
  107. package/dist/client/assets/{env-Bf33qXdb.js → env-Bcq9YR3B.js} +1 -1
  108. package/dist/client/assets/{getPseudoElementBounds-nDGTWECG.js → getPseudoElementBounds-CO5HJT7x.js} +1 -1
  109. package/dist/client/assets/{group-Cq4Llttm.js → group-CzdKmc45.js} +1 -1
  110. package/dist/client/assets/{index-BL8_ra0g.js → index-Gre6bNC8.js} +2 -2
  111. package/dist/client/assets/{input-Dl4N9ZfE.js → input-BZz4eLRl.js} +1 -1
  112. package/dist/client/assets/{kbd-CqoZVQfv.js → kbd-DbvN3zTb.js} +1 -1
  113. package/dist/client/assets/{keybindings-DQzcPjMv.js → keybindings-BPE3eEAM.js} +1 -1
  114. package/dist/client/assets/{label-x5DgpBI_.js → label-DZf4lbNF.js} +1 -1
  115. package/dist/client/assets/{lib-BXIqHSZx.js → lib-DgOYoged.js} +1 -1
  116. package/dist/client/assets/{logging-CZlHfeu2.js → logging-81iP6Hps.js} +1 -1
  117. package/dist/client/assets/main-DlGNPwsH.css +2 -0
  118. package/dist/client/assets/{main-J4YlUJad.js → main-Dz0zookE.js} +2 -2
  119. package/dist/client/assets/{menu-BuDpxm_Q.js → menu-B6UEFcn0.js} +1 -1
  120. package/dist/client/assets/{popover-DuprDUaB.js → popover-BuYzXGwl.js} +1 -1
  121. package/dist/client/assets/{primary-CJx2nSkc.js → primary-CiDY2oUi.js} +1 -1
  122. package/dist/client/assets/{projectPaths-DrelgodZ.js → projectPaths-D6fHIU1b.js} +1 -1
  123. package/dist/client/assets/{providerDriverMeta-D27Koh7Q.js → providerDriverMeta-sBwZhQoN.js} +1 -1
  124. package/dist/client/assets/{providerIconUtils-CtOHwjWL.js → providerIconUtils-DiDJeNtT.js} +1 -1
  125. package/dist/client/assets/providerInstances-vd2eZtHx.js +1 -0
  126. package/dist/client/assets/providerModels-vd2eZtHx.js +1 -0
  127. package/dist/client/assets/{qr-code-BVfzPOP3.js → qr-code-Ie92aZvE.js} +1 -1
  128. package/dist/client/assets/{radio-group-rgmJqPI7.js → radio-group-BuuTEtdC.js} +1 -1
  129. package/dist/client/assets/{resolveAriaLabelledBy-l4SuqStl.js → resolveAriaLabelledBy-0FA0k4xp.js} +1 -1
  130. package/dist/client/assets/{rightPanelRouteSearch-DmpObL1z.js → rightPanelRouteSearch-BS8CkNS6.js} +1 -1
  131. package/dist/client/assets/{runtime-DYzjhL5M.js → runtime-CPM0EUhb.js} +1 -1
  132. package/dist/client/assets/{scroll-area-DMs8l4bb.js → scroll-area-C0yF015F.js} +1 -1
  133. package/dist/client/assets/{scrollEdges-DWTOweRb.js → scrollEdges-DI5Y3mtR.js} +1 -1
  134. package/dist/client/assets/{select-Djwp8HDm.js → select-CZukJlTn.js} +1 -1
  135. package/dist/client/assets/{separator-rjtf5Q3V.js → separator-D4ckGtPe.js} +1 -1
  136. package/dist/client/assets/session-logic-BalPN1Sc.js +4 -0
  137. package/dist/client/assets/{settingsDialogStore-Dbykwvfs.js → settingsDialogStore-LxRFC5hh.js} +1 -1
  138. package/dist/client/assets/{settingsLayout-C7bl9Xi4.js → settingsLayout-CHJT5wtl.js} +1 -1
  139. package/dist/client/assets/{sheet-CQIQYfOM.js → sheet-BNfImQ-7.js} +1 -1
  140. package/dist/client/assets/{sidebar-BdDOvXe8.js → sidebar-CFGg5Tkr.js} +1 -1
  141. package/dist/client/assets/{sidebarProjectFolders-D_Me0oJ8.js → sidebarProjectFolders-bhNsO9Z_.js} +1 -1
  142. package/dist/client/assets/{sidebarStatusText-BF6odB03.js → sidebarStatusText-C8QBhZhZ.js} +1 -1
  143. package/dist/client/assets/{skeleton-Mgh4Gx9x.js → skeleton-DOgQaVXv.js} +1 -1
  144. package/dist/client/assets/{spinner-CzzUdFeE.js → spinner-ClQu8SdC.js} +1 -1
  145. package/dist/client/assets/{src-Ca7Gag3m.js → src-DmPIm3ie.js} +1 -1
  146. package/dist/client/assets/storeSelectors-Cf2WDMfx.js +1 -0
  147. package/dist/client/assets/{switch-CntUxI1A.js → switch-BZjA7VT9.js} +1 -1
  148. package/dist/client/assets/{terminal-links-CUFISn8U.js → terminal-links-CzJomeox.js} +1 -1
  149. package/dist/client/assets/{textarea-C8QxddDb.js → textarea-DHdmRD1r.js} +1 -1
  150. package/dist/client/assets/{threadPinning-BIV4KXZU.js → threadPinning-BLqwZebi.js} +1 -1
  151. package/dist/client/assets/{threadPriorityRefreshRuntime-B-pVYK_y.js → threadPriorityRefreshRuntime-BoNAlBXK.js} +1 -1
  152. package/dist/client/assets/{toast-Cw7bXJzg.js → toast-C-0Ft2jD.js} +1 -1
  153. package/dist/client/assets/{toggle-Bi9uP4Hb.js → toggle-DsnOFDbJ.js} +1 -1
  154. package/dist/client/assets/{toggle-group-LcgyMgj5.js → toggle-group-Chxh9G6t.js} +1 -1
  155. package/dist/client/assets/{tooltip-t3Nrleyq.js → tooltip-C_-9XEfA.js} +1 -1
  156. package/dist/client/assets/types-Cf2WDMfx.js +1 -0
  157. package/dist/client/assets/{uiStateStore-BW2WnK4k.js → uiStateStore-DzUrk2GS.js} +1 -1
  158. package/dist/client/assets/{useAtlassian-a-MaAd0k.js → useAtlassian-CoHKzu-e.js} +0 -0
  159. package/dist/client/assets/{useButton-DUuWgIMw.js → useButton-BmvYhoMC.js} +1 -1
  160. package/dist/client/assets/{useCompositeListItem-CL5mJqCb.js → useCompositeListItem-D0PvH4nv.js} +1 -1
  161. package/dist/client/assets/{useDebouncedValue-jDDWNjgt.js → useDebouncedValue-s0BC8Yyp.js} +1 -1
  162. package/dist/client/assets/{useFloatingRootContext-C4I8IxtL.js → useFloatingRootContext-CLCaQEJk.js} +1 -1
  163. package/dist/client/assets/{useHandleNewThread-820pBJCC.js → useHandleNewThread-Bw460iXT.js} +1 -1
  164. package/dist/client/assets/{useLabelableId-KX33mhBC.js → useLabelableId-CB_9OReR.js} +1 -1
  165. package/dist/client/assets/{useLocation-B4QlXdMt.js → useLocation-DGJMt6gP.js} +1 -1
  166. package/dist/client/assets/{useOpenInteractionType-DjM9MBY7.js → useOpenInteractionType-BSSI2GzS.js} +1 -1
  167. package/dist/client/assets/{usePhoneThreadActions-DxxWMYgC.js → usePhoneThreadActions-BIDUSWSI.js} +1 -1
  168. package/dist/client/assets/{usePopupViewport-CAMlnyaP.js → usePopupViewport-8F-J1h5f.js} +1 -1
  169. package/dist/client/assets/{useScrollLock-CAPfesBT.js → useScrollLock-CBz-5_MX.js} +1 -1
  170. package/dist/client/assets/{useStatistics-CWasDzsV.js → useStatistics-B91973jb.js} +1 -1
  171. package/dist/client/assets/{useSwipeDismiss-BZsYSBgq.js → useSwipeDismiss-D22_vuiH.js} +1 -1
  172. package/dist/client/assets/{useThreadActions-MOjDrEnS.js → useThreadActions-BCH01d6u.js} +1 -1
  173. package/dist/client/assets/{useTriggerFocusGuards-D5z439rn.js → useTriggerFocusGuards-f7afwACm.js} +1 -1
  174. package/dist/client/assets/{useValueChanged-D0CHQQwP.js → useValueChanged-EkWF0C3k.js} +1 -1
  175. package/dist/client/assets/{utils-B76_2Yk7.js → utils-CV2fJJxC.js} +1 -1
  176. package/dist/client/index.html +1 -1
  177. package/dist/{collectUint8StreamText-B9B7bGv9.cjs → collectUint8StreamText-Dsbmrw73.cjs} +2 -0
  178. package/dist/{collectUint8StreamText-RzKEq2NY.mjs → collectUint8StreamText-oFvWyN3_.mjs} +2 -0
  179. package/dist/{makeManagedServerProvider-BF1eBatf.cjs → makeManagedServerProvider-CANTNAsz.cjs} +9 -2
  180. package/dist/{makeManagedServerProvider-BuG2fLP8.mjs → makeManagedServerProvider-PLtJj7EV.mjs} +10 -3
  181. package/package.json +1 -1
  182. package/dist/client/assets/DialogRoot-CyEOjgGH.js +0 -1
  183. package/dist/client/assets/device-B0aqBYM1.js +0 -168
  184. package/dist/client/assets/main-B7T7on1T.css +0 -2
  185. package/dist/client/assets/providerInstances-BPwEwwpF.js +0 -1
  186. package/dist/client/assets/providerModels-BPwEwwpF.js +0 -1
  187. package/dist/client/assets/session-logic-DLEAZb3K.js +0 -4
  188. package/dist/client/assets/storeSelectors-D7HbqO4E.js +0 -1
  189. package/dist/client/assets/types-D7HbqO4E.js +0 -1
@@ -1,17 +1,78 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { Ba as ProviderDriverKind, Bo as EventId, Jo as RuntimeRequestId, Ko as ProviderItemId, Pn as TextGenerationError, Va as ProviderInstanceId, Xo as RuntimeSubagentId, ar as OpenCodeSettings, bi as PROVIDER_SEND_TURN_MAX_ATTACHMENT_TOTAL_BYTES, es as TurnId, qo as RuntimeItemId } from "./collectUint8StreamText-RzKEq2NY.mjs";
3
+ import { Ba as ProviderDriverKind, Bo as EventId, Jo as RuntimeRequestId, Ko as ProviderItemId, Pn as TextGenerationError, Va as ProviderInstanceId, Xo as RuntimeSubagentId, ar as OpenCodeSettings, bi as PROVIDER_SEND_TURN_MAX_ATTACHMENT_TOTAL_BYTES, es as TurnId, qo as RuntimeItemId } from "./collectUint8StreamText-oFvWyN3_.mjs";
4
4
  import { nt as sanitizeFeatureBranchName, st as ServerConfig, tt as sanitizeBranchFragment } from "./Metrics-BP9YjxZB.mjs";
5
- import { Bn as createModelCapabilities, C as buildCommitMessagePrompt, D as buildThreadPriorityPrompt, Dn as enrichProviderSnapshotWithVersionAdvisory, E as buildPrContentPrompt, Fn as ServerSettingsService, Hn as getModelSelectionStringOptionValue, In as readPersistedAttachment, K as buildServerProvider, M as sanitizePrTitle, Mn as normalizeCommandPath, N as sanitizeThreadTitle, Nn as resolveProviderMaintenanceCapabilitiesEffect, O as buildThreadTitlePrompt, Pn as compareCliVersions, Q as providerModelsFromSettings, S as buildBranchNamePrompt, T as buildIssueContentTitlePrompt, X as nonEmptyTrimmed, Z as parseGenericCliVersion, _ as ProviderEventLoggers, at as createProcessDeviceToolBinding, c as OpenCodeRuntimeError, ct as ProviderAdapterSessionClosedError, d as openCodeRuntimeErrorDetail, dt as ProviderDriverError, f as parseOpenCodeModelSlug, g as toOpenCodeQuestionAnswers, h as toOpenCodePermissionReply, j as sanitizeCommitSubject, k as extractJsonObject, kn as makePackageManagedProviderMaintenanceResolver, l as buildOpenCodePermissionRules, lt as ProviderAdapterSessionNotFoundError, m as toOpenCodeFileParts, ot as ProviderAdapterProcessError, p as runOpenCodeSdk, s as OpenCodeRuntime, st as ProviderAdapterRequestError, t as makeServerQueueMetrics, tt as agentControlHostContext, u as openCodeQuestionId, ut as ProviderAdapterValidationError, v as makeEventNdjsonLogger, w as buildIssueContentPolishPrompt, x as validateRankInboxThreadsResult, z as mergeProviderInstanceEnvironment } from "./bin.mjs";
5
+ import { $ as parseGenericCliVersion, A as buildThreadTitlePrompt, C as validateRankInboxThreadsResult, D as buildIssueContentTitlePrompt, E as buildIssueContentPolishPrompt, F as sanitizeThreadTitle, Fn as resolveProviderMaintenanceCapabilitiesEffect, Hn as createModelCapabilities, In as compareCliVersions, J as buildServerProvider, Ln as ServerSettingsService, N as sanitizeCommitSubject, O as buildPrContentPrompt, P as sanitizePrTitle, Pn as normalizeCommandPath, Q as nonEmptyTrimmed, Rn as readPersistedAttachment, T as buildCommitMessagePrompt, V as mergeProviderInstanceEnvironment, Wn as getModelSelectionStringOptionValue, _ as toOpenCodeQuestionAnswers, b as makeEventNdjsonLogger, c as OpenCodeRuntime, ct as ProviderAdapterProcessError, d as openCodeQuestionId, dt as ProviderAdapterSessionNotFoundError, et as providerModelsFromSettings, f as openCodeRuntimeErrorDetail, ft as ProviderAdapterValidationError, g as toOpenCodePermissionReply, h as toOpenCodeFileParts, j as extractJsonObject, jn as makePackageManagedProviderMaintenanceResolver, k as buildThreadPriorityPrompt, kn as enrichProviderSnapshotWithVersionAdvisory, l as OpenCodeRuntimeError, lt as ProviderAdapterRequestError, m as runOpenCodeSdk, p as parseOpenCodeModelSlug, pt as ProviderDriverError, rt as agentControlHostContext, s as MINIMUM_OPENCODE_VERSION, st as createProcessDeviceToolBinding, t as makeServerQueueMetrics, u as buildOpenCodePermissionRules, ut as ProviderAdapterSessionClosedError, v as verifyOpenCodeServerVersion, w as buildBranchNamePrompt, y as ProviderEventLoggers } from "./bin.mjs";
6
6
  import { t as formatSourceControlContextsForAgent } from "./sourceControlContextFormatter-DEwpnVAH.mjs";
7
- import { n as requireRuntimeSessionId, r as stampRuntimeEvent, t as makeManagedServerProvider } from "./makeManagedServerProvider-BuG2fLP8.mjs";
7
+ import { n as requireRuntimeSessionId, r as stampRuntimeEvent, t as makeManagedServerProvider } from "./makeManagedServerProvider-PLtJj7EV.mjs";
8
8
  import { t as defaultProviderContinuationIdentity } from "./ProviderDriver-kCV60GKk.mjs";
9
- import { Cause, Data, Effect, Exit, Fiber, Queue, Ref, Schema, Scope, Stream } from "effect";
9
+ import { Cause, Data, Effect, Exit, Fiber, Queue, Ref, Schema, Scope, Semaphore, Stream } from "effect";
10
10
  import { HttpClient } from "effect/unstable/http";
11
11
  import "effect/unstable/process";
12
12
  import * as Semaphore$1 from "effect/Semaphore";
13
+ //#region src/provider/OpenCodeServerOwner.ts
14
+ const OPENCODE_MANAGED_SERVER_IDLE_TTL = "30 seconds";
15
+ const makeOpenCodeServerOwner = Effect.fn("makeOpenCodeServerOwner")(function* (settings, environment = process.env) {
16
+ const runtime = yield* OpenCodeRuntime;
17
+ const ownerScope = yield* Effect.scope;
18
+ const mutex = yield* Semaphore$1.make(1);
19
+ let owned = null;
20
+ const closeOwned = (record) => Effect.gen(function* () {
21
+ if (owned === record) owned = null;
22
+ const idleFiber = record.idleCloseFiber;
23
+ record.idleCloseFiber = null;
24
+ if (idleFiber !== null) yield* Fiber.interrupt(idleFiber).pipe(Effect.ignore);
25
+ yield* Scope.close(record.scope, Exit.void).pipe(Effect.ignore);
26
+ });
27
+ const cancelIdleClose = (record) => Effect.gen(function* () {
28
+ const fiber = record.idleCloseFiber;
29
+ record.idleCloseFiber = null;
30
+ if (fiber !== null) yield* Fiber.interrupt(fiber).pipe(Effect.ignore);
31
+ });
32
+ const acquireProcess = mutex.withPermit(Effect.gen(function* () {
33
+ if (owned !== null) {
34
+ yield* cancelIdleClose(owned);
35
+ owned.leases += 1;
36
+ return owned.process;
37
+ }
38
+ return yield* Effect.uninterruptibleMask((restore) => Effect.gen(function* () {
39
+ const processScope = yield* Scope.make();
40
+ const started = yield* Effect.exit(restore(runtime.startOpenCodeServerProcess({
41
+ binaryPath: settings.binaryPath,
42
+ ...settings.serverPassword ? { serverPassword: settings.serverPassword } : {},
43
+ environment
44
+ }).pipe(Effect.provideService(Scope.Scope, processScope))));
45
+ if (Exit.isFailure(started)) {
46
+ yield* Scope.close(processScope, Exit.void).pipe(Effect.ignore);
47
+ return yield* Effect.failCause(started.cause);
48
+ }
49
+ owned = {
50
+ process: started.value,
51
+ scope: processScope,
52
+ leases: 1,
53
+ idleCloseFiber: null
54
+ };
55
+ return started.value;
56
+ }));
57
+ }));
58
+ const releaseProcess = (process) => mutex.withPermit(Effect.gen(function* () {
59
+ const record = owned;
60
+ if (record === null || record.process !== process) return;
61
+ record.leases = Math.max(0, record.leases - 1);
62
+ if (record.leases > 0 || record.idleCloseFiber !== null) return;
63
+ record.idleCloseFiber = yield* Effect.sleep(OPENCODE_MANAGED_SERVER_IDLE_TTL).pipe(Effect.andThen(mutex.withPermit(Effect.gen(function* () {
64
+ if (owned !== record || record.leases > 0) return;
65
+ record.idleCloseFiber = null;
66
+ yield* closeOwned(record);
67
+ }))), Effect.forkIn(ownerScope));
68
+ }));
69
+ yield* Effect.addFinalizer(() => mutex.withPermit(Effect.gen(function* () {
70
+ if (owned !== null) yield* closeOwned(owned);
71
+ })));
72
+ return { acquire: Effect.acquireRelease(acquireProcess, releaseProcess) };
73
+ });
74
+ //#endregion
13
75
  //#region src/textGeneration/OpenCodeTextGeneration.ts
14
- const OPENCODE_TEXT_GENERATION_IDLE_TTL = "30 seconds";
15
76
  function getOpenCodePromptErrorMessage(error) {
16
77
  if (!error || typeof error !== "object") return null;
17
78
  const message = "data" in error && error.data && typeof error.data === "object" && "message" in error.data && typeof error.data.message === "string" ? error.data.message.trim() : "";
@@ -30,82 +91,10 @@ function getOpenCodeTextResponse(parts) {
30
91
  return [part.text];
31
92
  }).join("").trim();
32
93
  }
33
- const makeOpenCodeTextGeneration = Effect.fn("makeOpenCodeTextGeneration")(function* (openCodeSettings, environment = process.env) {
94
+ const makeOpenCodeTextGeneration = Effect.fn("makeOpenCodeTextGeneration")(function* (openCodeSettings, environment = process.env, options) {
34
95
  const serverConfig = yield* ServerConfig;
35
96
  const openCodeRuntime = yield* OpenCodeRuntime;
36
- const idleFiberScope = yield* Effect.acquireRelease(Scope.make(), (scope) => Scope.close(scope, Exit.void));
37
- const sharedServerMutex = yield* Semaphore$1.make(1);
38
- const sharedServerState = {
39
- server: null,
40
- serverScope: null,
41
- binaryPath: null,
42
- activeRequests: 0,
43
- idleCloseFiber: null
44
- };
45
- const closeSharedServer = Effect.fn("closeSharedServer")(function* () {
46
- const scope = sharedServerState.serverScope;
47
- sharedServerState.server = null;
48
- sharedServerState.serverScope = null;
49
- sharedServerState.binaryPath = null;
50
- if (scope !== null) yield* Scope.close(scope, Exit.void).pipe(Effect.ignore);
51
- });
52
- const cancelIdleCloseFiber = Effect.fn("cancelIdleCloseFiber")(function* () {
53
- const idleCloseFiber = sharedServerState.idleCloseFiber;
54
- sharedServerState.idleCloseFiber = null;
55
- if (idleCloseFiber !== null) yield* Fiber.interrupt(idleCloseFiber).pipe(Effect.ignore);
56
- });
57
- const scheduleIdleClose = Effect.fn("scheduleIdleClose")(function* (server) {
58
- yield* cancelIdleCloseFiber();
59
- const fiber = yield* Effect.sleep(OPENCODE_TEXT_GENERATION_IDLE_TTL).pipe(Effect.andThen(sharedServerMutex.withPermit(Effect.gen(function* () {
60
- if (sharedServerState.server !== server || sharedServerState.activeRequests > 0) return;
61
- sharedServerState.idleCloseFiber = null;
62
- yield* closeSharedServer();
63
- }))), Effect.forkIn(idleFiberScope));
64
- sharedServerState.idleCloseFiber = fiber;
65
- });
66
- const acquireSharedServer = (input) => sharedServerMutex.withPermit(Effect.gen(function* () {
67
- yield* cancelIdleCloseFiber();
68
- const existingServer = sharedServerState.server;
69
- if (existingServer !== null) {
70
- if (sharedServerState.binaryPath !== input.binaryPath && sharedServerState.activeRequests === 0) yield* closeSharedServer();
71
- else {
72
- if (sharedServerState.binaryPath !== input.binaryPath) yield* Effect.logWarning("OpenCode shared server binary path mismatch: requested " + input.binaryPath + " but active server uses " + sharedServerState.binaryPath + "; reusing existing server because there are active requests");
73
- sharedServerState.activeRequests += 1;
74
- return existingServer;
75
- }
76
- }
77
- return yield* Effect.uninterruptibleMask((restore) => Effect.gen(function* () {
78
- const serverScope = yield* Scope.make();
79
- const startedExit = yield* Effect.exit(restore(openCodeRuntime.startOpenCodeServerProcess({
80
- binaryPath: input.binaryPath,
81
- environment
82
- }).pipe(Effect.provideService(Scope.Scope, serverScope), Effect.mapError((cause) => new TextGenerationError({
83
- operation: input.operation,
84
- detail: openCodeRuntimeErrorDetail(cause),
85
- cause
86
- })))));
87
- if (startedExit._tag === "Failure") {
88
- yield* Scope.close(serverScope, Exit.void).pipe(Effect.ignore);
89
- return yield* Effect.failCause(startedExit.cause);
90
- }
91
- const server = startedExit.value;
92
- sharedServerState.server = server;
93
- sharedServerState.serverScope = serverScope;
94
- sharedServerState.binaryPath = input.binaryPath;
95
- sharedServerState.activeRequests = 1;
96
- return server;
97
- }));
98
- }));
99
- const releaseSharedServer = (server) => sharedServerMutex.withPermit(Effect.gen(function* () {
100
- if (sharedServerState.server !== server) return;
101
- sharedServerState.activeRequests = Math.max(0, sharedServerState.activeRequests - 1);
102
- if (sharedServerState.activeRequests === 0) yield* scheduleIdleClose(server);
103
- }));
104
- yield* Effect.addFinalizer(() => sharedServerMutex.withPermit(Effect.gen(function* () {
105
- yield* cancelIdleCloseFiber();
106
- sharedServerState.activeRequests = 0;
107
- yield* closeSharedServer();
108
- })));
97
+ const serverOwner = options?.serverOwner ?? (openCodeSettings.serverUrl.trim().length === 0 ? yield* makeOpenCodeServerOwner(openCodeSettings, environment) : void 0);
109
98
  const runOpenCodeJson = Effect.fn("runOpenCodeJson")(function* (input) {
110
99
  const parsedModel = parseOpenCodeModelSlug(input.modelSelection.model);
111
100
  if (!parsedModel) return yield* new TextGenerationError({
@@ -143,12 +132,17 @@ const makeOpenCodeTextGeneration = Effect.fn("makeOpenCodeTextGeneration")(funct
143
132
  const client = yield* openCodeRuntime.createOpenCodeSdkClient({
144
133
  baseUrl: server.url,
145
134
  directory: input.cwd,
146
- ...openCodeSettings.serverUrl.length > 0 && openCodeSettings.serverPassword ? { serverPassword: openCodeSettings.serverPassword } : {}
135
+ ...server.serverPassword ? { serverPassword: server.serverPassword } : {}
147
136
  }).pipe(Effect.mapError((cause) => new TextGenerationError({
148
137
  operation: input.operation,
149
138
  detail: openCodeRuntimeErrorDetail(cause),
150
139
  cause
151
140
  })));
141
+ yield* verifyOpenCodeServerVersion(client).pipe(Effect.mapError((cause) => new TextGenerationError({
142
+ operation: input.operation,
143
+ detail: openCodeRuntimeErrorDetail(cause),
144
+ cause
145
+ })));
152
146
  return yield* Effect.tryPromise({
153
147
  try: async () => {
154
148
  const session = await client.session.create({
@@ -186,10 +180,14 @@ const makeOpenCodeTextGeneration = Effect.fn("makeOpenCodeTextGeneration")(funct
186
180
  })
187
181
  });
188
182
  });
189
- const rawOutput = openCodeSettings.serverUrl.length > 0 ? yield* runAgainstServer({ url: openCodeSettings.serverUrl }) : yield* Effect.acquireUseRelease(acquireSharedServer({
190
- binaryPath: openCodeSettings.binaryPath,
191
- operation: input.operation
192
- }), runAgainstServer, releaseSharedServer);
183
+ const rawOutput = openCodeSettings.serverUrl.length > 0 ? yield* runAgainstServer({
184
+ url: openCodeSettings.serverUrl,
185
+ ...openCodeSettings.serverPassword ? { serverPassword: openCodeSettings.serverPassword } : {}
186
+ }) : yield* Effect.scoped(serverOwner.acquire.pipe(Effect.mapError((cause) => new TextGenerationError({
187
+ operation: input.operation,
188
+ detail: openCodeRuntimeErrorDetail(cause),
189
+ cause
190
+ })), Effect.flatMap(runAgainstServer)));
193
191
  return yield* Schema.decodeEffect(Schema.fromJsonString(input.outputSchemaJson))(extractJsonObject(rawOutput)).pipe(Effect.catchTag("SchemaError", (cause) => Effect.fail(new TextGenerationError({
194
192
  operation: input.operation,
195
193
  detail: "OpenCode returned invalid structured output.",
@@ -312,6 +310,7 @@ const makeOpenCodeTextGeneration = Effect.fn("makeOpenCodeTextGeneration")(funct
312
310
  //#endregion
313
311
  //#region src/provider/Layers/OpenCodeAdapter.ts
314
312
  const PROVIDER$1 = ProviderDriverKind.make("opencode");
313
+ const OPENCODE_RESUME_VERSION = 1;
315
314
  function nowIso() {
316
315
  return (/* @__PURE__ */ new Date()).toISOString();
317
316
  }
@@ -319,6 +318,15 @@ function nonEmptyString(value) {
319
318
  const trimmed = value?.trim();
320
319
  return trimmed && trimmed.length > 0 ? trimmed : void 0;
321
320
  }
321
+ function parseOpenCodeResume(value) {
322
+ if (!value || typeof value !== "object") return;
323
+ const cursor = value;
324
+ return cursor.schemaVersion === OPENCODE_RESUME_VERSION && typeof cursor.sessionId === "string" && cursor.sessionId.trim().length > 0 ? { sessionId: cursor.sessionId } : void 0;
325
+ }
326
+ function isOpenCodeNotFound(error) {
327
+ const cause = error.cause;
328
+ return typeof cause === "object" && cause !== null && "response" in cause && cause.response?.status === 404;
329
+ }
322
330
  function scopedOpenCodeId(sessionId, id) {
323
331
  return `${sessionId}:${id}`;
324
332
  }
@@ -331,6 +339,9 @@ function subagentKey(subagentId) {
331
339
  function statusFromOpenCodeSubagentState(status) {
332
340
  return status;
333
341
  }
342
+ function isOpenCodeRequestEvent(event) {
343
+ return event.type === "permission.asked" || event.type === "permission.replied" || event.type === "question.asked" || event.type === "question.replied" || event.type === "question.rejected";
344
+ }
334
345
  function subagentCompletionStatus(status) {
335
346
  return status;
336
347
  }
@@ -340,6 +351,7 @@ function metadataWithEntries(entries) {
340
351
  }
341
352
  function makeSubtaskSubagentRef(part) {
342
353
  const description = nonEmptyString(part.description) ?? nonEmptyString(part.prompt);
354
+ const model = part.model ? `${part.model.providerID}/${part.model.modelID}` : void 0;
343
355
  const label = nonEmptyString(part.agent) ?? nonEmptyString(part.command) ?? (description ? "OpenCode subtask" : void 0);
344
356
  return {
345
357
  subagentId: openCodeSubagentId("subtask", part.id),
@@ -347,6 +359,7 @@ function makeSubtaskSubagentRef(part) {
347
359
  capability: "summary",
348
360
  ...label ? { label } : {},
349
361
  ...description ? { description } : {},
362
+ ...model ? { model } : {},
350
363
  parentProviderItemId: ProviderItemId.make(part.id),
351
364
  metadata: metadataWithEntries([
352
365
  ["source", "opencode.subtask"],
@@ -365,6 +378,8 @@ function mergeOpenCodeChildSessionRef(existing, session, parentSessionId) {
365
378
  capability: "transcript",
366
379
  label,
367
380
  ...existing?.description ? { description: existing.description } : {},
381
+ ...existing?.model ? { model: existing.model } : {},
382
+ ...existing?.effort ? { effort: existing.effort } : {},
368
383
  providerSessionId: session.id,
369
384
  providerThreadId: session.id,
370
385
  ...existing?.parentProviderItemId && { parentProviderItemId: existing.parentProviderItemId },
@@ -401,6 +416,13 @@ const toProcessError = (threadId, cause) => new ProviderAdapterProcessError({
401
416
  detail: OpenCodeRuntimeError.is(cause) ? cause.detail : openCodeRuntimeErrorDetail(cause),
402
417
  cause
403
418
  });
419
+ const abortOpenCodeSession = (context, sessionID) => runOpenCodeSdk("session.abort", (signal) => context.client.session.abort({ sessionID }, { signal })).pipe(Effect.timeoutOrElse({
420
+ duration: "2 seconds",
421
+ orElse: () => Effect.fail(new OpenCodeRuntimeError({
422
+ operation: "session.abort",
423
+ detail: `Timed out aborting OpenCode session '${sessionID}'.`
424
+ }))
425
+ }));
404
426
  const buildEventBase = (input) => Effect.sync(() => crypto.randomUUID()).pipe(Effect.map((uuid) => ({
405
427
  eventId: EventId.make(uuid),
406
428
  provider: PROVIDER$1,
@@ -560,7 +582,12 @@ function updateProviderSession(context, patch, options) {
560
582
  }
561
583
  const stopOpenCodeContext = Effect.fn("stopOpenCodeContext")(function* (context) {
562
584
  if (yield* Ref.getAndSet(context.stopped, true)) return false;
563
- yield* Effect.forEach([context.openCodeSessionId, ...context.childSessionIds], (sessionID) => runOpenCodeSdk("session.abort", () => context.client.session.abort({ sessionID })).pipe(Effect.ignore({ log: true })), { discard: true });
585
+ const pendingPrompt = context.pendingPrompt;
586
+ if (pendingPrompt) {
587
+ context.pendingPrompt = void 0;
588
+ yield* Fiber.interrupt(pendingPrompt.fiber).pipe(Effect.ignore);
589
+ }
590
+ yield* Effect.forEach([context.openCodeSessionId, ...context.childSessionIds], (sessionID) => abortOpenCodeSession(context, sessionID).pipe(Effect.ignore({ log: true })), { discard: true });
564
591
  yield* Scope.close(context.sessionScope, Exit.void);
565
592
  return true;
566
593
  });
@@ -675,8 +702,8 @@ function makeOpenCodeAdapter(openCodeSettings, options) {
675
702
  return context.subagentBySubtaskPartId.get(partKey);
676
703
  };
677
704
  const registerOpenCodeChildSession = Effect.fn("registerOpenCodeChildSession")(function* (context, session, raw) {
678
- if (session.parentID !== context.openCodeSessionId) return;
679
- const subagent = mergeOpenCodeChildSessionRef(context.subagentBySessionId.get(session.id) ?? takeUnboundOpenCodeSubtask(context), session, context.openCodeSessionId);
705
+ if (session.parentID !== context.openCodeSessionId && (session.parentID === void 0 || !context.childSessionIds.has(session.parentID))) return;
706
+ const subagent = mergeOpenCodeChildSessionRef(context.subagentBySessionId.get(session.id) ?? takeUnboundOpenCodeSubtask(context), session, session.parentID ?? context.openCodeSessionId);
680
707
  const known = context.childSessionIds.has(session.id);
681
708
  context.childSessionIds.add(session.id);
682
709
  context.subagentBySessionId.set(session.id, subagent);
@@ -720,6 +747,89 @@ function makeOpenCodeAdapter(openCodeSettings, options) {
720
747
  child
721
748
  });
722
749
  });
750
+ const isRelatedOpenCodeSession = Effect.fn("isRelatedOpenCodeSession")(function* (context, candidateSessionId) {
751
+ if (candidateSessionId === context.openCodeSessionId || context.childSessionIds.has(candidateSessionId)) return true;
752
+ const seen = /* @__PURE__ */ new Set();
753
+ let sessionId = candidateSessionId;
754
+ for (let depth = 0; sessionId !== void 0 && depth < 32; depth += 1) {
755
+ if (sessionId === context.openCodeSessionId || context.childSessionIds.has(sessionId)) {
756
+ for (const relatedId of seen) context.childSessionIds.add(relatedId);
757
+ return true;
758
+ }
759
+ if (seen.has(sessionId)) return false;
760
+ seen.add(sessionId);
761
+ const currentSessionId = sessionId;
762
+ const response = yield* runOpenCodeSdk("session.get", () => context.client.session.get({ sessionID: currentSessionId })).pipe(Effect.catchIf(isOpenCodeNotFound, () => Effect.succeed(void 0)));
763
+ if (!response?.data) return false;
764
+ sessionId = response.data.parentID;
765
+ }
766
+ return false;
767
+ });
768
+ const recoverPendingOpenCodeRequests = Effect.fn("recoverPendingOpenCodeRequests")(function* (context) {
769
+ for (let attempt = 0; attempt < 5; attempt += 1) {
770
+ if (yield* Ref.get(context.stopped)) return;
771
+ const result = yield* Effect.all({
772
+ permissions: runOpenCodeSdk("permission.list", () => context.client.permission.list()),
773
+ questions: runOpenCodeSdk("question.list", () => context.client.question.list())
774
+ }).pipe(Effect.exit);
775
+ if (Exit.isFailure(result)) {
776
+ if (attempt === 4) {
777
+ yield* emitForContext(context, {
778
+ ...yield* buildEventBase({ threadId: context.session.threadId }),
779
+ type: "runtime.warning",
780
+ payload: {
781
+ message: "OpenCode pending request recovery failed.",
782
+ detail: openCodeRuntimeErrorDetail(Cause.squash(result.cause))
783
+ }
784
+ });
785
+ return;
786
+ }
787
+ yield* Effect.sleep(`${250 * 2 ** attempt} millis`);
788
+ continue;
789
+ }
790
+ for (const request of result.value.permissions.data ?? []) {
791
+ if (context.resolvedRequestIds.has(request.id) || context.pendingPermissions.has(request.id) || !(yield* isRelatedOpenCodeSession(context, request.sessionID))) continue;
792
+ context.pendingPermissions.set(request.id, request);
793
+ yield* emitForContext(context, {
794
+ ...yield* buildEventBase({
795
+ threadId: context.session.threadId,
796
+ turnId: context.activeTurnId,
797
+ requestId: request.id,
798
+ raw: {
799
+ type: "permission.asked",
800
+ properties: request,
801
+ recovered: true
802
+ }
803
+ }),
804
+ type: "request.opened",
805
+ payload: {
806
+ requestType: mapPermissionToRequestType(request.permission),
807
+ detail: request.patterns.length > 0 ? request.patterns.join("\n") : request.permission,
808
+ args: request.metadata
809
+ }
810
+ });
811
+ }
812
+ for (const request of result.value.questions.data ?? []) {
813
+ if (context.resolvedRequestIds.has(request.id) || context.pendingQuestions.has(request.id) || !(yield* isRelatedOpenCodeSession(context, request.sessionID))) continue;
814
+ context.pendingQuestions.set(request.id, request);
815
+ yield* emitForContext(context, {
816
+ ...yield* buildEventBase({
817
+ threadId: context.session.threadId,
818
+ turnId: context.activeTurnId,
819
+ requestId: request.id,
820
+ raw: {
821
+ type: "question.asked",
822
+ properties: request,
823
+ recovered: true
824
+ }
825
+ }),
826
+ type: "user-input.requested",
827
+ payload: { questions: normalizeQuestionRequest(request) }
828
+ });
829
+ }
830
+ return;
831
+ }
832
+ });
723
833
  const emitUnexpectedExit = Effect.fn("emitUnexpectedExit")(function* (context, message) {
724
834
  if (yield* Ref.getAndSet(context.stopped, true)) return;
725
835
  const turnId = context.activeTurnId;
@@ -822,8 +932,9 @@ function makeOpenCodeAdapter(openCodeSettings, options) {
822
932
  const eventSessionId = typeof payloadSessionId === "string" ? payloadSessionId : void 0;
823
933
  const isRootSessionEvent = eventSessionId === context.openCodeSessionId;
824
934
  const isKnownChildSessionEvent = eventSessionId !== void 0 && context.childSessionIds.has(eventSessionId);
825
- const isChildSessionCreatedEvent = event.type === "session.created" && event.properties.info.parentID === context.openCodeSessionId;
826
- if (!isRootSessionEvent && !isKnownChildSessionEvent && !isChildSessionCreatedEvent) return;
935
+ const isChildSessionCreatedEvent = event.type === "session.created" && (event.properties.info.parentID === context.openCodeSessionId || event.properties.info.parentID !== void 0 && context.childSessionIds.has(event.properties.info.parentID));
936
+ const isRelatedRequestEvent = eventSessionId !== void 0 && isOpenCodeRequestEvent(event) && (yield* isRelatedOpenCodeSession(context, eventSessionId).pipe(Effect.orElseSucceed(() => false)));
937
+ if (!isRootSessionEvent && !isKnownChildSessionEvent && !isChildSessionCreatedEvent && !isRelatedRequestEvent) return;
827
938
  const turnId = context.activeTurnId;
828
939
  yield* writeNativeEventBestEffort(context.session.threadId, {
829
940
  observedAt: nowIso(),
@@ -946,6 +1057,7 @@ function makeOpenCodeAdapter(openCodeSettings, options) {
946
1057
  break;
947
1058
  }
948
1059
  case "permission.asked":
1060
+ if (context.resolvedRequestIds.has(event.properties.id) || context.pendingPermissions.has(event.properties.id)) break;
949
1061
  context.pendingPermissions.set(event.properties.id, event.properties);
950
1062
  yield* emitForContext(context, {
951
1063
  ...yield* buildEventBase({
@@ -963,6 +1075,7 @@ function makeOpenCodeAdapter(openCodeSettings, options) {
963
1075
  });
964
1076
  break;
965
1077
  case "permission.replied":
1078
+ context.resolvedRequestIds.add(event.properties.requestID);
966
1079
  context.pendingPermissions.delete(event.properties.requestID);
967
1080
  yield* emitForContext(context, {
968
1081
  ...yield* buildEventBase({
@@ -979,6 +1092,7 @@ function makeOpenCodeAdapter(openCodeSettings, options) {
979
1092
  });
980
1093
  break;
981
1094
  case "question.asked":
1095
+ if (context.resolvedRequestIds.has(event.properties.id) || context.pendingQuestions.has(event.properties.id)) break;
982
1096
  context.pendingQuestions.set(event.properties.id, event.properties);
983
1097
  yield* emitForContext(context, {
984
1098
  ...yield* buildEventBase({
@@ -992,6 +1106,7 @@ function makeOpenCodeAdapter(openCodeSettings, options) {
992
1106
  });
993
1107
  break;
994
1108
  case "question.replied": {
1109
+ context.resolvedRequestIds.add(event.properties.requestID);
995
1110
  const request = context.pendingQuestions.get(event.properties.requestID);
996
1111
  context.pendingQuestions.delete(event.properties.requestID);
997
1112
  const answers = Object.fromEntries((request?.questions ?? []).map((question, index) => [openCodeQuestionId(index, question), event.properties.answers[index]?.join(", ") ?? ""]));
@@ -1008,6 +1123,7 @@ function makeOpenCodeAdapter(openCodeSettings, options) {
1008
1123
  break;
1009
1124
  }
1010
1125
  case "question.rejected":
1126
+ context.resolvedRequestIds.add(event.properties.requestID);
1011
1127
  context.pendingQuestions.delete(event.properties.requestID);
1012
1128
  yield* emitForContext(context, {
1013
1129
  ...yield* buildEventBase({
@@ -1059,7 +1175,13 @@ function makeOpenCodeAdapter(openCodeSettings, options) {
1059
1175
  break;
1060
1176
  }
1061
1177
  if (event.properties.status.type === "idle" && turnId) {
1178
+ if (context.pendingPrompt?.turnId === turnId) {
1179
+ context.pendingPrompt.idleEvent = event;
1180
+ break;
1181
+ }
1062
1182
  context.activeTurnId = void 0;
1183
+ context.activeAgent = void 0;
1184
+ context.activeVariant = void 0;
1063
1185
  updateProviderSession(context, { status: "ready" }, { clearActiveTurnId: true });
1064
1186
  yield* emitForContext(context, {
1065
1187
  ...yield* buildEventBase({
@@ -1095,7 +1217,14 @@ function makeOpenCodeAdapter(openCodeSettings, options) {
1095
1217
  break;
1096
1218
  }
1097
1219
  const activeTurnId = context.activeTurnId;
1220
+ const pendingPrompt = context.pendingPrompt;
1221
+ if (pendingPrompt && pendingPrompt.turnId === activeTurnId) {
1222
+ context.pendingPrompt = void 0;
1223
+ yield* Fiber.interrupt(pendingPrompt.fiber).pipe(Effect.ignore);
1224
+ }
1098
1225
  context.activeTurnId = void 0;
1226
+ context.activeAgent = void 0;
1227
+ context.activeVariant = void 0;
1099
1228
  updateProviderSession(context, {
1100
1229
  status: "error",
1101
1230
  lastError: message
@@ -1160,6 +1289,7 @@ function makeOpenCodeAdapter(openCodeSettings, options) {
1160
1289
  const serverUrl = openCodeSettings.serverUrl;
1161
1290
  const serverPassword = openCodeSettings.serverPassword;
1162
1291
  const directory = input.cwd ?? serverConfig.cwd;
1292
+ const resumeSessionId = input.resumePolicy === "fresh" ? void 0 : parseOpenCodeResume(input.resumeCursor)?.sessionId;
1163
1293
  const existing = sessions.get(input.threadId);
1164
1294
  if (existing) {
1165
1295
  if (existing.session.runtimeSessionId === runtimeSessionId) return existing.session;
@@ -1178,16 +1308,23 @@ function makeOpenCodeAdapter(openCodeSettings, options) {
1178
1308
  const sessionScope = yield* Scope.make();
1179
1309
  if (deviceToolBinding) yield* Scope.addFinalizer(sessionScope, Effect.sync(() => deviceToolBinding.dispose()));
1180
1310
  const startedExit = yield* Effect.exit(Effect.gen(function* () {
1181
- const server = yield* openCodeRuntime.connectToOpenCodeServer({
1311
+ const server = options?.serverOwner ? yield* options.serverOwner.acquire.pipe(Effect.map((process) => ({
1312
+ url: process.url,
1313
+ ...process.serverPassword ? { serverPassword: process.serverPassword } : {},
1314
+ exitCode: process.exitCode,
1315
+ external: false
1316
+ }))) : yield* openCodeRuntime.connectToOpenCodeServer({
1182
1317
  binaryPath,
1183
1318
  serverUrl,
1319
+ ...serverPassword ? { serverPassword } : {},
1184
1320
  ...options?.environment ? { environment: options.environment } : {}
1185
1321
  });
1186
1322
  const client = yield* openCodeRuntime.createOpenCodeSdkClient({
1187
1323
  baseUrl: server.url,
1188
1324
  directory,
1189
- ...server.external && serverPassword ? { serverPassword } : {}
1325
+ ...server.serverPassword ? { serverPassword: server.serverPassword } : {}
1190
1326
  });
1327
+ yield* verifyOpenCodeServerVersion(client);
1191
1328
  if (deviceToolBinding) yield* runOpenCodeSdk("mcp.add", () => client.mcp.add({
1192
1329
  directory,
1193
1330
  name: `ryco_device_${runtimeSessionId}`,
@@ -1199,13 +1336,18 @@ function makeOpenCodeAdapter(openCodeSettings, options) {
1199
1336
  enabled: true
1200
1337
  }
1201
1338
  }));
1202
- const openCodeSession = yield* runOpenCodeSdk("session.create", () => client.session.create({
1339
+ const adoptedSession = resumeSessionId ? yield* runOpenCodeSdk("session.get", () => client.session.get({ sessionID: resumeSessionId })).pipe(Effect.map((response) => response.data), Effect.catchIf(isOpenCodeNotFound, () => Effect.succeed(void 0))) : void 0;
1340
+ if (adoptedSession) yield* runOpenCodeSdk("session.update", () => client.session.update({
1341
+ sessionID: adoptedSession.id,
1342
+ permission: buildOpenCodePermissionRules(input.runtimeMode)
1343
+ }));
1344
+ const openCodeSession = adoptedSession ? { data: adoptedSession } : yield* runOpenCodeSdk("session.create", () => client.session.create({
1203
1345
  title: `Ryco ${input.threadId}`,
1204
1346
  permission: buildOpenCodePermissionRules(input.runtimeMode)
1205
1347
  }));
1206
1348
  if (!openCodeSession.data) return yield* new OpenCodeRuntimeError({
1207
- operation: "session.create",
1208
- detail: "OpenCode session.create returned no session payload."
1349
+ operation: adoptedSession ? "session.get" : "session.create",
1350
+ detail: adoptedSession ? "OpenCode session.get returned no session payload." : "OpenCode session.create returned no session payload."
1209
1351
  });
1210
1352
  return {
1211
1353
  sessionScope,
@@ -1238,6 +1380,10 @@ function makeOpenCodeAdapter(openCodeSettings, options) {
1238
1380
  cwd: directory,
1239
1381
  ...input.modelSelection ? { model: input.modelSelection.model } : {},
1240
1382
  threadId: input.threadId,
1383
+ resumeCursor: {
1384
+ schemaVersion: OPENCODE_RESUME_VERSION,
1385
+ sessionId: started.openCodeSession.id
1386
+ },
1241
1387
  createdAt,
1242
1388
  updatedAt: createdAt
1243
1389
  };
@@ -1249,6 +1395,7 @@ function makeOpenCodeAdapter(openCodeSettings, options) {
1249
1395
  openCodeSessionId: started.openCodeSession.id,
1250
1396
  pendingPermissions: /* @__PURE__ */ new Map(),
1251
1397
  pendingQuestions: /* @__PURE__ */ new Map(),
1398
+ resolvedRequestIds: /* @__PURE__ */ new Set(),
1252
1399
  partById: /* @__PURE__ */ new Map(),
1253
1400
  emittedTextByPartId: /* @__PURE__ */ new Map(),
1254
1401
  messageRoleById: /* @__PURE__ */ new Map(),
@@ -1263,6 +1410,9 @@ function makeOpenCodeAdapter(openCodeSettings, options) {
1263
1410
  activeTurnId: void 0,
1264
1411
  activeAgent: void 0,
1265
1412
  activeVariant: void 0,
1413
+ promptSemaphore: yield* Semaphore.make(1),
1414
+ pendingPrompt: void 0,
1415
+ promptGeneration: 0,
1266
1416
  agentControlHostContextDelivered: false,
1267
1417
  stopped: yield* Ref.make(false),
1268
1418
  sessionScope: started.sessionScope
@@ -1280,138 +1430,193 @@ function makeOpenCodeAdapter(openCodeSettings, options) {
1280
1430
  payload: { providerThreadId: started.openCodeSession.id }
1281
1431
  });
1282
1432
  yield* startEventPump(context);
1283
- yield* hydrateOpenCodeChildSessions(context).pipe(Effect.forkIn(context.sessionScope));
1433
+ yield* Effect.gen(function* () {
1434
+ yield* hydrateOpenCodeChildSessions(context);
1435
+ yield* recoverPendingOpenCodeRequests(context);
1436
+ }).pipe(Effect.forkIn(context.sessionScope));
1284
1437
  return session;
1285
1438
  });
1286
1439
  const sendTurn = Effect.fn("sendTurn")(function* (input) {
1287
1440
  const context = ensureSessionContext(sessions, input.threadId);
1288
- const turnId = TurnId.make(`opencode-turn-${yield* Effect.sync(() => crypto.randomUUID())}`);
1289
- const modelSelection = input.modelSelection ?? (context.session.model ? {
1290
- instanceId: boundInstanceId,
1291
- model: context.session.model
1292
- } : void 0);
1293
- if (modelSelection !== void 0 && modelSelection.instanceId !== boundInstanceId) return yield* new ProviderAdapterValidationError({
1294
- provider: PROVIDER$1,
1295
- operation: "sendTurn",
1296
- issue: `OpenCode model selection is bound to instance '${modelSelection?.instanceId}', expected '${boundInstanceId}'.`
1297
- });
1298
- const parsedModel = parseOpenCodeModelSlug(modelSelection?.model);
1299
- if (!parsedModel) return yield* new ProviderAdapterValidationError({
1300
- provider: PROVIDER$1,
1301
- operation: "sendTurn",
1302
- issue: "OpenCode model selection must use the 'provider/model' format."
1303
- });
1304
- const formatted = formatSourceControlContextsForAgent(input.sourceControlContexts ?? []);
1305
- let text = formatted ? formatted + "\n\n" + (input.input?.trim() ?? "") : input.input?.trim();
1306
- const attachmentUrlById = /* @__PURE__ */ new Map();
1307
- const declaredAttachmentBytes = (input.attachments ?? []).reduce((total, attachment) => total + attachment.sizeBytes, 0);
1308
- if (declaredAttachmentBytes > 52428800) return yield* new ProviderAdapterRequestError({
1309
- provider: PROVIDER$1,
1310
- method: "session.prompt",
1311
- detail: `Attachments total ${declaredAttachmentBytes} bytes; limit is ${PROVIDER_SEND_TURN_MAX_ATTACHMENT_TOTAL_BYTES} bytes.`
1312
- });
1313
- let attachmentTotalBytes = 0;
1314
- for (const attachment of input.attachments ?? []) {
1315
- const persisted = readPersistedAttachment({
1316
- attachmentsDir: serverConfig.attachmentsDir,
1317
- attachment
1441
+ return yield* context.promptSemaphore.withPermits(1)(Effect.gen(function* () {
1442
+ if (sessions.get(input.threadId) !== context || (yield* Ref.get(context.stopped))) return yield* new ProviderAdapterSessionClosedError({
1443
+ provider: PROVIDER$1,
1444
+ threadId: input.threadId
1318
1445
  });
1319
- if (!persisted.ok) return yield* new ProviderAdapterRequestError({
1446
+ const turnId = TurnId.make(`opencode-turn-${yield* Effect.sync(() => crypto.randomUUID())}`);
1447
+ const modelSelection = input.modelSelection ?? (context.session.model ? {
1448
+ instanceId: boundInstanceId,
1449
+ model: context.session.model
1450
+ } : void 0);
1451
+ if (modelSelection !== void 0 && modelSelection.instanceId !== boundInstanceId) return yield* new ProviderAdapterValidationError({
1320
1452
  provider: PROVIDER$1,
1321
- method: "session.prompt",
1322
- detail: persisted.reason
1453
+ operation: "sendTurn",
1454
+ issue: `OpenCode model selection is bound to instance '${modelSelection?.instanceId}', expected '${boundInstanceId}'.`
1323
1455
  });
1324
- attachmentUrlById.set(attachment.id, `data:${attachment.mimeType};base64,${persisted.bytes.toString("base64")}`);
1325
- attachmentTotalBytes += persisted.sizeBytes;
1326
- if (attachmentTotalBytes > 52428800) return yield* new ProviderAdapterRequestError({
1456
+ const parsedModel = parseOpenCodeModelSlug(modelSelection?.model);
1457
+ if (!parsedModel) return yield* new ProviderAdapterValidationError({
1458
+ provider: PROVIDER$1,
1459
+ operation: "sendTurn",
1460
+ issue: "OpenCode model selection must use the 'provider/model' format."
1461
+ });
1462
+ const formatted = formatSourceControlContextsForAgent(input.sourceControlContexts ?? []);
1463
+ let text = formatted ? formatted + "\n\n" + (input.input?.trim() ?? "") : input.input?.trim();
1464
+ const attachmentUrlById = /* @__PURE__ */ new Map();
1465
+ const declaredAttachmentBytes = (input.attachments ?? []).reduce((total, attachment) => total + attachment.sizeBytes, 0);
1466
+ if (declaredAttachmentBytes > 52428800) return yield* new ProviderAdapterRequestError({
1327
1467
  provider: PROVIDER$1,
1328
1468
  method: "session.prompt",
1329
- detail: `Attachments total ${attachmentTotalBytes} bytes; limit is ${PROVIDER_SEND_TURN_MAX_ATTACHMENT_TOTAL_BYTES} bytes.`
1469
+ detail: `Attachments total ${declaredAttachmentBytes} bytes; limit is ${PROVIDER_SEND_TURN_MAX_ATTACHMENT_TOTAL_BYTES} bytes.`
1330
1470
  });
1331
- }
1332
- const fileParts = toOpenCodeFileParts({
1333
- attachments: input.attachments,
1334
- resolveAttachmentUrl: (attachment) => attachmentUrlById.get(attachment.id) ?? null
1335
- });
1336
- if ((!text || text.length === 0) && fileParts.length === 0) return yield* new ProviderAdapterValidationError({
1337
- provider: PROVIDER$1,
1338
- operation: "sendTurn",
1339
- issue: "OpenCode turns require text input or at least one attachment."
1340
- });
1341
- if (!context.agentControlHostContextDelivered) {
1342
- text = `<ryco_host_context>${agentControlHostContext(false)}</ryco_host_context>${text ? `\n\n${text}` : ""}`;
1343
- context.agentControlHostContextDelivered = true;
1344
- }
1345
- const agent = getModelSelectionStringOptionValue(modelSelection, "agent");
1346
- const variant = getModelSelectionStringOptionValue(modelSelection, "variant");
1347
- context.activeTurnId = turnId;
1348
- context.activeAgent = agent ?? (input.interactionMode === "plan" || input.interactionMode === "ask" ? "plan" : void 0);
1349
- context.activeVariant = variant;
1350
- updateProviderSession(context, {
1351
- status: "running",
1352
- activeTurnId: turnId,
1353
- model: modelSelection?.model ?? context.session.model
1354
- }, { clearLastError: true });
1355
- yield* emitForContext(context, {
1356
- ...yield* buildEventBase({
1357
- threadId: input.threadId,
1358
- turnId
1359
- }),
1360
- type: "turn.started",
1361
- payload: {
1362
- model: modelSelection?.model ?? context.session.model,
1363
- ...variant ? { effort: variant } : {}
1471
+ let attachmentTotalBytes = 0;
1472
+ for (const attachment of input.attachments ?? []) {
1473
+ const persisted = readPersistedAttachment({
1474
+ attachmentsDir: serverConfig.attachmentsDir,
1475
+ attachment
1476
+ });
1477
+ if (!persisted.ok) return yield* new ProviderAdapterRequestError({
1478
+ provider: PROVIDER$1,
1479
+ method: "session.prompt",
1480
+ detail: persisted.reason
1481
+ });
1482
+ attachmentUrlById.set(attachment.id, `data:${attachment.mimeType};base64,${persisted.bytes.toString("base64")}`);
1483
+ attachmentTotalBytes += persisted.sizeBytes;
1484
+ if (attachmentTotalBytes > 52428800) return yield* new ProviderAdapterRequestError({
1485
+ provider: PROVIDER$1,
1486
+ method: "session.prompt",
1487
+ detail: `Attachments total ${attachmentTotalBytes} bytes; limit is ${PROVIDER_SEND_TURN_MAX_ATTACHMENT_TOTAL_BYTES} bytes.`
1488
+ });
1364
1489
  }
1365
- });
1366
- yield* runOpenCodeSdk("session.promptAsync", () => context.client.session.promptAsync({
1367
- sessionID: context.openCodeSessionId,
1368
- model: parsedModel,
1369
- ...context.activeAgent ? { agent: context.activeAgent } : {},
1370
- ...context.activeVariant ? { variant: context.activeVariant } : {},
1371
- parts: [...text ? [{
1372
- type: "text",
1373
- text
1374
- }] : [], ...fileParts]
1375
- })).pipe(Effect.mapError(toRequestError), Effect.tapError((requestError) => Effect.gen(function* () {
1376
- context.activeTurnId = void 0;
1377
- context.activeAgent = void 0;
1378
- context.activeVariant = void 0;
1490
+ const fileParts = toOpenCodeFileParts({
1491
+ attachments: input.attachments,
1492
+ resolveAttachmentUrl: (attachment) => attachmentUrlById.get(attachment.id) ?? null
1493
+ });
1494
+ if ((!text || text.length === 0) && fileParts.length === 0) return yield* new ProviderAdapterValidationError({
1495
+ provider: PROVIDER$1,
1496
+ operation: "sendTurn",
1497
+ issue: "OpenCode turns require text input or at least one attachment."
1498
+ });
1499
+ if (!context.agentControlHostContextDelivered) {
1500
+ text = `<ryco_host_context>${agentControlHostContext(false)}</ryco_host_context>${text ? `\n\n${text}` : ""}`;
1501
+ context.agentControlHostContextDelivered = true;
1502
+ }
1503
+ const agent = getModelSelectionStringOptionValue(modelSelection, "agent");
1504
+ const variant = getModelSelectionStringOptionValue(modelSelection, "variant");
1505
+ context.activeTurnId = turnId;
1506
+ context.activeAgent = agent ?? (input.interactionMode === "plan" || input.interactionMode === "ask" ? "plan" : void 0);
1507
+ context.activeVariant = variant;
1379
1508
  updateProviderSession(context, {
1380
- status: "ready",
1381
- model: modelSelection?.model ?? context.session.model,
1382
- lastError: requestError.detail
1383
- }, { clearActiveTurnId: true });
1509
+ status: "running",
1510
+ activeTurnId: turnId,
1511
+ model: modelSelection?.model ?? context.session.model
1512
+ }, { clearLastError: true });
1384
1513
  yield* emitForContext(context, {
1385
1514
  ...yield* buildEventBase({
1386
1515
  threadId: input.threadId,
1387
1516
  turnId
1388
1517
  }),
1389
- type: "turn.aborted",
1390
- payload: { reason: requestError.detail }
1518
+ type: "turn.started",
1519
+ payload: {
1520
+ model: modelSelection?.model ?? context.session.model,
1521
+ ...variant ? { effort: variant } : {}
1522
+ }
1391
1523
  });
1392
- })));
1393
- return {
1394
- threadId: input.threadId,
1395
- turnId
1396
- };
1524
+ context.promptGeneration += 1;
1525
+ const generation = context.promptGeneration;
1526
+ const promptFiber = yield* runOpenCodeSdk("session.promptAsync", (signal) => context.client.session.promptAsync({
1527
+ sessionID: context.openCodeSessionId,
1528
+ model: parsedModel,
1529
+ ...context.activeAgent ? { agent: context.activeAgent } : {},
1530
+ ...context.activeVariant ? { variant: context.activeVariant } : {},
1531
+ parts: [...text ? [{
1532
+ type: "text",
1533
+ text
1534
+ }] : [], ...fileParts]
1535
+ }, { signal })).pipe(Effect.mapError(toRequestError), Effect.tapError((requestError) => context.activeTurnId === turnId && context.promptGeneration === generation ? Effect.gen(function* () {
1536
+ context.activeTurnId = void 0;
1537
+ context.activeAgent = void 0;
1538
+ context.activeVariant = void 0;
1539
+ updateProviderSession(context, {
1540
+ status: "ready",
1541
+ model: modelSelection?.model ?? context.session.model,
1542
+ lastError: requestError.detail
1543
+ }, { clearActiveTurnId: true });
1544
+ yield* emitForContext(context, {
1545
+ ...yield* buildEventBase({
1546
+ threadId: input.threadId,
1547
+ turnId
1548
+ }),
1549
+ type: "turn.aborted",
1550
+ payload: { reason: requestError.detail }
1551
+ });
1552
+ }) : Effect.void)).pipe(Effect.forkIn(context.sessionScope));
1553
+ const pendingPrompt = {
1554
+ turnId,
1555
+ fiber: promptFiber
1556
+ };
1557
+ context.pendingPrompt = pendingPrompt;
1558
+ yield* Fiber.join(promptFiber).pipe(Effect.ensuring(Effect.sync(() => {
1559
+ if (context.pendingPrompt?.fiber === promptFiber) context.pendingPrompt = void 0;
1560
+ })));
1561
+ const completedDuringAdmission = pendingPrompt.idleEvent !== void 0;
1562
+ if (completedDuringAdmission && context.activeTurnId === turnId) {
1563
+ context.activeTurnId = void 0;
1564
+ context.activeAgent = void 0;
1565
+ context.activeVariant = void 0;
1566
+ updateProviderSession(context, { status: "ready" }, { clearActiveTurnId: true });
1567
+ yield* emitForContext(context, {
1568
+ ...yield* buildEventBase({
1569
+ threadId: context.session.threadId,
1570
+ turnId,
1571
+ raw: pendingPrompt.idleEvent
1572
+ }),
1573
+ type: "turn.completed",
1574
+ payload: { state: "completed" }
1575
+ });
1576
+ }
1577
+ if (sessions.get(input.threadId) !== context || (yield* Ref.get(context.stopped)) || !completedDuringAdmission && context.activeTurnId !== turnId || context.promptGeneration !== generation) return yield* Effect.interrupt;
1578
+ return {
1579
+ threadId: input.threadId,
1580
+ turnId,
1581
+ resumeCursor: context.session.resumeCursor
1582
+ };
1583
+ }));
1397
1584
  });
1398
1585
  const interruptTurn = Effect.fn("interruptTurn")(function* (threadId, turnId) {
1399
1586
  const context = ensureSessionContext(sessions, threadId);
1400
- const rootAbortExit = yield* runOpenCodeSdk("session.abort", () => context.client.session.abort({ sessionID: context.openCodeSessionId })).pipe(Effect.mapError(toRequestError), Effect.exit);
1401
- yield* Effect.forEach(context.childSessionIds, (sessionID) => runOpenCodeSdk("session.abort", () => context.client.session.abort({ sessionID })).pipe(Effect.ignore({ log: true })), { discard: true });
1587
+ const interruptedTurnId = turnId ?? context.activeTurnId;
1588
+ if (turnId !== void 0 && context.activeTurnId !== void 0 && turnId !== context.activeTurnId) return;
1589
+ const pendingPrompt = context.pendingPrompt;
1590
+ if (pendingPrompt && pendingPrompt.turnId === interruptedTurnId) {
1591
+ context.pendingPrompt = void 0;
1592
+ yield* Fiber.interrupt(pendingPrompt.fiber).pipe(Effect.ignore);
1593
+ }
1594
+ const rootAbortExit = yield* abortOpenCodeSession(context, context.openCodeSessionId).pipe(Effect.mapError(toRequestError), Effect.exit);
1595
+ yield* Effect.forEach(context.childSessionIds, (sessionID) => abortOpenCodeSession(context, sessionID).pipe(Effect.ignore({ log: true })), { discard: true });
1402
1596
  yield* emitStoppedOpenCodeChildren(context, {
1403
1597
  method: "session.abort",
1404
1598
  reason: "turn-interrupted"
1405
1599
  });
1406
1600
  if (Exit.isFailure(rootAbortExit)) return yield* Effect.failCause(rootAbortExit.cause);
1407
- if (turnId ?? context.activeTurnId) yield* emitForContext(context, {
1408
- ...yield* buildEventBase({
1409
- threadId,
1410
- turnId: turnId ?? context.activeTurnId
1411
- }),
1412
- type: "turn.aborted",
1413
- payload: { reason: "Interrupted by user." }
1414
- });
1601
+ if (interruptedTurnId) {
1602
+ if (context.activeTurnId === interruptedTurnId) {
1603
+ context.activeTurnId = void 0;
1604
+ context.activeAgent = void 0;
1605
+ context.activeVariant = void 0;
1606
+ updateProviderSession(context, { status: "ready" }, {
1607
+ clearActiveTurnId: true,
1608
+ clearLastError: true
1609
+ });
1610
+ }
1611
+ yield* emitForContext(context, {
1612
+ ...yield* buildEventBase({
1613
+ threadId,
1614
+ turnId: interruptedTurnId
1615
+ }),
1616
+ type: "turn.aborted",
1617
+ payload: { reason: "Interrupted by user." }
1618
+ });
1619
+ }
1415
1620
  });
1416
1621
  const respondToRequest = Effect.fn("respondToRequest")(function* (threadId, requestId, decision) {
1417
1622
  const context = ensureSessionContext(sessions, threadId);
@@ -1520,7 +1725,6 @@ const OPENCODE_PRESENTATION = {
1520
1725
  displayName: "OpenCode",
1521
1726
  showInteractionModeToggle: false
1522
1727
  };
1523
- const MINIMUM_OPENCODE_VERSION = "1.14.19";
1524
1728
  var OpenCodeProbeError = class extends Data.TaggedError("OpenCodeProbeError") {};
1525
1729
  function normalizeProbeMessage(message) {
1526
1730
  const trimmed = message.trim();
@@ -1736,7 +1940,7 @@ const checkOpenCodeProviderStatus = Effect.fn("checkOpenCodeProviderStatus")(fun
1736
1940
  if (versionExit._tag === "Failure") return fallback(Cause.squash(versionExit.cause));
1737
1941
  version = parseGenericCliVersion(versionExit.value.stdout) ?? null;
1738
1942
  if (!version) return fallback(/* @__PURE__ */ new Error(`Unable to determine OpenCode version from \`opencode --version\` output. Ryco requires OpenCode v${MINIMUM_OPENCODE_VERSION} or newer.`), null);
1739
- if (compareCliVersions(version, MINIMUM_OPENCODE_VERSION) < 0) return buildServerProvider({
1943
+ if (compareCliVersions(version, "1.14.19") < 0) return buildServerProvider({
1740
1944
  presentation: OPENCODE_PRESENTATION,
1741
1945
  enabled: openCodeSettings.enabled,
1742
1946
  checkedAt,
@@ -1754,6 +1958,7 @@ const checkOpenCodeProviderStatus = Effect.fn("checkOpenCodeProviderStatus")(fun
1754
1958
  const server = yield* openCodeRuntime.connectToOpenCodeServer({
1755
1959
  binaryPath: openCodeSettings.binaryPath,
1756
1960
  serverUrl: openCodeSettings.serverUrl,
1961
+ ...openCodeSettings.serverPassword ? { serverPassword: openCodeSettings.serverPassword } : {},
1757
1962
  environment
1758
1963
  }).pipe(Effect.mapError((cause) => new OpenCodeProbeError({
1759
1964
  cause,
@@ -1762,19 +1967,27 @@ const checkOpenCodeProviderStatus = Effect.fn("checkOpenCodeProviderStatus")(fun
1762
1967
  const client = yield* openCodeRuntime.createOpenCodeSdkClient({
1763
1968
  baseUrl: server.url,
1764
1969
  directory: cwd,
1765
- ...isExternalServer && openCodeSettings.serverPassword ? { serverPassword: openCodeSettings.serverPassword } : {}
1970
+ ...server.serverPassword ? { serverPassword: server.serverPassword } : {}
1766
1971
  }).pipe(Effect.mapError((cause) => new OpenCodeProbeError({
1767
1972
  cause,
1768
1973
  detail: openCodeRuntimeErrorDetail(cause)
1769
1974
  })));
1770
- return yield* openCodeRuntime.loadOpenCodeInventory(client).pipe(Effect.mapError((cause) => new OpenCodeProbeError({
1975
+ const serverVersion = yield* verifyOpenCodeServerVersion(client).pipe(Effect.mapError((cause) => new OpenCodeProbeError({
1771
1976
  cause,
1772
1977
  detail: openCodeRuntimeErrorDetail(cause)
1773
1978
  })));
1979
+ return {
1980
+ inventory: yield* openCodeRuntime.loadOpenCodeInventory(client).pipe(Effect.mapError((cause) => new OpenCodeProbeError({
1981
+ cause,
1982
+ detail: openCodeRuntimeErrorDetail(cause)
1983
+ }))),
1984
+ serverVersion
1985
+ };
1774
1986
  })));
1775
1987
  if (inventoryExit._tag === "Failure") return fallback(Cause.squash(inventoryExit.cause), version);
1776
- const models = providerModelsFromSettings(flattenOpenCodeModels(inventoryExit.value), PROVIDER, customModels, DEFAULT_OPENCODE_MODEL_CAPABILITIES);
1777
- const connectedCount = new Set(inventoryExit.value.providerList.connected).size;
1988
+ version = inventoryExit.value.serverVersion;
1989
+ const models = providerModelsFromSettings(flattenOpenCodeModels(inventoryExit.value.inventory), PROVIDER, customModels, DEFAULT_OPENCODE_MODEL_CAPABILITIES);
1990
+ const connectedCount = new Set(inventoryExit.value.inventory.providerList.connected).size;
1778
1991
  return buildServerProvider({
1779
1992
  presentation: OPENCODE_PRESENTATION,
1780
1993
  enabled: true,
@@ -1803,8 +2016,7 @@ const checkOpenCodeProviderStatus = Effect.fn("checkOpenCodeProviderStatus")(fun
1803
2016
  *
1804
2017
  * Two instances with different `serverUrl`s therefore talk to independent
1805
2018
  * OpenCode servers; when no `serverUrl` is set, the adapter + text-generation
1806
- * shares spin up their own scoped child processes, and those child
1807
- * processes are released when the registry scope closes.
2019
+ * shares reuse one scoped child process owned by the provider instance.
1808
2020
  *
1809
2021
  * @module provider/Drivers/OpenCodeDriver
1810
2022
  */
@@ -1865,12 +2077,14 @@ const OpenCodeDriver = {
1865
2077
  binaryPath: effectiveConfig.binaryPath,
1866
2078
  env: processEnv
1867
2079
  });
2080
+ const serverOwner = effectiveConfig.serverUrl.trim().length === 0 ? yield* makeOpenCodeServerOwner(effectiveConfig, processEnv) : void 0;
1868
2081
  const adapter = yield* makeOpenCodeAdapter(effectiveConfig, {
1869
2082
  instanceId,
1870
2083
  environment: processEnv,
2084
+ ...serverOwner ? { serverOwner } : {},
1871
2085
  ...eventLoggers.native ? { nativeEventLogger: eventLoggers.native } : {}
1872
2086
  });
1873
- const textGeneration = yield* makeOpenCodeTextGeneration(effectiveConfig, processEnv);
2087
+ const textGeneration = yield* makeOpenCodeTextGeneration(effectiveConfig, processEnv, serverOwner ? { serverOwner } : void 0);
1874
2088
  const checkProvider = checkOpenCodeProviderStatus(effectiveConfig, serverConfig.cwd, processEnv).pipe(Effect.map(stampIdentity), Effect.provideService(OpenCodeRuntime, openCodeRuntime));
1875
2089
  const snapshot = yield* makeManagedServerProvider({
1876
2090
  maintenanceCapabilities,
@@ -1880,6 +2094,7 @@ const OpenCodeDriver = {
1880
2094
  initialSnapshot: (settings) => stampIdentity(makePendingOpenCodeProvider(settings)),
1881
2095
  checkProvider,
1882
2096
  enrichSnapshot: ({ snapshot, publishSnapshot }) => enrichProviderSnapshotWithVersionAdvisory(snapshot, maintenanceCapabilities).pipe(Effect.provideService(HttpClient.HttpClient, httpClient), Effect.provideService(ServerSettingsService, serverSettings), Effect.flatMap((enrichedSnapshot) => publishSnapshot(enrichedSnapshot))),
2097
+ retainInventoryOnError: true,
1883
2098
  refreshInterval: null
1884
2099
  }).pipe(Effect.mapError((cause) => new ProviderDriverError({
1885
2100
  driver: DRIVER_KIND,