ryco-cli 0.1.29 → 0.1.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -0
- package/dist/{AcpAdapter-8CSe4HK7.cjs → AcpAdapter-ByUp9-wk.cjs} +74 -54
- package/dist/{AcpAdapter-CG1wRWcf.mjs → AcpAdapter-CY_ANTKu.mjs} +74 -54
- package/dist/{AcpNativeLogging-B6TtnnKL.mjs → AcpNativeLogging-C7PC6imv.mjs} +30 -4
- package/dist/{AcpNativeLogging-DbjnRnTf.cjs → AcpNativeLogging-OQeAya9d.cjs} +33 -1
- package/dist/{AcpRegistryDriver-16ZTxUs3.cjs → AcpRegistryDriver-CD9GN7rI.cjs} +3 -3
- package/dist/{AcpRegistryDriver-DZFasKaz.mjs → AcpRegistryDriver-DMZ5VBWJ.mjs} +4 -4
- package/dist/AzureDevOpsSourceControlProvider-5giVYoNi.mjs +2053 -0
- package/dist/AzureDevOpsSourceControlProvider-BKMXEUaN.cjs +2055 -0
- package/dist/{BitbucketSourceControlProvider-DplKc8Wo.mjs → BitbucketSourceControlProvider-BVUBsEUF.mjs} +63 -23
- package/dist/{BitbucketSourceControlProvider-B-ZwKj72.cjs → BitbucketSourceControlProvider-BWnnrbch.cjs} +62 -22
- package/dist/{BunPTY-Dcl1Lp62.mjs → BunPTY-CMbDQ1Xb.mjs} +1 -1
- package/dist/{ClaudeDriver-r0lJ9vmE.cjs → ClaudeDriver-DCrqouOR.cjs} +1376 -194
- package/dist/{ClaudeDriver-0gGVop27.mjs → ClaudeDriver-DVOss8cC.mjs} +1377 -195
- package/dist/{CodexDriver-bJAbhSwY.cjs → CodexDriver-CBQPHJqU.cjs} +259 -29
- package/dist/{CodexDriver-baT02xVb.mjs → CodexDriver-DJoTky7Z.mjs} +261 -31
- package/dist/{CodexTextGeneration-Dwp6X3dq.mjs → CodexTextGeneration-BSgNgfZv.mjs} +6 -6
- package/dist/{CodexTextGeneration-DFZ5y4gj.cjs → CodexTextGeneration-C9MDQmZm.cjs} +7 -7
- package/dist/{CopilotDriver-C0OhnSB1.mjs → CopilotDriver-CUkdPXcH.mjs} +78 -20
- package/dist/{CopilotDriver-B_jEqfYQ.cjs → CopilotDriver-DbaMDH16.cjs} +76 -18
- package/dist/{CursorDriver-DinXkGP9.mjs → CursorDriver-B-ZilXJB.mjs} +115 -98
- package/dist/{CursorDriver-BBFEW7ZI.cjs → CursorDriver-DKQqPbKH.cjs} +116 -99
- package/dist/{ForgejoSourceControlProvider-iG9o7aZB.cjs → ForgejoSourceControlProvider-CgpjFECj.cjs} +94 -60
- package/dist/{ForgejoSourceControlProvider-Dr0fxfud.mjs → ForgejoSourceControlProvider-DemMYUye.mjs} +95 -61
- package/dist/{GitHubSourceControlProvider-L1yFpep4.cjs → GitHubSourceControlProvider-C4un6hOK.cjs} +218 -119
- package/dist/{GitHubSourceControlProvider-CnIu0n2Y.mjs → GitHubSourceControlProvider-CRSDYcjc.mjs} +206 -108
- package/dist/GitLabSourceControlProvider-D8W1ZLPh.cjs +2260 -0
- package/dist/GitLabSourceControlProvider-DpWkJ0M3.mjs +2258 -0
- package/dist/{GrokDriver-D_Ylzh5z.cjs → GrokDriver-BQ6G_7ZZ.cjs} +11 -12
- package/dist/{GrokDriver-pX-N6HGS.mjs → GrokDriver-Buvas9-q.mjs} +7 -8
- package/dist/{Metrics-BjqGlIP4.mjs → Metrics-C3vLS9rz.mjs} +1264 -1151
- package/dist/{Metrics-Bf96NJ4j.cjs → Metrics-DjRPLE98.cjs} +1295 -1134
- package/dist/{NodePTY-D7tFWuQe.mjs → NodePTY-DgnuBruq.mjs} +1 -1
- package/dist/{NodeSqliteClient-BGg70C7Q.cjs → NodeSqliteClient-D8bzGgPN.cjs} +1 -1
- package/dist/{OpenCodeDriver-Byu1pf_i.mjs → OpenCodeDriver-BWEZD841.mjs} +184 -50
- package/dist/{OpenCodeDriver-BFEw5t09.cjs → OpenCodeDriver-qUiX0RLH.cjs} +185 -51
- package/dist/{SideQuestionIsolation-81IoAuoi.mjs → SideQuestionIsolation-B1T-DsR0.mjs} +1 -1
- package/dist/{SideQuestionIsolation-CMPkCUP0.cjs → SideQuestionIsolation-BPC-Bxsz.cjs} +1 -1
- package/dist/bin.cjs +50689 -15659
- package/dist/bin.mjs +50578 -15585
- package/dist/client/assets/AccountSettings-B88Q_w9Y.js +1 -0
- package/dist/client/assets/AiFocusSettings-Bb0TrCPn.js +1 -0
- package/dist/client/assets/{AnimatedHeight-BNg7wnTK.js → AnimatedHeight-epXOsgdm.js} +1 -1
- package/dist/client/assets/AppearanceSettings-XS9WRVPU.js +1 -0
- package/dist/client/assets/AutomationsDialog-bZckh4Y3.js +1 -0
- package/dist/client/assets/AutomationsSummary-wPFZCF49.js +1 -0
- package/dist/client/assets/BranchToolbar.logic-DjzLKbbB.js +3 -0
- package/dist/client/assets/BrowserPanel-CdBLnnfz.js +1 -0
- package/dist/client/assets/ChatRightPanel-BCINd0vP.js +34 -0
- package/dist/client/assets/ChatThreadRouteView-BFZ0Si-l.js +1 -0
- package/dist/client/assets/ColorSwatchPicker-CGyo99o0.js +1 -0
- package/dist/client/assets/CommandPalette.logic-BIOMtnEQ.js +1 -0
- package/dist/client/assets/CommandPaletteDialog-Db4LH--z.js +2 -0
- package/dist/client/assets/CompositeRoot-DtnwMJKj.js +1 -0
- package/dist/client/assets/ComputerUseSettings-CkqCqDsU.js +1 -0
- package/dist/client/assets/ConnectionsSettings-B9mxExdG.js +7 -0
- package/dist/client/assets/CreatePullRequestDialog-CJ7pNCue.js +1 -0
- package/dist/client/assets/CreatePullRequestDialogHost-n4ZjdSr4.js +1 -0
- package/dist/client/assets/DiagnosticsSettings-f9rFG9re.js +2 -0
- package/dist/client/assets/DiagnosticsSettings.logic-Byf-Bu4S.js +1 -0
- package/dist/client/assets/DialogHandle-C0c_rK3I.js +1 -0
- package/dist/client/assets/{DialogPopup-DdZlhHuQ.js → DialogPopup-BKW1PEEa.js} +1 -1
- package/dist/client/assets/DialogRoot-BIubqrv0.js +1 -0
- package/dist/client/assets/DialogTitle-BAX_FLoG.js +1 -0
- package/dist/client/assets/{DialogViewport-BwuqbGLY.js → DialogViewport-C2iOUx0O.js} +1 -1
- package/dist/client/assets/DiffPanel-BkqDt_SS.js +25 -0
- package/dist/client/assets/DisclosureRegion-B8556yU0.js +1 -0
- package/dist/client/assets/DraftChatThreadRouteView-BKgRKJ2w.js +1 -0
- package/dist/client/assets/{ExternalIdentityWeb.logic-DsTJQkg-.js → ExternalIdentityWeb.logic-Cu6suNrN.js} +1 -1
- package/dist/client/assets/GlassSurface-DLYYzRdP.js +1 -0
- package/dist/client/assets/HostedConnectionControls-CoVqtnrK.js +1 -0
- package/dist/client/assets/HostedHubRoot-CM2CwPUr.js +2 -0
- package/dist/client/assets/{HostedNativeAuthorizationRoute-BSq_AlY2.js → HostedNativeAuthorizationRoute-Bizmqrh_.js} +2 -2
- package/dist/client/assets/HostedNodeRenameDialog-SXWMsTO0.js +1 -0
- package/dist/client/assets/HostedRelayTrustNotice-BfTyrBi5.js +1 -0
- package/dist/client/assets/InboxStatusGlyph-BPTqzp7l.js +1 -0
- package/dist/client/assets/IntegrationsSettingsPanel-DAPvkV4i.js +1 -0
- package/dist/client/assets/KeybindingsSettings-B8g-YI2O.js +1 -0
- package/dist/client/assets/LazyBrowserPanel-Ds9cdOC_.js +2 -0
- package/dist/client/assets/McpServersSettings-Dw6G3ff3.js +6 -0
- package/dist/client/assets/MobileSheet-DfgXNWbd.js +1 -0
- package/dist/client/assets/ModelTuningDial-DQBAbuNL.js +1 -0
- package/dist/client/assets/NewWorktreeDialog-CDZAJmK6.js +4 -0
- package/dist/client/assets/NodeSecuritySettings-3MELA9ru.js +1 -0
- package/dist/client/assets/NullStore-gT_6_xZE.js +1 -0
- package/dist/client/assets/OnboardingDialog-CAAtNnJf.js +1 -0
- package/dist/client/assets/OpinionatedPluginsSettings-AiDB0Vl4.js +1 -0
- package/dist/client/assets/{PdfAttachmentPreview-CTo1AyZs.js → PdfAttachmentPreview-BFNW2wjN.js} +2 -2
- package/dist/client/assets/{PhoneGetAppInterstitial-DwopOWnQ.js → PhoneGetAppInterstitial-D8fwZ8E9.js} +1 -1
- package/dist/client/assets/PhoneHome-YHgHljA0.js +1 -0
- package/dist/client/assets/PhoneSettingsSurface-BVxJppvK.js +2 -0
- package/dist/client/assets/PreviewPanel-BYcEnkv9.js +643 -0
- package/dist/client/assets/ProjectScriptDialog-K34K2Kzm.js +1 -0
- package/dist/client/assets/ProjectsPage-DXnMYLjb.js +1 -0
- package/dist/client/assets/PromoteChatDialog-CAY7_wJ-.js +1 -0
- package/dist/client/assets/ProviderLimitWindow-CK04BSkM.js +1 -0
- package/dist/client/assets/ProviderUpdateLaunchNotification.logic-BMBrDDOC.js +1 -0
- package/dist/client/assets/ProvidersSettingsPanel-C85PX9Es.js +1 -0
- package/dist/client/assets/PullRequestsPage-C0rgfGwB.js +1 -0
- package/dist/client/assets/{QuitShortcutFeedback-eCvP_MNj.js → QuitShortcutFeedback-DSkKqETs.js} +1 -1
- package/dist/client/assets/RedactedSensitiveText-DQ0YveQd.js +1 -0
- package/dist/client/assets/RollingText-BzvpP5fa.js +1 -0
- package/dist/client/assets/RootAppShell-BYQ-eGNT.js +6 -0
- package/dist/client/assets/{Separator-BiINUUQl.js → Separator-DpiW19Vw.js} +1 -1
- package/dist/client/assets/SettingsPage-BCFN7Ju2.js +2 -0
- package/dist/client/assets/SettingsPanels-CP6z2b1x.js +3 -0
- package/dist/client/assets/SettingsPanels.editor-D8U-TWWG.js +1 -0
- package/dist/client/assets/SettingsSelect-DEhNaz3E.js +1 -0
- package/dist/client/assets/Sidebar.logic-D_ODfSpl.js +1 -0
- package/dist/client/assets/SimulatorPanel-DCT6fZ0X.js +1 -0
- package/dist/client/assets/SourceControlSettings-DxUtvPMK.js +1 -0
- package/dist/client/assets/StatisticsPage-C9SrwtM4.js +1 -0
- package/dist/client/assets/StatisticsPanel-BMYLETs0.js +1 -0
- package/dist/client/assets/ThreadLinkList-BN5z5EpS.js +169 -0
- package/dist/client/assets/ThreadTerminalDrawer-CgIFOlR-.js +18 -0
- package/dist/client/assets/ThreadWorkspacePanel-DvXoqQPF.js +3 -0
- package/dist/client/assets/ToolbarRootContext-8FsV9Cpj.js +1 -0
- package/dist/client/assets/TraitsPicker-DcrpJahy.js +1 -0
- package/dist/client/assets/Virtualizer-CwXeUPla.js +1345 -0
- package/dist/client/assets/WorkspacePullRequestPanel-3mlcJn9G.js +1 -0
- package/dist/client/assets/WorkspaceReview-UGbCgXeK.js +2 -0
- package/dist/client/assets/{abnfDiagram-N423BO3Z-DAmGykdr.js → abnfDiagram-N423BO3Z-DVEM6Scc.js} +1 -1
- package/dist/client/assets/{activity-DRZlu-MC.js → activity-DVCuAejY.js} +1 -1
- package/dist/client/assets/{alert-CwrDisFU.js → alert-FV7ZIit_.js} +1 -1
- package/dist/client/assets/alert-dialog-CgXR9tED.js +1 -0
- package/dist/client/assets/app-window-3xtwqZgI.js +1 -0
- package/dist/client/assets/appChrome-COCz-T7w.js +1 -0
- package/dist/client/assets/{appearancePreferences-nFx4MHoI.js → appearancePreferences-NnsvXwBe.js} +1 -1
- package/dist/client/assets/architecture-7GRP2DOG-DXXb_0_g.js +1 -0
- package/dist/client/assets/{architectureDiagram-T3A2C74G-DypU2ERW.js → architectureDiagram-T3A2C74G-B6pcKiCj.js} +1 -1
- package/dist/client/assets/{arrow-left-XhcJWpRy.js → arrow-left-Blu3LSE2.js} +1 -1
- package/dist/client/assets/{arrow-right-BBs6iTUL.js → arrow-right-CO3CH0ne.js} +1 -1
- package/dist/client/assets/arrow-up-B69gV2Bq.js +1 -0
- package/dist/client/assets/{arrow-up-right-CJ9Vq7nK.js → arrow-up-right-BbPGFOLA.js} +1 -1
- package/dist/client/assets/authorization-Ob6YwWiI.js +1 -0
- package/dist/client/assets/autocomplete-RVpjsrDv.js +1 -0
- package/dist/client/assets/ban-BIm2PVkE.js +1 -0
- package/dist/client/assets/{blockDiagram-VBNYF7ZC-B9MhR9hY.js → blockDiagram-VBNYF7ZC-WNerGp9V.js} +1 -1
- package/dist/client/assets/{bot-D5wgL7pu.js → bot-C9nWtaWq.js} +1 -1
- package/dist/client/assets/browserState-jt47YsqD.js +1 -0
- package/dist/client/assets/{c4Diagram-5PPSVZJV-C22FWSoE.js → c4Diagram-5PPSVZJV-wp1ioOoM.js} +1 -1
- package/dist/client/assets/camera-C13VoW3c.js +1 -0
- package/dist/client/assets/capabilities-CfOhq009.js +1 -0
- package/dist/client/assets/channel-56r2qL2v.js +1 -0
- package/dist/client/assets/{chart-column-D6Lnkklk.js → chart-column-DRv0YtL_.js} +1 -1
- package/dist/client/assets/checkbox-CIIIY9FA.js +1 -0
- package/dist/client/assets/checks-Dw022Bvy.js +1 -0
- package/dist/client/assets/{chunk-2GRJ4B5K-D1tZuCzA.js → chunk-2GRJ4B5K-DRl3ILpc.js} +1 -1
- package/dist/client/assets/{chunk-4I5QYGJK-Clf86zK0.js → chunk-4I5QYGJK-CYTRl4bo.js} +1 -1
- package/dist/client/assets/{chunk-5RXB4S5H-B36N5RYZ.js → chunk-5RXB4S5H-VCNwRsOa.js} +1 -1
- package/dist/client/assets/{chunk-6Q2QTUOP-IAxdzsQJ.js → chunk-6Q2QTUOP-DnSeKGPG.js} +1 -1
- package/dist/client/assets/{chunk-7Z6QIM7H-Ctqebv_4.js → chunk-7Z6QIM7H-Cjilh9TF.js} +1 -1
- package/dist/client/assets/{chunk-GF5L2VYU-CAfciJae.js → chunk-GF5L2VYU-CGR7AW0t.js} +1 -1
- package/dist/client/assets/{chunk-I66GZJ75-BZ7XtZf4.js → chunk-I66GZJ75-CXSn8dDu.js} +1 -1
- package/dist/client/assets/{chunk-JQJVKLGR-DVuZCWnv.js → chunk-JQJVKLGR-Dro-75lU.js} +1 -1
- package/dist/client/assets/{chunk-KBJHAD2P-DtWbzsRm.js → chunk-KBJHAD2P-BDqN2kVf.js} +1 -1
- package/dist/client/assets/{chunk-NSK5VX7P-BVMz_Hc4.js → chunk-NSK5VX7P-DGo5UczH.js} +1 -1
- package/dist/client/assets/{chunk-QR6OTTB3-DWitTCy-.js → chunk-QR6OTTB3-RWuyWnBI.js} +1 -1
- package/dist/client/assets/{chunk-UBXNYLIW-BuxXXP2s.js → chunk-UBXNYLIW-BPRzeB0w.js} +1 -1
- package/dist/client/assets/{chunk-W5SLKNZC-Bnf3sQl4.js → chunk-W5SLKNZC-DYWocTFi.js} +1 -1
- package/dist/client/assets/{chunk-WRU74C26-xu-KDOon.js → chunk-WRU74C26-ChbB1jY3.js} +1 -1
- package/dist/client/assets/circle-stop-D8B4hRpY.js +1 -0
- package/dist/client/assets/circle-x-CNLfrTqR.js +1 -0
- package/dist/client/assets/classDiagram-JCYQIIEL-DGvmFev3.js +1 -0
- package/dist/client/assets/classDiagram-v2-OCEON4UE-DGvmFev3.js +1 -0
- package/dist/client/assets/{clipboard-copy-oDSkUUg4.js → clipboard-copy-DGi8FKNO.js} +1 -1
- package/dist/client/assets/clock-3-DmJ4_XPI.js +1 -0
- package/dist/client/assets/clock-DZIuPtNG.js +1 -0
- package/dist/client/assets/color-picker-BdBXje-a.js +1 -0
- package/dist/client/assets/columns-2-CWlMOClK.js +1 -0
- package/dist/client/assets/combobox-Dtjtf7AB.js +1 -0
- package/dist/client/assets/{cynefin-OW5HDTMX-DGNyiNSf.js → cynefin-OW5HDTMX-TuShvMuM.js} +1 -1
- package/dist/client/assets/{cynefinDiagram-MW4NZA55-_ctibv4i.js → cynefinDiagram-MW4NZA55-B0Edt2Em.js} +1 -1
- package/dist/client/assets/{dagre-VZM6K2ZE-Bo-bS1Y0.js → dagre-VZM6K2ZE-D-eiuqHx.js} +1 -1
- package/dist/client/assets/{data-list-DLsM39Hp.js → data-list-BAx6jBY1.js} +1 -1
- package/dist/client/assets/desktopUpdateAtoms-BjrLa3tl.js +1 -0
- package/dist/client/assets/desktopWorkspace-C2wXVBhc.js +1 -0
- package/dist/client/assets/{deviceName-z0ZWSq0z.js → deviceName-B4youG0v.js} +1 -1
- package/dist/client/assets/{diagram-7IWD3JNH-DSjtw1SY.js → diagram-7IWD3JNH-DgM6lMlR.js} +1 -1
- package/dist/client/assets/{diagram-B4RE2ZJO-B7fWEvIa.js → diagram-B4RE2ZJO-CyHNDjzV.js} +1 -1
- package/dist/client/assets/{diagram-LBJQPF4R-trRYCE5d.js → diagram-LBJQPF4R-DDzuLIN5.js} +1 -1
- package/dist/client/assets/{diagram-Q27KOJAE-_DYcRggk.js → diagram-Q27KOJAE-BaBvK9QB.js} +1 -1
- package/dist/client/assets/{diagram-UB23O5K3-BkMzOHX8.js → diagram-UB23O5K3-CzZ2ewuZ.js} +1 -1
- package/dist/client/assets/dialogWords-Cg0YkJVg.js +1 -0
- package/dist/client/assets/diffRouteSearch-D2MKN_ah.js +1 -0
- package/dist/client/assets/disclosureMotion-cbMJn5-z.js +1 -0
- package/dist/client/assets/{download-CHdS3R_v.js → download-TvtXS4hE.js} +1 -1
- package/dist/client/assets/{ebnfDiagram-BXEA7PRR-DubiOMCG.js → ebnfDiagram-BXEA7PRR-CL1vdOKi.js} +1 -1
- package/dist/client/assets/editorPreferences-DqKyA-2Z.js +1 -0
- package/dist/client/assets/ellipsis-CDK1dNFZ.js +1 -0
- package/dist/client/assets/ellipsis-vertical-CwzEUTwV.js +1 -0
- package/dist/client/assets/{empty-BlBl_Vvw.js → empty-BovKoxbn.js} +1 -1
- package/dist/client/assets/{erDiagram-JOGREHBK-CFDiNfSJ.js → erDiagram-JOGREHBK-DmQR2if6.js} +1 -1
- package/dist/client/assets/eventmodeling-NTZA5JFV-D272GIcY.js +1 -0
- package/dist/client/assets/external-link-CJeVJZ7s.js +1 -0
- package/dist/client/assets/eye-BUmrXqzg.js +1 -0
- package/dist/client/assets/file-diff-BWc3mYsz.js +1 -0
- package/dist/client/assets/flowDiagram-UKHOOZJN-DLyS38Mm.js +1 -0
- package/dist/client/assets/folder-git-2-CPxg5wKP.js +1 -0
- package/dist/client/assets/folder-open-DcMymvp1.js +1 -0
- package/dist/client/assets/formatCount-B4KLI651.js +1 -0
- package/dist/client/assets/{ganttDiagram-PKOTCBZU-DT2XhE-m.js → ganttDiagram-PKOTCBZU-1q2nUL92.js} +1 -1
- package/dist/client/assets/git-pull-request-BFPwpm3c.js +1 -0
- package/dist/client/assets/{gitGraph-4MIJSDKK-BI5UGiqb.js → gitGraph-4MIJSDKK-COtwmv2S.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-DS77QQ5N-CzAB97Rd.js → gitGraphDiagram-DS77QQ5N-ChsvaxX4.js} +1 -1
- package/dist/client/assets/{group-DZJuSiJL.js → group-DWWn0dTx.js} +1 -1
- package/dist/client/assets/hammer-BXo-EU88.js +1 -0
- package/dist/client/assets/hostedConnectionCoordinator-BkAE-RhA.js +1 -0
- package/dist/client/assets/hostedPairing-5n5srRC9.js +1 -0
- package/dist/client/assets/{index-BAJdq3TK.js → index-DARIYokI.js} +2 -2
- package/dist/client/assets/{info-A6RAGUB7-DdGYYgLX.js → info-A6RAGUB7-CI2qZ9wW.js} +1 -1
- package/dist/client/assets/{infoDiagram-6WML65LV-zhUpER6a.js → infoDiagram-6WML65LV-BPmgcTPH.js} +1 -1
- package/dist/client/assets/{input-CzU08wbL.js → input-CCie4mm1.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-WSZJBQD7-BQLkqykE.js → ishikawaDiagram-WSZJBQD7-LyS9p3Yg.js} +1 -1
- package/dist/client/assets/{journeyDiagram-NVQOT4AX-DBgsbKOF.js → journeyDiagram-NVQOT4AX-BYaAmN65.js} +1 -1
- package/dist/client/assets/{kanban-definition-27J2QSJJ-DF-Rr-xs.js → kanban-definition-27J2QSJJ-D-pwzqFt.js} +1 -1
- package/dist/client/assets/{key-round-CvyrSjb2.js → key-round-BlrUTfxB.js} +1 -1
- package/dist/client/assets/keyboard-DlBdq6sz.js +1 -0
- package/dist/client/assets/label-ChtVI9lp.js +1 -0
- package/dist/client/assets/layers-BB-ruGvd.js +1 -0
- package/dist/client/assets/lifecycleSuggestionPolicy-0ERe_O53.js +1 -0
- package/dist/client/assets/list-checks-BkM_ZRsj.js +1 -0
- package/dist/client/assets/loader-3vQnfqIT.js +1 -0
- package/dist/client/assets/{log-out-D3rICSt5.js → log-out-CKq9YiLY.js} +1 -1
- package/dist/client/assets/{logging-C6tXZlGQ.js → logging-CCg76rgn.js} +1 -1
- package/dist/client/assets/main-Ch0bwS-M.js +9 -0
- package/dist/client/assets/main-Di0isH9D.css +2 -0
- package/dist/client/assets/{mermaid-parser.core-BiGKtilP.js → mermaid-parser.core-RK9ah5RM.js} +2 -2
- package/dist/client/assets/{mermaidEngine-Cjfgf3Bg.js → mermaidEngine-Dr8UsPhH.js} +3 -3
- package/dist/client/assets/message-circle-dashed-BrjwqS7-.js +1 -0
- package/dist/client/assets/messageQueueDrain-B7R7Qmq6.js +1 -0
- package/dist/client/assets/messages-square-cDTkDJv_.js +1 -0
- package/dist/client/assets/{mindmap-definition-FAOFIHXS-SiU9JwWJ.js → mindmap-definition-FAOFIHXS-DVudWasx.js} +1 -1
- package/dist/client/assets/{packet-AYTQ26CC-F-HuW5Dr.js → packet-AYTQ26CC-DnkTsVhD.js} +1 -1
- package/dist/client/assets/{pairingUrl-rQM9kSGT.js → pairingUrl-Dn1e2CVw.js} +1 -1
- package/dist/client/assets/panels-top-left-B7jZiLth.js +1 -0
- package/dist/client/assets/path-text-3Rfu6lt8.js +1 -0
- package/dist/client/assets/{pegDiagram-VL7TDLO6-cC-QUd7I.js → pegDiagram-VL7TDLO6-Do5PIp8B.js} +1 -1
- package/dist/client/assets/pencil-Bzg-nc6d.js +1 -0
- package/dist/client/assets/{pie-WAS4IAKB-BI3XUcLN.js → pie-WAS4IAKB-B_nNQOzn.js} +1 -1
- package/dist/client/assets/{pieDiagram-7S7Q4E2Y-BP4gJ4ZK.js → pieDiagram-7S7Q4E2Y-D_IG4xwA.js} +1 -1
- package/dist/client/assets/{play-BJZrOx6T.js → play-DpXXQ1qB.js} +1 -1
- package/dist/client/assets/popover-OWEv6cQz.js +48 -0
- package/dist/client/assets/presentationTier-DPVAxTK4.js +1 -0
- package/dist/client/assets/previewRouteSearch-BjZdTuSf.js +1 -0
- package/dist/client/assets/primary-Cf-xJExj.js +4 -0
- package/dist/client/assets/primitives-CxTBN7D4.js +1 -0
- package/dist/client/assets/projectCheckouts.logic-DUT4AxXr.js +1 -0
- package/dist/client/assets/projectPaths-B8aVmOZX.js +1 -0
- package/dist/client/assets/projectPreferences-CzWBItFj.js +1 -0
- package/dist/client/assets/providerCapabilities-B2YOPsLN.js +1 -0
- package/dist/client/assets/providerDriverMeta-BHHL9uw0.js +1 -0
- package/dist/client/assets/providerModels-v9PYbzRE.js +1 -0
- package/dist/client/assets/providerStatus-CDPaqb0S.js +1 -0
- package/dist/client/assets/pullRequestsModel.logic-Dv_om_C4.js +1 -0
- package/dist/client/assets/{qr-code-BFO8lV1M.js → qr-code-BlbiBIwH.js} +1 -1
- package/dist/client/assets/{qr-code-Cmfz5JKf.js → qr-code-DywzVgQC.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-CIZ2JOQS-DO-N1m-q.js → quadrantDiagram-CIZ2JOQS-DY6fJyrM.js} +1 -1
- package/dist/client/assets/{radar-RG4KPBEZ-CfayXQ5F.js → radar-RG4KPBEZ-D9689I5m.js} +1 -1
- package/dist/client/assets/radio-group-DVwD6Cuy.js +1 -0
- package/dist/client/assets/{railroad-74A4TZTK-CT6f-etT.js → railroad-74A4TZTK-DVzWbQnl.js} +1 -1
- package/dist/client/assets/railroad-abnf-HS5TGJTU-C_2P6umA.js +1 -0
- package/dist/client/assets/railroad-ebnf-LZEXJU2U-aGlR3R3z.js +1 -0
- package/dist/client/assets/railroad-peg-WCYAUIDC-DCB9oE8y.js +1 -0
- package/dist/client/assets/{railroadDiagram-AXF67PYL-DC8egbob.js → railroadDiagram-AXF67PYL-D1oJ6Jtl.js} +1 -1
- package/dist/client/assets/readCache-B7cDPz2O.js +1 -0
- package/dist/client/assets/{refresh-cw-K_hU8_ld.js → refresh-cw-CRUTivd6.js} +1 -1
- package/dist/client/assets/{requirementDiagram-LRYGKXZP-DJMzcLk_.js → requirementDiagram-LRYGKXZP-7RM8iREp.js} +1 -1
- package/dist/client/assets/rotate-ccw-BE2ZCwL6.js +1 -0
- package/dist/client/assets/roving-radio-group-NMPWrDqe.js +1 -0
- package/dist/client/assets/rows-2-DDS4dGTX.js +1 -0
- package/dist/client/assets/runtime-DjjjAcTE.js +18 -0
- package/dist/client/assets/safePolygon-C1AzMRS4.js +1 -0
- package/dist/client/assets/{sankeyDiagram-W5VNT64P-YR6aIYLj.js → sankeyDiagram-W5VNT64P-C1tKAPGN.js} +1 -1
- package/dist/client/assets/{save-Mh-PA_2P.js → save-OZdkPs_y.js} +1 -1
- package/dist/client/assets/scroll-area-80P7vbjw.js +1 -0
- package/dist/client/assets/{scrollEdges-Zcpuz3un.js → scrollEdges-C0Oc-5qi.js} +1 -1
- package/dist/client/assets/select-Cb9FUPHD.js +1 -0
- package/dist/client/assets/separator-CO8bC7Wc.js +1 -0
- package/dist/client/assets/{sequenceDiagram-SI44F4Z6-BVeSqWDA.js → sequenceDiagram-SI44F4Z6-DGVpb7jL.js} +1 -1
- package/dist/client/assets/settings-2-PrRDu6Lc.js +1 -0
- package/dist/client/assets/settingsLayout-CRFNCk_D.js +1 -0
- package/dist/client/assets/sheet-C5DW7qVO.js +1 -0
- package/dist/client/assets/{shield-i098Bm_B.js → shield-CBHYqlkR.js} +1 -1
- package/dist/client/assets/{shield-alert-CXmR7fM9.js → shield-alert-Dc2cGwyR.js} +1 -1
- package/dist/client/assets/{shield-check-CdFhWT_o.js → shield-check-_wl7R4Js.js} +1 -1
- package/dist/client/assets/sidebar-0BBaFNm3.js +1 -0
- package/dist/client/assets/sidebarProjectFolders-BjWzbt8C.js +3 -0
- package/dist/client/assets/sidebarProjectGrouping-nQRStWrZ.js +1 -0
- package/dist/client/assets/sidebarStatusText-BBKuNies.js +1 -0
- package/dist/client/assets/sidebarUndo-Dfq1lvyF.js +1 -0
- package/dist/client/assets/{skeleton-BwFgUtuE.js → skeleton-DfUe6VV_.js} +1 -1
- package/dist/client/assets/sliders-horizontal-BGXkwvKv.js +1 -0
- package/dist/client/assets/sliding-tabs-BnDSjRU3.js +39 -0
- package/dist/client/assets/{smartphone-DGfizz51.js → smartphone-OEAQOTdv.js} +1 -1
- package/dist/client/assets/spinner-lHRJWsym.js +1 -0
- package/dist/client/assets/square-B05NKv3e.js +1 -0
- package/dist/client/assets/{star-J3x3fktG.js → star-C8mHmfZu.js} +1 -1
- package/dist/client/assets/{stateDiagram-OKZ733FA-DoIZN669.js → stateDiagram-OKZ733FA-CCOAegCG.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-UEYNNEHI-D60qqBed.js +1 -0
- package/dist/client/assets/storeSelectors-BichCKDC.js +1 -0
- package/dist/client/assets/surfaceMorph-BTRijmlU.js +1 -0
- package/dist/client/assets/{swimlanes-SLNWSIFB-BoFLigyK.js → swimlanes-SLNWSIFB-CFsLYT4h.js} +1 -1
- package/dist/client/assets/swimlanesDiagram-ULZ7WXOC-D0SaJgSn.js +8 -0
- package/dist/client/assets/switch-oQc7Ifbl.js +1 -0
- package/dist/client/assets/text-wrap-DSRdSfDm.js +1 -0
- package/dist/client/assets/textarea-VyiIZ0wQ.js +1 -0
- package/dist/client/assets/threadPriorityRefreshRuntime-H656C1J_.js +1 -0
- package/dist/client/assets/ticker-CPutfhZ4.js +1 -0
- package/dist/client/assets/{timeline-definition-Z64GVDOM-D65EmNWc.js → timeline-definition-Z64GVDOM-B4agmO7R.js} +1 -1
- package/dist/client/assets/toggle-DFqtCPt-.js +1 -0
- package/dist/client/assets/toggle-group-C5ICmqkI.js +1 -0
- package/dist/client/assets/{tokenModePresentation-C0-NgmX5.js → tokenModePresentation-umDRm4k1.js} +1 -1
- package/dist/client/assets/tooltip-DbqhseXd.js +1 -0
- package/dist/client/assets/{treeView-Q6P3EWNA-C2S-OPgI.js → treeView-Q6P3EWNA-C_S3udFB.js} +1 -1
- package/dist/client/assets/{treemap-WGGIJYW6-6Ovsu9iH.js → treemap-WGGIJYW6-B-kUSAkE.js} +1 -1
- package/dist/client/assets/undo-2-lyluTGMW.js +1 -0
- package/dist/client/assets/{unplug-BEfcl9Ht.js → unplug-D6iu-qlh.js} +1 -1
- package/dist/client/assets/usage-ClF-eUmy.js +1 -0
- package/dist/client/assets/useActiveIndicator-R5NWu8Fg.js +1 -0
- package/dist/client/assets/useAppSidebarCollapsed-BbMxfio5.js +1 -0
- package/dist/client/assets/useAppearancePreference-Ix13pMKy.js +1 -0
- package/dist/client/assets/useAtlassian-BYDCc9lv.js +0 -0
- package/dist/client/assets/useCheckoutResolution-CR-oOp5-.js +1 -0
- package/dist/client/assets/useDesktopRelaunchGuard-Jmh615iZ.js +1 -0
- package/dist/client/assets/useDiffFileNavigation-DeuzdD5E.js +15 -0
- package/dist/client/assets/useDiffLayout-DhcXwhBL.js +1 -0
- package/dist/client/assets/useEnvironmentSettingsTarget-DM6BRDT7.js +1 -0
- package/dist/client/assets/useFocus-CV0KIZwg.js +1 -0
- package/dist/client/assets/useGit-CUcs7h5_.js +1 -0
- package/dist/client/assets/useGitBranchSearch-CeKFtnCL.js +1 -0
- package/dist/client/assets/useHostedDraftExecutionTarget-DvQU5UOq.js +1 -0
- package/dist/client/assets/useLabelableId-CEgCRi6q.js +1 -0
- package/dist/client/assets/useLandingFlash-BfOOlFtW.js +1 -0
- package/dist/client/assets/useLogicalProjectSnapshots-CRNZke74.js +1 -0
- package/dist/client/assets/useNavigate-sQZthdyT.js +1 -0
- package/dist/client/assets/usePageLeadingInsetClass-Bf4nUvx4.js +1 -0
- package/dist/client/assets/usePhoneThreadActions-VaQ-mZex.js +1 -0
- package/dist/client/assets/usePopupHandleStore-DimKo2Yy.js +1 -0
- package/dist/client/assets/usePopupViewport-YeqX_UM3.js +1 -0
- package/dist/client/assets/usePresentationTier-B9kCQ4YH.js +1 -0
- package/dist/client/assets/useProject-Kt74Z12J.js +1 -0
- package/dist/client/assets/useProviderOptionsUpdater-CTzNh2B7.js +2 -0
- package/dist/client/assets/usePullRequestFilesViewed-D5Snmzys.js +1 -0
- package/dist/client/assets/usePullRequestsModel-DJL5HHbP.js +40 -0
- package/dist/client/assets/useScrollLock-CLZ31xsK.js +1 -0
- package/dist/client/assets/useSidebarThreadActions-n6EkLATf.js +6 -0
- package/dist/client/assets/{useStatistics-D55-xLMz.js → useStatistics-DD0mYS4J.js} +14 -14
- package/dist/client/assets/{useTheme-B441xg4F.js → useTheme-Bdy-BDs-.js} +1 -1
- package/dist/client/assets/useValueChanged-DoumqMnV.js +1 -0
- package/dist/client/assets/{user-round-C-U7TZKG.js → user-round-BPDXr8Gq.js} +1 -1
- package/dist/client/assets/{vennDiagram-T6HMQDX7-fZAexcYr.js → vennDiagram-T6HMQDX7-B1UEn_j_.js} +1 -1
- package/dist/client/assets/{vscode-icons-BYX6fBsM.js → vscode-icons-Ccy-gzFN.js} +1 -1
- package/dist/client/assets/{wardley-WFR3VGLG-gdYWSMxK.js → wardley-WFR3VGLG-gPdyDc-7.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-T6FBY63Y-iDJxQb70.js → wardleyDiagram-T6FBY63Y-2aDcwOA4.js} +1 -1
- package/dist/client/assets/workspaceLifecycle-OJ1aKksw.js +3 -0
- package/dist/client/assets/workspaceMetadataProjection-CyEyJhUa.js +1 -0
- package/dist/client/assets/workspaceRouteSearch-CCavUdbH.js +1 -0
- package/dist/client/assets/{wrench-D79uBUSl.js → wrench-CPUCA_rn.js} +1 -1
- package/dist/client/assets/wsTransport-C88seBPA.js +15 -0
- package/dist/client/assets/{xychartDiagram-ELKLHX3M-B4cfMwpJ.js → xychartDiagram-ELKLHX3M-C1_7Q-1i.js} +1 -1
- package/dist/client/favicon.svg +1 -1
- package/dist/client/index.html +1 -1
- package/dist/collectUint8StreamText-BsLSgI8i.mjs +710 -0
- package/dist/collectUint8StreamText-D5olwfpM.cjs +757 -0
- package/dist/{deviceHostWorker-L8C9wy38.mjs → deviceHostWorker-B-Dn-6An.mjs} +1 -1
- package/dist/{deviceHostWorker-CYnrwfrv.cjs → deviceHostWorker-D4HauWIV.cjs} +1 -1
- package/dist/{makeManagedServerProvider-CUwxc0Pn.cjs → makeManagedServerProvider-B5tP7tvg.cjs} +2 -2
- package/dist/{makeManagedServerProvider-B_lPFNpL.mjs → makeManagedServerProvider-B65ipCxM.mjs} +2 -2
- package/dist/resource-monitor/linux-arm64/ryco-resource-monitor +0 -0
- package/dist/resource-monitor/ryco-resource-monitor +0 -0
- package/dist/resource-monitor/ryco-resource-monitor.exe +0 -0
- package/dist/resource-monitor/win32-arm64/ryco-resource-monitor.exe +0 -0
- package/dist/resource-monitor/win32-x64/ryco-resource-monitor.exe +0 -0
- package/dist/{rolldown-runtime-LGfotAqq.cjs → rolldown-runtime-HbSU0i7K.cjs} +7 -0
- package/dist/{runtimeSession-V3RIy8Ao.mjs → runtimeSession-D_BZ-wRH.mjs} +1 -1
- package/dist/{src-BzVJd3Me.cjs → src-FmeCeBJ9.cjs} +3408 -308
- package/dist/{src-7E1M4gTQ.mjs → src-VTj60bUm.mjs} +2154 -140
- package/package.json +1 -1
- package/dist/AzureDevOpsSourceControlProvider-DmJD1-WL.cjs +0 -190
- package/dist/AzureDevOpsSourceControlProvider-d5Ogsspk.mjs +0 -188
- package/dist/GitLabSourceControlProvider-BZdwXdJl.mjs +0 -186
- package/dist/GitLabSourceControlProvider-CrcBR6KQ.cjs +0 -188
- package/dist/client/assets/AccountSettings-FN7pwqYA.js +0 -1
- package/dist/client/assets/AiFocusSettings-xcDAMaqH.js +0 -1
- package/dist/client/assets/AppearanceSettings-BvsvAOsG.js +0 -1
- package/dist/client/assets/BranchToolbar.logic-DFsXV3Qs.js +0 -3
- package/dist/client/assets/BrowserPanel-D-g_xDZs.js +0 -1
- package/dist/client/assets/ChatRightPanel-Bm906qNi.js +0 -201
- package/dist/client/assets/ChatThreadRouteView-CATwakjI.js +0 -1
- package/dist/client/assets/CommandPaletteDialog-Obv1bvxj.js +0 -1
- package/dist/client/assets/CompositeRoot-CfkIdky8.js +0 -1
- package/dist/client/assets/ComputerUseSettings-ljYmTHea.js +0 -1
- package/dist/client/assets/ConnectionsSettings-CIXs7x_E.js +0 -7
- package/dist/client/assets/ContextHandoffEndpointLabel-BzI4Wi1i.js +0 -4
- package/dist/client/assets/DiagnosticsSettings-DGX_2T2M.js +0 -2
- package/dist/client/assets/DialogHandle-CTtSYpsC.js +0 -1
- package/dist/client/assets/DialogRoot-k2_0SNKA.js +0 -1
- package/dist/client/assets/DialogTitle-Du7CAbaO.js +0 -1
- package/dist/client/assets/DialogTrigger-VpFh8Xza.js +0 -1
- package/dist/client/assets/DraftChatThreadRouteView-Cmc5HpWf.js +0 -1
- package/dist/client/assets/GlassSurface-BlWIlQ0s.js +0 -1
- package/dist/client/assets/HostedConnectionControls-ySHqwr4K.js +0 -1
- package/dist/client/assets/HostedHubRoot-Caz8PElK.js +0 -2
- package/dist/client/assets/HostedNodeRenameDialog-ChxJdr-Z.js +0 -1
- package/dist/client/assets/HostedRelayTrustNotice-DPVrIfj_.js +0 -1
- package/dist/client/assets/IntegrationsSettingsPanel-eAq5h-D5.js +0 -2
- package/dist/client/assets/KeybindingsSettings-D1XaEVGH.js +0 -7
- package/dist/client/assets/LazyBrowserPanel-B6POLJh3.js +0 -2
- package/dist/client/assets/McpServersSettings-DqLA6n5v.js +0 -6
- package/dist/client/assets/MobileSheet-CtQIYRlY.js +0 -1
- package/dist/client/assets/NodeSecuritySettings-Skm7GQDl.js +0 -1
- package/dist/client/assets/NullStore-b8PhjwPZ.js +0 -1
- package/dist/client/assets/OnboardingDialog-8-fKvY5H.js +0 -1
- package/dist/client/assets/OpinionatedPluginsSettings-BIJfJ34L.js +0 -1
- package/dist/client/assets/PhoneHome-CUzxhhR4.js +0 -1
- package/dist/client/assets/PhoneSettingsSurface-BK2RHmYJ.js +0 -2
- package/dist/client/assets/ProvidersSettingsPanel-DPxL7AsR.js +0 -1
- package/dist/client/assets/RedactedSensitiveText-DH4mWpB6.js +0 -1
- package/dist/client/assets/RootAppShell-DwiWD4Cy.js +0 -7
- package/dist/client/assets/SettingsDialog-CE8qy0qL.js +0 -2
- package/dist/client/assets/SettingsPanels-BYknk6GO.js +0 -3
- package/dist/client/assets/SettingsPanels.editor-64bM0lhg.js +0 -2
- package/dist/client/assets/SourceControlSettings-BbveiAj3.js +0 -1
- package/dist/client/assets/StatisticsPage-CAO_tCeC.js +0 -1
- package/dist/client/assets/StatisticsPanel-SNlgMv2o.js +0 -1
- package/dist/client/assets/StatisticsSettingsLink-BpkNubL2.js +0 -1
- package/dist/client/assets/ThreadTerminalDrawer-9x_kqQPy.js +0 -18
- package/dist/client/assets/ThreadWorkspacePanel-BXE17C4x.js +0 -2073
- package/dist/client/assets/appChrome-B_VWWDFj.js +0 -1
- package/dist/client/assets/architecture-7GRP2DOG-CQNNG5gU.js +0 -1
- package/dist/client/assets/authorization-BugIGt5e.js +0 -1
- package/dist/client/assets/badge-BswOCwph.js +0 -1
- package/dist/client/assets/capabilities-Bj_X9FZ-.js +0 -1
- package/dist/client/assets/channel-BtX-w3CK.js +0 -1
- package/dist/client/assets/chevron-right-Ddq5gL-L.js +0 -1
- package/dist/client/assets/classDiagram-JCYQIIEL-BgDa3HFl.js +0 -1
- package/dist/client/assets/classDiagram-v2-OCEON4UE-BgDa3HFl.js +0 -1
- package/dist/client/assets/compiler-runtime-C4g8XhC5.js +0 -1
- package/dist/client/assets/desktopWorkspace-Ocqt625W.js +0 -1
- package/dist/client/assets/editorPreferences-DVhg0CXd.js +0 -1
- package/dist/client/assets/eventmodeling-NTZA5JFV-DpzGHjmu.js +0 -1
- package/dist/client/assets/flowDiagram-UKHOOZJN-CaDVMm72.js +0 -1
- package/dist/client/assets/hostedConnectionCoordinator-BztHfGNt.js +0 -1
- package/dist/client/assets/hostedPairing-CqhLPQqG.js +0 -1
- package/dist/client/assets/hubRoutes-DExWSvVE.js +0 -1
- package/dist/client/assets/kbd-DKuvGqFP.js +0 -1
- package/dist/client/assets/layers-CwP65mnC.js +0 -1
- package/dist/client/assets/liquidGlass-CA2o_Cq0.js +0 -1
- package/dist/client/assets/liquidGlass.worker-icvLJKHf.js +0 -1
- package/dist/client/assets/main-BqSANuAs.css +0 -2
- package/dist/client/assets/main-RFllWEko.js +0 -9
- package/dist/client/assets/motion-C9rN_t9p.js +0 -1
- package/dist/client/assets/palette-gaqgtube.js +0 -1
- package/dist/client/assets/perfInstrumentation-BT27w4tn.js +0 -1
- package/dist/client/assets/presentationTier-xlIjcFab.js +0 -1
- package/dist/client/assets/primary-CQh_KHGG.js +0 -5
- package/dist/client/assets/providerDriverMeta-LJ2vJxm-.js +0 -1
- package/dist/client/assets/providerStatus-DBGvvkyF.js +0 -1
- package/dist/client/assets/radio-group-BueX1AVO.js +0 -1
- package/dist/client/assets/railroad-abnf-HS5TGJTU-B890iayj.js +0 -1
- package/dist/client/assets/railroad-ebnf-LZEXJU2U-C079Tzw6.js +0 -1
- package/dist/client/assets/railroad-peg-WCYAUIDC-DxvOX5Rh.js +0 -1
- package/dist/client/assets/runtime-OM-uAtaj.js +0 -18
- package/dist/client/assets/scroll-area-BC-LB_zE.js +0 -1
- package/dist/client/assets/separator-yx1r9ZDw.js +0 -1
- package/dist/client/assets/settingsLayout-BbjDM-p0.js +0 -1
- package/dist/client/assets/sheet-CpEwjOWn.js +0 -1
- package/dist/client/assets/sidebar-DayQTDZp.js +0 -1
- package/dist/client/assets/sidebarProjectFolders-DXqx3OlZ.js +0 -4
- package/dist/client/assets/sidebarStatusText-kdA6QMZS.js +0 -1
- package/dist/client/assets/sidebarUndo-BHFfJj0k.js +0 -1
- package/dist/client/assets/square-Cd2WS1gv.js +0 -1
- package/dist/client/assets/src-DHNjfMxR.js +0 -14
- package/dist/client/assets/stateDiagram-v2-UEYNNEHI-BnzsGHaN.js +0 -1
- package/dist/client/assets/storeSelectors-D60AAN01.js +0 -1
- package/dist/client/assets/swimlanesDiagram-ULZ7WXOC-BnA-oDvU.js +0 -8
- package/dist/client/assets/switch-D9inWKdd.js +0 -48
- package/dist/client/assets/toggle-group-YNqzWsK0.js +0 -1
- package/dist/client/assets/toggle-wMq3LLn1.js +0 -1
- package/dist/client/assets/tooltip-mwOCSCXF.js +0 -1
- package/dist/client/assets/usage-DF8oQrsy.js +0 -1
- package/dist/client/assets/useAppSidebarCollapsed-C0jpPtER.js +0 -1
- package/dist/client/assets/useAppearancePreference-Dlh9P8iu.js +0 -1
- package/dist/client/assets/useBaseUiId-Bz8dcyjd.js +0 -1
- package/dist/client/assets/useLabelableId-C8bc9a0F.js +0 -1
- package/dist/client/assets/useNavigate-01O5dMQe.js +0 -1
- package/dist/client/assets/usePhoneThreadActions-BIdh81kF.js +0 -1
- package/dist/client/assets/usePopupViewport-DYYZwfTW.js +0 -1
- package/dist/client/assets/usePresentationTier-hxB7Yv_Q.js +0 -1
- package/dist/client/assets/useScrollLock-BO185DkJ.js +0 -1
- package/dist/client/assets/useTriggerFocusGuards-CMLVr18J.js +0 -1
- package/dist/client/assets/useValueChanged-DSyRHPje.js +0 -1
- package/dist/client/assets/workspaceMetadataProjection-So9-wSEZ.js +0 -1
- package/dist/collectUint8StreamText-BAUF-vzz.mjs +0 -37
- package/dist/collectUint8StreamText-vagpNUMJ.cjs +0 -42
- package/dist/git-BKwGfw8A.mjs +0 -132
- package/dist/git-Dn5wrgFY.cjs +0 -218
- package/dist/sourceControl-B0D1Op29.cjs +0 -253
- package/dist/sourceControl-BiEBxN01.mjs +0 -224
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { i as formatAttachmentPathLines, n as stampRuntimeEvent, r as appendAttachmentPathLines, t as requireRuntimeSessionId } from "./runtimeSession-V3RIy8Ao.mjs";
|
|
3
|
+
import { $t as resolvePromptInjectedEffort, Gt as getModelSelectionBooleanOptionValue, Ht as applyClaudePromptEffortPrefix, Jt as getProviderOptionCurrentValue, Kt as getModelSelectionStringOptionValue, Nt as ServerConfig, Ut as createModelCapabilities, X as ServerSettingsService, Yt as getProviderOptionDescriptors } from "./Metrics-C3vLS9rz.mjs";
|
|
4
|
+
import { Ad as ProviderItemId, Fd as RuntimeTaskId, Id as ThreadId, Ks as ProviderDriverKind, Md as RuntimeRequestId, Pd as RuntimeSubagentId, Rd as TurnId, ei as TextGenerationError, gd as ApprovalRequestId, jd as RuntimeItemId, qs as ProviderInstanceId, wd as EventId, xi as ClaudeSettings } from "./src-VTj60bUm.mjs";
|
|
5
|
+
import { A as ProviderEventLoggers, At as isCommandMissingCause, Bt as createProcessDeviceToolBinding, Ci as sanitizeFeatureBranchName, Dt as buildServerProvider, Ft as AGENT_CONTROL_INTERNAL_SERVER_NAME, Gt as ProviderAdapterValidationError, H as checkRtkAvailability, Ht as ProviderAdapterRequestError, It as agentControlHostContext, J as resolveHtmlRenderToolKind, Kt as ProviderDriverError, Mt as parseGenericCliVersion, Nt as providerModelsFromSettings, Pt as spawnAndCollect, Qn as isPersistableChatAttachment, Rt as installAgentControlNativeHttp, Si as sanitizeBranchFragment, Ut as ProviderAdapterSessionClosedError, V as buildTokenReductionInstructions, Vt as ProviderAdapterProcessError, Wt as ProviderAdapterSessionNotFoundError, X as withoutHtmlRenderMarkup, Y as resolveHtmlRenderToolPresentation, _i as normalizeCliError, _t as mergeProviderInstanceEnvironment, at as enrichProviderSnapshotWithVersionAdvisory, bi as sanitizeThreadTitle, c as getClaudeCatalogModelCapabilities, ci as buildBranchNamePrompt, d as resolveClaudeModelCatalog, di as buildIssueContentTitlePrompt, dt as resolveProviderMaintenanceCapabilitiesEffect, er as resolveAttachmentPath, f as resolveClaudeModelsForVersion, fi as buildPrContentPrompt, ft as classifyTaskAgentKind, gt as resolveClaudeHomePath, h as isClaudeNativeCompaction, hi as buildThreadTitlePrompt, ht as makeClaudeEnvironment, i as AgentControlSessionRegistry, it as ModelManifest, j as makeEventNdjsonLogger, kt as detailFromResult, l as normalizeClaudeCatalogEffort, li as buildCommitMessagePrompt, mi as buildThreadPriorityPrompt, mt as makeClaudeContinuationGroupKey, n as usageLimitStateFromWindows, o as formatClaudeVersionUpgradeMessage, p as setActiveClaudeModelCatalog, pi as buildSideQuestionPrompt, pt as makeClaudeCapabilitiesCacheKey, qt as ProviderTurnNotSteerableError, r as makeServerQueueMetrics, s as getActiveClaudeModelCatalog, si as validateRankInboxThreadsResult, st as makePackageManagedProviderMaintenanceResolver, t as isRepresentableEpochMs, u as resolveClaudeCatalogApiModelId, ui as buildIssueContentPolishPrompt, ut as normalizeCommandPath, vi as sanitizeCommitSubject, wt as DEFAULT_TIMEOUT_MS, xi as toJsonSchemaObject, yi as sanitizePrTitle, zt as redactAgentControlSecrets } from "./bin.mjs";
|
|
6
|
+
import { i as formatAttachmentPathLines, n as stampRuntimeEvent, r as appendAttachmentPathLines, t as requireRuntimeSessionId } from "./runtimeSession-D_BZ-wRH.mjs";
|
|
8
7
|
import { t as defaultProviderContinuationIdentity } from "./ProviderDriver-kCV60GKk.mjs";
|
|
9
|
-
import { n as sideQuestionEnvironment, t as sideQuestionDirectory } from "./SideQuestionIsolation-
|
|
8
|
+
import { n as sideQuestionEnvironment, t as sideQuestionDirectory } from "./SideQuestionIsolation-B1T-DsR0.mjs";
|
|
10
9
|
import { t as formatSourceControlContextsForAgent } from "./sourceControlContextFormatter-DEwpnVAH.mjs";
|
|
11
10
|
import { n as formatProjectCustomSystemPrompt } from "./ProjectCustomSystemPrompt-CS1nulhL.mjs";
|
|
12
|
-
import { t as makeManagedServerProvider } from "./makeManagedServerProvider-
|
|
13
|
-
import { Cache, Cause, DateTime, Deferred, Duration, Effect, Exit, Fiber, FileSystem, Option, Path, Queue, Ref, Result, Schema, Stream } from "effect";
|
|
14
|
-
import {
|
|
11
|
+
import { t as makeManagedServerProvider } from "./makeManagedServerProvider-B65ipCxM.mjs";
|
|
12
|
+
import { Cache, Cause, Clock, DateTime, Deferred, Duration, Effect, Exit, Fiber, FileSystem, Option, Path, Queue, Ref, Result, Schema, Semaphore, Stream } from "effect";
|
|
13
|
+
import { execFile } from "node:child_process";
|
|
15
14
|
import * as NodePath from "node:path";
|
|
15
|
+
import { HttpClient } from "effect/unstable/http";
|
|
16
16
|
import * as NodeOS from "node:os";
|
|
17
|
-
import { execFile } from "node:child_process";
|
|
18
17
|
import * as NodeFS from "node:fs/promises";
|
|
19
18
|
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process";
|
|
20
|
-
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
19
|
+
import { getSessionMessages, query } from "@anthropic-ai/claude-agent-sdk";
|
|
21
20
|
//#region src/provider/Layers/ClaudeProvider.ts
|
|
22
21
|
const DEFAULT_CLAUDE_MODEL_CAPABILITIES = createModelCapabilities({ optionDescriptors: [] });
|
|
23
22
|
const PROVIDER$1 = ProviderDriverKind.make("claudeAgent");
|
|
24
23
|
const CLAUDE_PRESENTATION = {
|
|
25
24
|
displayName: "Claude",
|
|
26
25
|
showInteractionModeToggle: true,
|
|
27
|
-
supportsAskMode: true
|
|
26
|
+
supportsAskMode: true,
|
|
27
|
+
supportsTurnSteering: true
|
|
28
28
|
};
|
|
29
29
|
function getClaudeModelCapabilities(model) {
|
|
30
30
|
const capabilities = getClaudeCatalogModelCapabilities(getActiveClaudeModelCatalog(), model);
|
|
@@ -625,6 +625,7 @@ function observeClaudeCache(input) {
|
|
|
625
625
|
providerInstanceId: input.providerInstanceId,
|
|
626
626
|
model: input.model,
|
|
627
627
|
...input.modelSelection ? { modelSelection: input.modelSelection } : {},
|
|
628
|
+
...input.cwd ? { cwd: input.cwd } : {},
|
|
628
629
|
messageId: input.messageId,
|
|
629
630
|
directInputTokens: counts.directInputTokens,
|
|
630
631
|
cacheReadInputTokens: counts.cacheReadInputTokens,
|
|
@@ -633,6 +634,278 @@ function observeClaudeCache(input) {
|
|
|
633
634
|
};
|
|
634
635
|
}
|
|
635
636
|
//#endregion
|
|
637
|
+
//#region src/provider/claudeContextUsage.ts
|
|
638
|
+
function knownContextWindow(value) {
|
|
639
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : void 0;
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* `compact_boundary.compact_metadata.post_tokens` as a context gauge; undefined when absent or
|
|
643
|
+
* invalid. Compaction invalidated the cache evidence, so the gauge never carries `claudeCache`.
|
|
644
|
+
*/
|
|
645
|
+
function claudePostCompactionUsage(compactMetadata, contextWindow) {
|
|
646
|
+
if (compactMetadata === null || typeof compactMetadata !== "object") return;
|
|
647
|
+
const postTokens = compactMetadata.post_tokens;
|
|
648
|
+
if (typeof postTokens !== "number" || !Number.isFinite(postTokens)) return;
|
|
649
|
+
const rounded = Math.round(postTokens);
|
|
650
|
+
if (rounded <= 0) return;
|
|
651
|
+
const maxTokens = knownContextWindow(contextWindow);
|
|
652
|
+
return {
|
|
653
|
+
usedTokens: maxTokens !== void 0 ? Math.min(rounded, maxTokens) : rounded,
|
|
654
|
+
...maxTokens !== void 0 ? { maxTokens } : {}
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* The gauge a Claude result publishes. `result.usage` is cumulative across every API call of the
|
|
659
|
+
* turn, so the last main-loop gauge wins and the cumulative figure only rides along as
|
|
660
|
+
* `totalProcessedTokens`. Without a gauge the cumulative snapshot is a fallback, but never for a
|
|
661
|
+
* turn that crossed a compaction boundary: its cumulative input is the pre-compaction size.
|
|
662
|
+
*/
|
|
663
|
+
function selectClaudeResultUsageGauge(input) {
|
|
664
|
+
const { lastGauge, cumulative, maxTokens } = input;
|
|
665
|
+
if (lastGauge === void 0) return input.cumulativeIsGauge ? cumulative : void 0;
|
|
666
|
+
const cumulativeTotal = cumulative?.totalProcessedTokens ?? cumulative?.usedTokens;
|
|
667
|
+
return {
|
|
668
|
+
...lastGauge,
|
|
669
|
+
...typeof maxTokens === "number" && Number.isFinite(maxTokens) && maxTokens > 0 ? { maxTokens } : {},
|
|
670
|
+
...typeof cumulativeTotal === "number" && Number.isFinite(cumulativeTotal) && cumulativeTotal > lastGauge.usedTokens ? { totalProcessedTokens: cumulativeTotal } : {}
|
|
671
|
+
};
|
|
672
|
+
}
|
|
673
|
+
const ABORT_TERMINAL_REASONS = /* @__PURE__ */ new Set(["aborted_streaming", "aborted_tools"]);
|
|
674
|
+
function resultErrorsText(result) {
|
|
675
|
+
return "errors" in result && Array.isArray(result.errors) ? result.errors.join(" ").toLowerCase() : "";
|
|
676
|
+
}
|
|
677
|
+
function isInterruptedResult(result) {
|
|
678
|
+
const errors = resultErrorsText(result);
|
|
679
|
+
if (errors.includes("interrupt")) return true;
|
|
680
|
+
return result.subtype === "error_during_execution" && result.is_error === false && (errors.includes("request was aborted") || errors.includes("interrupted by user") || errors.includes("aborted"));
|
|
681
|
+
}
|
|
682
|
+
/** The CLI ended the segment by aborting it (a Stop or a `priority: "now"` steer). */
|
|
683
|
+
function isClaudeAbortTerminalReason(result) {
|
|
684
|
+
const terminalReason = Reflect.get(result, "terminal_reason");
|
|
685
|
+
return typeof terminalReason === "string" && ABORT_TERMINAL_REASONS.has(terminalReason);
|
|
686
|
+
}
|
|
687
|
+
function readStringArray(value) {
|
|
688
|
+
return Array.isArray(value) && value.every((entry) => typeof entry === "string") ? value : void 0;
|
|
689
|
+
}
|
|
690
|
+
function isRootFrame$1(message) {
|
|
691
|
+
const parentToolUseId = Reflect.get(message, "parent_tool_use_id");
|
|
692
|
+
return parentToolUseId === null || parentToolUseId === void 0;
|
|
693
|
+
}
|
|
694
|
+
/**
|
|
695
|
+
* The prompt uuids a frame echoes. Results echo every user message the CLI turn consumed. The
|
|
696
|
+
* CLI turn's first reply frame echoes the messages that started it (early echo): its first
|
|
697
|
+
* non-ping stream event, or its first root assistant message when it streamed nothing (a request
|
|
698
|
+
* that failed at the API replies with a synthetic error message).
|
|
699
|
+
*/
|
|
700
|
+
function claudeEchoedPromptUuids(message) {
|
|
701
|
+
if (message.type !== "result" && message.type !== "stream_event" && !(message.type === "assistant" && isRootFrame$1(message))) return [];
|
|
702
|
+
const uuids = readStringArray(Reflect.get(message, "user_message_uuids"));
|
|
703
|
+
if (uuids !== void 0 && uuids.length > 0) return uuids;
|
|
704
|
+
const uuid = Reflect.get(message, "user_message_uuid");
|
|
705
|
+
return typeof uuid === "string" && uuid.length > 0 ? [uuid] : [];
|
|
706
|
+
}
|
|
707
|
+
function classifyClaudeResultKind(result) {
|
|
708
|
+
if (result.subtype === "success" && !result.is_error) return "success";
|
|
709
|
+
if (isClaudeAbortTerminalReason(result)) return "abort";
|
|
710
|
+
if (Reflect.get(result, "terminal_reason") === void 0 && isInterruptedResult(result)) return "abort";
|
|
711
|
+
return "failure";
|
|
712
|
+
}
|
|
713
|
+
/** Whether an echo names the turn's prompt or one of its steers. */
|
|
714
|
+
function claudeEchoNamesTurn(input) {
|
|
715
|
+
return input.echoed.some((uuid) => uuid === input.promptUuid || input.steerPromptUuids.has(uuid));
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* Whether a result belongs to the open prompt turn. It does when it echoes the prompt or any of
|
|
719
|
+
* the turn's steers. Without an echo (older CLIs) it belongs unless its origin is not human.
|
|
720
|
+
* Callers skip the check for provider turns (no prompt uuid).
|
|
721
|
+
*/
|
|
722
|
+
function claudeResultBelongsToTurn(input) {
|
|
723
|
+
if (input.echoed.length > 0) return claudeEchoNamesTurn(input);
|
|
724
|
+
return input.origin === void 0 || input.origin.kind === "human";
|
|
725
|
+
}
|
|
726
|
+
/**
|
|
727
|
+
* The turn waits only when Stop was not requested, a steer is still unsettled, the segment ended
|
|
728
|
+
* by abort or success, and the CLI positively promised another result (`queued_turn_count > 0`).
|
|
729
|
+
* Every other result completes the turn, so no waiting is unbounded.
|
|
730
|
+
*/
|
|
731
|
+
function decideClaudeTurnResult(input) {
|
|
732
|
+
const echoed = new Set(input.echoedPromptUuids);
|
|
733
|
+
const newlySettled = [];
|
|
734
|
+
const unsettled = [];
|
|
735
|
+
for (const uuid of input.steerPromptUuids) {
|
|
736
|
+
if (input.settledSteerPromptUuids.has(uuid)) continue;
|
|
737
|
+
if (echoed.has(uuid)) newlySettled.push(uuid);
|
|
738
|
+
else unsettled.push(uuid);
|
|
739
|
+
}
|
|
740
|
+
const awaitSteer = !input.interruptRequested && unsettled.length > 0 && (input.kind === "abort" || input.kind === "success") && typeof input.queuedTurnCount === "number" && input.queuedTurnCount > 0;
|
|
741
|
+
const completingWithSteers = !awaitSteer && unsettled.length > 0;
|
|
742
|
+
return {
|
|
743
|
+
decision: awaitSteer ? "await-steer" : "complete",
|
|
744
|
+
newlySettled,
|
|
745
|
+
unsettled,
|
|
746
|
+
discardUnsettled: completingWithSteers && (input.interruptRequested || input.kind === "failure"),
|
|
747
|
+
abortedBySteer: completingWithSteers && !input.interruptRequested && input.kind === "abort"
|
|
748
|
+
};
|
|
749
|
+
}
|
|
750
|
+
/**
|
|
751
|
+
* The status a completing turn reports. It follows the result except where the result's status
|
|
752
|
+
* would misstate what happened to the turn: Ryco's own discard re-interrupt or a steer's abort is
|
|
753
|
+
* never a Stop (which would hold the client queue), a Stop always ends as interrupted, and a
|
|
754
|
+
* failure that drops a pending steer is always reported as one (so the queue holds and the user
|
|
755
|
+
* sees why the steer got no reply).
|
|
756
|
+
*/
|
|
757
|
+
function decideClaudeTurnClose(input) {
|
|
758
|
+
if (input.foldedIntoDiscardedCliTurn) return input.interruptRequested ? {
|
|
759
|
+
status: "interrupted",
|
|
760
|
+
cause: "stopped"
|
|
761
|
+
} : {
|
|
762
|
+
status: "failed",
|
|
763
|
+
cause: "folded-into-discarded-cli-turn"
|
|
764
|
+
};
|
|
765
|
+
if (input.resultStatus === "completed") {
|
|
766
|
+
const endsSteerSegment = input.echoedPromptUuids.some((uuid) => input.steerPromptUuids.has(uuid)) && (input.promptUuid === void 0 || !input.echoedPromptUuids.includes(input.promptUuid));
|
|
767
|
+
if (input.interruptRequested && endsSteerSegment) return {
|
|
768
|
+
status: "interrupted",
|
|
769
|
+
cause: "stopped"
|
|
770
|
+
};
|
|
771
|
+
if (!input.interruptRequested && input.decision.discardUnsettled) return {
|
|
772
|
+
status: "failed",
|
|
773
|
+
cause: "failed-segment-dropped-steers"
|
|
774
|
+
};
|
|
775
|
+
}
|
|
776
|
+
if (input.decision.abortedBySteer) return {
|
|
777
|
+
status: "completed",
|
|
778
|
+
cause: "aborted-by-steer"
|
|
779
|
+
};
|
|
780
|
+
return {
|
|
781
|
+
status: input.resultStatus,
|
|
782
|
+
cause: "result"
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
/** Defensive: anything but a `still_queued` string array is "no receipt" (older CLIs). */
|
|
786
|
+
function readClaudeInterruptReceipt(value) {
|
|
787
|
+
if (value === null || typeof value !== "object") return void 0;
|
|
788
|
+
const stillQueued = readStringArray(Reflect.get(value, "still_queued"));
|
|
789
|
+
if (stillQueued === void 0) return void 0;
|
|
790
|
+
return {
|
|
791
|
+
stillQueued,
|
|
792
|
+
cancelled: readStringArray(Reflect.get(value, "cancelled"))
|
|
793
|
+
};
|
|
794
|
+
}
|
|
795
|
+
/**
|
|
796
|
+
* Stop with steers pending. A steer that already streamed into the turn, or that the receipt
|
|
797
|
+
* does not list as queued or cancelled (in transit), counts as running, so its own aborted
|
|
798
|
+
* result closes the turn. The discard and release lists hold whether or not the stopped turn is
|
|
799
|
+
* still open.
|
|
800
|
+
*/
|
|
801
|
+
function decideClaudeStop(input) {
|
|
802
|
+
if (input.receipt === void 0) return {
|
|
803
|
+
forceClose: input.awaitingSteerContinuation,
|
|
804
|
+
discard: [...input.unsettledSteers],
|
|
805
|
+
release: []
|
|
806
|
+
};
|
|
807
|
+
const cancelled = new Set(input.receipt.cancelled ?? []);
|
|
808
|
+
const outstanding = /* @__PURE__ */ new Set([...input.receipt.stillQueued, ...cancelled]);
|
|
809
|
+
const runningSteers = input.unsettledSteers.filter((uuid) => input.startedSteers.has(uuid) || !outstanding.has(uuid));
|
|
810
|
+
const isReleased = (uuid) => cancelled.has(uuid) && !input.startedSteers.has(uuid);
|
|
811
|
+
return {
|
|
812
|
+
forceClose: (input.sealedSegmentCount > 0 || input.promptUuid !== void 0 && cancelled.has(input.promptUuid)) && runningSteers.length === 0,
|
|
813
|
+
discard: input.unsettledSteers.filter((uuid) => !isReleased(uuid)),
|
|
814
|
+
release: input.unsettledSteers.filter(isReleased)
|
|
815
|
+
};
|
|
816
|
+
}
|
|
817
|
+
/** FIFO-bounded insert. */
|
|
818
|
+
function rememberDiscardedSteer(set, uuid, cap = 64) {
|
|
819
|
+
if (set.has(uuid)) return;
|
|
820
|
+
while (set.size >= cap) {
|
|
821
|
+
const oldest = set.values().next();
|
|
822
|
+
if (oldest.done) break;
|
|
823
|
+
set.delete(oldest.value);
|
|
824
|
+
}
|
|
825
|
+
set.add(uuid);
|
|
826
|
+
}
|
|
827
|
+
/** Capabilities a CLI advertises on `system/init`; empty when the field is absent. */
|
|
828
|
+
function parseClaudeCliCapabilities(initMessage) {
|
|
829
|
+
const capabilities = Reflect.get(initMessage, "capabilities");
|
|
830
|
+
return new Set(Array.isArray(capabilities) ? capabilities.filter((entry) => typeof entry === "string") : []);
|
|
831
|
+
}
|
|
832
|
+
/**
|
|
833
|
+
* Root model-turn content frames: a CLI segment's output, as opposed to system, subagent or
|
|
834
|
+
* keep-alive frames. A CLI turn's first such frame carries its echo: a stream event, or the
|
|
835
|
+
* assistant message when nothing streamed. System frames (`api_retry`, compaction) carry no
|
|
836
|
+
* echo, so they never qualify.
|
|
837
|
+
*/
|
|
838
|
+
function isClaudeRootTurnFrame(message) {
|
|
839
|
+
if (message.type !== "stream_event" && message.type !== "assistant" && message.type !== "user") return false;
|
|
840
|
+
if (message.type === "stream_event") {
|
|
841
|
+
const event = Reflect.get(message, "event");
|
|
842
|
+
if (typeof event === "object" && event !== null && Reflect.get(event, "type") === "ping") return false;
|
|
843
|
+
}
|
|
844
|
+
return isRootFrame$1(message);
|
|
845
|
+
}
|
|
846
|
+
/**
|
|
847
|
+
* A synthetic API-error reply: the request failed after its retries and the CLI turn ends with
|
|
848
|
+
* the next result, so interrupting it again could only reach whatever the CLI runs next.
|
|
849
|
+
* `max_output_tokens` is excluded because the CLI can continue that turn.
|
|
850
|
+
*/
|
|
851
|
+
function isClaudeApiErrorReply(message) {
|
|
852
|
+
if (message.type !== "assistant") return false;
|
|
853
|
+
const error = Reflect.get(message, "error");
|
|
854
|
+
return typeof error === "string" && error !== "max_output_tokens";
|
|
855
|
+
}
|
|
856
|
+
//#endregion
|
|
857
|
+
//#region src/provider/claudeWakeTurn.ts
|
|
858
|
+
/**
|
|
859
|
+
* Claude can start a turn without a prompt (a "wake"): background work finished, a schedule or
|
|
860
|
+
* monitor fired, a rate limit lifted. These rules decide when such a provider turn opens and
|
|
861
|
+
* which frames prove it is alive.
|
|
862
|
+
*/
|
|
863
|
+
/** Longest a wake-signal turn may stay open without any root output before it is aborted. */
|
|
864
|
+
const CLAUDE_WAKE_TURN_FIRST_OUTPUT_TIMEOUT_MS = 12e4;
|
|
865
|
+
/** How long Stop waits for the CLI to end a provider turn before finishing it locally. */
|
|
866
|
+
const CLAUDE_PROVIDER_TURN_STOP_GRACE_MS = 5e3;
|
|
867
|
+
function isRootFrame(message) {
|
|
868
|
+
const parentToolUseId = message.parent_tool_use_id;
|
|
869
|
+
return parentToolUseId === null || parentToolUseId === void 0;
|
|
870
|
+
}
|
|
871
|
+
/**
|
|
872
|
+
* Root system/status (requesting|compacting) → "status"; root system/init → "init"; else
|
|
873
|
+
* undefined. A frame with a non-null parent_tool_use_id is never a signal.
|
|
874
|
+
*/
|
|
875
|
+
function claudeWakeSignal(message) {
|
|
876
|
+
if (message.type !== "system" || !isRootFrame(message)) return;
|
|
877
|
+
if (message.subtype === "status") return message.status === "requesting" || message.status === "compacting" ? "status" : void 0;
|
|
878
|
+
return message.subtype === "init" ? "init" : void 0;
|
|
879
|
+
}
|
|
880
|
+
/**
|
|
881
|
+
* Deny-list gate; "init" opens only when the CLI was never seen to emit `status: requesting`
|
|
882
|
+
* (legacy CLIs). There is deliberately no allow list: every kind of wake is covered.
|
|
883
|
+
*/
|
|
884
|
+
function shouldOpenClaudeWakeTurn(gate) {
|
|
885
|
+
if (gate.hasOpenTurn || gate.sessionStopped || !gate.promptSent || gate.turnInstallsInFlight > 0) return false;
|
|
886
|
+
return gate.signal === "status" || !gate.requestingStatusObserved;
|
|
887
|
+
}
|
|
888
|
+
/**
|
|
889
|
+
* Root frames that prove Claude is producing the current turn (watchdog liveness). A positive
|
|
890
|
+
* list, so a future periodic background frame cannot keep a phantom turn alive.
|
|
891
|
+
*/
|
|
892
|
+
function isClaudeRootTurnOutput(message) {
|
|
893
|
+
if (!isRootFrame(message)) return false;
|
|
894
|
+
switch (message.type) {
|
|
895
|
+
case "stream_event":
|
|
896
|
+
case "assistant":
|
|
897
|
+
case "user":
|
|
898
|
+
case "result": return true;
|
|
899
|
+
case "system": switch (message.subtype) {
|
|
900
|
+
case "compact_boundary":
|
|
901
|
+
case "api_retry": return true;
|
|
902
|
+
case "status": return message.status === "compacting";
|
|
903
|
+
default: return false;
|
|
904
|
+
}
|
|
905
|
+
default: return false;
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
//#endregion
|
|
636
909
|
//#region ../../packages/shared/src/cliArgs.ts
|
|
637
910
|
/**
|
|
638
911
|
* Parse CLI-style arguments into flags and positionals.
|
|
@@ -768,6 +1041,70 @@ function disableContextCompaction(state, generation) {
|
|
|
768
1041
|
};
|
|
769
1042
|
}
|
|
770
1043
|
//#endregion
|
|
1044
|
+
//#region src/provider/Layers/claudeUsageLimits.ts
|
|
1045
|
+
const CLAUDE_USAGE_LIMIT_FALLBACK_MESSAGE = "Claude usage limit reached.";
|
|
1046
|
+
const MESSAGE_MAX_LENGTH = 500;
|
|
1047
|
+
function resetIso(resetsAtSeconds) {
|
|
1048
|
+
if (resetsAtSeconds === void 0 || !Number.isFinite(resetsAtSeconds)) return null;
|
|
1049
|
+
const ms = resetsAtSeconds * 1e3;
|
|
1050
|
+
return isRepresentableEpochMs(ms) ? new Date(ms).toISOString() : null;
|
|
1051
|
+
}
|
|
1052
|
+
/** Applies one `rate_limit_event` to the session's rejected windows. */
|
|
1053
|
+
function applyClaudeRateLimitInfo(windows, info) {
|
|
1054
|
+
const limitType = info.rateLimitType ?? "unknown";
|
|
1055
|
+
const overageAllowed = info.overageStatus === "allowed" || info.overageStatus === "allowed_warning" || info.isUsingOverage === true || info.overageInUse === true;
|
|
1056
|
+
const blocked = info.status === "rejected" && !overageAllowed;
|
|
1057
|
+
const resetAt = resetIso(info.resetsAt);
|
|
1058
|
+
if (blocked) windows.set(limitType, resetAt);
|
|
1059
|
+
else windows.delete(limitType);
|
|
1060
|
+
return {
|
|
1061
|
+
blocked,
|
|
1062
|
+
key: `${limitType}:${info.resetsAt ?? "unknown"}`,
|
|
1063
|
+
limitType,
|
|
1064
|
+
resetAt
|
|
1065
|
+
};
|
|
1066
|
+
}
|
|
1067
|
+
/** Current state of the rejected windows; windows whose known reset passed are ignored. */
|
|
1068
|
+
function claudeUsageLimitState(windows, nowMs) {
|
|
1069
|
+
return usageLimitStateFromWindows([...windows.values()].map((resetAt) => ({
|
|
1070
|
+
exhausted: true,
|
|
1071
|
+
resetAtMs: resetAt === null ? null : Date.parse(resetAt)
|
|
1072
|
+
})), nowMs);
|
|
1073
|
+
}
|
|
1074
|
+
function trimmed(value) {
|
|
1075
|
+
if (typeof value !== "string") return void 0;
|
|
1076
|
+
const text = value.trim();
|
|
1077
|
+
return text.length > 0 ? text : void 0;
|
|
1078
|
+
}
|
|
1079
|
+
function limitMessage(result) {
|
|
1080
|
+
const message = (result.subtype === "success" ? trimmed(result.result) : trimmed(result.errors?.[0] ?? "")) ?? "Claude usage limit reached.";
|
|
1081
|
+
return message.length > MESSAGE_MAX_LENGTH ? message.slice(0, MESSAGE_MAX_LENGTH) : message;
|
|
1082
|
+
}
|
|
1083
|
+
/**
|
|
1084
|
+
* Whether a turn's result is a usage-limit stop. Only call it for a result that belongs
|
|
1085
|
+
* to an open turn and was not interrupted or cancelled.
|
|
1086
|
+
*/
|
|
1087
|
+
function classifyClaudeUsageLimitResult(input) {
|
|
1088
|
+
const { result } = input;
|
|
1089
|
+
const state = claudeUsageLimitState(input.windows, input.nowMs);
|
|
1090
|
+
const terminalReason = result.terminal_reason;
|
|
1091
|
+
if (terminalReason === "blocking_limit") return {
|
|
1092
|
+
message: limitMessage(result),
|
|
1093
|
+
resetAt: state.resetAt
|
|
1094
|
+
};
|
|
1095
|
+
if (!state.exhausted) return null;
|
|
1096
|
+
if (!(result.subtype !== "success" || result.is_error === true)) return null;
|
|
1097
|
+
if (terminalReason !== void 0 && terminalReason !== null && terminalReason !== "api_error") return null;
|
|
1098
|
+
if (result.subtype === "success") {
|
|
1099
|
+
const status = result.api_error_status;
|
|
1100
|
+
if (status !== void 0 && status !== null && status !== 429) return null;
|
|
1101
|
+
}
|
|
1102
|
+
return {
|
|
1103
|
+
message: limitMessage(result),
|
|
1104
|
+
resetAt: state.resetAt
|
|
1105
|
+
};
|
|
1106
|
+
}
|
|
1107
|
+
//#endregion
|
|
771
1108
|
//#region src/provider/Layers/ClaudeAdapter.ts
|
|
772
1109
|
/**
|
|
773
1110
|
* ClaudeAdapterLive - Scoped live implementation for the Claude Agent provider adapter.
|
|
@@ -778,20 +1115,49 @@ function disableContextCompaction(state, generation) {
|
|
|
778
1115
|
* @module ClaudeAdapterLive
|
|
779
1116
|
*/
|
|
780
1117
|
const PROVIDER = ProviderDriverKind.make("claudeAgent");
|
|
781
|
-
const
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
1118
|
+
const WAKE_NO_OUTPUT_REASON = "Claude started a background turn but produced no output.";
|
|
1119
|
+
const PROVIDER_TURN_STOP_REASON = "Claude did not end the background turn after Stop.";
|
|
1120
|
+
const DISCARDED_STEER_TURN_REASON = "Claude started a turn for a message Stop cancelled.";
|
|
1121
|
+
const FOLDED_INTO_DISCARDED_STEER_REASON = "Claude Code merged this message into a cancelled steer's request, so no reply is shown. Send it again.";
|
|
1122
|
+
const STEER_TURN_ENDED_DETAIL = "The turn finished before this message could be steered. It stays queued and is sent next.";
|
|
1123
|
+
const CLAUDE_TURN_HEADS_CAP = 64;
|
|
1124
|
+
const CLAUDE_REWIND_PROBE_TIMEOUT = "30 seconds";
|
|
1125
|
+
const CLAUDE_REWIND_TRANSCRIPT_TIMEOUT = "10 seconds";
|
|
1126
|
+
const CLAUDE_REWIND_QUERY_EXIT_MS = 5e3;
|
|
1127
|
+
/** The only turn-state constructor: prompt and provider turns must share one shape. */
|
|
1128
|
+
function makeClaudeTurnState(input) {
|
|
1129
|
+
return {
|
|
1130
|
+
turnId: input.turnId,
|
|
1131
|
+
...input.promptUuid !== void 0 ? { promptUuid: input.promptUuid } : {},
|
|
1132
|
+
openedBy: input.openedBy,
|
|
1133
|
+
startedAt: input.startedAt,
|
|
1134
|
+
items: [],
|
|
1135
|
+
assistantTextBlocks: /* @__PURE__ */ new Map(),
|
|
1136
|
+
assistantTextBlockOrder: [],
|
|
1137
|
+
capturedProposedPlanKeys: /* @__PURE__ */ new Set(),
|
|
1138
|
+
nextSyntheticAssistantBlockIndex: -1,
|
|
1139
|
+
reasoningBlocks: /* @__PURE__ */ new Map(),
|
|
1140
|
+
reasoningBlockCount: 0,
|
|
1141
|
+
rootOutputObserved: input.openedBy !== "wake-signal",
|
|
1142
|
+
lastChainUuid: void 0,
|
|
1143
|
+
rootContentObserved: input.openedBy !== "wake-signal",
|
|
1144
|
+
completion: void 0,
|
|
1145
|
+
steerPromptUuids: /* @__PURE__ */ new Set(),
|
|
1146
|
+
settledSteerPromptUuids: /* @__PURE__ */ new Set(),
|
|
1147
|
+
startedSteerPromptUuids: /* @__PURE__ */ new Set(),
|
|
1148
|
+
reinterruptedEchoKeys: /* @__PURE__ */ new Set(),
|
|
1149
|
+
interruptRequested: false,
|
|
1150
|
+
sealedSegmentCount: 0,
|
|
1151
|
+
awaitingSteerContinuation: void 0
|
|
1152
|
+
};
|
|
788
1153
|
}
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
1154
|
+
const CLAUDE_SUBAGENT_ATTRIBUTION_CACHE_CAP = 256;
|
|
1155
|
+
function rememberClaudeSubagentAttribution(cache, toolUseId, value) {
|
|
1156
|
+
if (!cache.has(toolUseId) && cache.size >= CLAUDE_SUBAGENT_ATTRIBUTION_CACHE_CAP) {
|
|
1157
|
+
const oldestToolUseId = cache.keys().next().value;
|
|
1158
|
+
if (oldestToolUseId !== void 0) cache.delete(oldestToolUseId);
|
|
793
1159
|
}
|
|
794
|
-
|
|
1160
|
+
cache.set(toolUseId, value);
|
|
795
1161
|
}
|
|
796
1162
|
function claudeSubagentLaunchModel(input) {
|
|
797
1163
|
const model = trimmedClaudeString(input?.model);
|
|
@@ -811,6 +1177,12 @@ function toMessage(cause, fallback) {
|
|
|
811
1177
|
if (cause instanceof Error && cause.message.length > 0) return cause.message;
|
|
812
1178
|
return fallback;
|
|
813
1179
|
}
|
|
1180
|
+
/** A typed adapter error's user-level text: its `detail` or `issue`, not its prefixed message. */
|
|
1181
|
+
function adapterFailureDetail(error) {
|
|
1182
|
+
const fields = error;
|
|
1183
|
+
for (const value of [fields.detail, fields.issue]) if (typeof value === "string" && value.trim().length > 0) return value.trim();
|
|
1184
|
+
return error.message;
|
|
1185
|
+
}
|
|
814
1186
|
function toError(cause, fallback) {
|
|
815
1187
|
return cause instanceof Error ? cause : new Error(toMessage(cause, fallback));
|
|
816
1188
|
}
|
|
@@ -844,14 +1216,6 @@ function interruptionMessageFromClaudeCause(cause) {
|
|
|
844
1216
|
const message = messageFromClaudeStreamCause(cause, "Claude runtime interrupted.");
|
|
845
1217
|
return isClaudeInterruptedMessage(message) ? "Claude runtime interrupted." : message;
|
|
846
1218
|
}
|
|
847
|
-
function resultErrorsText(result) {
|
|
848
|
-
return "errors" in result && Array.isArray(result.errors) ? result.errors.join(" ").toLowerCase() : "";
|
|
849
|
-
}
|
|
850
|
-
function isInterruptedResult(result) {
|
|
851
|
-
const errors = resultErrorsText(result);
|
|
852
|
-
if (errors.includes("interrupt")) return true;
|
|
853
|
-
return result.subtype === "error_during_execution" && result.is_error === false && (errors.includes("request was aborted") || errors.includes("interrupted by user") || errors.includes("aborted"));
|
|
854
|
-
}
|
|
855
1219
|
function asRuntimeItemId(value) {
|
|
856
1220
|
return RuntimeItemId.make(value);
|
|
857
1221
|
}
|
|
@@ -905,14 +1269,27 @@ function readClaudeResumeState(resumeCursor) {
|
|
|
905
1269
|
const resumeCandidate = typeof cursor.resume === "string" ? cursor.resume : typeof cursor.sessionId === "string" ? cursor.sessionId : void 0;
|
|
906
1270
|
const resume = resumeCandidate && isUuid(resumeCandidate) ? resumeCandidate : void 0;
|
|
907
1271
|
const resumeSessionAt = typeof cursor.resumeSessionAt === "string" ? cursor.resumeSessionAt : void 0;
|
|
1272
|
+
const rewind = resumeCursor.rewind;
|
|
1273
|
+
const rewindAt = rewind !== null && typeof rewind === "object" && typeof rewind.at === "string" && rewind.at.length > 0 ? rewind.at : void 0;
|
|
908
1274
|
const turnCountValue = typeof cursor.turnCount === "number" ? cursor.turnCount : void 0;
|
|
909
1275
|
return {
|
|
910
1276
|
...threadId ? { threadId } : {},
|
|
911
1277
|
...resume ? { resume } : {},
|
|
912
1278
|
...resumeSessionAt ? { resumeSessionAt } : {},
|
|
1279
|
+
...rewindAt ? { rewindAt } : {},
|
|
913
1280
|
...turnCountValue !== void 0 && Number.isInteger(turnCountValue) && turnCountValue >= 0 ? { turnCount: turnCountValue } : {}
|
|
914
1281
|
};
|
|
915
1282
|
}
|
|
1283
|
+
/**
|
|
1284
|
+
* The uuid of a main-chain transcript entry (user, assistant, compaction
|
|
1285
|
+
* boundary), or undefined for subagent sidechains and non-chain frames.
|
|
1286
|
+
*/
|
|
1287
|
+
function claudeMainChainUuid(message) {
|
|
1288
|
+
if (!(message.type === "user" || message.type === "assistant" || message.type === "system" && message.subtype === "compact_boundary")) return void 0;
|
|
1289
|
+
const uuid = message.uuid;
|
|
1290
|
+
const parentToolUseId = message.parent_tool_use_id;
|
|
1291
|
+
return typeof uuid === "string" && uuid.length > 0 && (parentToolUseId === null || parentToolUseId === void 0) ? uuid : void 0;
|
|
1292
|
+
}
|
|
916
1293
|
function trimmedClaudeString(value) {
|
|
917
1294
|
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
918
1295
|
}
|
|
@@ -1161,6 +1538,11 @@ function extractPlanStepsFromTodoInput(input) {
|
|
|
1161
1538
|
}));
|
|
1162
1539
|
}
|
|
1163
1540
|
function summarizeToolRequest(toolName, input) {
|
|
1541
|
+
const htmlRender = resolveHtmlRenderToolPresentation({
|
|
1542
|
+
toolName,
|
|
1543
|
+
input
|
|
1544
|
+
});
|
|
1545
|
+
if (htmlRender) return htmlRender.detail ? `${toolName}: ${htmlRender.detail}` : toolName;
|
|
1164
1546
|
const commandValue = input.command ?? input.cmd;
|
|
1165
1547
|
const command = typeof commandValue === "string" ? commandValue : void 0;
|
|
1166
1548
|
if (command && command.trim().length > 0) return `${toolName}: ${command.trim().slice(0, 400)}`;
|
|
@@ -1174,6 +1556,24 @@ function summarizeToolRequest(toolName, input) {
|
|
|
1174
1556
|
if (serialized.length <= 400) return `${toolName}: ${serialized}`;
|
|
1175
1557
|
return `${toolName}: ${serialized.slice(0, 397)}...`;
|
|
1176
1558
|
}
|
|
1559
|
+
/** Work-log detail of a tool item: an HTML tool shows its page title or viewport alone. */
|
|
1560
|
+
function toolItemDetail(toolName, input) {
|
|
1561
|
+
const htmlRender = resolveHtmlRenderToolPresentation({
|
|
1562
|
+
toolName,
|
|
1563
|
+
input
|
|
1564
|
+
});
|
|
1565
|
+
return htmlRender ? htmlRender.detail : summarizeToolRequest(toolName, input);
|
|
1566
|
+
}
|
|
1567
|
+
function toolItemTitle(toolName, itemType) {
|
|
1568
|
+
return resolveHtmlRenderToolPresentation({
|
|
1569
|
+
toolName,
|
|
1570
|
+
input: void 0
|
|
1571
|
+
})?.title ?? titleForTool(itemType);
|
|
1572
|
+
}
|
|
1573
|
+
/** Tool input as carried on runtime events: an HTML tool's page is reduced to its length. */
|
|
1574
|
+
function toolEventInput(toolName, input) {
|
|
1575
|
+
return resolveHtmlRenderToolKind(toolName) === void 0 ? input : withoutHtmlRenderMarkup(input);
|
|
1576
|
+
}
|
|
1177
1577
|
function titleForTool(itemType) {
|
|
1178
1578
|
switch (itemType) {
|
|
1179
1579
|
case "command_execution": return "Command run";
|
|
@@ -1291,11 +1691,25 @@ const buildUserMessageEffect = Effect.fn("buildUserMessageEffect")(function* (in
|
|
|
1291
1691
|
});
|
|
1292
1692
|
function turnStatusFromResult(result) {
|
|
1293
1693
|
if (result.subtype === "success") return "completed";
|
|
1694
|
+
if (isClaudeAbortTerminalReason(result)) return "interrupted";
|
|
1294
1695
|
const errors = resultErrorsText(result);
|
|
1295
1696
|
if (isInterruptedResult(result)) return "interrupted";
|
|
1296
1697
|
if (errors.includes("cancel")) return "cancelled";
|
|
1297
1698
|
return "failed";
|
|
1298
1699
|
}
|
|
1700
|
+
/** The error a completing turn reports, by why it reports its status (`decideClaudeTurnClose`). */
|
|
1701
|
+
function claudeTurnCloseErrorMessage(cause, result) {
|
|
1702
|
+
switch (cause) {
|
|
1703
|
+
case "result": return result.subtype === "success" ? void 0 : result.errors[0];
|
|
1704
|
+
case "aborted-by-steer": return;
|
|
1705
|
+
case "stopped": return "Interrupted by user.";
|
|
1706
|
+
case "failed-segment-dropped-steers": {
|
|
1707
|
+
const text = result.subtype === "success" ? result.result.trim() : result.errors[0];
|
|
1708
|
+
return text !== void 0 && text.length > 0 ? text : "Claude turn failed.";
|
|
1709
|
+
}
|
|
1710
|
+
case "folded-into-discarded-cli-turn": return FOLDED_INTO_DISCARDED_STEER_REASON;
|
|
1711
|
+
}
|
|
1712
|
+
}
|
|
1299
1713
|
function streamKindFromDeltaType(deltaType) {
|
|
1300
1714
|
return deltaType.includes("thinking") ? "reasoning_text" : "assistant_text";
|
|
1301
1715
|
}
|
|
@@ -1336,6 +1750,35 @@ function extractExitPlanModePlan(value) {
|
|
|
1336
1750
|
function exitPlanCaptureKey(input) {
|
|
1337
1751
|
return input.toolUseId && input.toolUseId.length > 0 ? `tool:${input.toolUseId}` : `plan:${input.planMarkdown}`;
|
|
1338
1752
|
}
|
|
1753
|
+
const EMPTY_STREAMED_JSON_SCAN = {
|
|
1754
|
+
depth: 0,
|
|
1755
|
+
inString: false,
|
|
1756
|
+
escaped: false,
|
|
1757
|
+
opened: false
|
|
1758
|
+
};
|
|
1759
|
+
function scanStreamedJson(scan, chunk) {
|
|
1760
|
+
let { depth, inString, escaped, opened } = scan;
|
|
1761
|
+
for (let index = 0; index < chunk.length; index += 1) {
|
|
1762
|
+
const code = chunk.charCodeAt(index);
|
|
1763
|
+
if (inString) {
|
|
1764
|
+
if (escaped) escaped = false;
|
|
1765
|
+
else if (code === 92) escaped = true;
|
|
1766
|
+
else if (code === 34) inString = false;
|
|
1767
|
+
} else if (code === 34) inString = true;
|
|
1768
|
+
else if (code === 123 || code === 91) {
|
|
1769
|
+
depth += 1;
|
|
1770
|
+
opened = true;
|
|
1771
|
+
} else if (code === 125 || code === 93) depth -= 1;
|
|
1772
|
+
}
|
|
1773
|
+
return {
|
|
1774
|
+
depth,
|
|
1775
|
+
inString,
|
|
1776
|
+
escaped,
|
|
1777
|
+
opened
|
|
1778
|
+
};
|
|
1779
|
+
}
|
|
1780
|
+
/** Every complete JSON object passes this, so skipping the parse otherwise changes nothing. */
|
|
1781
|
+
const mayBeCompleteJson = (scan) => scan.opened && scan.depth === 0 && !scan.inString;
|
|
1339
1782
|
function tryParseJsonRecord(value) {
|
|
1340
1783
|
try {
|
|
1341
1784
|
const parsed = JSON.parse(value);
|
|
@@ -1443,13 +1886,19 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
1443
1886
|
const serverConfig = yield* ServerConfig;
|
|
1444
1887
|
const claudeEnvironment = yield* makeClaudeEnvironment(claudeSettings, options?.environment).pipe(Effect.provideService(Path.Path, path));
|
|
1445
1888
|
const nativeEventLogger = options?.nativeEventLogger ?? (options?.nativeEventLogPath !== void 0 ? yield* makeEventNdjsonLogger(options.nativeEventLogPath, { stream: "native" }) : void 0);
|
|
1889
|
+
const readSessionMessages = options?.readSessionMessages ?? ((sessionId, readOptions) => getSessionMessages(sessionId, {
|
|
1890
|
+
...readOptions.dir !== void 0 ? { dir: readOptions.dir } : {},
|
|
1891
|
+
includeSystemMessages: readOptions.includeSystemMessages
|
|
1892
|
+
}));
|
|
1893
|
+
/** Threads whose session is being closed and reopened by a checkpoint revert. */
|
|
1894
|
+
const rewindingThreads = /* @__PURE__ */ new Set();
|
|
1446
1895
|
const createQuery = options?.createQuery ?? ((input) => query({
|
|
1447
1896
|
prompt: input.prompt,
|
|
1448
1897
|
options: input.options
|
|
1449
1898
|
}));
|
|
1450
1899
|
const sessions = /* @__PURE__ */ new Map();
|
|
1451
1900
|
let nextSessionGeneration = 0;
|
|
1452
|
-
const runtimeEventQueue = yield* Queue.bounded(2048);
|
|
1901
|
+
const runtimeEventQueue = yield* Queue.bounded(options?.runtimeEventQueueCapacity ?? 2048);
|
|
1453
1902
|
const runtimeEventQueueMetrics = yield* makeServerQueueMetrics({
|
|
1454
1903
|
queue: "provider.adapter.runtimeEvents",
|
|
1455
1904
|
component: "ClaudeAdapter",
|
|
@@ -1591,18 +2040,19 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
1591
2040
|
};
|
|
1592
2041
|
});
|
|
1593
2042
|
const updateResumeCursor = Effect.fn("updateResumeCursor")(function* (context) {
|
|
1594
|
-
|
|
1595
|
-
|
|
2043
|
+
if (!context.session.threadId) return;
|
|
2044
|
+
const updatedAt = yield* nowIso;
|
|
1596
2045
|
const resumeCursor = {
|
|
1597
|
-
threadId,
|
|
2046
|
+
threadId: context.session.threadId,
|
|
1598
2047
|
...context.resumeSessionId ? { resume: context.resumeSessionId } : {},
|
|
1599
2048
|
...context.lastAssistantUuid ? { resumeSessionAt: context.lastAssistantUuid } : {},
|
|
2049
|
+
...context.pendingRewind ? { rewind: { at: context.pendingRewind.at } } : {},
|
|
1600
2050
|
turnCount: context.turns.length
|
|
1601
2051
|
};
|
|
1602
2052
|
context.session = {
|
|
1603
2053
|
...context.session,
|
|
1604
2054
|
resumeCursor,
|
|
1605
|
-
updatedAt
|
|
2055
|
+
updatedAt
|
|
1606
2056
|
};
|
|
1607
2057
|
});
|
|
1608
2058
|
const ensureAssistantTextBlock = Effect.fn("ensureAssistantTextBlock")(function* (context, blockIndex, options) {
|
|
@@ -1741,7 +2191,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
1741
2191
|
});
|
|
1742
2192
|
}
|
|
1743
2193
|
});
|
|
1744
|
-
const emitRuntimeError = Effect.fn("emitRuntimeError")(function* (context, message, cause) {
|
|
2194
|
+
const emitRuntimeError = Effect.fn("emitRuntimeError")(function* (context, message, cause, options) {
|
|
1745
2195
|
if (cause !== void 0) {}
|
|
1746
2196
|
const turnState = context.turnState;
|
|
1747
2197
|
const stamp = yield* makeEventStamp();
|
|
@@ -1754,8 +2204,9 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
1754
2204
|
...turnState ? { turnId: asCanonicalTurnId(turnState.turnId) } : {},
|
|
1755
2205
|
payload: {
|
|
1756
2206
|
message,
|
|
1757
|
-
class: "provider_error",
|
|
1758
|
-
...cause !== void 0 ? { detail: cause } : {}
|
|
2207
|
+
class: options?.class ?? "provider_error",
|
|
2208
|
+
...cause !== void 0 ? { detail: cause } : {},
|
|
2209
|
+
...options?.resetAt !== void 0 ? { resetAt: options.resetAt } : {}
|
|
1759
2210
|
},
|
|
1760
2211
|
providerRefs: nativeProviderRefs(context)
|
|
1761
2212
|
});
|
|
@@ -1838,7 +2289,8 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
1838
2289
|
yield* emitCompactionUnavailableWarning(context);
|
|
1839
2290
|
}
|
|
1840
2291
|
});
|
|
1841
|
-
|
|
2292
|
+
/** The context gauge a result (or a local close without one) publishes. */
|
|
2293
|
+
const resolveResultUsageSnapshot = Effect.fn("resolveResultUsageSnapshot")(function* (context, result) {
|
|
1842
2294
|
const resultCounts = readClaudeCacheCounts(result?.usage);
|
|
1843
2295
|
if (context.cacheObservation && resultCounts?.outputTokens !== void 0) context.cacheObservation = {
|
|
1844
2296
|
...context.cacheObservation,
|
|
@@ -1852,41 +2304,46 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
1852
2304
|
const resultContextWindow = mainClaudeContextWindowFromModelUsage(result?.modelUsage, context.cacheObservation?.model ?? context.currentApiModelId);
|
|
1853
2305
|
if (resultContextWindow !== void 0) context.lastKnownContextWindow = resultContextWindow;
|
|
1854
2306
|
const accumulatedSnapshot = normalizeClaudeTokenUsage(result?.usage, resultContextWindow ?? context.lastKnownContextWindow);
|
|
1855
|
-
const
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
const usageSnapshot = rawUsageSnapshot ? withAutomaticCompactionCapability({
|
|
2307
|
+
const rawUsageSnapshot = selectClaudeResultUsageGauge({
|
|
2308
|
+
lastGauge: context.lastKnownTokenUsage,
|
|
2309
|
+
cumulative: accumulatedSnapshot,
|
|
2310
|
+
maxTokens: resultContextWindow ?? context.lastKnownContextWindow,
|
|
2311
|
+
cumulativeIsGauge: !context.cumulativeUsageSpansCompaction
|
|
2312
|
+
});
|
|
2313
|
+
if (result !== void 0) context.cumulativeUsageSpansCompaction = false;
|
|
2314
|
+
return rawUsageSnapshot ? withAutomaticCompactionCapability({
|
|
1864
2315
|
...rawUsageSnapshot,
|
|
2316
|
+
...accumulatedSnapshot ? { processedUsage: {
|
|
2317
|
+
scope: "turn",
|
|
2318
|
+
inputTokens: accumulatedSnapshot.inputTokens ?? 0,
|
|
2319
|
+
cachedInputTokens: accumulatedSnapshot.cachedInputTokens ?? 0,
|
|
2320
|
+
outputTokens: accumulatedSnapshot.outputTokens ?? 0,
|
|
2321
|
+
reasoningOutputTokens: accumulatedSnapshot.reasoningOutputTokens ?? 0,
|
|
2322
|
+
totalTokens: accumulatedSnapshot.totalProcessedTokens ?? accumulatedSnapshot.usedTokens
|
|
2323
|
+
} } : {},
|
|
1865
2324
|
...context.cacheObservation ? { claudeCache: context.cacheObservation } : {}
|
|
1866
2325
|
}, context.supportsAutomaticCompaction) : void 0;
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
return;
|
|
1889
|
-
}
|
|
2326
|
+
});
|
|
2327
|
+
/** Publishes a context-gauge snapshot, attributed to a turn when one is given. */
|
|
2328
|
+
const emitTokenUsageSnapshot = Effect.fn("emitTokenUsageSnapshot")(function* (context, usageSnapshot, turnId) {
|
|
2329
|
+
if (!usageSnapshot) return;
|
|
2330
|
+
const usageStamp = yield* makeEventStamp();
|
|
2331
|
+
yield* offerRuntimeEventForContext(context, {
|
|
2332
|
+
type: "thread.token-usage.updated",
|
|
2333
|
+
eventId: usageStamp.eventId,
|
|
2334
|
+
provider: PROVIDER,
|
|
2335
|
+
createdAt: usageStamp.createdAt,
|
|
2336
|
+
threadId: context.session.threadId,
|
|
2337
|
+
...turnId !== void 0 ? { turnId } : {},
|
|
2338
|
+
payload: { usage: usageSnapshot },
|
|
2339
|
+
providerRefs: nativeProviderRefs(context)
|
|
2340
|
+
});
|
|
2341
|
+
});
|
|
2342
|
+
/**
|
|
2343
|
+
* Closes everything a CLI segment left open (in-flight tools, assistant text and reasoning
|
|
2344
|
+
* blocks) while the turn itself may stay open: between a steer's segments and at completion.
|
|
2345
|
+
*/
|
|
2346
|
+
const sealTurnSegment = Effect.fn("sealTurnSegment")(function* (context, turnState, status, result) {
|
|
1890
2347
|
for (const [index, tool] of context.inFlightTools.entries()) {
|
|
1891
2348
|
const toolStamp = yield* makeEventStamp();
|
|
1892
2349
|
yield* offerRuntimeEventForContext(context, {
|
|
@@ -1904,7 +2361,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
1904
2361
|
...tool.detail ? { detail: tool.detail } : {},
|
|
1905
2362
|
data: {
|
|
1906
2363
|
toolName: tool.toolName,
|
|
1907
|
-
input: tool.input
|
|
2364
|
+
input: toolEventInput(tool.toolName, tool.input)
|
|
1908
2365
|
}
|
|
1909
2366
|
},
|
|
1910
2367
|
providerRefs: nativeProviderRefs(context, { providerItemId: tool.itemId }),
|
|
@@ -1923,25 +2380,73 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
1923
2380
|
rawMethod: "claude/result",
|
|
1924
2381
|
rawPayload: result ?? { status }
|
|
1925
2382
|
});
|
|
2383
|
+
turnState.assistantTextBlockOrder.length = 0;
|
|
2384
|
+
for (const reasoningBlock of turnState.reasoningBlocks.values()) {
|
|
2385
|
+
const stamp = yield* makeEventStamp();
|
|
2386
|
+
yield* offerRuntimeEventForContext(context, {
|
|
2387
|
+
type: "item.completed",
|
|
2388
|
+
eventId: stamp.eventId,
|
|
2389
|
+
provider: PROVIDER,
|
|
2390
|
+
createdAt: stamp.createdAt,
|
|
2391
|
+
threadId: context.session.threadId,
|
|
2392
|
+
turnId: asCanonicalTurnId(turnState.turnId),
|
|
2393
|
+
itemId: asRuntimeItemId(reasoningBlock.itemId),
|
|
2394
|
+
payload: {
|
|
2395
|
+
itemType: "reasoning",
|
|
2396
|
+
status: status === "failed" ? "failed" : "completed",
|
|
2397
|
+
title: "Reasoning"
|
|
2398
|
+
},
|
|
2399
|
+
providerRefs: nativeProviderRefs(context),
|
|
2400
|
+
raw: {
|
|
2401
|
+
source: "claude.sdk.message",
|
|
2402
|
+
method: "claude/result",
|
|
2403
|
+
payload: result ?? { status }
|
|
2404
|
+
}
|
|
2405
|
+
});
|
|
2406
|
+
}
|
|
2407
|
+
turnState.reasoningBlocks.clear();
|
|
2408
|
+
});
|
|
2409
|
+
/** A result (or local close) with no open turn: keep usage, never publish a lifecycle event. */
|
|
2410
|
+
const publishTurnlessResult = Effect.fn("publishTurnlessResult")(function* (context, status, errorMessage, result) {
|
|
2411
|
+
yield* emitTokenUsageSnapshot(context, yield* resolveResultUsageSnapshot(context, result), void 0);
|
|
2412
|
+
yield* Effect.logInfo("claude.turn.result-without-active-turn", {
|
|
2413
|
+
threadId: context.session.threadId,
|
|
2414
|
+
status,
|
|
2415
|
+
numTurns: result?.num_turns,
|
|
2416
|
+
hasUsage: result?.usage !== void 0,
|
|
2417
|
+
...errorMessage ? { errorMessage } : {}
|
|
2418
|
+
});
|
|
2419
|
+
});
|
|
2420
|
+
/** Finishes a turn this fiber claimed in `completeTurn`. Never call it directly. */
|
|
2421
|
+
const finishClaimedTurn = Effect.fn("finishClaimedTurn")(function* (context, turnState, completion, status, errorMessage, result, options) {
|
|
2422
|
+
const usageSnapshot = yield* resolveResultUsageSnapshot(context, result);
|
|
2423
|
+
yield* sealTurnSegment(context, turnState, status, result);
|
|
1926
2424
|
context.turns.push({
|
|
1927
2425
|
id: turnState.turnId,
|
|
1928
2426
|
items: [...turnState.items]
|
|
1929
2427
|
});
|
|
1930
|
-
if (
|
|
1931
|
-
|
|
1932
|
-
yield* offerRuntimeEventForContext(context, {
|
|
1933
|
-
type: "thread.token-usage.updated",
|
|
1934
|
-
eventId: usageStamp.eventId,
|
|
1935
|
-
provider: PROVIDER,
|
|
1936
|
-
createdAt: usageStamp.createdAt,
|
|
1937
|
-
threadId: context.session.threadId,
|
|
2428
|
+
if (turnState.lastChainUuid !== void 0) {
|
|
2429
|
+
context.turnHeads.push({
|
|
1938
2430
|
turnId: turnState.turnId,
|
|
1939
|
-
|
|
1940
|
-
providerRefs: nativeProviderRefs(context)
|
|
2431
|
+
head: turnState.lastChainUuid
|
|
1941
2432
|
});
|
|
2433
|
+
if (context.turnHeads.length > CLAUDE_TURN_HEADS_CAP) context.turnHeads.shift();
|
|
1942
2434
|
}
|
|
2435
|
+
if (status === "completed") context.pendingRewind = void 0;
|
|
2436
|
+
yield* updateResumeCursor(context);
|
|
2437
|
+
yield* emitTokenUsageSnapshot(context, usageSnapshot, turnState.turnId);
|
|
1943
2438
|
const stamp = yield* makeEventStamp();
|
|
1944
|
-
yield* offerRuntimeEventForContext(context, {
|
|
2439
|
+
if (options?.abortReason !== void 0) yield* offerRuntimeEventForContext(context, {
|
|
2440
|
+
type: "turn.aborted",
|
|
2441
|
+
eventId: stamp.eventId,
|
|
2442
|
+
provider: PROVIDER,
|
|
2443
|
+
createdAt: stamp.createdAt,
|
|
2444
|
+
threadId: context.session.threadId,
|
|
2445
|
+
turnId: turnState.turnId,
|
|
2446
|
+
payload: { reason: options.abortReason },
|
|
2447
|
+
providerRefs: nativeProviderRefs(context)
|
|
2448
|
+
});
|
|
2449
|
+
else yield* offerRuntimeEventForContext(context, {
|
|
1945
2450
|
type: "turn.completed",
|
|
1946
2451
|
eventId: stamp.eventId,
|
|
1947
2452
|
provider: PROVIDER,
|
|
@@ -1959,18 +2464,45 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
1959
2464
|
providerRefs: nativeProviderRefs(context)
|
|
1960
2465
|
});
|
|
1961
2466
|
const updatedAt = yield* nowIso;
|
|
1962
|
-
context.turnState
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
2467
|
+
if (context.turnState === turnState) {
|
|
2468
|
+
context.turnState = void 0;
|
|
2469
|
+
context.session = {
|
|
2470
|
+
...context.session,
|
|
2471
|
+
status: "ready",
|
|
2472
|
+
activeTurnId: void 0,
|
|
2473
|
+
updatedAt,
|
|
2474
|
+
...status === "failed" && errorMessage ? { lastError: errorMessage } : {}
|
|
2475
|
+
};
|
|
2476
|
+
}
|
|
2477
|
+
Deferred.doneUnsafe(completion, Effect.void);
|
|
1970
2478
|
if (context.agentControl) yield* context.agentControl.retireTurn(turnState.turnId);
|
|
1971
|
-
yield* updateResumeCursor(context);
|
|
1972
2479
|
if (status === "completed" && usageSnapshot) yield* maybeEnableAutomaticCompaction(context, usageSnapshot);
|
|
1973
2480
|
});
|
|
2481
|
+
/**
|
|
2482
|
+
* The single owner of turn completion. The open turn is claimed synchronously at entry, so a
|
|
2483
|
+
* concurrent close (sendTurn, Stop grace, watchdog, stream exit) waits for the claimer instead
|
|
2484
|
+
* of emitting a second lifecycle event.
|
|
2485
|
+
*/
|
|
2486
|
+
const completeTurn = Effect.fn("completeTurn")(function* (context, status, errorMessage, result, options) {
|
|
2487
|
+
const turnState = context.turnState;
|
|
2488
|
+
if (options?.expectedTurnState !== void 0 && turnState !== options.expectedTurnState) return;
|
|
2489
|
+
if (turnState?.completion !== void 0) {
|
|
2490
|
+
if (result !== void 0) yield* Effect.logInfo("claude.turn.result-during-completion", {
|
|
2491
|
+
threadId: context.session.threadId,
|
|
2492
|
+
turnId: turnState.turnId,
|
|
2493
|
+
status
|
|
2494
|
+
});
|
|
2495
|
+
yield* Deferred.await(turnState.completion);
|
|
2496
|
+
return;
|
|
2497
|
+
}
|
|
2498
|
+
if (turnState === void 0) return yield* publishTurnlessResult(context, status, errorMessage, result);
|
|
2499
|
+
const completion = Deferred.makeUnsafe();
|
|
2500
|
+
turnState.completion = completion;
|
|
2501
|
+
yield* finishClaimedTurn(context, turnState, completion, status, errorMessage, result, options).pipe(Effect.ensuring(Effect.sync(() => {
|
|
2502
|
+
if (context.turnState === turnState) turnState.completion = void 0;
|
|
2503
|
+
Deferred.doneUnsafe(completion, Effect.void);
|
|
2504
|
+
})));
|
|
2505
|
+
});
|
|
1974
2506
|
const handleStreamEvent = Effect.fn("handleStreamEvent")(function* (context, message) {
|
|
1975
2507
|
if (message.type !== "stream_event") return;
|
|
1976
2508
|
const { event } = message;
|
|
@@ -1999,10 +2531,8 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
1999
2531
|
const deltaText = event.delta.type === "text_delta" ? event.delta.text : typeof event.delta.thinking === "string" ? event.delta.thinking : "";
|
|
2000
2532
|
if (deltaText.length === 0) return;
|
|
2001
2533
|
const streamKind = streamKindFromDeltaType(event.delta.type);
|
|
2002
|
-
const
|
|
2003
|
-
|
|
2004
|
-
block: context.turnState.assistantTextBlocks.get(event.index)
|
|
2005
|
-
} : void 0;
|
|
2534
|
+
const reasoningBlock = event.delta.type === "thinking_delta" ? context.turnState.reasoningBlocks.get(event.index) : void 0;
|
|
2535
|
+
const assistantBlockEntry = event.delta.type === "text_delta" ? yield* ensureAssistantTextBlock(context, event.index) : void 0;
|
|
2006
2536
|
if (assistantBlockEntry?.block && event.delta.type === "text_delta") assistantBlockEntry.block.emittedTextDelta = true;
|
|
2007
2537
|
const stamp = yield* makeEventStamp();
|
|
2008
2538
|
yield* offerRuntimeEventForContext(context, {
|
|
@@ -2012,7 +2542,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
2012
2542
|
createdAt: stamp.createdAt,
|
|
2013
2543
|
threadId: context.session.threadId,
|
|
2014
2544
|
turnId: context.turnState.turnId,
|
|
2015
|
-
...assistantBlockEntry?.block ? { itemId: asRuntimeItemId(assistantBlockEntry.block.itemId) } : {},
|
|
2545
|
+
...assistantBlockEntry?.block ? { itemId: asRuntimeItemId(assistantBlockEntry.block.itemId) } : reasoningBlock ? { itemId: asRuntimeItemId(reasoningBlock.itemId) } : {},
|
|
2016
2546
|
payload: {
|
|
2017
2547
|
streamKind,
|
|
2018
2548
|
delta: deltaText
|
|
@@ -2030,17 +2560,19 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
2030
2560
|
const tool = context.inFlightTools.get(event.index);
|
|
2031
2561
|
if (!tool || typeof event.delta.partial_json !== "string") return;
|
|
2032
2562
|
const partialInputJson = tool.partialInputJson + event.delta.partial_json;
|
|
2033
|
-
const
|
|
2034
|
-
const
|
|
2563
|
+
const partialInputScan = scanStreamedJson(tool.partialInputScan, event.delta.partial_json);
|
|
2564
|
+
const parsedInput = mayBeCompleteJson(partialInputScan) ? tryParseJsonRecord(partialInputJson) : void 0;
|
|
2565
|
+
const detail = parsedInput ? toolItemDetail(tool.toolName, parsedInput) : tool.detail;
|
|
2035
2566
|
let nextTool = {
|
|
2036
2567
|
...tool,
|
|
2037
2568
|
partialInputJson,
|
|
2569
|
+
partialInputScan,
|
|
2038
2570
|
...parsedInput ? { input: parsedInput } : {},
|
|
2039
2571
|
...detail ? { detail } : {}
|
|
2040
2572
|
};
|
|
2041
2573
|
const nextFingerprint = parsedInput && Object.keys(parsedInput).length > 0 ? toolInputFingerprint(parsedInput) : void 0;
|
|
2042
2574
|
context.inFlightTools.set(event.index, nextTool);
|
|
2043
|
-
if (nextTool.itemType === "collab_agent_tool_call" && parsedInput)
|
|
2575
|
+
if (nextTool.itemType === "collab_agent_tool_call" && parsedInput) rememberClaudeSubagentAttribution(context.subagentLaunchInputByToolUseId, nextTool.itemId, parsedInput);
|
|
2044
2576
|
if (!parsedInput || !nextFingerprint || tool.lastEmittedInputFingerprint === nextFingerprint) return;
|
|
2045
2577
|
nextTool = {
|
|
2046
2578
|
...nextTool,
|
|
@@ -2065,7 +2597,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
2065
2597
|
...nextTool.parentToolUseId ? { parentToolUseId: nextTool.parentToolUseId } : {},
|
|
2066
2598
|
data: {
|
|
2067
2599
|
toolName: nextTool.toolName,
|
|
2068
|
-
input: nextTool.input
|
|
2600
|
+
input: toolEventInput(nextTool.toolName, nextTool.input)
|
|
2069
2601
|
}
|
|
2070
2602
|
},
|
|
2071
2603
|
providerRefs: nativeProviderRefs(context, { providerItemId: nextTool.itemId }),
|
|
@@ -2100,12 +2632,40 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
2100
2632
|
yield* ensureAssistantTextBlock(context, index, { fallbackText: extractContentBlockText(block) });
|
|
2101
2633
|
return;
|
|
2102
2634
|
}
|
|
2635
|
+
if (block.type === "thinking" && context.turnState) {
|
|
2636
|
+
const turnState = context.turnState;
|
|
2637
|
+
turnState.reasoningBlockCount += 1;
|
|
2638
|
+
const itemId = `${turnState.turnId}:thinking:${turnState.reasoningBlockCount}`;
|
|
2639
|
+
turnState.reasoningBlocks.set(index, { itemId });
|
|
2640
|
+
const stamp = yield* makeEventStamp();
|
|
2641
|
+
yield* offerRuntimeEventForContext(context, {
|
|
2642
|
+
type: "item.started",
|
|
2643
|
+
eventId: stamp.eventId,
|
|
2644
|
+
provider: PROVIDER,
|
|
2645
|
+
createdAt: stamp.createdAt,
|
|
2646
|
+
threadId: context.session.threadId,
|
|
2647
|
+
turnId: asCanonicalTurnId(turnState.turnId),
|
|
2648
|
+
itemId: asRuntimeItemId(itemId),
|
|
2649
|
+
payload: {
|
|
2650
|
+
itemType: "reasoning",
|
|
2651
|
+
status: "inProgress",
|
|
2652
|
+
title: "Reasoning"
|
|
2653
|
+
},
|
|
2654
|
+
providerRefs: nativeProviderRefs(context),
|
|
2655
|
+
raw: {
|
|
2656
|
+
source: "claude.sdk.message",
|
|
2657
|
+
method: "claude/stream_event/content_block_start",
|
|
2658
|
+
payload: message
|
|
2659
|
+
}
|
|
2660
|
+
});
|
|
2661
|
+
return;
|
|
2662
|
+
}
|
|
2103
2663
|
if (block.type !== "tool_use" && block.type !== "server_tool_use" && block.type !== "mcp_tool_use") return;
|
|
2104
2664
|
const toolName = block.name;
|
|
2105
2665
|
const itemType = classifyToolItemType(toolName);
|
|
2106
2666
|
const toolInput = typeof block.input === "object" && block.input !== null ? block.input : {};
|
|
2107
2667
|
const itemId = block.id;
|
|
2108
|
-
const detail =
|
|
2668
|
+
const detail = toolItemDetail(toolName, toolInput);
|
|
2109
2669
|
const inputFingerprint = Object.keys(toolInput).length > 0 ? toolInputFingerprint(toolInput) : void 0;
|
|
2110
2670
|
const parentToolUseId = message.parent_tool_use_id ?? void 0;
|
|
2111
2671
|
const owningAgentId = agentIdForParentToolUse(context.taskAgents, parentToolUseId);
|
|
@@ -2113,16 +2673,17 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
2113
2673
|
itemId,
|
|
2114
2674
|
itemType,
|
|
2115
2675
|
toolName,
|
|
2116
|
-
title:
|
|
2117
|
-
detail,
|
|
2676
|
+
title: toolItemTitle(toolName, itemType),
|
|
2677
|
+
...detail ? { detail } : {},
|
|
2118
2678
|
input: toolInput,
|
|
2119
2679
|
partialInputJson: "",
|
|
2680
|
+
partialInputScan: EMPTY_STREAMED_JSON_SCAN,
|
|
2120
2681
|
...inputFingerprint ? { lastEmittedInputFingerprint: inputFingerprint } : {},
|
|
2121
2682
|
...owningAgentId ? { agentId: owningAgentId } : {},
|
|
2122
2683
|
...parentToolUseId ? { parentToolUseId } : {}
|
|
2123
2684
|
};
|
|
2124
2685
|
context.inFlightTools.set(index, tool);
|
|
2125
|
-
if (itemType === "collab_agent_tool_call")
|
|
2686
|
+
if (itemType === "collab_agent_tool_call") rememberClaudeSubagentAttribution(context.subagentLaunchInputByToolUseId, itemId, toolInput);
|
|
2126
2687
|
const stamp = yield* makeEventStamp();
|
|
2127
2688
|
yield* offerRuntimeEventForContext(context, {
|
|
2128
2689
|
type: "item.started",
|
|
@@ -2141,7 +2702,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
2141
2702
|
...tool.parentToolUseId ? { parentToolUseId: tool.parentToolUseId } : {},
|
|
2142
2703
|
data: {
|
|
2143
2704
|
toolName: tool.toolName,
|
|
2144
|
-
input: toolInput
|
|
2705
|
+
input: toolEventInput(tool.toolName, toolInput)
|
|
2145
2706
|
}
|
|
2146
2707
|
},
|
|
2147
2708
|
providerRefs: nativeProviderRefs(context, { providerItemId: tool.itemId }),
|
|
@@ -2155,6 +2716,32 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
2155
2716
|
}
|
|
2156
2717
|
if (event.type === "content_block_stop") {
|
|
2157
2718
|
const { index } = event;
|
|
2719
|
+
const reasoningBlock = context.turnState?.reasoningBlocks.get(index);
|
|
2720
|
+
if (reasoningBlock && context.turnState) {
|
|
2721
|
+
context.turnState.reasoningBlocks.delete(index);
|
|
2722
|
+
const stamp = yield* makeEventStamp();
|
|
2723
|
+
yield* offerRuntimeEventForContext(context, {
|
|
2724
|
+
type: "item.completed",
|
|
2725
|
+
eventId: stamp.eventId,
|
|
2726
|
+
provider: PROVIDER,
|
|
2727
|
+
createdAt: stamp.createdAt,
|
|
2728
|
+
threadId: context.session.threadId,
|
|
2729
|
+
turnId: asCanonicalTurnId(context.turnState.turnId),
|
|
2730
|
+
itemId: asRuntimeItemId(reasoningBlock.itemId),
|
|
2731
|
+
payload: {
|
|
2732
|
+
itemType: "reasoning",
|
|
2733
|
+
status: "completed",
|
|
2734
|
+
title: "Reasoning"
|
|
2735
|
+
},
|
|
2736
|
+
providerRefs: nativeProviderRefs(context),
|
|
2737
|
+
raw: {
|
|
2738
|
+
source: "claude.sdk.message",
|
|
2739
|
+
method: "claude/stream_event/content_block_stop",
|
|
2740
|
+
payload: message
|
|
2741
|
+
}
|
|
2742
|
+
});
|
|
2743
|
+
return;
|
|
2744
|
+
}
|
|
2158
2745
|
const assistantBlock = context.turnState?.assistantTextBlocks.get(index);
|
|
2159
2746
|
if (assistantBlock) {
|
|
2160
2747
|
assistantBlock.streamClosed = true;
|
|
@@ -2177,7 +2764,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
2177
2764
|
const itemStatus = toolResult.isError ? "failed" : "completed";
|
|
2178
2765
|
const toolData = {
|
|
2179
2766
|
toolName: tool.toolName,
|
|
2180
|
-
input: tool.input,
|
|
2767
|
+
input: toolEventInput(tool.toolName, tool.input),
|
|
2181
2768
|
result: toolResult.block
|
|
2182
2769
|
};
|
|
2183
2770
|
const updatedStamp = yield* makeEventStamp();
|
|
@@ -2282,6 +2869,49 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
2282
2869
|
context.inFlightTools.delete(index);
|
|
2283
2870
|
}
|
|
2284
2871
|
});
|
|
2872
|
+
/**
|
|
2873
|
+
* Opens a provider turn: one Claude started without a prompt, either at its turn-start signal
|
|
2874
|
+
* ("wake-signal") or, when no signal opened one, at its first root assistant output. Never
|
|
2875
|
+
* bound to Agent Control authority; exact-turn binding stays prompt-only.
|
|
2876
|
+
*/
|
|
2877
|
+
const startProviderTurn = Effect.fn("startProviderTurn")(function* (context, openedBy) {
|
|
2878
|
+
const turnId = TurnId.make(yield* Effect.sync(() => crypto.randomUUID()));
|
|
2879
|
+
const startedAt = yield* nowIso;
|
|
2880
|
+
if (context.turnState !== void 0 || context.stopped) return;
|
|
2881
|
+
if (openedBy === "wake-signal" && (context.turnInstallsInFlight > 0 || !context.promptSent)) return;
|
|
2882
|
+
const turnState = makeClaudeTurnState({
|
|
2883
|
+
turnId,
|
|
2884
|
+
startedAt,
|
|
2885
|
+
openedBy
|
|
2886
|
+
});
|
|
2887
|
+
context.turnState = turnState;
|
|
2888
|
+
context.session = {
|
|
2889
|
+
...context.session,
|
|
2890
|
+
status: "running",
|
|
2891
|
+
activeTurnId: turnId,
|
|
2892
|
+
updatedAt: startedAt
|
|
2893
|
+
};
|
|
2894
|
+
const turnStartedStamp = yield* makeEventStamp();
|
|
2895
|
+
yield* offerRuntimeEventForContext(context, {
|
|
2896
|
+
type: "turn.started",
|
|
2897
|
+
eventId: turnStartedStamp.eventId,
|
|
2898
|
+
provider: PROVIDER,
|
|
2899
|
+
createdAt: turnStartedStamp.createdAt,
|
|
2900
|
+
threadId: context.session.threadId,
|
|
2901
|
+
turnId,
|
|
2902
|
+
payload: {},
|
|
2903
|
+
providerRefs: {
|
|
2904
|
+
...nativeProviderRefs(context),
|
|
2905
|
+
providerTurnId: turnId
|
|
2906
|
+
},
|
|
2907
|
+
raw: {
|
|
2908
|
+
source: "claude.sdk.message",
|
|
2909
|
+
method: "claude/synthetic-turn-start",
|
|
2910
|
+
payload: { openedBy }
|
|
2911
|
+
}
|
|
2912
|
+
});
|
|
2913
|
+
if (openedBy === "wake-signal") yield* Effect.sleep(Duration.millis(CLAUDE_WAKE_TURN_FIRST_OUTPUT_TIMEOUT_MS)).pipe(Effect.andThen(Effect.suspend(() => context.turnState === turnState && !turnState.rootOutputObserved && !context.stopped ? completeTurn(context, "interrupted", WAKE_NO_OUTPUT_REASON, void 0, { abortReason: WAKE_NO_OUTPUT_REASON }) : Effect.void)), Effect.ignoreCause({ log: true }), Effect.forkDetach);
|
|
2914
|
+
});
|
|
2285
2915
|
const handleAssistantMessage = Effect.fn("handleAssistantMessage")(function* (context, message) {
|
|
2286
2916
|
if (message.type !== "assistant") return;
|
|
2287
2917
|
const assistantParentToolUseId = message.parent_tool_use_id;
|
|
@@ -2289,8 +2919,39 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
2289
2919
|
const owningTaskId = agentIdForParentToolUse(context.taskAgents, assistantParentToolUseId);
|
|
2290
2920
|
const snapshotModel = trimmedClaudeString(message.message.model);
|
|
2291
2921
|
const owningAgent = owningTaskId ? context.taskAgents.get(owningTaskId) : void 0;
|
|
2292
|
-
if (owningAgent && snapshotModel
|
|
2293
|
-
|
|
2922
|
+
if (owningAgent && snapshotModel && owningAgent.model !== snapshotModel) {
|
|
2923
|
+
owningAgent.model = snapshotModel;
|
|
2924
|
+
const stamp = yield* makeEventStamp();
|
|
2925
|
+
yield* offerRuntimeEventForContext(context, {
|
|
2926
|
+
...stamp,
|
|
2927
|
+
type: "task.updated",
|
|
2928
|
+
provider: PROVIDER,
|
|
2929
|
+
threadId: context.session.threadId,
|
|
2930
|
+
...context.turnState ? { turnId: asCanonicalTurnId(context.turnState.turnId) } : {},
|
|
2931
|
+
providerRefs: nativeProviderRefs(context),
|
|
2932
|
+
payload: {
|
|
2933
|
+
taskId: RuntimeTaskId.make(owningAgent.taskId),
|
|
2934
|
+
...taskLinkageFor(context.taskAgents, owningAgent.taskId)
|
|
2935
|
+
}
|
|
2936
|
+
});
|
|
2937
|
+
const existingSubagent = context.subagentByTaskId.get(owningAgent.taskId);
|
|
2938
|
+
if (existingSubagent) {
|
|
2939
|
+
const subagent = {
|
|
2940
|
+
...existingSubagent,
|
|
2941
|
+
model: snapshotModel
|
|
2942
|
+
};
|
|
2943
|
+
context.subagentByTaskId.set(owningAgent.taskId, subagent);
|
|
2944
|
+
yield* emitClaudeSubagentUpdated(context, {
|
|
2945
|
+
subagent,
|
|
2946
|
+
raw: message
|
|
2947
|
+
});
|
|
2948
|
+
}
|
|
2949
|
+
} else if (!owningAgent && snapshotModel) rememberClaudeSubagentAttribution(context.subagentModelByToolUseId, assistantParentToolUseId, snapshotModel);
|
|
2950
|
+
for (const block of message.message.content) {
|
|
2951
|
+
if (block.type !== "tool_use") continue;
|
|
2952
|
+
rememberClaudeSubagentAttribution(context.subagentParentByToolUseId, block.id, assistantParentToolUseId);
|
|
2953
|
+
if (classifyToolItemType(block.name) === "collab_agent_tool_call" && block.input !== null && typeof block.input === "object" && !Array.isArray(block.input)) rememberClaudeSubagentAttribution(context.subagentLaunchInputByToolUseId, block.id, block.input);
|
|
2954
|
+
}
|
|
2294
2955
|
context.lastAssistantUuid = message.uuid;
|
|
2295
2956
|
yield* updateResumeCursor(context);
|
|
2296
2957
|
return;
|
|
@@ -2302,11 +2963,13 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
2302
2963
|
messageId: message.message.id,
|
|
2303
2964
|
model: message.message.model,
|
|
2304
2965
|
...context.cacheModelSelection ? { modelSelection: context.cacheModelSelection } : {},
|
|
2966
|
+
...context.session.cwd ? { cwd: context.session.cwd } : {},
|
|
2305
2967
|
runtimeSessionId: context.session.runtimeSessionId,
|
|
2306
2968
|
providerInstanceId: context.session.providerInstanceId,
|
|
2307
2969
|
observedAt: cacheStamp.createdAt,
|
|
2308
2970
|
...previousCache ? { previous: previousCache } : {}
|
|
2309
2971
|
});
|
|
2972
|
+
if (context.cacheObservation) context.mainLoopUsageObserved = true;
|
|
2310
2973
|
if (context.cacheObservation && context.cacheObservation !== previousCache) {
|
|
2311
2974
|
const observation = context.cacheObservation;
|
|
2312
2975
|
const usedTokens = observation.directInputTokens + observation.cacheReadInputTokens + observation.cacheWriteInputTokens;
|
|
@@ -2329,44 +2992,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
2329
2992
|
providerRefs: {}
|
|
2330
2993
|
});
|
|
2331
2994
|
}
|
|
2332
|
-
if (!context.turnState)
|
|
2333
|
-
const turnId = TurnId.make(yield* Effect.sync(() => crypto.randomUUID()));
|
|
2334
|
-
const startedAt = yield* nowIso;
|
|
2335
|
-
context.turnState = {
|
|
2336
|
-
turnId,
|
|
2337
|
-
startedAt,
|
|
2338
|
-
items: [],
|
|
2339
|
-
assistantTextBlocks: /* @__PURE__ */ new Map(),
|
|
2340
|
-
assistantTextBlockOrder: [],
|
|
2341
|
-
capturedProposedPlanKeys: /* @__PURE__ */ new Set(),
|
|
2342
|
-
nextSyntheticAssistantBlockIndex: -1
|
|
2343
|
-
};
|
|
2344
|
-
context.session = {
|
|
2345
|
-
...context.session,
|
|
2346
|
-
status: "running",
|
|
2347
|
-
activeTurnId: turnId,
|
|
2348
|
-
updatedAt: startedAt
|
|
2349
|
-
};
|
|
2350
|
-
const turnStartedStamp = yield* makeEventStamp();
|
|
2351
|
-
yield* offerRuntimeEventForContext(context, {
|
|
2352
|
-
type: "turn.started",
|
|
2353
|
-
eventId: turnStartedStamp.eventId,
|
|
2354
|
-
provider: PROVIDER,
|
|
2355
|
-
createdAt: turnStartedStamp.createdAt,
|
|
2356
|
-
threadId: context.session.threadId,
|
|
2357
|
-
turnId,
|
|
2358
|
-
payload: {},
|
|
2359
|
-
providerRefs: {
|
|
2360
|
-
...nativeProviderRefs(context),
|
|
2361
|
-
providerTurnId: turnId
|
|
2362
|
-
},
|
|
2363
|
-
raw: {
|
|
2364
|
-
source: "claude.sdk.message",
|
|
2365
|
-
method: "claude/synthetic-turn-start",
|
|
2366
|
-
payload: {}
|
|
2367
|
-
}
|
|
2368
|
-
});
|
|
2369
|
-
}
|
|
2995
|
+
if (!context.turnState) yield* startProviderTurn(context, "assistant-output");
|
|
2370
2996
|
const content = message.message?.content;
|
|
2371
2997
|
if (Array.isArray(content)) for (const block of content) {
|
|
2372
2998
|
if (!block || typeof block !== "object") continue;
|
|
@@ -2389,12 +3015,106 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
2389
3015
|
context.lastAssistantUuid = message.uuid;
|
|
2390
3016
|
yield* updateResumeCursor(context);
|
|
2391
3017
|
});
|
|
2392
|
-
const handleResultMessage = Effect.fn("handleResultMessage")(function* (context, message) {
|
|
3018
|
+
const handleResultMessage = Effect.fn("handleResultMessage")(function* (context, message, options) {
|
|
2393
3019
|
if (message.type !== "result") return;
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
3020
|
+
if (context.probing && context.turnState === void 0) {
|
|
3021
|
+
if (message.subtype !== "success" || message.is_error) {
|
|
3022
|
+
const detail = (message.subtype !== "success" ? message.errors[0] : void 0) ?? `Claude reported ${message.subtype} while reopening the conversation.`;
|
|
3023
|
+
if (context.probeFailure) yield* Deferred.succeed(context.probeFailure, detail);
|
|
3024
|
+
}
|
|
3025
|
+
return;
|
|
3026
|
+
}
|
|
3027
|
+
const turnState = context.turnState;
|
|
3028
|
+
const echoedPromptUuids = claudeEchoedPromptUuids(message);
|
|
3029
|
+
if (turnState?.promptUuid !== void 0 && !claudeResultBelongsToTurn({
|
|
3030
|
+
echoed: echoedPromptUuids,
|
|
3031
|
+
origin: message.origin,
|
|
3032
|
+
promptUuid: turnState.promptUuid,
|
|
3033
|
+
steerPromptUuids: turnState.steerPromptUuids
|
|
3034
|
+
})) {
|
|
3035
|
+
yield* Effect.logInfo("claude.turn.result-for-other-prompt", {
|
|
3036
|
+
threadId: context.session.threadId,
|
|
3037
|
+
turnId: turnState.turnId,
|
|
3038
|
+
origin: message.origin?.kind
|
|
3039
|
+
});
|
|
3040
|
+
return;
|
|
3041
|
+
}
|
|
3042
|
+
const resultStatus = turnStatusFromResult(message);
|
|
3043
|
+
let close = {
|
|
3044
|
+
status: resultStatus,
|
|
3045
|
+
cause: "result"
|
|
3046
|
+
};
|
|
3047
|
+
if (turnState) {
|
|
3048
|
+
const decision = decideClaudeTurnResult({
|
|
3049
|
+
kind: classifyClaudeResultKind(message),
|
|
3050
|
+
echoedPromptUuids,
|
|
3051
|
+
queuedTurnCount: message.queued_turn_count,
|
|
3052
|
+
steerPromptUuids: turnState.steerPromptUuids,
|
|
3053
|
+
settledSteerPromptUuids: turnState.settledSteerPromptUuids,
|
|
3054
|
+
interruptRequested: turnState.interruptRequested
|
|
3055
|
+
});
|
|
3056
|
+
for (const uuid of decision.newlySettled) {
|
|
3057
|
+
turnState.settledSteerPromptUuids.add(uuid);
|
|
3058
|
+
context.discardedSteerPromptUuids.delete(uuid);
|
|
3059
|
+
}
|
|
3060
|
+
if (decision.decision === "await-steer") {
|
|
3061
|
+
yield* sealTurnSegment(context, turnState, resultStatus, message);
|
|
3062
|
+
yield* emitTokenUsageSnapshot(context, yield* resolveResultUsageSnapshot(context, message), turnState.turnId);
|
|
3063
|
+
turnState.sealedSegmentCount += 1;
|
|
3064
|
+
turnState.awaitingSteerContinuation = {
|
|
3065
|
+
since: yield* nowIso,
|
|
3066
|
+
segmentStatus: resultStatus
|
|
3067
|
+
};
|
|
3068
|
+
yield* Effect.logInfo("claude.turn.awaiting-steer-continuation", {
|
|
3069
|
+
threadId: context.session.threadId,
|
|
3070
|
+
turnId: turnState.turnId,
|
|
3071
|
+
queuedTurnCount: message.queued_turn_count,
|
|
3072
|
+
unsettled: decision.unsettled.length,
|
|
3073
|
+
terminalReason: message.terminal_reason
|
|
3074
|
+
});
|
|
3075
|
+
return;
|
|
3076
|
+
}
|
|
3077
|
+
if (decision.discardUnsettled) for (const uuid of decision.unsettled) rememberDiscardedSteer(context.discardedSteerPromptUuids, uuid);
|
|
3078
|
+
close = decideClaudeTurnClose({
|
|
3079
|
+
resultStatus,
|
|
3080
|
+
decision,
|
|
3081
|
+
interruptRequested: turnState.interruptRequested,
|
|
3082
|
+
echoedPromptUuids,
|
|
3083
|
+
promptUuid: turnState.promptUuid,
|
|
3084
|
+
steerPromptUuids: turnState.steerPromptUuids,
|
|
3085
|
+
foldedIntoDiscardedCliTurn: options?.foldedIntoDiscardedCliTurn === true
|
|
3086
|
+
});
|
|
3087
|
+
if (close.cause !== "result") {
|
|
3088
|
+
if (close.status !== "failed") yield* sealTurnSegment(context, turnState, resultStatus, message);
|
|
3089
|
+
yield* Effect.logInfo("claude.turn.closed-as", {
|
|
3090
|
+
threadId: context.session.threadId,
|
|
3091
|
+
turnId: turnState.turnId,
|
|
3092
|
+
cause: close.cause,
|
|
3093
|
+
resultStatus,
|
|
3094
|
+
status: close.status,
|
|
3095
|
+
queuedTurnCount: message.queued_turn_count,
|
|
3096
|
+
unsettled: decision.unsettled.length,
|
|
3097
|
+
terminalReason: message.terminal_reason
|
|
3098
|
+
});
|
|
3099
|
+
}
|
|
3100
|
+
}
|
|
3101
|
+
const notInterrupted = (status) => status !== "interrupted" && status !== "cancelled";
|
|
3102
|
+
const usageLimit = context.turnState && notInterrupted(resultStatus) && notInterrupted(close.status) ? classifyClaudeUsageLimitResult({
|
|
3103
|
+
result: message,
|
|
3104
|
+
windows: context.rejectedRateLimitWindows,
|
|
3105
|
+
nowMs: yield* Clock.currentTimeMillis
|
|
3106
|
+
}) : null;
|
|
3107
|
+
if (usageLimit) {
|
|
3108
|
+
yield* emitRuntimeError(context, usageLimit.message, void 0, {
|
|
3109
|
+
class: "usage_limit",
|
|
3110
|
+
resetAt: usageLimit.resetAt
|
|
3111
|
+
});
|
|
3112
|
+
yield* completeTurn(context, "failed", usageLimit.message, message);
|
|
3113
|
+
return;
|
|
3114
|
+
}
|
|
3115
|
+
const errorMessage = claudeTurnCloseErrorMessage(close.cause, message);
|
|
3116
|
+
if (close.status === "failed") yield* emitRuntimeError(context, errorMessage ?? "Claude turn failed.");
|
|
3117
|
+
yield* completeTurn(context, close.status, errorMessage, message);
|
|
2398
3118
|
});
|
|
2399
3119
|
/**
|
|
2400
3120
|
* Synthesizes per-member task.progress rows from the coordinator's
|
|
@@ -2463,6 +3183,19 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
2463
3183
|
});
|
|
2464
3184
|
const handleSystemMessage = Effect.fn("handleSystemMessage")(function* (context, message) {
|
|
2465
3185
|
if (message.type !== "system") return;
|
|
3186
|
+
if (message.subtype === "status" && message.status === "requesting") context.requestingStatusObserved = true;
|
|
3187
|
+
const wakeSignal = claudeWakeSignal(message);
|
|
3188
|
+
if (wakeSignal !== void 0 && shouldOpenClaudeWakeTurn({
|
|
3189
|
+
signal: wakeSignal,
|
|
3190
|
+
hasOpenTurn: context.turnState !== void 0,
|
|
3191
|
+
sessionStopped: context.stopped,
|
|
3192
|
+
promptSent: context.promptSent,
|
|
3193
|
+
turnInstallsInFlight: context.turnInstallsInFlight,
|
|
3194
|
+
requestingStatusObserved: context.requestingStatusObserved
|
|
3195
|
+
})) {
|
|
3196
|
+
if (context.discardedSteerPromptUuids.size > 0) context.wakeSignalDeferred = true;
|
|
3197
|
+
else yield* startProviderTurn(context, "wake-signal");
|
|
3198
|
+
}
|
|
2466
3199
|
const stamp = yield* makeEventStamp();
|
|
2467
3200
|
const base = {
|
|
2468
3201
|
eventId: stamp.eventId,
|
|
@@ -2576,6 +3309,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
2576
3309
|
}
|
|
2577
3310
|
switch (message.subtype) {
|
|
2578
3311
|
case "init":
|
|
3312
|
+
context.cliCapabilities = parseClaudeCliCapabilities(message);
|
|
2579
3313
|
yield* offerRuntimeEventForContext(context, {
|
|
2580
3314
|
...base,
|
|
2581
3315
|
type: "session.configured",
|
|
@@ -2598,10 +3332,12 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
2598
3332
|
}
|
|
2599
3333
|
});
|
|
2600
3334
|
return;
|
|
2601
|
-
case "compact_boundary":
|
|
3335
|
+
case "compact_boundary": {
|
|
2602
3336
|
context.compactionPolicy = settleContextCompaction(context.compactionPolicy, context.generation);
|
|
2603
|
-
|
|
3337
|
+
const postCompactionUsage = claudePostCompactionUsage(message.compact_metadata, context.lastKnownContextWindow);
|
|
3338
|
+
context.lastKnownTokenUsage = postCompactionUsage;
|
|
2604
3339
|
context.cacheObservation = void 0;
|
|
3340
|
+
context.cumulativeUsageSpansCompaction = true;
|
|
2605
3341
|
yield* offerRuntimeEventForContext(context, {
|
|
2606
3342
|
...base,
|
|
2607
3343
|
type: "thread.state.changed",
|
|
@@ -2610,7 +3346,18 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
2610
3346
|
detail: message
|
|
2611
3347
|
}
|
|
2612
3348
|
});
|
|
3349
|
+
if (postCompactionUsage) {
|
|
3350
|
+
const usageStamp = yield* makeEventStamp();
|
|
3351
|
+
yield* offerRuntimeEventForContext(context, {
|
|
3352
|
+
...base,
|
|
3353
|
+
eventId: usageStamp.eventId,
|
|
3354
|
+
createdAt: usageStamp.createdAt,
|
|
3355
|
+
type: "thread.token-usage.updated",
|
|
3356
|
+
payload: { usage: withAutomaticCompactionCapability(postCompactionUsage, context.supportsAutomaticCompaction) }
|
|
3357
|
+
});
|
|
3358
|
+
}
|
|
2613
3359
|
return;
|
|
3360
|
+
}
|
|
2614
3361
|
case "hook_started":
|
|
2615
3362
|
yield* offerRuntimeEventForContext(context, {
|
|
2616
3363
|
...base,
|
|
@@ -2650,7 +3397,9 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
2650
3397
|
return;
|
|
2651
3398
|
case "task_started": {
|
|
2652
3399
|
const launchingTool = message.tool_use_id ? Array.from(context.inFlightTools.values()).find((tool) => tool.itemId === message.tool_use_id) : void 0;
|
|
2653
|
-
const
|
|
3400
|
+
const parentToolUseId = message.tool_use_id ? context.subagentParentByToolUseId.get(message.tool_use_id) : void 0;
|
|
3401
|
+
const owningAgentId = launchingTool?.agentId ?? agentIdForParentToolUse(context.taskAgents, parentToolUseId);
|
|
3402
|
+
if (message.tool_use_id) context.subagentParentByToolUseId.delete(message.tool_use_id);
|
|
2654
3403
|
const launchInput = launchingTool?.input ?? (message.tool_use_id ? context.subagentLaunchInputByToolUseId.get(message.tool_use_id) : void 0);
|
|
2655
3404
|
const backgroundFlag = message.is_backgrounded;
|
|
2656
3405
|
if (backgroundFlag === true || backgroundFlag === void 0 && launchInput?.run_in_background === true) context.backgroundedTaskIds.add(message.task_id);
|
|
@@ -2707,7 +3456,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
2707
3456
|
return;
|
|
2708
3457
|
}
|
|
2709
3458
|
case "task_progress": {
|
|
2710
|
-
if (message.usage && !context.
|
|
3459
|
+
if (message.usage && !context.mainLoopUsageObserved && !isClaudeSubagentTaskMessage(message) && !context.taskAgents.get(message.task_id)?.toolUseId) {
|
|
2711
3460
|
const normalizedUsage = normalizeClaudeTokenUsage(message.usage, context.lastKnownContextWindow);
|
|
2712
3461
|
if (normalizedUsage) {
|
|
2713
3462
|
context.lastKnownTokenUsage = normalizedUsage;
|
|
@@ -2789,7 +3538,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
2789
3538
|
case "task_notification": {
|
|
2790
3539
|
context.liveTaskIds.delete(message.task_id);
|
|
2791
3540
|
context.backgroundedTaskIds.delete(message.task_id);
|
|
2792
|
-
if (message.usage && !context.
|
|
3541
|
+
if (message.usage && !context.mainLoopUsageObserved && !isClaudeSubagentTaskMessage(message) && !context.taskAgents.get(message.task_id)?.toolUseId) {
|
|
2793
3542
|
const normalizedUsage = normalizeClaudeTokenUsage(message.usage, context.lastKnownContextWindow);
|
|
2794
3543
|
if (normalizedUsage) {
|
|
2795
3544
|
context.lastKnownTokenUsage = normalizedUsage;
|
|
@@ -2924,17 +3673,175 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
2924
3673
|
return;
|
|
2925
3674
|
}
|
|
2926
3675
|
if (message.type === "rate_limit_event") {
|
|
3676
|
+
const transition = message.rate_limit_info ? applyClaudeRateLimitInfo(context.rejectedRateLimitWindows, message.rate_limit_info) : void 0;
|
|
2927
3677
|
yield* offerRuntimeEventForContext(context, {
|
|
2928
3678
|
...base,
|
|
2929
3679
|
type: "account.rate-limits.updated",
|
|
2930
|
-
payload: {
|
|
3680
|
+
payload: {
|
|
3681
|
+
rateLimits: message,
|
|
3682
|
+
usageLimitState: claudeUsageLimitState(context.rejectedRateLimitWindows, yield* Clock.currentTimeMillis)
|
|
3683
|
+
}
|
|
2931
3684
|
});
|
|
3685
|
+
const turnState = context.turnState;
|
|
3686
|
+
if (transition?.blocked && turnState) {
|
|
3687
|
+
const announced = turnState.announcedUsageLimitKeys ??= /* @__PURE__ */ new Set();
|
|
3688
|
+
if (!announced.has(transition.key)) {
|
|
3689
|
+
announced.add(transition.key);
|
|
3690
|
+
yield* emitRuntimeWarning(context, CLAUDE_USAGE_LIMIT_FALLBACK_MESSAGE, { usageLimit: {
|
|
3691
|
+
limitType: transition.limitType,
|
|
3692
|
+
resetAt: transition.resetAt
|
|
3693
|
+
} });
|
|
3694
|
+
}
|
|
3695
|
+
}
|
|
2932
3696
|
return;
|
|
2933
3697
|
}
|
|
2934
3698
|
});
|
|
3699
|
+
/** Plain interrupt for a CLI segment Stop already ended; bounded, failures only logged. */
|
|
3700
|
+
const forkReinterrupt = (context, reason) => Effect.tryPromise({
|
|
3701
|
+
try: () => context.query.interrupt(),
|
|
3702
|
+
catch: (cause) => toRequestError(context.session.threadId, "turn/interrupt", cause)
|
|
3703
|
+
}).pipe(Effect.timeoutOption("5 seconds"), Effect.tap(() => Effect.logInfo("claude.turn.reinterrupted", {
|
|
3704
|
+
threadId: context.session.threadId,
|
|
3705
|
+
reason
|
|
3706
|
+
})), Effect.ignoreCause({ log: true }), Effect.forkDetach, Effect.asVoid);
|
|
3707
|
+
/**
|
|
3708
|
+
* A discarded steer's CLI turn turned out to be the one a provider turn was opened for (by its
|
|
3709
|
+
* `status: requesting`, legacy `init`, `api_retry` or compaction frame, before its echo). That
|
|
3710
|
+
* turn has routed no content: retract it.
|
|
3711
|
+
*/
|
|
3712
|
+
const retractDiscardedSteerWakeTurn = Effect.fn("retractDiscardedSteerWakeTurn")(function* (context) {
|
|
3713
|
+
const turnState = context.turnState;
|
|
3714
|
+
if (turnState === void 0 || turnState.openedBy !== "wake-signal" || turnState.rootContentObserved || turnState.steerPromptUuids.size > 0) return;
|
|
3715
|
+
yield* completeTurn(context, "interrupted", DISCARDED_STEER_TURN_REASON, void 0, {
|
|
3716
|
+
abortReason: DISCARDED_STEER_TURN_REASON,
|
|
3717
|
+
expectedTurnState: turnState
|
|
3718
|
+
});
|
|
3719
|
+
});
|
|
3720
|
+
/**
|
|
3721
|
+
* The discarded CLI turn's result: forget its uuids, then drop it (keeping its usage). Returns
|
|
3722
|
+
* whether it was consumed. Only this result can end the open turn when:
|
|
3723
|
+
* - it echoes the open turn's prompt or steer, which the CLI folded into the discarded CLI turn
|
|
3724
|
+
* (a fold shows only on the result). That turn's reply went with the dropped frames, and the
|
|
3725
|
+
* discard's re-interrupt usually aborted it, so the result closes it here as failed (never as
|
|
3726
|
+
* a Stop the user did not press);
|
|
3727
|
+
* - the CLI turn's output already reached an open provider turn (its frames carried no echo,
|
|
3728
|
+
* or beat Stop's bookkeeping). The result is routed on and completes that turn.
|
|
3729
|
+
*/
|
|
3730
|
+
const endDiscardedSteerCliTurn = Effect.fn("endDiscardedSteerCliTurn")(function* (context, message, uuids) {
|
|
3731
|
+
let count = 0;
|
|
3732
|
+
for (const uuid of uuids) {
|
|
3733
|
+
context.discardedSteerPromptUuids.delete(uuid);
|
|
3734
|
+
count += 1;
|
|
3735
|
+
}
|
|
3736
|
+
context.discardingCliTurn = void 0;
|
|
3737
|
+
context.wakeSignalDeferred = false;
|
|
3738
|
+
const open = context.turnState;
|
|
3739
|
+
if (open !== void 0) {
|
|
3740
|
+
const logContext = {
|
|
3741
|
+
threadId: context.session.threadId,
|
|
3742
|
+
turnId: open.turnId,
|
|
3743
|
+
openedBy: open.openedBy,
|
|
3744
|
+
uuids: count
|
|
3745
|
+
};
|
|
3746
|
+
if (claudeEchoNamesTurn({
|
|
3747
|
+
echoed: claudeEchoedPromptUuids(message),
|
|
3748
|
+
promptUuid: open.promptUuid,
|
|
3749
|
+
steerPromptUuids: open.steerPromptUuids
|
|
3750
|
+
})) {
|
|
3751
|
+
yield* Effect.logInfo("claude.turn.discarded-steer-folded-open-turn", logContext);
|
|
3752
|
+
yield* handleResultMessage(context, message, { foldedIntoDiscardedCliTurn: true });
|
|
3753
|
+
return true;
|
|
3754
|
+
}
|
|
3755
|
+
if (open.promptUuid === void 0 && open.rootContentObserved) {
|
|
3756
|
+
yield* Effect.logInfo("claude.turn.discarded-steer-output-leaked", logContext);
|
|
3757
|
+
return false;
|
|
3758
|
+
}
|
|
3759
|
+
}
|
|
3760
|
+
yield* emitTokenUsageSnapshot(context, yield* resolveResultUsageSnapshot(context, message), void 0);
|
|
3761
|
+
yield* retractDiscardedSteerWakeTurn(context);
|
|
3762
|
+
yield* Effect.logInfo("claude.turn.discarded-cancelled-steer", {
|
|
3763
|
+
threadId: context.session.threadId,
|
|
3764
|
+
uuids: count
|
|
3765
|
+
});
|
|
3766
|
+
return true;
|
|
3767
|
+
});
|
|
3768
|
+
/**
|
|
3769
|
+
* Routes frames of CLI segments started by steers. Returns true when the frame was consumed
|
|
3770
|
+
* (dropped, or a result that already closed the open turn). The echo is read on a CLI turn's
|
|
3771
|
+
* first reply frame (its first stream event, or its first root assistant message when it
|
|
3772
|
+
* streamed nothing) and on its result. A CLI turn whose echo holds only steers Stop (or a failed
|
|
3773
|
+
* segment) discarded is interrupted again (unless its reply is an API error, which ends it
|
|
3774
|
+
* anyway) and dropped up to and including its result; a result with such an echo and no reply
|
|
3775
|
+
* before it is dropped alone. Either result still ends the open turn when only it can (see
|
|
3776
|
+
* `endDiscardedSteerCliTurn`). The open turn owns its own steers' segments; after Stop, one that
|
|
3777
|
+
* starts is interrupted again too, with the same API-error exception.
|
|
3778
|
+
*/
|
|
3779
|
+
const routeSteerFrame = Effect.fn("routeSteerFrame")(function* (context, message) {
|
|
3780
|
+
const discarding = context.discardingCliTurn;
|
|
3781
|
+
if (discarding !== void 0) switch (message.type) {
|
|
3782
|
+
case "result": return yield* endDiscardedSteerCliTurn(context, message, [...discarding.uuids, ...claudeEchoedPromptUuids(message)]);
|
|
3783
|
+
case "stream_event":
|
|
3784
|
+
case "assistant":
|
|
3785
|
+
case "user":
|
|
3786
|
+
case "tool_progress":
|
|
3787
|
+
case "tool_use_summary": return true;
|
|
3788
|
+
default: return false;
|
|
3789
|
+
}
|
|
3790
|
+
if (message.type !== "stream_event" && message.type !== "assistant" && message.type !== "result") return false;
|
|
3791
|
+
const echoed = claudeEchoedPromptUuids(message);
|
|
3792
|
+
if (echoed.length === 0) return false;
|
|
3793
|
+
const discarded = context.discardedSteerPromptUuids;
|
|
3794
|
+
const turnState = context.turnState;
|
|
3795
|
+
const owned = turnState !== void 0 && claudeEchoNamesTurn({
|
|
3796
|
+
echoed,
|
|
3797
|
+
promptUuid: turnState.promptUuid,
|
|
3798
|
+
steerPromptUuids: turnState.steerPromptUuids
|
|
3799
|
+
});
|
|
3800
|
+
const reinterruptable = !isClaudeApiErrorReply(message);
|
|
3801
|
+
if (owned || !echoed.every((uuid) => discarded.has(uuid))) {
|
|
3802
|
+
if (owned && message.type !== "result") {
|
|
3803
|
+
for (const uuid of echoed) if (turnState.steerPromptUuids.has(uuid)) turnState.startedSteerPromptUuids.add(uuid);
|
|
3804
|
+
const echoKey = [...echoed].toSorted().join(" ");
|
|
3805
|
+
if (reinterruptable && turnState.interruptRequested && echoed.some((uuid) => turnState.steerPromptUuids.has(uuid) && !turnState.settledSteerPromptUuids.has(uuid)) && !turnState.reinterruptedEchoKeys.has(echoKey)) {
|
|
3806
|
+
turnState.reinterruptedEchoKeys.add(echoKey);
|
|
3807
|
+
yield* forkReinterrupt(context, "steer-segment-after-stop");
|
|
3808
|
+
}
|
|
3809
|
+
}
|
|
3810
|
+
for (const uuid of echoed) discarded.delete(uuid);
|
|
3811
|
+
return false;
|
|
3812
|
+
}
|
|
3813
|
+
if (message.type === "result") return yield* endDiscardedSteerCliTurn(context, message, echoed);
|
|
3814
|
+
context.discardingCliTurn = { uuids: new Set(echoed) };
|
|
3815
|
+
context.wakeSignalDeferred = false;
|
|
3816
|
+
if (reinterruptable) yield* forkReinterrupt(context, "discarded-steer-segment");
|
|
3817
|
+
yield* Effect.logInfo("claude.turn.discarding-cancelled-steer", {
|
|
3818
|
+
threadId: context.session.threadId,
|
|
3819
|
+
uuids: echoed.length
|
|
3820
|
+
});
|
|
3821
|
+
yield* retractDiscardedSteerWakeTurn(context);
|
|
3822
|
+
return true;
|
|
3823
|
+
});
|
|
2935
3824
|
const handleSdkMessage = Effect.fn("handleSdkMessage")(function* (context, message) {
|
|
2936
3825
|
yield* logNativeSdkMessage(context, message);
|
|
2937
3826
|
yield* ensureThreadId(context, message);
|
|
3827
|
+
if (yield* routeSteerFrame(context, message)) return;
|
|
3828
|
+
const chainUuid = claudeMainChainUuid(message);
|
|
3829
|
+
if (chainUuid !== void 0 && context.turnState) context.turnState.lastChainUuid = chainUuid;
|
|
3830
|
+
const rootContent = isClaudeRootTurnFrame(message);
|
|
3831
|
+
if (context.wakeSignalDeferred) {
|
|
3832
|
+
if (rootContent) {
|
|
3833
|
+
context.wakeSignalDeferred = false;
|
|
3834
|
+
if (context.turnState === void 0) yield* startProviderTurn(context, "wake-signal");
|
|
3835
|
+
} else if (message.type === "result") context.wakeSignalDeferred = false;
|
|
3836
|
+
}
|
|
3837
|
+
const waiting = context.turnState;
|
|
3838
|
+
if (waiting?.awaitingSteerContinuation !== void 0 && rootContent) waiting.awaitingSteerContinuation = void 0;
|
|
3839
|
+
yield* routeSdkMessage(context, message);
|
|
3840
|
+
const open = context.turnState;
|
|
3841
|
+
if (open && !open.rootOutputObserved && isClaudeRootTurnOutput(message)) open.rootOutputObserved = true;
|
|
3842
|
+
if (open && rootContent) open.rootContentObserved = true;
|
|
3843
|
+
});
|
|
3844
|
+
const routeSdkMessage = Effect.fn("routeSdkMessage")(function* (context, message) {
|
|
2938
3845
|
switch (message.type) {
|
|
2939
3846
|
case "stream_event":
|
|
2940
3847
|
yield* handleStreamEvent(context, message);
|
|
@@ -2962,7 +3869,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
2962
3869
|
return;
|
|
2963
3870
|
}
|
|
2964
3871
|
});
|
|
2965
|
-
const runSdkStream = (context) => Stream.fromAsyncIterable(context.query, (cause) => toError(cause, "Claude runtime stream failed.")).pipe(Stream.takeWhile(() => !context.stopped), Stream.runForEach((message) => handleSdkMessage(context, message)));
|
|
3872
|
+
const runSdkStream = (context) => Stream.fromAsyncIterable(context.query, (cause) => toError(cause, "Claude runtime stream failed.")).pipe(Stream.takeWhile(() => !context.stopped), Stream.runForEach((message) => context.turnLock.withPermits(1)(handleSdkMessage(context, message))));
|
|
2966
3873
|
const handleStreamExit = Effect.fn("handleStreamExit")(function* (context, exit) {
|
|
2967
3874
|
if (context.stopped) return;
|
|
2968
3875
|
if (Exit.isFailure(exit)) {
|
|
@@ -2979,6 +3886,9 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
2979
3886
|
const stopSessionInternal = Effect.fn("stopSessionInternal")(function* (context, options) {
|
|
2980
3887
|
if (context.stopped) return;
|
|
2981
3888
|
context.stopped = true;
|
|
3889
|
+
context.discardedSteerPromptUuids.clear();
|
|
3890
|
+
context.discardingCliTurn = void 0;
|
|
3891
|
+
context.wakeSignalDeferred = false;
|
|
2982
3892
|
context.deviceToolBinding?.dispose();
|
|
2983
3893
|
if (context.agentControl) yield* context.agentControl.revoke("runtime-teardown");
|
|
2984
3894
|
for (const [requestId, pending] of context.pendingApprovals) {
|
|
@@ -3005,11 +3915,22 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
3005
3915
|
yield* Queue.shutdown(context.promptQueue);
|
|
3006
3916
|
const streamFiber = context.streamFiber;
|
|
3007
3917
|
context.streamFiber = void 0;
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3918
|
+
const closeQuery = Effect.gen(function* () {
|
|
3919
|
+
try {
|
|
3920
|
+
context.query.close();
|
|
3921
|
+
} catch (cause) {
|
|
3922
|
+
yield* emitRuntimeError(context, "Failed to close Claude runtime query.", cause);
|
|
3923
|
+
}
|
|
3924
|
+
});
|
|
3925
|
+
if (options?.awaitQueryExitMs !== void 0) {
|
|
3926
|
+
yield* closeQuery;
|
|
3927
|
+
if (streamFiber && streamFiber.pollUnsafe() === void 0) {
|
|
3928
|
+
const exited = yield* Fiber.await(streamFiber).pipe(Effect.timeoutOption(Duration.millis(options.awaitQueryExitMs)));
|
|
3929
|
+
if (Option.isNone(exited)) yield* Fiber.interrupt(streamFiber);
|
|
3930
|
+
}
|
|
3931
|
+
} else {
|
|
3932
|
+
if (streamFiber && streamFiber.pollUnsafe() === void 0) yield* Fiber.interrupt(streamFiber);
|
|
3933
|
+
yield* closeQuery;
|
|
3013
3934
|
}
|
|
3014
3935
|
const updatedAt = yield* nowIso;
|
|
3015
3936
|
context.session = {
|
|
@@ -3059,6 +3980,11 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
3059
3980
|
issue: `Expected provider instance '${boundInstanceId}' but received '${input.providerInstanceId}'.`
|
|
3060
3981
|
});
|
|
3061
3982
|
const runtimeSessionId = yield* requireRuntimeSessionId(PROVIDER, input);
|
|
3983
|
+
if (rewindingThreads.has(input.threadId)) return yield* new ProviderAdapterValidationError({
|
|
3984
|
+
provider: PROVIDER,
|
|
3985
|
+
operation: "startSession",
|
|
3986
|
+
issue: "Claude is rewinding this thread; try again in a moment."
|
|
3987
|
+
});
|
|
3062
3988
|
const existingContext = sessions.get(input.threadId);
|
|
3063
3989
|
if (existingContext) {
|
|
3064
3990
|
if (existingContext.session.runtimeSessionId === runtimeSessionId) return existingContext.session;
|
|
@@ -3068,6 +3994,15 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
3068
3994
|
issue: `Thread '${input.threadId}' still has runtime '${existingContext.session.runtimeSessionId ?? "legacy"}'; stop it before starting '${runtimeSessionId}'.`
|
|
3069
3995
|
});
|
|
3070
3996
|
}
|
|
3997
|
+
return { ...(yield* openSessionContext(input, {})).session };
|
|
3998
|
+
});
|
|
3999
|
+
/**
|
|
4000
|
+
* Opens a query for `input` and registers its context. With `probe`, the
|
|
4001
|
+
* reopened CLI must accept a control request before this succeeds; a failed
|
|
4002
|
+
* probe stops the context silently (no runtime.error or session.exited).
|
|
4003
|
+
*/
|
|
4004
|
+
const openSessionContext = Effect.fn("openSessionContext")(function* (input, openOptions) {
|
|
4005
|
+
const runtimeSessionId = yield* requireRuntimeSessionId(PROVIDER, input);
|
|
3071
4006
|
const startedAt = yield* nowIso;
|
|
3072
4007
|
const effectiveResumeCursor = input.resumePolicy === "fresh" ? void 0 : input.resumeCursor;
|
|
3073
4008
|
const resumeState = readClaudeResumeState(effectiveResumeCursor);
|
|
@@ -3299,7 +4234,10 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
3299
4234
|
});
|
|
3300
4235
|
const canUseTool = (toolName, toolInput, callbackOptions) => runPromise(canUseToolEffect(toolName, toolInput, callbackOptions));
|
|
3301
4236
|
const claudeBinaryPath = claudeSettings.binaryPath;
|
|
3302
|
-
const extraArgs =
|
|
4237
|
+
const extraArgs = {
|
|
4238
|
+
"thinking-display": "summarized",
|
|
4239
|
+
...parseCliArgs(claudeSettings.launchArgs).flags
|
|
4240
|
+
};
|
|
3303
4241
|
const modelSelection = input.modelSelection?.instanceId === boundInstanceId ? input.modelSelection : void 0;
|
|
3304
4242
|
const caps = getClaudeModelCapabilities(modelSelection?.model);
|
|
3305
4243
|
const descriptors = getProviderOptionDescriptors({ caps });
|
|
@@ -3356,6 +4294,8 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
3356
4294
|
...permissionMode === "bypassPermissions" ? { allowDangerouslySkipPermissions: true } : {},
|
|
3357
4295
|
...Object.keys(settings).length > 0 ? { settings } : {},
|
|
3358
4296
|
...existingResumeSessionId ? { resume: existingResumeSessionId } : {},
|
|
4297
|
+
...existingResumeSessionId && resumeState?.rewindAt ? { resumeSessionAt: resumeState.rewindAt } : {},
|
|
4298
|
+
...existingResumeSessionId && resumeState?.rewindAt && openOptions.resumeDropsTurn ? { resumeDropsTurn: openOptions.resumeDropsTurn } : {},
|
|
3359
4299
|
...newSessionId ? { sessionId: newSessionId } : {},
|
|
3360
4300
|
includePartialMessages: true,
|
|
3361
4301
|
canUseTool,
|
|
@@ -3429,6 +4369,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
3429
4369
|
...threadId ? { threadId } : {},
|
|
3430
4370
|
...sessionId ? { resume: sessionId } : {},
|
|
3431
4371
|
...resumeState?.resumeSessionAt ? { resumeSessionAt: resumeState.resumeSessionAt } : {},
|
|
4372
|
+
...existingResumeSessionId && resumeState?.rewindAt ? { rewind: { at: resumeState.rewindAt } } : {},
|
|
3432
4373
|
turnCount: resumeState?.turnCount ?? 0
|
|
3433
4374
|
},
|
|
3434
4375
|
createdAt: startedAt,
|
|
@@ -3436,9 +4377,15 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
3436
4377
|
};
|
|
3437
4378
|
const generation = ++nextSessionGeneration;
|
|
3438
4379
|
const supportsAutomaticCompaction = typeof queryRuntime.applyFlagSettings === "function";
|
|
4380
|
+
const { resumeCursor: _resumeCursor, resumePolicy: _resumePolicy, ...startInput } = input;
|
|
3439
4381
|
const context = {
|
|
3440
4382
|
generation,
|
|
3441
4383
|
session,
|
|
4384
|
+
startInput,
|
|
4385
|
+
turnHeads: [...openOptions.turnHeads ?? []],
|
|
4386
|
+
pendingRewind: existingResumeSessionId && resumeState?.rewindAt ? { at: resumeState.rewindAt } : void 0,
|
|
4387
|
+
probing: openOptions.probe === true,
|
|
4388
|
+
probeFailure: openOptions.probe === true ? Deferred.makeUnsafe() : void 0,
|
|
3442
4389
|
promptQueue,
|
|
3443
4390
|
query: queryRuntime,
|
|
3444
4391
|
deviceToolBinding,
|
|
@@ -3459,7 +4406,9 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
3459
4406
|
taskAgents: /* @__PURE__ */ new Map(),
|
|
3460
4407
|
subagentLaunchInputByToolUseId: /* @__PURE__ */ new Map(),
|
|
3461
4408
|
subagentModelByToolUseId: /* @__PURE__ */ new Map(),
|
|
4409
|
+
subagentParentByToolUseId: /* @__PURE__ */ new Map(),
|
|
3462
4410
|
workflowMemberFingerprints: /* @__PURE__ */ new Map(),
|
|
4411
|
+
rejectedRateLimitWindows: /* @__PURE__ */ new Map(),
|
|
3463
4412
|
workflowPhasesByTaskId: /* @__PURE__ */ new Map(),
|
|
3464
4413
|
liveTaskIds: /* @__PURE__ */ new Set(),
|
|
3465
4414
|
backgroundedTaskIds: /* @__PURE__ */ new Set(),
|
|
@@ -3467,6 +4416,8 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
3467
4416
|
lastKnownContextWindow: void 0,
|
|
3468
4417
|
lastKnownTokenUsage: void 0,
|
|
3469
4418
|
cacheObservation: void 0,
|
|
4419
|
+
mainLoopUsageObserved: false,
|
|
4420
|
+
cumulativeUsageSpansCompaction: false,
|
|
3470
4421
|
cacheModelSelection: modelSelection,
|
|
3471
4422
|
compactionPolicy: initialContextCompactionPolicyState(generation),
|
|
3472
4423
|
supportsAutomaticCompaction,
|
|
@@ -3476,7 +4427,15 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
3476
4427
|
subagentByTaskId: /* @__PURE__ */ new Map(),
|
|
3477
4428
|
startedSubagentIds: /* @__PURE__ */ new Set(),
|
|
3478
4429
|
completedSubagentIds: /* @__PURE__ */ new Set(),
|
|
3479
|
-
stopped: false
|
|
4430
|
+
stopped: false,
|
|
4431
|
+
promptSent: false,
|
|
4432
|
+
turnInstallsInFlight: 0,
|
|
4433
|
+
requestingStatusObserved: false,
|
|
4434
|
+
cliCapabilities: void 0,
|
|
4435
|
+
discardedSteerPromptUuids: /* @__PURE__ */ new Set(),
|
|
4436
|
+
discardingCliTurn: void 0,
|
|
4437
|
+
wakeSignalDeferred: false,
|
|
4438
|
+
turnLock: yield* Semaphore.make(1)
|
|
3480
4439
|
};
|
|
3481
4440
|
deviceToolContext = context;
|
|
3482
4441
|
yield* Ref.set(contextRef, context);
|
|
@@ -3521,18 +4480,35 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
3521
4480
|
streamFiber = runFork(Effect.exit(runSdkStream(context)).pipe(Effect.flatMap((exit) => {
|
|
3522
4481
|
if (context.stopped) return Effect.void;
|
|
3523
4482
|
if (context.streamFiber === streamFiber) context.streamFiber = void 0;
|
|
4483
|
+
if (context.probing && context.probeFailure) return Deferred.succeed(context.probeFailure, Exit.isFailure(exit) ? messageFromClaudeStreamCause(exit.cause, "Claude runtime stream failed.") : "Claude exited while reopening the conversation.").pipe(Effect.asVoid);
|
|
3524
4484
|
return handleStreamExit(context, exit);
|
|
3525
4485
|
})));
|
|
3526
4486
|
context.streamFiber = streamFiber;
|
|
3527
4487
|
streamFiber.addObserver(() => {
|
|
3528
4488
|
if (context.streamFiber === streamFiber) context.streamFiber = void 0;
|
|
3529
4489
|
});
|
|
3530
|
-
|
|
4490
|
+
if (context.probing && context.probeFailure) {
|
|
4491
|
+
const probeFailure = context.probeFailure;
|
|
4492
|
+
const controlRequest = Effect.tryPromise({
|
|
4493
|
+
try: () => queryRuntime.initializationResult?.() ?? queryRuntime.mcpServerStatus?.() ?? Promise.resolve(),
|
|
4494
|
+
catch: (cause) => toMessage(cause, "Claude rejected the reopened conversation.")
|
|
4495
|
+
});
|
|
4496
|
+
const probe = yield* Effect.raceFirst(controlRequest.pipe(Effect.asVoid), Deferred.await(probeFailure).pipe(Effect.flatMap((detail) => Effect.fail(detail)))).pipe(Effect.timeoutOption(CLAUDE_REWIND_PROBE_TIMEOUT), Effect.result);
|
|
4497
|
+
context.probing = false;
|
|
4498
|
+
const failure = probe._tag === "Failure" ? probe.failure : Option.isNone(probe.success) ? "Claude did not respond while reopening the conversation." : Deferred.isDoneUnsafe(probeFailure) ? "Claude exited while reopening the conversation." : void 0;
|
|
4499
|
+
if (failure !== void 0) {
|
|
4500
|
+
yield* stopSessionInternal(context, { emitExitEvent: false });
|
|
4501
|
+
return yield* new ProviderAdapterProcessError({
|
|
4502
|
+
provider: PROVIDER,
|
|
4503
|
+
threadId,
|
|
4504
|
+
detail: failure
|
|
4505
|
+
});
|
|
4506
|
+
}
|
|
4507
|
+
}
|
|
4508
|
+
return context;
|
|
3531
4509
|
});
|
|
3532
|
-
const
|
|
3533
|
-
const context = yield* requireSession(input.threadId);
|
|
4510
|
+
const sendTurnOnContext = Effect.fn("sendTurnOnContext")(function* (context, input) {
|
|
3534
4511
|
const modelSelection = input.modelSelection !== void 0 && input.modelSelection.instanceId === boundInstanceId ? input.modelSelection : void 0;
|
|
3535
|
-
if (context.turnState) yield* completeTurn(context, "completed");
|
|
3536
4512
|
if (modelSelection?.model) {
|
|
3537
4513
|
const apiModelId = resolveClaudeApiModelId(modelSelection);
|
|
3538
4514
|
if (context.currentApiModelId !== apiModelId) {
|
|
@@ -3559,24 +4535,23 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
3559
4535
|
try: () => context.query.setPermissionMode(context.basePermissionMode ?? "default"),
|
|
3560
4536
|
catch: (cause) => toRequestError(input.threadId, "turn/setPermissionMode", cause)
|
|
3561
4537
|
});
|
|
3562
|
-
const
|
|
3563
|
-
const
|
|
4538
|
+
const promptUuid = yield* Effect.sync(() => crypto.randomUUID());
|
|
4539
|
+
const turnId = TurnId.make(promptUuid);
|
|
4540
|
+
const startedAt = yield* nowIso;
|
|
4541
|
+
while (context.turnState !== void 0) yield* completeTurn(context, "completed");
|
|
4542
|
+
context.turnState = makeClaudeTurnState({
|
|
3564
4543
|
turnId,
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
capturedProposedPlanKeys: /* @__PURE__ */ new Set(),
|
|
3570
|
-
nextSyntheticAssistantBlockIndex: -1
|
|
3571
|
-
};
|
|
3572
|
-
const updatedAt = yield* nowIso;
|
|
3573
|
-
context.turnState = turnState;
|
|
4544
|
+
promptUuid,
|
|
4545
|
+
startedAt,
|
|
4546
|
+
openedBy: "prompt"
|
|
4547
|
+
});
|
|
3574
4548
|
context.session = {
|
|
3575
4549
|
...context.session,
|
|
3576
4550
|
status: "running",
|
|
3577
4551
|
activeTurnId: turnId,
|
|
3578
|
-
updatedAt
|
|
4552
|
+
updatedAt: startedAt
|
|
3579
4553
|
};
|
|
4554
|
+
context.promptSent = true;
|
|
3580
4555
|
const turnStartedStamp = yield* makeEventStamp();
|
|
3581
4556
|
yield* offerRuntimeEventForContext(context, {
|
|
3582
4557
|
type: "turn.started",
|
|
@@ -3600,7 +4575,10 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
3600
4575
|
});
|
|
3601
4576
|
yield* Queue.offer(context.promptQueue, {
|
|
3602
4577
|
type: "message",
|
|
3603
|
-
message
|
|
4578
|
+
message: {
|
|
4579
|
+
...message,
|
|
4580
|
+
uuid: promptUuid
|
|
4581
|
+
}
|
|
3604
4582
|
}).pipe(Effect.mapError((cause) => toRequestError(input.threadId, "turn/start", cause)));
|
|
3605
4583
|
if (context.agentControl) yield* context.agentControl.bindTurn(turnId).pipe(Effect.catchCause((cause) => Effect.logWarning("failed to bind Agent Control turn authority", {
|
|
3606
4584
|
threadId: input.threadId,
|
|
@@ -3613,9 +4591,73 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
3613
4591
|
...context.session.resumeCursor !== void 0 ? { resumeCursor: context.session.resumeCursor } : {}
|
|
3614
4592
|
};
|
|
3615
4593
|
});
|
|
3616
|
-
const
|
|
4594
|
+
const sendTurn = Effect.fn("sendTurn")(function* (input) {
|
|
4595
|
+
const context = yield* requireSession(input.threadId);
|
|
4596
|
+
return yield* Effect.acquireUseRelease(Effect.sync(() => {
|
|
4597
|
+
context.turnInstallsInFlight += 1;
|
|
4598
|
+
}), () => sendTurnOnContext(context, input), () => Effect.sync(() => {
|
|
4599
|
+
context.turnInstallsInFlight -= 1;
|
|
4600
|
+
}));
|
|
4601
|
+
});
|
|
4602
|
+
/**
|
|
4603
|
+
* Adds a user message to the exact running turn: an SDK user message with `priority: "now"`
|
|
4604
|
+
* and its own uuid. The Ryco turn keeps its id and absorbs the CLI segments the steer starts.
|
|
4605
|
+
* Refusals are `ProviderTurnNotSteerableError`, so the message stays queued as the next turn.
|
|
4606
|
+
*/
|
|
4607
|
+
const steerTurn = Effect.fn("steerTurn")(function* (input) {
|
|
4608
|
+
const context = yield* requireSession(input.threadId);
|
|
4609
|
+
const refuse = (reason, detail) => new ProviderTurnNotSteerableError({
|
|
4610
|
+
provider: PROVIDER,
|
|
4611
|
+
threadId: input.threadId,
|
|
4612
|
+
turnId: input.expectedTurnId,
|
|
4613
|
+
reason,
|
|
4614
|
+
detail
|
|
4615
|
+
});
|
|
4616
|
+
const turnState = context.turnState;
|
|
4617
|
+
if (!turnState || turnState.turnId !== input.expectedTurnId || context.session.activeTurnId !== input.expectedTurnId || turnState.interruptRequested) return yield* refuse("turn-ended", STEER_TURN_ENDED_DETAIL);
|
|
4618
|
+
if (context.pendingApprovals.size > 0 || context.pendingUserInputs.size > 0) return yield* refuse("busy", "Claude is waiting for an approval or answer. The message stays queued.");
|
|
4619
|
+
if (!context.cliCapabilities?.has("interrupt_receipt_v1")) return yield* refuse("unsupported", "This Claude Code version can't steer a running turn. The message stays queued.");
|
|
4620
|
+
if (input.input?.trimStart().startsWith("/")) return yield* refuse("unsupported", "Slash commands can't be steered into a running turn. The message stays queued.");
|
|
4621
|
+
const message = yield* buildUserMessageEffect({
|
|
4622
|
+
threadId: input.threadId,
|
|
4623
|
+
...input.input ? { input: input.input } : {},
|
|
4624
|
+
attachments: input.attachments ?? [],
|
|
4625
|
+
...context.cacheModelSelection ? { modelSelection: context.cacheModelSelection } : {}
|
|
4626
|
+
}, {
|
|
4627
|
+
fileSystem,
|
|
4628
|
+
attachmentsDir: serverConfig.attachmentsDir,
|
|
4629
|
+
boundInstanceId
|
|
4630
|
+
});
|
|
4631
|
+
const steerUuid = yield* Effect.sync(() => crypto.randomUUID());
|
|
4632
|
+
if (!(yield* context.turnLock.withPermits(1)(Effect.gen(function* () {
|
|
4633
|
+
if (sessions.get(input.threadId) !== context || context.stopped || context.turnState !== turnState || turnState.interruptRequested || turnState.completion !== void 0) return false;
|
|
4634
|
+
turnState.steerPromptUuids.add(steerUuid);
|
|
4635
|
+
const offered = yield* Queue.offer(context.promptQueue, {
|
|
4636
|
+
type: "message",
|
|
4637
|
+
message: {
|
|
4638
|
+
...message,
|
|
4639
|
+
uuid: steerUuid,
|
|
4640
|
+
priority: "now"
|
|
4641
|
+
}
|
|
4642
|
+
});
|
|
4643
|
+
if (!offered) turnState.steerPromptUuids.delete(steerUuid);
|
|
4644
|
+
return offered;
|
|
4645
|
+
})))) return yield* refuse("turn-ended", STEER_TURN_ENDED_DETAIL);
|
|
4646
|
+
yield* Effect.logInfo("claude.turn.steered", {
|
|
4647
|
+
threadId: input.threadId,
|
|
4648
|
+
turnId: turnState.turnId,
|
|
4649
|
+
awaiting: turnState.awaitingSteerContinuation !== void 0
|
|
4650
|
+
});
|
|
4651
|
+
return {
|
|
4652
|
+
threadId: context.session.threadId,
|
|
4653
|
+
turnId: turnState.turnId
|
|
4654
|
+
};
|
|
4655
|
+
});
|
|
4656
|
+
const interruptTurn = Effect.fn("interruptTurn")(function* (threadId, turnId) {
|
|
3617
4657
|
const context = yield* requireSession(threadId);
|
|
3618
|
-
|
|
4658
|
+
const target = context.turnState;
|
|
4659
|
+
if (target) target.interruptRequested = true;
|
|
4660
|
+
if (context.agentControl) yield* context.agentControl.retireTurn(turnId);
|
|
3619
4661
|
if (context.query.stopTask && context.liveTaskIds.size > 0) {
|
|
3620
4662
|
const liveIds = Array.from(context.liveTaskIds);
|
|
3621
4663
|
yield* Effect.forEach(liveIds, (taskId) => Effect.gen(function* () {
|
|
@@ -3644,10 +4686,47 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
3644
4686
|
discard: true
|
|
3645
4687
|
}).pipe(Effect.timeoutOption("10 seconds"), Effect.ignore);
|
|
3646
4688
|
}
|
|
3647
|
-
|
|
3648
|
-
|
|
4689
|
+
const cancelQueued = (target ? [...target.steerPromptUuids].filter((uuid) => !target.settledSteerPromptUuids.has(uuid)) : []).length > 0 && context.cliCapabilities?.has("interrupt_cancel_queued_v1") === true;
|
|
4690
|
+
const rawReceipt = yield* Effect.tryPromise({
|
|
4691
|
+
try: () => cancelQueued ? context.query.interrupt({ cancelQueued: true }) : context.query.interrupt(),
|
|
3649
4692
|
catch: (cause) => toRequestError(threadId, "turn/interrupt", cause)
|
|
3650
4693
|
});
|
|
4694
|
+
if (target !== void 0 && target.steerPromptUuids.size > 0) {
|
|
4695
|
+
const receipt = readClaudeInterruptReceipt(rawReceipt);
|
|
4696
|
+
yield* Effect.logInfo("claude.turn.interrupt-receipt", {
|
|
4697
|
+
threadId: context.session.threadId,
|
|
4698
|
+
turnId: target.turnId,
|
|
4699
|
+
cancelQueued,
|
|
4700
|
+
hasReceipt: receipt !== void 0,
|
|
4701
|
+
stillQueued: receipt?.stillQueued.length ?? 0,
|
|
4702
|
+
cancelled: receipt?.cancelled?.length ?? 0
|
|
4703
|
+
});
|
|
4704
|
+
yield* context.turnLock.withPermits(1)(Effect.gen(function* () {
|
|
4705
|
+
if (context.stopped) return;
|
|
4706
|
+
const stop = decideClaudeStop({
|
|
4707
|
+
unsettledSteers: [...target.steerPromptUuids].filter((uuid) => !target.settledSteerPromptUuids.has(uuid)),
|
|
4708
|
+
startedSteers: target.startedSteerPromptUuids,
|
|
4709
|
+
promptUuid: target.promptUuid,
|
|
4710
|
+
sealedSegmentCount: target.sealedSegmentCount,
|
|
4711
|
+
awaitingSteerContinuation: target.awaitingSteerContinuation !== void 0,
|
|
4712
|
+
receipt
|
|
4713
|
+
});
|
|
4714
|
+
if (context.turnState === target) for (const uuid of stop.discard) rememberDiscardedSteer(context.discardedSteerPromptUuids, uuid);
|
|
4715
|
+
for (const uuid of stop.release) {
|
|
4716
|
+
context.discardedSteerPromptUuids.delete(uuid);
|
|
4717
|
+
target.settledSteerPromptUuids.add(uuid);
|
|
4718
|
+
}
|
|
4719
|
+
if (stop.forceClose && context.turnState === target) yield* completeTurn(context, "interrupted", "Interrupted by user.", void 0, { expectedTurnState: target });
|
|
4720
|
+
}));
|
|
4721
|
+
}
|
|
4722
|
+
if (target !== void 0 && target.openedBy !== "prompt" && (turnId === void 0 || target.turnId === turnId)) yield* Effect.sleep(Duration.millis(CLAUDE_PROVIDER_TURN_STOP_GRACE_MS)).pipe(Effect.andThen(Effect.suspend(() => {
|
|
4723
|
+
if (context.turnState !== target || target.completion !== void 0 || context.stopped) return Effect.void;
|
|
4724
|
+
return Effect.logInfo("claude.turn.provider-turn-finalized-after-stop", {
|
|
4725
|
+
threadId: context.session.threadId,
|
|
4726
|
+
turnId: target.turnId,
|
|
4727
|
+
openedBy: target.openedBy
|
|
4728
|
+
}).pipe(Effect.andThen(completeTurn(context, "interrupted", PROVIDER_TURN_STOP_REASON)));
|
|
4729
|
+
})), Effect.ignoreCause({ log: true }), Effect.forkDetach);
|
|
3651
4730
|
});
|
|
3652
4731
|
const stopBackgroundTask = Effect.fn("stopBackgroundTask")(function* (threadId, taskId, expected) {
|
|
3653
4732
|
const context = yield* requireSession(threadId);
|
|
@@ -3682,12 +4761,109 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
3682
4761
|
const context = yield* requireSession(threadId);
|
|
3683
4762
|
return yield* snapshotThread(context);
|
|
3684
4763
|
});
|
|
3685
|
-
|
|
4764
|
+
/** The session's main transcript chain, oldest first. Errors and timeouts read as empty. */
|
|
4765
|
+
const readMainTranscriptChain = Effect.fn("readMainTranscriptChain")(function* (sessionId, cwd) {
|
|
4766
|
+
const read = (dir) => Effect.tryPromise(() => readSessionMessages(sessionId, {
|
|
4767
|
+
...dir !== void 0 ? { dir } : {},
|
|
4768
|
+
includeSystemMessages: true
|
|
4769
|
+
})).pipe(Effect.timeoutOption(CLAUDE_REWIND_TRANSCRIPT_TIMEOUT), Effect.map((entries) => Option.getOrElse(entries, () => [])), Effect.catch(() => Effect.succeed([])), Effect.map((entries) => entries.filter((entry) => typeof entry.uuid === "string" && (entry.parent_tool_use_id === null || entry.parent_tool_use_id === void 0))));
|
|
4770
|
+
const inCwd = yield* read(cwd);
|
|
4771
|
+
return inCwd.length > 0 || cwd === void 0 ? inCwd : yield* read(void 0);
|
|
4772
|
+
});
|
|
4773
|
+
/**
|
|
4774
|
+
* Makes Claude forget the newest turns: close the live query, wait for the
|
|
4775
|
+
* CLI to exit, and reopen the transcript truncated just before the first
|
|
4776
|
+
* dropped prompt (or a fresh session for checkpoint 0). A reopen the CLI
|
|
4777
|
+
* refuses restores the previous conversation and reports the refusal.
|
|
4778
|
+
*/
|
|
4779
|
+
const rollbackThread = Effect.fn("rollbackThread")(function* (threadId, input) {
|
|
3686
4780
|
const context = yield* requireSession(threadId);
|
|
3687
|
-
const
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
4781
|
+
const refuse = (detail) => new ProviderAdapterRequestError({
|
|
4782
|
+
provider: PROVIDER,
|
|
4783
|
+
method: "thread/rollback",
|
|
4784
|
+
detail
|
|
4785
|
+
});
|
|
4786
|
+
if (context.turnState) return yield* refuse("A Claude turn is still running.");
|
|
4787
|
+
if (context.liveTaskIds.size > 0) return yield* refuse("Claude still has background tasks running. Stop them, then revert again.");
|
|
4788
|
+
if (context.pendingApprovals.size > 0 || context.pendingUserInputs.size > 0) return yield* refuse("Claude is waiting for your answer. Answer it, then revert again.");
|
|
4789
|
+
if (rewindingThreads.has(threadId)) return yield* refuse("Claude is already rewinding this thread.");
|
|
4790
|
+
let plan;
|
|
4791
|
+
if (input.targetTurnId === null) plan = { kind: "fresh" };
|
|
4792
|
+
else {
|
|
4793
|
+
const firstDropped = input.droppedTurnIds[0];
|
|
4794
|
+
const chain = context.resumeSessionId !== void 0 && firstDropped !== void 0 ? yield* readMainTranscriptChain(context.resumeSessionId, context.session.cwd) : [];
|
|
4795
|
+
const index = firstDropped === void 0 ? -1 : chain.findIndex((entry) => entry.uuid === firstDropped);
|
|
4796
|
+
if (index > 0) plan = {
|
|
4797
|
+
kind: "rewind",
|
|
4798
|
+
at: chain[index - 1].uuid,
|
|
4799
|
+
...input.droppedTurnIds.length === 1 && firstDropped !== void 0 ? { dropsTurn: firstDropped } : {}
|
|
4800
|
+
};
|
|
4801
|
+
else if (index === 0) plan = { kind: "fresh" };
|
|
4802
|
+
else {
|
|
4803
|
+
const head = context.turnHeads.find((entry) => entry.turnId === input.targetTurnId)?.head;
|
|
4804
|
+
if (head !== void 0) plan = {
|
|
4805
|
+
kind: "rewind",
|
|
4806
|
+
at: head
|
|
4807
|
+
};
|
|
4808
|
+
}
|
|
4809
|
+
}
|
|
4810
|
+
if (plan === void 0) return yield* refuse("Claude has no recorded transcript position for this checkpoint. Revert to an earlier checkpoint or start a new thread.");
|
|
4811
|
+
const rewindPlan = plan;
|
|
4812
|
+
rewindingThreads.add(threadId);
|
|
4813
|
+
return yield* Effect.gen(function* () {
|
|
4814
|
+
const previousCursor = context.session.resumeCursor;
|
|
4815
|
+
const dropped = new Set(input.droppedTurnIds);
|
|
4816
|
+
const keptTurnHeads = context.turnHeads.filter((entry) => !dropped.has(entry.turnId));
|
|
4817
|
+
yield* stopSessionInternal(context, {
|
|
4818
|
+
emitExitEvent: false,
|
|
4819
|
+
awaitQueryExitMs: CLAUDE_REWIND_QUERY_EXIT_MS
|
|
4820
|
+
});
|
|
4821
|
+
const previousTurnCount = readClaudeResumeState(previousCursor)?.turnCount ?? context.turns.length;
|
|
4822
|
+
const nextCursor = rewindPlan.kind === "fresh" || context.resumeSessionId === void 0 ? { threadId } : {
|
|
4823
|
+
threadId,
|
|
4824
|
+
resume: context.resumeSessionId,
|
|
4825
|
+
rewind: { at: rewindPlan.at },
|
|
4826
|
+
turnCount: Math.max(0, previousTurnCount - input.numTurns)
|
|
4827
|
+
};
|
|
4828
|
+
const reopenInput = {
|
|
4829
|
+
...context.startInput,
|
|
4830
|
+
runtimeMode: context.session.runtimeMode,
|
|
4831
|
+
...context.session.tokenMode !== void 0 ? { tokenMode: context.session.tokenMode } : {},
|
|
4832
|
+
...context.cacheModelSelection ?? context.startInput.modelSelection ? { modelSelection: context.cacheModelSelection ?? context.startInput.modelSelection } : {},
|
|
4833
|
+
...context.session.runtimeSessionId !== void 0 ? { runtimeSessionId: context.session.runtimeSessionId } : {}
|
|
4834
|
+
};
|
|
4835
|
+
const reopened = yield* Effect.result(openSessionContext({
|
|
4836
|
+
...reopenInput,
|
|
4837
|
+
resumeCursor: nextCursor
|
|
4838
|
+
}, {
|
|
4839
|
+
probe: true,
|
|
4840
|
+
turnHeads: keptTurnHeads
|
|
4841
|
+
}));
|
|
4842
|
+
if (reopened._tag === "Success") return yield* snapshotThread(reopened.success);
|
|
4843
|
+
const refusal = adapterFailureDetail(reopened.failure);
|
|
4844
|
+
if ((yield* Effect.result(openSessionContext({
|
|
4845
|
+
...reopenInput,
|
|
4846
|
+
resumeCursor: previousCursor
|
|
4847
|
+
}, {
|
|
4848
|
+
probe: true,
|
|
4849
|
+
turnHeads: context.turnHeads
|
|
4850
|
+
})))._tag === "Failure") {
|
|
4851
|
+
const stamp = yield* makeEventStamp();
|
|
4852
|
+
yield* offerRuntimeEventForContext(context, {
|
|
4853
|
+
type: "session.exited",
|
|
4854
|
+
eventId: stamp.eventId,
|
|
4855
|
+
provider: PROVIDER,
|
|
4856
|
+
createdAt: stamp.createdAt,
|
|
4857
|
+
threadId,
|
|
4858
|
+
payload: {
|
|
4859
|
+
reason: "Claude could not restart after a failed rewind",
|
|
4860
|
+
exitKind: "error"
|
|
4861
|
+
},
|
|
4862
|
+
providerRefs: {}
|
|
4863
|
+
});
|
|
4864
|
+
}
|
|
4865
|
+
return yield* refuse(`Claude refused to rewind this conversation, so nothing was changed. ${refusal}`);
|
|
4866
|
+
}).pipe(Effect.ensuring(Effect.sync(() => rewindingThreads.delete(threadId))));
|
|
3691
4867
|
});
|
|
3692
4868
|
const respondToRequest = Effect.fn("respondToRequest")(function* (threadId, requestId, decision) {
|
|
3693
4869
|
const context = yield* requireSession(threadId);
|
|
@@ -3724,9 +4900,15 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
3724
4900
|
yield* Effect.addFinalizer(() => Effect.forEach(sessions, ([, context]) => stopSessionInternal(context, { emitExitEvent: false }), { discard: true }).pipe(Effect.tap(() => runtimeEventQueueMetrics.reset), Effect.tap(() => Queue.shutdown(runtimeEventQueue))));
|
|
3725
4901
|
return {
|
|
3726
4902
|
provider: PROVIDER,
|
|
3727
|
-
capabilities: {
|
|
4903
|
+
capabilities: {
|
|
4904
|
+
sessionModelSwitch: "in-session",
|
|
4905
|
+
conversationRollback: "native",
|
|
4906
|
+
turnSteering: "native",
|
|
4907
|
+
resumeSurvivesCwdChange: false
|
|
4908
|
+
},
|
|
3728
4909
|
startSession,
|
|
3729
4910
|
sendTurn,
|
|
4911
|
+
steerTurn,
|
|
3730
4912
|
interruptTurn,
|
|
3731
4913
|
stopBackgroundTask,
|
|
3732
4914
|
readThread,
|