@openscout/scout 0.2.95 → 0.2.97
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/bin/scout +26 -10
- package/bin/scoutd +0 -0
- package/dist/build-manifest.json +3 -3
- package/dist/client/assets/{ActivityScreen--eANwuxa.js → ActivityScreen-y-5DLleY.js} +1 -1
- package/dist/client/assets/{AddProjectForm-CcD6qvV8.js → AddProjectForm-r_1tVuWk.js} +1 -1
- package/dist/client/assets/{AgentAvatar-CYhf6twS.js → AgentAvatar-B7c0egdP.js} +1 -1
- package/dist/client/assets/{AgentConfigurationScreen-BTI24HQX.js → AgentConfigurationScreen-BD7Unt2P.js} +1 -1
- package/dist/client/assets/{AgentDefinitionsWorkspace-srmN6-vj.js → AgentDefinitionsWorkspace-BbcZc9Xk.js} +1 -1
- package/dist/client/assets/{AgentDetailCard-UqPNpcvB.js → AgentDetailCard-B_KLcgsP.js} +1 -1
- package/dist/client/assets/{AgentFloorView-XXNgI5Cj.js → AgentFloorView-DMFiHs21.js} +1 -1
- package/dist/client/assets/{AgentInfoScreen-CimdOnZ9.js → AgentInfoScreen-DHGLRddI.js} +1 -1
- package/dist/client/assets/{AgentLaneCard-Z-aOBR3W.js → AgentLaneCard-ajZvcfdW.js} +1 -1
- package/dist/client/assets/{AgentLaneChrome-CyhA1reW.js → AgentLaneChrome-CTp39syR.js} +1 -1
- package/dist/client/assets/{AgentLaneDetailSheet-BNzjMjIH.js → AgentLaneDetailSheet-DRc-TpMB.js} +1 -1
- package/dist/client/assets/{AgentLaneSummaryResize-Box8-_rS.js → AgentLaneSummaryResize-VMNDo7kD.js} +1 -1
- package/dist/client/assets/AgentLanesEmbedScreen-C5k_dDS8.js +1 -0
- package/dist/client/assets/AgentLanesPreflight-CFadSaia.js +1 -0
- package/dist/client/assets/AgentLanesView-u5vpLwQf.js +2 -0
- package/dist/client/assets/{AgentLiveActions-BwuzOE8h.js → AgentLiveActions-CsQA3pu_.js} +1 -1
- package/dist/client/assets/AgentMasterScreen-C5WlWNmk.js +1 -0
- package/dist/client/assets/{AgentSessions-CsZwoukw.js → AgentSessions-BePq5Lgc.js} +1 -1
- package/dist/client/assets/{AgentsConsole-KCao4XmX.js → AgentsConsole-BuiZ_bDo.js} +1 -1
- package/dist/client/assets/{AgentsScreen-CtPAmwRX.js → AgentsScreen-CRi-hG2k.js} +1 -1
- package/dist/client/assets/AgentsSubnav-DUsya4WK.js +1 -0
- package/dist/client/assets/{AstronautSuit-Ckx7lu7G.js → AstronautSuit-Cjjcv6yQ.js} +1 -1
- package/dist/client/assets/{AtopView-DYlpgEHf.js → AtopView-PxWQd-sX.js} +1 -1
- package/dist/client/assets/{BackToPicker-4JaeRvDm.js → BackToPicker-Cto0Ioz9.js} +1 -1
- package/dist/client/assets/{BriefingDetailScreen-D6-xqrpo.js → BriefingDetailScreen-C29smC5d.js} +1 -1
- package/dist/client/assets/{BriefingsScreen-DKxSDEmk.js → BriefingsScreen-DNyFBrPn.js} +1 -1
- package/dist/client/assets/{BrokerMetadataPanel-BbREmsbK.js → BrokerMetadataPanel-DbaCQlhw.js} +1 -1
- package/dist/client/assets/{BrokerScreen-fbPIouMw.js → BrokerScreen-CS0s4Gm4.js} +1 -1
- package/dist/client/assets/{CastPicker-BcA2vDDV.js → CastPicker-CTBHjjGw.js} +1 -1
- package/dist/client/assets/ChatCollapsedStrip-D4rc7wBQ.js +1 -0
- package/dist/client/assets/{CodeDiffPane-Cn8Y9hAt.js → CodeDiffPane-QvxCUzTi.js} +1 -1
- package/dist/client/assets/{CodeProjectPicker-nPFktrco.js → CodeProjectPicker-DplkpM7f.js} +1 -1
- package/dist/client/assets/{CodeScreen-BlAxtxE5.js → CodeScreen-CrR2JaVj.js} +1 -1
- package/dist/client/assets/{ConversationComposer-2HjbGPL9.js → ConversationComposer-H8_hsYSc.js} +1 -1
- package/dist/client/assets/{ConversationFeedRows-C6wUqJrx.js → ConversationFeedRows-hlEFlURs.js} +1 -1
- package/dist/client/assets/{ConversationHeader-C8vfXaTF.js → ConversationHeader-B0ZBhE_E.js} +1 -1
- package/dist/client/assets/{ConversationPanels-CNCIbpqU.js → ConversationPanels-fMo6Uy1v.js} +2 -2
- package/dist/client/assets/ConversationScreen-CXAHQwQ3.js +2 -0
- package/dist/client/assets/{ConversationStatus-DZuyKsWN.js → ConversationStatus-DI5GCiyW.js} +1 -1
- package/dist/client/assets/{CrewAvatar-CTIuxp4G.js → CrewAvatar-CXJHLNVM.js} +1 -1
- package/dist/client/assets/CrewWorkspaces-Bz2Dcnt4.js +1 -0
- package/dist/client/assets/CrewWorkspaces-Diq11KDq.css +1 -0
- package/dist/client/assets/{DataTable-6IDhanr5.js → DataTable-DXIlOlVu.js} +1 -1
- package/dist/client/assets/{DispatchAftermath-DC1u9itO.js → DispatchAftermath-CrELgl2e.js} +1 -1
- package/dist/client/assets/{DocumentFocusViewer-DZVhS7as.js → DocumentFocusViewer-DFFE85Tq.js} +1 -1
- package/dist/client/assets/{EmbeddableSurfacesLab-BKUFJMCV.js → EmbeddableSurfacesLab-DgpewB3y.js} +1 -1
- package/dist/client/assets/{EmptyState-CeBl0iGd.js → EmptyState-D9X16fKq.js} +1 -1
- package/dist/client/assets/{FileViewerPane-DQlpNt2S.js → FileViewerPane-CY0RN78e.js} +1 -1
- package/dist/client/assets/FlightObserveScreen-qyzHzxLa.js +1 -0
- package/dist/client/assets/{FollowScreen-BXHOp3gb.js → FollowScreen-wZ-z67mX.js} +1 -1
- package/dist/client/assets/{HarnessMark-D5CA5uSp.js → HarnessMark-DAaWPiT_.js} +1 -1
- package/dist/client/assets/{HarnessesScreen-DhFXq1qz.js → HarnessesScreen-DbKkQM4o.js} +1 -1
- package/dist/client/assets/{HerdrSession-BRhs5LIR.js → HerdrSession-CYKRfBad.js} +1 -1
- package/dist/client/assets/{HomeHero-DMABJuze.js → HomeHero-DYyd3cpz.js} +1 -1
- package/dist/client/assets/{HostAdvisorView-RAociATV.js → HostAdvisorView-NtM0bsg8.js} +1 -1
- package/dist/client/assets/{KnowledgeSearchInspector-CZPyVNSw.js → KnowledgeSearchInspector-CU6BCFcS.js} +1 -1
- package/dist/client/assets/{KnowledgeSearchScreen-mGTKIg00.js → KnowledgeSearchScreen-DvbRRPQB.js} +1 -1
- package/dist/client/assets/{LaneToolHoverCard-D_DMlBeT.js → LaneToolHoverCard-Bo2Zl-1a.js} +1 -1
- package/dist/client/assets/{LaneTraceDetailSheet-BEHg3LmH.js → LaneTraceDetailSheet-C3C8UjXv.js} +1 -1
- package/dist/client/assets/{LaneTraceEventFocus-DVimcizS.js → LaneTraceEventFocus-Cek_64zR.js} +1 -1
- package/dist/client/assets/{MeshCanvas-BOuZx4AM.js → MeshCanvas-TvsID4fe.js} +1 -1
- package/dist/client/assets/{MeshCanvasMinimap-wL-1N94e.js → MeshCanvasMinimap-CxqeVVco.js} +1 -1
- package/dist/client/assets/{MeshScreen-DMY9Bmh5.js → MeshScreen-BJ-j9YXv.js} +1 -1
- package/dist/client/assets/{MeshTopologyView-DiDcX5f4.js → MeshTopologyView-BjprutE8.js} +2 -2
- package/dist/client/assets/MessagesScreen-CyNIZ3-X.js +1 -0
- package/dist/client/assets/{MissionContextRail-DrNKXG5u.js → MissionContextRail-Be0uXljQ.js} +1 -1
- package/dist/client/assets/{MissionControlView-ByBlHVN8.js → MissionControlView-Bj7cAbZd.js} +1 -1
- package/dist/client/assets/{MissionFocusOverlay-D1i6R6Zt.js → MissionFocusOverlay-DvTw6ts5.js} +1 -1
- package/dist/client/assets/{MissionLeftAgentRow-DN9NcCML.js → MissionLeftAgentRow-B0QG7Gys.js} +1 -1
- package/dist/client/assets/{MissionLogPane-DSeIv3Xo.js → MissionLogPane-EsM_S3ro.js} +1 -1
- package/dist/client/assets/{NewAgentModal-V7yK6J6j.js → NewAgentModal-Cqiq1CE1.js} +1 -1
- package/dist/client/assets/NewChatComposer-C_1op4dH.js +19 -0
- package/dist/client/assets/{NewChatOrigin-DdpzE4kz.js → NewChatOrigin-D7hwp6dm.js} +1 -1
- package/dist/client/assets/{ObserveEmbedScreen-l_Q3ts2q.js → ObserveEmbedScreen-CGHI_hb5.js} +1 -1
- package/dist/client/assets/{ObserveTextFlow-BSEtYTxU.js → ObserveTextFlow-BcrGQet8.js} +2 -2
- package/dist/client/assets/{ObservedTopologyPanel-CdGUXxGR.js → ObservedTopologyPanel-BhVsvwkh.js} +1 -1
- package/dist/client/assets/{OpenScoutAppShell-DN8dOSK4.js → OpenScoutAppShell-BtfvMkAp.js} +25 -25
- package/dist/client/assets/{OpsAgentsView-ntGr4pz4.js → OpsAgentsView-DBYtmLnh.js} +1 -1
- package/dist/client/assets/OpsScreen-CuYVgkC_.js +1 -0
- package/dist/client/assets/OpsSubnav-BEU4kKXm.js +1 -0
- package/dist/client/assets/ProjectAgentProfile-BhXAZEkW.js +1 -0
- package/dist/client/assets/{ProjectAgentProfileBar-BQET-qrY.js → ProjectAgentProfileBar-uJw9Wdfk.js} +1 -1
- package/dist/client/assets/{ProjectAgentProfileHero-Ck8mThtx.js → ProjectAgentProfileHero-CIMS4Dy_.js} +1 -1
- package/dist/client/assets/ProjectsInbox-JgU0lrY8.js +2 -0
- package/dist/client/assets/ProjectsRail-p99BRBOa.js +1 -0
- package/dist/client/assets/ProjectsScreen-BB45DU53.js +1 -0
- package/dist/client/assets/ProjectsThreadAside-BHDTJWOz.js +1 -0
- package/dist/client/assets/{Provider-B2xuo3rf.js → Provider-Bu-C8Hxc.js} +1 -1
- package/dist/client/assets/{RailRow-B-GycCBx.js → RailRow-ClMmtaIE.js} +1 -1
- package/dist/client/assets/{RawSessionsTable-AQThi6sm.js → RawSessionsTable-BtKdQPiv.js} +1 -1
- package/dist/client/assets/RealtimeVoiceScreen-KPHJgO1l.js +1 -0
- package/dist/client/assets/{RepoDiffEmbedScreen-DXWoRF_c.js → RepoDiffEmbedScreen-CjZ5ew3y.js} +1 -1
- package/dist/client/assets/{RepoDiffPageScreen-D_274ExO.js → RepoDiffPageScreen-CdTFfmbk.js} +1 -1
- package/dist/client/assets/{RepoDiffViewer-DbedmHDX.js → RepoDiffViewer-BFperHQg.js} +1 -1
- package/dist/client/assets/{RepoDiffViewerLazy-C0--fPtk.js → RepoDiffViewerLazy-BkBmbi1Z.js} +2 -2
- package/dist/client/assets/{ReposScreen-D39_YG4H.js → ReposScreen-C8dT4bK0.js} +1 -1
- package/dist/client/assets/ScoutDeckSurface-BcJsm2Kq.js +1 -0
- package/dist/client/assets/{ScoutSurface-UsRy0t-I.js → ScoutSurface-DmzEtrx8.js} +1 -1
- package/dist/client/assets/{ScoutbotFxLab-Fmdfboxs.js → ScoutbotFxLab-DU15Plja.js} +1 -1
- package/dist/client/assets/{SecondaryNav-o2RL9H8H.js → SecondaryNav-BrXMtvKE.js} +1 -1
- package/dist/client/assets/SessionEmbedScreen-Bt4flmAx.js +1 -0
- package/dist/client/assets/{SessionObserve-Dsd0j05N.js → SessionObserve-BCehTlO8.js} +1 -1
- package/dist/client/assets/{SessionObserveEvidence-DopQYDkD.js → SessionObserveEvidence-Bb6U-dem.js} +1 -1
- package/dist/client/assets/SessionRefScreen-C8BiRVPx.js +1 -0
- package/dist/client/assets/SessionsScreen-BNvjUflN.js +1 -0
- package/dist/client/assets/{SettingsDrawer-_AwuopMS.js → SettingsDrawer-BieUmb8g.js} +1 -1
- package/dist/client/assets/{SettingsScreen-Cw4DDfJP.js → SettingsScreen-3JvX1WFL.js} +1 -1
- package/dist/client/assets/{ShikiPane-BfHc_3pM.js → ShikiPane-DPWsVNtn.js} +1 -1
- package/dist/client/assets/{SlidePanel-C-q7XwTa.js → SlidePanel-BMRIR6bH.js} +1 -1
- package/dist/client/assets/{SpriteAvatar-Bs68ZENy.js → SpriteAvatar-56DTXxSV.js} +1 -1
- package/dist/client/assets/{StatusPill-ZZQwxB1a.js → StatusPill-BcuYUgsD.js} +1 -1
- package/dist/client/assets/{TailView-Q4FVMsUH.js → TailView-BDy8c2VB.js} +1 -1
- package/dist/client/assets/{Terminal-D7zqHwHV.js → Terminal-BlUQY9_Z.js} +1 -1
- package/dist/client/assets/{TerminalEmbedScreen-CXIJ7qv6.js → TerminalEmbedScreen-DTjxktyr.js} +1 -1
- package/dist/client/assets/{TerminalHeaderMount-BnBLOPbb.js → TerminalHeaderMount-Cy-uxkey.js} +1 -1
- package/dist/client/assets/{TextDocumentSurface-CKQP-cBT.js → TextDocumentSurface-BeSwe3Yl.js} +1 -1
- package/dist/client/assets/{TmuxPeek-V9dGESfO.js → TmuxPeek-B4no_aGI.js} +1 -1
- package/dist/client/assets/{VoicePermissionsPanel-k7sbLXx2.js → VoicePermissionsPanel-Bd16scwz.js} +1 -1
- package/dist/client/assets/{WorkDetailScreen-60p9litn.js → WorkDetailScreen-DIFQufak.js} +1 -1
- package/dist/client/assets/{WorkFilesViewer-BjJS7GyM.js → WorkFilesViewer-CT5XEFGf.js} +1 -1
- package/dist/client/assets/{activity-Bj3Hnbj3.js → activity-CqZafWfx.js} +1 -1
- package/dist/client/assets/{addon-fit-BL-NTWRU.js → addon-fit-CM6F_JRD.js} +1 -1
- package/dist/client/assets/{addon-webgl-CIMgmNjg.js → addon-webgl-DRTiePFC.js} +1 -1
- package/dist/client/assets/{agent-autocomplete-DXlvdc4b.js → agent-autocomplete-DXUBnlkN.js} +1 -1
- package/dist/client/assets/{agent-essentials-BOMHR0_U.js → agent-essentials-vytdybaX.js} +1 -1
- package/dist/client/assets/{agent-lane-card-model-CTLxf3R4.js → agent-lane-card-model-CNZMPkhc.js} +1 -1
- package/dist/client/assets/{agent-lanes-model-AfrjRNK5.js → agent-lanes-model-DXqjs0OK.js} +2 -2
- package/dist/client/assets/agent-master-I1W-5d-x.css +1 -0
- package/dist/client/assets/agent-master-model-DAZL92oe.js +1 -0
- package/dist/client/assets/{agent-specialization-BIPIBW8u.js → agent-specialization-BtxLN4UR.js} +1 -1
- package/dist/client/assets/agents-project-DgbqDc65.css +1 -0
- package/dist/client/assets/{arc.es-IR5r6sj_.js → arc.es-Bh84oHJ7.js} +1 -1
- package/dist/client/assets/{arrow-down-BydciYFZ.js → arrow-down-DvTsLokL.js} +1 -1
- package/dist/client/assets/{arrow-left-CghA0kTw.js → arrow-left-DHfdXJVZ.js} +1 -1
- package/dist/client/assets/{arrow-right-iJFv3jNh.js → arrow-right-BBsrogWf.js} +1 -1
- package/dist/client/assets/{arrow-up-right-CCfZXPqD.js → arrow-up-right-CY0Vw_67.js} +1 -1
- package/dist/client/assets/{bot-B5sub1-i.js → bot-DzkOUFBb.js} +1 -1
- package/dist/client/assets/{check-C18YQC90.js → check-DbIkldnK.js} +1 -1
- package/dist/client/assets/{chevron-down-Mp9mu_yd.js → chevron-down-C475vltS.js} +1 -1
- package/dist/client/assets/{chevron-right-CzH-TaSF.js → chevron-right-CnZRSd-V.js} +1 -1
- package/dist/client/assets/{chunk-HRAB3GC3-swV8PA2k.js → chunk-HRAB3GC3-DLNT8aOo.js} +1 -1
- package/dist/client/assets/{chunk-JTPDIGGW-BKXqcLKw.js → chunk-JTPDIGGW-Ci5j4vzV.js} +3 -3
- package/dist/client/assets/{chunk-T65CQEWV-vYbNJ8E6.js → chunk-T65CQEWV-BtNvicWs.js} +1 -1
- package/dist/client/assets/{chunk-YOZR3KYS-U65yUmqt.js → chunk-YOZR3KYS-DN5EJulq.js} +1 -1
- package/dist/client/assets/{clock-B4PTFi5m.js → clock-DVvENUU5.js} +1 -1
- package/dist/client/assets/{code-xml-Jtxsp5d1.js → code-xml-CvKBY3KA.js} +1 -1
- package/dist/client/assets/{compass-0_54-vz3.js → compass-BcRI_YXo.js} +1 -1
- package/dist/client/assets/content--T3p6akp.js +1 -0
- package/dist/client/assets/content-4nFMLuzF.js +1 -0
- package/dist/client/assets/content-BJ4nHvcu.js +1 -0
- package/dist/client/assets/{content-DMbawvqU.js → content-BNyAjpUl.js} +1 -1
- package/dist/client/assets/content-BmGp9wNl.js +1 -0
- package/dist/client/assets/content-CBWhwaRo.js +1 -0
- package/dist/client/assets/content-CQlykFbe.js +1 -0
- package/dist/client/assets/content-CevL0DgF.js +1 -0
- package/dist/client/assets/content-Ch8pf2bj.js +1 -0
- package/dist/client/assets/content-Cpvdcm_l.js +1 -0
- package/dist/client/assets/content-DfS3vgAu.js +1 -0
- package/dist/client/assets/content-DpQdNePJ.js +1 -0
- package/dist/client/assets/content-Dqpibejl.js +1 -0
- package/dist/client/assets/content-TV0nd6-r.js +1 -0
- package/dist/client/assets/{content-CHghn-rT.js → content-odbb5H4U.js} +1 -1
- package/dist/client/assets/content-uXHLPHe0.js +1 -0
- package/dist/client/assets/{conversation-icons-BV10B2Me.js → conversation-icons-CBMKBGHd.js} +1 -1
- package/dist/client/assets/{conversation-model-CwF6Y9gx.js → conversation-model-QsJVfSeG.js} +1 -1
- package/dist/client/assets/conversation-motion-features-BFLHX2eg.js +1 -0
- package/dist/client/assets/{copy-Dtpx4FOE.js → copy-Cj-owMb-.js} +1 -1
- package/dist/client/assets/{cpu-BjVis9mc.js → cpu-DuD3RFX5.js} +1 -1
- package/dist/client/assets/{createLucideIcon-DXpqZP7I.js → createLucideIcon-DthwWQIg.js} +1 -1
- package/dist/client/assets/{ctx-panel-D_HJ3nhb.css → ctx-panel-F05jXK4Q.css} +1 -1
- package/dist/client/assets/discover-B3uQlh5L.js +2 -0
- package/dist/client/assets/embed-entry-DkRcHKTh.js +2 -0
- package/dist/client/assets/{external-link-Ckiyzjwo.js → external-link-C_nxk0MJ.js} +1 -1
- package/dist/client/assets/{eye-CpfyvdLq.js → eye-FnaaPfja.js} +1 -1
- package/dist/client/assets/{file-code-corner-7mo7EviR.js → file-code-corner-DDPq4Cur.js} +1 -1
- package/dist/client/assets/{file-text-KijGBnME.js → file-text--hfhwZH1.js} +1 -1
- package/dist/client/assets/{gauge-y-Xg8Mrv.js → gauge-BVEknshP.js} +1 -1
- package/dist/client/assets/{gestures-Bq9XnSqY.js → gestures-3gw5VgUS.js} +1 -1
- package/dist/client/assets/{git-branch-BQ_x8KZL.js → git-branch-DJyvr0k-.js} +1 -1
- package/dist/client/assets/{home-moving-signal-DtRpiNa0.js → home-moving-signal-BPqBoNSm.js} +1 -1
- package/dist/client/assets/{home-now-card-DFb4GOgM.js → home-now-card-UspVW2-2.js} +1 -1
- package/dist/client/assets/{home-now-card-nano-D--m9jpq.js → home-now-card-nano-G8kMB32m.js} +1 -1
- package/dist/client/assets/{hooks-9d1SoaQA.js → hooks-BMsQzo9j.js} +1 -1
- package/dist/client/assets/{index-CZ-05hKz.js → index-BI9AljSD.js} +5 -5
- package/dist/client/assets/index-C-v0Z6ZS.js +1 -0
- package/dist/client/assets/index-D9DzUORB.js +1 -0
- package/dist/client/assets/index-DfsTyYDx.js +1 -0
- package/dist/client/assets/{inspector-panel-C-EhEDYy.js → inspector-panel-CFSArQ8Y.js} +1 -1
- package/dist/client/assets/{keyboard-nav-DFhAJkW3.js → keyboard-nav-e6yGeorb.js} +1 -1
- package/dist/client/assets/{lane-roster-store-gUBsydNf.js → lane-roster-store-Q7pcblY5.js} +1 -1
- package/dist/client/assets/{layers-CGou-LwV.js → layers-Dz2dKOnU.js} +1 -1
- package/dist/client/assets/{layout-grid-BrZt31QH.js → layout-grid-Bvs5fdB4.js} +1 -1
- package/dist/client/assets/{left-CwHZCGO3.js → left-B4Ak-Ibt.js} +1 -1
- package/dist/client/assets/{left-DA0amyfu.js → left-BMb493FZ.js} +1 -1
- package/dist/client/assets/{left-CwLs0okF.js → left-BjFLvVOC.js} +1 -1
- package/dist/client/assets/{left-B_o51JV6.js → left-CsXQ8Q3G.js} +1 -1
- package/dist/client/assets/left-FNH7faCI.js +1 -0
- package/dist/client/assets/left-POkqE8gI.js +2 -0
- package/dist/client/assets/left-UulOTcWh.js +1 -0
- package/dist/client/assets/{left-advisor-DU3s01gk.js → left-advisor-CJkQS2d6.js} +1 -1
- package/dist/client/assets/left-agents-CFMxyEjT.js +1 -0
- package/dist/client/assets/{left-default-uvuvDmt0.js → left-default-rnX5HANc.js} +1 -1
- package/dist/client/assets/{left-lanes-DnNLgec8.js → left-lanes-BpLXT_qH.js} +1 -1
- package/dist/client/assets/{left-mission-DN3-NLPC.js → left-mission-B0bhseWw.js} +1 -1
- package/dist/client/assets/library-D1iXfda2.js +1 -0
- package/dist/client/assets/{loader-circle-BiohlpM3.js → loader-circle-B2W9DPG5.js} +1 -1
- package/dist/client/assets/{local-agents-wUIaBcEr.js → local-agents-DKr-gIDC.js} +1 -1
- package/dist/client/assets/{mentions-CcPFMbmZ.js → mentions-DuLQnEcn.js} +1 -1
- package/dist/client/assets/{mesh-buckets-ByyFXdKT.js → mesh-buckets-6y3ZIibI.js} +1 -1
- package/dist/client/assets/{mesh-ops-CvGyjK84.js → mesh-ops-CRR-KnCG.js} +1 -1
- package/dist/client/assets/{mesh-roster-n2nDpEmA.js → mesh-roster-Bc7T4b7z.js} +1 -1
- package/dist/client/assets/{mesh-view-store-BpxGm71b.js → mesh-view-store-CiET-yN8.js} +1 -1
- package/dist/client/assets/{message-circle-B2ddzBrX.js → message-circle-B2DoYKDO.js} +1 -1
- package/dist/client/assets/{message-markup-RkfmDfME.js → message-markup-Cc_O-WdA.js} +1 -1
- package/dist/client/assets/{message-square-D9YYWE0x.js → message-square-O-Hu9Mk2.js} +1 -1
- package/dist/client/assets/{message-visibility-DwxgcgYK.js → message-visibility-CGOmSSKs.js} +1 -1
- package/dist/client/assets/{mission-control-store-Bf4b54MV.js → mission-control-store-DDAgWKUl.js} +1 -1
- package/dist/client/assets/{observe-CJRIvOCn.js → observe-Da2mRAsc.js} +1 -1
- package/dist/client/assets/{page-status-BptpTdQ-.js → page-status-Crtgjbq3.js} +1 -1
- package/dist/client/assets/{paperclip-B1UNGl5d.js → paperclip-BudMKSyr.js} +1 -1
- package/dist/client/assets/{persistent-state-YI-WHSCF.js → persistent-state-xJz-qAFc.js} +1 -1
- package/dist/client/assets/{plus-CuU_X0-8.js → plus-BJ1If8vj.js} +1 -1
- package/dist/client/assets/{profile-rY8jO38P.js → profile-B3qDSbrH.js} +1 -1
- package/dist/client/assets/projects-inbox-CLek3QaG.js +1 -0
- package/dist/client/assets/projects-inbox-DRBl2N85.css +1 -0
- package/dist/client/assets/{proxy-DnLpZIi9.js → proxy-1BABCaDb.js} +1 -1
- package/dist/client/assets/{radio-Dm1ItnA4.js → radio-B5OpHrrK.js} +1 -1
- package/dist/client/assets/{refresh-cw-BRn9Oxxl.js → refresh-cw-DmNAhaH0.js} +1 -1
- package/dist/client/assets/resolve-panes-DXw-cHaj.js +1 -0
- package/dist/client/assets/resolve-sidebar-context-CDdbRDEa.js +1 -0
- package/dist/client/assets/{right-BJltPRnd.js → right-BgJ4mQLf.js} +1 -1
- package/dist/client/assets/{right-DtsRNX5b.js → right-Bk6h7o-Z.js} +1 -1
- package/dist/client/assets/{right-C1yumXNx.js → right-BrICCmEt.js} +1 -1
- package/dist/client/assets/{right-BbyYdzHn.js → right-C1QIbqFZ.js} +1 -1
- package/dist/client/assets/{right-Shpw_xDy.js → right-CfliKiHY.js} +1 -1
- package/dist/client/assets/{right-D3aTKf1F.js → right-CtOLXB9s.js} +1 -1
- package/dist/client/assets/{right-CJnB_Bg7.js → right-D8id_DWQ.js} +1 -1
- package/dist/client/assets/{right-CPP7GyOm.js → right-DJ34yMAi.js} +1 -1
- package/dist/client/assets/{right-DI1B79nR.js → right-DiFmtw6d.js} +1 -1
- package/dist/client/assets/{right-Beh3nCUB.js → right-Lx79pxpG.js} +1 -1
- package/dist/client/assets/{rocket-DOwXHKWA.js → rocket-D3-TUJ2m.js} +1 -1
- package/dist/client/assets/router-DTtux5sP.js +1 -0
- package/dist/client/assets/{scope-views-A4_vP97W.js → scope-views-CPM0sBw_.js} +1 -1
- package/dist/client/assets/{scout-voice-BhPzrc6P.js → scout-voice-BZKsdquE.js} +1 -1
- package/dist/client/assets/{scoutbot-markdown-jh7tzFB1.js → scoutbot-markdown-CQ7Y1McC.js} +1 -1
- package/dist/client/assets/{scroll-text-DO0GQzvN.js → scroll-text-kPhYbh-M.js} +1 -1
- package/dist/client/assets/{search-D1tJSAWe.js → search-DmFM_9jm.js} +1 -1
- package/dist/client/assets/{secondaryNavConfig-B9IF8wXl.js → secondaryNavConfig-C9bQ9_IA.js} +1 -1
- package/dist/client/assets/{selection-bridge-i2S9zpf8.js → selection-bridge-Dy2mtMyi.js} +1 -1
- package/dist/client/assets/{send-horizontal-CgLppsIC.js → send-horizontal-qyjNgEaV.js} +1 -1
- package/dist/client/assets/{server-Dymv5Emh.js → server-nWqndnxu.js} +1 -1
- package/dist/client/assets/{session-catalog-DNaOEzoQ.js → session-catalog-BkmktBHI.js} +1 -1
- package/dist/client/assets/session-ref-lookup-state-SATH_jAP.js +1 -0
- package/dist/client/assets/{session-table-PTQVoTyc.js → session-table-DKSF0mrS.js} +1 -1
- package/dist/client/assets/{settings-2fC_G9nX.js → settings-C6h9y5XX.js} +1 -1
- package/dist/client/assets/{sliders-horizontal-BPSMHhbm.js → sliders-horizontal-BhHKxsCO.js} +1 -1
- package/dist/client/assets/{sparkles-Dy8p5xN8.js → sparkles-Cf8gin88.js} +1 -1
- package/dist/client/assets/{sse-CiOSzE5n.js → sse-DDHEHUgz.js} +1 -1
- package/dist/client/assets/{tail-events-BMQmSx1n.js → tail-events-BdUrO0kb.js} +1 -1
- package/dist/client/assets/{terminal-yN9xN-h9.js → terminal-C3YRPfyz.js} +1 -1
- package/dist/client/assets/{terminal-relay-9lhzEp2V.js → terminal-relay-BFhdIstF.js} +1 -1
- package/dist/client/assets/{terminal-takeover-DANQfTcy.js → terminal-takeover-B6H4llRR.js} +1 -1
- package/dist/client/assets/{text-rLpBg4_z.css → text-BYAFNLNq.css} +1 -1
- package/dist/client/assets/{text-CnZ0e1-V.js → text-Faa3ZStB.js} +1 -1
- package/dist/client/assets/{use-conversation-list-D9BNLfnW.js → use-conversation-list-DO5J8T1H.js} +1 -1
- package/dist/client/assets/use-fleet-active-asks-BtgNnRgK.js +1 -0
- package/dist/client/assets/{use-mesh-ops-items-BIvIHlqe.js → use-mesh-ops-items-N1HHhChY.js} +1 -1
- package/dist/client/assets/{use-reduced-motion-CKkhq9c5.js → use-reduced-motion-8WuxLa5l.js} +1 -1
- package/dist/client/assets/{use-scout-dev-flags-B2KCzPxn.js → use-scout-dev-flags-B31qTy6m.js} +1 -1
- package/dist/client/assets/{useAgentHoverCard-CHBsxcbp.js → useAgentHoverCard-Bkv-Uz_V.js} +1 -1
- package/dist/client/assets/useContentSecondaryNav-Bpkc8ayb.js +1 -0
- package/dist/client/assets/{usePierreRuntime-DUuXH5yp.js → usePierreRuntime-BfZHKAkI.js} +1 -1
- package/dist/client/assets/{wrench-YcXMlsh2.js → wrench-DkxnZRlR.js} +1 -1
- package/dist/client/assets/{x-e3h2hDsp.js → x-DfRJbqrh.js} +1 -1
- package/dist/client/assets/{xterm-Byp1Hep_.js → xterm-CJw8Epxv.js} +1 -1
- package/dist/client/assets/{zap-nMcjPoWB.js → zap-CIo8msJB.js} +1 -1
- package/dist/client/index.html +1 -1
- package/dist/drizzle/0009_old_korg.sql +72 -0
- package/dist/drizzle/0010_sparkling_colonel_america.sql +2 -0
- package/dist/drizzle/0011_funny_onslaught.sql +4 -0
- package/dist/drizzle/0012_high_blazing_skull.sql +16 -0
- package/dist/drizzle/0013_perfect_juggernaut.sql +1 -0
- package/dist/drizzle/0014_legal_meggan.sql +6 -0
- package/dist/drizzle/0015_lame_marvel_boy.sql +12 -0
- package/dist/drizzle/0016_early_goliath.sql +6 -0
- package/dist/drizzle/meta/0009_snapshot.json +6262 -0
- package/dist/drizzle/meta/0010_snapshot.json +6286 -0
- package/dist/drizzle/meta/0011_snapshot.json +6337 -0
- package/dist/drizzle/meta/0012_snapshot.json +6458 -0
- package/dist/drizzle/meta/0013_snapshot.json +6465 -0
- package/dist/drizzle/meta/0014_snapshot.json +6503 -0
- package/dist/drizzle/meta/0015_snapshot.json +6596 -0
- package/dist/drizzle/meta/0016_snapshot.json +6611 -0
- package/dist/drizzle/meta/_journal.json +56 -0
- package/dist/main.mjs +1355 -365
- package/dist/node/main.mjs +314 -12
- package/dist/pairing-runtime-controller.mjs +616 -108
- package/dist/runtime/base-daemon.mjs +30 -3
- package/dist/runtime/broker-daemon.mjs +4822 -532
- package/dist/runtime/broker-process-manager.mjs +23 -2
- package/dist/runtime/mesh-discover.mjs +23 -2
- package/dist/scout-control-plane-web.mjs +1922 -478
- package/package.json +2 -2
- package/dist/client/assets/AgentLanesEmbedScreen-BmLnN4on.js +0 -1
- package/dist/client/assets/AgentLanesPreflight-5B6sXvRB.js +0 -1
- package/dist/client/assets/AgentLanesView-DHyzVBk6.js +0 -2
- package/dist/client/assets/AgentsSubnav-CDMjKeYC.js +0 -1
- package/dist/client/assets/ChatCollapsedStrip-Ycm0ecaX.js +0 -1
- package/dist/client/assets/ConversationScreen-BNULZAp2.js +0 -2
- package/dist/client/assets/CrewWorkspaces-CJhBKVoZ.css +0 -1
- package/dist/client/assets/CrewWorkspaces-CkPYIA46.js +0 -1
- package/dist/client/assets/FlightObserveScreen-CDWGSKZg.js +0 -1
- package/dist/client/assets/MessagesScreen-Eulveud3.js +0 -1
- package/dist/client/assets/NewChatComposer-hlWT-nbR.js +0 -19
- package/dist/client/assets/OpsScreen-Ppen_Lmj.js +0 -1
- package/dist/client/assets/OpsSubnav-GAKsoSor.js +0 -1
- package/dist/client/assets/ProjectAgentProfile-BLlp2e6t.js +0 -1
- package/dist/client/assets/ProjectsInbox-Dlt8OQ8O.js +0 -2
- package/dist/client/assets/ProjectsRail-DCfNMmnW.js +0 -1
- package/dist/client/assets/ProjectsScreen-BP-hmI1m.js +0 -1
- package/dist/client/assets/ProjectsThreadAside-CWpMjGIH.js +0 -1
- package/dist/client/assets/RealtimeVoiceScreen-D7zZHK_t.js +0 -1
- package/dist/client/assets/ScoutDeckSurface-CKT3qdqY.js +0 -1
- package/dist/client/assets/SessionEmbedScreen-RD5XOx7R.js +0 -1
- package/dist/client/assets/SessionRefScreen-B_cTv47v.js +0 -1
- package/dist/client/assets/SessionsScreen-Bq0Z77On.js +0 -1
- package/dist/client/assets/agents-project-COzHxZAF.css +0 -1
- package/dist/client/assets/archive-BjcGiAy8.js +0 -1
- package/dist/client/assets/content-6RvWTrtk.js +0 -1
- package/dist/client/assets/content-BCgwMUqz.js +0 -1
- package/dist/client/assets/content-Bf2VLhx0.js +0 -1
- package/dist/client/assets/content-BrU_38-m.js +0 -1
- package/dist/client/assets/content-BvvJN8rN.js +0 -1
- package/dist/client/assets/content-CAeEqYPw.js +0 -1
- package/dist/client/assets/content-CI_Z9DXk.js +0 -1
- package/dist/client/assets/content-CbyKONhW.js +0 -1
- package/dist/client/assets/content-Czogvp43.js +0 -1
- package/dist/client/assets/content-DFk0zNzX.js +0 -1
- package/dist/client/assets/content-DHe4DgkA.js +0 -1
- package/dist/client/assets/content-DTz7cKjo.js +0 -1
- package/dist/client/assets/content-E3kudY-W.js +0 -1
- package/dist/client/assets/content-LpO0aO_U.js +0 -1
- package/dist/client/assets/conversation-motion-features-BKkCRaWR.js +0 -1
- package/dist/client/assets/discover-CHbrEItO.js +0 -2
- package/dist/client/assets/embed-entry-vil28MyU.js +0 -2
- package/dist/client/assets/index-BVlMw8x_.js +0 -1
- package/dist/client/assets/index-Cn0GR-q1.js +0 -1
- package/dist/client/assets/index-DosI4AG9.js +0 -1
- package/dist/client/assets/left-BpgWnaah.js +0 -1
- package/dist/client/assets/left-Cx0kv6pe.js +0 -1
- package/dist/client/assets/left-agents-qL5PpUY-.js +0 -1
- package/dist/client/assets/left-z-6CkuBe.js +0 -2
- package/dist/client/assets/library-DIo5NiGP.js +0 -1
- package/dist/client/assets/projects-inbox-BBs1hG13.css +0 -1
- package/dist/client/assets/projects-inbox-D-zAb9Gp.js +0 -1
- package/dist/client/assets/resolve-panes-DO6LkwhQ.js +0 -1
- package/dist/client/assets/resolve-sidebar-context-CIF288wY.js +0 -1
- package/dist/client/assets/router-DJj2WbDg.js +0 -1
- package/dist/client/assets/use-fleet-active-asks-BeAdcl09.js +0 -1
- package/dist/client/assets/useContentSecondaryNav-D0mUhxTF.js +0 -1
|
@@ -5539,7 +5539,7 @@ var init_sqlite_core = __esm(() => {
|
|
|
5539
5539
|
});
|
|
5540
5540
|
|
|
5541
5541
|
// packages/runtime/src/drizzle-schema.ts
|
|
5542
|
-
var epochMsNow, nodesTable, trustedPeersTable, peerNoncesTable, actorsTable, agentsTable, agentEndpointsTable, runtimeSessionsTable, runtimeSessionAliasesTable, routeAliasBindingsTable, routeAliasRevisionsTable, conversationsTable, conversationMembersTable, messagesTable, messageMentionsTable, messageAttachmentsTable, conversationReadCursorsTable, invocationsTable, flightsTable, bindingsTable, deliveriesTable, deliveryAttemptsTable, durableActionsTable, durableAttemptsTable, durableCheckpointsTable, durableSignalsTable, collaborationRecordsTable, collaborationEventsTable, contextBlocksTable, contextPacksTable, eventsTable, threadEventsTable, threadCursorsTable, scoutDispatchesTable, activityItemsTable, budgetUsageEventsTable, budgetQuotaWindowSnapshotsTable, mobilePushRegistrationsTable, briefingsTable, roleAssignmentsTable, missionLogEntriesTable, controlPlaneDrizzleSchema;
|
|
5542
|
+
var epochMsNow, nodesTable, trustedPeersTable, peerNoncesTable, actorsTable, agentsTable, agentEndpointsTable, runtimeSessionsTable, runtimeSessionAliasesTable, routeAliasBindingsTable, routeAliasRevisionsTable, conversationsTable, conversationMembersTable, messagesTable, messageMentionsTable, messageAttachmentsTable, conversationReadCursorsTable, brokerJournalProjectionCheckpointsTable, conversationProjectionMetaTable, conversationProjectionItemsTable, conversationProjectionMessageFactsTable, conversationProjectionMessageStatsTable, conversationProjectionSourcesTable, conversationProjectionEventsTable, invocationsTable, flightsTable, bindingsTable, deliveriesTable, deliveryAttemptsTable, durableActionsTable, durableAttemptsTable, durableCheckpointsTable, durableSignalsTable, collaborationRecordsTable, collaborationEventsTable, contextBlocksTable, contextPacksTable, eventsTable, threadEventsTable, threadCursorsTable, scoutDispatchesTable, activityItemsTable, budgetUsageEventsTable, budgetQuotaWindowSnapshotsTable, mobilePushRegistrationsTable, briefingsTable, roleAssignmentsTable, missionLogEntriesTable, controlPlaneDrizzleSchema;
|
|
5543
5543
|
var init_drizzle_schema = __esm(() => {
|
|
5544
5544
|
init_drizzle_orm();
|
|
5545
5545
|
init_sqlite_core();
|
|
@@ -5611,7 +5611,10 @@ var init_drizzle_schema = __esm(() => {
|
|
|
5611
5611
|
advertiseScope: text("advertise_scope").notNull(),
|
|
5612
5612
|
ownerId: text("owner_id"),
|
|
5613
5613
|
metadataJson: text("metadata_json")
|
|
5614
|
-
})
|
|
5614
|
+
}, (table3) => [
|
|
5615
|
+
index("idx_agents_home_node_id").on(table3.homeNodeId),
|
|
5616
|
+
index("idx_agents_authority_node_id").on(table3.authorityNodeId)
|
|
5617
|
+
]);
|
|
5615
5618
|
agentEndpointsTable = sqliteTable("agent_endpoints", {
|
|
5616
5619
|
id: text("id").primaryKey(),
|
|
5617
5620
|
agentId: text("agent_id").notNull().references(() => agentsTable.id, { onDelete: "cascade" }),
|
|
@@ -5627,7 +5630,14 @@ var init_drizzle_schema = __esm(() => {
|
|
|
5627
5630
|
metadataJson: text("metadata_json"),
|
|
5628
5631
|
updatedAt: integer("updated_at").notNull().default(epochMsNow)
|
|
5629
5632
|
}, (table3) => [
|
|
5630
|
-
index("idx_agent_endpoints_agent_updated_at").on(table3.agentId, desc(table3.updatedAt))
|
|
5633
|
+
index("idx_agent_endpoints_agent_updated_at").on(table3.agentId, desc(table3.updatedAt)),
|
|
5634
|
+
index("idx_agent_endpoints_roster_recency").on(desc(sql`CASE
|
|
5635
|
+
WHEN ${table3.updatedAt} IS NULL THEN NULL
|
|
5636
|
+
WHEN CAST(${table3.updatedAt} AS REAL) < 1000000000000
|
|
5637
|
+
THEN CAST(CAST(${table3.updatedAt} AS REAL) * 1000 AS INTEGER)
|
|
5638
|
+
ELSE CAST(${table3.updatedAt} AS INTEGER)
|
|
5639
|
+
END`), table3.agentId),
|
|
5640
|
+
index("idx_agent_endpoints_node_id").on(table3.nodeId)
|
|
5631
5641
|
]);
|
|
5632
5642
|
runtimeSessionsTable = sqliteTable("runtime_sessions", {
|
|
5633
5643
|
id: text("id").primaryKey(),
|
|
@@ -5651,6 +5661,7 @@ var init_drizzle_schema = __esm(() => {
|
|
|
5651
5661
|
}, (table3) => [
|
|
5652
5662
|
index("idx_runtime_sessions_agent_last_seen").on(table3.agentId, desc(table3.lastSeenAt)),
|
|
5653
5663
|
index("idx_runtime_sessions_endpoint_last_seen").on(table3.endpointId, desc(table3.lastSeenAt)),
|
|
5664
|
+
index("idx_runtime_sessions_node_id").on(table3.nodeId),
|
|
5654
5665
|
index("idx_runtime_sessions_external").on(table3.externalSessionId),
|
|
5655
5666
|
index("idx_runtime_sessions_expires").on(table3.expiresAt).where(sql`expires_at IS NOT NULL`)
|
|
5656
5667
|
]);
|
|
@@ -5670,6 +5681,8 @@ var init_drizzle_schema = __esm(() => {
|
|
|
5670
5681
|
primaryKey({ columns: [table3.alias, table3.sessionId] }),
|
|
5671
5682
|
index("idx_runtime_session_aliases_alias").on(table3.alias, desc(table3.lastSeenAt)),
|
|
5672
5683
|
index("idx_runtime_session_aliases_session").on(table3.sessionId),
|
|
5684
|
+
index("idx_runtime_session_aliases_endpoint").on(table3.endpointId),
|
|
5685
|
+
index("idx_runtime_session_aliases_node_id").on(table3.nodeId),
|
|
5673
5686
|
index("idx_runtime_session_aliases_expires").on(table3.expiresAt).where(sql`expires_at IS NOT NULL`)
|
|
5674
5687
|
]);
|
|
5675
5688
|
routeAliasBindingsTable = sqliteTable("route_alias_bindings", {
|
|
@@ -5749,7 +5762,8 @@ var init_drizzle_schema = __esm(() => {
|
|
|
5749
5762
|
actorId: text("actor_id").notNull().references(() => actorsTable.id, { onDelete: "cascade" }),
|
|
5750
5763
|
role: text("role")
|
|
5751
5764
|
}, (table3) => [
|
|
5752
|
-
primaryKey({ columns: [table3.conversationId, table3.actorId] })
|
|
5765
|
+
primaryKey({ columns: [table3.conversationId, table3.actorId] }),
|
|
5766
|
+
index("idx_conversation_members_actor").on(table3.actorId, table3.conversationId)
|
|
5753
5767
|
]);
|
|
5754
5768
|
messagesTable = sqliteTable("messages", {
|
|
5755
5769
|
id: text("id").primaryKey(),
|
|
@@ -5769,7 +5783,8 @@ var init_drizzle_schema = __esm(() => {
|
|
|
5769
5783
|
}, (table3) => [
|
|
5770
5784
|
index("idx_messages_conversation_created_at").on(table3.conversationId, table3.createdAt),
|
|
5771
5785
|
index("idx_messages_created_at").on(desc(table3.createdAt)),
|
|
5772
|
-
index("idx_messages_actor_created_at").on(table3.actorId, desc(table3.createdAt))
|
|
5786
|
+
index("idx_messages_actor_created_at").on(table3.actorId, desc(table3.createdAt)),
|
|
5787
|
+
index("idx_messages_origin_node_id").on(table3.originNodeId)
|
|
5773
5788
|
]);
|
|
5774
5789
|
messageMentionsTable = sqliteTable("message_mentions", {
|
|
5775
5790
|
messageId: text("message_id").notNull().references(() => messagesTable.id, { onDelete: "cascade" }),
|
|
@@ -5798,7 +5813,102 @@ var init_drizzle_schema = __esm(() => {
|
|
|
5798
5813
|
metadataJson: text("metadata_json")
|
|
5799
5814
|
}, (table3) => [
|
|
5800
5815
|
primaryKey({ columns: [table3.conversationId, table3.actorId] }),
|
|
5801
|
-
index("idx_read_cursors_conversation_updated_at").on(table3.conversationId, desc(table3.updatedAt))
|
|
5816
|
+
index("idx_read_cursors_conversation_updated_at").on(table3.conversationId, desc(table3.updatedAt)),
|
|
5817
|
+
index("idx_read_cursors_reader_node_id").on(table3.readerNodeId)
|
|
5818
|
+
]);
|
|
5819
|
+
brokerJournalProjectionCheckpointsTable = sqliteTable("broker_journal_projection_checkpoints", {
|
|
5820
|
+
projectionId: text("projection_id").primaryKey(),
|
|
5821
|
+
projectionVersion: integer("projection_version").notNull(),
|
|
5822
|
+
barrierId: text("barrier_id").notNull(),
|
|
5823
|
+
updatedAt: integer("updated_at").notNull()
|
|
5824
|
+
});
|
|
5825
|
+
conversationProjectionMetaTable = sqliteTable("conversation_projection_meta", {
|
|
5826
|
+
singleton: integer("singleton").primaryKey(),
|
|
5827
|
+
projectionId: text("projection_id").notNull(),
|
|
5828
|
+
projectionVersion: integer("projection_version").notNull(),
|
|
5829
|
+
headSeq: integer("head_seq").notNull(),
|
|
5830
|
+
minReplayableSeq: integer("min_replayable_seq").notNull(),
|
|
5831
|
+
updatedAt: integer("updated_at").notNull()
|
|
5832
|
+
}, (table3) => [
|
|
5833
|
+
check("conversation_projection_meta_singleton_check", sql`${table3.singleton} = 1`)
|
|
5834
|
+
]);
|
|
5835
|
+
conversationProjectionItemsTable = sqliteTable("conversation_projection_items", {
|
|
5836
|
+
feedId: text("feed_id").primaryKey(),
|
|
5837
|
+
entityKind: text("entity_kind").notNull(),
|
|
5838
|
+
kind: text("kind").notNull(),
|
|
5839
|
+
conversationId: text("conversation_id"),
|
|
5840
|
+
runtimeSessionId: text("runtime_session_id"),
|
|
5841
|
+
source: text("source"),
|
|
5842
|
+
sourceSessionId: text("source_session_id"),
|
|
5843
|
+
title: text("title"),
|
|
5844
|
+
alias: text("alias"),
|
|
5845
|
+
naturalKey: text("natural_key"),
|
|
5846
|
+
projectRoot: text("project_root"),
|
|
5847
|
+
harness: text("harness"),
|
|
5848
|
+
model: text("model"),
|
|
5849
|
+
effort: text("effort"),
|
|
5850
|
+
agentId: text("agent_id"),
|
|
5851
|
+
agentName: text("agent_name"),
|
|
5852
|
+
currentBranch: text("current_branch"),
|
|
5853
|
+
authorityNodeId: text("authority_node_id"),
|
|
5854
|
+
authorityNodeName: text("authority_node_name"),
|
|
5855
|
+
parentConversationId: text("parent_conversation_id"),
|
|
5856
|
+
anchorMessageId: text("anchor_message_id"),
|
|
5857
|
+
activityState: text("activity_state").notNull(),
|
|
5858
|
+
lastMessageId: text("last_message_id"),
|
|
5859
|
+
lastMessageAt: integer("last_message_at"),
|
|
5860
|
+
lastActivityAt: integer("last_activity_at").notNull(),
|
|
5861
|
+
messageCount: integer("message_count").notNull().default(0),
|
|
5862
|
+
unreadCount: integer("unread_count").notNull().default(0),
|
|
5863
|
+
participantCount: integer("participant_count").notNull().default(0),
|
|
5864
|
+
preview: text("preview"),
|
|
5865
|
+
lastEngagedAt: integer("last_engaged_at"),
|
|
5866
|
+
sourceFreshAt: integer("source_fresh_at"),
|
|
5867
|
+
visibilityState: text("visibility_state").notNull().default("visible"),
|
|
5868
|
+
updatedSeq: integer("updated_seq").notNull(),
|
|
5869
|
+
updatedAt: integer("updated_at").notNull()
|
|
5870
|
+
}, (table3) => [
|
|
5871
|
+
check("conversation_projection_items_entity_kind_check", sql`${table3.entityKind} IN ('scout_conversation', 'observed_session')`),
|
|
5872
|
+
check("conversation_projection_items_visibility_check", sql`${table3.visibilityState} IN ('visible', 'hidden')`),
|
|
5873
|
+
index("idx_conversation_projection_recent").on(table3.visibilityState, desc(table3.lastActivityAt), table3.feedId),
|
|
5874
|
+
index("idx_conversation_projection_project_recent").on(table3.projectRoot, table3.visibilityState, desc(table3.lastActivityAt)),
|
|
5875
|
+
index("idx_conversation_projection_engaged").on(table3.visibilityState, desc(table3.lastEngagedAt), desc(table3.lastActivityAt), table3.feedId),
|
|
5876
|
+
index("idx_conversation_projection_source_fresh").on(table3.visibilityState, desc(table3.sourceFreshAt)),
|
|
5877
|
+
index("idx_conversation_projection_runtime_session").on(table3.entityKind, table3.runtimeSessionId),
|
|
5878
|
+
index("idx_conversation_projection_source_session").on(table3.entityKind, table3.sourceSessionId),
|
|
5879
|
+
uniqueIndex("idx_conversation_projection_conversation").on(table3.conversationId).where(sql`conversation_id IS NOT NULL`)
|
|
5880
|
+
]);
|
|
5881
|
+
conversationProjectionMessageFactsTable = sqliteTable("conversation_projection_message_facts", {
|
|
5882
|
+
messageId: text("message_id").primaryKey().references(() => messagesTable.id, { onDelete: "cascade" }),
|
|
5883
|
+
conversationId: text("conversation_id").notNull().references(() => conversationsTable.id, { onDelete: "cascade" }),
|
|
5884
|
+
createdAt: integer("created_at").notNull()
|
|
5885
|
+
}, (table3) => [
|
|
5886
|
+
index("idx_conversation_projection_message_facts_conversation").on(table3.conversationId, table3.createdAt, table3.messageId)
|
|
5887
|
+
]);
|
|
5888
|
+
conversationProjectionMessageStatsTable = sqliteTable("conversation_projection_message_stats", {
|
|
5889
|
+
conversationId: text("conversation_id").primaryKey().references(() => conversationsTable.id, { onDelete: "cascade" }),
|
|
5890
|
+
messageCount: integer("message_count").notNull().default(0),
|
|
5891
|
+
latestMessageId: text("latest_message_id"),
|
|
5892
|
+
latestMessageAt: integer("latest_message_at")
|
|
5893
|
+
});
|
|
5894
|
+
conversationProjectionSourcesTable = sqliteTable("conversation_projection_sources", {
|
|
5895
|
+
source: text("source").notNull(),
|
|
5896
|
+
sourceSessionId: text("source_session_id").notNull(),
|
|
5897
|
+
feedId: text("feed_id").notNull().references(() => conversationProjectionItemsTable.feedId, { onDelete: "cascade" }),
|
|
5898
|
+
firstSeenAt: integer("first_seen_at").notNull(),
|
|
5899
|
+
lastSeenAt: integer("last_seen_at").notNull()
|
|
5900
|
+
}, (table3) => [
|
|
5901
|
+
primaryKey({ columns: [table3.source, table3.sourceSessionId] }),
|
|
5902
|
+
index("idx_conversation_projection_sources_feed").on(table3.feedId)
|
|
5903
|
+
]);
|
|
5904
|
+
conversationProjectionEventsTable = sqliteTable("conversation_projection_events", {
|
|
5905
|
+
seq: integer("seq").primaryKey({ autoIncrement: true }),
|
|
5906
|
+
projectionId: text("projection_id").notNull(),
|
|
5907
|
+
ts: integer("ts").notNull(),
|
|
5908
|
+
payloadJson: text("payload_json").notNull()
|
|
5909
|
+
}, (table3) => [
|
|
5910
|
+
index("idx_conversation_projection_events_projection_seq").on(table3.projectionId, table3.seq),
|
|
5911
|
+
index("idx_conversation_projection_events_ts").on(table3.ts)
|
|
5802
5912
|
]);
|
|
5803
5913
|
invocationsTable = sqliteTable("invocations", {
|
|
5804
5914
|
id: text("id").primaryKey(),
|
|
@@ -5830,7 +5940,10 @@ var init_drizzle_schema = __esm(() => {
|
|
|
5830
5940
|
executionResolutionJson: text("execution_resolution_json")
|
|
5831
5941
|
}, (table3) => [
|
|
5832
5942
|
index("idx_invocations_target_created_at").on(table3.targetAgentId, table3.createdAt),
|
|
5833
|
-
index("idx_invocations_requester_created_at").on(table3.requesterId, desc(table3.createdAt))
|
|
5943
|
+
index("idx_invocations_requester_created_at").on(table3.requesterId, desc(table3.createdAt)),
|
|
5944
|
+
index("idx_invocations_conversation_created_at").on(table3.conversationId, desc(table3.createdAt)),
|
|
5945
|
+
index("idx_invocations_requester_node_id").on(table3.requesterNodeId),
|
|
5946
|
+
index("idx_invocations_target_node_id").on(table3.targetNodeId)
|
|
5834
5947
|
]);
|
|
5835
5948
|
flightsTable = sqliteTable("flights", {
|
|
5836
5949
|
id: text("id").primaryKey(),
|
|
@@ -5876,7 +5989,8 @@ var init_drizzle_schema = __esm(() => {
|
|
|
5876
5989
|
createdAt: integer("created_at").notNull().default(epochMsNow)
|
|
5877
5990
|
}, (table3) => [
|
|
5878
5991
|
index("idx_deliveries_status_transport").on(table3.status, table3.transport),
|
|
5879
|
-
index("idx_deliveries_created_at").on(desc(table3.createdAt))
|
|
5992
|
+
index("idx_deliveries_created_at").on(desc(table3.createdAt)),
|
|
5993
|
+
index("idx_deliveries_target_node_id").on(table3.targetNodeId)
|
|
5880
5994
|
]);
|
|
5881
5995
|
deliveryAttemptsTable = sqliteTable("delivery_attempts", {
|
|
5882
5996
|
id: text("id").primaryKey(),
|
|
@@ -6046,7 +6160,8 @@ var init_drizzle_schema = __esm(() => {
|
|
|
6046
6160
|
}, (table3) => [
|
|
6047
6161
|
unique2().on(table3.conversationId, table3.seq),
|
|
6048
6162
|
index("idx_thread_events_conversation_seq").on(table3.conversationId, desc(table3.seq)),
|
|
6049
|
-
index("idx_thread_events_conversation_ts").on(table3.conversationId, desc(table3.ts))
|
|
6163
|
+
index("idx_thread_events_conversation_ts").on(table3.conversationId, desc(table3.ts)),
|
|
6164
|
+
index("idx_thread_events_authority_node_id").on(table3.authorityNodeId)
|
|
6050
6165
|
]);
|
|
6051
6166
|
threadCursorsTable = sqliteTable("thread_cursors", {
|
|
6052
6167
|
conversationId: text("conversation_id").notNull().references(() => conversationsTable.id, { onDelete: "cascade" }),
|
|
@@ -6054,7 +6169,8 @@ var init_drizzle_schema = __esm(() => {
|
|
|
6054
6169
|
lastAppliedSeq: integer("last_applied_seq").notNull(),
|
|
6055
6170
|
updatedAt: integer("updated_at").notNull()
|
|
6056
6171
|
}, (table3) => [
|
|
6057
|
-
primaryKey({ columns: [table3.conversationId, table3.authorityNodeId] })
|
|
6172
|
+
primaryKey({ columns: [table3.conversationId, table3.authorityNodeId] }),
|
|
6173
|
+
index("idx_thread_cursors_authority_node_id").on(table3.authorityNodeId)
|
|
6058
6174
|
]);
|
|
6059
6175
|
scoutDispatchesTable = sqliteTable("scout_dispatches", {
|
|
6060
6176
|
id: text("id").primaryKey(),
|
|
@@ -6256,6 +6372,13 @@ var init_drizzle_schema = __esm(() => {
|
|
|
6256
6372
|
messageMentions: messageMentionsTable,
|
|
6257
6373
|
messageAttachments: messageAttachmentsTable,
|
|
6258
6374
|
conversationReadCursors: conversationReadCursorsTable,
|
|
6375
|
+
brokerJournalProjectionCheckpoints: brokerJournalProjectionCheckpointsTable,
|
|
6376
|
+
conversationProjectionMeta: conversationProjectionMetaTable,
|
|
6377
|
+
conversationProjectionItems: conversationProjectionItemsTable,
|
|
6378
|
+
conversationProjectionMessageFacts: conversationProjectionMessageFactsTable,
|
|
6379
|
+
conversationProjectionMessageStats: conversationProjectionMessageStatsTable,
|
|
6380
|
+
conversationProjectionSources: conversationProjectionSourcesTable,
|
|
6381
|
+
conversationProjectionEvents: conversationProjectionEventsTable,
|
|
6259
6382
|
invocations: invocationsTable,
|
|
6260
6383
|
flights: flightsTable,
|
|
6261
6384
|
bindings: bindingsTable,
|
|
@@ -6328,6 +6451,8 @@ CREATE INDEX IF NOT EXISTS idx_runtime_sessions_agent_last_seen
|
|
|
6328
6451
|
ON runtime_sessions (agent_id, last_seen_at DESC);
|
|
6329
6452
|
CREATE INDEX IF NOT EXISTS idx_runtime_sessions_endpoint_last_seen
|
|
6330
6453
|
ON runtime_sessions (endpoint_id, last_seen_at DESC);
|
|
6454
|
+
CREATE INDEX IF NOT EXISTS idx_runtime_sessions_node_id
|
|
6455
|
+
ON runtime_sessions (node_id);
|
|
6331
6456
|
CREATE INDEX IF NOT EXISTS idx_runtime_sessions_external
|
|
6332
6457
|
ON runtime_sessions (external_session_id);
|
|
6333
6458
|
CREATE INDEX IF NOT EXISTS idx_runtime_sessions_expires
|
|
@@ -6337,6 +6462,10 @@ CREATE INDEX IF NOT EXISTS idx_runtime_session_aliases_alias
|
|
|
6337
6462
|
ON runtime_session_aliases (alias, last_seen_at DESC);
|
|
6338
6463
|
CREATE INDEX IF NOT EXISTS idx_runtime_session_aliases_session
|
|
6339
6464
|
ON runtime_session_aliases (session_id);
|
|
6465
|
+
CREATE INDEX IF NOT EXISTS idx_runtime_session_aliases_endpoint
|
|
6466
|
+
ON runtime_session_aliases (endpoint_id);
|
|
6467
|
+
CREATE INDEX IF NOT EXISTS idx_runtime_session_aliases_node_id
|
|
6468
|
+
ON runtime_session_aliases (node_id);
|
|
6340
6469
|
CREATE INDEX IF NOT EXISTS idx_runtime_session_aliases_expires
|
|
6341
6470
|
ON runtime_session_aliases (expires_at)
|
|
6342
6471
|
WHERE expires_at IS NOT NULL;
|
|
@@ -6582,6 +6711,93 @@ CREATE TABLE IF NOT EXISTS conversation_read_cursors (
|
|
|
6582
6711
|
PRIMARY KEY (conversation_id, actor_id)
|
|
6583
6712
|
);
|
|
6584
6713
|
|
|
6714
|
+
CREATE TABLE IF NOT EXISTS broker_journal_projection_checkpoints (
|
|
6715
|
+
projection_id TEXT PRIMARY KEY,
|
|
6716
|
+
projection_version INTEGER NOT NULL,
|
|
6717
|
+
barrier_id TEXT NOT NULL,
|
|
6718
|
+
updated_at INTEGER NOT NULL
|
|
6719
|
+
);
|
|
6720
|
+
|
|
6721
|
+
CREATE TABLE IF NOT EXISTS conversation_projection_meta (
|
|
6722
|
+
singleton INTEGER PRIMARY KEY,
|
|
6723
|
+
projection_id TEXT NOT NULL,
|
|
6724
|
+
projection_version INTEGER NOT NULL,
|
|
6725
|
+
head_seq INTEGER NOT NULL,
|
|
6726
|
+
min_replayable_seq INTEGER NOT NULL,
|
|
6727
|
+
updated_at INTEGER NOT NULL,
|
|
6728
|
+
CONSTRAINT conversation_projection_meta_singleton_check CHECK (singleton = 1)
|
|
6729
|
+
);
|
|
6730
|
+
|
|
6731
|
+
CREATE TABLE IF NOT EXISTS conversation_projection_items (
|
|
6732
|
+
feed_id TEXT PRIMARY KEY,
|
|
6733
|
+
entity_kind TEXT NOT NULL,
|
|
6734
|
+
kind TEXT NOT NULL,
|
|
6735
|
+
conversation_id TEXT,
|
|
6736
|
+
runtime_session_id TEXT,
|
|
6737
|
+
source TEXT,
|
|
6738
|
+
source_session_id TEXT,
|
|
6739
|
+
title TEXT,
|
|
6740
|
+
alias TEXT,
|
|
6741
|
+
natural_key TEXT,
|
|
6742
|
+
project_root TEXT,
|
|
6743
|
+
harness TEXT,
|
|
6744
|
+
model TEXT,
|
|
6745
|
+
effort TEXT,
|
|
6746
|
+
agent_id TEXT,
|
|
6747
|
+
agent_name TEXT,
|
|
6748
|
+
current_branch TEXT,
|
|
6749
|
+
authority_node_id TEXT,
|
|
6750
|
+
authority_node_name TEXT,
|
|
6751
|
+
parent_conversation_id TEXT,
|
|
6752
|
+
anchor_message_id TEXT,
|
|
6753
|
+
activity_state TEXT NOT NULL,
|
|
6754
|
+
last_message_id TEXT,
|
|
6755
|
+
last_message_at INTEGER,
|
|
6756
|
+
last_activity_at INTEGER NOT NULL,
|
|
6757
|
+
message_count INTEGER NOT NULL DEFAULT 0,
|
|
6758
|
+
unread_count INTEGER NOT NULL DEFAULT 0,
|
|
6759
|
+
participant_count INTEGER NOT NULL DEFAULT 0,
|
|
6760
|
+
preview TEXT,
|
|
6761
|
+
last_engaged_at INTEGER,
|
|
6762
|
+
source_fresh_at INTEGER,
|
|
6763
|
+
visibility_state TEXT NOT NULL DEFAULT 'visible',
|
|
6764
|
+
updated_seq INTEGER NOT NULL,
|
|
6765
|
+
updated_at INTEGER NOT NULL,
|
|
6766
|
+
CONSTRAINT conversation_projection_items_entity_kind_check
|
|
6767
|
+
CHECK (entity_kind IN ('scout_conversation', 'observed_session')),
|
|
6768
|
+
CONSTRAINT conversation_projection_items_visibility_check
|
|
6769
|
+
CHECK (visibility_state IN ('visible', 'hidden'))
|
|
6770
|
+
);
|
|
6771
|
+
|
|
6772
|
+
CREATE TABLE IF NOT EXISTS conversation_projection_message_facts (
|
|
6773
|
+
message_id TEXT PRIMARY KEY REFERENCES messages(id) ON DELETE CASCADE,
|
|
6774
|
+
conversation_id TEXT NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
|
|
6775
|
+
created_at INTEGER NOT NULL
|
|
6776
|
+
);
|
|
6777
|
+
|
|
6778
|
+
CREATE TABLE IF NOT EXISTS conversation_projection_message_stats (
|
|
6779
|
+
conversation_id TEXT PRIMARY KEY REFERENCES conversations(id) ON DELETE CASCADE,
|
|
6780
|
+
message_count INTEGER NOT NULL DEFAULT 0,
|
|
6781
|
+
latest_message_id TEXT,
|
|
6782
|
+
latest_message_at INTEGER
|
|
6783
|
+
);
|
|
6784
|
+
|
|
6785
|
+
CREATE TABLE IF NOT EXISTS conversation_projection_sources (
|
|
6786
|
+
source TEXT NOT NULL,
|
|
6787
|
+
source_session_id TEXT NOT NULL,
|
|
6788
|
+
feed_id TEXT NOT NULL REFERENCES conversation_projection_items(feed_id) ON DELETE CASCADE,
|
|
6789
|
+
first_seen_at INTEGER NOT NULL,
|
|
6790
|
+
last_seen_at INTEGER NOT NULL,
|
|
6791
|
+
PRIMARY KEY (source, source_session_id)
|
|
6792
|
+
);
|
|
6793
|
+
|
|
6794
|
+
CREATE TABLE IF NOT EXISTS conversation_projection_events (
|
|
6795
|
+
seq INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
6796
|
+
projection_id TEXT NOT NULL,
|
|
6797
|
+
ts INTEGER NOT NULL,
|
|
6798
|
+
payload_json TEXT NOT NULL
|
|
6799
|
+
);
|
|
6800
|
+
|
|
6585
6801
|
CREATE TABLE IF NOT EXISTS invocations (
|
|
6586
6802
|
id TEXT PRIMARY KEY,
|
|
6587
6803
|
requester_id TEXT NOT NULL REFERENCES actors(id) ON DELETE RESTRICT,
|
|
@@ -6989,18 +7205,74 @@ CREATE INDEX IF NOT EXISTS idx_peer_nonces_seen_at
|
|
|
6989
7205
|
ON peer_nonces (seen_at);
|
|
6990
7206
|
CREATE INDEX IF NOT EXISTS idx_agent_endpoints_agent_updated_at
|
|
6991
7207
|
ON agent_endpoints (agent_id, updated_at DESC);
|
|
7208
|
+
CREATE INDEX IF NOT EXISTS idx_agent_endpoints_roster_recency
|
|
7209
|
+
ON agent_endpoints (
|
|
7210
|
+
CASE
|
|
7211
|
+
WHEN updated_at IS NULL THEN NULL
|
|
7212
|
+
WHEN CAST(updated_at AS REAL) < 1000000000000
|
|
7213
|
+
THEN CAST(CAST(updated_at AS REAL) * 1000 AS INTEGER)
|
|
7214
|
+
ELSE CAST(updated_at AS INTEGER)
|
|
7215
|
+
END DESC,
|
|
7216
|
+
agent_id
|
|
7217
|
+
);
|
|
7218
|
+
CREATE INDEX IF NOT EXISTS idx_agents_home_node_id
|
|
7219
|
+
ON agents (home_node_id);
|
|
7220
|
+
CREATE INDEX IF NOT EXISTS idx_agents_authority_node_id
|
|
7221
|
+
ON agents (authority_node_id);
|
|
7222
|
+
CREATE INDEX IF NOT EXISTS idx_agent_endpoints_node_id
|
|
7223
|
+
ON agent_endpoints (node_id);
|
|
7224
|
+
CREATE INDEX IF NOT EXISTS idx_conversation_members_actor
|
|
7225
|
+
ON conversation_members (actor_id, conversation_id);
|
|
6992
7226
|
CREATE INDEX IF NOT EXISTS idx_messages_conversation_created_at
|
|
6993
7227
|
ON messages (conversation_id, created_at);
|
|
6994
7228
|
CREATE INDEX IF NOT EXISTS idx_messages_created_at
|
|
6995
7229
|
ON messages (created_at DESC);
|
|
6996
7230
|
CREATE INDEX IF NOT EXISTS idx_messages_actor_created_at
|
|
6997
7231
|
ON messages (actor_id, created_at DESC);
|
|
7232
|
+
CREATE INDEX IF NOT EXISTS idx_messages_origin_node_id
|
|
7233
|
+
ON messages (origin_node_id);
|
|
6998
7234
|
CREATE INDEX IF NOT EXISTS idx_read_cursors_conversation_updated_at
|
|
6999
7235
|
ON conversation_read_cursors (conversation_id, updated_at DESC);
|
|
7236
|
+
CREATE INDEX IF NOT EXISTS idx_read_cursors_reader_node_id
|
|
7237
|
+
ON conversation_read_cursors (reader_node_id);
|
|
7238
|
+
CREATE INDEX IF NOT EXISTS idx_conversation_projection_recent
|
|
7239
|
+
ON conversation_projection_items (visibility_state, last_activity_at DESC, feed_id);
|
|
7240
|
+
CREATE INDEX IF NOT EXISTS idx_conversation_projection_project_recent
|
|
7241
|
+
ON conversation_projection_items (project_root, visibility_state, last_activity_at DESC);
|
|
7242
|
+
CREATE INDEX IF NOT EXISTS idx_conversation_projection_message_facts_conversation
|
|
7243
|
+
ON conversation_projection_message_facts (conversation_id, created_at, message_id);
|
|
7244
|
+
CREATE INDEX IF NOT EXISTS idx_conversation_projection_engaged
|
|
7245
|
+
ON conversation_projection_items (
|
|
7246
|
+
visibility_state,
|
|
7247
|
+
last_engaged_at DESC,
|
|
7248
|
+
last_activity_at DESC,
|
|
7249
|
+
feed_id
|
|
7250
|
+
);
|
|
7251
|
+
CREATE INDEX IF NOT EXISTS idx_conversation_projection_source_fresh
|
|
7252
|
+
ON conversation_projection_items (visibility_state, source_fresh_at DESC);
|
|
7253
|
+
CREATE INDEX IF NOT EXISTS idx_conversation_projection_runtime_session
|
|
7254
|
+
ON conversation_projection_items (entity_kind, runtime_session_id);
|
|
7255
|
+
CREATE INDEX IF NOT EXISTS idx_conversation_projection_source_session
|
|
7256
|
+
ON conversation_projection_items (entity_kind, source_session_id);
|
|
7257
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_conversation_projection_conversation
|
|
7258
|
+
ON conversation_projection_items (conversation_id)
|
|
7259
|
+
WHERE conversation_id IS NOT NULL;
|
|
7260
|
+
CREATE INDEX IF NOT EXISTS idx_conversation_projection_sources_feed
|
|
7261
|
+
ON conversation_projection_sources (feed_id);
|
|
7262
|
+
CREATE INDEX IF NOT EXISTS idx_conversation_projection_events_projection_seq
|
|
7263
|
+
ON conversation_projection_events (projection_id, seq);
|
|
7264
|
+
CREATE INDEX IF NOT EXISTS idx_conversation_projection_events_ts
|
|
7265
|
+
ON conversation_projection_events (ts);
|
|
7000
7266
|
CREATE INDEX IF NOT EXISTS idx_invocations_target_created_at
|
|
7001
7267
|
ON invocations (target_agent_id, created_at);
|
|
7002
7268
|
CREATE INDEX IF NOT EXISTS idx_invocations_requester_created_at
|
|
7003
7269
|
ON invocations (requester_id, created_at DESC);
|
|
7270
|
+
CREATE INDEX IF NOT EXISTS idx_invocations_conversation_created_at
|
|
7271
|
+
ON invocations (conversation_id, created_at DESC);
|
|
7272
|
+
CREATE INDEX IF NOT EXISTS idx_invocations_requester_node_id
|
|
7273
|
+
ON invocations (requester_node_id);
|
|
7274
|
+
CREATE INDEX IF NOT EXISTS idx_invocations_target_node_id
|
|
7275
|
+
ON invocations (target_node_id);
|
|
7004
7276
|
CREATE INDEX IF NOT EXISTS idx_flights_target_state
|
|
7005
7277
|
ON flights (target_agent_id, state);
|
|
7006
7278
|
CREATE INDEX IF NOT EXISTS idx_flights_invocation_id
|
|
@@ -7009,6 +7281,8 @@ CREATE INDEX IF NOT EXISTS idx_deliveries_status_transport
|
|
|
7009
7281
|
ON deliveries (status, transport);
|
|
7010
7282
|
CREATE INDEX IF NOT EXISTS idx_deliveries_created_at
|
|
7011
7283
|
ON deliveries (created_at DESC);
|
|
7284
|
+
CREATE INDEX IF NOT EXISTS idx_deliveries_target_node_id
|
|
7285
|
+
ON deliveries (target_node_id);
|
|
7012
7286
|
CREATE INDEX IF NOT EXISTS idx_delivery_attempts_created_at
|
|
7013
7287
|
ON delivery_attempts (created_at DESC);
|
|
7014
7288
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_durable_actions_idempotency_key
|
|
@@ -7055,6 +7329,10 @@ CREATE INDEX IF NOT EXISTS idx_thread_events_conversation_seq
|
|
|
7055
7329
|
ON thread_events (conversation_id, seq DESC);
|
|
7056
7330
|
CREATE INDEX IF NOT EXISTS idx_thread_events_conversation_ts
|
|
7057
7331
|
ON thread_events (conversation_id, ts DESC);
|
|
7332
|
+
CREATE INDEX IF NOT EXISTS idx_thread_events_authority_node_id
|
|
7333
|
+
ON thread_events (authority_node_id);
|
|
7334
|
+
CREATE INDEX IF NOT EXISTS idx_thread_cursors_authority_node_id
|
|
7335
|
+
ON thread_cursors (authority_node_id);
|
|
7058
7336
|
CREATE INDEX IF NOT EXISTS idx_activity_items_agent_ts
|
|
7059
7337
|
ON activity_items (agent_id, ts DESC);
|
|
7060
7338
|
CREATE INDEX IF NOT EXISTS idx_activity_items_actor_ts
|
|
@@ -8630,12 +8908,15 @@ var init_host_integrations = () => {};
|
|
|
8630
8908
|
// packages/protocol/src/native-interactions.ts
|
|
8631
8909
|
var init_native_interactions = () => {};
|
|
8632
8910
|
|
|
8911
|
+
// packages/protocol/src/session-handle.ts
|
|
8912
|
+
var init_session_handle = () => {};
|
|
8913
|
+
|
|
8633
8914
|
// packages/protocol/src/runtime-catalog.generated.ts
|
|
8634
8915
|
var SCOUT_RUNTIME_CATALOG_DATA;
|
|
8635
8916
|
var init_runtime_catalog_generated = __esm(() => {
|
|
8636
8917
|
SCOUT_RUNTIME_CATALOG_DATA = {
|
|
8637
8918
|
schemaVersion: "openscout.runtime-catalog.v1",
|
|
8638
|
-
revision: "2026-
|
|
8919
|
+
revision: "2026-09-01.1",
|
|
8639
8920
|
harnesses: [
|
|
8640
8921
|
{
|
|
8641
8922
|
id: "claude",
|
|
@@ -8659,6 +8940,13 @@ var init_runtime_catalog_generated = __esm(() => {
|
|
|
8659
8940
|
family: "Opus",
|
|
8660
8941
|
version: "5"
|
|
8661
8942
|
},
|
|
8943
|
+
{
|
|
8944
|
+
id: "claude-fable-5",
|
|
8945
|
+
label: "Fable 5",
|
|
8946
|
+
enabled: true,
|
|
8947
|
+
family: "Fable",
|
|
8948
|
+
version: "5"
|
|
8949
|
+
},
|
|
8662
8950
|
{
|
|
8663
8951
|
id: "claude-sonnet-4-6",
|
|
8664
8952
|
label: "Sonnet 4.6",
|
|
@@ -9277,6 +9565,12 @@ var init_runtime_catalog = __esm(() => {
|
|
|
9277
9565
|
reasoningEfforts = new Set(SCOUT_REASONING_EFFORTS);
|
|
9278
9566
|
});
|
|
9279
9567
|
|
|
9568
|
+
// packages/protocol/src/scout-baseline-runtime.ts
|
|
9569
|
+
var init_scout_baseline_runtime = () => {};
|
|
9570
|
+
|
|
9571
|
+
// packages/protocol/src/session-title.ts
|
|
9572
|
+
var init_session_title = () => {};
|
|
9573
|
+
|
|
9280
9574
|
// packages/protocol/src/reserved-vocabulary.ts
|
|
9281
9575
|
function scoutReservedVocabularyKind(value) {
|
|
9282
9576
|
const normalized = normalizeAgentSelectorSegment(value ?? "");
|
|
@@ -9769,6 +10063,7 @@ var init_broker_routes = __esm(() => {
|
|
|
9769
10063
|
home: "/v1/home",
|
|
9770
10064
|
node: "/v1/node",
|
|
9771
10065
|
snapshot: "/v1/snapshot",
|
|
10066
|
+
conversationProjection: "/v1/conversation-projection",
|
|
9772
10067
|
capabilities: "/v1/capabilities",
|
|
9773
10068
|
runtimeCatalog: "/v1/runtime-catalog",
|
|
9774
10069
|
topologySnapshot: "/v1/topology/snapshot",
|
|
@@ -9837,9 +10132,12 @@ var init_src = __esm(() => {
|
|
|
9837
10132
|
init_budget();
|
|
9838
10133
|
init_host_integrations();
|
|
9839
10134
|
init_native_interactions();
|
|
10135
|
+
init_session_handle();
|
|
9840
10136
|
init_runtime_profiles();
|
|
9841
10137
|
init_runtime_execution();
|
|
9842
10138
|
init_runtime_catalog();
|
|
10139
|
+
init_scout_baseline_runtime();
|
|
10140
|
+
init_session_title();
|
|
9843
10141
|
init_reserved_vocabulary();
|
|
9844
10142
|
init_scout_composer();
|
|
9845
10143
|
init_inbox();
|
|
@@ -15281,6 +15579,9 @@ var init_budget_observations = __esm(() => {
|
|
|
15281
15579
|
QUOTA_HISTORY_BUCKET_MS = 60 * 60 * 1000;
|
|
15282
15580
|
});
|
|
15283
15581
|
|
|
15582
|
+
// packages/runtime/src/runtime-session-handle.ts
|
|
15583
|
+
var init_runtime_session_handle = () => {};
|
|
15584
|
+
|
|
15284
15585
|
// packages/runtime/src/sqlite-store.ts
|
|
15285
15586
|
var RUNTIME_SESSION_RETENTION_MS;
|
|
15286
15587
|
var init_sqlite_store = __esm(() => {
|
|
@@ -15292,6 +15593,7 @@ var init_sqlite_store = __esm(() => {
|
|
|
15292
15593
|
init_api();
|
|
15293
15594
|
init_drizzle_schema();
|
|
15294
15595
|
init_budget_observations();
|
|
15596
|
+
init_runtime_session_handle();
|
|
15295
15597
|
RUNTIME_SESSION_RETENTION_MS = 30 * 24 * 60 * 60 * 1000;
|
|
15296
15598
|
});
|
|
15297
15599
|
|
|
@@ -32595,10 +32897,12 @@ var init_iroh_bridge = __esm(() => {
|
|
|
32595
32897
|
var init_mesh_dial_order = () => {};
|
|
32596
32898
|
|
|
32597
32899
|
// packages/runtime/src/mesh-forwarding.ts
|
|
32900
|
+
var MAX_PEER_AGENT_SNAPSHOT_BYTES;
|
|
32598
32901
|
var init_mesh_forwarding = __esm(() => {
|
|
32599
32902
|
init_iroh_bridge();
|
|
32600
32903
|
init_mesh_peer_client();
|
|
32601
32904
|
init_mesh_dial_order();
|
|
32905
|
+
MAX_PEER_AGENT_SNAPSHOT_BYTES = 2 * 1024 * 1024;
|
|
32602
32906
|
});
|
|
32603
32907
|
|
|
32604
32908
|
// packages/runtime/src/broker-api.ts
|
|
@@ -33406,11 +33710,32 @@ function resolveBundledRuntimeDirFromModuleDir(moduleDir) {
|
|
|
33406
33710
|
resolve2(moduleDir, "..", "..")
|
|
33407
33711
|
];
|
|
33408
33712
|
for (const candidate of candidates) {
|
|
33409
|
-
if (isInstalledRuntimePackageDir(candidate))
|
|
33410
|
-
|
|
33713
|
+
if (!isInstalledRuntimePackageDir(candidate))
|
|
33714
|
+
continue;
|
|
33715
|
+
const sourceWorkspaceRuntime = resolveSourceWorkspaceRuntimeDir(candidate);
|
|
33716
|
+
if (sourceWorkspaceRuntime)
|
|
33717
|
+
return sourceWorkspaceRuntime;
|
|
33718
|
+
return candidate;
|
|
33411
33719
|
}
|
|
33412
33720
|
return null;
|
|
33413
33721
|
}
|
|
33722
|
+
function resolveSourceWorkspaceRuntimeDir(bundledPackageDir) {
|
|
33723
|
+
const packagesDir = dirname6(bundledPackageDir);
|
|
33724
|
+
if (resolve2(packagesDir, "cli") !== resolve2(bundledPackageDir))
|
|
33725
|
+
return null;
|
|
33726
|
+
const runtimeDir = join8(packagesDir, "runtime");
|
|
33727
|
+
if (!existsSync8(join8(runtimeDir, "src")))
|
|
33728
|
+
return null;
|
|
33729
|
+
if (!isInstalledRuntimePackageDir(runtimeDir))
|
|
33730
|
+
return null;
|
|
33731
|
+
try {
|
|
33732
|
+
const cliPackage = JSON.parse(readFileSync5(join8(bundledPackageDir, "package.json"), "utf8"));
|
|
33733
|
+
const runtimePackage = JSON.parse(readFileSync5(join8(runtimeDir, "package.json"), "utf8"));
|
|
33734
|
+
return cliPackage.name === "@openscout/scout" && runtimePackage.name === "@openscout/runtime" ? runtimeDir : null;
|
|
33735
|
+
} catch {
|
|
33736
|
+
return null;
|
|
33737
|
+
}
|
|
33738
|
+
}
|
|
33414
33739
|
function findWorkspaceRuntimeDir(startDir) {
|
|
33415
33740
|
let current = resolve2(startDir);
|
|
33416
33741
|
while (true) {
|
|
@@ -54137,6 +54462,7 @@ var TERMINAL_ENDPOINT_STATES;
|
|
|
54137
54462
|
var init_broker_endpoint_selection = __esm(() => {
|
|
54138
54463
|
init_a2a_http_endpoint();
|
|
54139
54464
|
init_local_agent_transports();
|
|
54465
|
+
init_runtime_session_handle();
|
|
54140
54466
|
TERMINAL_ENDPOINT_STATES = new Set([
|
|
54141
54467
|
"failed",
|
|
54142
54468
|
"superseded",
|
|
@@ -57632,6 +57958,14 @@ function resolveScoutWebBindHost(env) {
|
|
|
57632
57958
|
}
|
|
57633
57959
|
return host;
|
|
57634
57960
|
}
|
|
57961
|
+
function resolveScoutWebLanAccessScope(env) {
|
|
57962
|
+
const scope = env.OPENSCOUT_WEB_LAN_SCOPE?.trim().toLowerCase();
|
|
57963
|
+
if (!scope || scope === "full")
|
|
57964
|
+
return "full";
|
|
57965
|
+
if (scope === "pairing")
|
|
57966
|
+
return "pairing";
|
|
57967
|
+
throw new Error(`Unsupported OPENSCOUT_WEB_LAN_SCOPE: ${scope}`);
|
|
57968
|
+
}
|
|
57635
57969
|
function constantTimeTokenMatch(candidate, expected) {
|
|
57636
57970
|
if (!candidate)
|
|
57637
57971
|
return false;
|
|
@@ -57673,20 +58007,29 @@ function scoutWebAuthCookie(token, secure) {
|
|
|
57673
58007
|
function localInterfaceAddresses() {
|
|
57674
58008
|
return Object.values(networkInterfaces2()).flatMap((entries) => entries ?? []).map((entry) => entry.address);
|
|
57675
58009
|
}
|
|
57676
|
-
function
|
|
58010
|
+
function isSameMacScoutRequest(request, peerAddress, ownAddresses = localInterfaceAddresses()) {
|
|
57677
58011
|
if (!peerAddress || !isLoopbackScoutAddress(peerAddress))
|
|
57678
58012
|
return false;
|
|
57679
58013
|
if (request.headers.has("forwarded"))
|
|
57680
58014
|
return false;
|
|
57681
|
-
const
|
|
57682
|
-
|
|
57683
|
-
|
|
57684
|
-
|
|
57685
|
-
|
|
57686
|
-
|
|
57687
|
-
|
|
57688
|
-
|
|
57689
|
-
|
|
58015
|
+
const forwardedAddresses = [
|
|
58016
|
+
request.headers.get("x-forwarded-for"),
|
|
58017
|
+
request.headers.get("x-real-ip")
|
|
58018
|
+
].filter((value) => value !== null);
|
|
58019
|
+
for (const value of forwardedAddresses) {
|
|
58020
|
+
if (value.includes(","))
|
|
58021
|
+
return false;
|
|
58022
|
+
const clientAddress = normalizeIpAddress(value);
|
|
58023
|
+
if (!clientAddress)
|
|
58024
|
+
return false;
|
|
58025
|
+
if (!isLoopbackScoutAddress(clientAddress) && !ownAddresses.some((address) => normalizeIpAddress(address) === clientAddress)) {
|
|
58026
|
+
return false;
|
|
58027
|
+
}
|
|
58028
|
+
}
|
|
58029
|
+
return true;
|
|
58030
|
+
}
|
|
58031
|
+
function shouldIssueLocalScoutWebCredential(request, peerAddress, ownAddresses = localInterfaceAddresses()) {
|
|
58032
|
+
return isSameMacScoutRequest(request, peerAddress, ownAddresses);
|
|
57690
58033
|
}
|
|
57691
58034
|
function normalizeIpAddress(address) {
|
|
57692
58035
|
const normalized = normalizeHostname(address);
|
|
@@ -57728,13 +58071,32 @@ function isLoopbackScoutAddress(address) {
|
|
|
57728
58071
|
const mapped = normalized.startsWith("::ffff:") ? normalized.slice(7) : normalized;
|
|
57729
58072
|
return LOOPBACK_IPV4_HOST_PATTERN.test(mapped);
|
|
57730
58073
|
}
|
|
57731
|
-
function
|
|
58074
|
+
function resolveScoutRequestPeerAddress(c) {
|
|
57732
58075
|
try {
|
|
57733
58076
|
return getConnInfo(c).remote.address;
|
|
57734
58077
|
} catch {
|
|
57735
58078
|
return;
|
|
57736
58079
|
}
|
|
57737
58080
|
}
|
|
58081
|
+
function createScoutRequestPeerAddressRegistry() {
|
|
58082
|
+
const peers = new WeakMap;
|
|
58083
|
+
return {
|
|
58084
|
+
remember(request, address) {
|
|
58085
|
+
if (address)
|
|
58086
|
+
peers.set(request, address);
|
|
58087
|
+
},
|
|
58088
|
+
resolve(c) {
|
|
58089
|
+
return peers.get(c.req.raw) ?? resolveScoutRequestPeerAddress(c);
|
|
58090
|
+
}
|
|
58091
|
+
};
|
|
58092
|
+
}
|
|
58093
|
+
function isScoutWebRequestAllowedFromPeer(request, peerAddress, scope) {
|
|
58094
|
+
if (scope === "full" || isSameMacScoutRequest(request, peerAddress)) {
|
|
58095
|
+
return true;
|
|
58096
|
+
}
|
|
58097
|
+
const url = new URL(request.url);
|
|
58098
|
+
return request.method === "GET" && url.pathname === "/pair" && request.headers.get("upgrade") === null;
|
|
58099
|
+
}
|
|
57738
58100
|
function isTrustedScoutApiRequest(request, options = {}, peerAddress) {
|
|
57739
58101
|
const requestUrl = new URL(request.url);
|
|
57740
58102
|
const hostname2 = normalizeHostname(requestUrl.hostname);
|
|
@@ -57880,7 +58242,7 @@ function scoutApiPerfReport() {
|
|
|
57880
58242
|
}
|
|
57881
58243
|
function installScoutApiMiddleware(app, label = "api", options = {}) {
|
|
57882
58244
|
app.use("/api/*", async (c, next) => {
|
|
57883
|
-
const peerAddress = (options.resolvePeerAddress ??
|
|
58245
|
+
const peerAddress = (options.resolvePeerAddress ?? resolveScoutRequestPeerAddress)(c);
|
|
57884
58246
|
if (!isTrustedScoutApiRequest(c.req.raw, options, peerAddress)) {
|
|
57885
58247
|
return c.json({ error: "forbidden" }, 403);
|
|
57886
58248
|
}
|
|
@@ -58451,6 +58813,19 @@ async function readScoutBrokerHome(baseUrl = resolveScoutBrokerUrl(), options =
|
|
|
58451
58813
|
return null;
|
|
58452
58814
|
}
|
|
58453
58815
|
}
|
|
58816
|
+
async function readScoutConversationProjection(limit = 160, baseUrl = resolveScoutBrokerUrl(), options = {}) {
|
|
58817
|
+
const query = new URLSearchParams({
|
|
58818
|
+
limit: String(Math.min(160, Math.max(1, Math.floor(limit))))
|
|
58819
|
+
});
|
|
58820
|
+
try {
|
|
58821
|
+
return await brokerReadJson(baseUrl, `${scoutBrokerPaths.v1.conversationProjection}?${query}`, {
|
|
58822
|
+
...options,
|
|
58823
|
+
signal: options.signal ?? AbortSignal.timeout(450)
|
|
58824
|
+
});
|
|
58825
|
+
} catch {
|
|
58826
|
+
return null;
|
|
58827
|
+
}
|
|
58828
|
+
}
|
|
58454
58829
|
async function readScoutBrokerRuntimeCatalog(baseUrl = resolveScoutBrokerUrl()) {
|
|
58455
58830
|
try {
|
|
58456
58831
|
return await brokerReadJson(baseUrl, scoutBrokerPaths.v1.runtimeCatalog);
|
|
@@ -58458,6 +58833,13 @@ async function readScoutBrokerRuntimeCatalog(baseUrl = resolveScoutBrokerUrl())
|
|
|
58458
58833
|
return null;
|
|
58459
58834
|
}
|
|
58460
58835
|
}
|
|
58836
|
+
async function readScoutBrokerTailDiscovery(baseUrl = resolveScoutBrokerUrl()) {
|
|
58837
|
+
try {
|
|
58838
|
+
return await brokerReadJson(baseUrl, scoutBrokerPaths.v1.tailDiscover);
|
|
58839
|
+
} catch {
|
|
58840
|
+
return null;
|
|
58841
|
+
}
|
|
58842
|
+
}
|
|
58461
58843
|
async function readScoutBrokerSnapshot(baseUrl = resolveScoutBrokerUrl(), options = {}) {
|
|
58462
58844
|
try {
|
|
58463
58845
|
return await brokerReadJson(baseUrl, scoutBrokerPaths.v1.snapshot, options);
|
|
@@ -58495,26 +58877,24 @@ async function recordScoutBrokerReadCursor(input, baseUrl = resolveScoutBrokerUr
|
|
|
58495
58877
|
});
|
|
58496
58878
|
}
|
|
58497
58879
|
async function loadScoutBrokerContext(baseUrl = resolveScoutBrokerUrl(), options = {}) {
|
|
58498
|
-
const
|
|
58880
|
+
const usesRollingWindow = options.since === undefined;
|
|
58881
|
+
const since = usesRollingWindow ? Math.floor((Date.now() - DEFAULT_SCOUT_BROKER_SNAPSHOT_WINDOW_MS) / DEFAULT_SCOUT_BROKER_SNAPSHOT_BUCKET_MS) * DEFAULT_SCOUT_BROKER_SNAPSHOT_BUCKET_MS : options.since;
|
|
58499
58882
|
if (options.force) {
|
|
58500
58883
|
invalidateScoutBrokerContextCache(baseUrl);
|
|
58501
58884
|
}
|
|
58502
58885
|
const cacheKey = options.signal ? null : [
|
|
58503
58886
|
baseUrl,
|
|
58504
58887
|
resolveBrokerSocketPathForBaseUrl(baseUrl) ?? "http",
|
|
58505
|
-
since ?? "full",
|
|
58888
|
+
usesRollingWindow ? "rolling-24h" : since ?? "full",
|
|
58506
58889
|
options.scope ?? "default"
|
|
58507
58890
|
].join("\x00");
|
|
58508
58891
|
const now = Date.now();
|
|
58509
|
-
for (const [key,
|
|
58510
|
-
if (
|
|
58892
|
+
for (const [key, entry2] of scoutBrokerContextCache) {
|
|
58893
|
+
if (key !== cacheKey && !entry2.inFlight && entry2.expiresAt + SCOUT_BROKER_CONTEXT_STALE_RETENTION_MS <= now) {
|
|
58511
58894
|
scoutBrokerContextCache.delete(key);
|
|
58895
|
+
}
|
|
58512
58896
|
}
|
|
58513
|
-
const
|
|
58514
|
-
if (cached && cached.expiresAt > now) {
|
|
58515
|
-
return cached.promise;
|
|
58516
|
-
}
|
|
58517
|
-
const promise = (async () => {
|
|
58897
|
+
const readContext = async () => {
|
|
58518
58898
|
const health = await readScoutBrokerHealth(baseUrl, { signal: options.signal });
|
|
58519
58899
|
if (!health.reachable || !health.ok) {
|
|
58520
58900
|
return null;
|
|
@@ -58538,19 +58918,60 @@ async function loadScoutBrokerContext(baseUrl = resolveScoutBrokerUrl(), options
|
|
|
58538
58918
|
} catch {
|
|
58539
58919
|
return null;
|
|
58540
58920
|
}
|
|
58541
|
-
}
|
|
58542
|
-
if (cacheKey) {
|
|
58543
|
-
|
|
58544
|
-
|
|
58545
|
-
|
|
58546
|
-
|
|
58547
|
-
|
|
58548
|
-
|
|
58921
|
+
};
|
|
58922
|
+
if (!cacheKey) {
|
|
58923
|
+
return readContext();
|
|
58924
|
+
}
|
|
58925
|
+
const refresh = (entry2, delayMs = 0) => {
|
|
58926
|
+
if (entry2.inFlight)
|
|
58927
|
+
return entry2.inFlight;
|
|
58928
|
+
const attempt = (delayMs > 0 ? new Promise((resolve17) => setTimeout(resolve17, delayMs)) : Promise.resolve()).then(readContext).then((context) => {
|
|
58929
|
+
if (scoutBrokerContextCache.get(cacheKey) !== entry2)
|
|
58930
|
+
return context;
|
|
58931
|
+
if (context) {
|
|
58932
|
+
entry2.value = context;
|
|
58933
|
+
entry2.hasValue = true;
|
|
58934
|
+
entry2.expiresAt = Date.now() + SCOUT_BROKER_CONTEXT_CACHE_TTL_MS;
|
|
58935
|
+
} else if (!entry2.hasValue) {
|
|
58549
58936
|
scoutBrokerContextCache.delete(cacheKey);
|
|
58937
|
+
} else {
|
|
58938
|
+
entry2.expiresAt = Date.now() + SCOUT_BROKER_CONTEXT_CACHE_TTL_MS;
|
|
58939
|
+
}
|
|
58940
|
+
return context;
|
|
58941
|
+
}).finally(() => {
|
|
58942
|
+
if (scoutBrokerContextCache.get(cacheKey) === entry2) {
|
|
58943
|
+
entry2.inFlight = null;
|
|
58550
58944
|
}
|
|
58551
58945
|
});
|
|
58946
|
+
entry2.inFlight = attempt;
|
|
58947
|
+
return attempt;
|
|
58948
|
+
};
|
|
58949
|
+
const cached = scoutBrokerContextCache.get(cacheKey);
|
|
58950
|
+
if (cached) {
|
|
58951
|
+
if (cached.hasValue) {
|
|
58952
|
+
if (cached.expiresAt <= now && !cached.inFlight) {
|
|
58953
|
+
refresh(cached);
|
|
58954
|
+
}
|
|
58955
|
+
return cached.value;
|
|
58956
|
+
}
|
|
58957
|
+
if (options.waitForInitial === false) {
|
|
58958
|
+
refresh(cached, options.initialRefreshDelayMs);
|
|
58959
|
+
return null;
|
|
58960
|
+
}
|
|
58961
|
+
return refresh(cached);
|
|
58552
58962
|
}
|
|
58553
|
-
|
|
58963
|
+
const entry = {
|
|
58964
|
+
expiresAt: now + SCOUT_BROKER_CONTEXT_CACHE_TTL_MS,
|
|
58965
|
+
value: null,
|
|
58966
|
+
hasValue: false,
|
|
58967
|
+
inFlight: null
|
|
58968
|
+
};
|
|
58969
|
+
scoutBrokerContextCache.set(cacheKey, entry);
|
|
58970
|
+
if (options.waitForInitial === false) {
|
|
58971
|
+
refresh(entry, options.initialRefreshDelayMs);
|
|
58972
|
+
return null;
|
|
58973
|
+
}
|
|
58974
|
+
return refresh(entry);
|
|
58554
58975
|
}
|
|
58555
58976
|
async function requireScoutBrokerContext(baseUrl = resolveScoutBrokerUrl()) {
|
|
58556
58977
|
const context = await loadScoutBrokerContext(baseUrl);
|
|
@@ -59336,14 +59757,11 @@ async function loadScoutReadCursors(input) {
|
|
|
59336
59757
|
return brokerReadJson(input.baseUrl ?? resolveScoutBrokerUrl(), path);
|
|
59337
59758
|
}
|
|
59338
59759
|
async function markScoutConversationRead(input) {
|
|
59339
|
-
const
|
|
59340
|
-
if (!broker2) {
|
|
59341
|
-
throw new Error("broker unreachable");
|
|
59342
|
-
}
|
|
59760
|
+
const baseUrl = input.baseUrl ?? resolveScoutBrokerUrl();
|
|
59343
59761
|
const path = `/v1/conversations/${encodeURIComponent(input.conversationId)}/read-cursors`;
|
|
59344
|
-
return brokerPostJson(
|
|
59762
|
+
return brokerPostJson(baseUrl, path, {
|
|
59345
59763
|
actorId: input.actorId,
|
|
59346
|
-
readerNodeId: input.readerNodeId
|
|
59764
|
+
readerNodeId: input.readerNodeId,
|
|
59347
59765
|
lastReadMessageId: input.lastReadMessageId,
|
|
59348
59766
|
lastReadSeq: input.lastReadSeq,
|
|
59349
59767
|
lastReadAt: input.lastReadAt,
|
|
@@ -59507,7 +59925,7 @@ async function loadScoutRelayConfig() {
|
|
|
59507
59925
|
return {};
|
|
59508
59926
|
}
|
|
59509
59927
|
}
|
|
59510
|
-
var DEFAULT_SCOUT_BROKER_SNAPSHOT_WINDOW_MS, DEFAULT_SCOUT_BROKER_SNAPSHOT_BUCKET_MS, SCOUT_BROKER_CONTEXT_CACHE_TTL_MS =
|
|
59928
|
+
var DEFAULT_SCOUT_BROKER_SNAPSHOT_WINDOW_MS, DEFAULT_SCOUT_BROKER_SNAPSHOT_BUCKET_MS, SCOUT_BROKER_CONTEXT_CACHE_TTL_MS = 30000, SCOUT_BROKER_CONTEXT_STALE_RETENTION_MS = 60000, scoutBrokerContextCache, ScoutDirectDeliveryUnavailableError, OPERATOR_ID = "operator", SCOPED_ALIAS_POOL, readScoutBrokerNodeIdCoalesced;
|
|
59511
59929
|
var init_service = __esm(() => {
|
|
59512
59930
|
init_src();
|
|
59513
59931
|
init_setup();
|
|
@@ -60886,14 +61304,47 @@ function existingDirectConversationIdsForAgents(agentIds) {
|
|
|
60886
61304
|
}
|
|
60887
61305
|
return conversationIdByAgentId;
|
|
60888
61306
|
}
|
|
61307
|
+
function queryAgentIdsForBoundedRoster(limit) {
|
|
61308
|
+
const database = db2();
|
|
61309
|
+
let recentIds;
|
|
61310
|
+
try {
|
|
61311
|
+
recentIds = database.prepare(RECENT_ENDPOINT_AGENT_IDS_SQL).all(limit);
|
|
61312
|
+
} catch (error) {
|
|
61313
|
+
if (!(error instanceof Error) || !error.message.includes("idx_agent_endpoints_roster_recency")) {
|
|
61314
|
+
throw error;
|
|
61315
|
+
}
|
|
61316
|
+
recentIds = database.prepare(RECENT_ENDPOINT_AGENT_IDS_WITHOUT_INDEX_SQL).all(limit);
|
|
61317
|
+
}
|
|
61318
|
+
if (recentIds.length >= limit) {
|
|
61319
|
+
return recentIds.map((row) => row.id);
|
|
61320
|
+
}
|
|
61321
|
+
const endpointUpdatedAtExpression2 = sqlTimestampMsExpression("ep.updated_at");
|
|
61322
|
+
const fallbackIds = database.prepare(`SELECT a.id
|
|
61323
|
+
FROM agents a
|
|
61324
|
+
JOIN actors ac ON ac.id = a.id
|
|
61325
|
+
${LATEST_AGENT_ENDPOINT_JOIN}
|
|
61326
|
+
WHERE ${activeAgentMetadataPredicate("a")}
|
|
61327
|
+
AND COALESCE(${endpointUpdatedAtExpression2}, 0) <= 0
|
|
61328
|
+
ORDER BY COALESCE(${endpointUpdatedAtExpression2}, 0) DESC, ac.display_name ASC
|
|
61329
|
+
LIMIT ?`).all(limit - recentIds.length);
|
|
61330
|
+
return [...recentIds, ...fallbackIds].map((row) => row.id);
|
|
61331
|
+
}
|
|
61332
|
+
function queryAgentRowsByIds(agentIds) {
|
|
61333
|
+
if (agentIds.length === 0)
|
|
61334
|
+
return [];
|
|
61335
|
+
return db2().prepare(`${AGENT_ROW_SELECT}
|
|
61336
|
+
WHERE a.id IN (SELECT value FROM json_each(?))
|
|
61337
|
+
AND ${activeAgentMetadataPredicate("a")}
|
|
61338
|
+
ORDER BY COALESCE(${endpointUpdatedAtExpression}, 0) DESC, ac.display_name ASC`).all(JSON.stringify(agentIds));
|
|
61339
|
+
}
|
|
60889
61340
|
function queryAgentIdsByEndpointSessionId() {
|
|
60890
|
-
const
|
|
61341
|
+
const endpointUpdatedAtExpression2 = sqlTimestampMsExpression("ep.updated_at");
|
|
60891
61342
|
const rows = db2().prepare(`SELECT a.id, ep.session_id
|
|
60892
61343
|
FROM agents a
|
|
60893
61344
|
${LATEST_AGENT_ENDPOINT_JOIN}
|
|
60894
61345
|
WHERE ep.session_id IS NOT NULL
|
|
60895
61346
|
AND ${activeAgentMetadataPredicate("a")}
|
|
60896
|
-
ORDER BY COALESCE(${
|
|
61347
|
+
ORDER BY COALESCE(${endpointUpdatedAtExpression2}, 0) ASC`).all();
|
|
60897
61348
|
const map = new Map;
|
|
60898
61349
|
for (const row of rows) {
|
|
60899
61350
|
const sessionId = row.session_id.trim();
|
|
@@ -60905,87 +61356,20 @@ function queryAgentIdsByEndpointSessionId() {
|
|
|
60905
61356
|
}
|
|
60906
61357
|
function queryAgents(limit = 500) {
|
|
60907
61358
|
const flightPhases = queryAgentFlightPhases();
|
|
60908
|
-
|
|
60909
|
-
|
|
60910
|
-
|
|
60911
|
-
a
|
|
60912
|
-
|
|
60913
|
-
|
|
60914
|
-
|
|
60915
|
-
|
|
60916
|
-
|
|
60917
|
-
ac.handle,
|
|
60918
|
-
${actorCreatedAtExpression} AS actor_created_at,
|
|
60919
|
-
a.agent_class,
|
|
60920
|
-
a.default_selector,
|
|
60921
|
-
a.wake_policy,
|
|
60922
|
-
a.capabilities_json,
|
|
60923
|
-
a.metadata_json,
|
|
60924
|
-
a.authority_node_id,
|
|
60925
|
-
an.name AS authority_node_name,
|
|
60926
|
-
a.home_node_id,
|
|
60927
|
-
hn.name AS home_node_name,
|
|
60928
|
-
a.owner_id,
|
|
60929
|
-
oa.display_name AS owner_name,
|
|
60930
|
-
oa.handle AS owner_handle,
|
|
60931
|
-
ep.harness,
|
|
60932
|
-
ep.transport,
|
|
60933
|
-
ep.state,
|
|
60934
|
-
ep.project_root,
|
|
60935
|
-
ep.cwd,
|
|
60936
|
-
ep.session_id,
|
|
60937
|
-
ep.metadata_json AS endpoint_metadata_json,
|
|
60938
|
-
${endpointUpdatedAtExpression} AS updated_at
|
|
60939
|
-
FROM agents a
|
|
60940
|
-
JOIN actors ac ON ac.id = a.id
|
|
60941
|
-
LEFT JOIN nodes an ON an.id = a.authority_node_id
|
|
60942
|
-
LEFT JOIN nodes hn ON hn.id = a.home_node_id
|
|
60943
|
-
LEFT JOIN actors oa ON oa.id = a.owner_id
|
|
60944
|
-
${LATEST_AGENT_ENDPOINT_JOIN}
|
|
60945
|
-
WHERE ${activeAgentMetadataPredicate("a")}
|
|
60946
|
-
ORDER BY COALESCE(${endpointUpdatedAtExpression}, 0) DESC, ac.display_name ASC
|
|
60947
|
-
LIMIT ?`).all(limit);
|
|
61359
|
+
let rows;
|
|
61360
|
+
if (limit < 0) {
|
|
61361
|
+
rows = db2().prepare(`${AGENT_ROW_SELECT}
|
|
61362
|
+
WHERE ${activeAgentMetadataPredicate("a")}
|
|
61363
|
+
ORDER BY COALESCE(${endpointUpdatedAtExpression}, 0) DESC, ac.display_name ASC
|
|
61364
|
+
LIMIT ?`).all(limit);
|
|
61365
|
+
} else {
|
|
61366
|
+
rows = queryAgentRowsByIds(queryAgentIdsForBoundedRoster(limit));
|
|
61367
|
+
}
|
|
60948
61368
|
return mapAgentRows(rows, flightPhases, existingDirectConversationIdsForAgents(rows.map((row) => row.id)));
|
|
60949
61369
|
}
|
|
60950
61370
|
function queryAgentById(agentId) {
|
|
60951
61371
|
const flightPhases = queryAgentFlightPhases();
|
|
60952
|
-
const
|
|
60953
|
-
const endpointUpdatedAtExpression = sqlTimestampMsExpression("ep.updated_at");
|
|
60954
|
-
const row = db2().prepare(`SELECT
|
|
60955
|
-
a.id,
|
|
60956
|
-
a.definition_id,
|
|
60957
|
-
a.node_qualifier,
|
|
60958
|
-
a.workspace_qualifier,
|
|
60959
|
-
a.selector,
|
|
60960
|
-
ac.display_name AS name,
|
|
60961
|
-
ac.handle,
|
|
60962
|
-
${actorCreatedAtExpression} AS actor_created_at,
|
|
60963
|
-
a.agent_class,
|
|
60964
|
-
a.default_selector,
|
|
60965
|
-
a.wake_policy,
|
|
60966
|
-
a.capabilities_json,
|
|
60967
|
-
a.metadata_json,
|
|
60968
|
-
a.authority_node_id,
|
|
60969
|
-
an.name AS authority_node_name,
|
|
60970
|
-
a.home_node_id,
|
|
60971
|
-
hn.name AS home_node_name,
|
|
60972
|
-
a.owner_id,
|
|
60973
|
-
oa.display_name AS owner_name,
|
|
60974
|
-
oa.handle AS owner_handle,
|
|
60975
|
-
ep.harness,
|
|
60976
|
-
ep.transport,
|
|
60977
|
-
ep.state,
|
|
60978
|
-
ep.project_root,
|
|
60979
|
-
ep.cwd,
|
|
60980
|
-
ep.session_id,
|
|
60981
|
-
ep.metadata_json AS endpoint_metadata_json,
|
|
60982
|
-
${endpointUpdatedAtExpression} AS updated_at
|
|
60983
|
-
FROM agents a
|
|
60984
|
-
JOIN actors ac ON ac.id = a.id
|
|
60985
|
-
LEFT JOIN nodes an ON an.id = a.authority_node_id
|
|
60986
|
-
LEFT JOIN nodes hn ON hn.id = a.home_node_id
|
|
60987
|
-
LEFT JOIN actors oa ON oa.id = a.owner_id
|
|
60988
|
-
${LATEST_AGENT_ENDPOINT_JOIN}
|
|
61372
|
+
const row = db2().prepare(`${AGENT_ROW_SELECT}
|
|
60989
61373
|
WHERE a.id = ?
|
|
60990
61374
|
AND ${activeAgentMetadataPredicate("a")}
|
|
60991
61375
|
LIMIT 1`).get(agentId);
|
|
@@ -61051,12 +61435,70 @@ function mapAgentRows(rows, flightPhases, conversationIdByAgentId) {
|
|
|
61051
61435
|
};
|
|
61052
61436
|
});
|
|
61053
61437
|
}
|
|
61438
|
+
var actorCreatedAtExpression, endpointUpdatedAtExpression, AGENT_ROW_SELECT, RECENT_ENDPOINT_AGENT_IDS_WITHOUT_INDEX_SQL, RECENT_ENDPOINT_AGENT_IDS_SQL;
|
|
61054
61439
|
var init_agents = __esm(() => {
|
|
61055
61440
|
init_src();
|
|
61056
61441
|
init_db2();
|
|
61057
61442
|
init_parse2();
|
|
61058
61443
|
init_paths3();
|
|
61059
61444
|
init_sql_helpers();
|
|
61445
|
+
actorCreatedAtExpression = sqlTimestampMsExpression("ac.created_at");
|
|
61446
|
+
endpointUpdatedAtExpression = sqlTimestampMsExpression("ep.updated_at");
|
|
61447
|
+
AGENT_ROW_SELECT = `SELECT
|
|
61448
|
+
a.id,
|
|
61449
|
+
a.definition_id,
|
|
61450
|
+
a.node_qualifier,
|
|
61451
|
+
a.workspace_qualifier,
|
|
61452
|
+
a.selector,
|
|
61453
|
+
ac.display_name AS name,
|
|
61454
|
+
ac.handle,
|
|
61455
|
+
${actorCreatedAtExpression} AS actor_created_at,
|
|
61456
|
+
a.agent_class,
|
|
61457
|
+
a.default_selector,
|
|
61458
|
+
a.wake_policy,
|
|
61459
|
+
a.capabilities_json,
|
|
61460
|
+
a.metadata_json,
|
|
61461
|
+
a.authority_node_id,
|
|
61462
|
+
an.name AS authority_node_name,
|
|
61463
|
+
a.home_node_id,
|
|
61464
|
+
hn.name AS home_node_name,
|
|
61465
|
+
a.owner_id,
|
|
61466
|
+
oa.display_name AS owner_name,
|
|
61467
|
+
oa.handle AS owner_handle,
|
|
61468
|
+
ep.harness,
|
|
61469
|
+
ep.transport,
|
|
61470
|
+
ep.state,
|
|
61471
|
+
ep.project_root,
|
|
61472
|
+
ep.cwd,
|
|
61473
|
+
ep.session_id,
|
|
61474
|
+
ep.metadata_json AS endpoint_metadata_json,
|
|
61475
|
+
${endpointUpdatedAtExpression} AS updated_at
|
|
61476
|
+
FROM agents a
|
|
61477
|
+
JOIN actors ac ON ac.id = a.id
|
|
61478
|
+
LEFT JOIN nodes an ON an.id = a.authority_node_id
|
|
61479
|
+
LEFT JOIN nodes hn ON hn.id = a.home_node_id
|
|
61480
|
+
LEFT JOIN actors oa ON oa.id = a.owner_id
|
|
61481
|
+
${LATEST_AGENT_ENDPOINT_JOIN}`;
|
|
61482
|
+
RECENT_ENDPOINT_AGENT_IDS_WITHOUT_INDEX_SQL = (() => {
|
|
61483
|
+
const endpointUpdatedAtExpression2 = sqlTimestampMsExpression("ep.updated_at");
|
|
61484
|
+
const latestEndpointUpdatedAtExpression = sqlTimestampMsCoalesceExpression("ep2.updated_at");
|
|
61485
|
+
return `SELECT a.id
|
|
61486
|
+
FROM agent_endpoints ep
|
|
61487
|
+
JOIN agents a ON a.id = ep.agent_id
|
|
61488
|
+
JOIN actors ac ON ac.id = a.id
|
|
61489
|
+
WHERE ep.id = (
|
|
61490
|
+
SELECT ep2.id
|
|
61491
|
+
FROM agent_endpoints ep2
|
|
61492
|
+
WHERE ep2.agent_id = a.id
|
|
61493
|
+
ORDER BY ${latestEndpointUpdatedAtExpression} DESC
|
|
61494
|
+
LIMIT 1
|
|
61495
|
+
)
|
|
61496
|
+
AND ${endpointUpdatedAtExpression2} > 0
|
|
61497
|
+
AND ${activeAgentMetadataPredicate("a")}
|
|
61498
|
+
ORDER BY ${endpointUpdatedAtExpression2} DESC, ac.display_name ASC
|
|
61499
|
+
LIMIT ?`;
|
|
61500
|
+
})();
|
|
61501
|
+
RECENT_ENDPOINT_AGENT_IDS_SQL = RECENT_ENDPOINT_AGENT_IDS_WITHOUT_INDEX_SQL.replace("FROM agent_endpoints ep", "FROM agent_endpoints ep INDEXED BY idx_agent_endpoints_roster_recency");
|
|
61060
61502
|
});
|
|
61061
61503
|
|
|
61062
61504
|
// packages/web/server/db/internal/conversation-ids.ts
|
|
@@ -61148,7 +61590,11 @@ function queryRecentMessages(limit = 80, opts) {
|
|
|
61148
61590
|
const beforeMessage = resolveBeforeMessage(opts?.beforeMessageId, conversationIds, messageCreatedAtExpression);
|
|
61149
61591
|
const where = sqlJoinClauses([
|
|
61150
61592
|
transientBrokerWorkingStatusPredicate("m"),
|
|
61151
|
-
conversationIds.length > 0 ? `m.conversation_id IN (${sqlPlaceholders(conversationIds.length)})` :
|
|
61593
|
+
conversationIds.length > 0 ? `m.conversation_id IN (${sqlPlaceholders(conversationIds.length)})` : `(
|
|
61594
|
+
(m.conversation_id LIKE 'chn-%' AND length(m.conversation_id) > 4)
|
|
61595
|
+
OR (substr(m.conversation_id, 1, 5) = 'chat_' AND length(m.conversation_id) > 5)
|
|
61596
|
+
OR (m.conversation_id LIKE 'c.%' AND length(m.conversation_id) > 2)
|
|
61597
|
+
)`,
|
|
61152
61598
|
beforeMessage ? `(
|
|
61153
61599
|
${messageCreatedAtExpression} < ?
|
|
61154
61600
|
OR (${messageCreatedAtExpression} = ? AND m.id < ?)
|
|
@@ -62747,6 +63193,30 @@ function metadataString8(metadata, key) {
|
|
|
62747
63193
|
const value = metadata[key];
|
|
62748
63194
|
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
|
|
62749
63195
|
}
|
|
63196
|
+
function executionResolutionDimension(resolution, dimension) {
|
|
63197
|
+
const value = resolution?.[dimension];
|
|
63198
|
+
return value?.observed?.trim() || value?.resolved?.trim() || value?.requested?.trim() || null;
|
|
63199
|
+
}
|
|
63200
|
+
function durableConversationRuntime(row) {
|
|
63201
|
+
if (!row)
|
|
63202
|
+
return null;
|
|
63203
|
+
const execution = parseMetadataJson(row.execution_json);
|
|
63204
|
+
const rawResolution = parseMetadataJson(row.execution_resolution_json);
|
|
63205
|
+
const resolution = rawResolution.schemaVersion === "openscout.execution-resolution.v1" ? rawResolution : null;
|
|
63206
|
+
const flightMetadata = parseMetadataJson(row.flight_metadata_json);
|
|
63207
|
+
const trace = Array.isArray(flightMetadata.sessionTrace) ? [...flightMetadata.sessionTrace].reverse().find((entry) => entry && typeof entry === "object" && !Array.isArray(entry)) : undefined;
|
|
63208
|
+
const traceResolutionRaw = trace?.executionResolution;
|
|
63209
|
+
const traceResolution = traceResolutionRaw && typeof traceResolutionRaw === "object" && !Array.isArray(traceResolutionRaw) && traceResolutionRaw.schemaVersion === "openscout.execution-resolution.v1" ? traceResolutionRaw : null;
|
|
63210
|
+
const effectiveResolution = traceResolution ?? resolution;
|
|
63211
|
+
return {
|
|
63212
|
+
targetAgentId: row.target_agent_id,
|
|
63213
|
+
harness: executionResolutionDimension(effectiveResolution, "harness") ?? metadataString8(trace ?? {}, "harness") ?? metadataString8(execution, "harness"),
|
|
63214
|
+
model: executionResolutionDimension(effectiveResolution, "model") ?? metadataString8(execution, "model"),
|
|
63215
|
+
reasoningEffort: executionResolutionDimension(effectiveResolution, "reasoningEffort") ?? metadataString8(execution, "reasoningEffort"),
|
|
63216
|
+
transport: metadataString8(trace ?? {}, "transport"),
|
|
63217
|
+
sessionId: metadataString8(trace ?? {}, "sessionId") ?? resolution?.sessionId?.trim() ?? metadataString8(execution, "targetSessionId")
|
|
63218
|
+
};
|
|
63219
|
+
}
|
|
62750
63220
|
function formatChannelAlias(value) {
|
|
62751
63221
|
const trimmed = value.trim();
|
|
62752
63222
|
if (!trimmed)
|
|
@@ -62798,22 +63268,34 @@ function projectSessionConversationRows(rows, opts) {
|
|
|
62798
63268
|
AND ${transientBrokerWorkingStatusPredicate("m")}
|
|
62799
63269
|
ORDER BY ${messageCreatedAtExpression} DESC
|
|
62800
63270
|
LIMIT 1`);
|
|
63271
|
+
const runtimeStmt = db2().prepare(`SELECT target_agent_id, execution_json, execution_resolution_json, flight_metadata_json
|
|
63272
|
+
FROM invocations
|
|
63273
|
+
WHERE conversation_id = ?
|
|
63274
|
+
ORDER BY ${sqlTimestampMsExpression("created_at")} DESC, id DESC
|
|
63275
|
+
LIMIT 1`);
|
|
62801
63276
|
const summaries = rows.flatMap((r) => {
|
|
62802
63277
|
const conversationMetadata = parseMetadataJson(r.metadata_json);
|
|
62803
63278
|
const participants = memberStmt.all(r.id).map((m) => m.actor_id);
|
|
62804
63279
|
const agentParticipants = agentMemberStmt.all(r.id);
|
|
62805
|
-
const
|
|
63280
|
+
const runtime = durableConversationRuntime(runtimeStmt.get(r.id));
|
|
63281
|
+
const runtimeTargetAgentId = runtime?.targetAgentId && agentParticipants.some((entry) => entry.agent_id === runtime.targetAgentId) ? runtime.targetAgentId : null;
|
|
63282
|
+
const primaryAgentId = r.kind === "direct" ? runtimeTargetAgentId ?? pickDirectConversationAgentId(participants, agentParticipants.map((entry) => entry.agent_id)) : agentParticipants.length === 1 ? agentParticipants[0]?.agent_id ?? null : null;
|
|
62806
63283
|
const primaryAgent = primaryAgentId ? agentParticipants.find((entry) => entry.agent_id === primaryAgentId) ?? null : null;
|
|
62807
63284
|
const agentId = primaryAgent?.agent_id ?? null;
|
|
62808
63285
|
let agentName = null;
|
|
62809
|
-
let harness2 = null;
|
|
63286
|
+
let harness2 = runtime?.harness ?? null;
|
|
63287
|
+
let model2 = runtime?.model ?? null;
|
|
63288
|
+
let reasoningEffort = runtime?.reasoningEffort ?? null;
|
|
63289
|
+
let transport = runtime?.transport ?? null;
|
|
63290
|
+
let sessionId = runtime?.sessionId ?? null;
|
|
62810
63291
|
let harnessSessionId = null;
|
|
62811
63292
|
let harnessLogPath = null;
|
|
62812
63293
|
let branch = null;
|
|
62813
63294
|
let workspaceRoot = null;
|
|
62814
63295
|
if (primaryAgent) {
|
|
62815
63296
|
agentName = primaryAgent.display_name;
|
|
62816
|
-
harness2 = primaryAgent.harness;
|
|
63297
|
+
harness2 = harness2 ?? primaryAgent.harness;
|
|
63298
|
+
transport = transport ?? primaryAgent.transport;
|
|
62817
63299
|
workspaceRoot = compact(primaryAgent.project_root);
|
|
62818
63300
|
try {
|
|
62819
63301
|
const meta = primaryAgent.metadata_json ? JSON.parse(primaryAgent.metadata_json) : {};
|
|
@@ -62821,13 +63303,19 @@ function projectSessionConversationRows(rows, opts) {
|
|
|
62821
63303
|
return [];
|
|
62822
63304
|
}
|
|
62823
63305
|
branch = meta.branch ?? meta.workspaceQualifier ?? null;
|
|
63306
|
+
model2 = model2 ?? metadataString8(meta, "model");
|
|
63307
|
+
reasoningEffort = reasoningEffort ?? metadataString8(meta, "reasoningEffort");
|
|
62824
63308
|
} catch {}
|
|
62825
63309
|
try {
|
|
62826
63310
|
const endpointMeta = primaryAgent.endpoint_metadata_json ? JSON.parse(primaryAgent.endpoint_metadata_json) : {};
|
|
62827
63311
|
harnessSessionId = resolveHarnessSessionId(primaryAgent.transport, primaryAgent.session_id, endpointMeta);
|
|
63312
|
+
sessionId = sessionId ?? harnessSessionId;
|
|
63313
|
+
model2 = model2 ?? metadataString8(endpointMeta, "observedModel") ?? metadataString8(endpointMeta, "model");
|
|
63314
|
+
reasoningEffort = reasoningEffort ?? metadataString8(endpointMeta, "observedReasoningEffort") ?? metadataString8(endpointMeta, "reasoningEffort");
|
|
62828
63315
|
harnessLogPath = resolveHarnessLogPath(primaryAgent.agent_id, primaryAgent.transport, primaryAgent.session_id, endpointMeta);
|
|
62829
63316
|
} catch {
|
|
62830
63317
|
harnessSessionId = resolveHarnessSessionId(primaryAgent.transport, primaryAgent.session_id, undefined);
|
|
63318
|
+
sessionId = sessionId ?? harnessSessionId;
|
|
62831
63319
|
harnessLogPath = resolveHarnessLogPath(primaryAgent.agent_id, primaryAgent.transport, primaryAgent.session_id, undefined);
|
|
62832
63320
|
}
|
|
62833
63321
|
}
|
|
@@ -62842,6 +63330,10 @@ function projectSessionConversationRows(rows, opts) {
|
|
|
62842
63330
|
agentId,
|
|
62843
63331
|
agentName,
|
|
62844
63332
|
harness: harness2,
|
|
63333
|
+
model: model2,
|
|
63334
|
+
reasoningEffort,
|
|
63335
|
+
transport,
|
|
63336
|
+
sessionId,
|
|
62845
63337
|
harnessSessionId,
|
|
62846
63338
|
harnessLogPath,
|
|
62847
63339
|
currentBranch: branch,
|
|
@@ -62898,7 +63390,9 @@ function querySessions(limit = 80) {
|
|
|
62898
63390
|
FROM messages
|
|
62899
63391
|
GROUP BY conversation_id
|
|
62900
63392
|
) ms ON ms.conversation_id = c.id
|
|
62901
|
-
WHERE c.id LIKE '
|
|
63393
|
+
WHERE (c.id LIKE 'chn-%' AND length(c.id) > 4)
|
|
63394
|
+
OR (substr(c.id, 1, 5) = 'chat_' AND length(c.id) > 5)
|
|
63395
|
+
OR (c.id LIKE 'c.%' AND length(c.id) > 2)
|
|
62902
63396
|
ORDER BY COALESCE(ms.last_message_at, ${conversationCreatedAtExpression}, 0) DESC, ${conversationCreatedAtExpression} DESC, c.id ASC
|
|
62903
63397
|
LIMIT ?`).all(limit);
|
|
62904
63398
|
return projectSessionConversationRows(rows, {
|
|
@@ -62926,6 +63420,7 @@ function querySessionFallbackFromMessages(conversationId) {
|
|
|
62926
63420
|
m.actor_id AS agent_id,
|
|
62927
63421
|
ac.display_name,
|
|
62928
63422
|
ep.harness,
|
|
63423
|
+
ep.transport,
|
|
62929
63424
|
ep.project_root,
|
|
62930
63425
|
ep.session_id,
|
|
62931
63426
|
ep.metadata_json AS endpoint_metadata_json
|
|
@@ -62947,8 +63442,12 @@ function querySessionFallbackFromMessages(conversationId) {
|
|
|
62947
63442
|
agentId: agentRow?.agent_id ?? null,
|
|
62948
63443
|
agentName: agentRow?.display_name ?? null,
|
|
62949
63444
|
harness: agentRow?.harness ?? null,
|
|
62950
|
-
|
|
62951
|
-
|
|
63445
|
+
model: metadataString8(endpointMetadata, "observedModel") ?? metadataString8(endpointMetadata, "model"),
|
|
63446
|
+
reasoningEffort: metadataString8(endpointMetadata, "observedReasoningEffort") ?? metadataString8(endpointMetadata, "reasoningEffort"),
|
|
63447
|
+
transport: agentRow?.transport ?? null,
|
|
63448
|
+
sessionId: resolveHarnessSessionId(agentRow?.transport ?? null, agentRow?.session_id ?? null, endpointMetadata),
|
|
63449
|
+
harnessSessionId: resolveHarnessSessionId(agentRow?.transport ?? null, agentRow?.session_id ?? null, endpointMetadata),
|
|
63450
|
+
harnessLogPath: agentRow?.agent_id ? resolveHarnessLogPath(agentRow.agent_id, agentRow.transport, agentRow.session_id, endpointMetadata) : null,
|
|
62952
63451
|
currentBranch: metadataString8(endpointMetadata, "branch"),
|
|
62953
63452
|
preview: previewRow?.body?.trim() || null,
|
|
62954
63453
|
messageCount: stats.message_count,
|
|
@@ -64000,8 +64499,8 @@ function queryFleetAskRows(requesterIds, limit) {
|
|
|
64000
64499
|
ep.state AS endpoint_state,
|
|
64001
64500
|
cr.title AS work_title,
|
|
64002
64501
|
cr.summary AS work_summary,
|
|
64502
|
+
cr.kind AS record_kind,
|
|
64003
64503
|
cr.state AS work_state,
|
|
64004
|
-
cr.acceptance_state,
|
|
64005
64504
|
cr.next_move_owner_id,
|
|
64006
64505
|
cr.updated_at AS work_updated_at
|
|
64007
64506
|
FROM invocations inv
|
|
@@ -64063,7 +64562,8 @@ function projectFleetAsk(row, requesterIdSet) {
|
|
|
64063
64562
|
const queuedUntilOnline = queuedFlight && row.dispatch_outcome_status === "queued_until_online";
|
|
64064
64563
|
const staleActiveFlight = hasFlight && row.flight_state !== null && !TERMINAL_FLIGHT_STATES.has(row.flight_state) && isStaleActiveFlight(row.started_at, row.created_at);
|
|
64065
64564
|
const isActiveFlight = hasFlight && row.flight_state !== null && !TERMINAL_FLIGHT_STATES.has(row.flight_state) && !failed && !staleActiveFlight;
|
|
64066
|
-
const
|
|
64565
|
+
const attentionEligibleState = row.record_kind === "work_item" && row.work_state !== null && ["open", "working", "waiting", "review"].includes(row.work_state) || row.record_kind === "question" && row.work_state !== null && ["open", "answered"].includes(row.work_state);
|
|
64566
|
+
const awaitingOperator = attentionEligibleState && Boolean(row.next_move_owner_id && requesterIdSet.has(row.next_move_owner_id));
|
|
64067
64567
|
const updatedAt = normalizeTimestampMs(row.status_ts ?? row.completed_at ?? row.started_at ?? row.work_updated_at ?? row.created_at) ?? Date.now();
|
|
64068
64568
|
const dismissedAt = normalizeTimestampMs(row.flight_dismissed_at);
|
|
64069
64569
|
const recoveredAfterFailureAt = normalizeTimestampMs(row.recovered_after_failure_at);
|
|
@@ -64076,10 +64576,10 @@ function projectFleetAsk(row, requesterIdSet) {
|
|
|
64076
64576
|
status = queuedUntilOnline ? "failed" : "queued";
|
|
64077
64577
|
} else if (isActiveFlight) {
|
|
64078
64578
|
status = "working";
|
|
64079
|
-
} else if (awaitingOperator) {
|
|
64080
|
-
status = "needs_attention";
|
|
64081
64579
|
} else if (failed || staleActiveFlight) {
|
|
64082
64580
|
status = "failed";
|
|
64581
|
+
} else if (awaitingOperator) {
|
|
64582
|
+
status = "needs_attention";
|
|
64083
64583
|
} else {
|
|
64084
64584
|
status = "completed";
|
|
64085
64585
|
}
|
|
@@ -64123,34 +64623,7 @@ function queryFleetAttentionRows(requesterIds, limit) {
|
|
|
64123
64623
|
(cr.kind = 'work_item' AND cr.state IN ('open', 'working', 'waiting', 'review'))
|
|
64124
64624
|
OR (cr.kind = 'question' AND cr.state IN ('open', 'answered'))
|
|
64125
64625
|
)
|
|
64126
|
-
AND (
|
|
64127
|
-
cr.next_move_owner_id IN (${requesterClause})
|
|
64128
|
-
OR (
|
|
64129
|
-
cr.kind = 'work_item'
|
|
64130
|
-
AND cr.state = 'review'
|
|
64131
|
-
AND cr.acceptance_state = 'pending'
|
|
64132
|
-
AND NOT EXISTS (
|
|
64133
|
-
SELECT 1
|
|
64134
|
-
FROM collaboration_events e
|
|
64135
|
-
WHERE e.record_id = cr.id
|
|
64136
|
-
AND e.created_at > cr.updated_at
|
|
64137
|
-
)
|
|
64138
|
-
AND NOT EXISTS (
|
|
64139
|
-
SELECT 1
|
|
64140
|
-
FROM invocations inv
|
|
64141
|
-
WHERE inv.collaboration_record_id = cr.id
|
|
64142
|
-
AND inv.flight_id IS NOT NULL
|
|
64143
|
-
AND COALESCE(inv.completed_at, inv.started_at, 0) > cr.updated_at
|
|
64144
|
-
)
|
|
64145
|
-
AND NOT EXISTS (
|
|
64146
|
-
SELECT 1
|
|
64147
|
-
FROM messages m
|
|
64148
|
-
WHERE m.conversation_id = cr.conversation_id
|
|
64149
|
-
AND m.actor_id = cr.owner_id
|
|
64150
|
-
AND m.created_at > cr.updated_at
|
|
64151
|
-
)
|
|
64152
|
-
)
|
|
64153
|
-
)
|
|
64626
|
+
AND cr.next_move_owner_id IN (${requesterClause})
|
|
64154
64627
|
AND NOT EXISTS (
|
|
64155
64628
|
SELECT 1
|
|
64156
64629
|
FROM collaboration_events dismissed
|
|
@@ -66101,7 +66574,7 @@ var init_service2 = __esm(() => {
|
|
|
66101
66574
|
// packages/web/server/service-budgets.ts
|
|
66102
66575
|
import { createHash as createHash8 } from "crypto";
|
|
66103
66576
|
import { existsSync as existsSync45, mkdirSync as mkdirSync19, readdirSync as readdirSync12, readFileSync as readFileSync27, renameSync as renameSync7, statSync as statSync18, writeFileSync as writeFileSync17 } from "fs";
|
|
66104
|
-
import { open as open2 } from "fs/promises";
|
|
66577
|
+
import { open as open2, readdir as readdir4, stat as stat10 } from "fs/promises";
|
|
66105
66578
|
import { homedir as homedir45 } from "os";
|
|
66106
66579
|
import { dirname as dirname35, join as join63 } from "path";
|
|
66107
66580
|
import { createInterface as createInterface2 } from "readline";
|
|
@@ -66181,12 +66654,14 @@ async function loadCodexGauge(forceRefresh = false) {
|
|
|
66181
66654
|
const root = join63(homeDir(), ".codex", "sessions");
|
|
66182
66655
|
if (!existsSync45(root))
|
|
66183
66656
|
return fallback;
|
|
66184
|
-
const
|
|
66185
|
-
if (
|
|
66657
|
+
const candidates = await findRecentCodexJsonl(root, CODEX_LOOKBACK_DAYS);
|
|
66658
|
+
if (candidates.length === 0)
|
|
66186
66659
|
return fallback;
|
|
66187
|
-
const observations = (await
|
|
66660
|
+
const observations = (await harvestRecentCodexRateLimits(candidates)).sort((left, right) => left.capturedAt - right.capturedAt);
|
|
66188
66661
|
if (observations.length === 0)
|
|
66189
66662
|
return fallback;
|
|
66663
|
+
if (!observations.some(isCodexAccountPoolObservation))
|
|
66664
|
+
return fallback;
|
|
66190
66665
|
const snapshots = bindingCodexPoolSnapshots(observations.flatMap((observation) => codexQuotaSnapshotsFromObservation(observation.usage, observation.capturedAt)));
|
|
66191
66666
|
persistQuotaSnapshots(snapshots);
|
|
66192
66667
|
const persisted = loadPersistedProviderQuotaGauge({
|
|
@@ -66243,9 +66718,11 @@ function bindingCodexPoolSnapshots(snapshots) {
|
|
|
66243
66718
|
const usedPercent = quotaSnapshotUsage(row)?.fill;
|
|
66244
66719
|
if (usedPercent === undefined)
|
|
66245
66720
|
continue;
|
|
66721
|
+
const poolId = poolIdOf(row);
|
|
66722
|
+
const accountPool = isCodexAccountPoolId(poolId);
|
|
66246
66723
|
const best = bindingPoolByLabel.get(row.label);
|
|
66247
|
-
if (!best || usedPercent > best.usedPercent || usedPercent === best.usedPercent && row.capturedAt > best.capturedAt) {
|
|
66248
|
-
bindingPoolByLabel.set(row.label, { poolId
|
|
66724
|
+
if (!best || usedPercent > best.usedPercent || usedPercent === best.usedPercent && accountPool && !best.accountPool || usedPercent === best.usedPercent && accountPool === best.accountPool && row.capturedAt > best.capturedAt) {
|
|
66725
|
+
bindingPoolByLabel.set(row.label, { poolId, usedPercent, capturedAt: row.capturedAt, accountPool });
|
|
66249
66726
|
}
|
|
66250
66727
|
}
|
|
66251
66728
|
return snapshots.filter((row) => bindingPoolByLabel.get(row.label)?.poolId === poolIdOf(row));
|
|
@@ -66262,37 +66739,83 @@ function formatQuotaWindowLabel(windowMinutes, fallback) {
|
|
|
66262
66739
|
}
|
|
66263
66740
|
return `${windowMinutes}m`;
|
|
66264
66741
|
}
|
|
66265
|
-
function findRecentCodexJsonl(root, lookbackDays) {
|
|
66742
|
+
async function findRecentCodexJsonl(root, lookbackDays) {
|
|
66266
66743
|
const cutoffMs = Date.now() - lookbackDays * 86400 * 1000;
|
|
66267
66744
|
const paths2 = [];
|
|
66268
|
-
const
|
|
66745
|
+
const pending = [root];
|
|
66746
|
+
while (pending.length > 0) {
|
|
66747
|
+
const dir = pending.pop();
|
|
66748
|
+
if (!dir)
|
|
66749
|
+
continue;
|
|
66269
66750
|
let entries2;
|
|
66270
66751
|
try {
|
|
66271
|
-
entries2 =
|
|
66752
|
+
entries2 = await readdir4(dir, { withFileTypes: true });
|
|
66272
66753
|
} catch {
|
|
66273
|
-
|
|
66754
|
+
continue;
|
|
66274
66755
|
}
|
|
66275
66756
|
for (const entry of entries2) {
|
|
66276
66757
|
const full = join63(dir, entry.name);
|
|
66277
66758
|
if (entry.isDirectory()) {
|
|
66278
|
-
|
|
66759
|
+
pending.push(full);
|
|
66279
66760
|
} else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
66280
|
-
|
|
66281
|
-
|
|
66282
|
-
|
|
66283
|
-
|
|
66761
|
+
try {
|
|
66762
|
+
const fileStat = await stat10(full);
|
|
66763
|
+
if (fileStat.mtimeMs < cutoffMs)
|
|
66764
|
+
continue;
|
|
66765
|
+
paths2.push({ path: full, mtimeMs: fileStat.mtimeMs });
|
|
66766
|
+
} catch {}
|
|
66284
66767
|
}
|
|
66285
66768
|
}
|
|
66286
|
-
}
|
|
66287
|
-
|
|
66288
|
-
|
|
66769
|
+
}
|
|
66770
|
+
return paths2.sort((left, right) => right.mtimeMs - left.mtimeMs).slice(0, CODEX_RECENT_CANDIDATE_LIMIT);
|
|
66771
|
+
}
|
|
66772
|
+
async function harvestRecentCodexRateLimits(candidates) {
|
|
66773
|
+
const observations = await readCodexCandidateBatch(candidates.slice(0, CODEX_INITIAL_FILE_LIMIT));
|
|
66774
|
+
if (observations.some(isCodexAccountPoolObservation))
|
|
66775
|
+
return observations;
|
|
66776
|
+
const overflow = candidates.slice(CODEX_INITIAL_FILE_LIMIT, CODEX_RECENT_CANDIDATE_LIMIT);
|
|
66777
|
+
for (let index2 = 0;index2 < overflow.length; index2 += CODEX_JSONL_READ_CONCURRENCY) {
|
|
66778
|
+
observations.push(...await readCodexCandidateBatch(overflow.slice(index2, index2 + CODEX_JSONL_READ_CONCURRENCY)));
|
|
66779
|
+
if (observations.some(isCodexAccountPoolObservation))
|
|
66780
|
+
break;
|
|
66781
|
+
}
|
|
66782
|
+
return observations;
|
|
66783
|
+
}
|
|
66784
|
+
async function readCodexCandidateBatch(candidates) {
|
|
66785
|
+
return (await Promise.all(candidates.map(async (candidate) => {
|
|
66786
|
+
try {
|
|
66787
|
+
return await readLatestCodexRateLimits(candidate.path);
|
|
66788
|
+
} catch {
|
|
66789
|
+
return [];
|
|
66790
|
+
}
|
|
66791
|
+
}))).flat();
|
|
66792
|
+
}
|
|
66793
|
+
function isCodexAccountPoolObservation(observation) {
|
|
66794
|
+
return isCodexAccountPoolId(observation.usage.limitId);
|
|
66795
|
+
}
|
|
66796
|
+
function isCodexAccountPoolId(limitId) {
|
|
66797
|
+
const normalized = limitId?.trim().toLowerCase();
|
|
66798
|
+
return !normalized || normalized === "codex";
|
|
66289
66799
|
}
|
|
66290
66800
|
async function readLatestCodexRateLimits(path2) {
|
|
66291
66801
|
const handle = await open2(path2, "r");
|
|
66292
66802
|
try {
|
|
66293
|
-
const
|
|
66803
|
+
const fileStat = await handle.stat();
|
|
66804
|
+
const start = Math.max(0, fileStat.size - CODEX_JSONL_TAIL_MAX_BYTES);
|
|
66805
|
+
const rl = createInterface2({
|
|
66806
|
+
input: handle.createReadStream({
|
|
66807
|
+
encoding: "utf8",
|
|
66808
|
+
start,
|
|
66809
|
+
autoClose: false
|
|
66810
|
+
})
|
|
66811
|
+
});
|
|
66294
66812
|
const latestByPool = new Map;
|
|
66813
|
+
let firstLine = start > 0;
|
|
66295
66814
|
for await (const line of rl) {
|
|
66815
|
+
if (firstLine) {
|
|
66816
|
+
firstLine = false;
|
|
66817
|
+
continue;
|
|
66818
|
+
}
|
|
66296
66819
|
if (!line.includes('"rate_limits"'))
|
|
66297
66820
|
continue;
|
|
66298
66821
|
try {
|
|
@@ -66369,8 +66892,8 @@ function loadClaudeStatuslineQuotaSnapshots() {
|
|
|
66369
66892
|
}
|
|
66370
66893
|
function readClaudeStatuslineHistory(minCapturedAt) {
|
|
66371
66894
|
const path2 = join63(claudeStatuslineDir(), "claude-history.jsonl");
|
|
66372
|
-
const
|
|
66373
|
-
if (!
|
|
66895
|
+
const stat11 = safeStat(path2);
|
|
66896
|
+
if (!stat11)
|
|
66374
66897
|
return [];
|
|
66375
66898
|
let content;
|
|
66376
66899
|
try {
|
|
@@ -66378,7 +66901,7 @@ function readClaudeStatuslineHistory(minCapturedAt) {
|
|
|
66378
66901
|
} catch {
|
|
66379
66902
|
return [];
|
|
66380
66903
|
}
|
|
66381
|
-
if (
|
|
66904
|
+
if (stat11.size > CLAUDE_STATUSLINE_HISTORY_MAX_BYTES) {
|
|
66382
66905
|
content = content.slice(-CLAUDE_STATUSLINE_HISTORY_MAX_BYTES);
|
|
66383
66906
|
const firstNewline = content.indexOf(`
|
|
66384
66907
|
`);
|
|
@@ -67078,11 +67601,11 @@ async function loadGrokGauge() {
|
|
|
67078
67601
|
}
|
|
67079
67602
|
async function loadGrokBillingQuotaSnapshots() {
|
|
67080
67603
|
const path2 = join63(homeDir(), ".grok", "logs", "unified.jsonl");
|
|
67081
|
-
const
|
|
67082
|
-
if (!
|
|
67604
|
+
const stat11 = safeStat(path2);
|
|
67605
|
+
if (!stat11 || stat11.size <= 0)
|
|
67083
67606
|
return [];
|
|
67084
|
-
const length = Math.min(
|
|
67085
|
-
const start = Math.max(0,
|
|
67607
|
+
const length = Math.min(stat11.size, GROK_BILLING_LOG_MAX_BYTES);
|
|
67608
|
+
const start = Math.max(0, stat11.size - length);
|
|
67086
67609
|
let content = "";
|
|
67087
67610
|
let handle;
|
|
67088
67611
|
try {
|
|
@@ -67609,11 +68132,13 @@ function persistQuotaSnapshots(snapshots) {
|
|
|
67609
68132
|
return;
|
|
67610
68133
|
statement.run(id, snapshot.source ?? "provider_reported", snapshot.provider ?? null, snapshot.harness ?? null, snapshot.transport ?? null, snapshot.planType ?? null, snapshot.label, snapshot.windowKind ?? null, finiteNumber(snapshot.usedPercent) ?? null, finiteNumber(snapshot.percentRemaining) ?? null, finiteNumber(snapshot.used) ?? null, finiteNumber(snapshot.limitValue) ?? null, finiteNumber(snapshot.resetAt) ?? null, finiteNumber(snapshot.windowMs) ?? null, snapshot.capturedAt, JSON.stringify(metadata ?? {}), createdAt);
|
|
67611
68134
|
};
|
|
67612
|
-
|
|
67613
|
-
|
|
67614
|
-
|
|
67615
|
-
|
|
67616
|
-
|
|
68135
|
+
writer.transaction(() => {
|
|
68136
|
+
for (const snapshot of snapshots) {
|
|
68137
|
+
writeSnapshot(quotaSnapshotId(snapshot), snapshot, snapshot.metadata);
|
|
68138
|
+
writeSnapshot(quotaHistorySnapshotId(snapshot), snapshot, quotaHistoryMetadata(snapshot));
|
|
68139
|
+
}
|
|
68140
|
+
pruneHistory.run(createdAt - QUOTA_HISTORY_LOOKBACK_MS - QUOTA_HISTORY_BUCKET_MS2);
|
|
68141
|
+
})();
|
|
67617
68142
|
} catch {}
|
|
67618
68143
|
}
|
|
67619
68144
|
function quotaSnapshotMayReplace(existing, incoming) {
|
|
@@ -67718,7 +68243,7 @@ function safeStat(path2) {
|
|
|
67718
68243
|
return null;
|
|
67719
68244
|
}
|
|
67720
68245
|
}
|
|
67721
|
-
var CACHE_TTL_MS, WEEK_MS, CODEX_LOOKBACK_DAYS = 3, LOCAL_QUOTA_FRESH_MS, REMOTE_QUOTA_FRESH_MS, GH_CLI_TIMEOUT_MS = 4000, KIMI_USAGE_TIMEOUT_MS = 4000, MINIMAX_REMAINS_TIMEOUT_MS = 4000, DB_BUSY_TIMEOUT_MS3 = 2500, QUOTA_HISTORY_BUCKET_MS2, QUOTA_HISTORY_LOOKBACK_MS, QUOTA_HISTORY_ID_PREFIX = "budget:quota:history:", PERSISTED_QUOTA_ROW_LIMIT = 768, CLAUDE_STATUSLINE_HISTORY_MAX_BYTES, GROK_BILLING_LOG_MAX_BYTES, GH_CLI_BIN_ENV = "OPENSCOUT_GH_BIN", GH_RATE_LIMIT_JSON_ENV = "OPENSCOUT_GH_RATE_LIMIT_JSON", KIMI_USAGE_JSON_ENV = "OPENSCOUT_KIMI_USAGE_JSON", CURSOR_STATUS_JSON_ENV = "OPENSCOUT_CURSOR_STATUS_JSON", GROK_USAGE_JSON_ENV = "OPENSCOUT_GROK_USAGE_JSON", MINIMAX_REMAINS_JSON_ENV = "OPENSCOUT_MINIMAX_REMAINS_JSON", DASHBOARD_IMPORT_MAX_CHARS, cached = null, inflightNormal = null, inflightForce = null, quotaWriteDb = null;
|
|
68246
|
+
var CACHE_TTL_MS, WEEK_MS, CODEX_LOOKBACK_DAYS = 3, CODEX_JSONL_TAIL_MAX_BYTES, CODEX_INITIAL_FILE_LIMIT = 32, CODEX_RECENT_CANDIDATE_LIMIT = 64, CODEX_JSONL_READ_CONCURRENCY = 8, LOCAL_QUOTA_FRESH_MS, REMOTE_QUOTA_FRESH_MS, GH_CLI_TIMEOUT_MS = 4000, KIMI_USAGE_TIMEOUT_MS = 4000, MINIMAX_REMAINS_TIMEOUT_MS = 4000, DB_BUSY_TIMEOUT_MS3 = 2500, QUOTA_HISTORY_BUCKET_MS2, QUOTA_HISTORY_LOOKBACK_MS, QUOTA_HISTORY_ID_PREFIX = "budget:quota:history:", PERSISTED_QUOTA_ROW_LIMIT = 768, CLAUDE_STATUSLINE_HISTORY_MAX_BYTES, GROK_BILLING_LOG_MAX_BYTES, GH_CLI_BIN_ENV = "OPENSCOUT_GH_BIN", GH_RATE_LIMIT_JSON_ENV = "OPENSCOUT_GH_RATE_LIMIT_JSON", KIMI_USAGE_JSON_ENV = "OPENSCOUT_KIMI_USAGE_JSON", CURSOR_STATUS_JSON_ENV = "OPENSCOUT_CURSOR_STATUS_JSON", GROK_USAGE_JSON_ENV = "OPENSCOUT_GROK_USAGE_JSON", MINIMAX_REMAINS_JSON_ENV = "OPENSCOUT_MINIMAX_REMAINS_JSON", DASHBOARD_IMPORT_MAX_CHARS, cached = null, inflightNormal = null, inflightForce = null, quotaWriteDb = null;
|
|
67722
68247
|
var init_service_budgets = __esm(() => {
|
|
67723
68248
|
init_src2();
|
|
67724
68249
|
init_src();
|
|
@@ -67728,6 +68253,7 @@ var init_service_budgets = __esm(() => {
|
|
|
67728
68253
|
init_db2();
|
|
67729
68254
|
CACHE_TTL_MS = 60 * 1000;
|
|
67730
68255
|
WEEK_MS = 7 * 24 * 3600 * 1000;
|
|
68256
|
+
CODEX_JSONL_TAIL_MAX_BYTES = 2 * 1024 * 1024;
|
|
67731
68257
|
LOCAL_QUOTA_FRESH_MS = 2 * 60 * 1000;
|
|
67732
68258
|
REMOTE_QUOTA_FRESH_MS = 5 * 60 * 1000;
|
|
67733
68259
|
QUOTA_HISTORY_BUCKET_MS2 = 60 * 60 * 1000;
|
|
@@ -69159,9 +69685,9 @@ function readFilePreview(input) {
|
|
|
69159
69685
|
}
|
|
69160
69686
|
const { realPath, root } = resolved;
|
|
69161
69687
|
try {
|
|
69162
|
-
const
|
|
69688
|
+
const stat12 = statSync22(realPath);
|
|
69163
69689
|
const title = realPath === "/" ? "/" : realPath.split("/").pop() || realPath;
|
|
69164
|
-
if (
|
|
69690
|
+
if (stat12.isDirectory()) {
|
|
69165
69691
|
return {
|
|
69166
69692
|
ok: true,
|
|
69167
69693
|
content: {
|
|
@@ -69177,7 +69703,7 @@ function readFilePreview(input) {
|
|
|
69177
69703
|
}
|
|
69178
69704
|
};
|
|
69179
69705
|
}
|
|
69180
|
-
if (!
|
|
69706
|
+
if (!stat12.isFile()) {
|
|
69181
69707
|
return { ok: false, status: 415, error: "path is not a file or directory" };
|
|
69182
69708
|
}
|
|
69183
69709
|
const mediaType = mediaTypeFor(realPath);
|
|
@@ -69194,14 +69720,14 @@ function readFilePreview(input) {
|
|
|
69194
69720
|
title,
|
|
69195
69721
|
mediaType,
|
|
69196
69722
|
rawUrl,
|
|
69197
|
-
sizeBytes:
|
|
69723
|
+
sizeBytes: stat12.size,
|
|
69198
69724
|
previewReason: previewReasonFor(mediaType),
|
|
69199
69725
|
generatedAt: Date.now()
|
|
69200
69726
|
}
|
|
69201
69727
|
};
|
|
69202
69728
|
}
|
|
69203
|
-
const truncated =
|
|
69204
|
-
const readable = readPreviewBuffer(realPath, Math.min(
|
|
69729
|
+
const truncated = stat12.size > MAX_PREVIEW_BYTES;
|
|
69730
|
+
const readable = readPreviewBuffer(realPath, Math.min(stat12.size, MAX_PREVIEW_BYTES));
|
|
69205
69731
|
if (!looksTextual2(realPath, readable)) {
|
|
69206
69732
|
return {
|
|
69207
69733
|
ok: true,
|
|
@@ -69214,7 +69740,7 @@ function readFilePreview(input) {
|
|
|
69214
69740
|
title,
|
|
69215
69741
|
mediaType,
|
|
69216
69742
|
rawUrl,
|
|
69217
|
-
sizeBytes:
|
|
69743
|
+
sizeBytes: stat12.size,
|
|
69218
69744
|
previewReason: previewReasonFor(mediaType),
|
|
69219
69745
|
generatedAt: Date.now()
|
|
69220
69746
|
}
|
|
@@ -69232,7 +69758,7 @@ function readFilePreview(input) {
|
|
|
69232
69758
|
mediaType,
|
|
69233
69759
|
rawUrl,
|
|
69234
69760
|
content: readable.toString("utf8"),
|
|
69235
|
-
sizeBytes:
|
|
69761
|
+
sizeBytes: stat12.size,
|
|
69236
69762
|
truncated,
|
|
69237
69763
|
generatedAt: Date.now()
|
|
69238
69764
|
}
|
|
@@ -71432,7 +71958,7 @@ __export(exports_agent_definitions, {
|
|
|
71432
71958
|
resolveAgentProjectRoot: () => resolveAgentProjectRoot,
|
|
71433
71959
|
buildAgentDefinitions: () => buildAgentDefinitions
|
|
71434
71960
|
});
|
|
71435
|
-
import { access as access3, readdir as
|
|
71961
|
+
import { access as access3, readdir as readdir6, readFile as readFile19 } from "fs/promises";
|
|
71436
71962
|
import { join as join71 } from "path";
|
|
71437
71963
|
function excerptFromText2(raw2) {
|
|
71438
71964
|
const trimmed = raw2.trim();
|
|
@@ -71476,7 +72002,7 @@ function agentSlugFromHandle(handle, name2) {
|
|
|
71476
72002
|
return fromName || null;
|
|
71477
72003
|
}
|
|
71478
72004
|
async function listFolderFiles(folderPath, slug) {
|
|
71479
|
-
const entries2 = await
|
|
72005
|
+
const entries2 = await readdir6(folderPath, { withFileTypes: true });
|
|
71480
72006
|
const files = [];
|
|
71481
72007
|
for (const entry of entries2) {
|
|
71482
72008
|
if (!entry.isFile())
|
|
@@ -71516,7 +72042,7 @@ async function buildAgentDefinitions(input) {
|
|
|
71516
72042
|
const selectedSlug = agentSlugFromHandle(input.agentHandle, input.agentName ?? "");
|
|
71517
72043
|
const folders = [];
|
|
71518
72044
|
if (agentsRootExists) {
|
|
71519
|
-
const entries2 = await
|
|
72045
|
+
const entries2 = await readdir6(agentsRoot, { withFileTypes: true });
|
|
71520
72046
|
for (const entry of entries2) {
|
|
71521
72047
|
if (!entry.isDirectory() || SKIPPED_NAMES.has(entry.name) || entry.name.startsWith(".")) {
|
|
71522
72048
|
continue;
|
|
@@ -73133,8 +73659,55 @@ function assertIsolatedPairingRunStateWrite(path) {
|
|
|
73133
73659
|
}
|
|
73134
73660
|
|
|
73135
73661
|
// packages/web/server/pairing-pair-requests.ts
|
|
73662
|
+
var SCOUT_PAIR_CLIENT_HEADER = "x-scout-client";
|
|
73663
|
+
var SCOUT_PAIR_RELAY_HEADER = "x-scout-pair-relay";
|
|
73664
|
+
|
|
73665
|
+
class PairRequestCapacityError extends Error {
|
|
73666
|
+
retryAfterMs;
|
|
73667
|
+
constructor(retryAfterMs) {
|
|
73668
|
+
super("Too many live pairing requests");
|
|
73669
|
+
this.name = "PairRequestCapacityError";
|
|
73670
|
+
this.retryAfterMs = retryAfterMs;
|
|
73671
|
+
}
|
|
73672
|
+
}
|
|
73673
|
+
var PAIR_CLIENT_ID_PATTERN = /^[a-z0-9][a-z0-9-]{0,31}$/;
|
|
73674
|
+
var PAIR_CLIENT_LABELS = {
|
|
73675
|
+
"scout-ios": "Scout iOS",
|
|
73676
|
+
"scout-macos": "Scout macOS",
|
|
73677
|
+
"talkie-ios": "Talkie iOS",
|
|
73678
|
+
"talkie-macos": "Talkie macOS"
|
|
73679
|
+
};
|
|
73680
|
+
function parseScoutPairClient(headerValue, userAgent) {
|
|
73681
|
+
const raw2 = headerValue?.trim().toLowerCase() ?? "";
|
|
73682
|
+
if (PAIR_CLIENT_ID_PATTERN.test(raw2))
|
|
73683
|
+
return raw2;
|
|
73684
|
+
const ua = userAgent ?? "";
|
|
73685
|
+
if (/Scout/i.test(ua) && /iPhone|iPad|iOS/i.test(ua))
|
|
73686
|
+
return "scout-ios";
|
|
73687
|
+
if (/Talkie/i.test(ua) && /iPhone|iPad|iOS/i.test(ua))
|
|
73688
|
+
return "talkie-ios";
|
|
73689
|
+
return null;
|
|
73690
|
+
}
|
|
73691
|
+
function formatScoutPairClient(app) {
|
|
73692
|
+
const id = app?.trim() || null;
|
|
73693
|
+
if (!id)
|
|
73694
|
+
return null;
|
|
73695
|
+
return PAIR_CLIENT_LABELS[id] ?? id;
|
|
73696
|
+
}
|
|
73697
|
+
function pairRequesterDisplay(req) {
|
|
73698
|
+
const label = req.requesterLabel?.trim() || null;
|
|
73699
|
+
const app = formatScoutPairClient(req.requesterApp);
|
|
73700
|
+
if (label && app)
|
|
73701
|
+
return `${label} \xB7 ${app}`;
|
|
73702
|
+
return label || app || "A device";
|
|
73703
|
+
}
|
|
73136
73704
|
var DEFAULT_TTL_MS = 2 * 60 * 1000;
|
|
73705
|
+
var DEFAULT_MAX_LIVE_REQUESTS = 32;
|
|
73137
73706
|
var SWEEP_INTERVAL_MS = 30 * 1000;
|
|
73707
|
+
function boundedMetadata(value, maxLength) {
|
|
73708
|
+
const trimmed = value?.trim() || null;
|
|
73709
|
+
return trimmed ? trimmed.slice(0, maxLength) : null;
|
|
73710
|
+
}
|
|
73138
73711
|
var MAX_PUBLISH_ATTEMPTS = 32;
|
|
73139
73712
|
var PUBLISH_SPIN_ATTEMPTS = 8;
|
|
73140
73713
|
var PUBLISH_BACKOFF_CEILING_MS = 8;
|
|
@@ -73187,7 +73760,7 @@ function isPairRequest(value) {
|
|
|
73187
73760
|
if (!value || typeof value !== "object")
|
|
73188
73761
|
return false;
|
|
73189
73762
|
const r = value;
|
|
73190
|
-
return typeof r.token === "string" && r.token.length > 0 && (r.status === "pending" || r.status === "approved" || r.status === "denied") && isNullableString(r.requesterIp) && isNullableString(r.requesterLabel) && isNullableString(r.route) && typeof r.createdAt === "number" && typeof r.updatedAt === "number" && typeof r.expiresAt === "number";
|
|
73763
|
+
return typeof r.token === "string" && r.token.length > 0 && (r.status === "pending" || r.status === "approved" || r.status === "denied") && isNullableString(r.requesterIp) && isNullableString(r.requesterLabel) && (r.requesterApp === undefined || isNullableString(r.requesterApp)) && isNullableString(r.route) && typeof r.createdAt === "number" && typeof r.updatedAt === "number" && typeof r.expiresAt === "number";
|
|
73191
73764
|
}
|
|
73192
73765
|
function fileSignature(path) {
|
|
73193
73766
|
try {
|
|
@@ -73209,7 +73782,11 @@ function parseTerminalMarkers(value) {
|
|
|
73209
73782
|
continue;
|
|
73210
73783
|
if (typeof marker.collectAfter !== "number" || !Number.isFinite(marker.collectAfter))
|
|
73211
73784
|
continue;
|
|
73212
|
-
markers.push({
|
|
73785
|
+
markers.push({
|
|
73786
|
+
token: marker.token,
|
|
73787
|
+
collectAfter: marker.collectAfter,
|
|
73788
|
+
...typeof marker.claimId === "string" && marker.claimId.length > 0 ? { claimId: marker.claimId } : {}
|
|
73789
|
+
});
|
|
73213
73790
|
}
|
|
73214
73791
|
return markers;
|
|
73215
73792
|
}
|
|
@@ -73231,6 +73808,8 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73231
73808
|
const ttlMs = options.ttlMs ?? DEFAULT_TTL_MS;
|
|
73232
73809
|
const now = options.now ?? (() => Date.now());
|
|
73233
73810
|
const statePath = options.statePath;
|
|
73811
|
+
const maxLiveRequests = Math.max(1, Math.floor(options.maxLiveRequests ?? DEFAULT_MAX_LIVE_REQUESTS));
|
|
73812
|
+
const renewalWindowMs = Math.max(0, options.renewalWindowMs ?? Math.floor(ttlMs / 2));
|
|
73234
73813
|
const byToken = new Map;
|
|
73235
73814
|
let loadedGeneration = null;
|
|
73236
73815
|
let loadedSignature = null;
|
|
@@ -73239,6 +73818,7 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73239
73818
|
const unpersistedUpserts = new Set;
|
|
73240
73819
|
const unpersistedExpiries = new Map;
|
|
73241
73820
|
const fulfilledMarkers = new Map;
|
|
73821
|
+
const fulfilledClaims = new Map;
|
|
73242
73822
|
const unpublishedFulfilled = new Set;
|
|
73243
73823
|
const lastSeenInShared = new Map;
|
|
73244
73824
|
const tempPath = statePath ? `${statePath}.${process.pid}.${crypto.randomUUID().slice(0, 8)}.tmp` : null;
|
|
@@ -73256,6 +73836,17 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73256
73836
|
function latestGeneration() {
|
|
73257
73837
|
return statePath ? latestPairRequestGeneration(statePath) : null;
|
|
73258
73838
|
}
|
|
73839
|
+
function generationHasTerminalClaim(generation, claim) {
|
|
73840
|
+
const raw2 = readFileOrNull(generationPath(generation));
|
|
73841
|
+
if (raw2 === null)
|
|
73842
|
+
return false;
|
|
73843
|
+
try {
|
|
73844
|
+
const parsed = JSON.parse(raw2);
|
|
73845
|
+
return parseTerminalMarkers(parsed.fulfilled).some((marker) => marker.token === claim.token && marker.claimId === claim.claimId);
|
|
73846
|
+
} catch {
|
|
73847
|
+
return false;
|
|
73848
|
+
}
|
|
73849
|
+
}
|
|
73259
73850
|
function movedOnSince(sighting) {
|
|
73260
73851
|
if (loadedEpoch !== sighting.epoch)
|
|
73261
73852
|
return false;
|
|
@@ -73267,10 +73858,11 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73267
73858
|
function terminalMarkerHorizon(expiresAt) {
|
|
73268
73859
|
return Math.max(expiresAt, now()) + ttlMs;
|
|
73269
73860
|
}
|
|
73270
|
-
function markFulfilled(request) {
|
|
73861
|
+
function markFulfilled(request, claimId) {
|
|
73271
73862
|
const horizon = terminalMarkerHorizon(request.expiresAt);
|
|
73272
73863
|
const known = fulfilledMarkers.get(request.token);
|
|
73273
73864
|
fulfilledMarkers.set(request.token, known === undefined ? horizon : Math.max(known, horizon));
|
|
73865
|
+
fulfilledClaims.set(request.token, claimId);
|
|
73274
73866
|
if (statePath)
|
|
73275
73867
|
unpublishedFulfilled.add(request.token);
|
|
73276
73868
|
}
|
|
@@ -73279,8 +73871,10 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73279
73871
|
for (const [token, collectAfter] of fulfilledMarkers) {
|
|
73280
73872
|
if (unpublishedFulfilled.has(token))
|
|
73281
73873
|
continue;
|
|
73282
|
-
if (collectAfter < t)
|
|
73874
|
+
if (collectAfter < t) {
|
|
73283
73875
|
fulfilledMarkers.delete(token);
|
|
73876
|
+
fulfilledClaims.delete(token);
|
|
73877
|
+
}
|
|
73284
73878
|
}
|
|
73285
73879
|
}
|
|
73286
73880
|
function mergeUnpersisted(loaded) {
|
|
@@ -73340,6 +73934,8 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73340
73934
|
for (const marker of markers) {
|
|
73341
73935
|
const known = fulfilledMarkers.get(marker.token);
|
|
73342
73936
|
fulfilledMarkers.set(marker.token, known === undefined ? marker.collectAfter : Math.max(known, marker.collectAfter));
|
|
73937
|
+
if (marker.claimId !== undefined)
|
|
73938
|
+
fulfilledClaims.set(marker.token, marker.claimId);
|
|
73343
73939
|
}
|
|
73344
73940
|
for (const [token, row] of loaded) {
|
|
73345
73941
|
const known = fulfilledMarkers.get(token);
|
|
@@ -73406,7 +74002,10 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73406
74002
|
}
|
|
73407
74003
|
loadedEpoch = epoch;
|
|
73408
74004
|
loadedHasTerminalLedger = hasLedger;
|
|
73409
|
-
adopt(rows.filter(isPairRequest)
|
|
74005
|
+
adopt(rows.filter(isPairRequest).map((row) => ({
|
|
74006
|
+
...row,
|
|
74007
|
+
requesterApp: row.requesterApp ?? null
|
|
74008
|
+
})), markers);
|
|
73410
74009
|
return;
|
|
73411
74010
|
}
|
|
73412
74011
|
}
|
|
@@ -73417,7 +74016,7 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73417
74016
|
rmSync5(tempPath, { force: true });
|
|
73418
74017
|
} catch {}
|
|
73419
74018
|
}
|
|
73420
|
-
function publish(touched, expired) {
|
|
74019
|
+
function publish(touched, expired, terminalClaim) {
|
|
73421
74020
|
if (!statePath || !tempPath)
|
|
73422
74021
|
return "won";
|
|
73423
74022
|
if (touched.length === 0 && expired.length === 0 && !hasOutstandingWrites())
|
|
@@ -73433,7 +74032,11 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73433
74032
|
version: 1,
|
|
73434
74033
|
epoch,
|
|
73435
74034
|
requests: [...byToken.values()],
|
|
73436
|
-
fulfilled: [...fulfilledMarkers].map(([token, collectAfter]) => ({
|
|
74035
|
+
fulfilled: [...fulfilledMarkers].map(([token, collectAfter]) => ({
|
|
74036
|
+
token,
|
|
74037
|
+
collectAfter,
|
|
74038
|
+
...fulfilledClaims.has(token) ? { claimId: fulfilledClaims.get(token) } : {}
|
|
74039
|
+
}))
|
|
73437
74040
|
});
|
|
73438
74041
|
try {
|
|
73439
74042
|
mkdirSync11(dirname26(statePath), { recursive: true, mode: 448 });
|
|
@@ -73454,7 +74057,9 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73454
74057
|
discardTemp();
|
|
73455
74058
|
if (!landed || signature === null)
|
|
73456
74059
|
return "lost";
|
|
73457
|
-
|
|
74060
|
+
const frontier = latestGeneration();
|
|
74061
|
+
const inheritedClaim = terminalClaim !== undefined && frontier !== null && frontier > next && generationHasTerminalClaim(frontier, terminalClaim);
|
|
74062
|
+
if (frontier !== next && !inheritedClaim) {
|
|
73458
74063
|
try {
|
|
73459
74064
|
if (inodeOf(target2) === ours)
|
|
73460
74065
|
unlinkSync2(target2);
|
|
@@ -73472,7 +74077,7 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73472
74077
|
for (const token of byToken.keys())
|
|
73473
74078
|
lastSeenInShared.set(token, sighting);
|
|
73474
74079
|
forgetSightingsWeNoLongerHold();
|
|
73475
|
-
collectSuperseded(next);
|
|
74080
|
+
collectSuperseded(frontier ?? next);
|
|
73476
74081
|
return "won";
|
|
73477
74082
|
}
|
|
73478
74083
|
function collectSuperseded(published) {
|
|
@@ -73514,7 +74119,7 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73514
74119
|
function hasOutstandingWrites() {
|
|
73515
74120
|
return unpersistedUpserts.size > 0 || unpersistedExpiries.size > 0 || unpublishedFulfilled.size > 0;
|
|
73516
74121
|
}
|
|
73517
|
-
function commit(apply) {
|
|
74122
|
+
function commit(apply, options2 = {}) {
|
|
73518
74123
|
if (!statePath) {
|
|
73519
74124
|
pruneExpired();
|
|
73520
74125
|
collectTerminalMarkers();
|
|
@@ -73525,10 +74130,17 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73525
74130
|
const expired = pruneExpired();
|
|
73526
74131
|
collectTerminalMarkers();
|
|
73527
74132
|
const { value, touched } = apply();
|
|
73528
|
-
const outcome = publish(touched, expired);
|
|
74133
|
+
const outcome = publish(touched, expired, options2.terminalClaim);
|
|
73529
74134
|
if (outcome === "won")
|
|
73530
74135
|
return value;
|
|
74136
|
+
if (outcome === "lost")
|
|
74137
|
+
options2.rollback?.();
|
|
73531
74138
|
if (outcome === "failed" || attempt >= MAX_PUBLISH_ATTEMPTS) {
|
|
74139
|
+
if (options2.failClosed) {
|
|
74140
|
+
if (outcome === "failed")
|
|
74141
|
+
options2.rollback?.();
|
|
74142
|
+
return options2.failClosed();
|
|
74143
|
+
}
|
|
73532
74144
|
recordOutstanding(touched, expired);
|
|
73533
74145
|
return value;
|
|
73534
74146
|
}
|
|
@@ -73556,7 +74168,7 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73556
74168
|
return null;
|
|
73557
74169
|
const t = now();
|
|
73558
74170
|
for (const req of byToken.values()) {
|
|
73559
|
-
if (req.requesterIp === requesterIp && req.expiresAt > t
|
|
74171
|
+
if (req.requesterIp === requesterIp && req.expiresAt > t) {
|
|
73560
74172
|
return req;
|
|
73561
74173
|
}
|
|
73562
74174
|
}
|
|
@@ -73564,19 +74176,38 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73564
74176
|
}
|
|
73565
74177
|
return {
|
|
73566
74178
|
create(input) {
|
|
73567
|
-
const requesterIp = input.requesterIp
|
|
73568
|
-
const label = input.requesterLabel
|
|
74179
|
+
const requesterIp = boundedMetadata(input.requesterIp, 64);
|
|
74180
|
+
const label = boundedMetadata(input.requesterLabel, 96);
|
|
74181
|
+
const app = boundedMetadata(input.requesterApp, 32);
|
|
74182
|
+
const route = boundedMetadata(input.route, 16);
|
|
73569
74183
|
const token = crypto.randomUUID();
|
|
73570
|
-
|
|
74184
|
+
const result = commit(() => {
|
|
73571
74185
|
const existing = findReusable(requesterIp);
|
|
73572
74186
|
if (existing) {
|
|
73573
|
-
|
|
73574
|
-
existing.expiresAt
|
|
73575
|
-
if (
|
|
73576
|
-
existing.
|
|
73577
|
-
|
|
73578
|
-
|
|
73579
|
-
|
|
74187
|
+
const t2 = now();
|
|
74188
|
+
const renew = existing.status !== "denied" && existing.expiresAt - t2 <= renewalWindowMs;
|
|
74189
|
+
if (renew) {
|
|
74190
|
+
existing.updatedAt = t2;
|
|
74191
|
+
existing.expiresAt = t2 + ttlMs;
|
|
74192
|
+
if (route)
|
|
74193
|
+
existing.route = route;
|
|
74194
|
+
if (label)
|
|
74195
|
+
existing.requesterLabel = label;
|
|
74196
|
+
if (app)
|
|
74197
|
+
existing.requesterApp = app;
|
|
74198
|
+
}
|
|
74199
|
+
return { value: existing, touched: renew ? [existing.token] : [] };
|
|
74200
|
+
}
|
|
74201
|
+
if (byToken.size >= maxLiveRequests) {
|
|
74202
|
+
const t2 = now();
|
|
74203
|
+
const earliestExpiry = Math.min(...[...byToken.values()].map((request2) => request2.expiresAt));
|
|
74204
|
+
return {
|
|
74205
|
+
value: {
|
|
74206
|
+
capacity: true,
|
|
74207
|
+
retryAfterMs: Math.max(1000, earliestExpiry - t2)
|
|
74208
|
+
},
|
|
74209
|
+
touched: []
|
|
74210
|
+
};
|
|
73580
74211
|
}
|
|
73581
74212
|
const t = now();
|
|
73582
74213
|
const request = {
|
|
@@ -73584,7 +74215,8 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73584
74215
|
status: "pending",
|
|
73585
74216
|
requesterIp,
|
|
73586
74217
|
requesterLabel: label,
|
|
73587
|
-
|
|
74218
|
+
requesterApp: app,
|
|
74219
|
+
route,
|
|
73588
74220
|
createdAt: t,
|
|
73589
74221
|
updatedAt: t,
|
|
73590
74222
|
expiresAt: t + ttlMs
|
|
@@ -73592,6 +74224,10 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73592
74224
|
byToken.set(token, request);
|
|
73593
74225
|
return { value: request, touched: [token] };
|
|
73594
74226
|
});
|
|
74227
|
+
if ("capacity" in result) {
|
|
74228
|
+
throw new PairRequestCapacityError(result.retryAfterMs);
|
|
74229
|
+
}
|
|
74230
|
+
return result;
|
|
73595
74231
|
},
|
|
73596
74232
|
get(token) {
|
|
73597
74233
|
reload();
|
|
@@ -73601,8 +74237,9 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73601
74237
|
touch(token) {
|
|
73602
74238
|
commit(() => {
|
|
73603
74239
|
const req = byToken.get(token);
|
|
73604
|
-
const
|
|
73605
|
-
const
|
|
74240
|
+
const t = now();
|
|
74241
|
+
const extended = t + ttlMs;
|
|
74242
|
+
const extend = req !== undefined && (req.status === "pending" || req.status === "approved") && req.expiresAt - t <= renewalWindowMs && extended > req.expiresAt;
|
|
73606
74243
|
if (extend && req)
|
|
73607
74244
|
req.expiresAt = extended;
|
|
73608
74245
|
return { value: undefined, touched: extend ? [token] : [] };
|
|
@@ -73619,24 +74256,55 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73619
74256
|
return { value: null, touched: [] };
|
|
73620
74257
|
req.status = decision === "approve" ? "approved" : "denied";
|
|
73621
74258
|
req.updatedAt = now();
|
|
73622
|
-
|
|
73623
|
-
req.expiresAt = now() + ttlMs;
|
|
74259
|
+
req.expiresAt = now() + ttlMs;
|
|
73624
74260
|
return { value: req, touched: [token] };
|
|
73625
74261
|
});
|
|
73626
74262
|
},
|
|
73627
|
-
fulfill(token) {
|
|
73628
|
-
let
|
|
74263
|
+
fulfill(token, requiredStatus) {
|
|
74264
|
+
let proposal = null;
|
|
74265
|
+
const claim = { token, claimId: crypto.randomUUID() };
|
|
74266
|
+
let previousMarker;
|
|
74267
|
+
let previousClaim;
|
|
74268
|
+
let previouslyUnpublished = false;
|
|
74269
|
+
let previouslyUnpersisted = false;
|
|
74270
|
+
const rollback = () => {
|
|
74271
|
+
if (proposal === null)
|
|
74272
|
+
return;
|
|
74273
|
+
if (previousMarker === undefined)
|
|
74274
|
+
fulfilledMarkers.delete(token);
|
|
74275
|
+
else
|
|
74276
|
+
fulfilledMarkers.set(token, previousMarker);
|
|
74277
|
+
if (previousClaim === undefined)
|
|
74278
|
+
fulfilledClaims.delete(token);
|
|
74279
|
+
else
|
|
74280
|
+
fulfilledClaims.set(token, previousClaim);
|
|
74281
|
+
if (!previouslyUnpublished)
|
|
74282
|
+
unpublishedFulfilled.delete(token);
|
|
74283
|
+
byToken.set(token, proposal);
|
|
74284
|
+
if (previouslyUnpersisted)
|
|
74285
|
+
unpersistedUpserts.add(token);
|
|
74286
|
+
else
|
|
74287
|
+
unpersistedUpserts.delete(token);
|
|
74288
|
+
proposal = null;
|
|
74289
|
+
};
|
|
73629
74290
|
return commit(() => {
|
|
73630
|
-
|
|
73631
|
-
|
|
73632
|
-
|
|
73633
|
-
return { value: null, touched: [] };
|
|
73634
|
-
delivered = { ...request };
|
|
74291
|
+
const request = byToken.get(token);
|
|
74292
|
+
if (!request || !isLive(request) || requiredStatus !== undefined && request.status !== requiredStatus) {
|
|
74293
|
+
return { value: null, touched: [] };
|
|
73635
74294
|
}
|
|
73636
|
-
|
|
74295
|
+
proposal = { ...request };
|
|
74296
|
+
previousMarker = fulfilledMarkers.get(token);
|
|
74297
|
+
previousClaim = fulfilledClaims.get(token);
|
|
74298
|
+
previouslyUnpublished = unpublishedFulfilled.has(token);
|
|
74299
|
+
previouslyUnpersisted = unpersistedUpserts.has(token);
|
|
74300
|
+
markFulfilled(proposal, claim.claimId);
|
|
73637
74301
|
byToken.delete(token);
|
|
73638
74302
|
unpersistedUpserts.delete(token);
|
|
73639
|
-
return { value:
|
|
74303
|
+
return { value: proposal, touched: [] };
|
|
74304
|
+
}, {
|
|
74305
|
+
rollback,
|
|
74306
|
+
terminalClaim: claim,
|
|
74307
|
+
failClosed: () => null
|
|
73640
74308
|
});
|
|
73641
74309
|
},
|
|
73642
74310
|
dispose() {
|
|
@@ -73647,6 +74315,7 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73647
74315
|
unpersistedExpiries.clear();
|
|
73648
74316
|
unpublishedFulfilled.clear();
|
|
73649
74317
|
fulfilledMarkers.clear();
|
|
74318
|
+
fulfilledClaims.clear();
|
|
73650
74319
|
lastSeenInShared.clear();
|
|
73651
74320
|
}
|
|
73652
74321
|
};
|
|
@@ -73887,7 +74556,8 @@ init_agent_endpoints();
|
|
|
73887
74556
|
|
|
73888
74557
|
// packages/web/server/core/repo-identity.ts
|
|
73889
74558
|
init_system_probes();
|
|
73890
|
-
var REPO_KEY_TTL_MS = 60000;
|
|
74559
|
+
var REPO_KEY_TTL_MS = 10 * 60000;
|
|
74560
|
+
var REPO_KEY_PROBE_CONCURRENCY = 4;
|
|
73891
74561
|
function normalizeGitRemoteUrl(remote) {
|
|
73892
74562
|
const trimmed = remote?.trim() ?? "";
|
|
73893
74563
|
if (!trimmed)
|
|
@@ -73911,15 +74581,14 @@ function canonicalRepoKey(host, path2) {
|
|
|
73911
74581
|
}
|
|
73912
74582
|
var repoKeyCache = new Map;
|
|
73913
74583
|
var repoKeyInFlight = new Map;
|
|
74584
|
+
var queuedRepoKeyRoots = [];
|
|
74585
|
+
var queuedRepoKeyRootSet = new Set;
|
|
74586
|
+
var activeRepoKeyProbes = 0;
|
|
73914
74587
|
async function probeRepoKey(root) {
|
|
73915
74588
|
const remote = await gitRemoteGetUrlOrigin(root).catch(() => null);
|
|
73916
74589
|
return normalizeGitRemoteUrl(remote);
|
|
73917
74590
|
}
|
|
73918
|
-
function
|
|
73919
|
-
const cached = repoKeyCache.get(root);
|
|
73920
|
-
if (cached && Date.now() - cached.at < REPO_KEY_TTL_MS) {
|
|
73921
|
-
return Promise.resolve(cached.key);
|
|
73922
|
-
}
|
|
74591
|
+
function refreshRepoKeyForRoot(root) {
|
|
73923
74592
|
const inFlight = repoKeyInFlight.get(root);
|
|
73924
74593
|
if (inFlight)
|
|
73925
74594
|
return inFlight;
|
|
@@ -73933,10 +74602,38 @@ function resolveRepoKeyForRoot(root) {
|
|
|
73933
74602
|
repoKeyInFlight.set(root, promise);
|
|
73934
74603
|
return promise;
|
|
73935
74604
|
}
|
|
73936
|
-
|
|
74605
|
+
function drainRepoKeyProbeQueue() {
|
|
74606
|
+
while (activeRepoKeyProbes < REPO_KEY_PROBE_CONCURRENCY) {
|
|
74607
|
+
const root = queuedRepoKeyRoots.shift();
|
|
74608
|
+
if (!root)
|
|
74609
|
+
return;
|
|
74610
|
+
queuedRepoKeyRootSet.delete(root);
|
|
74611
|
+
activeRepoKeyProbes += 1;
|
|
74612
|
+
refreshRepoKeyForRoot(root).catch(() => null).finally(() => {
|
|
74613
|
+
activeRepoKeyProbes -= 1;
|
|
74614
|
+
drainRepoKeyProbeQueue();
|
|
74615
|
+
});
|
|
74616
|
+
}
|
|
74617
|
+
}
|
|
74618
|
+
function scheduleRepoKeyProbe(root) {
|
|
74619
|
+
if (repoKeyInFlight.has(root) || queuedRepoKeyRootSet.has(root))
|
|
74620
|
+
return;
|
|
74621
|
+
queuedRepoKeyRootSet.add(root);
|
|
74622
|
+
queuedRepoKeyRoots.push(root);
|
|
74623
|
+
drainRepoKeyProbeQueue();
|
|
74624
|
+
}
|
|
74625
|
+
function cachedRepoKeysByRoot(roots) {
|
|
74626
|
+
const now = Date.now();
|
|
73937
74627
|
const distinct = [...new Set(roots)];
|
|
73938
|
-
const
|
|
73939
|
-
|
|
74628
|
+
const result = new Map;
|
|
74629
|
+
for (const root of distinct) {
|
|
74630
|
+
const cached = repoKeyCache.get(root);
|
|
74631
|
+
result.set(root, cached?.key ?? null);
|
|
74632
|
+
if (!cached || now - cached.at >= REPO_KEY_TTL_MS) {
|
|
74633
|
+
scheduleRepoKeyProbe(root);
|
|
74634
|
+
}
|
|
74635
|
+
}
|
|
74636
|
+
return result;
|
|
73940
74637
|
}
|
|
73941
74638
|
|
|
73942
74639
|
// packages/web/server/terminal-session-discovery.ts
|
|
@@ -75353,6 +76050,50 @@ init_src();
|
|
|
75353
76050
|
init_legacy_ids();
|
|
75354
76051
|
init_service();
|
|
75355
76052
|
init_message_pagination();
|
|
76053
|
+
function provisionalScoutConversations(snapshot, filters = {}) {
|
|
76054
|
+
const allowedKinds = new Set(filters.kinds ?? DEFAULT_CONVERSATION_KINDS);
|
|
76055
|
+
const query = normalizeQuery(filters.query);
|
|
76056
|
+
const limit = Math.max(1, Math.floor(filters.limit ?? snapshot.items.length));
|
|
76057
|
+
return snapshot.items.filter((item) => item.entityKind === "scout_conversation" && item.visibilityState === "visible" && Boolean(item.conversationId) && allowedKinds.has(item.kind)).filter((item) => !query || [
|
|
76058
|
+
item.title,
|
|
76059
|
+
item.alias,
|
|
76060
|
+
item.agentName,
|
|
76061
|
+
item.preview,
|
|
76062
|
+
item.projectRoot
|
|
76063
|
+
].some((value) => value?.toLocaleLowerCase().includes(query))).slice(0, limit).map((item) => {
|
|
76064
|
+
const conversationId = item.conversationId;
|
|
76065
|
+
const participantIds = item.kind === "direct" && item.agentId ? ["operator", item.agentId] : [];
|
|
76066
|
+
return {
|
|
76067
|
+
id: conversationId,
|
|
76068
|
+
chatId: conversationId,
|
|
76069
|
+
equivalentConversationIds: [conversationId],
|
|
76070
|
+
kind: item.kind,
|
|
76071
|
+
title: item.title ?? item.agentName ?? item.alias ?? conversationId,
|
|
76072
|
+
alias: item.alias,
|
|
76073
|
+
naturalKey: item.naturalKey,
|
|
76074
|
+
participantIds,
|
|
76075
|
+
participants: [],
|
|
76076
|
+
participantCount: item.participantCount,
|
|
76077
|
+
authorityNodeId: item.authorityNodeId,
|
|
76078
|
+
authorityNodeName: item.authorityNodeName,
|
|
76079
|
+
agentId: item.agentId,
|
|
76080
|
+
agentName: item.agentName,
|
|
76081
|
+
harness: item.harness,
|
|
76082
|
+
model: item.model,
|
|
76083
|
+
reasoningEffort: item.effort,
|
|
76084
|
+
transport: null,
|
|
76085
|
+
sessionId: item.runtimeSessionId,
|
|
76086
|
+
currentBranch: item.currentBranch,
|
|
76087
|
+
parentConversationId: item.parentConversationId,
|
|
76088
|
+
anchorMessageId: item.anchorMessageId,
|
|
76089
|
+
preview: item.preview,
|
|
76090
|
+
messageCount: item.messageCount,
|
|
76091
|
+
lastMessageAt: item.lastMessageAt,
|
|
76092
|
+
workspaceRoot: item.projectRoot,
|
|
76093
|
+
unreadCount: item.unreadCount
|
|
76094
|
+
};
|
|
76095
|
+
});
|
|
76096
|
+
}
|
|
75356
76097
|
var DEFAULT_CONVERSATION_KINDS = [
|
|
75357
76098
|
"direct",
|
|
75358
76099
|
"channel",
|
|
@@ -75421,6 +76162,53 @@ function metadataObject2(metadata, key) {
|
|
|
75421
76162
|
function metadataSessionId(metadata) {
|
|
75422
76163
|
return metadataString9(metadata, "targetSessionId") ?? metadataString9(metadata, "responderSessionId") ?? metadataString9(metadata, "sessionId") ?? metadataString9(metadata, "externalSessionId") ?? metadataString9(metadata, "threadId") ?? metadataString9(metadataObject2(metadata, "returnAddress"), "sessionId");
|
|
75423
76164
|
}
|
|
76165
|
+
function executionResolutionDimension2(resolution, dimension) {
|
|
76166
|
+
const value = resolution?.[dimension];
|
|
76167
|
+
return value?.observed?.trim() || value?.resolved?.trim() || value?.requested?.trim() || null;
|
|
76168
|
+
}
|
|
76169
|
+
function executionResolutionFromUnknown(value) {
|
|
76170
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
76171
|
+
return null;
|
|
76172
|
+
const resolution = value;
|
|
76173
|
+
return resolution.schemaVersion === "openscout.execution-resolution.v1" ? resolution : null;
|
|
76174
|
+
}
|
|
76175
|
+
function flightSessionRuntime(flights, sessionId) {
|
|
76176
|
+
for (const flight of [...flights].reverse()) {
|
|
76177
|
+
const rawTrace = flight.metadata?.sessionTrace;
|
|
76178
|
+
if (!Array.isArray(rawTrace))
|
|
76179
|
+
continue;
|
|
76180
|
+
const entries2 = [...rawTrace].reverse();
|
|
76181
|
+
const candidate = entries2.find((entry) => {
|
|
76182
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry))
|
|
76183
|
+
return false;
|
|
76184
|
+
const id = metadataString9(entry, "sessionId");
|
|
76185
|
+
return sessionId ? id === sessionId : Boolean(id);
|
|
76186
|
+
});
|
|
76187
|
+
if (!candidate || typeof candidate !== "object" || Array.isArray(candidate))
|
|
76188
|
+
continue;
|
|
76189
|
+
const record2 = candidate;
|
|
76190
|
+
return {
|
|
76191
|
+
resolution: executionResolutionFromUnknown(record2.executionResolution),
|
|
76192
|
+
harness: metadataString9(record2, "harness"),
|
|
76193
|
+
transport: metadataString9(record2, "transport")
|
|
76194
|
+
};
|
|
76195
|
+
}
|
|
76196
|
+
return null;
|
|
76197
|
+
}
|
|
76198
|
+
function latestConversationRuntime(input) {
|
|
76199
|
+
const matchingParticipant = input.sessionId ? input.participants.find((participant) => participant.sessionId === input.sessionId) ?? null : null;
|
|
76200
|
+
const matchingInvocation = input.sessionId ? [...input.invocations].reverse().find((invocation2) => invocation2.executionResolution?.sessionId === input.sessionId || invocation2.execution?.targetSessionId === input.sessionId || metadataSessionId(invocation2.metadata) === input.sessionId) ?? null : null;
|
|
76201
|
+
const latestInvocation = input.invocations.at(-1) ?? null;
|
|
76202
|
+
const invocation = matchingInvocation ?? latestInvocation;
|
|
76203
|
+
const trace = flightSessionRuntime(input.flights, input.sessionId);
|
|
76204
|
+
const resolution = matchingInvocation?.executionResolution ?? trace?.resolution ?? invocation?.executionResolution ?? null;
|
|
76205
|
+
return {
|
|
76206
|
+
harness: executionResolutionDimension2(resolution, "harness") ?? trace?.harness ?? matchingParticipant?.harness ?? invocation?.execution?.harness?.trim() ?? input.endpoint?.harness ?? null,
|
|
76207
|
+
model: executionResolutionDimension2(resolution, "model") ?? matchingParticipant?.model ?? invocation?.execution?.model?.trim() ?? metadataString9(input.endpoint?.metadata, "observedModel") ?? metadataString9(input.endpoint?.metadata, "model"),
|
|
76208
|
+
reasoningEffort: executionResolutionDimension2(resolution, "reasoningEffort") ?? matchingParticipant?.reasoningEffort ?? invocation?.execution?.reasoningEffort?.trim() ?? metadataString9(input.endpoint?.metadata, "observedReasoningEffort") ?? metadataString9(input.endpoint?.metadata, "reasoningEffort"),
|
|
76209
|
+
transport: trace?.transport ?? matchingParticipant?.transport ?? input.endpoint?.transport ?? null
|
|
76210
|
+
};
|
|
76211
|
+
}
|
|
75424
76212
|
function formatChannelAlias2(value) {
|
|
75425
76213
|
const trimmed = value.trim();
|
|
75426
76214
|
if (!trimmed)
|
|
@@ -75751,6 +76539,8 @@ function buildScopedParticipants(snapshot, endpoints, operatorIds, conversationI
|
|
|
75751
76539
|
agentId: agent?.id ?? null,
|
|
75752
76540
|
sessionId: endpoint?.sessionId ?? metadataSessionId(endpoint?.metadata) ?? metadataSessionId(actor?.metadata) ?? (kind === "session" ? participantId : null),
|
|
75753
76541
|
harness: endpoint?.harness ?? metadataString9(actor?.metadata, "harness"),
|
|
76542
|
+
model: metadataString9(endpoint?.metadata, "observedModel") ?? metadataString9(endpoint?.metadata, "model") ?? metadataString9(actor?.metadata, "model"),
|
|
76543
|
+
reasoningEffort: metadataString9(endpoint?.metadata, "observedReasoningEffort") ?? metadataString9(endpoint?.metadata, "reasoningEffort") ?? metadataString9(actor?.metadata, "reasoningEffort"),
|
|
75754
76544
|
transport: endpoint?.transport ?? metadataString9(actor?.metadata, "transport"),
|
|
75755
76545
|
workspaceRoot: endpoint?.projectRoot ?? endpoint?.cwd ?? metadataString9(actor?.metadata, "projectRoot")
|
|
75756
76546
|
};
|
|
@@ -75772,6 +76562,9 @@ function includeConversation(summary, query) {
|
|
|
75772
76562
|
summary.title,
|
|
75773
76563
|
summary.agentId ?? "",
|
|
75774
76564
|
summary.agentName ?? "",
|
|
76565
|
+
summary.harness ?? "",
|
|
76566
|
+
summary.model ?? "",
|
|
76567
|
+
summary.reasoningEffort ?? "",
|
|
75775
76568
|
summary.preview ?? "",
|
|
75776
76569
|
summary.workspaceRoot ?? "",
|
|
75777
76570
|
...summary.participantIds,
|
|
@@ -75839,6 +76632,10 @@ function coalesceDuplicateNamedChannels(summaries, snapshot, endpoints, operator
|
|
|
75839
76632
|
preview: latest.preview,
|
|
75840
76633
|
lastMessageAt: latest.lastMessageAt,
|
|
75841
76634
|
sessionId: latest.sessionId ?? canonical2.sessionId,
|
|
76635
|
+
harness: latest.harness ?? canonical2.harness,
|
|
76636
|
+
model: latest.model ?? canonical2.model,
|
|
76637
|
+
reasoningEffort: latest.reasoningEffort ?? canonical2.reasoningEffort,
|
|
76638
|
+
transport: latest.transport ?? canonical2.transport,
|
|
75842
76639
|
messageCount: Math.max(...group.map((summary) => summary.messageCount)),
|
|
75843
76640
|
unreadCount: Math.max(...group.map((summary) => summary.unreadCount)),
|
|
75844
76641
|
...latestTurn ? { turn: latestTurn } : {}
|
|
@@ -75910,6 +76707,13 @@ async function getScoutConversations(filters = {}, brokerContext) {
|
|
|
75910
76707
|
}
|
|
75911
76708
|
const title = agentDisplayName(snapshot, endpointsByAgent, agentId);
|
|
75912
76709
|
const identityFields2 = conversationIdentityFields2(conversation);
|
|
76710
|
+
const runtime2 = latestConversationRuntime({
|
|
76711
|
+
sessionId,
|
|
76712
|
+
participants,
|
|
76713
|
+
invocations: invocations2,
|
|
76714
|
+
flights,
|
|
76715
|
+
endpoint
|
|
76716
|
+
});
|
|
75913
76717
|
return [{
|
|
75914
76718
|
id: conversation.id,
|
|
75915
76719
|
chatId: conversation.id,
|
|
@@ -75924,7 +76728,10 @@ async function getScoutConversations(filters = {}, brokerContext) {
|
|
|
75924
76728
|
authorityNodeName: snapshot.nodes?.[conversation.authorityNodeId]?.name ?? null,
|
|
75925
76729
|
agentId,
|
|
75926
76730
|
agentName: title,
|
|
75927
|
-
harness:
|
|
76731
|
+
harness: runtime2.harness,
|
|
76732
|
+
model: runtime2.model,
|
|
76733
|
+
reasoningEffort: runtime2.reasoningEffort,
|
|
76734
|
+
transport: runtime2.transport,
|
|
75928
76735
|
sessionId,
|
|
75929
76736
|
currentBranch: metadataString9(endpoint?.metadata, "branch") ?? metadataString9(endpoint?.metadata, "workspaceQualifier") ?? metadataString9(agent?.metadata, "branch") ?? metadataString9(agent?.metadata, "workspaceQualifier"),
|
|
75930
76737
|
parentConversationId: conversation.parentConversationId ?? null,
|
|
@@ -75951,6 +76758,13 @@ async function getScoutConversations(filters = {}, brokerContext) {
|
|
|
75951
76758
|
return [];
|
|
75952
76759
|
}
|
|
75953
76760
|
const identityFields = conversationIdentityFields2(conversation);
|
|
76761
|
+
const runtime = latestConversationRuntime({
|
|
76762
|
+
sessionId,
|
|
76763
|
+
participants,
|
|
76764
|
+
invocations: invocations2,
|
|
76765
|
+
flights,
|
|
76766
|
+
endpoint: null
|
|
76767
|
+
});
|
|
75954
76768
|
return [{
|
|
75955
76769
|
id: conversation.id,
|
|
75956
76770
|
chatId: conversation.id,
|
|
@@ -75965,7 +76779,10 @@ async function getScoutConversations(filters = {}, brokerContext) {
|
|
|
75965
76779
|
authorityNodeName: snapshot.nodes?.[conversation.authorityNodeId]?.name ?? null,
|
|
75966
76780
|
agentId: null,
|
|
75967
76781
|
agentName: null,
|
|
75968
|
-
harness:
|
|
76782
|
+
harness: runtime.harness,
|
|
76783
|
+
model: runtime.model,
|
|
76784
|
+
reasoningEffort: runtime.reasoningEffort,
|
|
76785
|
+
transport: runtime.transport,
|
|
75969
76786
|
sessionId,
|
|
75970
76787
|
currentBranch: null,
|
|
75971
76788
|
parentConversationId: conversation.parentConversationId ?? null,
|
|
@@ -75992,15 +76809,17 @@ function capSummaryRoster(summary, operatorIds, endpoints) {
|
|
|
75992
76809
|
if (summary.participantIds.length <= CHANNEL_ROSTER_CAP)
|
|
75993
76810
|
return summary;
|
|
75994
76811
|
const keep = new Set;
|
|
75995
|
-
|
|
75996
|
-
|
|
75997
|
-
keep.
|
|
75998
|
-
|
|
75999
|
-
|
|
76000
|
-
|
|
76001
|
-
|
|
76002
|
-
|
|
76003
|
-
|
|
76812
|
+
const fillFromTier = (matches) => {
|
|
76813
|
+
for (const id of summary.participantIds) {
|
|
76814
|
+
if (keep.size >= CHANNEL_ROSTER_CAP)
|
|
76815
|
+
return;
|
|
76816
|
+
if (matches(id))
|
|
76817
|
+
keep.add(id);
|
|
76818
|
+
}
|
|
76819
|
+
};
|
|
76820
|
+
fillFromTier((id) => operatorIds.has(id));
|
|
76821
|
+
fillFromTier((id) => !operatorIds.has(id) && participantEndpoint(endpoints, id) !== null);
|
|
76822
|
+
fillFromTier(() => true);
|
|
76004
76823
|
const keptIds = summary.participantIds.filter((id) => keep.has(id));
|
|
76005
76824
|
const droppedIds = summary.participantIds.filter((id) => !keep.has(id));
|
|
76006
76825
|
return {
|
|
@@ -76009,12 +76828,12 @@ function capSummaryRoster(summary, operatorIds, endpoints) {
|
|
|
76009
76828
|
participants: summary.participants.filter((participant) => keep.has(participant.actorId))
|
|
76010
76829
|
};
|
|
76011
76830
|
}
|
|
76012
|
-
async function getScoutConversationMessages(conversationId, limit = 80, beforeMessageId) {
|
|
76831
|
+
async function getScoutConversationMessages(conversationId, limit = 80, beforeMessageId, brokerContext) {
|
|
76013
76832
|
const normalizedId = conversationId.trim();
|
|
76014
76833
|
if (!normalizedId || !isOpaqueChannelId(normalizedId)) {
|
|
76015
76834
|
return [];
|
|
76016
76835
|
}
|
|
76017
|
-
const broker2 = await loadScoutBrokerContext(undefined, { scope: "conversations" });
|
|
76836
|
+
const broker2 = brokerContext === undefined ? await loadScoutBrokerContext(undefined, { scope: "conversations" }) : brokerContext;
|
|
76018
76837
|
if (!broker2)
|
|
76019
76838
|
return null;
|
|
76020
76839
|
const snapshot = broker2.snapshot;
|
|
@@ -76085,6 +76904,7 @@ import { basename as basename20, join as join54, resolve as resolve20 } from "pa
|
|
|
76085
76904
|
init_secret_redaction();
|
|
76086
76905
|
import { basename as basename19 } from "path";
|
|
76087
76906
|
import { open, stat as stat9 } from "fs/promises";
|
|
76907
|
+
import { StringDecoder } from "string_decoder";
|
|
76088
76908
|
|
|
76089
76909
|
// packages/runtime/src/tail/claude-source.ts
|
|
76090
76910
|
init_user_config();
|
|
@@ -78991,8 +79811,10 @@ function readPositiveIntEnv8(name2, fallback) {
|
|
|
78991
79811
|
const raw2 = Number.parseInt(process.env[name2] ?? "", 10);
|
|
78992
79812
|
return Number.isFinite(raw2) && raw2 > 0 ? raw2 : fallback;
|
|
78993
79813
|
}
|
|
78994
|
-
var
|
|
78995
|
-
var
|
|
79814
|
+
var DEFAULT_TAIL_POLL_INTERVAL_MS = 1e4;
|
|
79815
|
+
var DEFAULT_HOT_DISCOVERY_INTERVAL_MS = 60000;
|
|
79816
|
+
var TAIL_POLL_INTERVAL_MS = readPositiveIntEnv8("OPENSCOUT_TAIL_POLL_INTERVAL_MS", DEFAULT_TAIL_POLL_INTERVAL_MS);
|
|
79817
|
+
var HOT_DISCOVERY_INTERVAL_MS = readPositiveIntEnv8("OPENSCOUT_TAIL_HOT_DISCOVERY_INTERVAL_MS", DEFAULT_HOT_DISCOVERY_INTERVAL_MS);
|
|
78996
79818
|
var DISCOVERY_CACHE_MAX_AGE_MS = readPositiveIntEnv8("OPENSCOUT_TAIL_DISCOVERY_CACHE_MAX_AGE_MS", HOT_DISCOVERY_INTERVAL_MS);
|
|
78997
79819
|
var SHALLOW_DISCOVERY_INTERVAL_MS = readPositiveIntEnv8("OPENSCOUT_TAIL_SHALLOW_DISCOVERY_INTERVAL_MS", 10 * 60000);
|
|
78998
79820
|
var DEEP_DISCOVERY_INTERVAL_MS = readPositiveIntEnv8("OPENSCOUT_TAIL_DEEP_DISCOVERY_INTERVAL_MS", 60 * 60000);
|
|
@@ -79006,23 +79828,42 @@ var RAW_MAX_STRING_LEN = 1000;
|
|
|
79006
79828
|
var RAW_MAX_ARRAY_ITEMS = 25;
|
|
79007
79829
|
var RAW_MAX_OBJECT_KEYS = 50;
|
|
79008
79830
|
var RECENT_TRANSCRIPT_READ_BYTES = 512 * 1024;
|
|
79831
|
+
var WATCHER_READ_BYTES = readPositiveIntEnv8("OPENSCOUT_TAIL_WATCHER_READ_BYTES", 512 * 1024);
|
|
79832
|
+
var WATCHER_DRAIN_BYTES = Math.max(WATCHER_READ_BYTES, readPositiveIntEnv8("OPENSCOUT_TAIL_WATCHER_DRAIN_BYTES", 4 * 1024 * 1024));
|
|
79833
|
+
var WATCHER_PUMP_CONCURRENCY = readPositiveIntEnv8("OPENSCOUT_TAIL_WATCHER_PUMP_CONCURRENCY", 16);
|
|
79009
79834
|
var SESSION_TRANSCRIPT_READ_BYTES = 8 * 1024 * 1024;
|
|
79010
79835
|
var RECENT_TRANSCRIPT_KIND_SCAN_READ_BYTES = 32 * 1024 * 1024;
|
|
79011
79836
|
var RECENT_TRANSCRIPT_LINES_PER_FILE = 200;
|
|
79012
79837
|
var RECENT_TRANSCRIPT_KIND_SCAN_MAX_LINES = 65536;
|
|
79013
79838
|
var RECENT_TRANSCRIPT_MAX_FILES = readPositiveIntEnv8("OPENSCOUT_TAIL_RECENT_TRANSCRIPT_MAX_FILES", 24);
|
|
79839
|
+
var INTERNAL_RECONCILE_SESSIONS_PER_SOURCE = readPositiveIntEnv8("OPENSCOUT_TAIL_INTERNAL_RECONCILE_SESSIONS_PER_SOURCE", 12);
|
|
79840
|
+
var INTERNAL_RECONCILE_LINES_PER_SESSION = readPositiveIntEnv8("OPENSCOUT_TAIL_INTERNAL_RECONCILE_LINES_PER_SESSION", 128);
|
|
79841
|
+
var INTERNAL_RECONCILE_READ_BYTES = readPositiveIntEnv8("OPENSCOUT_TAIL_INTERNAL_RECONCILE_READ_BYTES", 256 * 1024);
|
|
79842
|
+
var INTERNAL_HOT_WATCHER_WINDOW_MS = readPositiveIntEnv8("OPENSCOUT_TAIL_INTERNAL_HOT_WATCHER_WINDOW_MS", 60000);
|
|
79843
|
+
var INTERNAL_IDLE_WATCHER_INTERVAL_MS = readPositiveIntEnv8("OPENSCOUT_TAIL_INTERNAL_IDLE_WATCHER_INTERVAL_MS", 15000);
|
|
79844
|
+
var INTERNAL_IDLE_WATCHER_BATCH_SIZE = readPositiveIntEnv8("OPENSCOUT_TAIL_INTERNAL_IDLE_WATCHER_BATCH_SIZE", 32);
|
|
79845
|
+
var INTERNAL_ACTIVE_STALE_AFTER_MS = readPositiveIntEnv8("OPENSCOUT_TAIL_INTERNAL_ACTIVE_STALE_AFTER_MS", 30 * 60000);
|
|
79846
|
+
var INTERNAL_STALE_CONFIRMATION_COUNT = 2;
|
|
79847
|
+
var AUTHORITATIVE_MISSING_CONFIRMATION_COUNT = 2;
|
|
79848
|
+
var INTERNAL_PERSISTED_OBSERVED_SEED_LIMIT = readPositiveIntEnv8("OPENSCOUT_TAIL_PERSISTED_OBSERVED_SEED_LIMIT", 4096);
|
|
79014
79849
|
var NATIVE_TAIL_SOURCES = new Set(["grok", "kimi", "opencode", "cursor"]);
|
|
79015
79850
|
var TRANSCRIPT_REPLAY_MEMO_MAX_ENTRIES = readPositiveIntEnv8("OPENSCOUT_TAIL_REPLAY_MEMO_MAX_ENTRIES", 256);
|
|
79016
79851
|
var TRANSCRIPT_REPLAY_ACTIVE_GRACE_MS = readPositiveIntEnv8("OPENSCOUT_TAIL_REPLAY_MEMO_ACTIVE_GRACE_MS", 2000);
|
|
79017
79852
|
var transcriptReplayMemo = new Map;
|
|
79018
79853
|
var transcriptReplayInFlight = new Map;
|
|
79854
|
+
var INTERNAL_TAIL_SESSION_OFFLINE_SUMMARY = "session lifecycle \xB7 confirmed offline";
|
|
79855
|
+
var INTERNAL_TAIL_SESSION_STALLED_SUMMARY = "session lifecycle \xB7 confirmed stale";
|
|
79019
79856
|
var sources = [GrokSource, KimiSource, ClaudeSource, CodexSource, CursorSource, OpenCodeSource, PiSource];
|
|
79020
79857
|
var watchers = new Map;
|
|
79021
79858
|
var aggregateBuffer = [];
|
|
79022
79859
|
var assistantBuffer = [];
|
|
79023
79860
|
var perSessionBuffer = new Map;
|
|
79024
79861
|
var subscribers = new Set;
|
|
79862
|
+
var internalSubscribers = new Set;
|
|
79863
|
+
var watcherPumpQueue = [];
|
|
79864
|
+
var activeWatcherPumps = 0;
|
|
79025
79865
|
var knownTranscripts = new Map;
|
|
79866
|
+
var persistedObservedSessions = new Map;
|
|
79026
79867
|
var quietEventLastSeen = new Map;
|
|
79027
79868
|
var pollTimer = null;
|
|
79028
79869
|
var hotDiscoveryTimer = null;
|
|
@@ -79219,10 +80060,19 @@ function shouldCoalesceQuietTailEvent(event) {
|
|
|
79219
80060
|
pruneQuietTailCoalescer(now);
|
|
79220
80061
|
return false;
|
|
79221
80062
|
}
|
|
79222
|
-
function
|
|
80063
|
+
function pushInternalEvent(rawEvent) {
|
|
79223
80064
|
const event = compactEvent(rawEvent);
|
|
80065
|
+
for (const subscriber of [...internalSubscribers]) {
|
|
80066
|
+
try {
|
|
80067
|
+
subscriber(event);
|
|
80068
|
+
} catch {}
|
|
80069
|
+
}
|
|
80070
|
+
return event;
|
|
80071
|
+
}
|
|
80072
|
+
function pushEvent(rawEvent) {
|
|
80073
|
+
const event = pushInternalEvent(rawEvent);
|
|
79224
80074
|
if (shouldCoalesceQuietTailEvent(event))
|
|
79225
|
-
return;
|
|
80075
|
+
return event;
|
|
79226
80076
|
aggregateBuffer.push(event);
|
|
79227
80077
|
if (aggregateBuffer.length > AGGREGATE_BUFFER_LIMIT) {
|
|
79228
80078
|
aggregateBuffer.splice(0, aggregateBuffer.length - AGGREGATE_BUFFER_LIMIT);
|
|
@@ -79247,15 +80097,114 @@ function pushEvent(rawEvent) {
|
|
|
79247
80097
|
subscriber(event);
|
|
79248
80098
|
} catch {}
|
|
79249
80099
|
}
|
|
80100
|
+
return event;
|
|
80101
|
+
}
|
|
80102
|
+
function rememberWatcherEvent(watcher, rawEvent, delivery) {
|
|
80103
|
+
if (watcher.emittedEventIds.has(rawEvent.id))
|
|
80104
|
+
return;
|
|
80105
|
+
watcher.emittedEventIds.add(rawEvent.id);
|
|
80106
|
+
const event = delivery === "all" ? pushEvent(rawEvent) : pushInternalEvent(rawEvent);
|
|
80107
|
+
watcher.internalObserved = true;
|
|
80108
|
+
watcher.lastInternalEvent = event;
|
|
80109
|
+
watcher.staleObservations = 0;
|
|
80110
|
+
watcher.lifecycleNotification = "none";
|
|
80111
|
+
const lifecycle = persistedObservedSessions.get(observedSessionLifecycleKey(watcher.source.name, event.sessionId));
|
|
80112
|
+
if (lifecycle) {
|
|
80113
|
+
lifecycle.missingAuthoritativePasses = 0;
|
|
80114
|
+
lifecycle.lifecycleNotification = "none";
|
|
80115
|
+
}
|
|
80116
|
+
}
|
|
80117
|
+
function observedSessionLifecycleKey(source, sourceSessionId) {
|
|
80118
|
+
return `${source.trim()}\x00${sourceSessionId.trim()}`;
|
|
80119
|
+
}
|
|
80120
|
+
function persistedSeedEvent(seed) {
|
|
80121
|
+
const source = seed.source.trim();
|
|
80122
|
+
const sourceSessionId = seed.sourceSessionId.trim();
|
|
80123
|
+
const timestamp = Number.isFinite(seed.lastActivityAt) && seed.lastActivityAt > 0 ? seed.lastActivityAt : 0;
|
|
80124
|
+
return {
|
|
80125
|
+
id: `tail-persisted-seed:${source}:${sourceSessionId}:${timestamp}`,
|
|
80126
|
+
ts: timestamp,
|
|
80127
|
+
source,
|
|
80128
|
+
sessionId: sourceSessionId,
|
|
80129
|
+
pid: virtualPidForPath(`${source}:${sourceSessionId}`),
|
|
80130
|
+
parentPid: null,
|
|
80131
|
+
project: seed.project?.trim() ?? "",
|
|
80132
|
+
cwd: seed.cwd?.trim() || seed.projectRoot?.trim() || "",
|
|
80133
|
+
harness: "unattributed",
|
|
80134
|
+
kind: "system",
|
|
80135
|
+
summary: "session lifecycle \xB7 restored persisted active identity",
|
|
80136
|
+
raw: { reason: "persisted_active_seed" }
|
|
80137
|
+
};
|
|
80138
|
+
}
|
|
80139
|
+
function applyPersistedObservedSeedToWatcher(watcher) {
|
|
80140
|
+
if (watcher.internalObserved)
|
|
80141
|
+
return;
|
|
80142
|
+
const sessionId = watcher.transcript.sessionId?.trim();
|
|
80143
|
+
if (!sessionId)
|
|
80144
|
+
return;
|
|
80145
|
+
const lifecycle = persistedObservedSessions.get(observedSessionLifecycleKey(watcher.source.name, sessionId));
|
|
80146
|
+
if (!lifecycle)
|
|
80147
|
+
return;
|
|
80148
|
+
watcher.internalObserved = true;
|
|
80149
|
+
watcher.lastInternalEvent = persistedSeedEvent(lifecycle.seed);
|
|
80150
|
+
watcher.missingAuthoritativePasses = lifecycle.missingAuthoritativePasses;
|
|
80151
|
+
watcher.lifecycleNotification = lifecycle.lifecycleNotification;
|
|
80152
|
+
}
|
|
80153
|
+
function watcherSessionId(watcher) {
|
|
80154
|
+
return watcher.lastInternalEvent?.sessionId.trim() || watcher.transcript.sessionId?.trim() || null;
|
|
80155
|
+
}
|
|
80156
|
+
function notifyWatcherLifecycle(watcher, reason, observedAt) {
|
|
80157
|
+
const nextNotification = reason === "missing" ? "offline" : "stalled";
|
|
80158
|
+
const sessionId = watcherSessionId(watcher);
|
|
80159
|
+
if (!sessionId)
|
|
80160
|
+
return;
|
|
80161
|
+
const lifecycleKey = observedSessionLifecycleKey(watcher.source.name, sessionId);
|
|
80162
|
+
const persistedLifecycle = persistedObservedSessions.get(lifecycleKey);
|
|
80163
|
+
if (!watcher.internalObserved || watcher.lifecycleNotification === nextNotification || watcher.lifecycleNotification === "offline" || persistedLifecycle?.lifecycleNotification === nextNotification || persistedLifecycle?.lifecycleNotification === "offline")
|
|
80164
|
+
return;
|
|
80165
|
+
watcher.lifecycleNotification = nextNotification;
|
|
80166
|
+
if (persistedLifecycle) {
|
|
80167
|
+
persistedLifecycle.lifecycleNotification = nextNotification;
|
|
80168
|
+
}
|
|
80169
|
+
pushInternalEvent({
|
|
80170
|
+
id: `tail-lifecycle:${watcher.source.name}:${sessionId}:${nextNotification}:${observedAt}`,
|
|
80171
|
+
ts: observedAt,
|
|
80172
|
+
source: watcher.source.name,
|
|
80173
|
+
sessionId,
|
|
80174
|
+
pid: watcher.process.pid,
|
|
80175
|
+
parentPid: watcher.process.ppid || null,
|
|
80176
|
+
project: watcher.transcript.project,
|
|
80177
|
+
cwd: watcher.transcript.cwd ?? watcher.process.cwd ?? "",
|
|
80178
|
+
harness: watcher.transcript.harness,
|
|
80179
|
+
kind: "system",
|
|
80180
|
+
summary: reason === "missing" ? INTERNAL_TAIL_SESSION_OFFLINE_SUMMARY : INTERNAL_TAIL_SESSION_STALLED_SUMMARY,
|
|
80181
|
+
raw: { reason }
|
|
80182
|
+
});
|
|
80183
|
+
if (nextNotification === "offline") {
|
|
80184
|
+
persistedObservedSessions.delete(lifecycleKey);
|
|
80185
|
+
}
|
|
80186
|
+
}
|
|
80187
|
+
function observeWatcherStaleness(watcher, observedAt) {
|
|
80188
|
+
if (watcher.lifecycleNotification !== "none" || !watcher.internalObserved || observedAt - watcher.lastObservedChangeAt < INTERNAL_ACTIVE_STALE_AFTER_MS) {
|
|
80189
|
+
watcher.staleObservations = 0;
|
|
80190
|
+
return;
|
|
80191
|
+
}
|
|
80192
|
+
watcher.staleObservations++;
|
|
80193
|
+
if (watcher.staleObservations >= INTERNAL_STALE_CONFIRMATION_COUNT) {
|
|
80194
|
+
notifyWatcherLifecycle(watcher, "stale", observedAt);
|
|
80195
|
+
}
|
|
79250
80196
|
}
|
|
79251
80197
|
async function readNew(handle, fromOffset, fileSize) {
|
|
79252
80198
|
if (fileSize <= fromOffset) {
|
|
79253
|
-
return {
|
|
80199
|
+
return { bytes: Buffer.alloc(0), nextOffset: fromOffset };
|
|
79254
80200
|
}
|
|
79255
|
-
const length = fileSize - fromOffset;
|
|
79256
|
-
const buffer = Buffer.
|
|
79257
|
-
await handle.read(buffer, 0, length, fromOffset);
|
|
79258
|
-
return {
|
|
80201
|
+
const length = Math.min(fileSize - fromOffset, WATCHER_READ_BYTES);
|
|
80202
|
+
const buffer = Buffer.allocUnsafe(length);
|
|
80203
|
+
const { bytesRead } = await handle.read(buffer, 0, length, fromOffset);
|
|
80204
|
+
return {
|
|
80205
|
+
bytes: buffer.subarray(0, bytesRead),
|
|
80206
|
+
nextOffset: fromOffset + bytesRead
|
|
80207
|
+
};
|
|
79259
80208
|
}
|
|
79260
80209
|
async function readTranscriptText(path2, maxBytes = RECENT_TRANSCRIPT_READ_BYTES) {
|
|
79261
80210
|
let handle = null;
|
|
@@ -79275,23 +80224,35 @@ async function readTranscriptText(path2, maxBytes = RECENT_TRANSCRIPT_READ_BYTES
|
|
|
79275
80224
|
await handle?.close().catch(() => {});
|
|
79276
80225
|
}
|
|
79277
80226
|
}
|
|
79278
|
-
async function
|
|
80227
|
+
async function runWatcherPump(watcher, observedAt) {
|
|
79279
80228
|
let handle = null;
|
|
80229
|
+
watcher.lastPumpAt = observedAt;
|
|
79280
80230
|
try {
|
|
79281
80231
|
const stats = await stat9(watcher.transcriptPath);
|
|
80232
|
+
const changed = stats.size !== watcher.lastKnownSize || stats.mtimeMs !== watcher.lastKnownMtimeMs;
|
|
80233
|
+
watcher.lastKnownSize = stats.size;
|
|
80234
|
+
watcher.lastKnownMtimeMs = stats.mtimeMs;
|
|
80235
|
+
if (changed) {
|
|
80236
|
+
watcher.lastObservedChangeAt = observedAt;
|
|
80237
|
+
watcher.staleObservations = 0;
|
|
80238
|
+
watcher.lifecycleNotification = "none";
|
|
80239
|
+
}
|
|
79282
80240
|
if (stats.size < watcher.offset) {
|
|
79283
80241
|
watcher.offset = 0;
|
|
79284
80242
|
watcher.carry = "";
|
|
80243
|
+
watcher.decoder = new StringDecoder("utf8");
|
|
79285
80244
|
watcher.emittedEventIds.clear();
|
|
79286
80245
|
}
|
|
79287
|
-
if (stats.size <= watcher.offset)
|
|
80246
|
+
if (stats.size <= watcher.offset) {
|
|
80247
|
+
observeWatcherStaleness(watcher, observedAt);
|
|
79288
80248
|
return;
|
|
80249
|
+
}
|
|
79289
80250
|
if (watcher.source.parseFile) {
|
|
79290
|
-
const
|
|
80251
|
+
const text4 = await readTranscriptText(watcher.transcriptPath);
|
|
79291
80252
|
watcher.offset = stats.size;
|
|
79292
|
-
if (!
|
|
80253
|
+
if (!text4)
|
|
79293
80254
|
return;
|
|
79294
|
-
const events2 = parsedEventsToArray(watcher.source.parseFile(
|
|
80255
|
+
const events2 = parsedEventsToArray(watcher.source.parseFile(text4, {
|
|
79295
80256
|
process: watcher.process,
|
|
79296
80257
|
transcript: watcher.transcript,
|
|
79297
80258
|
transcriptPath: watcher.transcriptPath,
|
|
@@ -79300,74 +80261,203 @@ async function pumpWatcher(watcher) {
|
|
|
79300
80261
|
}));
|
|
79301
80262
|
watcher.lineCounter += Math.max(1, events2.length);
|
|
79302
80263
|
for (const event of events2) {
|
|
79303
|
-
|
|
79304
|
-
continue;
|
|
79305
|
-
watcher.emittedEventIds.add(event.id);
|
|
79306
|
-
pushEvent(event);
|
|
80264
|
+
rememberWatcherEvent(watcher, event, "all");
|
|
79307
80265
|
}
|
|
79308
80266
|
return;
|
|
79309
80267
|
}
|
|
79310
|
-
|
|
79311
|
-
|
|
79312
|
-
|
|
79313
|
-
|
|
79314
|
-
|
|
79315
|
-
|
|
79316
|
-
|
|
79317
|
-
|
|
79318
|
-
|
|
79319
|
-
|
|
79320
|
-
if (!
|
|
80268
|
+
const drainEnd = Math.min(stats.size, watcher.offset + WATCHER_DRAIN_BYTES);
|
|
80269
|
+
while (watcher.offset < drainEnd) {
|
|
80270
|
+
handle = await open(watcher.transcriptPath, "r");
|
|
80271
|
+
const { bytes, nextOffset } = await readNew(handle, watcher.offset, drainEnd);
|
|
80272
|
+
await handle.close();
|
|
80273
|
+
handle = null;
|
|
80274
|
+
if (nextOffset <= watcher.offset)
|
|
80275
|
+
break;
|
|
80276
|
+
watcher.offset = nextOffset;
|
|
80277
|
+
const text4 = watcher.decoder.write(bytes);
|
|
80278
|
+
if (!text4)
|
|
79321
80279
|
continue;
|
|
79322
|
-
const
|
|
79323
|
-
|
|
79324
|
-
|
|
79325
|
-
|
|
79326
|
-
|
|
79327
|
-
|
|
79328
|
-
});
|
|
79329
|
-
watcher.lineCounter++;
|
|
79330
|
-
if (event) {
|
|
79331
|
-
if (watcher.emittedEventIds.has(event.id))
|
|
80280
|
+
const combined = watcher.carry + text4;
|
|
80281
|
+
const lines = combined.split(`
|
|
80282
|
+
`);
|
|
80283
|
+
watcher.carry = lines.pop() ?? "";
|
|
80284
|
+
for (const line of lines) {
|
|
80285
|
+
if (!line)
|
|
79332
80286
|
continue;
|
|
79333
|
-
watcher.
|
|
79334
|
-
|
|
80287
|
+
const event = watcher.source.parseLine(line, {
|
|
80288
|
+
process: watcher.process,
|
|
80289
|
+
transcript: watcher.transcript,
|
|
80290
|
+
transcriptPath: watcher.transcriptPath,
|
|
80291
|
+
lineOffset: watcher.lineCounter,
|
|
80292
|
+
state: watcher.state
|
|
80293
|
+
});
|
|
80294
|
+
watcher.lineCounter++;
|
|
80295
|
+
if (event) {
|
|
80296
|
+
rememberWatcherEvent(watcher, event, "all");
|
|
80297
|
+
}
|
|
79335
80298
|
}
|
|
79336
80299
|
}
|
|
80300
|
+
if (stats.size > watcher.offset) {
|
|
80301
|
+
const continuation = setTimeout(() => {
|
|
80302
|
+
pumpWatcher(watcher);
|
|
80303
|
+
}, 0);
|
|
80304
|
+
continuation.unref?.();
|
|
80305
|
+
}
|
|
79337
80306
|
} catch {} finally {
|
|
79338
80307
|
await handle?.close().catch(() => {});
|
|
79339
80308
|
}
|
|
79340
80309
|
}
|
|
79341
|
-
|
|
79342
|
-
|
|
80310
|
+
function scheduleWatcherPump(run) {
|
|
80311
|
+
return new Promise((resolve20, reject) => {
|
|
80312
|
+
const start = () => {
|
|
80313
|
+
activeWatcherPumps++;
|
|
80314
|
+
Promise.resolve().then(run).then(resolve20, reject).finally(() => {
|
|
80315
|
+
activeWatcherPumps--;
|
|
80316
|
+
watcherPumpQueue.shift()?.();
|
|
80317
|
+
});
|
|
80318
|
+
};
|
|
80319
|
+
if (activeWatcherPumps < WATCHER_PUMP_CONCURRENCY) {
|
|
80320
|
+
start();
|
|
80321
|
+
} else {
|
|
80322
|
+
watcherPumpQueue.push(start);
|
|
80323
|
+
}
|
|
80324
|
+
});
|
|
79343
80325
|
}
|
|
79344
|
-
|
|
80326
|
+
function pumpWatcher(watcher, observedAt = Date.now()) {
|
|
80327
|
+
if (watcher.pumpInFlight) {
|
|
80328
|
+
return watcher.pumpInFlight;
|
|
80329
|
+
}
|
|
80330
|
+
const request = scheduleWatcherPump(() => runWatcherPump(watcher, observedAt));
|
|
80331
|
+
watcher.pumpInFlight = request;
|
|
80332
|
+
request.finally(() => {
|
|
80333
|
+
if (watcher.pumpInFlight === request) {
|
|
80334
|
+
watcher.pumpInFlight = null;
|
|
80335
|
+
}
|
|
80336
|
+
}).catch(() => {});
|
|
80337
|
+
return request;
|
|
80338
|
+
}
|
|
80339
|
+
function selectWatchersForCurrentDemand(now = Date.now()) {
|
|
80340
|
+
const all = [...watchers.values()];
|
|
80341
|
+
if (subscribers.size > 0)
|
|
80342
|
+
return all;
|
|
80343
|
+
if (internalSubscribers.size === 0)
|
|
80344
|
+
return [];
|
|
80345
|
+
const hot = [];
|
|
80346
|
+
const coldDue = [];
|
|
80347
|
+
for (const watcher of all) {
|
|
80348
|
+
if (now - watcher.lastObservedChangeAt <= INTERNAL_HOT_WATCHER_WINDOW_MS) {
|
|
80349
|
+
hot.push(watcher);
|
|
80350
|
+
} else if (now - watcher.lastPumpAt >= INTERNAL_IDLE_WATCHER_INTERVAL_MS) {
|
|
80351
|
+
coldDue.push(watcher);
|
|
80352
|
+
}
|
|
80353
|
+
}
|
|
80354
|
+
coldDue.sort((left, right) => left.lastPumpAt - right.lastPumpAt);
|
|
80355
|
+
return [...hot, ...coldDue.slice(0, INTERNAL_IDLE_WATCHER_BATCH_SIZE)];
|
|
80356
|
+
}
|
|
80357
|
+
async function pumpWatchersForCurrentDemand(now = Date.now()) {
|
|
80358
|
+
const selected = selectWatchersForCurrentDemand(now);
|
|
80359
|
+
await Promise.allSettled(selected.map((watcher) => pumpWatcher(watcher, now)));
|
|
80360
|
+
}
|
|
80361
|
+
async function seedTail(watcher, options = { reconcileInternal: false }) {
|
|
80362
|
+
let stats;
|
|
79345
80363
|
try {
|
|
79346
|
-
|
|
79347
|
-
|
|
79348
|
-
|
|
79349
|
-
|
|
80364
|
+
stats = await stat9(watcher.transcriptPath);
|
|
80365
|
+
} catch {
|
|
80366
|
+
watcher.offset = 0;
|
|
80367
|
+
return;
|
|
80368
|
+
}
|
|
80369
|
+
const seededAt = Date.now();
|
|
80370
|
+
watcher.offset = options.reconcileInternal || !watcher.source.parseFile ? stats.size : 0;
|
|
80371
|
+
watcher.lastPumpAt = seededAt;
|
|
80372
|
+
watcher.lastKnownSize = stats.size;
|
|
80373
|
+
watcher.lastKnownMtimeMs = stats.mtimeMs;
|
|
80374
|
+
watcher.lastObservedChangeAt = Math.max(watcher.transcript.lastEventAt ?? 0, watcher.transcript.mtimeMs, stats.mtimeMs);
|
|
80375
|
+
try {
|
|
80376
|
+
if (options.reconcileInternal && watcher.source.parseFile) {
|
|
80377
|
+
const text4 = await readTranscriptText(watcher.transcriptPath, INTERNAL_RECONCILE_READ_BYTES);
|
|
80378
|
+
if (!text4)
|
|
80379
|
+
return;
|
|
80380
|
+
const events2 = parsedEventsToArray(watcher.source.parseFile(text4, {
|
|
80381
|
+
process: watcher.process,
|
|
80382
|
+
transcript: watcher.transcript,
|
|
80383
|
+
transcriptPath: watcher.transcriptPath,
|
|
80384
|
+
lineOffset: 0,
|
|
80385
|
+
state: watcher.state
|
|
80386
|
+
}));
|
|
80387
|
+
watcher.lineCounter = Math.max(1, events2.length);
|
|
80388
|
+
for (const event of events2)
|
|
80389
|
+
rememberWatcherEvent(watcher, event, "internal");
|
|
80390
|
+
return;
|
|
80391
|
+
}
|
|
80392
|
+
if (!watcher.source.parseFile && (options.reconcileInternal || watcher.source.name === "codex")) {
|
|
80393
|
+
const lines = await readRecentTranscriptLines(watcher.transcriptPath, options.reconcileInternal ? INTERNAL_RECONCILE_LINES_PER_SESSION : RECENT_TRANSCRIPT_LINES_PER_FILE, options.reconcileInternal ? INTERNAL_RECONCILE_READ_BYTES : RECENT_TRANSCRIPT_READ_BYTES);
|
|
79350
80394
|
lines.forEach((line, index2) => {
|
|
79351
|
-
watcher.source.parseLine(line, {
|
|
80395
|
+
const parsed = watcher.source.parseLine(line, {
|
|
79352
80396
|
process: watcher.process,
|
|
79353
80397
|
transcript: watcher.transcript,
|
|
79354
80398
|
transcriptPath: watcher.transcriptPath,
|
|
79355
80399
|
lineOffset: index2,
|
|
79356
80400
|
state: watcher.state
|
|
79357
80401
|
});
|
|
80402
|
+
if (options.reconcileInternal && parsed) {
|
|
80403
|
+
rememberWatcherEvent(watcher, parsed, "internal");
|
|
80404
|
+
}
|
|
79358
80405
|
});
|
|
80406
|
+
watcher.lineCounter = lines.length;
|
|
79359
80407
|
}
|
|
79360
|
-
} catch {
|
|
79361
|
-
|
|
80408
|
+
} catch {}
|
|
80409
|
+
}
|
|
80410
|
+
function reconcileMissingWatchers(seenSessionKeys, successfullyScannedSources, observedAt) {
|
|
80411
|
+
for (const [sessionKey4, watcher] of watchers) {
|
|
80412
|
+
if (seenSessionKeys.has(sessionKey4)) {
|
|
80413
|
+
watcher.missingAuthoritativePasses = 0;
|
|
80414
|
+
continue;
|
|
80415
|
+
}
|
|
80416
|
+
if (!successfullyScannedSources.has(watcher.source.name))
|
|
80417
|
+
continue;
|
|
80418
|
+
watcher.missingAuthoritativePasses++;
|
|
80419
|
+
if (watcher.missingAuthoritativePasses < AUTHORITATIVE_MISSING_CONFIRMATION_COUNT) {
|
|
80420
|
+
continue;
|
|
80421
|
+
}
|
|
80422
|
+
notifyWatcherLifecycle(watcher, "missing", observedAt);
|
|
80423
|
+
watchers.delete(sessionKey4);
|
|
80424
|
+
knownTranscripts.delete(sessionKey4);
|
|
80425
|
+
}
|
|
80426
|
+
}
|
|
80427
|
+
function reconcilePersistedObservedSessions(seenLifecycleKeys, successfullyScannedSources, observedAt) {
|
|
80428
|
+
for (const [lifecycleKey, lifecycle] of persistedObservedSessions) {
|
|
80429
|
+
if (seenLifecycleKeys.has(lifecycleKey)) {
|
|
80430
|
+
lifecycle.missingAuthoritativePasses = 0;
|
|
80431
|
+
continue;
|
|
80432
|
+
}
|
|
80433
|
+
if (!successfullyScannedSources.has(lifecycle.seed.source))
|
|
80434
|
+
continue;
|
|
80435
|
+
lifecycle.missingAuthoritativePasses++;
|
|
80436
|
+
if (lifecycle.missingAuthoritativePasses < AUTHORITATIVE_MISSING_CONFIRMATION_COUNT || lifecycle.lifecycleNotification === "offline") {
|
|
80437
|
+
continue;
|
|
80438
|
+
}
|
|
80439
|
+
lifecycle.lifecycleNotification = "offline";
|
|
80440
|
+
const seedEvent = persistedSeedEvent(lifecycle.seed);
|
|
80441
|
+
pushInternalEvent({
|
|
80442
|
+
...seedEvent,
|
|
80443
|
+
id: `tail-lifecycle:${lifecycle.seed.source}:${lifecycle.seed.sourceSessionId}:offline:${observedAt}`,
|
|
80444
|
+
ts: observedAt,
|
|
80445
|
+
summary: INTERNAL_TAIL_SESSION_OFFLINE_SUMMARY,
|
|
80446
|
+
raw: { reason: "missing" }
|
|
80447
|
+
});
|
|
80448
|
+
persistedObservedSessions.delete(lifecycleKey);
|
|
79362
80449
|
}
|
|
79363
80450
|
}
|
|
79364
80451
|
async function refreshDiscovery(scope = "shallow", options = { pruneMissing: scope !== "hot" }) {
|
|
79365
80452
|
const allProcesses = [];
|
|
79366
80453
|
const cachedProcesses = lastDiscovery?.processes ?? [];
|
|
79367
80454
|
const seenSessionKeys = new Set;
|
|
80455
|
+
const seenObservedLifecycleKeys = new Set;
|
|
80456
|
+
const successfullyScannedSources = new Set;
|
|
79368
80457
|
const discoveryIssues = [];
|
|
79369
80458
|
const discoveryIssueKeys = new Set;
|
|
79370
80459
|
for (const source of sources) {
|
|
80460
|
+
let remainingInternalReconciliations = internalSubscribers.size > 0 ? INTERNAL_RECONCILE_SESSIONS_PER_SOURCE : 0;
|
|
79371
80461
|
let processes = [];
|
|
79372
80462
|
if (scope === "hot" && cachedProcesses.length > 0) {
|
|
79373
80463
|
processes = cachedProcesses.filter((proc) => proc.source === source.name);
|
|
@@ -79382,14 +80472,19 @@ async function refreshDiscovery(scope = "shallow", options = { pruneMissing: sco
|
|
|
79382
80472
|
let transcripts = [];
|
|
79383
80473
|
try {
|
|
79384
80474
|
transcripts = await source.discoverTranscripts(processes, scope);
|
|
80475
|
+
successfullyScannedSources.add(source.name);
|
|
79385
80476
|
} catch {
|
|
79386
80477
|
transcripts = [];
|
|
79387
80478
|
}
|
|
79388
|
-
for (const transcript of transcripts) {
|
|
80479
|
+
for (const transcript of [...transcripts].sort((left, right) => right.mtimeMs - left.mtimeMs)) {
|
|
79389
80480
|
const primary = processForTranscript(transcript, processes);
|
|
79390
80481
|
const transcriptPath = transcript.transcriptPath;
|
|
79391
80482
|
const sessionKey4 = sessionRegistryKey(transcript);
|
|
79392
80483
|
seenSessionKeys.add(sessionKey4);
|
|
80484
|
+
const sourceSessionId = transcript.sessionId?.trim();
|
|
80485
|
+
if (sourceSessionId) {
|
|
80486
|
+
seenObservedLifecycleKeys.add(observedSessionLifecycleKey(source.name, sourceSessionId));
|
|
80487
|
+
}
|
|
79393
80488
|
const prior = knownTranscripts.get(sessionKey4);
|
|
79394
80489
|
if (transcript.source !== "cursor" && prior && prior.transcriptPath !== transcriptPath) {
|
|
79395
80490
|
const issueKey = `${sessionKey4}\x00${prior.transcriptPath}\x00${transcriptPath}`;
|
|
@@ -79417,10 +80512,25 @@ async function refreshDiscovery(scope = "shallow", options = { pruneMissing: sco
|
|
|
79417
80512
|
offset: 0,
|
|
79418
80513
|
lineCounter: 0,
|
|
79419
80514
|
carry: "",
|
|
80515
|
+
decoder: new StringDecoder("utf8"),
|
|
79420
80516
|
emittedEventIds: new Set,
|
|
79421
|
-
state: {}
|
|
80517
|
+
state: {},
|
|
80518
|
+
lastPumpAt: 0,
|
|
80519
|
+
lastObservedChangeAt: Math.max(transcript.lastEventAt ?? 0, transcript.mtimeMs),
|
|
80520
|
+
lastKnownSize: transcript.size,
|
|
80521
|
+
lastKnownMtimeMs: transcript.mtimeMs,
|
|
80522
|
+
missingAuthoritativePasses: 0,
|
|
80523
|
+
staleObservations: 0,
|
|
80524
|
+
lifecycleNotification: "none",
|
|
80525
|
+
internalObserved: false,
|
|
80526
|
+
lastInternalEvent: null,
|
|
80527
|
+
pumpInFlight: null
|
|
79422
80528
|
};
|
|
79423
|
-
|
|
80529
|
+
const reconcileInternal = remainingInternalReconciliations > 0;
|
|
80530
|
+
if (reconcileInternal)
|
|
80531
|
+
remainingInternalReconciliations--;
|
|
80532
|
+
await seedTail(watcher, { reconcileInternal });
|
|
80533
|
+
applyPersistedObservedSeedToWatcher(watcher);
|
|
79424
80534
|
watchers.set(sessionKey4, watcher);
|
|
79425
80535
|
continue;
|
|
79426
80536
|
}
|
|
@@ -79428,21 +80538,33 @@ async function refreshDiscovery(scope = "shallow", options = { pruneMissing: sco
|
|
|
79428
80538
|
watcher.transcriptPath = transcriptPath;
|
|
79429
80539
|
watcher.lineCounter = 0;
|
|
79430
80540
|
watcher.carry = "";
|
|
80541
|
+
watcher.decoder = new StringDecoder("utf8");
|
|
79431
80542
|
watcher.emittedEventIds = new Set;
|
|
79432
80543
|
watcher.state = {};
|
|
79433
|
-
|
|
80544
|
+
watcher.internalObserved = false;
|
|
80545
|
+
watcher.lastInternalEvent = null;
|
|
80546
|
+
const reconcileInternal = remainingInternalReconciliations > 0;
|
|
80547
|
+
if (reconcileInternal)
|
|
80548
|
+
remainingInternalReconciliations--;
|
|
80549
|
+
await seedTail(watcher, { reconcileInternal });
|
|
80550
|
+
}
|
|
80551
|
+
applyPersistedObservedSeedToWatcher(watcher);
|
|
80552
|
+
if (transcript.mtimeMs > watcher.transcript.mtimeMs) {
|
|
80553
|
+
watcher.lastObservedChangeAt = Date.now();
|
|
80554
|
+
watcher.staleObservations = 0;
|
|
80555
|
+
watcher.lifecycleNotification = "none";
|
|
80556
|
+
if (watcher.source.parseFile)
|
|
80557
|
+
watcher.offset = 0;
|
|
79434
80558
|
}
|
|
79435
80559
|
watcher.process = primary;
|
|
79436
80560
|
watcher.transcript = transcript;
|
|
80561
|
+
watcher.missingAuthoritativePasses = 0;
|
|
79437
80562
|
}
|
|
79438
80563
|
}
|
|
79439
80564
|
if (options.pruneMissing) {
|
|
79440
|
-
|
|
79441
|
-
|
|
79442
|
-
|
|
79443
|
-
knownTranscripts.delete(sessionKey4);
|
|
79444
|
-
}
|
|
79445
|
-
}
|
|
80565
|
+
const observedAt = Date.now();
|
|
80566
|
+
reconcileMissingWatchers(seenSessionKeys, successfullyScannedSources, observedAt);
|
|
80567
|
+
reconcilePersistedObservedSessions(seenObservedLifecycleKeys, successfullyScannedSources, observedAt);
|
|
79446
80568
|
}
|
|
79447
80569
|
const allTranscripts = [...knownTranscripts.values()].sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
79448
80570
|
let scoutManaged = 0;
|
|
@@ -79486,7 +80608,7 @@ function scheduleDiscovery(scope, options = { pruneMissing: scope !== "hot" }) {
|
|
|
79486
80608
|
function ensureLoopRunning() {
|
|
79487
80609
|
if (!pollTimer) {
|
|
79488
80610
|
pollTimer = setInterval(() => {
|
|
79489
|
-
|
|
80611
|
+
pumpWatchersForCurrentDemand();
|
|
79490
80612
|
}, TAIL_POLL_INTERVAL_MS);
|
|
79491
80613
|
}
|
|
79492
80614
|
if (!hotDiscoveryTimer) {
|
|
@@ -79506,7 +80628,7 @@ function ensureLoopRunning() {
|
|
|
79506
80628
|
}
|
|
79507
80629
|
}
|
|
79508
80630
|
function stopLoopIfIdle() {
|
|
79509
|
-
if (subscribers.size > 0)
|
|
80631
|
+
if (subscribers.size > 0 || internalSubscribers.size > 0)
|
|
79510
80632
|
return;
|
|
79511
80633
|
if (pollTimer) {
|
|
79512
80634
|
clearInterval(pollTimer);
|
|
@@ -79525,6 +80647,7 @@ function stopLoopIfIdle() {
|
|
|
79525
80647
|
deepDiscoveryTimer = null;
|
|
79526
80648
|
}
|
|
79527
80649
|
watchers.clear();
|
|
80650
|
+
persistedObservedSessions.clear();
|
|
79528
80651
|
}
|
|
79529
80652
|
function normalizeTailDiscoveryOptions(input = false) {
|
|
79530
80653
|
if (typeof input === "boolean") {
|
|
@@ -79550,18 +80673,19 @@ async function refreshTailDiscovery(scope = "shallow") {
|
|
|
79550
80673
|
}
|
|
79551
80674
|
function subscribeTail(handler) {
|
|
79552
80675
|
subscribers.add(handler);
|
|
80676
|
+
startTailLoopForSubscriber();
|
|
80677
|
+
return () => {
|
|
80678
|
+
subscribers.delete(handler);
|
|
80679
|
+
stopLoopIfIdle();
|
|
80680
|
+
};
|
|
80681
|
+
}
|
|
80682
|
+
function startTailLoopForSubscriber() {
|
|
79553
80683
|
ensureLoopRunning();
|
|
79554
80684
|
if (watchers.size === 0) {
|
|
79555
|
-
runDiscovery("shallow", { pruneMissing: true }).then(() =>
|
|
80685
|
+
runDiscovery("shallow", { pruneMissing: true }).then(() => pumpWatchersForCurrentDemand()).catch(() => {});
|
|
79556
80686
|
} else {
|
|
79557
|
-
|
|
80687
|
+
pumpWatchersForCurrentDemand();
|
|
79558
80688
|
}
|
|
79559
|
-
return () => {
|
|
79560
|
-
subscribers.delete(handler);
|
|
79561
|
-
if (subscribers.size === 0) {
|
|
79562
|
-
stopLoopIfIdle();
|
|
79563
|
-
}
|
|
79564
|
-
};
|
|
79565
80689
|
}
|
|
79566
80690
|
function snapshotRecentEvents(limit = 500) {
|
|
79567
80691
|
return aggregateBuffer.slice(-limit);
|
|
@@ -79755,7 +80879,7 @@ async function readRecentTranscriptEvents(limit = 50, options) {
|
|
|
79755
80879
|
const lineLimit = options?.perTranscriptLineLimit ?? RECENT_TRANSCRIPT_LINES_PER_FILE;
|
|
79756
80880
|
const kinds = options?.kinds?.length ? new Set(options.kinds) : null;
|
|
79757
80881
|
const kindQuota = kinds ? Math.max(1, options?.perTranscriptKindLimit ?? limit) : undefined;
|
|
79758
|
-
const activeWatchers = [...watchers.values()].sort((left, right) => right.transcript.mtimeMs - left.transcript.mtimeMs).slice(0, transcriptReadLimit);
|
|
80882
|
+
const activeWatchers = [...watchers.values()].filter((watcher) => options?.since === undefined || watcher.transcript.mtimeMs >= options.since).sort((left, right) => right.transcript.mtimeMs - left.transcript.mtimeMs).slice(0, transcriptReadLimit);
|
|
79759
80883
|
for (const watcher of activeWatchers) {
|
|
79760
80884
|
seenTranscriptPaths.add(watcher.transcriptPath);
|
|
79761
80885
|
await appendWatcherTranscriptEvents(events2, seenEvents, watcher, {
|
|
@@ -79765,7 +80889,7 @@ async function readRecentTranscriptEvents(limit = 50, options) {
|
|
|
79765
80889
|
});
|
|
79766
80890
|
}
|
|
79767
80891
|
if (options?.discovery?.transcripts?.length) {
|
|
79768
|
-
const discoveryTranscripts = [...options.discovery.transcripts].filter((transcript) => !seenTranscriptPaths.has(transcript.transcriptPath)).sort((left, right) => right.mtimeMs - left.mtimeMs).slice(0, transcriptReadLimit);
|
|
80892
|
+
const discoveryTranscripts = [...options.discovery.transcripts].filter((transcript) => !seenTranscriptPaths.has(transcript.transcriptPath) && (options.since === undefined || transcript.mtimeMs >= options.since)).sort((left, right) => right.mtimeMs - left.mtimeMs).slice(0, Math.max(0, transcriptReadLimit - activeWatchers.length));
|
|
79769
80893
|
for (const transcript of discoveryTranscripts) {
|
|
79770
80894
|
const parsed = await parseTranscriptSessionEvents(transcript, options.discovery.processes, lineLimit, {
|
|
79771
80895
|
kinds,
|
|
@@ -79778,7 +80902,7 @@ async function readRecentTranscriptEvents(limit = 50, options) {
|
|
|
79778
80902
|
seenTranscriptPaths.add(transcript.transcriptPath);
|
|
79779
80903
|
}
|
|
79780
80904
|
}
|
|
79781
|
-
return events2.filter((event) => !kinds || kinds.has(event.kind)).sort((left, right) => right.ts - left.ts).slice(0, limit);
|
|
80905
|
+
return events2.filter((event) => (!kinds || kinds.has(event.kind)) && (options?.since === undefined || event.ts >= options.since)).sort((left, right) => right.ts - left.ts).slice(0, limit);
|
|
79782
80906
|
}
|
|
79783
80907
|
function normalizeTailSessionRef(value) {
|
|
79784
80908
|
const trimmed = value?.trim();
|
|
@@ -80105,7 +81229,7 @@ function buildObserveDataFromTail(transcript, events2, current) {
|
|
|
80105
81229
|
var HISTORY_SNAPSHOT_CACHE_LIMIT = 128;
|
|
80106
81230
|
var historySnapshotCache = new Map;
|
|
80107
81231
|
var OBSERVE_SUMMARY_TAIL_SIZE = 8;
|
|
80108
|
-
var SESSION_REF_LOOKUP_TTL_MS =
|
|
81232
|
+
var SESSION_REF_LOOKUP_TTL_MS = 60000;
|
|
80109
81233
|
var sessionRefLookupCache = null;
|
|
80110
81234
|
var AMBIGUOUS_TAIL_SESSION_REF = Symbol("ambiguous-tail-session-ref");
|
|
80111
81235
|
function normalizedComparableString2(value) {
|
|
@@ -80194,6 +81318,23 @@ function tailSessionRefTranscripts(discovery, normalizedRef, harness2) {
|
|
|
80194
81318
|
return refs.includes(normalizedRef);
|
|
80195
81319
|
});
|
|
80196
81320
|
}
|
|
81321
|
+
function bestTailSessionRefLookupEntry(transcripts, normalizedRef) {
|
|
81322
|
+
const matches = [];
|
|
81323
|
+
for (const transcript of transcripts) {
|
|
81324
|
+
const adapterType = adapterTypeFromTailSource(transcript.source);
|
|
81325
|
+
if (!adapterType || !supportsHistorySessionSnapshotForPath(transcript.transcriptPath, adapterType)) {
|
|
81326
|
+
continue;
|
|
81327
|
+
}
|
|
81328
|
+
matches.push({
|
|
81329
|
+
refId: normalizedRef,
|
|
81330
|
+
historyPath: transcript.transcriptPath,
|
|
81331
|
+
adapterType,
|
|
81332
|
+
mtimeMs: transcript.mtimeMs,
|
|
81333
|
+
size: transcript.size
|
|
81334
|
+
});
|
|
81335
|
+
}
|
|
81336
|
+
return matches.sort((left, right) => right.mtimeMs - left.mtimeMs)[0] ?? null;
|
|
81337
|
+
}
|
|
80197
81338
|
function hasAmbiguousTailHarness(transcripts) {
|
|
80198
81339
|
const sources2 = new Set(transcripts.map((transcript) => canonicalSessionHarness(transcript.source) ?? transcript.source.trim().toLowerCase()));
|
|
80199
81340
|
return sources2.size > 1;
|
|
@@ -80270,23 +81411,7 @@ async function findTailSessionRefLookupEntry(normalizedRef, harness2 = null) {
|
|
|
80270
81411
|
const transcripts = tailSessionRefTranscripts(discovery, normalizedRef, harness2);
|
|
80271
81412
|
if (!harness2 && hasAmbiguousTailHarness(transcripts))
|
|
80272
81413
|
return AMBIGUOUS_TAIL_SESSION_REF;
|
|
80273
|
-
|
|
80274
|
-
for (const transcript of transcripts) {
|
|
80275
|
-
const adapterType = adapterTypeFromTailSource(transcript.source);
|
|
80276
|
-
if (!adapterType || !supportsHistorySessionSnapshotForPath(transcript.transcriptPath, adapterType)) {
|
|
80277
|
-
continue;
|
|
80278
|
-
}
|
|
80279
|
-
matches.push({
|
|
80280
|
-
refId: normalizedRef,
|
|
80281
|
-
historyPath: transcript.transcriptPath,
|
|
80282
|
-
adapterType,
|
|
80283
|
-
mtimeMs: transcript.mtimeMs,
|
|
80284
|
-
size: transcript.size
|
|
80285
|
-
});
|
|
80286
|
-
}
|
|
80287
|
-
if (matches.length === 0)
|
|
80288
|
-
return null;
|
|
80289
|
-
return matches.sort((left, right) => right.mtimeMs - left.mtimeMs)[0] ?? null;
|
|
81414
|
+
return bestTailSessionRefLookupEntry(transcripts, normalizedRef);
|
|
80290
81415
|
}
|
|
80291
81416
|
function historyAdapterAlias(value) {
|
|
80292
81417
|
const normalized = value?.trim().toLowerCase();
|
|
@@ -81707,11 +82832,12 @@ async function loadSessionRefObservePayload(refId) {
|
|
|
81707
82832
|
return null;
|
|
81708
82833
|
}
|
|
81709
82834
|
let [discovery, brokerContext] = await Promise.all([
|
|
81710
|
-
|
|
82835
|
+
readScoutBrokerTailDiscovery().catch(() => null),
|
|
81711
82836
|
loadScoutBrokerContext().catch(() => null)
|
|
81712
82837
|
]);
|
|
81713
82838
|
let matchingTranscripts = discovery ? tailSessionRefTranscripts(discovery, normalizedRef, requestedHarness) : [];
|
|
81714
|
-
const
|
|
82839
|
+
const discoveredHistoryEntry = bestTailSessionRefLookupEntry(matchingTranscripts, normalizedRef);
|
|
82840
|
+
const cachedHistoryEntry = !discoveredHistoryEntry && matchingTranscripts.length === 0 && (!requestedHarness || requestedHarness === "claude") ? sessionRefLookup().get(normalizedRef) ?? null : null;
|
|
81715
82841
|
const matchingAgents = queryAgents(200).filter((agent) => normalizeSessionRefId(agent.harnessSessionId) === normalizedRef && sessionHarnessMatches(requestedHarness, agent.harness));
|
|
81716
82842
|
const matchingAgentOwners = new Set(matchingAgents.map((agent) => agent.id));
|
|
81717
82843
|
if (matchingAgentOwners.size > 1)
|
|
@@ -81778,7 +82904,7 @@ async function loadSessionRefObservePayload(refId) {
|
|
|
81778
82904
|
}
|
|
81779
82905
|
if (!requestedHarness && hasAmbiguousTailHarness(matchingTranscripts))
|
|
81780
82906
|
return null;
|
|
81781
|
-
const tailHistoryEntry = await findTailSessionRefLookupEntry(normalizedRef, requestedHarness);
|
|
82907
|
+
const tailHistoryEntry = discoveredHistoryEntry ?? await findTailSessionRefLookupEntry(normalizedRef, requestedHarness);
|
|
81782
82908
|
if (tailHistoryEntry === AMBIGUOUS_TAIL_SESSION_REF)
|
|
81783
82909
|
return null;
|
|
81784
82910
|
const historyEntry = tailHistoryEntry ?? (requestedHarness === "claude" || !requestedHarness && (!discovery || matchingTranscripts.length === 0) ? cachedHistoryEntry : null);
|
|
@@ -86450,6 +87576,7 @@ var MAX_EVENTS_PER_SESSION = 200;
|
|
|
86450
87576
|
var sessions4 = new Map;
|
|
86451
87577
|
var hosts = new Map;
|
|
86452
87578
|
var sessionSubscribers = new Map;
|
|
87579
|
+
var hostCommandWaiters = new Map;
|
|
86453
87580
|
var nextHostPollId = 1;
|
|
86454
87581
|
var DEFAULT_VOICE_SETTINGS = {
|
|
86455
87582
|
preference: "auto",
|
|
@@ -86464,6 +87591,9 @@ function registerScoutVoiceHost(input) {
|
|
|
86464
87591
|
const now = Date.now();
|
|
86465
87592
|
const previous = hosts.get(hostId);
|
|
86466
87593
|
const instanceId = input.instanceId?.trim() || null;
|
|
87594
|
+
if (previous && previous.instanceId !== instanceId) {
|
|
87595
|
+
finishScoutVoiceHostCommandWaiter(hostId, null);
|
|
87596
|
+
}
|
|
86467
87597
|
const settings = mergeVoiceSettings(previous?.settings ?? DEFAULT_VOICE_SETTINGS, input.settings);
|
|
86468
87598
|
hosts.set(hostId, {
|
|
86469
87599
|
hostId,
|
|
@@ -86545,6 +87675,7 @@ function awaitScoutVoiceHostCommand(hostId, timeoutMs = 25000, instanceId, signa
|
|
|
86545
87675
|
if (host.instanceId !== normalizedInstanceId) {
|
|
86546
87676
|
return Promise.resolve({ command: null });
|
|
86547
87677
|
}
|
|
87678
|
+
finishScoutVoiceHostCommandWaiter(normalizedHostId, null);
|
|
86548
87679
|
const pollId = nextHostPollId++;
|
|
86549
87680
|
host.activePollId = pollId;
|
|
86550
87681
|
touchScoutVoiceHost(normalizedHostId);
|
|
@@ -86559,40 +87690,37 @@ function awaitScoutVoiceHostCommand(hostId, timeoutMs = 25000, instanceId, signa
|
|
|
86559
87690
|
return Promise.resolve({ command: null });
|
|
86560
87691
|
}
|
|
86561
87692
|
return new Promise((resolve23) => {
|
|
86562
|
-
const startedAt = Date.now();
|
|
86563
87693
|
let settled = false;
|
|
87694
|
+
let timeout = null;
|
|
86564
87695
|
const finish = (command) => {
|
|
86565
87696
|
if (settled)
|
|
86566
87697
|
return;
|
|
86567
87698
|
settled = true;
|
|
86568
|
-
|
|
87699
|
+
if (timeout)
|
|
87700
|
+
clearTimeout(timeout);
|
|
86569
87701
|
signal?.removeEventListener("abort", abort);
|
|
87702
|
+
const waiter = hostCommandWaiters.get(normalizedHostId);
|
|
87703
|
+
if (waiter?.pollId === pollId)
|
|
87704
|
+
hostCommandWaiters.delete(normalizedHostId);
|
|
86570
87705
|
const current = hosts.get(normalizedHostId);
|
|
86571
87706
|
if (current?.activePollId === pollId)
|
|
86572
87707
|
current.activePollId = null;
|
|
86573
87708
|
resolve23({ command });
|
|
86574
87709
|
};
|
|
86575
87710
|
const abort = () => finish(null);
|
|
86576
|
-
|
|
87711
|
+
hostCommandWaiters.set(normalizedHostId, {
|
|
87712
|
+
pollId,
|
|
87713
|
+
instanceId: normalizedInstanceId,
|
|
87714
|
+
finish
|
|
87715
|
+
});
|
|
87716
|
+
timeout = setTimeout(() => {
|
|
86577
87717
|
const current = hosts.get(normalizedHostId);
|
|
86578
|
-
if (
|
|
86579
|
-
|
|
86580
|
-
return;
|
|
86581
|
-
}
|
|
86582
|
-
if (current.instanceId !== normalizedInstanceId || current.activePollId !== pollId) {
|
|
86583
|
-
finish(null);
|
|
86584
|
-
return;
|
|
86585
|
-
}
|
|
86586
|
-
current.lastSeenAt = Date.now();
|
|
86587
|
-
if (current.pendingCommands.length > 0) {
|
|
86588
|
-
const command = current.pendingCommands.shift() ?? null;
|
|
86589
|
-
finish(command);
|
|
86590
|
-
return;
|
|
87718
|
+
if (current && current.instanceId === normalizedInstanceId && current.activePollId === pollId) {
|
|
87719
|
+
current.lastSeenAt = Date.now();
|
|
86591
87720
|
}
|
|
86592
|
-
|
|
86593
|
-
|
|
86594
|
-
|
|
86595
|
-
}, 100);
|
|
87721
|
+
finish(null);
|
|
87722
|
+
}, timeoutMs);
|
|
87723
|
+
timeout.unref?.();
|
|
86596
87724
|
signal?.addEventListener("abort", abort, { once: true });
|
|
86597
87725
|
if (signal?.aborted)
|
|
86598
87726
|
abort();
|
|
@@ -86813,6 +87941,22 @@ function queueHostCommand(hostId, command) {
|
|
|
86813
87941
|
}
|
|
86814
87942
|
host.pendingCommands.push(command);
|
|
86815
87943
|
host.lastSeenAt = Date.now();
|
|
87944
|
+
deliverPendingScoutVoiceHostCommand(host);
|
|
87945
|
+
}
|
|
87946
|
+
function finishScoutVoiceHostCommandWaiter(hostId, command) {
|
|
87947
|
+
hostCommandWaiters.get(hostId)?.finish(command);
|
|
87948
|
+
}
|
|
87949
|
+
function deliverPendingScoutVoiceHostCommand(host) {
|
|
87950
|
+
const waiter = hostCommandWaiters.get(host.hostId);
|
|
87951
|
+
if (!waiter)
|
|
87952
|
+
return;
|
|
87953
|
+
if (waiter.instanceId !== host.instanceId || waiter.pollId !== host.activePollId) {
|
|
87954
|
+
waiter.finish(null);
|
|
87955
|
+
return;
|
|
87956
|
+
}
|
|
87957
|
+
const command = host.pendingCommands.shift();
|
|
87958
|
+
if (command)
|
|
87959
|
+
waiter.finish(command);
|
|
86816
87960
|
}
|
|
86817
87961
|
function dispatchSessionCommand(session3, command) {
|
|
86818
87962
|
const hostId = session3.assignedHostId ?? pickLiveVoiceHost()?.hostId;
|
|
@@ -87226,6 +88370,127 @@ function defaultVoiceForModel(providers2, modelId2) {
|
|
|
87226
88370
|
return firstNonEmptyString7(provider?.env.VOX_MLX_AUDIO_TTS_DEFAULT_VOICE);
|
|
87227
88371
|
}
|
|
87228
88372
|
|
|
88373
|
+
// packages/web/server/nvidia-speech.ts
|
|
88374
|
+
var NVIDIA_MAGPIE_SPEECH_URL = "https://877104f7-e885-42b9-8de8-f6e4c6303969.invocation.api.nvcf.nvidia.com/v1/audio/synthesize";
|
|
88375
|
+
var NVIDIA_MAGPIE_VOICES_URL = "https://877104f7-e885-42b9-8de8-f6e4c6303969.invocation.api.nvcf.nvidia.com/v1/audio/list_voices";
|
|
88376
|
+
var NVIDIA_MAGPIE_MODEL = "magpie-tts-multilingual";
|
|
88377
|
+
var NVIDIA_MAGPIE_DEFAULT_VOICE = "Magpie-Multilingual.EN-US.Aria";
|
|
88378
|
+
var NVIDIA_MAGPIE_TIMEOUT_MS = 60000;
|
|
88379
|
+
var NVIDIA_MAGPIE_MAX_CHARACTERS = 2000;
|
|
88380
|
+
function resolveNvidiaApiKey(env = process.env) {
|
|
88381
|
+
return firstNonEmptyString8(env.NV_API_KEY, env.NVIDIA_API_KEY);
|
|
88382
|
+
}
|
|
88383
|
+
function isNvidiaMagpieSpeechModel(modelId2) {
|
|
88384
|
+
return modelId2?.trim() === NVIDIA_MAGPIE_MODEL;
|
|
88385
|
+
}
|
|
88386
|
+
async function listNvidiaMagpieVoices(input) {
|
|
88387
|
+
const timeout = AbortSignal.timeout(NVIDIA_MAGPIE_TIMEOUT_MS);
|
|
88388
|
+
const signal = input.signal ? AbortSignal.any([input.signal, timeout]) : timeout;
|
|
88389
|
+
const response = await fetch(input.endpoint ?? NVIDIA_MAGPIE_VOICES_URL, {
|
|
88390
|
+
method: "GET",
|
|
88391
|
+
headers: { authorization: `Bearer ${input.apiKey}` },
|
|
88392
|
+
signal
|
|
88393
|
+
});
|
|
88394
|
+
if (!response.ok) {
|
|
88395
|
+
const detail = await response.text().catch(() => "");
|
|
88396
|
+
throw new Error(`NVIDIA Magpie voice discovery failed (${response.status})${detail ? `: ${detail.slice(0, 200)}` : ""}`);
|
|
88397
|
+
}
|
|
88398
|
+
const voices = parseNvidiaMagpieVoices(await response.json());
|
|
88399
|
+
if (voices.length === 0) {
|
|
88400
|
+
throw new Error("NVIDIA Magpie voice discovery returned no voices.");
|
|
88401
|
+
}
|
|
88402
|
+
return voices;
|
|
88403
|
+
}
|
|
88404
|
+
async function synthesizeNvidiaMagpieSpeech(input) {
|
|
88405
|
+
const text4 = Array.from(input.text).slice(0, NVIDIA_MAGPIE_MAX_CHARACTERS).join("");
|
|
88406
|
+
const voiceId = input.voiceId?.trim() || NVIDIA_MAGPIE_DEFAULT_VOICE;
|
|
88407
|
+
const language = magpieLanguageForVoice(voiceId);
|
|
88408
|
+
const form = new FormData;
|
|
88409
|
+
form.set("text", text4);
|
|
88410
|
+
form.set("language", language);
|
|
88411
|
+
form.set("voice", voiceId);
|
|
88412
|
+
form.set("encoding", "LINEAR_PCM");
|
|
88413
|
+
form.set("sample_rate_hz", "44100");
|
|
88414
|
+
const timeout = AbortSignal.timeout(NVIDIA_MAGPIE_TIMEOUT_MS);
|
|
88415
|
+
const signal = input.signal ? AbortSignal.any([input.signal, timeout]) : timeout;
|
|
88416
|
+
const response = await fetch(input.endpoint ?? NVIDIA_MAGPIE_SPEECH_URL, {
|
|
88417
|
+
method: "POST",
|
|
88418
|
+
headers: { authorization: `Bearer ${input.apiKey}` },
|
|
88419
|
+
body: form,
|
|
88420
|
+
signal
|
|
88421
|
+
});
|
|
88422
|
+
if (!response.ok) {
|
|
88423
|
+
const detail = await response.text().catch(() => "");
|
|
88424
|
+
throw new Error(`NVIDIA Magpie speech failed (${response.status})${detail ? `: ${detail.slice(0, 200)}` : ""}`);
|
|
88425
|
+
}
|
|
88426
|
+
const audio = new Uint8Array(await response.arrayBuffer());
|
|
88427
|
+
if (audio.byteLength === 0) {
|
|
88428
|
+
throw new Error("NVIDIA Magpie returned no audio.");
|
|
88429
|
+
}
|
|
88430
|
+
const responseContentType = response.headers.get("content-type")?.split(";")[0];
|
|
88431
|
+
return {
|
|
88432
|
+
contentType: responseContentType?.startsWith("audio/") ? responseContentType : "audio/wav",
|
|
88433
|
+
audioBase64: Buffer.from(audio).toString("base64"),
|
|
88434
|
+
modelId: NVIDIA_MAGPIE_MODEL,
|
|
88435
|
+
voiceId,
|
|
88436
|
+
audioBytes: audio.byteLength
|
|
88437
|
+
};
|
|
88438
|
+
}
|
|
88439
|
+
function magpieLanguageForVoice(voiceId) {
|
|
88440
|
+
const locale = magpieLocaleSegment(voiceId);
|
|
88441
|
+
if (!locale)
|
|
88442
|
+
return "en-US";
|
|
88443
|
+
const [language, region] = locale.split("-");
|
|
88444
|
+
return `${language.toLowerCase()}-${region.toUpperCase()}`;
|
|
88445
|
+
}
|
|
88446
|
+
function parseNvidiaMagpieVoices(value) {
|
|
88447
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
88448
|
+
return [];
|
|
88449
|
+
const ids = new Set;
|
|
88450
|
+
for (const group of Object.values(value)) {
|
|
88451
|
+
if (!group || typeof group !== "object" || Array.isArray(group))
|
|
88452
|
+
continue;
|
|
88453
|
+
const voices = group.voices;
|
|
88454
|
+
if (!Array.isArray(voices))
|
|
88455
|
+
continue;
|
|
88456
|
+
for (const voice of voices) {
|
|
88457
|
+
if (typeof voice !== "string")
|
|
88458
|
+
continue;
|
|
88459
|
+
const id = voice.trim();
|
|
88460
|
+
if (id)
|
|
88461
|
+
ids.add(id);
|
|
88462
|
+
}
|
|
88463
|
+
}
|
|
88464
|
+
return Array.from(ids, voiceDetails).sort((left, right) => left.language.localeCompare(right.language) || left.name.localeCompare(right.name) || left.id.localeCompare(right.id));
|
|
88465
|
+
}
|
|
88466
|
+
function voiceDetails(id) {
|
|
88467
|
+
const parts = id.split(".");
|
|
88468
|
+
const language = magpieLanguageForVoice(id);
|
|
88469
|
+
const localeIndex = parts.findIndex(isLocaleSegment);
|
|
88470
|
+
const nameParts = localeIndex >= 0 ? parts.slice(localeIndex + 1) : [];
|
|
88471
|
+
const name2 = nameParts.length > 0 ? nameParts.join(" \xB7 ") : parts.at(-1) || id;
|
|
88472
|
+
return {
|
|
88473
|
+
id,
|
|
88474
|
+
name: name2,
|
|
88475
|
+
language,
|
|
88476
|
+
isDefault: id === NVIDIA_MAGPIE_DEFAULT_VOICE
|
|
88477
|
+
};
|
|
88478
|
+
}
|
|
88479
|
+
function magpieLocaleSegment(voiceId) {
|
|
88480
|
+
return voiceId.split(".").find(isLocaleSegment);
|
|
88481
|
+
}
|
|
88482
|
+
function isLocaleSegment(value) {
|
|
88483
|
+
return /^[a-z]{2,3}-[a-z]{2}$/i.test(value);
|
|
88484
|
+
}
|
|
88485
|
+
function firstNonEmptyString8(...values) {
|
|
88486
|
+
for (const value of values) {
|
|
88487
|
+
const trimmed = value?.trim();
|
|
88488
|
+
if (trimmed)
|
|
88489
|
+
return trimmed;
|
|
88490
|
+
}
|
|
88491
|
+
return;
|
|
88492
|
+
}
|
|
88493
|
+
|
|
87229
88494
|
// packages/web/server/scout-voice.ts
|
|
87230
88495
|
var SCOUT_VOICE_CLIENT_ID = "openscout-web";
|
|
87231
88496
|
var DEFAULT_SCOUT_VOICE_ASR_URL = "http://127.0.0.1:43115";
|
|
@@ -87268,14 +88533,16 @@ async function getScoutSpeechCatalog(input = {}) {
|
|
|
87268
88533
|
let models = [];
|
|
87269
88534
|
let voices = [];
|
|
87270
88535
|
let source = "fallback";
|
|
87271
|
-
|
|
87272
|
-
|
|
87273
|
-
|
|
87274
|
-
|
|
87275
|
-
|
|
87276
|
-
|
|
87277
|
-
|
|
87278
|
-
|
|
88536
|
+
if (requestedModelId !== NVIDIA_MAGPIE_MODEL) {
|
|
88537
|
+
try {
|
|
88538
|
+
[models, voices] = await Promise.all([
|
|
88539
|
+
listVoxSpeechModels(input.signal),
|
|
88540
|
+
listVoxSpeechVoices(requestedModelId, input.signal)
|
|
88541
|
+
]);
|
|
88542
|
+
if (models.length > 0)
|
|
88543
|
+
source = "vox";
|
|
88544
|
+
} catch {}
|
|
88545
|
+
}
|
|
87279
88546
|
const fallback = fallbackScoutSpeechCatalog(requestedModelId, defaults);
|
|
87280
88547
|
for (const model2 of fallback.models) {
|
|
87281
88548
|
if (!models.some((candidate) => candidate.id === model2.id)) {
|
|
@@ -87289,6 +88556,25 @@ async function getScoutSpeechCatalog(input = {}) {
|
|
|
87289
88556
|
models = models.map((model2) => model2.provider === "openai" ? { ...model2, available: true } : model2);
|
|
87290
88557
|
voices = voices.map((voice) => voice.provider === "openai" ? { ...voice, available: true } : voice);
|
|
87291
88558
|
}
|
|
88559
|
+
if (input.directNvidiaAvailable || input.directNvidiaApiKey) {
|
|
88560
|
+
models = models.map((model2) => model2.provider === "nvidia" ? { ...model2, available: true } : model2);
|
|
88561
|
+
voices = voices.map((voice) => voice.provider === "nvidia" ? { ...voice, available: true } : voice);
|
|
88562
|
+
}
|
|
88563
|
+
if (input.directNvidiaApiKey && requestedModelId === NVIDIA_MAGPIE_MODEL) {
|
|
88564
|
+
try {
|
|
88565
|
+
const discovered = await listNvidiaMagpieVoices({
|
|
88566
|
+
apiKey: input.directNvidiaApiKey,
|
|
88567
|
+
signal: input.signal
|
|
88568
|
+
});
|
|
88569
|
+
voices = discovered.map((voice) => ({
|
|
88570
|
+
...voice,
|
|
88571
|
+
provider: "nvidia",
|
|
88572
|
+
modelId: NVIDIA_MAGPIE_MODEL,
|
|
88573
|
+
available: true
|
|
88574
|
+
}));
|
|
88575
|
+
source = "nvidia-developer-inference";
|
|
88576
|
+
} catch {}
|
|
88577
|
+
}
|
|
87292
88578
|
return {
|
|
87293
88579
|
defaultModelId: defaults.modelId,
|
|
87294
88580
|
...defaults.voiceId ? { defaultVoiceId: defaults.voiceId } : {},
|
|
@@ -87300,7 +88586,8 @@ async function getScoutSpeechCatalog(input = {}) {
|
|
|
87300
88586
|
function fallbackScoutSpeechCatalog(modelId2, defaults = resolveScoutSpeechDefaults()) {
|
|
87301
88587
|
const models = [
|
|
87302
88588
|
{ id: "gpt-4o-mini-tts", name: "GPT-4o mini TTS", provider: "openai", available: true },
|
|
87303
|
-
{ id: "eleven_multilingual_v2", name: "Eleven Multilingual v2", provider: "elevenlabs", available: true }
|
|
88589
|
+
{ id: "eleven_multilingual_v2", name: "Eleven Multilingual v2", provider: "elevenlabs", available: true },
|
|
88590
|
+
{ id: NVIDIA_MAGPIE_MODEL, name: "Magpie TTS Multilingual", provider: "nvidia", available: true }
|
|
87304
88591
|
];
|
|
87305
88592
|
const openAIVoices = ["alloy", "ash", "ballad", "cedar", "coral", "echo", "fable", "marin", "nova", "onyx", "sage", "shimmer", "verse"].map((id) => ({
|
|
87306
88593
|
id,
|
|
@@ -87318,11 +88605,20 @@ function fallbackScoutSpeechCatalog(modelId2, defaults = resolveScoutSpeechDefau
|
|
|
87318
88605
|
available: true,
|
|
87319
88606
|
isDefault: true
|
|
87320
88607
|
}];
|
|
88608
|
+
const nvidiaVoices = [{
|
|
88609
|
+
id: NVIDIA_MAGPIE_DEFAULT_VOICE,
|
|
88610
|
+
name: "Aria",
|
|
88611
|
+
language: "en-US",
|
|
88612
|
+
provider: "nvidia",
|
|
88613
|
+
modelId: NVIDIA_MAGPIE_MODEL,
|
|
88614
|
+
available: true,
|
|
88615
|
+
isDefault: true
|
|
88616
|
+
}];
|
|
87321
88617
|
return {
|
|
87322
88618
|
defaultModelId: defaults.modelId,
|
|
87323
88619
|
...defaults.voiceId ? { defaultVoiceId: defaults.voiceId } : {},
|
|
87324
88620
|
models,
|
|
87325
|
-
voices: modelId2 === "eleven_multilingual_v2" ? elevenLabsVoices : openAIVoices,
|
|
88621
|
+
voices: modelId2 === "eleven_multilingual_v2" ? elevenLabsVoices : modelId2 === NVIDIA_MAGPIE_MODEL ? nvidiaVoices : openAIVoices,
|
|
87326
88622
|
source: "fallback"
|
|
87327
88623
|
};
|
|
87328
88624
|
}
|
|
@@ -87337,9 +88633,9 @@ function createScoutVoiceAsrClient(probeTimeout) {
|
|
|
87337
88633
|
});
|
|
87338
88634
|
}
|
|
87339
88635
|
function resolveScoutVoiceAsrUrl(env = process.env) {
|
|
87340
|
-
return
|
|
88636
|
+
return firstNonEmptyString9(env.OPENSCOUT_VOICE_ASR_URL, env.OPENSCOUT_VOICE_BRIDGE_URL, env.VOX_COMPANION_URL) ?? DEFAULT_SCOUT_VOICE_ASR_URL;
|
|
87341
88637
|
}
|
|
87342
|
-
function
|
|
88638
|
+
function firstNonEmptyString9(...values) {
|
|
87343
88639
|
for (const value of values) {
|
|
87344
88640
|
const trimmed = value?.trim();
|
|
87345
88641
|
if (trimmed)
|
|
@@ -87528,9 +88824,9 @@ class ScoutRealtimeVoiceAdmission {
|
|
|
87528
88824
|
}
|
|
87529
88825
|
function resolveScoutRealtimeVoiceConfig(env = process.env) {
|
|
87530
88826
|
return {
|
|
87531
|
-
model:
|
|
87532
|
-
voice:
|
|
87533
|
-
instructions:
|
|
88827
|
+
model: firstNonEmptyString10(env.OPENSCOUT_REALTIME_MODEL) ?? DEFAULT_REALTIME_MODEL,
|
|
88828
|
+
voice: firstNonEmptyString10(env.OPENSCOUT_REALTIME_VOICE) ?? DEFAULT_REALTIME_VOICE,
|
|
88829
|
+
instructions: firstNonEmptyString10(env.OPENSCOUT_REALTIME_INSTRUCTIONS) ?? SCOUT_REALTIME_INSTRUCTIONS
|
|
87534
88830
|
};
|
|
87535
88831
|
}
|
|
87536
88832
|
function scoutRealtimeVoiceEnvironmentOverride(env = process.env) {
|
|
@@ -87668,7 +88964,7 @@ function positiveInteger3(value, fallback) {
|
|
|
87668
88964
|
function secondsUntil(timestamp, now) {
|
|
87669
88965
|
return Math.max(1, Math.ceil((timestamp - now) / 1000));
|
|
87670
88966
|
}
|
|
87671
|
-
function
|
|
88967
|
+
function firstNonEmptyString10(value) {
|
|
87672
88968
|
const trimmed = value?.trim();
|
|
87673
88969
|
return trimmed || undefined;
|
|
87674
88970
|
}
|
|
@@ -88035,10 +89331,13 @@ function mountScoutVoiceRoutes(app, deps = {}) {
|
|
|
88035
89331
|
const directOpenAIAvailable = Boolean(await deps.resolveOpenAIApiKey?.().catch(() => {
|
|
88036
89332
|
return;
|
|
88037
89333
|
}) ?? process.env.OPENAI_API_KEY?.trim());
|
|
89334
|
+
const directNvidiaApiKey = resolveNvidiaApiKey();
|
|
88038
89335
|
return c.json(await getScoutSpeechCatalog({
|
|
88039
89336
|
modelId: c.req.query("modelId"),
|
|
88040
89337
|
signal: c.req.raw.signal,
|
|
88041
|
-
directOpenAIAvailable
|
|
89338
|
+
directOpenAIAvailable,
|
|
89339
|
+
directNvidiaAvailable: Boolean(directNvidiaApiKey),
|
|
89340
|
+
directNvidiaApiKey
|
|
88042
89341
|
}));
|
|
88043
89342
|
});
|
|
88044
89343
|
app.post("/api/voice/engage", async (c) => {
|
|
@@ -88254,6 +89553,28 @@ function mountScoutVoiceRoutes(app, deps = {}) {
|
|
|
88254
89553
|
if (speechTiming === null) {
|
|
88255
89554
|
return c.json({ error: "speechTiming is invalid" }, 400);
|
|
88256
89555
|
}
|
|
89556
|
+
const defaults = resolveScoutSpeechDefaults();
|
|
89557
|
+
const requestedModelId = body.modelId ?? defaults.modelId;
|
|
89558
|
+
if (isNvidiaMagpieSpeechModel(requestedModelId)) {
|
|
89559
|
+
const nvidiaApiKey = resolveNvidiaApiKey();
|
|
89560
|
+
if (!nvidiaApiKey) {
|
|
89561
|
+
return c.json({ error: "NV_API_KEY is required for hosted NVIDIA Developer Inference." }, 503);
|
|
89562
|
+
}
|
|
89563
|
+
try {
|
|
89564
|
+
return c.json({
|
|
89565
|
+
...await synthesizeNvidiaMagpieSpeech({
|
|
89566
|
+
text: text4,
|
|
89567
|
+
apiKey: nvidiaApiKey,
|
|
89568
|
+
voiceId: body.voiceId,
|
|
89569
|
+
signal: c.req.raw.signal
|
|
89570
|
+
}),
|
|
89571
|
+
route: "nvidia-developer-inference"
|
|
89572
|
+
});
|
|
89573
|
+
} catch (error) {
|
|
89574
|
+
const message = error instanceof Error ? error.message : "NVIDIA Magpie speech failed";
|
|
89575
|
+
return c.json({ error: message }, 503);
|
|
89576
|
+
}
|
|
89577
|
+
}
|
|
88257
89578
|
try {
|
|
88258
89579
|
return c.json(await synthesizeScoutSpeech({
|
|
88259
89580
|
text: text4,
|
|
@@ -88271,13 +89592,12 @@ function mountScoutVoiceRoutes(app, deps = {}) {
|
|
|
88271
89592
|
return;
|
|
88272
89593
|
}) ?? process.env.OPENAI_API_KEY?.trim();
|
|
88273
89594
|
if (apiKey && !c.req.raw.signal.aborted) {
|
|
88274
|
-
const defaults = resolveScoutSpeechDefaults();
|
|
88275
89595
|
try {
|
|
88276
89596
|
return c.json({
|
|
88277
89597
|
...await synthesizeOpenAISpeech({
|
|
88278
89598
|
text: text4,
|
|
88279
89599
|
apiKey,
|
|
88280
|
-
modelId:
|
|
89600
|
+
modelId: requestedModelId,
|
|
88281
89601
|
voiceId: body.voiceId ?? defaults.voiceId,
|
|
88282
89602
|
speed: body.speed,
|
|
88283
89603
|
instructions: optionalString(body.instructions),
|
|
@@ -89300,8 +90620,8 @@ function normalizeExistingPath(value) {
|
|
|
89300
90620
|
return null;
|
|
89301
90621
|
}
|
|
89302
90622
|
try {
|
|
89303
|
-
const
|
|
89304
|
-
return
|
|
90623
|
+
const stat11 = statSync21(absolute);
|
|
90624
|
+
return stat11.isDirectory() ? absolute : dirname37(absolute);
|
|
89305
90625
|
} catch {
|
|
89306
90626
|
return null;
|
|
89307
90627
|
}
|
|
@@ -90050,8 +91370,8 @@ async function resolveTrustedMaterialPath(work, materialId) {
|
|
|
90050
91370
|
if (!pathInsideRoot(realPath, realRoot)) {
|
|
90051
91371
|
return { ok: false, status: 403, error: "material path is outside its trusted root" };
|
|
90052
91372
|
}
|
|
90053
|
-
const
|
|
90054
|
-
if (!
|
|
91373
|
+
const stat11 = statSync21(realPath);
|
|
91374
|
+
if (!stat11.isFile()) {
|
|
90055
91375
|
return { ok: false, status: 415, error: "material is not a file" };
|
|
90056
91376
|
}
|
|
90057
91377
|
return { ok: true, material, realPath };
|
|
@@ -90065,12 +91385,12 @@ async function readWorkMaterialRaw(work, materialId) {
|
|
|
90065
91385
|
return resolved;
|
|
90066
91386
|
}
|
|
90067
91387
|
try {
|
|
90068
|
-
const
|
|
91388
|
+
const stat11 = statSync21(resolved.realPath);
|
|
90069
91389
|
return {
|
|
90070
91390
|
ok: true,
|
|
90071
91391
|
realPath: resolved.realPath,
|
|
90072
91392
|
mediaType: materialMediaType(resolved.realPath),
|
|
90073
|
-
sizeBytes:
|
|
91393
|
+
sizeBytes: stat11.size
|
|
90074
91394
|
};
|
|
90075
91395
|
} catch {
|
|
90076
91396
|
return { ok: false, status: 404, error: "material could not be read" };
|
|
@@ -90100,8 +91420,8 @@ async function readWorkMaterialContent(work, materialId) {
|
|
|
90100
91420
|
if (!pathInsideRoot(realPath, realRoot)) {
|
|
90101
91421
|
return { ok: false, status: 403, error: "material path is outside its trusted root" };
|
|
90102
91422
|
}
|
|
90103
|
-
const
|
|
90104
|
-
if (!
|
|
91423
|
+
const stat11 = statSync21(realPath);
|
|
91424
|
+
if (!stat11.isFile()) {
|
|
90105
91425
|
return { ok: false, status: 415, error: "material is not a file" };
|
|
90106
91426
|
}
|
|
90107
91427
|
const buffer = readFileSync29(realPath);
|
|
@@ -90133,7 +91453,7 @@ async function readWorkMaterialContent(work, materialId) {
|
|
|
90133
91453
|
|
|
90134
91454
|
// packages/web/server/plan-documents.ts
|
|
90135
91455
|
import { createHash as createHash9 } from "crypto";
|
|
90136
|
-
import { readdir as
|
|
91456
|
+
import { readdir as readdir5, readFile as readFile17, stat as stat11 } from "fs/promises";
|
|
90137
91457
|
import { homedir as homedir49 } from "os";
|
|
90138
91458
|
import { basename as basename25, isAbsolute as isAbsolute10, join as join65, relative as relative8, resolve as resolve27 } from "path";
|
|
90139
91459
|
var HOME3 = homedir49();
|
|
@@ -90216,7 +91536,7 @@ async function walkMarkdownFiles(directory, remaining = { count: MAX_FILES_PER_R
|
|
|
90216
91536
|
return [];
|
|
90217
91537
|
let entries2;
|
|
90218
91538
|
try {
|
|
90219
|
-
entries2 = await
|
|
91539
|
+
entries2 = await readdir5(directory, { withFileTypes: true });
|
|
90220
91540
|
} catch (error) {
|
|
90221
91541
|
if (error.code === "ENOENT")
|
|
90222
91542
|
return [];
|
|
@@ -90249,7 +91569,7 @@ async function discoverPlanFiles(root) {
|
|
|
90249
91569
|
const fromPlanDirs = (await Promise.all(PLAN_SUBDIRECTORIES.map((subdir) => walkMarkdownFiles(join65(root.root, subdir))))).flat();
|
|
90250
91570
|
let directPlanFiles = [];
|
|
90251
91571
|
try {
|
|
90252
|
-
const entries2 = await
|
|
91572
|
+
const entries2 = await readdir5(root.root, { withFileTypes: true });
|
|
90253
91573
|
directPlanFiles = entries2.filter((entry) => entry.isFile() && /\.plan\.md$/i.test(entry.name)).map((entry) => join65(root.root, entry.name));
|
|
90254
91574
|
} catch {
|
|
90255
91575
|
directPlanFiles = [];
|
|
@@ -90432,7 +91752,7 @@ function idForPlan(root, filePath) {
|
|
|
90432
91752
|
return `plan-doc:${hash}`;
|
|
90433
91753
|
}
|
|
90434
91754
|
async function readPlanDocument(root, filePath) {
|
|
90435
|
-
const fileStats = await
|
|
91755
|
+
const fileStats = await stat11(filePath).catch(() => null);
|
|
90436
91756
|
if (!fileStats || !fileStats.isFile() || fileStats.size > MAX_DOCUMENT_BYTES) {
|
|
90437
91757
|
return null;
|
|
90438
91758
|
}
|
|
@@ -92101,7 +93421,8 @@ function brokerCardAgentsForWeb(broker2) {
|
|
|
92101
93421
|
}
|
|
92102
93422
|
var AGENT_ATTENTION_TTL_MS2 = 1e4;
|
|
92103
93423
|
var AGENT_BACKGROUND_REFRESH_DELAY_MS = 500;
|
|
92104
|
-
var AGENT_BROKER_CONTEXT_TTL_MS =
|
|
93424
|
+
var AGENT_BROKER_CONTEXT_TTL_MS = 60000;
|
|
93425
|
+
var AGENT_BROKER_CONTEXT_COLD_BUDGET_MS = 75;
|
|
92105
93426
|
var agentAttentionCache = null;
|
|
92106
93427
|
var agentAttentionInFlight = null;
|
|
92107
93428
|
function queryAgentAttentionIndex(broker2, capture = defaultCaptureTmuxPane) {
|
|
@@ -92151,8 +93472,12 @@ function createAgentBrokerContextReader() {
|
|
|
92151
93472
|
return promise;
|
|
92152
93473
|
};
|
|
92153
93474
|
return () => {
|
|
92154
|
-
if (!cache)
|
|
92155
|
-
return
|
|
93475
|
+
if (!cache) {
|
|
93476
|
+
return Promise.race([
|
|
93477
|
+
refresh(0),
|
|
93478
|
+
delay2(AGENT_BROKER_CONTEXT_COLD_BUDGET_MS).then(() => null)
|
|
93479
|
+
]);
|
|
93480
|
+
}
|
|
92156
93481
|
if (Date.now() - cache.at >= AGENT_BROKER_CONTEXT_TTL_MS && !inFlight) {
|
|
92157
93482
|
refresh(AGENT_BACKGROUND_REFRESH_DELAY_MS);
|
|
92158
93483
|
}
|
|
@@ -92246,24 +93571,37 @@ function withPinnedMeshPeerAgents(agents, broker2, limit) {
|
|
|
92246
93571
|
if (!localNodeId)
|
|
92247
93572
|
return mostRecentAgents(agents, limit);
|
|
92248
93573
|
const peerNodeIds = pinnedMeshPeerNodeIds(broker2);
|
|
92249
|
-
const
|
|
93574
|
+
const representativeCardByNode = new Map;
|
|
93575
|
+
for (const agent of Object.values(broker2.snapshot.agents ?? {})) {
|
|
93576
|
+
const homeNodeId = agent.homeNodeId;
|
|
93577
|
+
if (!homeNodeId || !peerNodeIds.has(homeNodeId) || !isBrokerAgentVisibleInWeb(agent))
|
|
93578
|
+
continue;
|
|
93579
|
+
const existing = representativeCardByNode.get(homeNodeId);
|
|
93580
|
+
if (!existing || (latestBrokerAgentTimestamp(agent, null) ?? 0) > (latestBrokerAgentTimestamp(existing, null) ?? 0)) {
|
|
93581
|
+
representativeCardByNode.set(homeNodeId, agent);
|
|
93582
|
+
}
|
|
93583
|
+
}
|
|
93584
|
+
const peerAgents = [...representativeCardByNode.values()].map((agent) => brokerAgentCardToWebAgent(broker2, agent)).filter((agent) => Boolean(agent)).sort((left, right) => (right.updatedAt ?? 0) - (left.updatedAt ?? 0) || left.name.localeCompare(right.name));
|
|
92250
93585
|
if (peerAgents.length === 0)
|
|
92251
93586
|
return mostRecentAgents(agents, limit);
|
|
92252
93587
|
const byId = new Map(agents.map((agent) => [agent.id, agent]));
|
|
92253
93588
|
for (const peer of peerAgents) {
|
|
92254
|
-
byId.
|
|
93589
|
+
if (!byId.has(peer.id))
|
|
93590
|
+
byId.set(peer.id, peer);
|
|
92255
93591
|
}
|
|
92256
93592
|
const merged = [...byId.values()];
|
|
92257
93593
|
if (limit === undefined)
|
|
92258
93594
|
return merged;
|
|
92259
|
-
const
|
|
92260
|
-
const included = new Set(
|
|
92261
|
-
|
|
92262
|
-
|
|
92263
|
-
|
|
92264
|
-
|
|
93595
|
+
const representatives = peerAgents.map((peer) => byId.get(peer.id) ?? peer).slice(0, limit);
|
|
93596
|
+
const included = new Set(representatives.map((agent) => agent.id));
|
|
93597
|
+
const limited = [...representatives];
|
|
93598
|
+
for (const agent of mostRecentAgents(merged, undefined)) {
|
|
93599
|
+
if (limited.length >= limit)
|
|
93600
|
+
break;
|
|
93601
|
+
if (included.add(agent.id))
|
|
93602
|
+
limited.push(agent);
|
|
92265
93603
|
}
|
|
92266
|
-
return limited;
|
|
93604
|
+
return mostRecentAgents(limited, undefined);
|
|
92267
93605
|
}
|
|
92268
93606
|
function agentListSummary(agent) {
|
|
92269
93607
|
return {
|
|
@@ -92313,13 +93651,11 @@ function agentListSummary(agent) {
|
|
|
92313
93651
|
createdAt: agent.createdAt
|
|
92314
93652
|
};
|
|
92315
93653
|
}
|
|
92316
|
-
|
|
93654
|
+
function withAgentRepoKeys(agents) {
|
|
92317
93655
|
const roots = agents.map((agent) => agent.projectRoot).filter((root) => Boolean(root));
|
|
92318
93656
|
if (roots.length === 0)
|
|
92319
93657
|
return agents;
|
|
92320
|
-
const keys =
|
|
92321
|
-
if (!keys)
|
|
92322
|
-
return agents;
|
|
93658
|
+
const keys = cachedRepoKeysByRoot(roots);
|
|
92323
93659
|
return agents.map((agent) => {
|
|
92324
93660
|
const repoKey = agent.projectRoot ? keys.get(agent.projectRoot) ?? null : null;
|
|
92325
93661
|
return repoKey ? { ...agent, repoKey } : agent;
|
|
@@ -92403,11 +93739,11 @@ async function queryAgentsIncludingBrokerCards(limit, includeRichBrokerContext =
|
|
|
92403
93739
|
const brokerById2 = new Map(brokerAgents2.map((agent) => [agent.id, agent]));
|
|
92404
93740
|
const mergedAgents2 = agents.map((agent) => mergeBrokerAgentProjection(agent, brokerById2.get(agent.id)));
|
|
92405
93741
|
const existingIds2 = new Set(mergedAgents2.map((agent) => agent.id));
|
|
92406
|
-
const
|
|
92407
|
-
const roster2 =
|
|
93742
|
+
const attention2 = includeAttention ? await queryAgentAttentionIndex(null, capture) : new Map;
|
|
93743
|
+
const roster2 = mostRecentAgents(applyAgentAttention([
|
|
92408
93744
|
...mergedAgents2,
|
|
92409
93745
|
...brokerAgents2.filter((agent) => !existingIds2.has(agent.id))
|
|
92410
|
-
],
|
|
93746
|
+
], attention2), limit);
|
|
92411
93747
|
return withAgentRepoKeys(roster2);
|
|
92412
93748
|
}
|
|
92413
93749
|
const broker2 = await loadBrokerContext();
|
|
@@ -94039,13 +95375,11 @@ function dedupeHudRunnerProjects(projects) {
|
|
|
94039
95375
|
return result;
|
|
94040
95376
|
}
|
|
94041
95377
|
async function buildHudRunnerOptions(currentDirectory, input = {}) {
|
|
94042
|
-
const [settingsResult,
|
|
95378
|
+
const [settingsResult, runtimeCatalogResult] = await Promise.allSettled([
|
|
94043
95379
|
readOpenScoutSettings({ currentDirectory }),
|
|
94044
|
-
loadHarnessCatalogSnapshot(),
|
|
94045
95380
|
loadBrokerRuntimeCatalog()
|
|
94046
95381
|
]);
|
|
94047
95382
|
const settings = settingsResult.status === "fulfilled" ? settingsResult.value : null;
|
|
94048
|
-
const catalog = catalogResult.status === "fulfilled" ? catalogResult.value : null;
|
|
94049
95383
|
const liveRuntimeCatalog = runtimeCatalogResult.status === "fulfilled" ? runtimeCatalogResult.value : null;
|
|
94050
95384
|
const runtimeCatalog = liveRuntimeCatalog?.catalog ?? SCOUT_RUNTIME_CATALOG;
|
|
94051
95385
|
const allAgents = queryAgents(50);
|
|
@@ -94058,19 +95392,17 @@ async function buildHudRunnerOptions(currentDirectory, input = {}) {
|
|
|
94058
95392
|
const configuredDefaultHarness = settings?.agents.defaultHarness?.trim() ?? "";
|
|
94059
95393
|
const defaultHarness = isScoutRuntimeHarnessEnabled(configuredDefaultHarness, runtimeCatalog) ? configuredDefaultHarness : scoutRuntimeDefaultHarness(runtimeCatalog) ?? "claude";
|
|
94060
95394
|
const harnessesById = new Map;
|
|
94061
|
-
const readinessByHarness = new Map((catalog?.entries ?? []).map((entry) => [entry.harness, entry]));
|
|
94062
95395
|
for (const entry of runtimeCatalog.harnesses) {
|
|
94063
95396
|
if (!entry.enabled || entry.listed === false)
|
|
94064
95397
|
continue;
|
|
94065
|
-
const readiness = readinessByHarness.get(entry.id);
|
|
94066
95398
|
harnessesById.set(entry.id, {
|
|
94067
95399
|
id: entry.id,
|
|
94068
95400
|
name: entry.id,
|
|
94069
95401
|
label: entry.label,
|
|
94070
95402
|
description: null,
|
|
94071
|
-
state:
|
|
94072
|
-
ready:
|
|
94073
|
-
detail:
|
|
95403
|
+
state: null,
|
|
95404
|
+
ready: null,
|
|
95405
|
+
detail: null
|
|
94074
95406
|
});
|
|
94075
95407
|
}
|
|
94076
95408
|
const projectOptions = allAgents.map((agent) => agent.projectRoot ?? agent.cwd).filter((root) => typeof root === "string" && root.trim().length > 0).map((root) => {
|
|
@@ -94266,6 +95598,7 @@ function fallbackOpenScoutHostInfo(options, currentDirectory) {
|
|
|
94266
95598
|
async function createOpenScoutWebServer(options) {
|
|
94267
95599
|
const shellTtl = options.shellStateCacheTtlMs ?? 15000;
|
|
94268
95600
|
const currentDirectory = options.currentDirectory;
|
|
95601
|
+
const lanAccessScope = options.lanAccessScope ?? resolveScoutWebLanAccessScope(process.env);
|
|
94269
95602
|
const pendingPairRequests = createPendingPairRequestStore({
|
|
94270
95603
|
statePath: pairRequestStatePath(localConfigHome())
|
|
94271
95604
|
});
|
|
@@ -94281,8 +95614,28 @@ async function createOpenScoutWebServer(options) {
|
|
|
94281
95614
|
startGlobalHeuristicsWatcher();
|
|
94282
95615
|
}
|
|
94283
95616
|
const app = new Hono2;
|
|
95617
|
+
app.use("*", async (c, next) => {
|
|
95618
|
+
const peerAddress = (options.resolvePeerAddress ?? resolveScoutRequestPeerAddress)(c);
|
|
95619
|
+
if (!isScoutWebRequestAllowedFromPeer(c.req.raw, peerAddress, lanAccessScope)) {
|
|
95620
|
+
return c.text("Not Found", 404);
|
|
95621
|
+
}
|
|
95622
|
+
await next();
|
|
95623
|
+
});
|
|
94284
95624
|
installHttpsEdgeSecurityHeaders(app, options.publicOrigin);
|
|
94285
95625
|
const shellStateCache = createCachedSnapshot(loadOpenScoutWebShellState, shellTtl);
|
|
95626
|
+
const readAgentConfigurationSnapshot = coalesce(() => buildAgentConfigurationSnapshot(currentDirectory), 30000);
|
|
95627
|
+
const runnerOptionsReaders = new Map;
|
|
95628
|
+
const readRunnerOptions = (scope, projectRoot) => {
|
|
95629
|
+
const key = `${scope}\x00${projectRoot}`;
|
|
95630
|
+
let read = runnerOptionsReaders.get(key);
|
|
95631
|
+
if (!read) {
|
|
95632
|
+
if (runnerOptionsReaders.size >= 32)
|
|
95633
|
+
runnerOptionsReaders.clear();
|
|
95634
|
+
read = coalesce(() => buildHudRunnerOptions(currentDirectory, { scope, projectRoot }), 30000);
|
|
95635
|
+
runnerOptionsReaders.set(key, read);
|
|
95636
|
+
}
|
|
95637
|
+
return read();
|
|
95638
|
+
};
|
|
94286
95639
|
const agentBrokerContextReader = createAgentBrokerContextReader();
|
|
94287
95640
|
const agentBrokerHomeReader = createAgentBrokerHomeReader();
|
|
94288
95641
|
const dispatchBrokerSnapshotCache = createCachedSnapshot(async () => {
|
|
@@ -94339,7 +95692,8 @@ async function createOpenScoutWebServer(options) {
|
|
|
94339
95692
|
installScoutApiMiddleware(app, "openscout-web api", {
|
|
94340
95693
|
trustedHosts: options.trustedHosts,
|
|
94341
95694
|
trustedOrigins: options.trustedOrigins,
|
|
94342
|
-
authToken: options.authToken
|
|
95695
|
+
authToken: options.authToken,
|
|
95696
|
+
resolvePeerAddress: options.resolvePeerAddress
|
|
94343
95697
|
});
|
|
94344
95698
|
mountScoutDeckSurfaceRoutes(app, {
|
|
94345
95699
|
currentDirectory,
|
|
@@ -94666,33 +96020,68 @@ async function createOpenScoutWebServer(options) {
|
|
|
94666
96020
|
const route = c.req.query("route")?.trim().toLowerCase() ?? null;
|
|
94667
96021
|
const token = c.req.query("token")?.trim() || null;
|
|
94668
96022
|
const wantsJson = (c.req.header("accept") ?? "").includes("application/json");
|
|
94669
|
-
const
|
|
96023
|
+
const peerAddress = (options.resolvePeerAddress ?? resolveScoutRequestPeerAddress)(c);
|
|
96024
|
+
const xff = c.req.header("x-forwarded-for");
|
|
96025
|
+
const forwardedIp = (xff ? xff.split(",").at(-1)?.trim() : null) || c.req.header("x-real-ip")?.trim() || null;
|
|
96026
|
+
const loopbackPeer = Boolean(peerAddress && isLoopbackScoutAddress(peerAddress));
|
|
96027
|
+
const sameMacRequest = isSameMacScoutRequest(c.req.raw, peerAddress);
|
|
96028
|
+
const relayedLanRequest = Boolean(loopbackPeer && c.req.header(SCOUT_PAIR_RELAY_HEADER) === "1");
|
|
96029
|
+
const directLanRequest = Boolean(peerAddress && !isLoopbackScoutAddress(peerAddress));
|
|
96030
|
+
const proxiedLanRequest = Boolean(loopbackPeer && !relayedLanRequest && !sameMacRequest);
|
|
96031
|
+
const unidentifiedPairingIngress = !peerAddress;
|
|
96032
|
+
const requiresApproval = relayedLanRequest || directLanRequest || proxiedLanRequest || unidentifiedPairingIngress;
|
|
96033
|
+
const requesterApp = parseScoutPairClient(c.req.header(SCOUT_PAIR_CLIENT_HEADER), c.req.header("user-agent"));
|
|
96034
|
+
const state = await loadPairingState(currentDirectory, false);
|
|
94670
96035
|
const location = pickPairingLocation(state, route);
|
|
94671
|
-
if (location) {
|
|
94672
|
-
if (token && !pendingPairRequests.fulfill(token)) {
|
|
94673
|
-
return wantsJson ? c.json({ status: "expired", token }, 410) : c.text("Pairing request expired.", 410);
|
|
94674
|
-
}
|
|
94675
|
-
return c.redirect(location, 302);
|
|
94676
|
-
}
|
|
94677
96036
|
if (token) {
|
|
94678
|
-
const
|
|
94679
|
-
if (!
|
|
96037
|
+
const request2 = pendingPairRequests.get(token);
|
|
96038
|
+
if (!request2) {
|
|
94680
96039
|
return wantsJson ? c.json({ status: "expired", token }, 410) : c.text("Pairing request expired.", 410);
|
|
94681
96040
|
}
|
|
94682
|
-
if (
|
|
96041
|
+
if (request2.status === "denied") {
|
|
94683
96042
|
return wantsJson ? c.json({ status: "denied", token }, 403) : c.text("Pairing request was denied.", 403);
|
|
94684
96043
|
}
|
|
96044
|
+
if (location && request2.status === "approved") {
|
|
96045
|
+
if (!pendingPairRequests.fulfill(token, "approved")) {
|
|
96046
|
+
const current = pendingPairRequests.get(token);
|
|
96047
|
+
if (current?.status === "approved" || current?.status === "pending") {
|
|
96048
|
+
return c.json({ status: current.status, token, pollAfterMs: 1200 }, 202);
|
|
96049
|
+
}
|
|
96050
|
+
if (current?.status === "denied") {
|
|
96051
|
+
return wantsJson ? c.json({ status: "denied", token }, 403) : c.text("Pairing request was denied.", 403);
|
|
96052
|
+
}
|
|
96053
|
+
return wantsJson ? c.json({ status: "expired", token }, 410) : c.text("Pairing request expired.", 410);
|
|
96054
|
+
}
|
|
96055
|
+
return c.redirect(location, 302);
|
|
96056
|
+
}
|
|
94685
96057
|
pendingPairRequests.touch(token);
|
|
94686
|
-
return c.json({ status:
|
|
96058
|
+
return c.json({ status: request2.status, token, pollAfterMs: 1200 }, 202);
|
|
94687
96059
|
}
|
|
94688
|
-
|
|
94689
|
-
|
|
94690
|
-
|
|
94691
|
-
|
|
94692
|
-
|
|
94693
|
-
|
|
94694
|
-
}
|
|
94695
|
-
|
|
96060
|
+
if (location && !requiresApproval) {
|
|
96061
|
+
return c.redirect(location, 302);
|
|
96062
|
+
}
|
|
96063
|
+
const requesterIp = unidentifiedPairingIngress ? null : relayedLanRequest || proxiedLanRequest ? forwardedIp : directLanRequest ? peerAddress ?? null : forwardedIp;
|
|
96064
|
+
if (requiresApproval && !requesterIp) {
|
|
96065
|
+
return wantsJson ? c.json({ status: "unavailable" }, 503) : c.text("Unable to identify pairing requester.", 503);
|
|
96066
|
+
}
|
|
96067
|
+
let request;
|
|
96068
|
+
try {
|
|
96069
|
+
request = pendingPairRequests.create({
|
|
96070
|
+
requesterIp,
|
|
96071
|
+
requesterLabel: c.req.header("x-scout-device-name")?.trim() || null,
|
|
96072
|
+
requesterApp,
|
|
96073
|
+
route
|
|
96074
|
+
});
|
|
96075
|
+
} catch (error) {
|
|
96076
|
+
if (!(error instanceof PairRequestCapacityError))
|
|
96077
|
+
throw error;
|
|
96078
|
+
c.header("retry-after", String(Math.ceil(error.retryAfterMs / 1000)));
|
|
96079
|
+
return wantsJson ? c.json({ status: "busy", retryAfterMs: error.retryAfterMs }, 429) : c.text("Too many pairing requests. Try again shortly.", 429);
|
|
96080
|
+
}
|
|
96081
|
+
if (request.status === "denied") {
|
|
96082
|
+
return wantsJson ? c.json({ status: "denied", token: request.token }, 403) : c.text("Pairing request was denied.", 403);
|
|
96083
|
+
}
|
|
96084
|
+
return wantsJson ? c.json({ status: request.status, token: request.token, pollAfterMs: 1200 }, 202) : c.text(`${SCOUT_PAIRING_DEEP_LINK_SCHEME}://${SCOUT_PAIRING_DEEP_LINK_PATH} pairing requires approval on the Mac.`, 202);
|
|
94696
96085
|
});
|
|
94697
96086
|
app.get("/api/notifications", (c) => {
|
|
94698
96087
|
const rawType = c.req.query("type") ?? "";
|
|
@@ -94701,7 +96090,7 @@ async function createOpenScoutWebServer(options) {
|
|
|
94701
96090
|
const notifications = includePairingRequests ? pendingPairRequests.list().filter((request) => request.status === "pending").map((request) => ({
|
|
94702
96091
|
id: `pairing_request:${request.token}`,
|
|
94703
96092
|
type: "pairing_request",
|
|
94704
|
-
title: `${request
|
|
96093
|
+
title: `${pairRequesterDisplay(request)} wants to pair`,
|
|
94705
96094
|
body: `On your network${request.requesterIp ? ` \xB7 ${request.requesterIp}` : ""}.`,
|
|
94706
96095
|
createdAt: request.createdAt,
|
|
94707
96096
|
updatedAt: request.updatedAt,
|
|
@@ -94791,14 +96180,11 @@ async function createOpenScoutWebServer(options) {
|
|
|
94791
96180
|
});
|
|
94792
96181
|
app.get("/api/shell-state", async (c) => c.json(await shellStateCache.get()));
|
|
94793
96182
|
app.get("/api/shell-state/refresh", async (c) => c.json(await shellStateCache.refresh()));
|
|
94794
|
-
app.get("/api/agent-config/snapshot", async (c) => c.json(await
|
|
96183
|
+
app.get("/api/agent-config/snapshot", async (c) => c.json(await readAgentConfigurationSnapshot()));
|
|
94795
96184
|
app.get("/api/runner/options", async (c) => {
|
|
94796
96185
|
const requestedScope = c.req.query("scope");
|
|
94797
96186
|
const scope = requestedScope === "global" || requestedScope === "project" || requestedScope === "global+project" ? requestedScope : "global+project";
|
|
94798
|
-
return c.json(await
|
|
94799
|
-
scope,
|
|
94800
|
-
projectRoot: c.req.query("projectRoot") || currentDirectory
|
|
94801
|
-
}));
|
|
96187
|
+
return c.json(await readRunnerOptions(scope, c.req.query("projectRoot") || currentDirectory));
|
|
94802
96188
|
});
|
|
94803
96189
|
const agentsResponseCache = new Map;
|
|
94804
96190
|
const readAgentsResponse = (limit, summary, attentionRequested) => {
|
|
@@ -94807,7 +96193,7 @@ async function createOpenScoutWebServer(options) {
|
|
|
94807
96193
|
if (!entry) {
|
|
94808
96194
|
if (agentsResponseCache.size >= 32)
|
|
94809
96195
|
agentsResponseCache.clear();
|
|
94810
|
-
entry = coalesce(() => queryAgentsIncludingBrokerCards(limit, !summary
|
|
96196
|
+
entry = coalesce(() => queryAgentsIncludingBrokerCards(limit, !summary, attentionRequested, options.captureTmuxPane ?? defaultCaptureTmuxPane, agentBrokerContextReader, agentBrokerHomeReader), 3000);
|
|
94811
96197
|
agentsResponseCache.set(key, entry);
|
|
94812
96198
|
}
|
|
94813
96199
|
return entry();
|
|
@@ -95580,7 +96966,12 @@ async function createOpenScoutWebServer(options) {
|
|
|
95580
96966
|
let messages2;
|
|
95581
96967
|
try {
|
|
95582
96968
|
parseMessageHistoryCursor(beforeMessageId);
|
|
95583
|
-
const
|
|
96969
|
+
const brokerContext = cId ? await loadScoutBrokerContext(undefined, {
|
|
96970
|
+
scope: "conversations",
|
|
96971
|
+
waitForInitial: false,
|
|
96972
|
+
initialRefreshDelayMs: 750
|
|
96973
|
+
}).catch(() => null) : null;
|
|
96974
|
+
const brokerMessages = cId ? await getScoutConversationMessages(cId, limit, beforeMessageId, brokerContext) : null;
|
|
95584
96975
|
if (cId && brokerMessages && brokerMessages.length > 0 && brokerMessages.length < limit) {
|
|
95585
96976
|
const oldest = brokerMessages[0];
|
|
95586
96977
|
const seen = new Set(brokerMessages.map((message) => message.id));
|
|
@@ -95953,7 +97344,11 @@ async function createOpenScoutWebServer(options) {
|
|
|
95953
97344
|
if (flights.length > 0) {
|
|
95954
97345
|
return c.json(flights);
|
|
95955
97346
|
}
|
|
95956
|
-
const broker2 = await loadScoutBrokerContext(
|
|
97347
|
+
const broker2 = await loadScoutBrokerContext(undefined, {
|
|
97348
|
+
scope: "conversations",
|
|
97349
|
+
waitForInitial: false,
|
|
97350
|
+
initialRefreshDelayMs: 750
|
|
97351
|
+
}).catch(() => null);
|
|
95957
97352
|
return c.json(broker2 ? queryBrokerFlightsForWeb(broker2, query) : flights);
|
|
95958
97353
|
});
|
|
95959
97354
|
app.get("/api/follow", (c) => {
|
|
@@ -95970,7 +97365,7 @@ async function createOpenScoutWebServer(options) {
|
|
|
95970
97365
|
targetAgentId: c.req.query("targetAgentId") || undefined
|
|
95971
97366
|
}));
|
|
95972
97367
|
});
|
|
95973
|
-
const readCommsList = async (c) => {
|
|
97368
|
+
const readCommsList = async (c, options2 = {}) => {
|
|
95974
97369
|
const rawLimit = Number(c.req.query("limit"));
|
|
95975
97370
|
const rawKinds = c.req.query("kinds")?.trim();
|
|
95976
97371
|
const filters = {
|
|
@@ -95979,11 +97374,43 @@ async function createOpenScoutWebServer(options) {
|
|
|
95979
97374
|
kinds: parseConversationKinds(rawKinds),
|
|
95980
97375
|
machineId: c.req.query("machineId") || undefined
|
|
95981
97376
|
};
|
|
95982
|
-
const
|
|
97377
|
+
const preferredProjection = options2.preferMaterialized && !filters.machineId ? await readScoutConversationProjection(160) : undefined;
|
|
97378
|
+
if (preferredProjection?.items.some((item) => item.entityKind === "scout_conversation")) {
|
|
97379
|
+
return {
|
|
97380
|
+
items: provisionalScoutConversations(preferredProjection, filters),
|
|
97381
|
+
listReady: true
|
|
97382
|
+
};
|
|
97383
|
+
}
|
|
97384
|
+
const broker2 = await loadScoutBrokerContext(undefined, filters.machineId ? {} : {
|
|
97385
|
+
scope: "conversations",
|
|
97386
|
+
waitForInitial: false,
|
|
97387
|
+
initialRefreshDelayMs: 750
|
|
97388
|
+
}).catch(() => null);
|
|
95983
97389
|
if (broker2) {
|
|
95984
97390
|
const items = await getScoutConversations(filters, broker2);
|
|
95985
97391
|
return { items, listReady: true };
|
|
95986
97392
|
}
|
|
97393
|
+
if (!filters.machineId) {
|
|
97394
|
+
const launchProjection = preferredProjection === undefined ? await readScoutConversationProjection(Math.min(160, filters.limit ?? 160)) : preferredProjection;
|
|
97395
|
+
if (launchProjection?.items.some((item) => item.entityKind === "scout_conversation")) {
|
|
97396
|
+
return {
|
|
97397
|
+
items: provisionalScoutConversations(launchProjection, filters),
|
|
97398
|
+
listReady: true
|
|
97399
|
+
};
|
|
97400
|
+
}
|
|
97401
|
+
const projected = querySessions(250);
|
|
97402
|
+
if (projected.length > 0) {
|
|
97403
|
+
const query = filters.query?.trim().toLocaleLowerCase() ?? "";
|
|
97404
|
+
const kinds = filters.kinds ? new Set(filters.kinds) : null;
|
|
97405
|
+
const items = projected.filter((item) => !kinds || kinds.has(item.kind)).filter((item) => !query || [
|
|
97406
|
+
item.title,
|
|
97407
|
+
item.alias,
|
|
97408
|
+
item.agentName,
|
|
97409
|
+
item.preview
|
|
97410
|
+
].some((value) => value?.toLocaleLowerCase().includes(query))).slice(0, filters.limit ?? projected.length);
|
|
97411
|
+
return { items, listReady: true };
|
|
97412
|
+
}
|
|
97413
|
+
}
|
|
95987
97414
|
const health = await readScoutBrokerHealth(resolveScoutBrokerUrl(), {
|
|
95988
97415
|
signal: AbortSignal.timeout(2000)
|
|
95989
97416
|
});
|
|
@@ -95996,7 +97423,7 @@ async function createOpenScoutWebServer(options) {
|
|
|
95996
97423
|
retryable: true
|
|
95997
97424
|
}, 503);
|
|
95998
97425
|
app.get("/api/comms", async (c) => {
|
|
95999
|
-
const { items, listReady } = await readCommsList(c);
|
|
97426
|
+
const { items, listReady } = await readCommsList(c, { preferMaterialized: true });
|
|
96000
97427
|
if (!listReady) {
|
|
96001
97428
|
return unavailableConversationList(c);
|
|
96002
97429
|
}
|
|
@@ -96176,10 +97603,10 @@ async function createOpenScoutWebServer(options) {
|
|
|
96176
97603
|
session: conversation
|
|
96177
97604
|
});
|
|
96178
97605
|
}
|
|
96179
|
-
const parsedRef = parseSessionRouteRef(refId);
|
|
96180
|
-
const harnessSession = parsedRef ? querySessions(200).find((session3) => sessionHarnessMatches(parsedRef.harness, session3.harness) && parseSessionRouteRef(session3.harnessSessionId)?.refId === parsedRef.refId) : null;
|
|
96181
97606
|
const payload = await loadSessionRefObservePayload(refId);
|
|
96182
97607
|
if (payload) {
|
|
97608
|
+
const parsedRef = payload.agentId ? parseSessionRouteRef(refId) : null;
|
|
97609
|
+
const harnessSession = parsedRef ? querySessions(200).find((session3) => sessionHarnessMatches(parsedRef.harness, session3.harness) && parseSessionRouteRef(session3.harnessSessionId)?.refId === parsedRef.refId) : null;
|
|
96183
97610
|
return c.json({
|
|
96184
97611
|
kind: "observe",
|
|
96185
97612
|
refId,
|
|
@@ -96204,7 +97631,12 @@ async function createOpenScoutWebServer(options) {
|
|
|
96204
97631
|
return c.json({ error: "chatId must be an opaque chat id" }, 400);
|
|
96205
97632
|
}
|
|
96206
97633
|
const session3 = querySessionById(resolvedChatId);
|
|
96207
|
-
const
|
|
97634
|
+
const broker2 = session3 ? await loadScoutBrokerContext(undefined, {
|
|
97635
|
+
scope: "conversations",
|
|
97636
|
+
waitForInitial: false,
|
|
97637
|
+
initialRefreshDelayMs: 750
|
|
97638
|
+
}).catch(() => null) : undefined;
|
|
97639
|
+
const conversation = broker2 === null ? null : broker2 ? (await getScoutConversations({ conversationId: resolvedChatId, limit: 1 }, broker2))[0] ?? null : await getScoutConversationById(resolvedChatId);
|
|
96208
97640
|
if (session3 && conversation) {
|
|
96209
97641
|
return c.json({ ...session3, ...conversation });
|
|
96210
97642
|
}
|
|
@@ -97093,6 +98525,8 @@ async function createOpenScoutWebServer(options) {
|
|
|
97093
98525
|
const limitParam = parseOptionalPositiveInt3(c.req.query("limit"), 500) ?? 500;
|
|
97094
98526
|
const includeTranscripts = c.req.query("transcripts") === "true" || c.req.query("transcripts") === "1";
|
|
97095
98527
|
const mode = c.req.query("mode") === "assistant-replies" ? "assistant-replies" : null;
|
|
98528
|
+
const requestedWindowMs = parseOptionalPositiveInt3(c.req.query("windowMs"));
|
|
98529
|
+
const windowMs = requestedWindowMs === undefined ? undefined : Math.min(requestedWindowMs, 86400000);
|
|
97096
98530
|
const url = new URL(scoutBrokerPaths.v1.tailRecent, resolveScoutBrokerUrl());
|
|
97097
98531
|
url.searchParams.set("limit", String(limitParam));
|
|
97098
98532
|
if (includeTranscripts) {
|
|
@@ -97101,7 +98535,10 @@ async function createOpenScoutWebServer(options) {
|
|
|
97101
98535
|
if (mode) {
|
|
97102
98536
|
url.searchParams.set("mode", mode);
|
|
97103
98537
|
}
|
|
97104
|
-
|
|
98538
|
+
if (windowMs !== undefined) {
|
|
98539
|
+
url.searchParams.set("windowMs", String(windowMs));
|
|
98540
|
+
}
|
|
98541
|
+
const cacheKey = `limit=${limitParam};transcripts=${includeTranscripts ? "1" : "0"};mode=${mode ?? "all"};window=${windowMs ?? "all"}`;
|
|
97105
98542
|
let cache = tailRecentCaches.get(cacheKey);
|
|
97106
98543
|
if (!cache) {
|
|
97107
98544
|
cache = createBrokerJsonCache();
|
|
@@ -97811,6 +99248,7 @@ function startProcessParentWatchdog(expectedParentPidRaw, options = {}) {
|
|
|
97811
99248
|
process.title = "scout-web";
|
|
97812
99249
|
var port = Number.parseInt(process.env.OPENSCOUT_WEB_PORT ?? process.env.SCOUT_WEB_PORT ?? String(resolveWebPort()), 10);
|
|
97813
99250
|
var hostname2 = resolveScoutWebBindHost(process.env);
|
|
99251
|
+
var lanAccessScope = resolveScoutWebLanAccessScope(process.env);
|
|
97814
99252
|
var webAuthToken = resolveWebAuthToken(process.env);
|
|
97815
99253
|
var currentDirectory = resolveOpenScoutSetupContextRoot({
|
|
97816
99254
|
env: process.env,
|
|
@@ -97820,6 +99258,7 @@ var shellStateCacheTtlMs = Number.parseInt(process.env.OPENSCOUT_WEB_SHELL_CACHE
|
|
|
97820
99258
|
var providerTelemetryBootstrapEnabled = process.env.OPENSCOUT_WEB_PROVIDER_TELEMETRY_BOOTSTRAP?.trim() === "1";
|
|
97821
99259
|
var startupWarmupEnabled = process.env.OPENSCOUT_WEB_STARTUP_WARMUP?.trim() === "1";
|
|
97822
99260
|
var routes = resolveOpenScoutWebRoutes(process.env);
|
|
99261
|
+
var requestPeerAddresses = createScoutRequestPeerAddressRegistry();
|
|
97823
99262
|
function resolveStaticRoot2() {
|
|
97824
99263
|
if (process.env.OPENSCOUT_WEB_STATIC_ROOT?.trim()) {
|
|
97825
99264
|
return process.env.OPENSCOUT_WEB_STATIC_ROOT.trim();
|
|
@@ -97909,6 +99348,7 @@ var web = await createOpenScoutWebServer({
|
|
|
97909
99348
|
trustedHosts: applicationServerIdentity.trustedHosts,
|
|
97910
99349
|
trustedOrigins: applicationServerIdentity.trustedOrigins,
|
|
97911
99350
|
authToken: webAuthToken,
|
|
99351
|
+
resolvePeerAddress: requestPeerAddresses.resolve,
|
|
97912
99352
|
runTerminalCommand: async (request) => {
|
|
97913
99353
|
const relay = await ensureTerminalRelay();
|
|
97914
99354
|
if (!relay) {
|
|
@@ -97948,6 +99388,9 @@ try {
|
|
|
97948
99388
|
async fetch(req, server2) {
|
|
97949
99389
|
const url = new URL(req.url);
|
|
97950
99390
|
const peerAddress = server2.requestIP(req)?.address;
|
|
99391
|
+
if (!isScoutWebRequestAllowedFromPeer(req, peerAddress, lanAccessScope)) {
|
|
99392
|
+
return new Response("Not Found", { status: 404 });
|
|
99393
|
+
}
|
|
97951
99394
|
if (req.headers.get("upgrade")?.toLowerCase() === "websocket") {
|
|
97952
99395
|
let upstreamUrl = null;
|
|
97953
99396
|
const guardsOrigin = url.pathname === routes.terminalRelayPath || url.pathname === routes.tailStreamPath || url.pathname === routes.eventsStreamPath;
|
|
@@ -98003,6 +99446,7 @@ try {
|
|
|
98003
99446
|
return headers2;
|
|
98004
99447
|
})()
|
|
98005
99448
|
}) : req;
|
|
99449
|
+
requestPeerAddresses.remember(honoRequest, peerAddress);
|
|
98006
99450
|
const response = await honoFetch(honoRequest, server2);
|
|
98007
99451
|
if (!bootstrapEligible)
|
|
98008
99452
|
return response;
|