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,23 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
const require_rolldown_runtime = require("./rolldown-runtime-
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const require_git = require("./git-Dn5wrgFY.cjs");
|
|
3
|
+
const require_rolldown_runtime = require("./rolldown-runtime-HbSU0i7K.cjs");
|
|
4
|
+
const require_Metrics = require("./Metrics-DjRPLE98.cjs");
|
|
5
|
+
const require_src = require("./src-FmeCeBJ9.cjs");
|
|
7
6
|
const require_bin = require("./bin.cjs");
|
|
8
7
|
const require_runtimeSession = require("./runtimeSession-Bj0OUcNJ.cjs");
|
|
9
8
|
const require_ProviderDriver = require("./ProviderDriver--rNeAi3B.cjs");
|
|
10
|
-
const require_SideQuestionIsolation = require("./SideQuestionIsolation-
|
|
9
|
+
const require_SideQuestionIsolation = require("./SideQuestionIsolation-BPC-Bxsz.cjs");
|
|
11
10
|
const require_sourceControlContextFormatter = require("./sourceControlContextFormatter-BDZqn-4T.cjs");
|
|
12
11
|
const require_ProjectCustomSystemPrompt = require("./ProjectCustomSystemPrompt-B8SUlNGa.cjs");
|
|
13
|
-
const require_makeManagedServerProvider = require("./makeManagedServerProvider-
|
|
12
|
+
const require_makeManagedServerProvider = require("./makeManagedServerProvider-B5tP7tvg.cjs");
|
|
14
13
|
let effect = require("effect");
|
|
15
|
-
let
|
|
14
|
+
let node_child_process = require("node:child_process");
|
|
16
15
|
let node_path = require("node:path");
|
|
17
16
|
node_path = require_rolldown_runtime.__toESM(node_path, 1);
|
|
17
|
+
let effect_unstable_http = require("effect/unstable/http");
|
|
18
18
|
let node_os = require("node:os");
|
|
19
19
|
node_os = require_rolldown_runtime.__toESM(node_os, 1);
|
|
20
|
-
let node_child_process = require("node:child_process");
|
|
21
20
|
let node_fs_promises = require("node:fs/promises");
|
|
22
21
|
node_fs_promises = require_rolldown_runtime.__toESM(node_fs_promises, 1);
|
|
23
22
|
let effect_unstable_process = require("effect/unstable/process");
|
|
@@ -28,7 +27,8 @@ const PROVIDER$1 = require_src.ProviderDriverKind.make("claudeAgent");
|
|
|
28
27
|
const CLAUDE_PRESENTATION = {
|
|
29
28
|
displayName: "Claude",
|
|
30
29
|
showInteractionModeToggle: true,
|
|
31
|
-
supportsAskMode: true
|
|
30
|
+
supportsAskMode: true,
|
|
31
|
+
supportsTurnSteering: true
|
|
32
32
|
};
|
|
33
33
|
function getClaudeModelCapabilities(model) {
|
|
34
34
|
const capabilities = require_bin.getClaudeCatalogModelCapabilities(require_bin.getActiveClaudeModelCatalog(), model);
|
|
@@ -488,7 +488,7 @@ const makeClaudeTextGeneration = effect.Effect.fn("makeClaudeTextGeneration")(fu
|
|
|
488
488
|
return {
|
|
489
489
|
subject: require_bin.sanitizeCommitSubject(generated.subject),
|
|
490
490
|
body: generated.body.trim(),
|
|
491
|
-
..."branch" in generated && typeof generated.branch === "string" ? { branch:
|
|
491
|
+
..."branch" in generated && typeof generated.branch === "string" ? { branch: require_bin.sanitizeFeatureBranchName(generated.branch) } : {}
|
|
492
492
|
};
|
|
493
493
|
});
|
|
494
494
|
const generatePrContent = effect.Effect.fn("ClaudeTextGeneration.generatePrContent")(function* (input) {
|
|
@@ -523,7 +523,7 @@ const makeClaudeTextGeneration = effect.Effect.fn("makeClaudeTextGeneration")(fu
|
|
|
523
523
|
outputSchemaJson: outputSchema,
|
|
524
524
|
modelSelection: input.modelSelection
|
|
525
525
|
});
|
|
526
|
-
return { branch:
|
|
526
|
+
return { branch: require_bin.sanitizeBranchFragment(generated.branch) };
|
|
527
527
|
});
|
|
528
528
|
const generateThreadTitle = effect.Effect.fn("ClaudeTextGeneration.generateThreadTitle")(function* (input) {
|
|
529
529
|
const { prompt, outputSchema } = require_bin.buildThreadTitlePrompt({
|
|
@@ -629,6 +629,7 @@ function observeClaudeCache(input) {
|
|
|
629
629
|
providerInstanceId: input.providerInstanceId,
|
|
630
630
|
model: input.model,
|
|
631
631
|
...input.modelSelection ? { modelSelection: input.modelSelection } : {},
|
|
632
|
+
...input.cwd ? { cwd: input.cwd } : {},
|
|
632
633
|
messageId: input.messageId,
|
|
633
634
|
directInputTokens: counts.directInputTokens,
|
|
634
635
|
cacheReadInputTokens: counts.cacheReadInputTokens,
|
|
@@ -637,6 +638,278 @@ function observeClaudeCache(input) {
|
|
|
637
638
|
};
|
|
638
639
|
}
|
|
639
640
|
//#endregion
|
|
641
|
+
//#region src/provider/claudeContextUsage.ts
|
|
642
|
+
function knownContextWindow(value) {
|
|
643
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : void 0;
|
|
644
|
+
}
|
|
645
|
+
/**
|
|
646
|
+
* `compact_boundary.compact_metadata.post_tokens` as a context gauge; undefined when absent or
|
|
647
|
+
* invalid. Compaction invalidated the cache evidence, so the gauge never carries `claudeCache`.
|
|
648
|
+
*/
|
|
649
|
+
function claudePostCompactionUsage(compactMetadata, contextWindow) {
|
|
650
|
+
if (compactMetadata === null || typeof compactMetadata !== "object") return;
|
|
651
|
+
const postTokens = compactMetadata.post_tokens;
|
|
652
|
+
if (typeof postTokens !== "number" || !Number.isFinite(postTokens)) return;
|
|
653
|
+
const rounded = Math.round(postTokens);
|
|
654
|
+
if (rounded <= 0) return;
|
|
655
|
+
const maxTokens = knownContextWindow(contextWindow);
|
|
656
|
+
return {
|
|
657
|
+
usedTokens: maxTokens !== void 0 ? Math.min(rounded, maxTokens) : rounded,
|
|
658
|
+
...maxTokens !== void 0 ? { maxTokens } : {}
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
/**
|
|
662
|
+
* The gauge a Claude result publishes. `result.usage` is cumulative across every API call of the
|
|
663
|
+
* turn, so the last main-loop gauge wins and the cumulative figure only rides along as
|
|
664
|
+
* `totalProcessedTokens`. Without a gauge the cumulative snapshot is a fallback, but never for a
|
|
665
|
+
* turn that crossed a compaction boundary: its cumulative input is the pre-compaction size.
|
|
666
|
+
*/
|
|
667
|
+
function selectClaudeResultUsageGauge(input) {
|
|
668
|
+
const { lastGauge, cumulative, maxTokens } = input;
|
|
669
|
+
if (lastGauge === void 0) return input.cumulativeIsGauge ? cumulative : void 0;
|
|
670
|
+
const cumulativeTotal = cumulative?.totalProcessedTokens ?? cumulative?.usedTokens;
|
|
671
|
+
return {
|
|
672
|
+
...lastGauge,
|
|
673
|
+
...typeof maxTokens === "number" && Number.isFinite(maxTokens) && maxTokens > 0 ? { maxTokens } : {},
|
|
674
|
+
...typeof cumulativeTotal === "number" && Number.isFinite(cumulativeTotal) && cumulativeTotal > lastGauge.usedTokens ? { totalProcessedTokens: cumulativeTotal } : {}
|
|
675
|
+
};
|
|
676
|
+
}
|
|
677
|
+
const ABORT_TERMINAL_REASONS = /* @__PURE__ */ new Set(["aborted_streaming", "aborted_tools"]);
|
|
678
|
+
function resultErrorsText(result) {
|
|
679
|
+
return "errors" in result && Array.isArray(result.errors) ? result.errors.join(" ").toLowerCase() : "";
|
|
680
|
+
}
|
|
681
|
+
function isInterruptedResult(result) {
|
|
682
|
+
const errors = resultErrorsText(result);
|
|
683
|
+
if (errors.includes("interrupt")) return true;
|
|
684
|
+
return result.subtype === "error_during_execution" && result.is_error === false && (errors.includes("request was aborted") || errors.includes("interrupted by user") || errors.includes("aborted"));
|
|
685
|
+
}
|
|
686
|
+
/** The CLI ended the segment by aborting it (a Stop or a `priority: "now"` steer). */
|
|
687
|
+
function isClaudeAbortTerminalReason(result) {
|
|
688
|
+
const terminalReason = Reflect.get(result, "terminal_reason");
|
|
689
|
+
return typeof terminalReason === "string" && ABORT_TERMINAL_REASONS.has(terminalReason);
|
|
690
|
+
}
|
|
691
|
+
function readStringArray(value) {
|
|
692
|
+
return Array.isArray(value) && value.every((entry) => typeof entry === "string") ? value : void 0;
|
|
693
|
+
}
|
|
694
|
+
function isRootFrame$1(message) {
|
|
695
|
+
const parentToolUseId = Reflect.get(message, "parent_tool_use_id");
|
|
696
|
+
return parentToolUseId === null || parentToolUseId === void 0;
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* The prompt uuids a frame echoes. Results echo every user message the CLI turn consumed. The
|
|
700
|
+
* CLI turn's first reply frame echoes the messages that started it (early echo): its first
|
|
701
|
+
* non-ping stream event, or its first root assistant message when it streamed nothing (a request
|
|
702
|
+
* that failed at the API replies with a synthetic error message).
|
|
703
|
+
*/
|
|
704
|
+
function claudeEchoedPromptUuids(message) {
|
|
705
|
+
if (message.type !== "result" && message.type !== "stream_event" && !(message.type === "assistant" && isRootFrame$1(message))) return [];
|
|
706
|
+
const uuids = readStringArray(Reflect.get(message, "user_message_uuids"));
|
|
707
|
+
if (uuids !== void 0 && uuids.length > 0) return uuids;
|
|
708
|
+
const uuid = Reflect.get(message, "user_message_uuid");
|
|
709
|
+
return typeof uuid === "string" && uuid.length > 0 ? [uuid] : [];
|
|
710
|
+
}
|
|
711
|
+
function classifyClaudeResultKind(result) {
|
|
712
|
+
if (result.subtype === "success" && !result.is_error) return "success";
|
|
713
|
+
if (isClaudeAbortTerminalReason(result)) return "abort";
|
|
714
|
+
if (Reflect.get(result, "terminal_reason") === void 0 && isInterruptedResult(result)) return "abort";
|
|
715
|
+
return "failure";
|
|
716
|
+
}
|
|
717
|
+
/** Whether an echo names the turn's prompt or one of its steers. */
|
|
718
|
+
function claudeEchoNamesTurn(input) {
|
|
719
|
+
return input.echoed.some((uuid) => uuid === input.promptUuid || input.steerPromptUuids.has(uuid));
|
|
720
|
+
}
|
|
721
|
+
/**
|
|
722
|
+
* Whether a result belongs to the open prompt turn. It does when it echoes the prompt or any of
|
|
723
|
+
* the turn's steers. Without an echo (older CLIs) it belongs unless its origin is not human.
|
|
724
|
+
* Callers skip the check for provider turns (no prompt uuid).
|
|
725
|
+
*/
|
|
726
|
+
function claudeResultBelongsToTurn(input) {
|
|
727
|
+
if (input.echoed.length > 0) return claudeEchoNamesTurn(input);
|
|
728
|
+
return input.origin === void 0 || input.origin.kind === "human";
|
|
729
|
+
}
|
|
730
|
+
/**
|
|
731
|
+
* The turn waits only when Stop was not requested, a steer is still unsettled, the segment ended
|
|
732
|
+
* by abort or success, and the CLI positively promised another result (`queued_turn_count > 0`).
|
|
733
|
+
* Every other result completes the turn, so no waiting is unbounded.
|
|
734
|
+
*/
|
|
735
|
+
function decideClaudeTurnResult(input) {
|
|
736
|
+
const echoed = new Set(input.echoedPromptUuids);
|
|
737
|
+
const newlySettled = [];
|
|
738
|
+
const unsettled = [];
|
|
739
|
+
for (const uuid of input.steerPromptUuids) {
|
|
740
|
+
if (input.settledSteerPromptUuids.has(uuid)) continue;
|
|
741
|
+
if (echoed.has(uuid)) newlySettled.push(uuid);
|
|
742
|
+
else unsettled.push(uuid);
|
|
743
|
+
}
|
|
744
|
+
const awaitSteer = !input.interruptRequested && unsettled.length > 0 && (input.kind === "abort" || input.kind === "success") && typeof input.queuedTurnCount === "number" && input.queuedTurnCount > 0;
|
|
745
|
+
const completingWithSteers = !awaitSteer && unsettled.length > 0;
|
|
746
|
+
return {
|
|
747
|
+
decision: awaitSteer ? "await-steer" : "complete",
|
|
748
|
+
newlySettled,
|
|
749
|
+
unsettled,
|
|
750
|
+
discardUnsettled: completingWithSteers && (input.interruptRequested || input.kind === "failure"),
|
|
751
|
+
abortedBySteer: completingWithSteers && !input.interruptRequested && input.kind === "abort"
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* The status a completing turn reports. It follows the result except where the result's status
|
|
756
|
+
* would misstate what happened to the turn: Ryco's own discard re-interrupt or a steer's abort is
|
|
757
|
+
* never a Stop (which would hold the client queue), a Stop always ends as interrupted, and a
|
|
758
|
+
* failure that drops a pending steer is always reported as one (so the queue holds and the user
|
|
759
|
+
* sees why the steer got no reply).
|
|
760
|
+
*/
|
|
761
|
+
function decideClaudeTurnClose(input) {
|
|
762
|
+
if (input.foldedIntoDiscardedCliTurn) return input.interruptRequested ? {
|
|
763
|
+
status: "interrupted",
|
|
764
|
+
cause: "stopped"
|
|
765
|
+
} : {
|
|
766
|
+
status: "failed",
|
|
767
|
+
cause: "folded-into-discarded-cli-turn"
|
|
768
|
+
};
|
|
769
|
+
if (input.resultStatus === "completed") {
|
|
770
|
+
const endsSteerSegment = input.echoedPromptUuids.some((uuid) => input.steerPromptUuids.has(uuid)) && (input.promptUuid === void 0 || !input.echoedPromptUuids.includes(input.promptUuid));
|
|
771
|
+
if (input.interruptRequested && endsSteerSegment) return {
|
|
772
|
+
status: "interrupted",
|
|
773
|
+
cause: "stopped"
|
|
774
|
+
};
|
|
775
|
+
if (!input.interruptRequested && input.decision.discardUnsettled) return {
|
|
776
|
+
status: "failed",
|
|
777
|
+
cause: "failed-segment-dropped-steers"
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
if (input.decision.abortedBySteer) return {
|
|
781
|
+
status: "completed",
|
|
782
|
+
cause: "aborted-by-steer"
|
|
783
|
+
};
|
|
784
|
+
return {
|
|
785
|
+
status: input.resultStatus,
|
|
786
|
+
cause: "result"
|
|
787
|
+
};
|
|
788
|
+
}
|
|
789
|
+
/** Defensive: anything but a `still_queued` string array is "no receipt" (older CLIs). */
|
|
790
|
+
function readClaudeInterruptReceipt(value) {
|
|
791
|
+
if (value === null || typeof value !== "object") return void 0;
|
|
792
|
+
const stillQueued = readStringArray(Reflect.get(value, "still_queued"));
|
|
793
|
+
if (stillQueued === void 0) return void 0;
|
|
794
|
+
return {
|
|
795
|
+
stillQueued,
|
|
796
|
+
cancelled: readStringArray(Reflect.get(value, "cancelled"))
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
/**
|
|
800
|
+
* Stop with steers pending. A steer that already streamed into the turn, or that the receipt
|
|
801
|
+
* does not list as queued or cancelled (in transit), counts as running, so its own aborted
|
|
802
|
+
* result closes the turn. The discard and release lists hold whether or not the stopped turn is
|
|
803
|
+
* still open.
|
|
804
|
+
*/
|
|
805
|
+
function decideClaudeStop(input) {
|
|
806
|
+
if (input.receipt === void 0) return {
|
|
807
|
+
forceClose: input.awaitingSteerContinuation,
|
|
808
|
+
discard: [...input.unsettledSteers],
|
|
809
|
+
release: []
|
|
810
|
+
};
|
|
811
|
+
const cancelled = new Set(input.receipt.cancelled ?? []);
|
|
812
|
+
const outstanding = /* @__PURE__ */ new Set([...input.receipt.stillQueued, ...cancelled]);
|
|
813
|
+
const runningSteers = input.unsettledSteers.filter((uuid) => input.startedSteers.has(uuid) || !outstanding.has(uuid));
|
|
814
|
+
const isReleased = (uuid) => cancelled.has(uuid) && !input.startedSteers.has(uuid);
|
|
815
|
+
return {
|
|
816
|
+
forceClose: (input.sealedSegmentCount > 0 || input.promptUuid !== void 0 && cancelled.has(input.promptUuid)) && runningSteers.length === 0,
|
|
817
|
+
discard: input.unsettledSteers.filter((uuid) => !isReleased(uuid)),
|
|
818
|
+
release: input.unsettledSteers.filter(isReleased)
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
/** FIFO-bounded insert. */
|
|
822
|
+
function rememberDiscardedSteer(set, uuid, cap = 64) {
|
|
823
|
+
if (set.has(uuid)) return;
|
|
824
|
+
while (set.size >= cap) {
|
|
825
|
+
const oldest = set.values().next();
|
|
826
|
+
if (oldest.done) break;
|
|
827
|
+
set.delete(oldest.value);
|
|
828
|
+
}
|
|
829
|
+
set.add(uuid);
|
|
830
|
+
}
|
|
831
|
+
/** Capabilities a CLI advertises on `system/init`; empty when the field is absent. */
|
|
832
|
+
function parseClaudeCliCapabilities(initMessage) {
|
|
833
|
+
const capabilities = Reflect.get(initMessage, "capabilities");
|
|
834
|
+
return new Set(Array.isArray(capabilities) ? capabilities.filter((entry) => typeof entry === "string") : []);
|
|
835
|
+
}
|
|
836
|
+
/**
|
|
837
|
+
* Root model-turn content frames: a CLI segment's output, as opposed to system, subagent or
|
|
838
|
+
* keep-alive frames. A CLI turn's first such frame carries its echo: a stream event, or the
|
|
839
|
+
* assistant message when nothing streamed. System frames (`api_retry`, compaction) carry no
|
|
840
|
+
* echo, so they never qualify.
|
|
841
|
+
*/
|
|
842
|
+
function isClaudeRootTurnFrame(message) {
|
|
843
|
+
if (message.type !== "stream_event" && message.type !== "assistant" && message.type !== "user") return false;
|
|
844
|
+
if (message.type === "stream_event") {
|
|
845
|
+
const event = Reflect.get(message, "event");
|
|
846
|
+
if (typeof event === "object" && event !== null && Reflect.get(event, "type") === "ping") return false;
|
|
847
|
+
}
|
|
848
|
+
return isRootFrame$1(message);
|
|
849
|
+
}
|
|
850
|
+
/**
|
|
851
|
+
* A synthetic API-error reply: the request failed after its retries and the CLI turn ends with
|
|
852
|
+
* the next result, so interrupting it again could only reach whatever the CLI runs next.
|
|
853
|
+
* `max_output_tokens` is excluded because the CLI can continue that turn.
|
|
854
|
+
*/
|
|
855
|
+
function isClaudeApiErrorReply(message) {
|
|
856
|
+
if (message.type !== "assistant") return false;
|
|
857
|
+
const error = Reflect.get(message, "error");
|
|
858
|
+
return typeof error === "string" && error !== "max_output_tokens";
|
|
859
|
+
}
|
|
860
|
+
//#endregion
|
|
861
|
+
//#region src/provider/claudeWakeTurn.ts
|
|
862
|
+
/**
|
|
863
|
+
* Claude can start a turn without a prompt (a "wake"): background work finished, a schedule or
|
|
864
|
+
* monitor fired, a rate limit lifted. These rules decide when such a provider turn opens and
|
|
865
|
+
* which frames prove it is alive.
|
|
866
|
+
*/
|
|
867
|
+
/** Longest a wake-signal turn may stay open without any root output before it is aborted. */
|
|
868
|
+
const CLAUDE_WAKE_TURN_FIRST_OUTPUT_TIMEOUT_MS = 12e4;
|
|
869
|
+
/** How long Stop waits for the CLI to end a provider turn before finishing it locally. */
|
|
870
|
+
const CLAUDE_PROVIDER_TURN_STOP_GRACE_MS = 5e3;
|
|
871
|
+
function isRootFrame(message) {
|
|
872
|
+
const parentToolUseId = message.parent_tool_use_id;
|
|
873
|
+
return parentToolUseId === null || parentToolUseId === void 0;
|
|
874
|
+
}
|
|
875
|
+
/**
|
|
876
|
+
* Root system/status (requesting|compacting) → "status"; root system/init → "init"; else
|
|
877
|
+
* undefined. A frame with a non-null parent_tool_use_id is never a signal.
|
|
878
|
+
*/
|
|
879
|
+
function claudeWakeSignal(message) {
|
|
880
|
+
if (message.type !== "system" || !isRootFrame(message)) return;
|
|
881
|
+
if (message.subtype === "status") return message.status === "requesting" || message.status === "compacting" ? "status" : void 0;
|
|
882
|
+
return message.subtype === "init" ? "init" : void 0;
|
|
883
|
+
}
|
|
884
|
+
/**
|
|
885
|
+
* Deny-list gate; "init" opens only when the CLI was never seen to emit `status: requesting`
|
|
886
|
+
* (legacy CLIs). There is deliberately no allow list: every kind of wake is covered.
|
|
887
|
+
*/
|
|
888
|
+
function shouldOpenClaudeWakeTurn(gate) {
|
|
889
|
+
if (gate.hasOpenTurn || gate.sessionStopped || !gate.promptSent || gate.turnInstallsInFlight > 0) return false;
|
|
890
|
+
return gate.signal === "status" || !gate.requestingStatusObserved;
|
|
891
|
+
}
|
|
892
|
+
/**
|
|
893
|
+
* Root frames that prove Claude is producing the current turn (watchdog liveness). A positive
|
|
894
|
+
* list, so a future periodic background frame cannot keep a phantom turn alive.
|
|
895
|
+
*/
|
|
896
|
+
function isClaudeRootTurnOutput(message) {
|
|
897
|
+
if (!isRootFrame(message)) return false;
|
|
898
|
+
switch (message.type) {
|
|
899
|
+
case "stream_event":
|
|
900
|
+
case "assistant":
|
|
901
|
+
case "user":
|
|
902
|
+
case "result": return true;
|
|
903
|
+
case "system": switch (message.subtype) {
|
|
904
|
+
case "compact_boundary":
|
|
905
|
+
case "api_retry": return true;
|
|
906
|
+
case "status": return message.status === "compacting";
|
|
907
|
+
default: return false;
|
|
908
|
+
}
|
|
909
|
+
default: return false;
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
//#endregion
|
|
640
913
|
//#region ../../packages/shared/src/cliArgs.ts
|
|
641
914
|
/**
|
|
642
915
|
* Parse CLI-style arguments into flags and positionals.
|
|
@@ -772,6 +1045,70 @@ function disableContextCompaction(state, generation) {
|
|
|
772
1045
|
};
|
|
773
1046
|
}
|
|
774
1047
|
//#endregion
|
|
1048
|
+
//#region src/provider/Layers/claudeUsageLimits.ts
|
|
1049
|
+
const CLAUDE_USAGE_LIMIT_FALLBACK_MESSAGE = "Claude usage limit reached.";
|
|
1050
|
+
const MESSAGE_MAX_LENGTH = 500;
|
|
1051
|
+
function resetIso(resetsAtSeconds) {
|
|
1052
|
+
if (resetsAtSeconds === void 0 || !Number.isFinite(resetsAtSeconds)) return null;
|
|
1053
|
+
const ms = resetsAtSeconds * 1e3;
|
|
1054
|
+
return require_bin.isRepresentableEpochMs(ms) ? new Date(ms).toISOString() : null;
|
|
1055
|
+
}
|
|
1056
|
+
/** Applies one `rate_limit_event` to the session's rejected windows. */
|
|
1057
|
+
function applyClaudeRateLimitInfo(windows, info) {
|
|
1058
|
+
const limitType = info.rateLimitType ?? "unknown";
|
|
1059
|
+
const overageAllowed = info.overageStatus === "allowed" || info.overageStatus === "allowed_warning" || info.isUsingOverage === true || info.overageInUse === true;
|
|
1060
|
+
const blocked = info.status === "rejected" && !overageAllowed;
|
|
1061
|
+
const resetAt = resetIso(info.resetsAt);
|
|
1062
|
+
if (blocked) windows.set(limitType, resetAt);
|
|
1063
|
+
else windows.delete(limitType);
|
|
1064
|
+
return {
|
|
1065
|
+
blocked,
|
|
1066
|
+
key: `${limitType}:${info.resetsAt ?? "unknown"}`,
|
|
1067
|
+
limitType,
|
|
1068
|
+
resetAt
|
|
1069
|
+
};
|
|
1070
|
+
}
|
|
1071
|
+
/** Current state of the rejected windows; windows whose known reset passed are ignored. */
|
|
1072
|
+
function claudeUsageLimitState(windows, nowMs) {
|
|
1073
|
+
return require_bin.usageLimitStateFromWindows([...windows.values()].map((resetAt) => ({
|
|
1074
|
+
exhausted: true,
|
|
1075
|
+
resetAtMs: resetAt === null ? null : Date.parse(resetAt)
|
|
1076
|
+
})), nowMs);
|
|
1077
|
+
}
|
|
1078
|
+
function trimmed(value) {
|
|
1079
|
+
if (typeof value !== "string") return void 0;
|
|
1080
|
+
const text = value.trim();
|
|
1081
|
+
return text.length > 0 ? text : void 0;
|
|
1082
|
+
}
|
|
1083
|
+
function limitMessage(result) {
|
|
1084
|
+
const message = (result.subtype === "success" ? trimmed(result.result) : trimmed(result.errors?.[0] ?? "")) ?? "Claude usage limit reached.";
|
|
1085
|
+
return message.length > MESSAGE_MAX_LENGTH ? message.slice(0, MESSAGE_MAX_LENGTH) : message;
|
|
1086
|
+
}
|
|
1087
|
+
/**
|
|
1088
|
+
* Whether a turn's result is a usage-limit stop. Only call it for a result that belongs
|
|
1089
|
+
* to an open turn and was not interrupted or cancelled.
|
|
1090
|
+
*/
|
|
1091
|
+
function classifyClaudeUsageLimitResult(input) {
|
|
1092
|
+
const { result } = input;
|
|
1093
|
+
const state = claudeUsageLimitState(input.windows, input.nowMs);
|
|
1094
|
+
const terminalReason = result.terminal_reason;
|
|
1095
|
+
if (terminalReason === "blocking_limit") return {
|
|
1096
|
+
message: limitMessage(result),
|
|
1097
|
+
resetAt: state.resetAt
|
|
1098
|
+
};
|
|
1099
|
+
if (!state.exhausted) return null;
|
|
1100
|
+
if (!(result.subtype !== "success" || result.is_error === true)) return null;
|
|
1101
|
+
if (terminalReason !== void 0 && terminalReason !== null && terminalReason !== "api_error") return null;
|
|
1102
|
+
if (result.subtype === "success") {
|
|
1103
|
+
const status = result.api_error_status;
|
|
1104
|
+
if (status !== void 0 && status !== null && status !== 429) return null;
|
|
1105
|
+
}
|
|
1106
|
+
return {
|
|
1107
|
+
message: limitMessage(result),
|
|
1108
|
+
resetAt: state.resetAt
|
|
1109
|
+
};
|
|
1110
|
+
}
|
|
1111
|
+
//#endregion
|
|
775
1112
|
//#region src/provider/Layers/ClaudeAdapter.ts
|
|
776
1113
|
/**
|
|
777
1114
|
* ClaudeAdapterLive - Scoped live implementation for the Claude Agent provider adapter.
|
|
@@ -782,20 +1119,49 @@ function disableContextCompaction(state, generation) {
|
|
|
782
1119
|
* @module ClaudeAdapterLive
|
|
783
1120
|
*/
|
|
784
1121
|
const PROVIDER = require_src.ProviderDriverKind.make("claudeAgent");
|
|
785
|
-
const
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
1122
|
+
const WAKE_NO_OUTPUT_REASON = "Claude started a background turn but produced no output.";
|
|
1123
|
+
const PROVIDER_TURN_STOP_REASON = "Claude did not end the background turn after Stop.";
|
|
1124
|
+
const DISCARDED_STEER_TURN_REASON = "Claude started a turn for a message Stop cancelled.";
|
|
1125
|
+
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.";
|
|
1126
|
+
const STEER_TURN_ENDED_DETAIL = "The turn finished before this message could be steered. It stays queued and is sent next.";
|
|
1127
|
+
const CLAUDE_TURN_HEADS_CAP = 64;
|
|
1128
|
+
const CLAUDE_REWIND_PROBE_TIMEOUT = "30 seconds";
|
|
1129
|
+
const CLAUDE_REWIND_TRANSCRIPT_TIMEOUT = "10 seconds";
|
|
1130
|
+
const CLAUDE_REWIND_QUERY_EXIT_MS = 5e3;
|
|
1131
|
+
/** The only turn-state constructor: prompt and provider turns must share one shape. */
|
|
1132
|
+
function makeClaudeTurnState(input) {
|
|
1133
|
+
return {
|
|
1134
|
+
turnId: input.turnId,
|
|
1135
|
+
...input.promptUuid !== void 0 ? { promptUuid: input.promptUuid } : {},
|
|
1136
|
+
openedBy: input.openedBy,
|
|
1137
|
+
startedAt: input.startedAt,
|
|
1138
|
+
items: [],
|
|
1139
|
+
assistantTextBlocks: /* @__PURE__ */ new Map(),
|
|
1140
|
+
assistantTextBlockOrder: [],
|
|
1141
|
+
capturedProposedPlanKeys: /* @__PURE__ */ new Set(),
|
|
1142
|
+
nextSyntheticAssistantBlockIndex: -1,
|
|
1143
|
+
reasoningBlocks: /* @__PURE__ */ new Map(),
|
|
1144
|
+
reasoningBlockCount: 0,
|
|
1145
|
+
rootOutputObserved: input.openedBy !== "wake-signal",
|
|
1146
|
+
lastChainUuid: void 0,
|
|
1147
|
+
rootContentObserved: input.openedBy !== "wake-signal",
|
|
1148
|
+
completion: void 0,
|
|
1149
|
+
steerPromptUuids: /* @__PURE__ */ new Set(),
|
|
1150
|
+
settledSteerPromptUuids: /* @__PURE__ */ new Set(),
|
|
1151
|
+
startedSteerPromptUuids: /* @__PURE__ */ new Set(),
|
|
1152
|
+
reinterruptedEchoKeys: /* @__PURE__ */ new Set(),
|
|
1153
|
+
interruptRequested: false,
|
|
1154
|
+
sealedSegmentCount: 0,
|
|
1155
|
+
awaitingSteerContinuation: void 0
|
|
1156
|
+
};
|
|
792
1157
|
}
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
1158
|
+
const CLAUDE_SUBAGENT_ATTRIBUTION_CACHE_CAP = 256;
|
|
1159
|
+
function rememberClaudeSubagentAttribution(cache, toolUseId, value) {
|
|
1160
|
+
if (!cache.has(toolUseId) && cache.size >= CLAUDE_SUBAGENT_ATTRIBUTION_CACHE_CAP) {
|
|
1161
|
+
const oldestToolUseId = cache.keys().next().value;
|
|
1162
|
+
if (oldestToolUseId !== void 0) cache.delete(oldestToolUseId);
|
|
797
1163
|
}
|
|
798
|
-
|
|
1164
|
+
cache.set(toolUseId, value);
|
|
799
1165
|
}
|
|
800
1166
|
function claudeSubagentLaunchModel(input) {
|
|
801
1167
|
const model = trimmedClaudeString(input?.model);
|
|
@@ -815,6 +1181,12 @@ function toMessage(cause, fallback) {
|
|
|
815
1181
|
if (cause instanceof Error && cause.message.length > 0) return cause.message;
|
|
816
1182
|
return fallback;
|
|
817
1183
|
}
|
|
1184
|
+
/** A typed adapter error's user-level text: its `detail` or `issue`, not its prefixed message. */
|
|
1185
|
+
function adapterFailureDetail(error) {
|
|
1186
|
+
const fields = error;
|
|
1187
|
+
for (const value of [fields.detail, fields.issue]) if (typeof value === "string" && value.trim().length > 0) return value.trim();
|
|
1188
|
+
return error.message;
|
|
1189
|
+
}
|
|
818
1190
|
function toError(cause, fallback) {
|
|
819
1191
|
return cause instanceof Error ? cause : new Error(toMessage(cause, fallback));
|
|
820
1192
|
}
|
|
@@ -848,14 +1220,6 @@ function interruptionMessageFromClaudeCause(cause) {
|
|
|
848
1220
|
const message = messageFromClaudeStreamCause(cause, "Claude runtime interrupted.");
|
|
849
1221
|
return isClaudeInterruptedMessage(message) ? "Claude runtime interrupted." : message;
|
|
850
1222
|
}
|
|
851
|
-
function resultErrorsText(result) {
|
|
852
|
-
return "errors" in result && Array.isArray(result.errors) ? result.errors.join(" ").toLowerCase() : "";
|
|
853
|
-
}
|
|
854
|
-
function isInterruptedResult(result) {
|
|
855
|
-
const errors = resultErrorsText(result);
|
|
856
|
-
if (errors.includes("interrupt")) return true;
|
|
857
|
-
return result.subtype === "error_during_execution" && result.is_error === false && (errors.includes("request was aborted") || errors.includes("interrupted by user") || errors.includes("aborted"));
|
|
858
|
-
}
|
|
859
1223
|
function asRuntimeItemId(value) {
|
|
860
1224
|
return require_src.RuntimeItemId.make(value);
|
|
861
1225
|
}
|
|
@@ -909,14 +1273,27 @@ function readClaudeResumeState(resumeCursor) {
|
|
|
909
1273
|
const resumeCandidate = typeof cursor.resume === "string" ? cursor.resume : typeof cursor.sessionId === "string" ? cursor.sessionId : void 0;
|
|
910
1274
|
const resume = resumeCandidate && isUuid(resumeCandidate) ? resumeCandidate : void 0;
|
|
911
1275
|
const resumeSessionAt = typeof cursor.resumeSessionAt === "string" ? cursor.resumeSessionAt : void 0;
|
|
1276
|
+
const rewind = resumeCursor.rewind;
|
|
1277
|
+
const rewindAt = rewind !== null && typeof rewind === "object" && typeof rewind.at === "string" && rewind.at.length > 0 ? rewind.at : void 0;
|
|
912
1278
|
const turnCountValue = typeof cursor.turnCount === "number" ? cursor.turnCount : void 0;
|
|
913
1279
|
return {
|
|
914
1280
|
...threadId ? { threadId } : {},
|
|
915
1281
|
...resume ? { resume } : {},
|
|
916
1282
|
...resumeSessionAt ? { resumeSessionAt } : {},
|
|
1283
|
+
...rewindAt ? { rewindAt } : {},
|
|
917
1284
|
...turnCountValue !== void 0 && Number.isInteger(turnCountValue) && turnCountValue >= 0 ? { turnCount: turnCountValue } : {}
|
|
918
1285
|
};
|
|
919
1286
|
}
|
|
1287
|
+
/**
|
|
1288
|
+
* The uuid of a main-chain transcript entry (user, assistant, compaction
|
|
1289
|
+
* boundary), or undefined for subagent sidechains and non-chain frames.
|
|
1290
|
+
*/
|
|
1291
|
+
function claudeMainChainUuid(message) {
|
|
1292
|
+
if (!(message.type === "user" || message.type === "assistant" || message.type === "system" && message.subtype === "compact_boundary")) return void 0;
|
|
1293
|
+
const uuid = message.uuid;
|
|
1294
|
+
const parentToolUseId = message.parent_tool_use_id;
|
|
1295
|
+
return typeof uuid === "string" && uuid.length > 0 && (parentToolUseId === null || parentToolUseId === void 0) ? uuid : void 0;
|
|
1296
|
+
}
|
|
920
1297
|
function trimmedClaudeString(value) {
|
|
921
1298
|
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
922
1299
|
}
|
|
@@ -1165,6 +1542,11 @@ function extractPlanStepsFromTodoInput(input) {
|
|
|
1165
1542
|
}));
|
|
1166
1543
|
}
|
|
1167
1544
|
function summarizeToolRequest(toolName, input) {
|
|
1545
|
+
const htmlRender = require_bin.resolveHtmlRenderToolPresentation({
|
|
1546
|
+
toolName,
|
|
1547
|
+
input
|
|
1548
|
+
});
|
|
1549
|
+
if (htmlRender) return htmlRender.detail ? `${toolName}: ${htmlRender.detail}` : toolName;
|
|
1168
1550
|
const commandValue = input.command ?? input.cmd;
|
|
1169
1551
|
const command = typeof commandValue === "string" ? commandValue : void 0;
|
|
1170
1552
|
if (command && command.trim().length > 0) return `${toolName}: ${command.trim().slice(0, 400)}`;
|
|
@@ -1178,6 +1560,24 @@ function summarizeToolRequest(toolName, input) {
|
|
|
1178
1560
|
if (serialized.length <= 400) return `${toolName}: ${serialized}`;
|
|
1179
1561
|
return `${toolName}: ${serialized.slice(0, 397)}...`;
|
|
1180
1562
|
}
|
|
1563
|
+
/** Work-log detail of a tool item: an HTML tool shows its page title or viewport alone. */
|
|
1564
|
+
function toolItemDetail(toolName, input) {
|
|
1565
|
+
const htmlRender = require_bin.resolveHtmlRenderToolPresentation({
|
|
1566
|
+
toolName,
|
|
1567
|
+
input
|
|
1568
|
+
});
|
|
1569
|
+
return htmlRender ? htmlRender.detail : summarizeToolRequest(toolName, input);
|
|
1570
|
+
}
|
|
1571
|
+
function toolItemTitle(toolName, itemType) {
|
|
1572
|
+
return require_bin.resolveHtmlRenderToolPresentation({
|
|
1573
|
+
toolName,
|
|
1574
|
+
input: void 0
|
|
1575
|
+
})?.title ?? titleForTool(itemType);
|
|
1576
|
+
}
|
|
1577
|
+
/** Tool input as carried on runtime events: an HTML tool's page is reduced to its length. */
|
|
1578
|
+
function toolEventInput(toolName, input) {
|
|
1579
|
+
return require_bin.resolveHtmlRenderToolKind(toolName) === void 0 ? input : require_bin.withoutHtmlRenderMarkup(input);
|
|
1580
|
+
}
|
|
1181
1581
|
function titleForTool(itemType) {
|
|
1182
1582
|
switch (itemType) {
|
|
1183
1583
|
case "command_execution": return "Command run";
|
|
@@ -1295,11 +1695,25 @@ const buildUserMessageEffect = effect.Effect.fn("buildUserMessageEffect")(functi
|
|
|
1295
1695
|
});
|
|
1296
1696
|
function turnStatusFromResult(result) {
|
|
1297
1697
|
if (result.subtype === "success") return "completed";
|
|
1698
|
+
if (isClaudeAbortTerminalReason(result)) return "interrupted";
|
|
1298
1699
|
const errors = resultErrorsText(result);
|
|
1299
1700
|
if (isInterruptedResult(result)) return "interrupted";
|
|
1300
1701
|
if (errors.includes("cancel")) return "cancelled";
|
|
1301
1702
|
return "failed";
|
|
1302
1703
|
}
|
|
1704
|
+
/** The error a completing turn reports, by why it reports its status (`decideClaudeTurnClose`). */
|
|
1705
|
+
function claudeTurnCloseErrorMessage(cause, result) {
|
|
1706
|
+
switch (cause) {
|
|
1707
|
+
case "result": return result.subtype === "success" ? void 0 : result.errors[0];
|
|
1708
|
+
case "aborted-by-steer": return;
|
|
1709
|
+
case "stopped": return "Interrupted by user.";
|
|
1710
|
+
case "failed-segment-dropped-steers": {
|
|
1711
|
+
const text = result.subtype === "success" ? result.result.trim() : result.errors[0];
|
|
1712
|
+
return text !== void 0 && text.length > 0 ? text : "Claude turn failed.";
|
|
1713
|
+
}
|
|
1714
|
+
case "folded-into-discarded-cli-turn": return FOLDED_INTO_DISCARDED_STEER_REASON;
|
|
1715
|
+
}
|
|
1716
|
+
}
|
|
1303
1717
|
function streamKindFromDeltaType(deltaType) {
|
|
1304
1718
|
return deltaType.includes("thinking") ? "reasoning_text" : "assistant_text";
|
|
1305
1719
|
}
|
|
@@ -1340,6 +1754,35 @@ function extractExitPlanModePlan(value) {
|
|
|
1340
1754
|
function exitPlanCaptureKey(input) {
|
|
1341
1755
|
return input.toolUseId && input.toolUseId.length > 0 ? `tool:${input.toolUseId}` : `plan:${input.planMarkdown}`;
|
|
1342
1756
|
}
|
|
1757
|
+
const EMPTY_STREAMED_JSON_SCAN = {
|
|
1758
|
+
depth: 0,
|
|
1759
|
+
inString: false,
|
|
1760
|
+
escaped: false,
|
|
1761
|
+
opened: false
|
|
1762
|
+
};
|
|
1763
|
+
function scanStreamedJson(scan, chunk) {
|
|
1764
|
+
let { depth, inString, escaped, opened } = scan;
|
|
1765
|
+
for (let index = 0; index < chunk.length; index += 1) {
|
|
1766
|
+
const code = chunk.charCodeAt(index);
|
|
1767
|
+
if (inString) {
|
|
1768
|
+
if (escaped) escaped = false;
|
|
1769
|
+
else if (code === 92) escaped = true;
|
|
1770
|
+
else if (code === 34) inString = false;
|
|
1771
|
+
} else if (code === 34) inString = true;
|
|
1772
|
+
else if (code === 123 || code === 91) {
|
|
1773
|
+
depth += 1;
|
|
1774
|
+
opened = true;
|
|
1775
|
+
} else if (code === 125 || code === 93) depth -= 1;
|
|
1776
|
+
}
|
|
1777
|
+
return {
|
|
1778
|
+
depth,
|
|
1779
|
+
inString,
|
|
1780
|
+
escaped,
|
|
1781
|
+
opened
|
|
1782
|
+
};
|
|
1783
|
+
}
|
|
1784
|
+
/** Every complete JSON object passes this, so skipping the parse otherwise changes nothing. */
|
|
1785
|
+
const mayBeCompleteJson = (scan) => scan.opened && scan.depth === 0 && !scan.inString;
|
|
1343
1786
|
function tryParseJsonRecord(value) {
|
|
1344
1787
|
try {
|
|
1345
1788
|
const parsed = JSON.parse(value);
|
|
@@ -1447,13 +1890,19 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
1447
1890
|
const serverConfig = yield* require_Metrics.ServerConfig;
|
|
1448
1891
|
const claudeEnvironment = yield* require_bin.makeClaudeEnvironment(claudeSettings, options?.environment).pipe(effect.Effect.provideService(effect.Path.Path, path));
|
|
1449
1892
|
const nativeEventLogger = options?.nativeEventLogger ?? (options?.nativeEventLogPath !== void 0 ? yield* require_bin.makeEventNdjsonLogger(options.nativeEventLogPath, { stream: "native" }) : void 0);
|
|
1893
|
+
const readSessionMessages = options?.readSessionMessages ?? ((sessionId, readOptions) => (0, _anthropic_ai_claude_agent_sdk.getSessionMessages)(sessionId, {
|
|
1894
|
+
...readOptions.dir !== void 0 ? { dir: readOptions.dir } : {},
|
|
1895
|
+
includeSystemMessages: readOptions.includeSystemMessages
|
|
1896
|
+
}));
|
|
1897
|
+
/** Threads whose session is being closed and reopened by a checkpoint revert. */
|
|
1898
|
+
const rewindingThreads = /* @__PURE__ */ new Set();
|
|
1450
1899
|
const createQuery = options?.createQuery ?? ((input) => (0, _anthropic_ai_claude_agent_sdk.query)({
|
|
1451
1900
|
prompt: input.prompt,
|
|
1452
1901
|
options: input.options
|
|
1453
1902
|
}));
|
|
1454
1903
|
const sessions = /* @__PURE__ */ new Map();
|
|
1455
1904
|
let nextSessionGeneration = 0;
|
|
1456
|
-
const runtimeEventQueue = yield* effect.Queue.bounded(2048);
|
|
1905
|
+
const runtimeEventQueue = yield* effect.Queue.bounded(options?.runtimeEventQueueCapacity ?? 2048);
|
|
1457
1906
|
const runtimeEventQueueMetrics = yield* require_bin.makeServerQueueMetrics({
|
|
1458
1907
|
queue: "provider.adapter.runtimeEvents",
|
|
1459
1908
|
component: "ClaudeAdapter",
|
|
@@ -1595,18 +2044,19 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
1595
2044
|
};
|
|
1596
2045
|
});
|
|
1597
2046
|
const updateResumeCursor = effect.Effect.fn("updateResumeCursor")(function* (context) {
|
|
1598
|
-
|
|
1599
|
-
|
|
2047
|
+
if (!context.session.threadId) return;
|
|
2048
|
+
const updatedAt = yield* nowIso;
|
|
1600
2049
|
const resumeCursor = {
|
|
1601
|
-
threadId,
|
|
2050
|
+
threadId: context.session.threadId,
|
|
1602
2051
|
...context.resumeSessionId ? { resume: context.resumeSessionId } : {},
|
|
1603
2052
|
...context.lastAssistantUuid ? { resumeSessionAt: context.lastAssistantUuid } : {},
|
|
2053
|
+
...context.pendingRewind ? { rewind: { at: context.pendingRewind.at } } : {},
|
|
1604
2054
|
turnCount: context.turns.length
|
|
1605
2055
|
};
|
|
1606
2056
|
context.session = {
|
|
1607
2057
|
...context.session,
|
|
1608
2058
|
resumeCursor,
|
|
1609
|
-
updatedAt
|
|
2059
|
+
updatedAt
|
|
1610
2060
|
};
|
|
1611
2061
|
});
|
|
1612
2062
|
const ensureAssistantTextBlock = effect.Effect.fn("ensureAssistantTextBlock")(function* (context, blockIndex, options) {
|
|
@@ -1745,7 +2195,7 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
1745
2195
|
});
|
|
1746
2196
|
}
|
|
1747
2197
|
});
|
|
1748
|
-
const emitRuntimeError = effect.Effect.fn("emitRuntimeError")(function* (context, message, cause) {
|
|
2198
|
+
const emitRuntimeError = effect.Effect.fn("emitRuntimeError")(function* (context, message, cause, options) {
|
|
1749
2199
|
if (cause !== void 0) {}
|
|
1750
2200
|
const turnState = context.turnState;
|
|
1751
2201
|
const stamp = yield* makeEventStamp();
|
|
@@ -1758,8 +2208,9 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
1758
2208
|
...turnState ? { turnId: asCanonicalTurnId(turnState.turnId) } : {},
|
|
1759
2209
|
payload: {
|
|
1760
2210
|
message,
|
|
1761
|
-
class: "provider_error",
|
|
1762
|
-
...cause !== void 0 ? { detail: cause } : {}
|
|
2211
|
+
class: options?.class ?? "provider_error",
|
|
2212
|
+
...cause !== void 0 ? { detail: cause } : {},
|
|
2213
|
+
...options?.resetAt !== void 0 ? { resetAt: options.resetAt } : {}
|
|
1763
2214
|
},
|
|
1764
2215
|
providerRefs: nativeProviderRefs(context)
|
|
1765
2216
|
});
|
|
@@ -1842,7 +2293,8 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
1842
2293
|
yield* emitCompactionUnavailableWarning(context);
|
|
1843
2294
|
}
|
|
1844
2295
|
});
|
|
1845
|
-
|
|
2296
|
+
/** The context gauge a result (or a local close without one) publishes. */
|
|
2297
|
+
const resolveResultUsageSnapshot = effect.Effect.fn("resolveResultUsageSnapshot")(function* (context, result) {
|
|
1846
2298
|
const resultCounts = readClaudeCacheCounts(result?.usage);
|
|
1847
2299
|
if (context.cacheObservation && resultCounts?.outputTokens !== void 0) context.cacheObservation = {
|
|
1848
2300
|
...context.cacheObservation,
|
|
@@ -1856,41 +2308,46 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
1856
2308
|
const resultContextWindow = mainClaudeContextWindowFromModelUsage(result?.modelUsage, context.cacheObservation?.model ?? context.currentApiModelId);
|
|
1857
2309
|
if (resultContextWindow !== void 0) context.lastKnownContextWindow = resultContextWindow;
|
|
1858
2310
|
const accumulatedSnapshot = normalizeClaudeTokenUsage(result?.usage, resultContextWindow ?? context.lastKnownContextWindow);
|
|
1859
|
-
const
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
const usageSnapshot = rawUsageSnapshot ? withAutomaticCompactionCapability({
|
|
2311
|
+
const rawUsageSnapshot = selectClaudeResultUsageGauge({
|
|
2312
|
+
lastGauge: context.lastKnownTokenUsage,
|
|
2313
|
+
cumulative: accumulatedSnapshot,
|
|
2314
|
+
maxTokens: resultContextWindow ?? context.lastKnownContextWindow,
|
|
2315
|
+
cumulativeIsGauge: !context.cumulativeUsageSpansCompaction
|
|
2316
|
+
});
|
|
2317
|
+
if (result !== void 0) context.cumulativeUsageSpansCompaction = false;
|
|
2318
|
+
return rawUsageSnapshot ? withAutomaticCompactionCapability({
|
|
1868
2319
|
...rawUsageSnapshot,
|
|
2320
|
+
...accumulatedSnapshot ? { processedUsage: {
|
|
2321
|
+
scope: "turn",
|
|
2322
|
+
inputTokens: accumulatedSnapshot.inputTokens ?? 0,
|
|
2323
|
+
cachedInputTokens: accumulatedSnapshot.cachedInputTokens ?? 0,
|
|
2324
|
+
outputTokens: accumulatedSnapshot.outputTokens ?? 0,
|
|
2325
|
+
reasoningOutputTokens: accumulatedSnapshot.reasoningOutputTokens ?? 0,
|
|
2326
|
+
totalTokens: accumulatedSnapshot.totalProcessedTokens ?? accumulatedSnapshot.usedTokens
|
|
2327
|
+
} } : {},
|
|
1869
2328
|
...context.cacheObservation ? { claudeCache: context.cacheObservation } : {}
|
|
1870
2329
|
}, context.supportsAutomaticCompaction) : void 0;
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
return;
|
|
1893
|
-
}
|
|
2330
|
+
});
|
|
2331
|
+
/** Publishes a context-gauge snapshot, attributed to a turn when one is given. */
|
|
2332
|
+
const emitTokenUsageSnapshot = effect.Effect.fn("emitTokenUsageSnapshot")(function* (context, usageSnapshot, turnId) {
|
|
2333
|
+
if (!usageSnapshot) return;
|
|
2334
|
+
const usageStamp = yield* makeEventStamp();
|
|
2335
|
+
yield* offerRuntimeEventForContext(context, {
|
|
2336
|
+
type: "thread.token-usage.updated",
|
|
2337
|
+
eventId: usageStamp.eventId,
|
|
2338
|
+
provider: PROVIDER,
|
|
2339
|
+
createdAt: usageStamp.createdAt,
|
|
2340
|
+
threadId: context.session.threadId,
|
|
2341
|
+
...turnId !== void 0 ? { turnId } : {},
|
|
2342
|
+
payload: { usage: usageSnapshot },
|
|
2343
|
+
providerRefs: nativeProviderRefs(context)
|
|
2344
|
+
});
|
|
2345
|
+
});
|
|
2346
|
+
/**
|
|
2347
|
+
* Closes everything a CLI segment left open (in-flight tools, assistant text and reasoning
|
|
2348
|
+
* blocks) while the turn itself may stay open: between a steer's segments and at completion.
|
|
2349
|
+
*/
|
|
2350
|
+
const sealTurnSegment = effect.Effect.fn("sealTurnSegment")(function* (context, turnState, status, result) {
|
|
1894
2351
|
for (const [index, tool] of context.inFlightTools.entries()) {
|
|
1895
2352
|
const toolStamp = yield* makeEventStamp();
|
|
1896
2353
|
yield* offerRuntimeEventForContext(context, {
|
|
@@ -1908,7 +2365,7 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
1908
2365
|
...tool.detail ? { detail: tool.detail } : {},
|
|
1909
2366
|
data: {
|
|
1910
2367
|
toolName: tool.toolName,
|
|
1911
|
-
input: tool.input
|
|
2368
|
+
input: toolEventInput(tool.toolName, tool.input)
|
|
1912
2369
|
}
|
|
1913
2370
|
},
|
|
1914
2371
|
providerRefs: nativeProviderRefs(context, { providerItemId: tool.itemId }),
|
|
@@ -1927,25 +2384,73 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
1927
2384
|
rawMethod: "claude/result",
|
|
1928
2385
|
rawPayload: result ?? { status }
|
|
1929
2386
|
});
|
|
2387
|
+
turnState.assistantTextBlockOrder.length = 0;
|
|
2388
|
+
for (const reasoningBlock of turnState.reasoningBlocks.values()) {
|
|
2389
|
+
const stamp = yield* makeEventStamp();
|
|
2390
|
+
yield* offerRuntimeEventForContext(context, {
|
|
2391
|
+
type: "item.completed",
|
|
2392
|
+
eventId: stamp.eventId,
|
|
2393
|
+
provider: PROVIDER,
|
|
2394
|
+
createdAt: stamp.createdAt,
|
|
2395
|
+
threadId: context.session.threadId,
|
|
2396
|
+
turnId: asCanonicalTurnId(turnState.turnId),
|
|
2397
|
+
itemId: asRuntimeItemId(reasoningBlock.itemId),
|
|
2398
|
+
payload: {
|
|
2399
|
+
itemType: "reasoning",
|
|
2400
|
+
status: status === "failed" ? "failed" : "completed",
|
|
2401
|
+
title: "Reasoning"
|
|
2402
|
+
},
|
|
2403
|
+
providerRefs: nativeProviderRefs(context),
|
|
2404
|
+
raw: {
|
|
2405
|
+
source: "claude.sdk.message",
|
|
2406
|
+
method: "claude/result",
|
|
2407
|
+
payload: result ?? { status }
|
|
2408
|
+
}
|
|
2409
|
+
});
|
|
2410
|
+
}
|
|
2411
|
+
turnState.reasoningBlocks.clear();
|
|
2412
|
+
});
|
|
2413
|
+
/** A result (or local close) with no open turn: keep usage, never publish a lifecycle event. */
|
|
2414
|
+
const publishTurnlessResult = effect.Effect.fn("publishTurnlessResult")(function* (context, status, errorMessage, result) {
|
|
2415
|
+
yield* emitTokenUsageSnapshot(context, yield* resolveResultUsageSnapshot(context, result), void 0);
|
|
2416
|
+
yield* effect.Effect.logInfo("claude.turn.result-without-active-turn", {
|
|
2417
|
+
threadId: context.session.threadId,
|
|
2418
|
+
status,
|
|
2419
|
+
numTurns: result?.num_turns,
|
|
2420
|
+
hasUsage: result?.usage !== void 0,
|
|
2421
|
+
...errorMessage ? { errorMessage } : {}
|
|
2422
|
+
});
|
|
2423
|
+
});
|
|
2424
|
+
/** Finishes a turn this fiber claimed in `completeTurn`. Never call it directly. */
|
|
2425
|
+
const finishClaimedTurn = effect.Effect.fn("finishClaimedTurn")(function* (context, turnState, completion, status, errorMessage, result, options) {
|
|
2426
|
+
const usageSnapshot = yield* resolveResultUsageSnapshot(context, result);
|
|
2427
|
+
yield* sealTurnSegment(context, turnState, status, result);
|
|
1930
2428
|
context.turns.push({
|
|
1931
2429
|
id: turnState.turnId,
|
|
1932
2430
|
items: [...turnState.items]
|
|
1933
2431
|
});
|
|
1934
|
-
if (
|
|
1935
|
-
|
|
1936
|
-
yield* offerRuntimeEventForContext(context, {
|
|
1937
|
-
type: "thread.token-usage.updated",
|
|
1938
|
-
eventId: usageStamp.eventId,
|
|
1939
|
-
provider: PROVIDER,
|
|
1940
|
-
createdAt: usageStamp.createdAt,
|
|
1941
|
-
threadId: context.session.threadId,
|
|
2432
|
+
if (turnState.lastChainUuid !== void 0) {
|
|
2433
|
+
context.turnHeads.push({
|
|
1942
2434
|
turnId: turnState.turnId,
|
|
1943
|
-
|
|
1944
|
-
providerRefs: nativeProviderRefs(context)
|
|
2435
|
+
head: turnState.lastChainUuid
|
|
1945
2436
|
});
|
|
2437
|
+
if (context.turnHeads.length > CLAUDE_TURN_HEADS_CAP) context.turnHeads.shift();
|
|
1946
2438
|
}
|
|
2439
|
+
if (status === "completed") context.pendingRewind = void 0;
|
|
2440
|
+
yield* updateResumeCursor(context);
|
|
2441
|
+
yield* emitTokenUsageSnapshot(context, usageSnapshot, turnState.turnId);
|
|
1947
2442
|
const stamp = yield* makeEventStamp();
|
|
1948
|
-
yield* offerRuntimeEventForContext(context, {
|
|
2443
|
+
if (options?.abortReason !== void 0) yield* offerRuntimeEventForContext(context, {
|
|
2444
|
+
type: "turn.aborted",
|
|
2445
|
+
eventId: stamp.eventId,
|
|
2446
|
+
provider: PROVIDER,
|
|
2447
|
+
createdAt: stamp.createdAt,
|
|
2448
|
+
threadId: context.session.threadId,
|
|
2449
|
+
turnId: turnState.turnId,
|
|
2450
|
+
payload: { reason: options.abortReason },
|
|
2451
|
+
providerRefs: nativeProviderRefs(context)
|
|
2452
|
+
});
|
|
2453
|
+
else yield* offerRuntimeEventForContext(context, {
|
|
1949
2454
|
type: "turn.completed",
|
|
1950
2455
|
eventId: stamp.eventId,
|
|
1951
2456
|
provider: PROVIDER,
|
|
@@ -1963,18 +2468,45 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
1963
2468
|
providerRefs: nativeProviderRefs(context)
|
|
1964
2469
|
});
|
|
1965
2470
|
const updatedAt = yield* nowIso;
|
|
1966
|
-
context.turnState
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
2471
|
+
if (context.turnState === turnState) {
|
|
2472
|
+
context.turnState = void 0;
|
|
2473
|
+
context.session = {
|
|
2474
|
+
...context.session,
|
|
2475
|
+
status: "ready",
|
|
2476
|
+
activeTurnId: void 0,
|
|
2477
|
+
updatedAt,
|
|
2478
|
+
...status === "failed" && errorMessage ? { lastError: errorMessage } : {}
|
|
2479
|
+
};
|
|
2480
|
+
}
|
|
2481
|
+
effect.Deferred.doneUnsafe(completion, effect.Effect.void);
|
|
1974
2482
|
if (context.agentControl) yield* context.agentControl.retireTurn(turnState.turnId);
|
|
1975
|
-
yield* updateResumeCursor(context);
|
|
1976
2483
|
if (status === "completed" && usageSnapshot) yield* maybeEnableAutomaticCompaction(context, usageSnapshot);
|
|
1977
2484
|
});
|
|
2485
|
+
/**
|
|
2486
|
+
* The single owner of turn completion. The open turn is claimed synchronously at entry, so a
|
|
2487
|
+
* concurrent close (sendTurn, Stop grace, watchdog, stream exit) waits for the claimer instead
|
|
2488
|
+
* of emitting a second lifecycle event.
|
|
2489
|
+
*/
|
|
2490
|
+
const completeTurn = effect.Effect.fn("completeTurn")(function* (context, status, errorMessage, result, options) {
|
|
2491
|
+
const turnState = context.turnState;
|
|
2492
|
+
if (options?.expectedTurnState !== void 0 && turnState !== options.expectedTurnState) return;
|
|
2493
|
+
if (turnState?.completion !== void 0) {
|
|
2494
|
+
if (result !== void 0) yield* effect.Effect.logInfo("claude.turn.result-during-completion", {
|
|
2495
|
+
threadId: context.session.threadId,
|
|
2496
|
+
turnId: turnState.turnId,
|
|
2497
|
+
status
|
|
2498
|
+
});
|
|
2499
|
+
yield* effect.Deferred.await(turnState.completion);
|
|
2500
|
+
return;
|
|
2501
|
+
}
|
|
2502
|
+
if (turnState === void 0) return yield* publishTurnlessResult(context, status, errorMessage, result);
|
|
2503
|
+
const completion = effect.Deferred.makeUnsafe();
|
|
2504
|
+
turnState.completion = completion;
|
|
2505
|
+
yield* finishClaimedTurn(context, turnState, completion, status, errorMessage, result, options).pipe(effect.Effect.ensuring(effect.Effect.sync(() => {
|
|
2506
|
+
if (context.turnState === turnState) turnState.completion = void 0;
|
|
2507
|
+
effect.Deferred.doneUnsafe(completion, effect.Effect.void);
|
|
2508
|
+
})));
|
|
2509
|
+
});
|
|
1978
2510
|
const handleStreamEvent = effect.Effect.fn("handleStreamEvent")(function* (context, message) {
|
|
1979
2511
|
if (message.type !== "stream_event") return;
|
|
1980
2512
|
const { event } = message;
|
|
@@ -2003,10 +2535,8 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
2003
2535
|
const deltaText = event.delta.type === "text_delta" ? event.delta.text : typeof event.delta.thinking === "string" ? event.delta.thinking : "";
|
|
2004
2536
|
if (deltaText.length === 0) return;
|
|
2005
2537
|
const streamKind = streamKindFromDeltaType(event.delta.type);
|
|
2006
|
-
const
|
|
2007
|
-
|
|
2008
|
-
block: context.turnState.assistantTextBlocks.get(event.index)
|
|
2009
|
-
} : void 0;
|
|
2538
|
+
const reasoningBlock = event.delta.type === "thinking_delta" ? context.turnState.reasoningBlocks.get(event.index) : void 0;
|
|
2539
|
+
const assistantBlockEntry = event.delta.type === "text_delta" ? yield* ensureAssistantTextBlock(context, event.index) : void 0;
|
|
2010
2540
|
if (assistantBlockEntry?.block && event.delta.type === "text_delta") assistantBlockEntry.block.emittedTextDelta = true;
|
|
2011
2541
|
const stamp = yield* makeEventStamp();
|
|
2012
2542
|
yield* offerRuntimeEventForContext(context, {
|
|
@@ -2016,7 +2546,7 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
2016
2546
|
createdAt: stamp.createdAt,
|
|
2017
2547
|
threadId: context.session.threadId,
|
|
2018
2548
|
turnId: context.turnState.turnId,
|
|
2019
|
-
...assistantBlockEntry?.block ? { itemId: asRuntimeItemId(assistantBlockEntry.block.itemId) } : {},
|
|
2549
|
+
...assistantBlockEntry?.block ? { itemId: asRuntimeItemId(assistantBlockEntry.block.itemId) } : reasoningBlock ? { itemId: asRuntimeItemId(reasoningBlock.itemId) } : {},
|
|
2020
2550
|
payload: {
|
|
2021
2551
|
streamKind,
|
|
2022
2552
|
delta: deltaText
|
|
@@ -2034,17 +2564,19 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
2034
2564
|
const tool = context.inFlightTools.get(event.index);
|
|
2035
2565
|
if (!tool || typeof event.delta.partial_json !== "string") return;
|
|
2036
2566
|
const partialInputJson = tool.partialInputJson + event.delta.partial_json;
|
|
2037
|
-
const
|
|
2038
|
-
const
|
|
2567
|
+
const partialInputScan = scanStreamedJson(tool.partialInputScan, event.delta.partial_json);
|
|
2568
|
+
const parsedInput = mayBeCompleteJson(partialInputScan) ? tryParseJsonRecord(partialInputJson) : void 0;
|
|
2569
|
+
const detail = parsedInput ? toolItemDetail(tool.toolName, parsedInput) : tool.detail;
|
|
2039
2570
|
let nextTool = {
|
|
2040
2571
|
...tool,
|
|
2041
2572
|
partialInputJson,
|
|
2573
|
+
partialInputScan,
|
|
2042
2574
|
...parsedInput ? { input: parsedInput } : {},
|
|
2043
2575
|
...detail ? { detail } : {}
|
|
2044
2576
|
};
|
|
2045
2577
|
const nextFingerprint = parsedInput && Object.keys(parsedInput).length > 0 ? toolInputFingerprint(parsedInput) : void 0;
|
|
2046
2578
|
context.inFlightTools.set(event.index, nextTool);
|
|
2047
|
-
if (nextTool.itemType === "collab_agent_tool_call" && parsedInput)
|
|
2579
|
+
if (nextTool.itemType === "collab_agent_tool_call" && parsedInput) rememberClaudeSubagentAttribution(context.subagentLaunchInputByToolUseId, nextTool.itemId, parsedInput);
|
|
2048
2580
|
if (!parsedInput || !nextFingerprint || tool.lastEmittedInputFingerprint === nextFingerprint) return;
|
|
2049
2581
|
nextTool = {
|
|
2050
2582
|
...nextTool,
|
|
@@ -2069,7 +2601,7 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
2069
2601
|
...nextTool.parentToolUseId ? { parentToolUseId: nextTool.parentToolUseId } : {},
|
|
2070
2602
|
data: {
|
|
2071
2603
|
toolName: nextTool.toolName,
|
|
2072
|
-
input: nextTool.input
|
|
2604
|
+
input: toolEventInput(nextTool.toolName, nextTool.input)
|
|
2073
2605
|
}
|
|
2074
2606
|
},
|
|
2075
2607
|
providerRefs: nativeProviderRefs(context, { providerItemId: nextTool.itemId }),
|
|
@@ -2104,12 +2636,40 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
2104
2636
|
yield* ensureAssistantTextBlock(context, index, { fallbackText: extractContentBlockText(block) });
|
|
2105
2637
|
return;
|
|
2106
2638
|
}
|
|
2639
|
+
if (block.type === "thinking" && context.turnState) {
|
|
2640
|
+
const turnState = context.turnState;
|
|
2641
|
+
turnState.reasoningBlockCount += 1;
|
|
2642
|
+
const itemId = `${turnState.turnId}:thinking:${turnState.reasoningBlockCount}`;
|
|
2643
|
+
turnState.reasoningBlocks.set(index, { itemId });
|
|
2644
|
+
const stamp = yield* makeEventStamp();
|
|
2645
|
+
yield* offerRuntimeEventForContext(context, {
|
|
2646
|
+
type: "item.started",
|
|
2647
|
+
eventId: stamp.eventId,
|
|
2648
|
+
provider: PROVIDER,
|
|
2649
|
+
createdAt: stamp.createdAt,
|
|
2650
|
+
threadId: context.session.threadId,
|
|
2651
|
+
turnId: asCanonicalTurnId(turnState.turnId),
|
|
2652
|
+
itemId: asRuntimeItemId(itemId),
|
|
2653
|
+
payload: {
|
|
2654
|
+
itemType: "reasoning",
|
|
2655
|
+
status: "inProgress",
|
|
2656
|
+
title: "Reasoning"
|
|
2657
|
+
},
|
|
2658
|
+
providerRefs: nativeProviderRefs(context),
|
|
2659
|
+
raw: {
|
|
2660
|
+
source: "claude.sdk.message",
|
|
2661
|
+
method: "claude/stream_event/content_block_start",
|
|
2662
|
+
payload: message
|
|
2663
|
+
}
|
|
2664
|
+
});
|
|
2665
|
+
return;
|
|
2666
|
+
}
|
|
2107
2667
|
if (block.type !== "tool_use" && block.type !== "server_tool_use" && block.type !== "mcp_tool_use") return;
|
|
2108
2668
|
const toolName = block.name;
|
|
2109
2669
|
const itemType = classifyToolItemType(toolName);
|
|
2110
2670
|
const toolInput = typeof block.input === "object" && block.input !== null ? block.input : {};
|
|
2111
2671
|
const itemId = block.id;
|
|
2112
|
-
const detail =
|
|
2672
|
+
const detail = toolItemDetail(toolName, toolInput);
|
|
2113
2673
|
const inputFingerprint = Object.keys(toolInput).length > 0 ? toolInputFingerprint(toolInput) : void 0;
|
|
2114
2674
|
const parentToolUseId = message.parent_tool_use_id ?? void 0;
|
|
2115
2675
|
const owningAgentId = agentIdForParentToolUse(context.taskAgents, parentToolUseId);
|
|
@@ -2117,16 +2677,17 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
2117
2677
|
itemId,
|
|
2118
2678
|
itemType,
|
|
2119
2679
|
toolName,
|
|
2120
|
-
title:
|
|
2121
|
-
detail,
|
|
2680
|
+
title: toolItemTitle(toolName, itemType),
|
|
2681
|
+
...detail ? { detail } : {},
|
|
2122
2682
|
input: toolInput,
|
|
2123
2683
|
partialInputJson: "",
|
|
2684
|
+
partialInputScan: EMPTY_STREAMED_JSON_SCAN,
|
|
2124
2685
|
...inputFingerprint ? { lastEmittedInputFingerprint: inputFingerprint } : {},
|
|
2125
2686
|
...owningAgentId ? { agentId: owningAgentId } : {},
|
|
2126
2687
|
...parentToolUseId ? { parentToolUseId } : {}
|
|
2127
2688
|
};
|
|
2128
2689
|
context.inFlightTools.set(index, tool);
|
|
2129
|
-
if (itemType === "collab_agent_tool_call")
|
|
2690
|
+
if (itemType === "collab_agent_tool_call") rememberClaudeSubagentAttribution(context.subagentLaunchInputByToolUseId, itemId, toolInput);
|
|
2130
2691
|
const stamp = yield* makeEventStamp();
|
|
2131
2692
|
yield* offerRuntimeEventForContext(context, {
|
|
2132
2693
|
type: "item.started",
|
|
@@ -2145,7 +2706,7 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
2145
2706
|
...tool.parentToolUseId ? { parentToolUseId: tool.parentToolUseId } : {},
|
|
2146
2707
|
data: {
|
|
2147
2708
|
toolName: tool.toolName,
|
|
2148
|
-
input: toolInput
|
|
2709
|
+
input: toolEventInput(tool.toolName, toolInput)
|
|
2149
2710
|
}
|
|
2150
2711
|
},
|
|
2151
2712
|
providerRefs: nativeProviderRefs(context, { providerItemId: tool.itemId }),
|
|
@@ -2159,6 +2720,32 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
2159
2720
|
}
|
|
2160
2721
|
if (event.type === "content_block_stop") {
|
|
2161
2722
|
const { index } = event;
|
|
2723
|
+
const reasoningBlock = context.turnState?.reasoningBlocks.get(index);
|
|
2724
|
+
if (reasoningBlock && context.turnState) {
|
|
2725
|
+
context.turnState.reasoningBlocks.delete(index);
|
|
2726
|
+
const stamp = yield* makeEventStamp();
|
|
2727
|
+
yield* offerRuntimeEventForContext(context, {
|
|
2728
|
+
type: "item.completed",
|
|
2729
|
+
eventId: stamp.eventId,
|
|
2730
|
+
provider: PROVIDER,
|
|
2731
|
+
createdAt: stamp.createdAt,
|
|
2732
|
+
threadId: context.session.threadId,
|
|
2733
|
+
turnId: asCanonicalTurnId(context.turnState.turnId),
|
|
2734
|
+
itemId: asRuntimeItemId(reasoningBlock.itemId),
|
|
2735
|
+
payload: {
|
|
2736
|
+
itemType: "reasoning",
|
|
2737
|
+
status: "completed",
|
|
2738
|
+
title: "Reasoning"
|
|
2739
|
+
},
|
|
2740
|
+
providerRefs: nativeProviderRefs(context),
|
|
2741
|
+
raw: {
|
|
2742
|
+
source: "claude.sdk.message",
|
|
2743
|
+
method: "claude/stream_event/content_block_stop",
|
|
2744
|
+
payload: message
|
|
2745
|
+
}
|
|
2746
|
+
});
|
|
2747
|
+
return;
|
|
2748
|
+
}
|
|
2162
2749
|
const assistantBlock = context.turnState?.assistantTextBlocks.get(index);
|
|
2163
2750
|
if (assistantBlock) {
|
|
2164
2751
|
assistantBlock.streamClosed = true;
|
|
@@ -2181,7 +2768,7 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
2181
2768
|
const itemStatus = toolResult.isError ? "failed" : "completed";
|
|
2182
2769
|
const toolData = {
|
|
2183
2770
|
toolName: tool.toolName,
|
|
2184
|
-
input: tool.input,
|
|
2771
|
+
input: toolEventInput(tool.toolName, tool.input),
|
|
2185
2772
|
result: toolResult.block
|
|
2186
2773
|
};
|
|
2187
2774
|
const updatedStamp = yield* makeEventStamp();
|
|
@@ -2286,6 +2873,49 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
2286
2873
|
context.inFlightTools.delete(index);
|
|
2287
2874
|
}
|
|
2288
2875
|
});
|
|
2876
|
+
/**
|
|
2877
|
+
* Opens a provider turn: one Claude started without a prompt, either at its turn-start signal
|
|
2878
|
+
* ("wake-signal") or, when no signal opened one, at its first root assistant output. Never
|
|
2879
|
+
* bound to Agent Control authority; exact-turn binding stays prompt-only.
|
|
2880
|
+
*/
|
|
2881
|
+
const startProviderTurn = effect.Effect.fn("startProviderTurn")(function* (context, openedBy) {
|
|
2882
|
+
const turnId = require_src.TurnId.make(yield* effect.Effect.sync(() => crypto.randomUUID()));
|
|
2883
|
+
const startedAt = yield* nowIso;
|
|
2884
|
+
if (context.turnState !== void 0 || context.stopped) return;
|
|
2885
|
+
if (openedBy === "wake-signal" && (context.turnInstallsInFlight > 0 || !context.promptSent)) return;
|
|
2886
|
+
const turnState = makeClaudeTurnState({
|
|
2887
|
+
turnId,
|
|
2888
|
+
startedAt,
|
|
2889
|
+
openedBy
|
|
2890
|
+
});
|
|
2891
|
+
context.turnState = turnState;
|
|
2892
|
+
context.session = {
|
|
2893
|
+
...context.session,
|
|
2894
|
+
status: "running",
|
|
2895
|
+
activeTurnId: turnId,
|
|
2896
|
+
updatedAt: startedAt
|
|
2897
|
+
};
|
|
2898
|
+
const turnStartedStamp = yield* makeEventStamp();
|
|
2899
|
+
yield* offerRuntimeEventForContext(context, {
|
|
2900
|
+
type: "turn.started",
|
|
2901
|
+
eventId: turnStartedStamp.eventId,
|
|
2902
|
+
provider: PROVIDER,
|
|
2903
|
+
createdAt: turnStartedStamp.createdAt,
|
|
2904
|
+
threadId: context.session.threadId,
|
|
2905
|
+
turnId,
|
|
2906
|
+
payload: {},
|
|
2907
|
+
providerRefs: {
|
|
2908
|
+
...nativeProviderRefs(context),
|
|
2909
|
+
providerTurnId: turnId
|
|
2910
|
+
},
|
|
2911
|
+
raw: {
|
|
2912
|
+
source: "claude.sdk.message",
|
|
2913
|
+
method: "claude/synthetic-turn-start",
|
|
2914
|
+
payload: { openedBy }
|
|
2915
|
+
}
|
|
2916
|
+
});
|
|
2917
|
+
if (openedBy === "wake-signal") yield* effect.Effect.sleep(effect.Duration.millis(CLAUDE_WAKE_TURN_FIRST_OUTPUT_TIMEOUT_MS)).pipe(effect.Effect.andThen(effect.Effect.suspend(() => context.turnState === turnState && !turnState.rootOutputObserved && !context.stopped ? completeTurn(context, "interrupted", WAKE_NO_OUTPUT_REASON, void 0, { abortReason: WAKE_NO_OUTPUT_REASON }) : effect.Effect.void)), effect.Effect.ignoreCause({ log: true }), effect.Effect.forkDetach);
|
|
2918
|
+
});
|
|
2289
2919
|
const handleAssistantMessage = effect.Effect.fn("handleAssistantMessage")(function* (context, message) {
|
|
2290
2920
|
if (message.type !== "assistant") return;
|
|
2291
2921
|
const assistantParentToolUseId = message.parent_tool_use_id;
|
|
@@ -2293,8 +2923,39 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
2293
2923
|
const owningTaskId = agentIdForParentToolUse(context.taskAgents, assistantParentToolUseId);
|
|
2294
2924
|
const snapshotModel = trimmedClaudeString(message.message.model);
|
|
2295
2925
|
const owningAgent = owningTaskId ? context.taskAgents.get(owningTaskId) : void 0;
|
|
2296
|
-
if (owningAgent && snapshotModel
|
|
2297
|
-
|
|
2926
|
+
if (owningAgent && snapshotModel && owningAgent.model !== snapshotModel) {
|
|
2927
|
+
owningAgent.model = snapshotModel;
|
|
2928
|
+
const stamp = yield* makeEventStamp();
|
|
2929
|
+
yield* offerRuntimeEventForContext(context, {
|
|
2930
|
+
...stamp,
|
|
2931
|
+
type: "task.updated",
|
|
2932
|
+
provider: PROVIDER,
|
|
2933
|
+
threadId: context.session.threadId,
|
|
2934
|
+
...context.turnState ? { turnId: asCanonicalTurnId(context.turnState.turnId) } : {},
|
|
2935
|
+
providerRefs: nativeProviderRefs(context),
|
|
2936
|
+
payload: {
|
|
2937
|
+
taskId: require_src.RuntimeTaskId.make(owningAgent.taskId),
|
|
2938
|
+
...taskLinkageFor(context.taskAgents, owningAgent.taskId)
|
|
2939
|
+
}
|
|
2940
|
+
});
|
|
2941
|
+
const existingSubagent = context.subagentByTaskId.get(owningAgent.taskId);
|
|
2942
|
+
if (existingSubagent) {
|
|
2943
|
+
const subagent = {
|
|
2944
|
+
...existingSubagent,
|
|
2945
|
+
model: snapshotModel
|
|
2946
|
+
};
|
|
2947
|
+
context.subagentByTaskId.set(owningAgent.taskId, subagent);
|
|
2948
|
+
yield* emitClaudeSubagentUpdated(context, {
|
|
2949
|
+
subagent,
|
|
2950
|
+
raw: message
|
|
2951
|
+
});
|
|
2952
|
+
}
|
|
2953
|
+
} else if (!owningAgent && snapshotModel) rememberClaudeSubagentAttribution(context.subagentModelByToolUseId, assistantParentToolUseId, snapshotModel);
|
|
2954
|
+
for (const block of message.message.content) {
|
|
2955
|
+
if (block.type !== "tool_use") continue;
|
|
2956
|
+
rememberClaudeSubagentAttribution(context.subagentParentByToolUseId, block.id, assistantParentToolUseId);
|
|
2957
|
+
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);
|
|
2958
|
+
}
|
|
2298
2959
|
context.lastAssistantUuid = message.uuid;
|
|
2299
2960
|
yield* updateResumeCursor(context);
|
|
2300
2961
|
return;
|
|
@@ -2306,11 +2967,13 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
2306
2967
|
messageId: message.message.id,
|
|
2307
2968
|
model: message.message.model,
|
|
2308
2969
|
...context.cacheModelSelection ? { modelSelection: context.cacheModelSelection } : {},
|
|
2970
|
+
...context.session.cwd ? { cwd: context.session.cwd } : {},
|
|
2309
2971
|
runtimeSessionId: context.session.runtimeSessionId,
|
|
2310
2972
|
providerInstanceId: context.session.providerInstanceId,
|
|
2311
2973
|
observedAt: cacheStamp.createdAt,
|
|
2312
2974
|
...previousCache ? { previous: previousCache } : {}
|
|
2313
2975
|
});
|
|
2976
|
+
if (context.cacheObservation) context.mainLoopUsageObserved = true;
|
|
2314
2977
|
if (context.cacheObservation && context.cacheObservation !== previousCache) {
|
|
2315
2978
|
const observation = context.cacheObservation;
|
|
2316
2979
|
const usedTokens = observation.directInputTokens + observation.cacheReadInputTokens + observation.cacheWriteInputTokens;
|
|
@@ -2333,44 +2996,7 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
2333
2996
|
providerRefs: {}
|
|
2334
2997
|
});
|
|
2335
2998
|
}
|
|
2336
|
-
if (!context.turnState)
|
|
2337
|
-
const turnId = require_src.TurnId.make(yield* effect.Effect.sync(() => crypto.randomUUID()));
|
|
2338
|
-
const startedAt = yield* nowIso;
|
|
2339
|
-
context.turnState = {
|
|
2340
|
-
turnId,
|
|
2341
|
-
startedAt,
|
|
2342
|
-
items: [],
|
|
2343
|
-
assistantTextBlocks: /* @__PURE__ */ new Map(),
|
|
2344
|
-
assistantTextBlockOrder: [],
|
|
2345
|
-
capturedProposedPlanKeys: /* @__PURE__ */ new Set(),
|
|
2346
|
-
nextSyntheticAssistantBlockIndex: -1
|
|
2347
|
-
};
|
|
2348
|
-
context.session = {
|
|
2349
|
-
...context.session,
|
|
2350
|
-
status: "running",
|
|
2351
|
-
activeTurnId: turnId,
|
|
2352
|
-
updatedAt: startedAt
|
|
2353
|
-
};
|
|
2354
|
-
const turnStartedStamp = yield* makeEventStamp();
|
|
2355
|
-
yield* offerRuntimeEventForContext(context, {
|
|
2356
|
-
type: "turn.started",
|
|
2357
|
-
eventId: turnStartedStamp.eventId,
|
|
2358
|
-
provider: PROVIDER,
|
|
2359
|
-
createdAt: turnStartedStamp.createdAt,
|
|
2360
|
-
threadId: context.session.threadId,
|
|
2361
|
-
turnId,
|
|
2362
|
-
payload: {},
|
|
2363
|
-
providerRefs: {
|
|
2364
|
-
...nativeProviderRefs(context),
|
|
2365
|
-
providerTurnId: turnId
|
|
2366
|
-
},
|
|
2367
|
-
raw: {
|
|
2368
|
-
source: "claude.sdk.message",
|
|
2369
|
-
method: "claude/synthetic-turn-start",
|
|
2370
|
-
payload: {}
|
|
2371
|
-
}
|
|
2372
|
-
});
|
|
2373
|
-
}
|
|
2999
|
+
if (!context.turnState) yield* startProviderTurn(context, "assistant-output");
|
|
2374
3000
|
const content = message.message?.content;
|
|
2375
3001
|
if (Array.isArray(content)) for (const block of content) {
|
|
2376
3002
|
if (!block || typeof block !== "object") continue;
|
|
@@ -2393,12 +3019,106 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
2393
3019
|
context.lastAssistantUuid = message.uuid;
|
|
2394
3020
|
yield* updateResumeCursor(context);
|
|
2395
3021
|
});
|
|
2396
|
-
const handleResultMessage = effect.Effect.fn("handleResultMessage")(function* (context, message) {
|
|
3022
|
+
const handleResultMessage = effect.Effect.fn("handleResultMessage")(function* (context, message, options) {
|
|
2397
3023
|
if (message.type !== "result") return;
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
3024
|
+
if (context.probing && context.turnState === void 0) {
|
|
3025
|
+
if (message.subtype !== "success" || message.is_error) {
|
|
3026
|
+
const detail = (message.subtype !== "success" ? message.errors[0] : void 0) ?? `Claude reported ${message.subtype} while reopening the conversation.`;
|
|
3027
|
+
if (context.probeFailure) yield* effect.Deferred.succeed(context.probeFailure, detail);
|
|
3028
|
+
}
|
|
3029
|
+
return;
|
|
3030
|
+
}
|
|
3031
|
+
const turnState = context.turnState;
|
|
3032
|
+
const echoedPromptUuids = claudeEchoedPromptUuids(message);
|
|
3033
|
+
if (turnState?.promptUuid !== void 0 && !claudeResultBelongsToTurn({
|
|
3034
|
+
echoed: echoedPromptUuids,
|
|
3035
|
+
origin: message.origin,
|
|
3036
|
+
promptUuid: turnState.promptUuid,
|
|
3037
|
+
steerPromptUuids: turnState.steerPromptUuids
|
|
3038
|
+
})) {
|
|
3039
|
+
yield* effect.Effect.logInfo("claude.turn.result-for-other-prompt", {
|
|
3040
|
+
threadId: context.session.threadId,
|
|
3041
|
+
turnId: turnState.turnId,
|
|
3042
|
+
origin: message.origin?.kind
|
|
3043
|
+
});
|
|
3044
|
+
return;
|
|
3045
|
+
}
|
|
3046
|
+
const resultStatus = turnStatusFromResult(message);
|
|
3047
|
+
let close = {
|
|
3048
|
+
status: resultStatus,
|
|
3049
|
+
cause: "result"
|
|
3050
|
+
};
|
|
3051
|
+
if (turnState) {
|
|
3052
|
+
const decision = decideClaudeTurnResult({
|
|
3053
|
+
kind: classifyClaudeResultKind(message),
|
|
3054
|
+
echoedPromptUuids,
|
|
3055
|
+
queuedTurnCount: message.queued_turn_count,
|
|
3056
|
+
steerPromptUuids: turnState.steerPromptUuids,
|
|
3057
|
+
settledSteerPromptUuids: turnState.settledSteerPromptUuids,
|
|
3058
|
+
interruptRequested: turnState.interruptRequested
|
|
3059
|
+
});
|
|
3060
|
+
for (const uuid of decision.newlySettled) {
|
|
3061
|
+
turnState.settledSteerPromptUuids.add(uuid);
|
|
3062
|
+
context.discardedSteerPromptUuids.delete(uuid);
|
|
3063
|
+
}
|
|
3064
|
+
if (decision.decision === "await-steer") {
|
|
3065
|
+
yield* sealTurnSegment(context, turnState, resultStatus, message);
|
|
3066
|
+
yield* emitTokenUsageSnapshot(context, yield* resolveResultUsageSnapshot(context, message), turnState.turnId);
|
|
3067
|
+
turnState.sealedSegmentCount += 1;
|
|
3068
|
+
turnState.awaitingSteerContinuation = {
|
|
3069
|
+
since: yield* nowIso,
|
|
3070
|
+
segmentStatus: resultStatus
|
|
3071
|
+
};
|
|
3072
|
+
yield* effect.Effect.logInfo("claude.turn.awaiting-steer-continuation", {
|
|
3073
|
+
threadId: context.session.threadId,
|
|
3074
|
+
turnId: turnState.turnId,
|
|
3075
|
+
queuedTurnCount: message.queued_turn_count,
|
|
3076
|
+
unsettled: decision.unsettled.length,
|
|
3077
|
+
terminalReason: message.terminal_reason
|
|
3078
|
+
});
|
|
3079
|
+
return;
|
|
3080
|
+
}
|
|
3081
|
+
if (decision.discardUnsettled) for (const uuid of decision.unsettled) rememberDiscardedSteer(context.discardedSteerPromptUuids, uuid);
|
|
3082
|
+
close = decideClaudeTurnClose({
|
|
3083
|
+
resultStatus,
|
|
3084
|
+
decision,
|
|
3085
|
+
interruptRequested: turnState.interruptRequested,
|
|
3086
|
+
echoedPromptUuids,
|
|
3087
|
+
promptUuid: turnState.promptUuid,
|
|
3088
|
+
steerPromptUuids: turnState.steerPromptUuids,
|
|
3089
|
+
foldedIntoDiscardedCliTurn: options?.foldedIntoDiscardedCliTurn === true
|
|
3090
|
+
});
|
|
3091
|
+
if (close.cause !== "result") {
|
|
3092
|
+
if (close.status !== "failed") yield* sealTurnSegment(context, turnState, resultStatus, message);
|
|
3093
|
+
yield* effect.Effect.logInfo("claude.turn.closed-as", {
|
|
3094
|
+
threadId: context.session.threadId,
|
|
3095
|
+
turnId: turnState.turnId,
|
|
3096
|
+
cause: close.cause,
|
|
3097
|
+
resultStatus,
|
|
3098
|
+
status: close.status,
|
|
3099
|
+
queuedTurnCount: message.queued_turn_count,
|
|
3100
|
+
unsettled: decision.unsettled.length,
|
|
3101
|
+
terminalReason: message.terminal_reason
|
|
3102
|
+
});
|
|
3103
|
+
}
|
|
3104
|
+
}
|
|
3105
|
+
const notInterrupted = (status) => status !== "interrupted" && status !== "cancelled";
|
|
3106
|
+
const usageLimit = context.turnState && notInterrupted(resultStatus) && notInterrupted(close.status) ? classifyClaudeUsageLimitResult({
|
|
3107
|
+
result: message,
|
|
3108
|
+
windows: context.rejectedRateLimitWindows,
|
|
3109
|
+
nowMs: yield* effect.Clock.currentTimeMillis
|
|
3110
|
+
}) : null;
|
|
3111
|
+
if (usageLimit) {
|
|
3112
|
+
yield* emitRuntimeError(context, usageLimit.message, void 0, {
|
|
3113
|
+
class: "usage_limit",
|
|
3114
|
+
resetAt: usageLimit.resetAt
|
|
3115
|
+
});
|
|
3116
|
+
yield* completeTurn(context, "failed", usageLimit.message, message);
|
|
3117
|
+
return;
|
|
3118
|
+
}
|
|
3119
|
+
const errorMessage = claudeTurnCloseErrorMessage(close.cause, message);
|
|
3120
|
+
if (close.status === "failed") yield* emitRuntimeError(context, errorMessage ?? "Claude turn failed.");
|
|
3121
|
+
yield* completeTurn(context, close.status, errorMessage, message);
|
|
2402
3122
|
});
|
|
2403
3123
|
/**
|
|
2404
3124
|
* Synthesizes per-member task.progress rows from the coordinator's
|
|
@@ -2467,6 +3187,19 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
2467
3187
|
});
|
|
2468
3188
|
const handleSystemMessage = effect.Effect.fn("handleSystemMessage")(function* (context, message) {
|
|
2469
3189
|
if (message.type !== "system") return;
|
|
3190
|
+
if (message.subtype === "status" && message.status === "requesting") context.requestingStatusObserved = true;
|
|
3191
|
+
const wakeSignal = claudeWakeSignal(message);
|
|
3192
|
+
if (wakeSignal !== void 0 && shouldOpenClaudeWakeTurn({
|
|
3193
|
+
signal: wakeSignal,
|
|
3194
|
+
hasOpenTurn: context.turnState !== void 0,
|
|
3195
|
+
sessionStopped: context.stopped,
|
|
3196
|
+
promptSent: context.promptSent,
|
|
3197
|
+
turnInstallsInFlight: context.turnInstallsInFlight,
|
|
3198
|
+
requestingStatusObserved: context.requestingStatusObserved
|
|
3199
|
+
})) {
|
|
3200
|
+
if (context.discardedSteerPromptUuids.size > 0) context.wakeSignalDeferred = true;
|
|
3201
|
+
else yield* startProviderTurn(context, "wake-signal");
|
|
3202
|
+
}
|
|
2470
3203
|
const stamp = yield* makeEventStamp();
|
|
2471
3204
|
const base = {
|
|
2472
3205
|
eventId: stamp.eventId,
|
|
@@ -2580,6 +3313,7 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
2580
3313
|
}
|
|
2581
3314
|
switch (message.subtype) {
|
|
2582
3315
|
case "init":
|
|
3316
|
+
context.cliCapabilities = parseClaudeCliCapabilities(message);
|
|
2583
3317
|
yield* offerRuntimeEventForContext(context, {
|
|
2584
3318
|
...base,
|
|
2585
3319
|
type: "session.configured",
|
|
@@ -2602,10 +3336,12 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
2602
3336
|
}
|
|
2603
3337
|
});
|
|
2604
3338
|
return;
|
|
2605
|
-
case "compact_boundary":
|
|
3339
|
+
case "compact_boundary": {
|
|
2606
3340
|
context.compactionPolicy = settleContextCompaction(context.compactionPolicy, context.generation);
|
|
2607
|
-
|
|
3341
|
+
const postCompactionUsage = claudePostCompactionUsage(message.compact_metadata, context.lastKnownContextWindow);
|
|
3342
|
+
context.lastKnownTokenUsage = postCompactionUsage;
|
|
2608
3343
|
context.cacheObservation = void 0;
|
|
3344
|
+
context.cumulativeUsageSpansCompaction = true;
|
|
2609
3345
|
yield* offerRuntimeEventForContext(context, {
|
|
2610
3346
|
...base,
|
|
2611
3347
|
type: "thread.state.changed",
|
|
@@ -2614,7 +3350,18 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
2614
3350
|
detail: message
|
|
2615
3351
|
}
|
|
2616
3352
|
});
|
|
3353
|
+
if (postCompactionUsage) {
|
|
3354
|
+
const usageStamp = yield* makeEventStamp();
|
|
3355
|
+
yield* offerRuntimeEventForContext(context, {
|
|
3356
|
+
...base,
|
|
3357
|
+
eventId: usageStamp.eventId,
|
|
3358
|
+
createdAt: usageStamp.createdAt,
|
|
3359
|
+
type: "thread.token-usage.updated",
|
|
3360
|
+
payload: { usage: withAutomaticCompactionCapability(postCompactionUsage, context.supportsAutomaticCompaction) }
|
|
3361
|
+
});
|
|
3362
|
+
}
|
|
2617
3363
|
return;
|
|
3364
|
+
}
|
|
2618
3365
|
case "hook_started":
|
|
2619
3366
|
yield* offerRuntimeEventForContext(context, {
|
|
2620
3367
|
...base,
|
|
@@ -2654,7 +3401,9 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
2654
3401
|
return;
|
|
2655
3402
|
case "task_started": {
|
|
2656
3403
|
const launchingTool = message.tool_use_id ? Array.from(context.inFlightTools.values()).find((tool) => tool.itemId === message.tool_use_id) : void 0;
|
|
2657
|
-
const
|
|
3404
|
+
const parentToolUseId = message.tool_use_id ? context.subagentParentByToolUseId.get(message.tool_use_id) : void 0;
|
|
3405
|
+
const owningAgentId = launchingTool?.agentId ?? agentIdForParentToolUse(context.taskAgents, parentToolUseId);
|
|
3406
|
+
if (message.tool_use_id) context.subagentParentByToolUseId.delete(message.tool_use_id);
|
|
2658
3407
|
const launchInput = launchingTool?.input ?? (message.tool_use_id ? context.subagentLaunchInputByToolUseId.get(message.tool_use_id) : void 0);
|
|
2659
3408
|
const backgroundFlag = message.is_backgrounded;
|
|
2660
3409
|
if (backgroundFlag === true || backgroundFlag === void 0 && launchInput?.run_in_background === true) context.backgroundedTaskIds.add(message.task_id);
|
|
@@ -2711,7 +3460,7 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
2711
3460
|
return;
|
|
2712
3461
|
}
|
|
2713
3462
|
case "task_progress": {
|
|
2714
|
-
if (message.usage && !context.
|
|
3463
|
+
if (message.usage && !context.mainLoopUsageObserved && !isClaudeSubagentTaskMessage(message) && !context.taskAgents.get(message.task_id)?.toolUseId) {
|
|
2715
3464
|
const normalizedUsage = normalizeClaudeTokenUsage(message.usage, context.lastKnownContextWindow);
|
|
2716
3465
|
if (normalizedUsage) {
|
|
2717
3466
|
context.lastKnownTokenUsage = normalizedUsage;
|
|
@@ -2793,7 +3542,7 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
2793
3542
|
case "task_notification": {
|
|
2794
3543
|
context.liveTaskIds.delete(message.task_id);
|
|
2795
3544
|
context.backgroundedTaskIds.delete(message.task_id);
|
|
2796
|
-
if (message.usage && !context.
|
|
3545
|
+
if (message.usage && !context.mainLoopUsageObserved && !isClaudeSubagentTaskMessage(message) && !context.taskAgents.get(message.task_id)?.toolUseId) {
|
|
2797
3546
|
const normalizedUsage = normalizeClaudeTokenUsage(message.usage, context.lastKnownContextWindow);
|
|
2798
3547
|
if (normalizedUsage) {
|
|
2799
3548
|
context.lastKnownTokenUsage = normalizedUsage;
|
|
@@ -2928,17 +3677,175 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
2928
3677
|
return;
|
|
2929
3678
|
}
|
|
2930
3679
|
if (message.type === "rate_limit_event") {
|
|
3680
|
+
const transition = message.rate_limit_info ? applyClaudeRateLimitInfo(context.rejectedRateLimitWindows, message.rate_limit_info) : void 0;
|
|
2931
3681
|
yield* offerRuntimeEventForContext(context, {
|
|
2932
3682
|
...base,
|
|
2933
3683
|
type: "account.rate-limits.updated",
|
|
2934
|
-
payload: {
|
|
3684
|
+
payload: {
|
|
3685
|
+
rateLimits: message,
|
|
3686
|
+
usageLimitState: claudeUsageLimitState(context.rejectedRateLimitWindows, yield* effect.Clock.currentTimeMillis)
|
|
3687
|
+
}
|
|
2935
3688
|
});
|
|
3689
|
+
const turnState = context.turnState;
|
|
3690
|
+
if (transition?.blocked && turnState) {
|
|
3691
|
+
const announced = turnState.announcedUsageLimitKeys ??= /* @__PURE__ */ new Set();
|
|
3692
|
+
if (!announced.has(transition.key)) {
|
|
3693
|
+
announced.add(transition.key);
|
|
3694
|
+
yield* emitRuntimeWarning(context, CLAUDE_USAGE_LIMIT_FALLBACK_MESSAGE, { usageLimit: {
|
|
3695
|
+
limitType: transition.limitType,
|
|
3696
|
+
resetAt: transition.resetAt
|
|
3697
|
+
} });
|
|
3698
|
+
}
|
|
3699
|
+
}
|
|
2936
3700
|
return;
|
|
2937
3701
|
}
|
|
2938
3702
|
});
|
|
3703
|
+
/** Plain interrupt for a CLI segment Stop already ended; bounded, failures only logged. */
|
|
3704
|
+
const forkReinterrupt = (context, reason) => effect.Effect.tryPromise({
|
|
3705
|
+
try: () => context.query.interrupt(),
|
|
3706
|
+
catch: (cause) => toRequestError(context.session.threadId, "turn/interrupt", cause)
|
|
3707
|
+
}).pipe(effect.Effect.timeoutOption("5 seconds"), effect.Effect.tap(() => effect.Effect.logInfo("claude.turn.reinterrupted", {
|
|
3708
|
+
threadId: context.session.threadId,
|
|
3709
|
+
reason
|
|
3710
|
+
})), effect.Effect.ignoreCause({ log: true }), effect.Effect.forkDetach, effect.Effect.asVoid);
|
|
3711
|
+
/**
|
|
3712
|
+
* A discarded steer's CLI turn turned out to be the one a provider turn was opened for (by its
|
|
3713
|
+
* `status: requesting`, legacy `init`, `api_retry` or compaction frame, before its echo). That
|
|
3714
|
+
* turn has routed no content: retract it.
|
|
3715
|
+
*/
|
|
3716
|
+
const retractDiscardedSteerWakeTurn = effect.Effect.fn("retractDiscardedSteerWakeTurn")(function* (context) {
|
|
3717
|
+
const turnState = context.turnState;
|
|
3718
|
+
if (turnState === void 0 || turnState.openedBy !== "wake-signal" || turnState.rootContentObserved || turnState.steerPromptUuids.size > 0) return;
|
|
3719
|
+
yield* completeTurn(context, "interrupted", DISCARDED_STEER_TURN_REASON, void 0, {
|
|
3720
|
+
abortReason: DISCARDED_STEER_TURN_REASON,
|
|
3721
|
+
expectedTurnState: turnState
|
|
3722
|
+
});
|
|
3723
|
+
});
|
|
3724
|
+
/**
|
|
3725
|
+
* The discarded CLI turn's result: forget its uuids, then drop it (keeping its usage). Returns
|
|
3726
|
+
* whether it was consumed. Only this result can end the open turn when:
|
|
3727
|
+
* - it echoes the open turn's prompt or steer, which the CLI folded into the discarded CLI turn
|
|
3728
|
+
* (a fold shows only on the result). That turn's reply went with the dropped frames, and the
|
|
3729
|
+
* discard's re-interrupt usually aborted it, so the result closes it here as failed (never as
|
|
3730
|
+
* a Stop the user did not press);
|
|
3731
|
+
* - the CLI turn's output already reached an open provider turn (its frames carried no echo,
|
|
3732
|
+
* or beat Stop's bookkeeping). The result is routed on and completes that turn.
|
|
3733
|
+
*/
|
|
3734
|
+
const endDiscardedSteerCliTurn = effect.Effect.fn("endDiscardedSteerCliTurn")(function* (context, message, uuids) {
|
|
3735
|
+
let count = 0;
|
|
3736
|
+
for (const uuid of uuids) {
|
|
3737
|
+
context.discardedSteerPromptUuids.delete(uuid);
|
|
3738
|
+
count += 1;
|
|
3739
|
+
}
|
|
3740
|
+
context.discardingCliTurn = void 0;
|
|
3741
|
+
context.wakeSignalDeferred = false;
|
|
3742
|
+
const open = context.turnState;
|
|
3743
|
+
if (open !== void 0) {
|
|
3744
|
+
const logContext = {
|
|
3745
|
+
threadId: context.session.threadId,
|
|
3746
|
+
turnId: open.turnId,
|
|
3747
|
+
openedBy: open.openedBy,
|
|
3748
|
+
uuids: count
|
|
3749
|
+
};
|
|
3750
|
+
if (claudeEchoNamesTurn({
|
|
3751
|
+
echoed: claudeEchoedPromptUuids(message),
|
|
3752
|
+
promptUuid: open.promptUuid,
|
|
3753
|
+
steerPromptUuids: open.steerPromptUuids
|
|
3754
|
+
})) {
|
|
3755
|
+
yield* effect.Effect.logInfo("claude.turn.discarded-steer-folded-open-turn", logContext);
|
|
3756
|
+
yield* handleResultMessage(context, message, { foldedIntoDiscardedCliTurn: true });
|
|
3757
|
+
return true;
|
|
3758
|
+
}
|
|
3759
|
+
if (open.promptUuid === void 0 && open.rootContentObserved) {
|
|
3760
|
+
yield* effect.Effect.logInfo("claude.turn.discarded-steer-output-leaked", logContext);
|
|
3761
|
+
return false;
|
|
3762
|
+
}
|
|
3763
|
+
}
|
|
3764
|
+
yield* emitTokenUsageSnapshot(context, yield* resolveResultUsageSnapshot(context, message), void 0);
|
|
3765
|
+
yield* retractDiscardedSteerWakeTurn(context);
|
|
3766
|
+
yield* effect.Effect.logInfo("claude.turn.discarded-cancelled-steer", {
|
|
3767
|
+
threadId: context.session.threadId,
|
|
3768
|
+
uuids: count
|
|
3769
|
+
});
|
|
3770
|
+
return true;
|
|
3771
|
+
});
|
|
3772
|
+
/**
|
|
3773
|
+
* Routes frames of CLI segments started by steers. Returns true when the frame was consumed
|
|
3774
|
+
* (dropped, or a result that already closed the open turn). The echo is read on a CLI turn's
|
|
3775
|
+
* first reply frame (its first stream event, or its first root assistant message when it
|
|
3776
|
+
* streamed nothing) and on its result. A CLI turn whose echo holds only steers Stop (or a failed
|
|
3777
|
+
* segment) discarded is interrupted again (unless its reply is an API error, which ends it
|
|
3778
|
+
* anyway) and dropped up to and including its result; a result with such an echo and no reply
|
|
3779
|
+
* before it is dropped alone. Either result still ends the open turn when only it can (see
|
|
3780
|
+
* `endDiscardedSteerCliTurn`). The open turn owns its own steers' segments; after Stop, one that
|
|
3781
|
+
* starts is interrupted again too, with the same API-error exception.
|
|
3782
|
+
*/
|
|
3783
|
+
const routeSteerFrame = effect.Effect.fn("routeSteerFrame")(function* (context, message) {
|
|
3784
|
+
const discarding = context.discardingCliTurn;
|
|
3785
|
+
if (discarding !== void 0) switch (message.type) {
|
|
3786
|
+
case "result": return yield* endDiscardedSteerCliTurn(context, message, [...discarding.uuids, ...claudeEchoedPromptUuids(message)]);
|
|
3787
|
+
case "stream_event":
|
|
3788
|
+
case "assistant":
|
|
3789
|
+
case "user":
|
|
3790
|
+
case "tool_progress":
|
|
3791
|
+
case "tool_use_summary": return true;
|
|
3792
|
+
default: return false;
|
|
3793
|
+
}
|
|
3794
|
+
if (message.type !== "stream_event" && message.type !== "assistant" && message.type !== "result") return false;
|
|
3795
|
+
const echoed = claudeEchoedPromptUuids(message);
|
|
3796
|
+
if (echoed.length === 0) return false;
|
|
3797
|
+
const discarded = context.discardedSteerPromptUuids;
|
|
3798
|
+
const turnState = context.turnState;
|
|
3799
|
+
const owned = turnState !== void 0 && claudeEchoNamesTurn({
|
|
3800
|
+
echoed,
|
|
3801
|
+
promptUuid: turnState.promptUuid,
|
|
3802
|
+
steerPromptUuids: turnState.steerPromptUuids
|
|
3803
|
+
});
|
|
3804
|
+
const reinterruptable = !isClaudeApiErrorReply(message);
|
|
3805
|
+
if (owned || !echoed.every((uuid) => discarded.has(uuid))) {
|
|
3806
|
+
if (owned && message.type !== "result") {
|
|
3807
|
+
for (const uuid of echoed) if (turnState.steerPromptUuids.has(uuid)) turnState.startedSteerPromptUuids.add(uuid);
|
|
3808
|
+
const echoKey = [...echoed].toSorted().join(" ");
|
|
3809
|
+
if (reinterruptable && turnState.interruptRequested && echoed.some((uuid) => turnState.steerPromptUuids.has(uuid) && !turnState.settledSteerPromptUuids.has(uuid)) && !turnState.reinterruptedEchoKeys.has(echoKey)) {
|
|
3810
|
+
turnState.reinterruptedEchoKeys.add(echoKey);
|
|
3811
|
+
yield* forkReinterrupt(context, "steer-segment-after-stop");
|
|
3812
|
+
}
|
|
3813
|
+
}
|
|
3814
|
+
for (const uuid of echoed) discarded.delete(uuid);
|
|
3815
|
+
return false;
|
|
3816
|
+
}
|
|
3817
|
+
if (message.type === "result") return yield* endDiscardedSteerCliTurn(context, message, echoed);
|
|
3818
|
+
context.discardingCliTurn = { uuids: new Set(echoed) };
|
|
3819
|
+
context.wakeSignalDeferred = false;
|
|
3820
|
+
if (reinterruptable) yield* forkReinterrupt(context, "discarded-steer-segment");
|
|
3821
|
+
yield* effect.Effect.logInfo("claude.turn.discarding-cancelled-steer", {
|
|
3822
|
+
threadId: context.session.threadId,
|
|
3823
|
+
uuids: echoed.length
|
|
3824
|
+
});
|
|
3825
|
+
yield* retractDiscardedSteerWakeTurn(context);
|
|
3826
|
+
return true;
|
|
3827
|
+
});
|
|
2939
3828
|
const handleSdkMessage = effect.Effect.fn("handleSdkMessage")(function* (context, message) {
|
|
2940
3829
|
yield* logNativeSdkMessage(context, message);
|
|
2941
3830
|
yield* ensureThreadId(context, message);
|
|
3831
|
+
if (yield* routeSteerFrame(context, message)) return;
|
|
3832
|
+
const chainUuid = claudeMainChainUuid(message);
|
|
3833
|
+
if (chainUuid !== void 0 && context.turnState) context.turnState.lastChainUuid = chainUuid;
|
|
3834
|
+
const rootContent = isClaudeRootTurnFrame(message);
|
|
3835
|
+
if (context.wakeSignalDeferred) {
|
|
3836
|
+
if (rootContent) {
|
|
3837
|
+
context.wakeSignalDeferred = false;
|
|
3838
|
+
if (context.turnState === void 0) yield* startProviderTurn(context, "wake-signal");
|
|
3839
|
+
} else if (message.type === "result") context.wakeSignalDeferred = false;
|
|
3840
|
+
}
|
|
3841
|
+
const waiting = context.turnState;
|
|
3842
|
+
if (waiting?.awaitingSteerContinuation !== void 0 && rootContent) waiting.awaitingSteerContinuation = void 0;
|
|
3843
|
+
yield* routeSdkMessage(context, message);
|
|
3844
|
+
const open = context.turnState;
|
|
3845
|
+
if (open && !open.rootOutputObserved && isClaudeRootTurnOutput(message)) open.rootOutputObserved = true;
|
|
3846
|
+
if (open && rootContent) open.rootContentObserved = true;
|
|
3847
|
+
});
|
|
3848
|
+
const routeSdkMessage = effect.Effect.fn("routeSdkMessage")(function* (context, message) {
|
|
2942
3849
|
switch (message.type) {
|
|
2943
3850
|
case "stream_event":
|
|
2944
3851
|
yield* handleStreamEvent(context, message);
|
|
@@ -2966,7 +3873,7 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
2966
3873
|
return;
|
|
2967
3874
|
}
|
|
2968
3875
|
});
|
|
2969
|
-
const runSdkStream = (context) => effect.Stream.fromAsyncIterable(context.query, (cause) => toError(cause, "Claude runtime stream failed.")).pipe(effect.Stream.takeWhile(() => !context.stopped), effect.Stream.runForEach((message) => handleSdkMessage(context, message)));
|
|
3876
|
+
const runSdkStream = (context) => effect.Stream.fromAsyncIterable(context.query, (cause) => toError(cause, "Claude runtime stream failed.")).pipe(effect.Stream.takeWhile(() => !context.stopped), effect.Stream.runForEach((message) => context.turnLock.withPermits(1)(handleSdkMessage(context, message))));
|
|
2970
3877
|
const handleStreamExit = effect.Effect.fn("handleStreamExit")(function* (context, exit) {
|
|
2971
3878
|
if (context.stopped) return;
|
|
2972
3879
|
if (effect.Exit.isFailure(exit)) {
|
|
@@ -2983,6 +3890,9 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
2983
3890
|
const stopSessionInternal = effect.Effect.fn("stopSessionInternal")(function* (context, options) {
|
|
2984
3891
|
if (context.stopped) return;
|
|
2985
3892
|
context.stopped = true;
|
|
3893
|
+
context.discardedSteerPromptUuids.clear();
|
|
3894
|
+
context.discardingCliTurn = void 0;
|
|
3895
|
+
context.wakeSignalDeferred = false;
|
|
2986
3896
|
context.deviceToolBinding?.dispose();
|
|
2987
3897
|
if (context.agentControl) yield* context.agentControl.revoke("runtime-teardown");
|
|
2988
3898
|
for (const [requestId, pending] of context.pendingApprovals) {
|
|
@@ -3009,11 +3919,22 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
3009
3919
|
yield* effect.Queue.shutdown(context.promptQueue);
|
|
3010
3920
|
const streamFiber = context.streamFiber;
|
|
3011
3921
|
context.streamFiber = void 0;
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3922
|
+
const closeQuery = effect.Effect.gen(function* () {
|
|
3923
|
+
try {
|
|
3924
|
+
context.query.close();
|
|
3925
|
+
} catch (cause) {
|
|
3926
|
+
yield* emitRuntimeError(context, "Failed to close Claude runtime query.", cause);
|
|
3927
|
+
}
|
|
3928
|
+
});
|
|
3929
|
+
if (options?.awaitQueryExitMs !== void 0) {
|
|
3930
|
+
yield* closeQuery;
|
|
3931
|
+
if (streamFiber && streamFiber.pollUnsafe() === void 0) {
|
|
3932
|
+
const exited = yield* effect.Fiber.await(streamFiber).pipe(effect.Effect.timeoutOption(effect.Duration.millis(options.awaitQueryExitMs)));
|
|
3933
|
+
if (effect.Option.isNone(exited)) yield* effect.Fiber.interrupt(streamFiber);
|
|
3934
|
+
}
|
|
3935
|
+
} else {
|
|
3936
|
+
if (streamFiber && streamFiber.pollUnsafe() === void 0) yield* effect.Fiber.interrupt(streamFiber);
|
|
3937
|
+
yield* closeQuery;
|
|
3017
3938
|
}
|
|
3018
3939
|
const updatedAt = yield* nowIso;
|
|
3019
3940
|
context.session = {
|
|
@@ -3063,6 +3984,11 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
3063
3984
|
issue: `Expected provider instance '${boundInstanceId}' but received '${input.providerInstanceId}'.`
|
|
3064
3985
|
});
|
|
3065
3986
|
const runtimeSessionId = yield* require_runtimeSession.requireRuntimeSessionId(PROVIDER, input);
|
|
3987
|
+
if (rewindingThreads.has(input.threadId)) return yield* new require_bin.ProviderAdapterValidationError({
|
|
3988
|
+
provider: PROVIDER,
|
|
3989
|
+
operation: "startSession",
|
|
3990
|
+
issue: "Claude is rewinding this thread; try again in a moment."
|
|
3991
|
+
});
|
|
3066
3992
|
const existingContext = sessions.get(input.threadId);
|
|
3067
3993
|
if (existingContext) {
|
|
3068
3994
|
if (existingContext.session.runtimeSessionId === runtimeSessionId) return existingContext.session;
|
|
@@ -3072,6 +3998,15 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
3072
3998
|
issue: `Thread '${input.threadId}' still has runtime '${existingContext.session.runtimeSessionId ?? "legacy"}'; stop it before starting '${runtimeSessionId}'.`
|
|
3073
3999
|
});
|
|
3074
4000
|
}
|
|
4001
|
+
return { ...(yield* openSessionContext(input, {})).session };
|
|
4002
|
+
});
|
|
4003
|
+
/**
|
|
4004
|
+
* Opens a query for `input` and registers its context. With `probe`, the
|
|
4005
|
+
* reopened CLI must accept a control request before this succeeds; a failed
|
|
4006
|
+
* probe stops the context silently (no runtime.error or session.exited).
|
|
4007
|
+
*/
|
|
4008
|
+
const openSessionContext = effect.Effect.fn("openSessionContext")(function* (input, openOptions) {
|
|
4009
|
+
const runtimeSessionId = yield* require_runtimeSession.requireRuntimeSessionId(PROVIDER, input);
|
|
3075
4010
|
const startedAt = yield* nowIso;
|
|
3076
4011
|
const effectiveResumeCursor = input.resumePolicy === "fresh" ? void 0 : input.resumeCursor;
|
|
3077
4012
|
const resumeState = readClaudeResumeState(effectiveResumeCursor);
|
|
@@ -3303,7 +4238,10 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
3303
4238
|
});
|
|
3304
4239
|
const canUseTool = (toolName, toolInput, callbackOptions) => runPromise(canUseToolEffect(toolName, toolInput, callbackOptions));
|
|
3305
4240
|
const claudeBinaryPath = claudeSettings.binaryPath;
|
|
3306
|
-
const extraArgs =
|
|
4241
|
+
const extraArgs = {
|
|
4242
|
+
"thinking-display": "summarized",
|
|
4243
|
+
...parseCliArgs(claudeSettings.launchArgs).flags
|
|
4244
|
+
};
|
|
3307
4245
|
const modelSelection = input.modelSelection?.instanceId === boundInstanceId ? input.modelSelection : void 0;
|
|
3308
4246
|
const caps = getClaudeModelCapabilities(modelSelection?.model);
|
|
3309
4247
|
const descriptors = require_Metrics.getProviderOptionDescriptors({ caps });
|
|
@@ -3360,6 +4298,8 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
3360
4298
|
...permissionMode === "bypassPermissions" ? { allowDangerouslySkipPermissions: true } : {},
|
|
3361
4299
|
...Object.keys(settings).length > 0 ? { settings } : {},
|
|
3362
4300
|
...existingResumeSessionId ? { resume: existingResumeSessionId } : {},
|
|
4301
|
+
...existingResumeSessionId && resumeState?.rewindAt ? { resumeSessionAt: resumeState.rewindAt } : {},
|
|
4302
|
+
...existingResumeSessionId && resumeState?.rewindAt && openOptions.resumeDropsTurn ? { resumeDropsTurn: openOptions.resumeDropsTurn } : {},
|
|
3363
4303
|
...newSessionId ? { sessionId: newSessionId } : {},
|
|
3364
4304
|
includePartialMessages: true,
|
|
3365
4305
|
canUseTool,
|
|
@@ -3433,6 +4373,7 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
3433
4373
|
...threadId ? { threadId } : {},
|
|
3434
4374
|
...sessionId ? { resume: sessionId } : {},
|
|
3435
4375
|
...resumeState?.resumeSessionAt ? { resumeSessionAt: resumeState.resumeSessionAt } : {},
|
|
4376
|
+
...existingResumeSessionId && resumeState?.rewindAt ? { rewind: { at: resumeState.rewindAt } } : {},
|
|
3436
4377
|
turnCount: resumeState?.turnCount ?? 0
|
|
3437
4378
|
},
|
|
3438
4379
|
createdAt: startedAt,
|
|
@@ -3440,9 +4381,15 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
3440
4381
|
};
|
|
3441
4382
|
const generation = ++nextSessionGeneration;
|
|
3442
4383
|
const supportsAutomaticCompaction = typeof queryRuntime.applyFlagSettings === "function";
|
|
4384
|
+
const { resumeCursor: _resumeCursor, resumePolicy: _resumePolicy, ...startInput } = input;
|
|
3443
4385
|
const context = {
|
|
3444
4386
|
generation,
|
|
3445
4387
|
session,
|
|
4388
|
+
startInput,
|
|
4389
|
+
turnHeads: [...openOptions.turnHeads ?? []],
|
|
4390
|
+
pendingRewind: existingResumeSessionId && resumeState?.rewindAt ? { at: resumeState.rewindAt } : void 0,
|
|
4391
|
+
probing: openOptions.probe === true,
|
|
4392
|
+
probeFailure: openOptions.probe === true ? effect.Deferred.makeUnsafe() : void 0,
|
|
3446
4393
|
promptQueue,
|
|
3447
4394
|
query: queryRuntime,
|
|
3448
4395
|
deviceToolBinding,
|
|
@@ -3463,7 +4410,9 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
3463
4410
|
taskAgents: /* @__PURE__ */ new Map(),
|
|
3464
4411
|
subagentLaunchInputByToolUseId: /* @__PURE__ */ new Map(),
|
|
3465
4412
|
subagentModelByToolUseId: /* @__PURE__ */ new Map(),
|
|
4413
|
+
subagentParentByToolUseId: /* @__PURE__ */ new Map(),
|
|
3466
4414
|
workflowMemberFingerprints: /* @__PURE__ */ new Map(),
|
|
4415
|
+
rejectedRateLimitWindows: /* @__PURE__ */ new Map(),
|
|
3467
4416
|
workflowPhasesByTaskId: /* @__PURE__ */ new Map(),
|
|
3468
4417
|
liveTaskIds: /* @__PURE__ */ new Set(),
|
|
3469
4418
|
backgroundedTaskIds: /* @__PURE__ */ new Set(),
|
|
@@ -3471,6 +4420,8 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
3471
4420
|
lastKnownContextWindow: void 0,
|
|
3472
4421
|
lastKnownTokenUsage: void 0,
|
|
3473
4422
|
cacheObservation: void 0,
|
|
4423
|
+
mainLoopUsageObserved: false,
|
|
4424
|
+
cumulativeUsageSpansCompaction: false,
|
|
3474
4425
|
cacheModelSelection: modelSelection,
|
|
3475
4426
|
compactionPolicy: initialContextCompactionPolicyState(generation),
|
|
3476
4427
|
supportsAutomaticCompaction,
|
|
@@ -3480,7 +4431,15 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
3480
4431
|
subagentByTaskId: /* @__PURE__ */ new Map(),
|
|
3481
4432
|
startedSubagentIds: /* @__PURE__ */ new Set(),
|
|
3482
4433
|
completedSubagentIds: /* @__PURE__ */ new Set(),
|
|
3483
|
-
stopped: false
|
|
4434
|
+
stopped: false,
|
|
4435
|
+
promptSent: false,
|
|
4436
|
+
turnInstallsInFlight: 0,
|
|
4437
|
+
requestingStatusObserved: false,
|
|
4438
|
+
cliCapabilities: void 0,
|
|
4439
|
+
discardedSteerPromptUuids: /* @__PURE__ */ new Set(),
|
|
4440
|
+
discardingCliTurn: void 0,
|
|
4441
|
+
wakeSignalDeferred: false,
|
|
4442
|
+
turnLock: yield* effect.Semaphore.make(1)
|
|
3484
4443
|
};
|
|
3485
4444
|
deviceToolContext = context;
|
|
3486
4445
|
yield* effect.Ref.set(contextRef, context);
|
|
@@ -3525,18 +4484,35 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
3525
4484
|
streamFiber = runFork(effect.Effect.exit(runSdkStream(context)).pipe(effect.Effect.flatMap((exit) => {
|
|
3526
4485
|
if (context.stopped) return effect.Effect.void;
|
|
3527
4486
|
if (context.streamFiber === streamFiber) context.streamFiber = void 0;
|
|
4487
|
+
if (context.probing && context.probeFailure) return effect.Deferred.succeed(context.probeFailure, effect.Exit.isFailure(exit) ? messageFromClaudeStreamCause(exit.cause, "Claude runtime stream failed.") : "Claude exited while reopening the conversation.").pipe(effect.Effect.asVoid);
|
|
3528
4488
|
return handleStreamExit(context, exit);
|
|
3529
4489
|
})));
|
|
3530
4490
|
context.streamFiber = streamFiber;
|
|
3531
4491
|
streamFiber.addObserver(() => {
|
|
3532
4492
|
if (context.streamFiber === streamFiber) context.streamFiber = void 0;
|
|
3533
4493
|
});
|
|
3534
|
-
|
|
4494
|
+
if (context.probing && context.probeFailure) {
|
|
4495
|
+
const probeFailure = context.probeFailure;
|
|
4496
|
+
const controlRequest = effect.Effect.tryPromise({
|
|
4497
|
+
try: () => queryRuntime.initializationResult?.() ?? queryRuntime.mcpServerStatus?.() ?? Promise.resolve(),
|
|
4498
|
+
catch: (cause) => toMessage(cause, "Claude rejected the reopened conversation.")
|
|
4499
|
+
});
|
|
4500
|
+
const probe = yield* effect.Effect.raceFirst(controlRequest.pipe(effect.Effect.asVoid), effect.Deferred.await(probeFailure).pipe(effect.Effect.flatMap((detail) => effect.Effect.fail(detail)))).pipe(effect.Effect.timeoutOption(CLAUDE_REWIND_PROBE_TIMEOUT), effect.Effect.result);
|
|
4501
|
+
context.probing = false;
|
|
4502
|
+
const failure = probe._tag === "Failure" ? probe.failure : effect.Option.isNone(probe.success) ? "Claude did not respond while reopening the conversation." : effect.Deferred.isDoneUnsafe(probeFailure) ? "Claude exited while reopening the conversation." : void 0;
|
|
4503
|
+
if (failure !== void 0) {
|
|
4504
|
+
yield* stopSessionInternal(context, { emitExitEvent: false });
|
|
4505
|
+
return yield* new require_bin.ProviderAdapterProcessError({
|
|
4506
|
+
provider: PROVIDER,
|
|
4507
|
+
threadId,
|
|
4508
|
+
detail: failure
|
|
4509
|
+
});
|
|
4510
|
+
}
|
|
4511
|
+
}
|
|
4512
|
+
return context;
|
|
3535
4513
|
});
|
|
3536
|
-
const
|
|
3537
|
-
const context = yield* requireSession(input.threadId);
|
|
4514
|
+
const sendTurnOnContext = effect.Effect.fn("sendTurnOnContext")(function* (context, input) {
|
|
3538
4515
|
const modelSelection = input.modelSelection !== void 0 && input.modelSelection.instanceId === boundInstanceId ? input.modelSelection : void 0;
|
|
3539
|
-
if (context.turnState) yield* completeTurn(context, "completed");
|
|
3540
4516
|
if (modelSelection?.model) {
|
|
3541
4517
|
const apiModelId = resolveClaudeApiModelId(modelSelection);
|
|
3542
4518
|
if (context.currentApiModelId !== apiModelId) {
|
|
@@ -3563,24 +4539,23 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
3563
4539
|
try: () => context.query.setPermissionMode(context.basePermissionMode ?? "default"),
|
|
3564
4540
|
catch: (cause) => toRequestError(input.threadId, "turn/setPermissionMode", cause)
|
|
3565
4541
|
});
|
|
3566
|
-
const
|
|
3567
|
-
const
|
|
4542
|
+
const promptUuid = yield* effect.Effect.sync(() => crypto.randomUUID());
|
|
4543
|
+
const turnId = require_src.TurnId.make(promptUuid);
|
|
4544
|
+
const startedAt = yield* nowIso;
|
|
4545
|
+
while (context.turnState !== void 0) yield* completeTurn(context, "completed");
|
|
4546
|
+
context.turnState = makeClaudeTurnState({
|
|
3568
4547
|
turnId,
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
capturedProposedPlanKeys: /* @__PURE__ */ new Set(),
|
|
3574
|
-
nextSyntheticAssistantBlockIndex: -1
|
|
3575
|
-
};
|
|
3576
|
-
const updatedAt = yield* nowIso;
|
|
3577
|
-
context.turnState = turnState;
|
|
4548
|
+
promptUuid,
|
|
4549
|
+
startedAt,
|
|
4550
|
+
openedBy: "prompt"
|
|
4551
|
+
});
|
|
3578
4552
|
context.session = {
|
|
3579
4553
|
...context.session,
|
|
3580
4554
|
status: "running",
|
|
3581
4555
|
activeTurnId: turnId,
|
|
3582
|
-
updatedAt
|
|
4556
|
+
updatedAt: startedAt
|
|
3583
4557
|
};
|
|
4558
|
+
context.promptSent = true;
|
|
3584
4559
|
const turnStartedStamp = yield* makeEventStamp();
|
|
3585
4560
|
yield* offerRuntimeEventForContext(context, {
|
|
3586
4561
|
type: "turn.started",
|
|
@@ -3604,7 +4579,10 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
3604
4579
|
});
|
|
3605
4580
|
yield* effect.Queue.offer(context.promptQueue, {
|
|
3606
4581
|
type: "message",
|
|
3607
|
-
message
|
|
4582
|
+
message: {
|
|
4583
|
+
...message,
|
|
4584
|
+
uuid: promptUuid
|
|
4585
|
+
}
|
|
3608
4586
|
}).pipe(effect.Effect.mapError((cause) => toRequestError(input.threadId, "turn/start", cause)));
|
|
3609
4587
|
if (context.agentControl) yield* context.agentControl.bindTurn(turnId).pipe(effect.Effect.catchCause((cause) => effect.Effect.logWarning("failed to bind Agent Control turn authority", {
|
|
3610
4588
|
threadId: input.threadId,
|
|
@@ -3617,9 +4595,73 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
3617
4595
|
...context.session.resumeCursor !== void 0 ? { resumeCursor: context.session.resumeCursor } : {}
|
|
3618
4596
|
};
|
|
3619
4597
|
});
|
|
3620
|
-
const
|
|
4598
|
+
const sendTurn = effect.Effect.fn("sendTurn")(function* (input) {
|
|
4599
|
+
const context = yield* requireSession(input.threadId);
|
|
4600
|
+
return yield* effect.Effect.acquireUseRelease(effect.Effect.sync(() => {
|
|
4601
|
+
context.turnInstallsInFlight += 1;
|
|
4602
|
+
}), () => sendTurnOnContext(context, input), () => effect.Effect.sync(() => {
|
|
4603
|
+
context.turnInstallsInFlight -= 1;
|
|
4604
|
+
}));
|
|
4605
|
+
});
|
|
4606
|
+
/**
|
|
4607
|
+
* Adds a user message to the exact running turn: an SDK user message with `priority: "now"`
|
|
4608
|
+
* and its own uuid. The Ryco turn keeps its id and absorbs the CLI segments the steer starts.
|
|
4609
|
+
* Refusals are `ProviderTurnNotSteerableError`, so the message stays queued as the next turn.
|
|
4610
|
+
*/
|
|
4611
|
+
const steerTurn = effect.Effect.fn("steerTurn")(function* (input) {
|
|
4612
|
+
const context = yield* requireSession(input.threadId);
|
|
4613
|
+
const refuse = (reason, detail) => new require_bin.ProviderTurnNotSteerableError({
|
|
4614
|
+
provider: PROVIDER,
|
|
4615
|
+
threadId: input.threadId,
|
|
4616
|
+
turnId: input.expectedTurnId,
|
|
4617
|
+
reason,
|
|
4618
|
+
detail
|
|
4619
|
+
});
|
|
4620
|
+
const turnState = context.turnState;
|
|
4621
|
+
if (!turnState || turnState.turnId !== input.expectedTurnId || context.session.activeTurnId !== input.expectedTurnId || turnState.interruptRequested) return yield* refuse("turn-ended", STEER_TURN_ENDED_DETAIL);
|
|
4622
|
+
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.");
|
|
4623
|
+
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.");
|
|
4624
|
+
if (input.input?.trimStart().startsWith("/")) return yield* refuse("unsupported", "Slash commands can't be steered into a running turn. The message stays queued.");
|
|
4625
|
+
const message = yield* buildUserMessageEffect({
|
|
4626
|
+
threadId: input.threadId,
|
|
4627
|
+
...input.input ? { input: input.input } : {},
|
|
4628
|
+
attachments: input.attachments ?? [],
|
|
4629
|
+
...context.cacheModelSelection ? { modelSelection: context.cacheModelSelection } : {}
|
|
4630
|
+
}, {
|
|
4631
|
+
fileSystem,
|
|
4632
|
+
attachmentsDir: serverConfig.attachmentsDir,
|
|
4633
|
+
boundInstanceId
|
|
4634
|
+
});
|
|
4635
|
+
const steerUuid = yield* effect.Effect.sync(() => crypto.randomUUID());
|
|
4636
|
+
if (!(yield* context.turnLock.withPermits(1)(effect.Effect.gen(function* () {
|
|
4637
|
+
if (sessions.get(input.threadId) !== context || context.stopped || context.turnState !== turnState || turnState.interruptRequested || turnState.completion !== void 0) return false;
|
|
4638
|
+
turnState.steerPromptUuids.add(steerUuid);
|
|
4639
|
+
const offered = yield* effect.Queue.offer(context.promptQueue, {
|
|
4640
|
+
type: "message",
|
|
4641
|
+
message: {
|
|
4642
|
+
...message,
|
|
4643
|
+
uuid: steerUuid,
|
|
4644
|
+
priority: "now"
|
|
4645
|
+
}
|
|
4646
|
+
});
|
|
4647
|
+
if (!offered) turnState.steerPromptUuids.delete(steerUuid);
|
|
4648
|
+
return offered;
|
|
4649
|
+
})))) return yield* refuse("turn-ended", STEER_TURN_ENDED_DETAIL);
|
|
4650
|
+
yield* effect.Effect.logInfo("claude.turn.steered", {
|
|
4651
|
+
threadId: input.threadId,
|
|
4652
|
+
turnId: turnState.turnId,
|
|
4653
|
+
awaiting: turnState.awaitingSteerContinuation !== void 0
|
|
4654
|
+
});
|
|
4655
|
+
return {
|
|
4656
|
+
threadId: context.session.threadId,
|
|
4657
|
+
turnId: turnState.turnId
|
|
4658
|
+
};
|
|
4659
|
+
});
|
|
4660
|
+
const interruptTurn = effect.Effect.fn("interruptTurn")(function* (threadId, turnId) {
|
|
3621
4661
|
const context = yield* requireSession(threadId);
|
|
3622
|
-
|
|
4662
|
+
const target = context.turnState;
|
|
4663
|
+
if (target) target.interruptRequested = true;
|
|
4664
|
+
if (context.agentControl) yield* context.agentControl.retireTurn(turnId);
|
|
3623
4665
|
if (context.query.stopTask && context.liveTaskIds.size > 0) {
|
|
3624
4666
|
const liveIds = Array.from(context.liveTaskIds);
|
|
3625
4667
|
yield* effect.Effect.forEach(liveIds, (taskId) => effect.Effect.gen(function* () {
|
|
@@ -3648,10 +4690,47 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
3648
4690
|
discard: true
|
|
3649
4691
|
}).pipe(effect.Effect.timeoutOption("10 seconds"), effect.Effect.ignore);
|
|
3650
4692
|
}
|
|
3651
|
-
|
|
3652
|
-
|
|
4693
|
+
const cancelQueued = (target ? [...target.steerPromptUuids].filter((uuid) => !target.settledSteerPromptUuids.has(uuid)) : []).length > 0 && context.cliCapabilities?.has("interrupt_cancel_queued_v1") === true;
|
|
4694
|
+
const rawReceipt = yield* effect.Effect.tryPromise({
|
|
4695
|
+
try: () => cancelQueued ? context.query.interrupt({ cancelQueued: true }) : context.query.interrupt(),
|
|
3653
4696
|
catch: (cause) => toRequestError(threadId, "turn/interrupt", cause)
|
|
3654
4697
|
});
|
|
4698
|
+
if (target !== void 0 && target.steerPromptUuids.size > 0) {
|
|
4699
|
+
const receipt = readClaudeInterruptReceipt(rawReceipt);
|
|
4700
|
+
yield* effect.Effect.logInfo("claude.turn.interrupt-receipt", {
|
|
4701
|
+
threadId: context.session.threadId,
|
|
4702
|
+
turnId: target.turnId,
|
|
4703
|
+
cancelQueued,
|
|
4704
|
+
hasReceipt: receipt !== void 0,
|
|
4705
|
+
stillQueued: receipt?.stillQueued.length ?? 0,
|
|
4706
|
+
cancelled: receipt?.cancelled?.length ?? 0
|
|
4707
|
+
});
|
|
4708
|
+
yield* context.turnLock.withPermits(1)(effect.Effect.gen(function* () {
|
|
4709
|
+
if (context.stopped) return;
|
|
4710
|
+
const stop = decideClaudeStop({
|
|
4711
|
+
unsettledSteers: [...target.steerPromptUuids].filter((uuid) => !target.settledSteerPromptUuids.has(uuid)),
|
|
4712
|
+
startedSteers: target.startedSteerPromptUuids,
|
|
4713
|
+
promptUuid: target.promptUuid,
|
|
4714
|
+
sealedSegmentCount: target.sealedSegmentCount,
|
|
4715
|
+
awaitingSteerContinuation: target.awaitingSteerContinuation !== void 0,
|
|
4716
|
+
receipt
|
|
4717
|
+
});
|
|
4718
|
+
if (context.turnState === target) for (const uuid of stop.discard) rememberDiscardedSteer(context.discardedSteerPromptUuids, uuid);
|
|
4719
|
+
for (const uuid of stop.release) {
|
|
4720
|
+
context.discardedSteerPromptUuids.delete(uuid);
|
|
4721
|
+
target.settledSteerPromptUuids.add(uuid);
|
|
4722
|
+
}
|
|
4723
|
+
if (stop.forceClose && context.turnState === target) yield* completeTurn(context, "interrupted", "Interrupted by user.", void 0, { expectedTurnState: target });
|
|
4724
|
+
}));
|
|
4725
|
+
}
|
|
4726
|
+
if (target !== void 0 && target.openedBy !== "prompt" && (turnId === void 0 || target.turnId === turnId)) yield* effect.Effect.sleep(effect.Duration.millis(CLAUDE_PROVIDER_TURN_STOP_GRACE_MS)).pipe(effect.Effect.andThen(effect.Effect.suspend(() => {
|
|
4727
|
+
if (context.turnState !== target || target.completion !== void 0 || context.stopped) return effect.Effect.void;
|
|
4728
|
+
return effect.Effect.logInfo("claude.turn.provider-turn-finalized-after-stop", {
|
|
4729
|
+
threadId: context.session.threadId,
|
|
4730
|
+
turnId: target.turnId,
|
|
4731
|
+
openedBy: target.openedBy
|
|
4732
|
+
}).pipe(effect.Effect.andThen(completeTurn(context, "interrupted", PROVIDER_TURN_STOP_REASON)));
|
|
4733
|
+
})), effect.Effect.ignoreCause({ log: true }), effect.Effect.forkDetach);
|
|
3655
4734
|
});
|
|
3656
4735
|
const stopBackgroundTask = effect.Effect.fn("stopBackgroundTask")(function* (threadId, taskId, expected) {
|
|
3657
4736
|
const context = yield* requireSession(threadId);
|
|
@@ -3686,12 +4765,109 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
3686
4765
|
const context = yield* requireSession(threadId);
|
|
3687
4766
|
return yield* snapshotThread(context);
|
|
3688
4767
|
});
|
|
3689
|
-
|
|
4768
|
+
/** The session's main transcript chain, oldest first. Errors and timeouts read as empty. */
|
|
4769
|
+
const readMainTranscriptChain = effect.Effect.fn("readMainTranscriptChain")(function* (sessionId, cwd) {
|
|
4770
|
+
const read = (dir) => effect.Effect.tryPromise(() => readSessionMessages(sessionId, {
|
|
4771
|
+
...dir !== void 0 ? { dir } : {},
|
|
4772
|
+
includeSystemMessages: true
|
|
4773
|
+
})).pipe(effect.Effect.timeoutOption(CLAUDE_REWIND_TRANSCRIPT_TIMEOUT), effect.Effect.map((entries) => effect.Option.getOrElse(entries, () => [])), effect.Effect.catch(() => effect.Effect.succeed([])), effect.Effect.map((entries) => entries.filter((entry) => typeof entry.uuid === "string" && (entry.parent_tool_use_id === null || entry.parent_tool_use_id === void 0))));
|
|
4774
|
+
const inCwd = yield* read(cwd);
|
|
4775
|
+
return inCwd.length > 0 || cwd === void 0 ? inCwd : yield* read(void 0);
|
|
4776
|
+
});
|
|
4777
|
+
/**
|
|
4778
|
+
* Makes Claude forget the newest turns: close the live query, wait for the
|
|
4779
|
+
* CLI to exit, and reopen the transcript truncated just before the first
|
|
4780
|
+
* dropped prompt (or a fresh session for checkpoint 0). A reopen the CLI
|
|
4781
|
+
* refuses restores the previous conversation and reports the refusal.
|
|
4782
|
+
*/
|
|
4783
|
+
const rollbackThread = effect.Effect.fn("rollbackThread")(function* (threadId, input) {
|
|
3690
4784
|
const context = yield* requireSession(threadId);
|
|
3691
|
-
const
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
4785
|
+
const refuse = (detail) => new require_bin.ProviderAdapterRequestError({
|
|
4786
|
+
provider: PROVIDER,
|
|
4787
|
+
method: "thread/rollback",
|
|
4788
|
+
detail
|
|
4789
|
+
});
|
|
4790
|
+
if (context.turnState) return yield* refuse("A Claude turn is still running.");
|
|
4791
|
+
if (context.liveTaskIds.size > 0) return yield* refuse("Claude still has background tasks running. Stop them, then revert again.");
|
|
4792
|
+
if (context.pendingApprovals.size > 0 || context.pendingUserInputs.size > 0) return yield* refuse("Claude is waiting for your answer. Answer it, then revert again.");
|
|
4793
|
+
if (rewindingThreads.has(threadId)) return yield* refuse("Claude is already rewinding this thread.");
|
|
4794
|
+
let plan;
|
|
4795
|
+
if (input.targetTurnId === null) plan = { kind: "fresh" };
|
|
4796
|
+
else {
|
|
4797
|
+
const firstDropped = input.droppedTurnIds[0];
|
|
4798
|
+
const chain = context.resumeSessionId !== void 0 && firstDropped !== void 0 ? yield* readMainTranscriptChain(context.resumeSessionId, context.session.cwd) : [];
|
|
4799
|
+
const index = firstDropped === void 0 ? -1 : chain.findIndex((entry) => entry.uuid === firstDropped);
|
|
4800
|
+
if (index > 0) plan = {
|
|
4801
|
+
kind: "rewind",
|
|
4802
|
+
at: chain[index - 1].uuid,
|
|
4803
|
+
...input.droppedTurnIds.length === 1 && firstDropped !== void 0 ? { dropsTurn: firstDropped } : {}
|
|
4804
|
+
};
|
|
4805
|
+
else if (index === 0) plan = { kind: "fresh" };
|
|
4806
|
+
else {
|
|
4807
|
+
const head = context.turnHeads.find((entry) => entry.turnId === input.targetTurnId)?.head;
|
|
4808
|
+
if (head !== void 0) plan = {
|
|
4809
|
+
kind: "rewind",
|
|
4810
|
+
at: head
|
|
4811
|
+
};
|
|
4812
|
+
}
|
|
4813
|
+
}
|
|
4814
|
+
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.");
|
|
4815
|
+
const rewindPlan = plan;
|
|
4816
|
+
rewindingThreads.add(threadId);
|
|
4817
|
+
return yield* effect.Effect.gen(function* () {
|
|
4818
|
+
const previousCursor = context.session.resumeCursor;
|
|
4819
|
+
const dropped = new Set(input.droppedTurnIds);
|
|
4820
|
+
const keptTurnHeads = context.turnHeads.filter((entry) => !dropped.has(entry.turnId));
|
|
4821
|
+
yield* stopSessionInternal(context, {
|
|
4822
|
+
emitExitEvent: false,
|
|
4823
|
+
awaitQueryExitMs: CLAUDE_REWIND_QUERY_EXIT_MS
|
|
4824
|
+
});
|
|
4825
|
+
const previousTurnCount = readClaudeResumeState(previousCursor)?.turnCount ?? context.turns.length;
|
|
4826
|
+
const nextCursor = rewindPlan.kind === "fresh" || context.resumeSessionId === void 0 ? { threadId } : {
|
|
4827
|
+
threadId,
|
|
4828
|
+
resume: context.resumeSessionId,
|
|
4829
|
+
rewind: { at: rewindPlan.at },
|
|
4830
|
+
turnCount: Math.max(0, previousTurnCount - input.numTurns)
|
|
4831
|
+
};
|
|
4832
|
+
const reopenInput = {
|
|
4833
|
+
...context.startInput,
|
|
4834
|
+
runtimeMode: context.session.runtimeMode,
|
|
4835
|
+
...context.session.tokenMode !== void 0 ? { tokenMode: context.session.tokenMode } : {},
|
|
4836
|
+
...context.cacheModelSelection ?? context.startInput.modelSelection ? { modelSelection: context.cacheModelSelection ?? context.startInput.modelSelection } : {},
|
|
4837
|
+
...context.session.runtimeSessionId !== void 0 ? { runtimeSessionId: context.session.runtimeSessionId } : {}
|
|
4838
|
+
};
|
|
4839
|
+
const reopened = yield* effect.Effect.result(openSessionContext({
|
|
4840
|
+
...reopenInput,
|
|
4841
|
+
resumeCursor: nextCursor
|
|
4842
|
+
}, {
|
|
4843
|
+
probe: true,
|
|
4844
|
+
turnHeads: keptTurnHeads
|
|
4845
|
+
}));
|
|
4846
|
+
if (reopened._tag === "Success") return yield* snapshotThread(reopened.success);
|
|
4847
|
+
const refusal = adapterFailureDetail(reopened.failure);
|
|
4848
|
+
if ((yield* effect.Effect.result(openSessionContext({
|
|
4849
|
+
...reopenInput,
|
|
4850
|
+
resumeCursor: previousCursor
|
|
4851
|
+
}, {
|
|
4852
|
+
probe: true,
|
|
4853
|
+
turnHeads: context.turnHeads
|
|
4854
|
+
})))._tag === "Failure") {
|
|
4855
|
+
const stamp = yield* makeEventStamp();
|
|
4856
|
+
yield* offerRuntimeEventForContext(context, {
|
|
4857
|
+
type: "session.exited",
|
|
4858
|
+
eventId: stamp.eventId,
|
|
4859
|
+
provider: PROVIDER,
|
|
4860
|
+
createdAt: stamp.createdAt,
|
|
4861
|
+
threadId,
|
|
4862
|
+
payload: {
|
|
4863
|
+
reason: "Claude could not restart after a failed rewind",
|
|
4864
|
+
exitKind: "error"
|
|
4865
|
+
},
|
|
4866
|
+
providerRefs: {}
|
|
4867
|
+
});
|
|
4868
|
+
}
|
|
4869
|
+
return yield* refuse(`Claude refused to rewind this conversation, so nothing was changed. ${refusal}`);
|
|
4870
|
+
}).pipe(effect.Effect.ensuring(effect.Effect.sync(() => rewindingThreads.delete(threadId))));
|
|
3695
4871
|
});
|
|
3696
4872
|
const respondToRequest = effect.Effect.fn("respondToRequest")(function* (threadId, requestId, decision) {
|
|
3697
4873
|
const context = yield* requireSession(threadId);
|
|
@@ -3728,9 +4904,15 @@ const makeClaudeAdapter = effect.Effect.fn("makeClaudeAdapter")(function* (claud
|
|
|
3728
4904
|
yield* effect.Effect.addFinalizer(() => effect.Effect.forEach(sessions, ([, context]) => stopSessionInternal(context, { emitExitEvent: false }), { discard: true }).pipe(effect.Effect.tap(() => runtimeEventQueueMetrics.reset), effect.Effect.tap(() => effect.Queue.shutdown(runtimeEventQueue))));
|
|
3729
4905
|
return {
|
|
3730
4906
|
provider: PROVIDER,
|
|
3731
|
-
capabilities: {
|
|
4907
|
+
capabilities: {
|
|
4908
|
+
sessionModelSwitch: "in-session",
|
|
4909
|
+
conversationRollback: "native",
|
|
4910
|
+
turnSteering: "native",
|
|
4911
|
+
resumeSurvivesCwdChange: false
|
|
4912
|
+
},
|
|
3732
4913
|
startSession,
|
|
3733
4914
|
sendTurn,
|
|
4915
|
+
steerTurn,
|
|
3734
4916
|
interruptTurn,
|
|
3735
4917
|
stopBackgroundTask,
|
|
3736
4918
|
readThread,
|