@openscout/scout 0.2.95 → 0.2.96
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-BnoaUkVZ.js} +1 -1
- package/dist/client/assets/{AddProjectForm-CcD6qvV8.js → AddProjectForm-IqOtJfRs.js} +1 -1
- package/dist/client/assets/{AgentAvatar-CYhf6twS.js → AgentAvatar-6-KBVKUu.js} +1 -1
- package/dist/client/assets/{AgentConfigurationScreen-BTI24HQX.js → AgentConfigurationScreen-CuZJy07q.js} +1 -1
- package/dist/client/assets/{AgentDefinitionsWorkspace-srmN6-vj.js → AgentDefinitionsWorkspace-Iyl4BesU.js} +1 -1
- package/dist/client/assets/{AgentDetailCard-UqPNpcvB.js → AgentDetailCard-C9rn3Fj5.js} +1 -1
- package/dist/client/assets/{AgentFloorView-XXNgI5Cj.js → AgentFloorView-YT-Jjccf.js} +1 -1
- package/dist/client/assets/{AgentInfoScreen-CimdOnZ9.js → AgentInfoScreen-Dr99gQEZ.js} +1 -1
- package/dist/client/assets/{AgentLaneCard-Z-aOBR3W.js → AgentLaneCard-DI2iW9zO.js} +1 -1
- package/dist/client/assets/{AgentLaneChrome-CyhA1reW.js → AgentLaneChrome-D8bARHMx.js} +1 -1
- package/dist/client/assets/{AgentLaneDetailSheet-BNzjMjIH.js → AgentLaneDetailSheet-52un7dKC.js} +1 -1
- package/dist/client/assets/{AgentLaneSummaryResize-Box8-_rS.js → AgentLaneSummaryResize-CEBjmPTa.js} +1 -1
- package/dist/client/assets/AgentLanesEmbedScreen-Dgcm7zd_.js +1 -0
- package/dist/client/assets/AgentLanesPreflight-q20mTjms.js +1 -0
- package/dist/client/assets/AgentLanesView-CetZZDyF.js +2 -0
- package/dist/client/assets/{AgentLiveActions-BwuzOE8h.js → AgentLiveActions-DrEJDJef.js} +1 -1
- package/dist/client/assets/AgentMasterScreen-DJPnstoD.js +1 -0
- package/dist/client/assets/{AgentSessions-CsZwoukw.js → AgentSessions-DCPCG4xb.js} +1 -1
- package/dist/client/assets/{AgentsConsole-KCao4XmX.js → AgentsConsole-CsYOoFJi.js} +1 -1
- package/dist/client/assets/{AgentsScreen-CtPAmwRX.js → AgentsScreen-k8LvBuU_.js} +1 -1
- package/dist/client/assets/AgentsSubnav-C4xpQhsv.js +1 -0
- package/dist/client/assets/{AstronautSuit-Ckx7lu7G.js → AstronautSuit-DbjQtfD_.js} +1 -1
- package/dist/client/assets/{AtopView-DYlpgEHf.js → AtopView-Daq_ob3z.js} +1 -1
- package/dist/client/assets/{BackToPicker-4JaeRvDm.js → BackToPicker-CXZjBRAe.js} +1 -1
- package/dist/client/assets/{BriefingDetailScreen-D6-xqrpo.js → BriefingDetailScreen-CUCXO-KH.js} +1 -1
- package/dist/client/assets/{BriefingsScreen-DKxSDEmk.js → BriefingsScreen-B5oMTGKv.js} +1 -1
- package/dist/client/assets/{BrokerMetadataPanel-BbREmsbK.js → BrokerMetadataPanel-BsiU8lTD.js} +1 -1
- package/dist/client/assets/{BrokerScreen-fbPIouMw.js → BrokerScreen-BPbOHhCS.js} +1 -1
- package/dist/client/assets/{CastPicker-BcA2vDDV.js → CastPicker-_5E5hNUe.js} +1 -1
- package/dist/client/assets/ChatCollapsedStrip-D-eXhzPf.js +1 -0
- package/dist/client/assets/{CodeDiffPane-Cn8Y9hAt.js → CodeDiffPane-n7W4iGUG.js} +1 -1
- package/dist/client/assets/{CodeProjectPicker-nPFktrco.js → CodeProjectPicker-CMsbSTDq.js} +1 -1
- package/dist/client/assets/{CodeScreen-BlAxtxE5.js → CodeScreen-CeuO3EhR.js} +1 -1
- package/dist/client/assets/{ConversationComposer-2HjbGPL9.js → ConversationComposer-CXPKx86g.js} +1 -1
- package/dist/client/assets/{ConversationFeedRows-C6wUqJrx.js → ConversationFeedRows-WrH-YI3L.js} +1 -1
- package/dist/client/assets/{ConversationHeader-C8vfXaTF.js → ConversationHeader-BQWzGzLK.js} +1 -1
- package/dist/client/assets/{ConversationPanels-CNCIbpqU.js → ConversationPanels-Dujvnmup.js} +2 -2
- package/dist/client/assets/ConversationScreen-CR9pWB65.js +2 -0
- package/dist/client/assets/{ConversationStatus-DZuyKsWN.js → ConversationStatus-DVzSb2Hv.js} +1 -1
- package/dist/client/assets/{CrewAvatar-CTIuxp4G.js → CrewAvatar-BwXjyg8N.js} +1 -1
- package/dist/client/assets/CrewWorkspaces-CkQDhyie.css +1 -0
- package/dist/client/assets/CrewWorkspaces-NKujRzwh.js +1 -0
- package/dist/client/assets/{DataTable-6IDhanr5.js → DataTable-Bp8tU9AK.js} +1 -1
- package/dist/client/assets/{DispatchAftermath-DC1u9itO.js → DispatchAftermath-B-6rmXzL.js} +1 -1
- package/dist/client/assets/{DocumentFocusViewer-DZVhS7as.js → DocumentFocusViewer-Do3wQ_3Z.js} +1 -1
- package/dist/client/assets/{EmbeddableSurfacesLab-BKUFJMCV.js → EmbeddableSurfacesLab-C1orRyP9.js} +1 -1
- package/dist/client/assets/{EmptyState-CeBl0iGd.js → EmptyState-CJzXj1l5.js} +1 -1
- package/dist/client/assets/{FileViewerPane-DQlpNt2S.js → FileViewerPane-Df6VzXjA.js} +1 -1
- package/dist/client/assets/FlightObserveScreen-6mGnmWQA.js +1 -0
- package/dist/client/assets/{FollowScreen-BXHOp3gb.js → FollowScreen-DvnxYLVh.js} +1 -1
- package/dist/client/assets/{HarnessMark-D5CA5uSp.js → HarnessMark-B979GCSB.js} +1 -1
- package/dist/client/assets/{HarnessesScreen-DhFXq1qz.js → HarnessesScreen-CHTuv8p6.js} +1 -1
- package/dist/client/assets/{HerdrSession-BRhs5LIR.js → HerdrSession-B3McuYgi.js} +1 -1
- package/dist/client/assets/{HomeHero-DMABJuze.js → HomeHero-CdUVPjkG.js} +1 -1
- package/dist/client/assets/{HostAdvisorView-RAociATV.js → HostAdvisorView-Bok5Sk5c.js} +1 -1
- package/dist/client/assets/{KnowledgeSearchInspector-CZPyVNSw.js → KnowledgeSearchInspector-B7XSoJsu.js} +1 -1
- package/dist/client/assets/{KnowledgeSearchScreen-mGTKIg00.js → KnowledgeSearchScreen-D3o3IODW.js} +1 -1
- package/dist/client/assets/{LaneToolHoverCard-D_DMlBeT.js → LaneToolHoverCard-HByf2ndx.js} +1 -1
- package/dist/client/assets/{LaneTraceDetailSheet-BEHg3LmH.js → LaneTraceDetailSheet-BUgHz-sd.js} +1 -1
- package/dist/client/assets/{LaneTraceEventFocus-DVimcizS.js → LaneTraceEventFocus-DM-hoPxG.js} +1 -1
- package/dist/client/assets/{MeshCanvas-BOuZx4AM.js → MeshCanvas-DCLJRsBy.js} +1 -1
- package/dist/client/assets/{MeshCanvasMinimap-wL-1N94e.js → MeshCanvasMinimap-cEFS9eW7.js} +1 -1
- package/dist/client/assets/{MeshScreen-DMY9Bmh5.js → MeshScreen-BcxPkhm6.js} +1 -1
- package/dist/client/assets/{MeshTopologyView-DiDcX5f4.js → MeshTopologyView-CCRPd8PU.js} +2 -2
- package/dist/client/assets/MessagesScreen-Bb5l13MO.js +1 -0
- package/dist/client/assets/{MissionContextRail-DrNKXG5u.js → MissionContextRail-DF0_kiU7.js} +1 -1
- package/dist/client/assets/{MissionControlView-ByBlHVN8.js → MissionControlView-E3V7bENU.js} +1 -1
- package/dist/client/assets/{MissionFocusOverlay-D1i6R6Zt.js → MissionFocusOverlay-h15sQFvP.js} +1 -1
- package/dist/client/assets/{MissionLeftAgentRow-DN9NcCML.js → MissionLeftAgentRow-KPdk9rSa.js} +1 -1
- package/dist/client/assets/{MissionLogPane-DSeIv3Xo.js → MissionLogPane-BbdDKjUl.js} +1 -1
- package/dist/client/assets/{NewAgentModal-V7yK6J6j.js → NewAgentModal-DfHxad34.js} +1 -1
- package/dist/client/assets/NewChatComposer-_Stj0fZy.js +19 -0
- package/dist/client/assets/{NewChatOrigin-DdpzE4kz.js → NewChatOrigin-B1u7ki70.js} +1 -1
- package/dist/client/assets/{ObserveEmbedScreen-l_Q3ts2q.js → ObserveEmbedScreen-Co0xTii6.js} +1 -1
- package/dist/client/assets/{ObserveTextFlow-BSEtYTxU.js → ObserveTextFlow-ZQWwrK3i.js} +2 -2
- package/dist/client/assets/{ObservedTopologyPanel-CdGUXxGR.js → ObservedTopologyPanel-BJUhDSuQ.js} +1 -1
- package/dist/client/assets/{OpenScoutAppShell-DN8dOSK4.js → OpenScoutAppShell-CUd2yOLu.js} +25 -25
- package/dist/client/assets/{OpsAgentsView-ntGr4pz4.js → OpsAgentsView-DI5wu1si.js} +1 -1
- package/dist/client/assets/OpsScreen-D8fQafCl.js +1 -0
- package/dist/client/assets/OpsSubnav-1K4Jaf__.js +1 -0
- package/dist/client/assets/ProjectAgentProfile-Bdjd_dAx.js +1 -0
- package/dist/client/assets/{ProjectAgentProfileBar-BQET-qrY.js → ProjectAgentProfileBar-k2QHHHsQ.js} +1 -1
- package/dist/client/assets/{ProjectAgentProfileHero-Ck8mThtx.js → ProjectAgentProfileHero-Bpxk1ui2.js} +1 -1
- package/dist/client/assets/ProjectsInbox-C_bMHLCc.js +2 -0
- package/dist/client/assets/ProjectsRail-J-aH_pxT.js +1 -0
- package/dist/client/assets/ProjectsScreen-cVUkGbPz.js +1 -0
- package/dist/client/assets/ProjectsThreadAside-_ourdM-Q.js +1 -0
- package/dist/client/assets/{Provider-B2xuo3rf.js → Provider-CtXJeLrP.js} +1 -1
- package/dist/client/assets/{RailRow-B-GycCBx.js → RailRow-CEH2MFBw.js} +1 -1
- package/dist/client/assets/{RawSessionsTable-AQThi6sm.js → RawSessionsTable-CDyrom-F.js} +1 -1
- package/dist/client/assets/RealtimeVoiceScreen-DBl3DN1H.js +1 -0
- package/dist/client/assets/{RepoDiffEmbedScreen-DXWoRF_c.js → RepoDiffEmbedScreen-kY2pHjIs.js} +1 -1
- package/dist/client/assets/{RepoDiffPageScreen-D_274ExO.js → RepoDiffPageScreen-C6LhoKrn.js} +1 -1
- package/dist/client/assets/{RepoDiffViewer-DbedmHDX.js → RepoDiffViewer-BhcIIQQg.js} +1 -1
- package/dist/client/assets/{RepoDiffViewerLazy-C0--fPtk.js → RepoDiffViewerLazy-Csy_j9LD.js} +2 -2
- package/dist/client/assets/{ReposScreen-D39_YG4H.js → ReposScreen-B_cB0zu7.js} +1 -1
- package/dist/client/assets/ScoutDeckSurface-CSy_fjcG.js +1 -0
- package/dist/client/assets/{ScoutSurface-UsRy0t-I.js → ScoutSurface-CQVcSrin.js} +1 -1
- package/dist/client/assets/{ScoutbotFxLab-Fmdfboxs.js → ScoutbotFxLab-DqGiLYNy.js} +1 -1
- package/dist/client/assets/{SecondaryNav-o2RL9H8H.js → SecondaryNav-BR4VRdgh.js} +1 -1
- package/dist/client/assets/SessionEmbedScreen-BTlZ9gAg.js +1 -0
- package/dist/client/assets/{SessionObserve-Dsd0j05N.js → SessionObserve-dQDN23pP.js} +1 -1
- package/dist/client/assets/{SessionObserveEvidence-DopQYDkD.js → SessionObserveEvidence-BRBGKAgd.js} +1 -1
- package/dist/client/assets/SessionRefScreen-COVQMbtE.js +1 -0
- package/dist/client/assets/SessionsScreen--5OJ3p3v.js +1 -0
- package/dist/client/assets/{SettingsDrawer-_AwuopMS.js → SettingsDrawer-RGVK_bmE.js} +1 -1
- package/dist/client/assets/{SettingsScreen-Cw4DDfJP.js → SettingsScreen-CCxzy5IU.js} +1 -1
- package/dist/client/assets/{ShikiPane-BfHc_3pM.js → ShikiPane-DYI9Hkge.js} +1 -1
- package/dist/client/assets/{SlidePanel-C-q7XwTa.js → SlidePanel-B9ugxWgA.js} +1 -1
- package/dist/client/assets/{SpriteAvatar-Bs68ZENy.js → SpriteAvatar-z5hHesx9.js} +1 -1
- package/dist/client/assets/{StatusPill-ZZQwxB1a.js → StatusPill-BFvMjmZV.js} +1 -1
- package/dist/client/assets/{TailView-Q4FVMsUH.js → TailView-0uEIj2JH.js} +1 -1
- package/dist/client/assets/{Terminal-D7zqHwHV.js → Terminal-DouZeNxc.js} +1 -1
- package/dist/client/assets/{TerminalEmbedScreen-CXIJ7qv6.js → TerminalEmbedScreen-dMNUbzXr.js} +1 -1
- package/dist/client/assets/{TerminalHeaderMount-BnBLOPbb.js → TerminalHeaderMount-BL07cd0q.js} +1 -1
- package/dist/client/assets/{TextDocumentSurface-CKQP-cBT.js → TextDocumentSurface-BflAwXeZ.js} +1 -1
- package/dist/client/assets/{TmuxPeek-V9dGESfO.js → TmuxPeek-BTnjOQi0.js} +1 -1
- package/dist/client/assets/{VoicePermissionsPanel-k7sbLXx2.js → VoicePermissionsPanel-CgQ6GGS-.js} +1 -1
- package/dist/client/assets/{WorkDetailScreen-60p9litn.js → WorkDetailScreen-CaLG-zDs.js} +1 -1
- package/dist/client/assets/{WorkFilesViewer-BjJS7GyM.js → WorkFilesViewer-B9Sil_No.js} +1 -1
- package/dist/client/assets/{activity-Bj3Hnbj3.js → activity-DcrMApUY.js} +1 -1
- package/dist/client/assets/{addon-fit-BL-NTWRU.js → addon-fit-DMVrz5Sv.js} +1 -1
- package/dist/client/assets/{addon-webgl-CIMgmNjg.js → addon-webgl-BYvpZUyu.js} +1 -1
- package/dist/client/assets/{agent-autocomplete-DXlvdc4b.js → agent-autocomplete-B-5QTeas.js} +1 -1
- package/dist/client/assets/{agent-essentials-BOMHR0_U.js → agent-essentials-D7KRGYvF.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-DqjrVI2h.js +1 -0
- package/dist/client/assets/{agent-specialization-BIPIBW8u.js → agent-specialization-BujJVUTD.js} +1 -1
- package/dist/client/assets/{arc.es-IR5r6sj_.js → arc.es-NHqHWohb.js} +1 -1
- package/dist/client/assets/{arrow-down-BydciYFZ.js → arrow-down-CKtSUjmW.js} +1 -1
- package/dist/client/assets/{arrow-left-CghA0kTw.js → arrow-left-Czpf-AE4.js} +1 -1
- package/dist/client/assets/{arrow-right-iJFv3jNh.js → arrow-right-BuzMnLYP.js} +1 -1
- package/dist/client/assets/{arrow-up-right-CCfZXPqD.js → arrow-up-right-C6Wl-1uw.js} +1 -1
- package/dist/client/assets/{bot-B5sub1-i.js → bot-rd0awxD3.js} +1 -1
- package/dist/client/assets/{check-C18YQC90.js → check-ofKUE8yH.js} +1 -1
- package/dist/client/assets/{chevron-down-Mp9mu_yd.js → chevron-down-wciXnOQz.js} +1 -1
- package/dist/client/assets/{chevron-right-CzH-TaSF.js → chevron-right-D-HdlPg8.js} +1 -1
- package/dist/client/assets/{chunk-HRAB3GC3-swV8PA2k.js → chunk-HRAB3GC3-Tyv9rzx7.js} +1 -1
- package/dist/client/assets/{chunk-JTPDIGGW-BKXqcLKw.js → chunk-JTPDIGGW-BC2Mandc.js} +3 -3
- package/dist/client/assets/{chunk-T65CQEWV-vYbNJ8E6.js → chunk-T65CQEWV-C1AWTYZZ.js} +1 -1
- package/dist/client/assets/{chunk-YOZR3KYS-U65yUmqt.js → chunk-YOZR3KYS-DwHPHa6f.js} +1 -1
- package/dist/client/assets/{clock-B4PTFi5m.js → clock-B88r8OrZ.js} +1 -1
- package/dist/client/assets/{code-xml-Jtxsp5d1.js → code-xml-D7pOQM9l.js} +1 -1
- package/dist/client/assets/{compass-0_54-vz3.js → compass-Dt1AMXz2.js} +1 -1
- package/dist/client/assets/content-9K38QchR.js +1 -0
- package/dist/client/assets/content-BRgnyXWh.js +1 -0
- package/dist/client/assets/{content-CHghn-rT.js → content-BWPNyXJ0.js} +1 -1
- package/dist/client/assets/content-BdkI07v3.js +1 -0
- package/dist/client/assets/content-C4oWa8SB.js +1 -0
- package/dist/client/assets/content-C9ijJxyl.js +1 -0
- package/dist/client/assets/content-CFZ4rghn.js +1 -0
- package/dist/client/assets/content-CIqu_Ci_.js +1 -0
- package/dist/client/assets/content-CnJF9DGO.js +1 -0
- package/dist/client/assets/content-CriW8Y8u.js +1 -0
- package/dist/client/assets/content-DDCyPPk_.js +1 -0
- package/dist/client/assets/content-DtcZeh5m.js +1 -0
- package/dist/client/assets/content-U9tsdtle.js +1 -0
- package/dist/client/assets/content-hFLK3CON.js +1 -0
- package/dist/client/assets/{content-DMbawvqU.js → content-nkx0swDe.js} +1 -1
- package/dist/client/assets/content-p00KQrtD.js +1 -0
- package/dist/client/assets/{conversation-icons-BV10B2Me.js → conversation-icons-tp9BX6X2.js} +1 -1
- package/dist/client/assets/{conversation-model-CwF6Y9gx.js → conversation-model-Dc02NsGp.js} +1 -1
- package/dist/client/assets/conversation-motion-features-D9-RmBSq.js +1 -0
- package/dist/client/assets/{copy-Dtpx4FOE.js → copy-CWWAJ75H.js} +1 -1
- package/dist/client/assets/{cpu-BjVis9mc.js → cpu-DrqejfkB.js} +1 -1
- package/dist/client/assets/{createLucideIcon-DXpqZP7I.js → createLucideIcon-DezKXSG2.js} +1 -1
- package/dist/client/assets/{ctx-panel-D_HJ3nhb.css → ctx-panel-F05jXK4Q.css} +1 -1
- package/dist/client/assets/discover-C2CZO4Tk.js +2 -0
- package/dist/client/assets/embed-entry-BSMUykuG.js +2 -0
- package/dist/client/assets/{external-link-Ckiyzjwo.js → external-link-Dp_a2vRZ.js} +1 -1
- package/dist/client/assets/{eye-CpfyvdLq.js → eye-BRyD0jno.js} +1 -1
- package/dist/client/assets/{file-code-corner-7mo7EviR.js → file-code-corner-muIVH_xO.js} +1 -1
- package/dist/client/assets/{file-text-KijGBnME.js → file-text-CqJgwxmv.js} +1 -1
- package/dist/client/assets/{gauge-y-Xg8Mrv.js → gauge-hU--hKVP.js} +1 -1
- package/dist/client/assets/{gestures-Bq9XnSqY.js → gestures-DN4hEeqv.js} +1 -1
- package/dist/client/assets/{git-branch-BQ_x8KZL.js → git-branch-CK5v8F2v.js} +1 -1
- package/dist/client/assets/{home-moving-signal-DtRpiNa0.js → home-moving-signal-BjDtEJUP.js} +1 -1
- package/dist/client/assets/{home-now-card-DFb4GOgM.js → home-now-card-nF8OotI-.js} +1 -1
- package/dist/client/assets/{home-now-card-nano-D--m9jpq.js → home-now-card-nano-C-r_bBg5.js} +1 -1
- package/dist/client/assets/{hooks-9d1SoaQA.js → hooks-D46bABUP.js} +1 -1
- package/dist/client/assets/index-CPrU5q04.js +1 -0
- package/dist/client/assets/{index-CZ-05hKz.js → index-DvLtl7rV.js} +5 -5
- package/dist/client/assets/index-kL1WLbeS.js +1 -0
- package/dist/client/assets/index-zvhpRHao.js +1 -0
- package/dist/client/assets/{inspector-panel-C-EhEDYy.js → inspector-panel-Dkc7rLvY.js} +1 -1
- package/dist/client/assets/{keyboard-nav-DFhAJkW3.js → keyboard-nav-BLYDhL3Z.js} +1 -1
- package/dist/client/assets/{lane-roster-store-gUBsydNf.js → lane-roster-store-DOdI1O13.js} +1 -1
- package/dist/client/assets/{layers-CGou-LwV.js → layers-CSsg3JVP.js} +1 -1
- package/dist/client/assets/{layout-grid-BrZt31QH.js → layout-grid-DOChPJdZ.js} +1 -1
- package/dist/client/assets/left-B-SdEJSJ.js +1 -0
- package/dist/client/assets/{left-B_o51JV6.js → left-B3wSE6ql.js} +1 -1
- package/dist/client/assets/{left-CwHZCGO3.js → left-BNRFiRsb.js} +1 -1
- package/dist/client/assets/{left-DA0amyfu.js → left-BggzhgXN.js} +1 -1
- package/dist/client/assets/left-CARCvvxS.js +2 -0
- package/dist/client/assets/left-CpokZYHt.js +1 -0
- package/dist/client/assets/{left-CwLs0okF.js → left-YT7mIGuH.js} +1 -1
- package/dist/client/assets/{left-advisor-DU3s01gk.js → left-advisor-CCY0vkcO.js} +1 -1
- package/dist/client/assets/left-agents-trhO5sL8.js +1 -0
- package/dist/client/assets/{left-default-uvuvDmt0.js → left-default-CG33elBs.js} +1 -1
- package/dist/client/assets/{left-lanes-DnNLgec8.js → left-lanes-CitMgeTp.js} +1 -1
- package/dist/client/assets/{left-mission-DN3-NLPC.js → left-mission-Zl2m_5eU.js} +1 -1
- package/dist/client/assets/{library-DIo5NiGP.js → library-DkALuCh5.js} +1 -1
- package/dist/client/assets/{loader-circle-BiohlpM3.js → loader-circle-pM56HNhR.js} +1 -1
- package/dist/client/assets/{local-agents-wUIaBcEr.js → local-agents-C8xAhbO5.js} +1 -1
- package/dist/client/assets/{mentions-CcPFMbmZ.js → mentions-DG6OQrsc.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-BZ1h5RQs.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-ChUOASK8.js} +1 -1
- package/dist/client/assets/{message-circle-B2ddzBrX.js → message-circle-mZCv8tvB.js} +1 -1
- package/dist/client/assets/{message-markup-RkfmDfME.js → message-markup-C2LQDm_k.js} +1 -1
- package/dist/client/assets/{message-square-D9YYWE0x.js → message-square-C7t_qtuj.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-nDLdUZPA.js} +1 -1
- package/dist/client/assets/{observe-CJRIvOCn.js → observe-BpEm1INu.js} +1 -1
- package/dist/client/assets/{page-status-BptpTdQ-.js → page-status-E5jnk48p.js} +1 -1
- package/dist/client/assets/{paperclip-B1UNGl5d.js → paperclip-C64lkcbM.js} +1 -1
- package/dist/client/assets/{persistent-state-YI-WHSCF.js → persistent-state-EHXw8WNy.js} +1 -1
- package/dist/client/assets/{plus-CuU_X0-8.js → plus-Co-dqKul.js} +1 -1
- package/dist/client/assets/{profile-rY8jO38P.js → profile-APxDsN2P.js} +1 -1
- package/dist/client/assets/projects-inbox-Cg4X2lUQ.js +1 -0
- package/dist/client/assets/projects-inbox-DRBl2N85.css +1 -0
- package/dist/client/assets/{proxy-DnLpZIi9.js → proxy-BiW5suC7.js} +1 -1
- package/dist/client/assets/{radio-Dm1ItnA4.js → radio-BOxBQX-T.js} +1 -1
- package/dist/client/assets/{refresh-cw-BRn9Oxxl.js → refresh-cw-DMxGzDwn.js} +1 -1
- package/dist/client/assets/resolve-panes-DeVJbS9c.js +1 -0
- package/dist/client/assets/resolve-sidebar-context-BQe5J6xF.js +1 -0
- package/dist/client/assets/{right-BJltPRnd.js → right-Bmfd3pjP.js} +1 -1
- package/dist/client/assets/{right-Beh3nCUB.js → right-BqI-nr9G.js} +1 -1
- package/dist/client/assets/{right-D3aTKf1F.js → right-BuCgE0fZ.js} +1 -1
- package/dist/client/assets/{right-Shpw_xDy.js → right-BwlW6E57.js} +1 -1
- package/dist/client/assets/{right-CPP7GyOm.js → right-C0ybUw0j.js} +1 -1
- package/dist/client/assets/{right-BbyYdzHn.js → right-CdkcrmeD.js} +1 -1
- package/dist/client/assets/{right-CJnB_Bg7.js → right-CimaAvQN.js} +1 -1
- package/dist/client/assets/{right-C1yumXNx.js → right-CkCCPbCX.js} +1 -1
- package/dist/client/assets/{right-DI1B79nR.js → right-D3eSiy41.js} +1 -1
- package/dist/client/assets/{right-DtsRNX5b.js → right-Dz_xD0Vj.js} +1 -1
- package/dist/client/assets/{rocket-DOwXHKWA.js → rocket-BQm5_CvR.js} +1 -1
- package/dist/client/assets/router-B9vQkNJL.js +1 -0
- package/dist/client/assets/{scope-views-A4_vP97W.js → scope-views-1IYJdl41.js} +1 -1
- package/dist/client/assets/{scout-voice-BhPzrc6P.js → scout-voice-BVUqGhth.js} +1 -1
- package/dist/client/assets/{scoutbot-markdown-jh7tzFB1.js → scoutbot-markdown-BQ_Ee2Ic.js} +1 -1
- package/dist/client/assets/{scroll-text-DO0GQzvN.js → scroll-text-Dze_dXtQ.js} +1 -1
- package/dist/client/assets/{search-D1tJSAWe.js → search-CDko0PKE.js} +1 -1
- package/dist/client/assets/{secondaryNavConfig-B9IF8wXl.js → secondaryNavConfig-BoQ_zYR9.js} +1 -1
- package/dist/client/assets/{selection-bridge-i2S9zpf8.js → selection-bridge-Din6yV3h.js} +1 -1
- package/dist/client/assets/{send-horizontal-CgLppsIC.js → send-horizontal-CSjIm6xg.js} +1 -1
- package/dist/client/assets/{server-Dymv5Emh.js → server-Bzj7lPIx.js} +1 -1
- package/dist/client/assets/{session-catalog-DNaOEzoQ.js → session-catalog-DsaZJXZt.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-BQfR7u6r.js} +1 -1
- package/dist/client/assets/{settings-2fC_G9nX.js → settings-Dyvpkb1D.js} +1 -1
- package/dist/client/assets/{sliders-horizontal-BPSMHhbm.js → sliders-horizontal-C8njVwfg.js} +1 -1
- package/dist/client/assets/{sparkles-Dy8p5xN8.js → sparkles-CETYrxGA.js} +1 -1
- package/dist/client/assets/{sse-CiOSzE5n.js → sse-CD9MMUxl.js} +1 -1
- package/dist/client/assets/{tail-events-BMQmSx1n.js → tail-events-Ps8KpKah.js} +1 -1
- package/dist/client/assets/{terminal-yN9xN-h9.js → terminal-9GRS_Qdc.js} +1 -1
- package/dist/client/assets/{terminal-relay-9lhzEp2V.js → terminal-relay-GYMIvKs1.js} +1 -1
- package/dist/client/assets/{terminal-takeover-DANQfTcy.js → terminal-takeover-_Jyys4me.js} +1 -1
- package/dist/client/assets/{text-CnZ0e1-V.js → text-BP3oyl8-.js} +1 -1
- package/dist/client/assets/{text-rLpBg4_z.css → text-BYAFNLNq.css} +1 -1
- package/dist/client/assets/{use-conversation-list-D9BNLfnW.js → use-conversation-list-C9ABzjXI.js} +1 -1
- package/dist/client/assets/use-fleet-active-asks-DAspZQjE.js +1 -0
- package/dist/client/assets/{use-mesh-ops-items-BIvIHlqe.js → use-mesh-ops-items-Dh54ymEp.js} +1 -1
- package/dist/client/assets/{use-reduced-motion-CKkhq9c5.js → use-reduced-motion-x8pJMVrG.js} +1 -1
- package/dist/client/assets/{use-scout-dev-flags-B2KCzPxn.js → use-scout-dev-flags-DhCbiDK3.js} +1 -1
- package/dist/client/assets/{useAgentHoverCard-CHBsxcbp.js → useAgentHoverCard-DoBwV0LX.js} +1 -1
- package/dist/client/assets/useContentSecondaryNav-pZe2Zfk1.js +1 -0
- package/dist/client/assets/{usePierreRuntime-DUuXH5yp.js → usePierreRuntime-ejq9dCWV.js} +1 -1
- package/dist/client/assets/{wrench-YcXMlsh2.js → wrench-DjkoAOQt.js} +1 -1
- package/dist/client/assets/{x-e3h2hDsp.js → x-CAbNespN.js} +1 -1
- package/dist/client/assets/{xterm-Byp1Hep_.js → xterm-Cf-ngcGP.js} +1 -1
- package/dist/client/assets/{zap-nMcjPoWB.js → zap-Cq8eWkcF.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 +1306 -360
- package/dist/node/main.mjs +314 -12
- package/dist/pairing-runtime-controller.mjs +608 -108
- package/dist/runtime/base-daemon.mjs +30 -3
- package/dist/runtime/broker-daemon.mjs +4771 -529
- package/dist/runtime/broker-process-manager.mjs +23 -2
- package/dist/runtime/mesh-discover.mjs +23 -2
- package/dist/scout-control-plane-web.mjs +1914 -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/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/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",
|
|
@@ -9769,6 +10057,7 @@ var init_broker_routes = __esm(() => {
|
|
|
9769
10057
|
home: "/v1/home",
|
|
9770
10058
|
node: "/v1/node",
|
|
9771
10059
|
snapshot: "/v1/snapshot",
|
|
10060
|
+
conversationProjection: "/v1/conversation-projection",
|
|
9772
10061
|
capabilities: "/v1/capabilities",
|
|
9773
10062
|
runtimeCatalog: "/v1/runtime-catalog",
|
|
9774
10063
|
topologySnapshot: "/v1/topology/snapshot",
|
|
@@ -9837,6 +10126,7 @@ var init_src = __esm(() => {
|
|
|
9837
10126
|
init_budget();
|
|
9838
10127
|
init_host_integrations();
|
|
9839
10128
|
init_native_interactions();
|
|
10129
|
+
init_session_handle();
|
|
9840
10130
|
init_runtime_profiles();
|
|
9841
10131
|
init_runtime_execution();
|
|
9842
10132
|
init_runtime_catalog();
|
|
@@ -15281,6 +15571,9 @@ var init_budget_observations = __esm(() => {
|
|
|
15281
15571
|
QUOTA_HISTORY_BUCKET_MS = 60 * 60 * 1000;
|
|
15282
15572
|
});
|
|
15283
15573
|
|
|
15574
|
+
// packages/runtime/src/runtime-session-handle.ts
|
|
15575
|
+
var init_runtime_session_handle = () => {};
|
|
15576
|
+
|
|
15284
15577
|
// packages/runtime/src/sqlite-store.ts
|
|
15285
15578
|
var RUNTIME_SESSION_RETENTION_MS;
|
|
15286
15579
|
var init_sqlite_store = __esm(() => {
|
|
@@ -15292,6 +15585,7 @@ var init_sqlite_store = __esm(() => {
|
|
|
15292
15585
|
init_api();
|
|
15293
15586
|
init_drizzle_schema();
|
|
15294
15587
|
init_budget_observations();
|
|
15588
|
+
init_runtime_session_handle();
|
|
15295
15589
|
RUNTIME_SESSION_RETENTION_MS = 30 * 24 * 60 * 60 * 1000;
|
|
15296
15590
|
});
|
|
15297
15591
|
|
|
@@ -32595,10 +32889,12 @@ var init_iroh_bridge = __esm(() => {
|
|
|
32595
32889
|
var init_mesh_dial_order = () => {};
|
|
32596
32890
|
|
|
32597
32891
|
// packages/runtime/src/mesh-forwarding.ts
|
|
32892
|
+
var MAX_PEER_AGENT_SNAPSHOT_BYTES;
|
|
32598
32893
|
var init_mesh_forwarding = __esm(() => {
|
|
32599
32894
|
init_iroh_bridge();
|
|
32600
32895
|
init_mesh_peer_client();
|
|
32601
32896
|
init_mesh_dial_order();
|
|
32897
|
+
MAX_PEER_AGENT_SNAPSHOT_BYTES = 2 * 1024 * 1024;
|
|
32602
32898
|
});
|
|
32603
32899
|
|
|
32604
32900
|
// packages/runtime/src/broker-api.ts
|
|
@@ -33406,11 +33702,32 @@ function resolveBundledRuntimeDirFromModuleDir(moduleDir) {
|
|
|
33406
33702
|
resolve2(moduleDir, "..", "..")
|
|
33407
33703
|
];
|
|
33408
33704
|
for (const candidate of candidates) {
|
|
33409
|
-
if (isInstalledRuntimePackageDir(candidate))
|
|
33410
|
-
|
|
33705
|
+
if (!isInstalledRuntimePackageDir(candidate))
|
|
33706
|
+
continue;
|
|
33707
|
+
const sourceWorkspaceRuntime = resolveSourceWorkspaceRuntimeDir(candidate);
|
|
33708
|
+
if (sourceWorkspaceRuntime)
|
|
33709
|
+
return sourceWorkspaceRuntime;
|
|
33710
|
+
return candidate;
|
|
33411
33711
|
}
|
|
33412
33712
|
return null;
|
|
33413
33713
|
}
|
|
33714
|
+
function resolveSourceWorkspaceRuntimeDir(bundledPackageDir) {
|
|
33715
|
+
const packagesDir = dirname6(bundledPackageDir);
|
|
33716
|
+
if (resolve2(packagesDir, "cli") !== resolve2(bundledPackageDir))
|
|
33717
|
+
return null;
|
|
33718
|
+
const runtimeDir = join8(packagesDir, "runtime");
|
|
33719
|
+
if (!existsSync8(join8(runtimeDir, "src")))
|
|
33720
|
+
return null;
|
|
33721
|
+
if (!isInstalledRuntimePackageDir(runtimeDir))
|
|
33722
|
+
return null;
|
|
33723
|
+
try {
|
|
33724
|
+
const cliPackage = JSON.parse(readFileSync5(join8(bundledPackageDir, "package.json"), "utf8"));
|
|
33725
|
+
const runtimePackage = JSON.parse(readFileSync5(join8(runtimeDir, "package.json"), "utf8"));
|
|
33726
|
+
return cliPackage.name === "@openscout/scout" && runtimePackage.name === "@openscout/runtime" ? runtimeDir : null;
|
|
33727
|
+
} catch {
|
|
33728
|
+
return null;
|
|
33729
|
+
}
|
|
33730
|
+
}
|
|
33414
33731
|
function findWorkspaceRuntimeDir(startDir) {
|
|
33415
33732
|
let current = resolve2(startDir);
|
|
33416
33733
|
while (true) {
|
|
@@ -54137,6 +54454,7 @@ var TERMINAL_ENDPOINT_STATES;
|
|
|
54137
54454
|
var init_broker_endpoint_selection = __esm(() => {
|
|
54138
54455
|
init_a2a_http_endpoint();
|
|
54139
54456
|
init_local_agent_transports();
|
|
54457
|
+
init_runtime_session_handle();
|
|
54140
54458
|
TERMINAL_ENDPOINT_STATES = new Set([
|
|
54141
54459
|
"failed",
|
|
54142
54460
|
"superseded",
|
|
@@ -57632,6 +57950,14 @@ function resolveScoutWebBindHost(env) {
|
|
|
57632
57950
|
}
|
|
57633
57951
|
return host;
|
|
57634
57952
|
}
|
|
57953
|
+
function resolveScoutWebLanAccessScope(env) {
|
|
57954
|
+
const scope = env.OPENSCOUT_WEB_LAN_SCOPE?.trim().toLowerCase();
|
|
57955
|
+
if (!scope || scope === "full")
|
|
57956
|
+
return "full";
|
|
57957
|
+
if (scope === "pairing")
|
|
57958
|
+
return "pairing";
|
|
57959
|
+
throw new Error(`Unsupported OPENSCOUT_WEB_LAN_SCOPE: ${scope}`);
|
|
57960
|
+
}
|
|
57635
57961
|
function constantTimeTokenMatch(candidate, expected) {
|
|
57636
57962
|
if (!candidate)
|
|
57637
57963
|
return false;
|
|
@@ -57673,20 +57999,29 @@ function scoutWebAuthCookie(token, secure) {
|
|
|
57673
57999
|
function localInterfaceAddresses() {
|
|
57674
58000
|
return Object.values(networkInterfaces2()).flatMap((entries) => entries ?? []).map((entry) => entry.address);
|
|
57675
58001
|
}
|
|
57676
|
-
function
|
|
58002
|
+
function isSameMacScoutRequest(request, peerAddress, ownAddresses = localInterfaceAddresses()) {
|
|
57677
58003
|
if (!peerAddress || !isLoopbackScoutAddress(peerAddress))
|
|
57678
58004
|
return false;
|
|
57679
58005
|
if (request.headers.has("forwarded"))
|
|
57680
58006
|
return false;
|
|
57681
|
-
const
|
|
57682
|
-
|
|
57683
|
-
|
|
57684
|
-
|
|
57685
|
-
|
|
57686
|
-
|
|
57687
|
-
|
|
57688
|
-
|
|
57689
|
-
|
|
58007
|
+
const forwardedAddresses = [
|
|
58008
|
+
request.headers.get("x-forwarded-for"),
|
|
58009
|
+
request.headers.get("x-real-ip")
|
|
58010
|
+
].filter((value) => value !== null);
|
|
58011
|
+
for (const value of forwardedAddresses) {
|
|
58012
|
+
if (value.includes(","))
|
|
58013
|
+
return false;
|
|
58014
|
+
const clientAddress = normalizeIpAddress(value);
|
|
58015
|
+
if (!clientAddress)
|
|
58016
|
+
return false;
|
|
58017
|
+
if (!isLoopbackScoutAddress(clientAddress) && !ownAddresses.some((address) => normalizeIpAddress(address) === clientAddress)) {
|
|
58018
|
+
return false;
|
|
58019
|
+
}
|
|
58020
|
+
}
|
|
58021
|
+
return true;
|
|
58022
|
+
}
|
|
58023
|
+
function shouldIssueLocalScoutWebCredential(request, peerAddress, ownAddresses = localInterfaceAddresses()) {
|
|
58024
|
+
return isSameMacScoutRequest(request, peerAddress, ownAddresses);
|
|
57690
58025
|
}
|
|
57691
58026
|
function normalizeIpAddress(address) {
|
|
57692
58027
|
const normalized = normalizeHostname(address);
|
|
@@ -57728,13 +58063,32 @@ function isLoopbackScoutAddress(address) {
|
|
|
57728
58063
|
const mapped = normalized.startsWith("::ffff:") ? normalized.slice(7) : normalized;
|
|
57729
58064
|
return LOOPBACK_IPV4_HOST_PATTERN.test(mapped);
|
|
57730
58065
|
}
|
|
57731
|
-
function
|
|
58066
|
+
function resolveScoutRequestPeerAddress(c) {
|
|
57732
58067
|
try {
|
|
57733
58068
|
return getConnInfo(c).remote.address;
|
|
57734
58069
|
} catch {
|
|
57735
58070
|
return;
|
|
57736
58071
|
}
|
|
57737
58072
|
}
|
|
58073
|
+
function createScoutRequestPeerAddressRegistry() {
|
|
58074
|
+
const peers = new WeakMap;
|
|
58075
|
+
return {
|
|
58076
|
+
remember(request, address) {
|
|
58077
|
+
if (address)
|
|
58078
|
+
peers.set(request, address);
|
|
58079
|
+
},
|
|
58080
|
+
resolve(c) {
|
|
58081
|
+
return peers.get(c.req.raw) ?? resolveScoutRequestPeerAddress(c);
|
|
58082
|
+
}
|
|
58083
|
+
};
|
|
58084
|
+
}
|
|
58085
|
+
function isScoutWebRequestAllowedFromPeer(request, peerAddress, scope) {
|
|
58086
|
+
if (scope === "full" || isSameMacScoutRequest(request, peerAddress)) {
|
|
58087
|
+
return true;
|
|
58088
|
+
}
|
|
58089
|
+
const url = new URL(request.url);
|
|
58090
|
+
return request.method === "GET" && url.pathname === "/pair" && request.headers.get("upgrade") === null;
|
|
58091
|
+
}
|
|
57738
58092
|
function isTrustedScoutApiRequest(request, options = {}, peerAddress) {
|
|
57739
58093
|
const requestUrl = new URL(request.url);
|
|
57740
58094
|
const hostname2 = normalizeHostname(requestUrl.hostname);
|
|
@@ -57880,7 +58234,7 @@ function scoutApiPerfReport() {
|
|
|
57880
58234
|
}
|
|
57881
58235
|
function installScoutApiMiddleware(app, label = "api", options = {}) {
|
|
57882
58236
|
app.use("/api/*", async (c, next) => {
|
|
57883
|
-
const peerAddress = (options.resolvePeerAddress ??
|
|
58237
|
+
const peerAddress = (options.resolvePeerAddress ?? resolveScoutRequestPeerAddress)(c);
|
|
57884
58238
|
if (!isTrustedScoutApiRequest(c.req.raw, options, peerAddress)) {
|
|
57885
58239
|
return c.json({ error: "forbidden" }, 403);
|
|
57886
58240
|
}
|
|
@@ -58451,6 +58805,19 @@ async function readScoutBrokerHome(baseUrl = resolveScoutBrokerUrl(), options =
|
|
|
58451
58805
|
return null;
|
|
58452
58806
|
}
|
|
58453
58807
|
}
|
|
58808
|
+
async function readScoutConversationProjection(limit = 160, baseUrl = resolveScoutBrokerUrl(), options = {}) {
|
|
58809
|
+
const query = new URLSearchParams({
|
|
58810
|
+
limit: String(Math.min(160, Math.max(1, Math.floor(limit))))
|
|
58811
|
+
});
|
|
58812
|
+
try {
|
|
58813
|
+
return await brokerReadJson(baseUrl, `${scoutBrokerPaths.v1.conversationProjection}?${query}`, {
|
|
58814
|
+
...options,
|
|
58815
|
+
signal: options.signal ?? AbortSignal.timeout(450)
|
|
58816
|
+
});
|
|
58817
|
+
} catch {
|
|
58818
|
+
return null;
|
|
58819
|
+
}
|
|
58820
|
+
}
|
|
58454
58821
|
async function readScoutBrokerRuntimeCatalog(baseUrl = resolveScoutBrokerUrl()) {
|
|
58455
58822
|
try {
|
|
58456
58823
|
return await brokerReadJson(baseUrl, scoutBrokerPaths.v1.runtimeCatalog);
|
|
@@ -58458,6 +58825,13 @@ async function readScoutBrokerRuntimeCatalog(baseUrl = resolveScoutBrokerUrl())
|
|
|
58458
58825
|
return null;
|
|
58459
58826
|
}
|
|
58460
58827
|
}
|
|
58828
|
+
async function readScoutBrokerTailDiscovery(baseUrl = resolveScoutBrokerUrl()) {
|
|
58829
|
+
try {
|
|
58830
|
+
return await brokerReadJson(baseUrl, scoutBrokerPaths.v1.tailDiscover);
|
|
58831
|
+
} catch {
|
|
58832
|
+
return null;
|
|
58833
|
+
}
|
|
58834
|
+
}
|
|
58461
58835
|
async function readScoutBrokerSnapshot(baseUrl = resolveScoutBrokerUrl(), options = {}) {
|
|
58462
58836
|
try {
|
|
58463
58837
|
return await brokerReadJson(baseUrl, scoutBrokerPaths.v1.snapshot, options);
|
|
@@ -58495,26 +58869,24 @@ async function recordScoutBrokerReadCursor(input, baseUrl = resolveScoutBrokerUr
|
|
|
58495
58869
|
});
|
|
58496
58870
|
}
|
|
58497
58871
|
async function loadScoutBrokerContext(baseUrl = resolveScoutBrokerUrl(), options = {}) {
|
|
58498
|
-
const
|
|
58872
|
+
const usesRollingWindow = options.since === undefined;
|
|
58873
|
+
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
58874
|
if (options.force) {
|
|
58500
58875
|
invalidateScoutBrokerContextCache(baseUrl);
|
|
58501
58876
|
}
|
|
58502
58877
|
const cacheKey = options.signal ? null : [
|
|
58503
58878
|
baseUrl,
|
|
58504
58879
|
resolveBrokerSocketPathForBaseUrl(baseUrl) ?? "http",
|
|
58505
|
-
since ?? "full",
|
|
58880
|
+
usesRollingWindow ? "rolling-24h" : since ?? "full",
|
|
58506
58881
|
options.scope ?? "default"
|
|
58507
58882
|
].join("\x00");
|
|
58508
58883
|
const now = Date.now();
|
|
58509
|
-
for (const [key,
|
|
58510
|
-
if (
|
|
58884
|
+
for (const [key, entry2] of scoutBrokerContextCache) {
|
|
58885
|
+
if (key !== cacheKey && !entry2.inFlight && entry2.expiresAt + SCOUT_BROKER_CONTEXT_STALE_RETENTION_MS <= now) {
|
|
58511
58886
|
scoutBrokerContextCache.delete(key);
|
|
58887
|
+
}
|
|
58512
58888
|
}
|
|
58513
|
-
const
|
|
58514
|
-
if (cached && cached.expiresAt > now) {
|
|
58515
|
-
return cached.promise;
|
|
58516
|
-
}
|
|
58517
|
-
const promise = (async () => {
|
|
58889
|
+
const readContext = async () => {
|
|
58518
58890
|
const health = await readScoutBrokerHealth(baseUrl, { signal: options.signal });
|
|
58519
58891
|
if (!health.reachable || !health.ok) {
|
|
58520
58892
|
return null;
|
|
@@ -58538,19 +58910,60 @@ async function loadScoutBrokerContext(baseUrl = resolveScoutBrokerUrl(), options
|
|
|
58538
58910
|
} catch {
|
|
58539
58911
|
return null;
|
|
58540
58912
|
}
|
|
58541
|
-
}
|
|
58542
|
-
if (cacheKey) {
|
|
58543
|
-
|
|
58544
|
-
|
|
58545
|
-
|
|
58546
|
-
|
|
58547
|
-
|
|
58548
|
-
|
|
58913
|
+
};
|
|
58914
|
+
if (!cacheKey) {
|
|
58915
|
+
return readContext();
|
|
58916
|
+
}
|
|
58917
|
+
const refresh = (entry2, delayMs = 0) => {
|
|
58918
|
+
if (entry2.inFlight)
|
|
58919
|
+
return entry2.inFlight;
|
|
58920
|
+
const attempt = (delayMs > 0 ? new Promise((resolve17) => setTimeout(resolve17, delayMs)) : Promise.resolve()).then(readContext).then((context) => {
|
|
58921
|
+
if (scoutBrokerContextCache.get(cacheKey) !== entry2)
|
|
58922
|
+
return context;
|
|
58923
|
+
if (context) {
|
|
58924
|
+
entry2.value = context;
|
|
58925
|
+
entry2.hasValue = true;
|
|
58926
|
+
entry2.expiresAt = Date.now() + SCOUT_BROKER_CONTEXT_CACHE_TTL_MS;
|
|
58927
|
+
} else if (!entry2.hasValue) {
|
|
58549
58928
|
scoutBrokerContextCache.delete(cacheKey);
|
|
58929
|
+
} else {
|
|
58930
|
+
entry2.expiresAt = Date.now() + SCOUT_BROKER_CONTEXT_CACHE_TTL_MS;
|
|
58931
|
+
}
|
|
58932
|
+
return context;
|
|
58933
|
+
}).finally(() => {
|
|
58934
|
+
if (scoutBrokerContextCache.get(cacheKey) === entry2) {
|
|
58935
|
+
entry2.inFlight = null;
|
|
58550
58936
|
}
|
|
58551
58937
|
});
|
|
58938
|
+
entry2.inFlight = attempt;
|
|
58939
|
+
return attempt;
|
|
58940
|
+
};
|
|
58941
|
+
const cached = scoutBrokerContextCache.get(cacheKey);
|
|
58942
|
+
if (cached) {
|
|
58943
|
+
if (cached.hasValue) {
|
|
58944
|
+
if (cached.expiresAt <= now && !cached.inFlight) {
|
|
58945
|
+
refresh(cached);
|
|
58946
|
+
}
|
|
58947
|
+
return cached.value;
|
|
58948
|
+
}
|
|
58949
|
+
if (options.waitForInitial === false) {
|
|
58950
|
+
refresh(cached, options.initialRefreshDelayMs);
|
|
58951
|
+
return null;
|
|
58952
|
+
}
|
|
58953
|
+
return refresh(cached);
|
|
58552
58954
|
}
|
|
58553
|
-
|
|
58955
|
+
const entry = {
|
|
58956
|
+
expiresAt: now + SCOUT_BROKER_CONTEXT_CACHE_TTL_MS,
|
|
58957
|
+
value: null,
|
|
58958
|
+
hasValue: false,
|
|
58959
|
+
inFlight: null
|
|
58960
|
+
};
|
|
58961
|
+
scoutBrokerContextCache.set(cacheKey, entry);
|
|
58962
|
+
if (options.waitForInitial === false) {
|
|
58963
|
+
refresh(entry, options.initialRefreshDelayMs);
|
|
58964
|
+
return null;
|
|
58965
|
+
}
|
|
58966
|
+
return refresh(entry);
|
|
58554
58967
|
}
|
|
58555
58968
|
async function requireScoutBrokerContext(baseUrl = resolveScoutBrokerUrl()) {
|
|
58556
58969
|
const context = await loadScoutBrokerContext(baseUrl);
|
|
@@ -59336,14 +59749,11 @@ async function loadScoutReadCursors(input) {
|
|
|
59336
59749
|
return brokerReadJson(input.baseUrl ?? resolveScoutBrokerUrl(), path);
|
|
59337
59750
|
}
|
|
59338
59751
|
async function markScoutConversationRead(input) {
|
|
59339
|
-
const
|
|
59340
|
-
if (!broker2) {
|
|
59341
|
-
throw new Error("broker unreachable");
|
|
59342
|
-
}
|
|
59752
|
+
const baseUrl = input.baseUrl ?? resolveScoutBrokerUrl();
|
|
59343
59753
|
const path = `/v1/conversations/${encodeURIComponent(input.conversationId)}/read-cursors`;
|
|
59344
|
-
return brokerPostJson(
|
|
59754
|
+
return brokerPostJson(baseUrl, path, {
|
|
59345
59755
|
actorId: input.actorId,
|
|
59346
|
-
readerNodeId: input.readerNodeId
|
|
59756
|
+
readerNodeId: input.readerNodeId,
|
|
59347
59757
|
lastReadMessageId: input.lastReadMessageId,
|
|
59348
59758
|
lastReadSeq: input.lastReadSeq,
|
|
59349
59759
|
lastReadAt: input.lastReadAt,
|
|
@@ -59507,7 +59917,7 @@ async function loadScoutRelayConfig() {
|
|
|
59507
59917
|
return {};
|
|
59508
59918
|
}
|
|
59509
59919
|
}
|
|
59510
|
-
var DEFAULT_SCOUT_BROKER_SNAPSHOT_WINDOW_MS, DEFAULT_SCOUT_BROKER_SNAPSHOT_BUCKET_MS, SCOUT_BROKER_CONTEXT_CACHE_TTL_MS =
|
|
59920
|
+
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
59921
|
var init_service = __esm(() => {
|
|
59512
59922
|
init_src();
|
|
59513
59923
|
init_setup();
|
|
@@ -60886,14 +61296,47 @@ function existingDirectConversationIdsForAgents(agentIds) {
|
|
|
60886
61296
|
}
|
|
60887
61297
|
return conversationIdByAgentId;
|
|
60888
61298
|
}
|
|
61299
|
+
function queryAgentIdsForBoundedRoster(limit) {
|
|
61300
|
+
const database = db2();
|
|
61301
|
+
let recentIds;
|
|
61302
|
+
try {
|
|
61303
|
+
recentIds = database.prepare(RECENT_ENDPOINT_AGENT_IDS_SQL).all(limit);
|
|
61304
|
+
} catch (error) {
|
|
61305
|
+
if (!(error instanceof Error) || !error.message.includes("idx_agent_endpoints_roster_recency")) {
|
|
61306
|
+
throw error;
|
|
61307
|
+
}
|
|
61308
|
+
recentIds = database.prepare(RECENT_ENDPOINT_AGENT_IDS_WITHOUT_INDEX_SQL).all(limit);
|
|
61309
|
+
}
|
|
61310
|
+
if (recentIds.length >= limit) {
|
|
61311
|
+
return recentIds.map((row) => row.id);
|
|
61312
|
+
}
|
|
61313
|
+
const endpointUpdatedAtExpression2 = sqlTimestampMsExpression("ep.updated_at");
|
|
61314
|
+
const fallbackIds = database.prepare(`SELECT a.id
|
|
61315
|
+
FROM agents a
|
|
61316
|
+
JOIN actors ac ON ac.id = a.id
|
|
61317
|
+
${LATEST_AGENT_ENDPOINT_JOIN}
|
|
61318
|
+
WHERE ${activeAgentMetadataPredicate("a")}
|
|
61319
|
+
AND COALESCE(${endpointUpdatedAtExpression2}, 0) <= 0
|
|
61320
|
+
ORDER BY COALESCE(${endpointUpdatedAtExpression2}, 0) DESC, ac.display_name ASC
|
|
61321
|
+
LIMIT ?`).all(limit - recentIds.length);
|
|
61322
|
+
return [...recentIds, ...fallbackIds].map((row) => row.id);
|
|
61323
|
+
}
|
|
61324
|
+
function queryAgentRowsByIds(agentIds) {
|
|
61325
|
+
if (agentIds.length === 0)
|
|
61326
|
+
return [];
|
|
61327
|
+
return db2().prepare(`${AGENT_ROW_SELECT}
|
|
61328
|
+
WHERE a.id IN (SELECT value FROM json_each(?))
|
|
61329
|
+
AND ${activeAgentMetadataPredicate("a")}
|
|
61330
|
+
ORDER BY COALESCE(${endpointUpdatedAtExpression}, 0) DESC, ac.display_name ASC`).all(JSON.stringify(agentIds));
|
|
61331
|
+
}
|
|
60889
61332
|
function queryAgentIdsByEndpointSessionId() {
|
|
60890
|
-
const
|
|
61333
|
+
const endpointUpdatedAtExpression2 = sqlTimestampMsExpression("ep.updated_at");
|
|
60891
61334
|
const rows = db2().prepare(`SELECT a.id, ep.session_id
|
|
60892
61335
|
FROM agents a
|
|
60893
61336
|
${LATEST_AGENT_ENDPOINT_JOIN}
|
|
60894
61337
|
WHERE ep.session_id IS NOT NULL
|
|
60895
61338
|
AND ${activeAgentMetadataPredicate("a")}
|
|
60896
|
-
ORDER BY COALESCE(${
|
|
61339
|
+
ORDER BY COALESCE(${endpointUpdatedAtExpression2}, 0) ASC`).all();
|
|
60897
61340
|
const map = new Map;
|
|
60898
61341
|
for (const row of rows) {
|
|
60899
61342
|
const sessionId = row.session_id.trim();
|
|
@@ -60905,87 +61348,20 @@ function queryAgentIdsByEndpointSessionId() {
|
|
|
60905
61348
|
}
|
|
60906
61349
|
function queryAgents(limit = 500) {
|
|
60907
61350
|
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);
|
|
61351
|
+
let rows;
|
|
61352
|
+
if (limit < 0) {
|
|
61353
|
+
rows = db2().prepare(`${AGENT_ROW_SELECT}
|
|
61354
|
+
WHERE ${activeAgentMetadataPredicate("a")}
|
|
61355
|
+
ORDER BY COALESCE(${endpointUpdatedAtExpression}, 0) DESC, ac.display_name ASC
|
|
61356
|
+
LIMIT ?`).all(limit);
|
|
61357
|
+
} else {
|
|
61358
|
+
rows = queryAgentRowsByIds(queryAgentIdsForBoundedRoster(limit));
|
|
61359
|
+
}
|
|
60948
61360
|
return mapAgentRows(rows, flightPhases, existingDirectConversationIdsForAgents(rows.map((row) => row.id)));
|
|
60949
61361
|
}
|
|
60950
61362
|
function queryAgentById(agentId) {
|
|
60951
61363
|
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}
|
|
61364
|
+
const row = db2().prepare(`${AGENT_ROW_SELECT}
|
|
60989
61365
|
WHERE a.id = ?
|
|
60990
61366
|
AND ${activeAgentMetadataPredicate("a")}
|
|
60991
61367
|
LIMIT 1`).get(agentId);
|
|
@@ -61051,12 +61427,70 @@ function mapAgentRows(rows, flightPhases, conversationIdByAgentId) {
|
|
|
61051
61427
|
};
|
|
61052
61428
|
});
|
|
61053
61429
|
}
|
|
61430
|
+
var actorCreatedAtExpression, endpointUpdatedAtExpression, AGENT_ROW_SELECT, RECENT_ENDPOINT_AGENT_IDS_WITHOUT_INDEX_SQL, RECENT_ENDPOINT_AGENT_IDS_SQL;
|
|
61054
61431
|
var init_agents = __esm(() => {
|
|
61055
61432
|
init_src();
|
|
61056
61433
|
init_db2();
|
|
61057
61434
|
init_parse2();
|
|
61058
61435
|
init_paths3();
|
|
61059
61436
|
init_sql_helpers();
|
|
61437
|
+
actorCreatedAtExpression = sqlTimestampMsExpression("ac.created_at");
|
|
61438
|
+
endpointUpdatedAtExpression = sqlTimestampMsExpression("ep.updated_at");
|
|
61439
|
+
AGENT_ROW_SELECT = `SELECT
|
|
61440
|
+
a.id,
|
|
61441
|
+
a.definition_id,
|
|
61442
|
+
a.node_qualifier,
|
|
61443
|
+
a.workspace_qualifier,
|
|
61444
|
+
a.selector,
|
|
61445
|
+
ac.display_name AS name,
|
|
61446
|
+
ac.handle,
|
|
61447
|
+
${actorCreatedAtExpression} AS actor_created_at,
|
|
61448
|
+
a.agent_class,
|
|
61449
|
+
a.default_selector,
|
|
61450
|
+
a.wake_policy,
|
|
61451
|
+
a.capabilities_json,
|
|
61452
|
+
a.metadata_json,
|
|
61453
|
+
a.authority_node_id,
|
|
61454
|
+
an.name AS authority_node_name,
|
|
61455
|
+
a.home_node_id,
|
|
61456
|
+
hn.name AS home_node_name,
|
|
61457
|
+
a.owner_id,
|
|
61458
|
+
oa.display_name AS owner_name,
|
|
61459
|
+
oa.handle AS owner_handle,
|
|
61460
|
+
ep.harness,
|
|
61461
|
+
ep.transport,
|
|
61462
|
+
ep.state,
|
|
61463
|
+
ep.project_root,
|
|
61464
|
+
ep.cwd,
|
|
61465
|
+
ep.session_id,
|
|
61466
|
+
ep.metadata_json AS endpoint_metadata_json,
|
|
61467
|
+
${endpointUpdatedAtExpression} AS updated_at
|
|
61468
|
+
FROM agents a
|
|
61469
|
+
JOIN actors ac ON ac.id = a.id
|
|
61470
|
+
LEFT JOIN nodes an ON an.id = a.authority_node_id
|
|
61471
|
+
LEFT JOIN nodes hn ON hn.id = a.home_node_id
|
|
61472
|
+
LEFT JOIN actors oa ON oa.id = a.owner_id
|
|
61473
|
+
${LATEST_AGENT_ENDPOINT_JOIN}`;
|
|
61474
|
+
RECENT_ENDPOINT_AGENT_IDS_WITHOUT_INDEX_SQL = (() => {
|
|
61475
|
+
const endpointUpdatedAtExpression2 = sqlTimestampMsExpression("ep.updated_at");
|
|
61476
|
+
const latestEndpointUpdatedAtExpression = sqlTimestampMsCoalesceExpression("ep2.updated_at");
|
|
61477
|
+
return `SELECT a.id
|
|
61478
|
+
FROM agent_endpoints ep
|
|
61479
|
+
JOIN agents a ON a.id = ep.agent_id
|
|
61480
|
+
JOIN actors ac ON ac.id = a.id
|
|
61481
|
+
WHERE ep.id = (
|
|
61482
|
+
SELECT ep2.id
|
|
61483
|
+
FROM agent_endpoints ep2
|
|
61484
|
+
WHERE ep2.agent_id = a.id
|
|
61485
|
+
ORDER BY ${latestEndpointUpdatedAtExpression} DESC
|
|
61486
|
+
LIMIT 1
|
|
61487
|
+
)
|
|
61488
|
+
AND ${endpointUpdatedAtExpression2} > 0
|
|
61489
|
+
AND ${activeAgentMetadataPredicate("a")}
|
|
61490
|
+
ORDER BY ${endpointUpdatedAtExpression2} DESC, ac.display_name ASC
|
|
61491
|
+
LIMIT ?`;
|
|
61492
|
+
})();
|
|
61493
|
+
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
61494
|
});
|
|
61061
61495
|
|
|
61062
61496
|
// packages/web/server/db/internal/conversation-ids.ts
|
|
@@ -61148,7 +61582,11 @@ function queryRecentMessages(limit = 80, opts) {
|
|
|
61148
61582
|
const beforeMessage = resolveBeforeMessage(opts?.beforeMessageId, conversationIds, messageCreatedAtExpression);
|
|
61149
61583
|
const where = sqlJoinClauses([
|
|
61150
61584
|
transientBrokerWorkingStatusPredicate("m"),
|
|
61151
|
-
conversationIds.length > 0 ? `m.conversation_id IN (${sqlPlaceholders(conversationIds.length)})` :
|
|
61585
|
+
conversationIds.length > 0 ? `m.conversation_id IN (${sqlPlaceholders(conversationIds.length)})` : `(
|
|
61586
|
+
(m.conversation_id LIKE 'chn-%' AND length(m.conversation_id) > 4)
|
|
61587
|
+
OR (substr(m.conversation_id, 1, 5) = 'chat_' AND length(m.conversation_id) > 5)
|
|
61588
|
+
OR (m.conversation_id LIKE 'c.%' AND length(m.conversation_id) > 2)
|
|
61589
|
+
)`,
|
|
61152
61590
|
beforeMessage ? `(
|
|
61153
61591
|
${messageCreatedAtExpression} < ?
|
|
61154
61592
|
OR (${messageCreatedAtExpression} = ? AND m.id < ?)
|
|
@@ -62747,6 +63185,30 @@ function metadataString8(metadata, key) {
|
|
|
62747
63185
|
const value = metadata[key];
|
|
62748
63186
|
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
|
|
62749
63187
|
}
|
|
63188
|
+
function executionResolutionDimension(resolution, dimension) {
|
|
63189
|
+
const value = resolution?.[dimension];
|
|
63190
|
+
return value?.observed?.trim() || value?.resolved?.trim() || value?.requested?.trim() || null;
|
|
63191
|
+
}
|
|
63192
|
+
function durableConversationRuntime(row) {
|
|
63193
|
+
if (!row)
|
|
63194
|
+
return null;
|
|
63195
|
+
const execution = parseMetadataJson(row.execution_json);
|
|
63196
|
+
const rawResolution = parseMetadataJson(row.execution_resolution_json);
|
|
63197
|
+
const resolution = rawResolution.schemaVersion === "openscout.execution-resolution.v1" ? rawResolution : null;
|
|
63198
|
+
const flightMetadata = parseMetadataJson(row.flight_metadata_json);
|
|
63199
|
+
const trace = Array.isArray(flightMetadata.sessionTrace) ? [...flightMetadata.sessionTrace].reverse().find((entry) => entry && typeof entry === "object" && !Array.isArray(entry)) : undefined;
|
|
63200
|
+
const traceResolutionRaw = trace?.executionResolution;
|
|
63201
|
+
const traceResolution = traceResolutionRaw && typeof traceResolutionRaw === "object" && !Array.isArray(traceResolutionRaw) && traceResolutionRaw.schemaVersion === "openscout.execution-resolution.v1" ? traceResolutionRaw : null;
|
|
63202
|
+
const effectiveResolution = traceResolution ?? resolution;
|
|
63203
|
+
return {
|
|
63204
|
+
targetAgentId: row.target_agent_id,
|
|
63205
|
+
harness: executionResolutionDimension(effectiveResolution, "harness") ?? metadataString8(trace ?? {}, "harness") ?? metadataString8(execution, "harness"),
|
|
63206
|
+
model: executionResolutionDimension(effectiveResolution, "model") ?? metadataString8(execution, "model"),
|
|
63207
|
+
reasoningEffort: executionResolutionDimension(effectiveResolution, "reasoningEffort") ?? metadataString8(execution, "reasoningEffort"),
|
|
63208
|
+
transport: metadataString8(trace ?? {}, "transport"),
|
|
63209
|
+
sessionId: metadataString8(trace ?? {}, "sessionId") ?? resolution?.sessionId?.trim() ?? metadataString8(execution, "targetSessionId")
|
|
63210
|
+
};
|
|
63211
|
+
}
|
|
62750
63212
|
function formatChannelAlias(value) {
|
|
62751
63213
|
const trimmed = value.trim();
|
|
62752
63214
|
if (!trimmed)
|
|
@@ -62798,22 +63260,34 @@ function projectSessionConversationRows(rows, opts) {
|
|
|
62798
63260
|
AND ${transientBrokerWorkingStatusPredicate("m")}
|
|
62799
63261
|
ORDER BY ${messageCreatedAtExpression} DESC
|
|
62800
63262
|
LIMIT 1`);
|
|
63263
|
+
const runtimeStmt = db2().prepare(`SELECT target_agent_id, execution_json, execution_resolution_json, flight_metadata_json
|
|
63264
|
+
FROM invocations
|
|
63265
|
+
WHERE conversation_id = ?
|
|
63266
|
+
ORDER BY ${sqlTimestampMsExpression("created_at")} DESC, id DESC
|
|
63267
|
+
LIMIT 1`);
|
|
62801
63268
|
const summaries = rows.flatMap((r) => {
|
|
62802
63269
|
const conversationMetadata = parseMetadataJson(r.metadata_json);
|
|
62803
63270
|
const participants = memberStmt.all(r.id).map((m) => m.actor_id);
|
|
62804
63271
|
const agentParticipants = agentMemberStmt.all(r.id);
|
|
62805
|
-
const
|
|
63272
|
+
const runtime = durableConversationRuntime(runtimeStmt.get(r.id));
|
|
63273
|
+
const runtimeTargetAgentId = runtime?.targetAgentId && agentParticipants.some((entry) => entry.agent_id === runtime.targetAgentId) ? runtime.targetAgentId : null;
|
|
63274
|
+
const primaryAgentId = r.kind === "direct" ? runtimeTargetAgentId ?? pickDirectConversationAgentId(participants, agentParticipants.map((entry) => entry.agent_id)) : agentParticipants.length === 1 ? agentParticipants[0]?.agent_id ?? null : null;
|
|
62806
63275
|
const primaryAgent = primaryAgentId ? agentParticipants.find((entry) => entry.agent_id === primaryAgentId) ?? null : null;
|
|
62807
63276
|
const agentId = primaryAgent?.agent_id ?? null;
|
|
62808
63277
|
let agentName = null;
|
|
62809
|
-
let harness2 = null;
|
|
63278
|
+
let harness2 = runtime?.harness ?? null;
|
|
63279
|
+
let model2 = runtime?.model ?? null;
|
|
63280
|
+
let reasoningEffort = runtime?.reasoningEffort ?? null;
|
|
63281
|
+
let transport = runtime?.transport ?? null;
|
|
63282
|
+
let sessionId = runtime?.sessionId ?? null;
|
|
62810
63283
|
let harnessSessionId = null;
|
|
62811
63284
|
let harnessLogPath = null;
|
|
62812
63285
|
let branch = null;
|
|
62813
63286
|
let workspaceRoot = null;
|
|
62814
63287
|
if (primaryAgent) {
|
|
62815
63288
|
agentName = primaryAgent.display_name;
|
|
62816
|
-
harness2 = primaryAgent.harness;
|
|
63289
|
+
harness2 = harness2 ?? primaryAgent.harness;
|
|
63290
|
+
transport = transport ?? primaryAgent.transport;
|
|
62817
63291
|
workspaceRoot = compact(primaryAgent.project_root);
|
|
62818
63292
|
try {
|
|
62819
63293
|
const meta = primaryAgent.metadata_json ? JSON.parse(primaryAgent.metadata_json) : {};
|
|
@@ -62821,13 +63295,19 @@ function projectSessionConversationRows(rows, opts) {
|
|
|
62821
63295
|
return [];
|
|
62822
63296
|
}
|
|
62823
63297
|
branch = meta.branch ?? meta.workspaceQualifier ?? null;
|
|
63298
|
+
model2 = model2 ?? metadataString8(meta, "model");
|
|
63299
|
+
reasoningEffort = reasoningEffort ?? metadataString8(meta, "reasoningEffort");
|
|
62824
63300
|
} catch {}
|
|
62825
63301
|
try {
|
|
62826
63302
|
const endpointMeta = primaryAgent.endpoint_metadata_json ? JSON.parse(primaryAgent.endpoint_metadata_json) : {};
|
|
62827
63303
|
harnessSessionId = resolveHarnessSessionId(primaryAgent.transport, primaryAgent.session_id, endpointMeta);
|
|
63304
|
+
sessionId = sessionId ?? harnessSessionId;
|
|
63305
|
+
model2 = model2 ?? metadataString8(endpointMeta, "observedModel") ?? metadataString8(endpointMeta, "model");
|
|
63306
|
+
reasoningEffort = reasoningEffort ?? metadataString8(endpointMeta, "observedReasoningEffort") ?? metadataString8(endpointMeta, "reasoningEffort");
|
|
62828
63307
|
harnessLogPath = resolveHarnessLogPath(primaryAgent.agent_id, primaryAgent.transport, primaryAgent.session_id, endpointMeta);
|
|
62829
63308
|
} catch {
|
|
62830
63309
|
harnessSessionId = resolveHarnessSessionId(primaryAgent.transport, primaryAgent.session_id, undefined);
|
|
63310
|
+
sessionId = sessionId ?? harnessSessionId;
|
|
62831
63311
|
harnessLogPath = resolveHarnessLogPath(primaryAgent.agent_id, primaryAgent.transport, primaryAgent.session_id, undefined);
|
|
62832
63312
|
}
|
|
62833
63313
|
}
|
|
@@ -62842,6 +63322,10 @@ function projectSessionConversationRows(rows, opts) {
|
|
|
62842
63322
|
agentId,
|
|
62843
63323
|
agentName,
|
|
62844
63324
|
harness: harness2,
|
|
63325
|
+
model: model2,
|
|
63326
|
+
reasoningEffort,
|
|
63327
|
+
transport,
|
|
63328
|
+
sessionId,
|
|
62845
63329
|
harnessSessionId,
|
|
62846
63330
|
harnessLogPath,
|
|
62847
63331
|
currentBranch: branch,
|
|
@@ -62898,7 +63382,9 @@ function querySessions(limit = 80) {
|
|
|
62898
63382
|
FROM messages
|
|
62899
63383
|
GROUP BY conversation_id
|
|
62900
63384
|
) ms ON ms.conversation_id = c.id
|
|
62901
|
-
WHERE c.id LIKE '
|
|
63385
|
+
WHERE (c.id LIKE 'chn-%' AND length(c.id) > 4)
|
|
63386
|
+
OR (substr(c.id, 1, 5) = 'chat_' AND length(c.id) > 5)
|
|
63387
|
+
OR (c.id LIKE 'c.%' AND length(c.id) > 2)
|
|
62902
63388
|
ORDER BY COALESCE(ms.last_message_at, ${conversationCreatedAtExpression}, 0) DESC, ${conversationCreatedAtExpression} DESC, c.id ASC
|
|
62903
63389
|
LIMIT ?`).all(limit);
|
|
62904
63390
|
return projectSessionConversationRows(rows, {
|
|
@@ -62926,6 +63412,7 @@ function querySessionFallbackFromMessages(conversationId) {
|
|
|
62926
63412
|
m.actor_id AS agent_id,
|
|
62927
63413
|
ac.display_name,
|
|
62928
63414
|
ep.harness,
|
|
63415
|
+
ep.transport,
|
|
62929
63416
|
ep.project_root,
|
|
62930
63417
|
ep.session_id,
|
|
62931
63418
|
ep.metadata_json AS endpoint_metadata_json
|
|
@@ -62947,8 +63434,12 @@ function querySessionFallbackFromMessages(conversationId) {
|
|
|
62947
63434
|
agentId: agentRow?.agent_id ?? null,
|
|
62948
63435
|
agentName: agentRow?.display_name ?? null,
|
|
62949
63436
|
harness: agentRow?.harness ?? null,
|
|
62950
|
-
|
|
62951
|
-
|
|
63437
|
+
model: metadataString8(endpointMetadata, "observedModel") ?? metadataString8(endpointMetadata, "model"),
|
|
63438
|
+
reasoningEffort: metadataString8(endpointMetadata, "observedReasoningEffort") ?? metadataString8(endpointMetadata, "reasoningEffort"),
|
|
63439
|
+
transport: agentRow?.transport ?? null,
|
|
63440
|
+
sessionId: resolveHarnessSessionId(agentRow?.transport ?? null, agentRow?.session_id ?? null, endpointMetadata),
|
|
63441
|
+
harnessSessionId: resolveHarnessSessionId(agentRow?.transport ?? null, agentRow?.session_id ?? null, endpointMetadata),
|
|
63442
|
+
harnessLogPath: agentRow?.agent_id ? resolveHarnessLogPath(agentRow.agent_id, agentRow.transport, agentRow.session_id, endpointMetadata) : null,
|
|
62952
63443
|
currentBranch: metadataString8(endpointMetadata, "branch"),
|
|
62953
63444
|
preview: previewRow?.body?.trim() || null,
|
|
62954
63445
|
messageCount: stats.message_count,
|
|
@@ -64000,8 +64491,8 @@ function queryFleetAskRows(requesterIds, limit) {
|
|
|
64000
64491
|
ep.state AS endpoint_state,
|
|
64001
64492
|
cr.title AS work_title,
|
|
64002
64493
|
cr.summary AS work_summary,
|
|
64494
|
+
cr.kind AS record_kind,
|
|
64003
64495
|
cr.state AS work_state,
|
|
64004
|
-
cr.acceptance_state,
|
|
64005
64496
|
cr.next_move_owner_id,
|
|
64006
64497
|
cr.updated_at AS work_updated_at
|
|
64007
64498
|
FROM invocations inv
|
|
@@ -64063,7 +64554,8 @@ function projectFleetAsk(row, requesterIdSet) {
|
|
|
64063
64554
|
const queuedUntilOnline = queuedFlight && row.dispatch_outcome_status === "queued_until_online";
|
|
64064
64555
|
const staleActiveFlight = hasFlight && row.flight_state !== null && !TERMINAL_FLIGHT_STATES.has(row.flight_state) && isStaleActiveFlight(row.started_at, row.created_at);
|
|
64065
64556
|
const isActiveFlight = hasFlight && row.flight_state !== null && !TERMINAL_FLIGHT_STATES.has(row.flight_state) && !failed && !staleActiveFlight;
|
|
64066
|
-
const
|
|
64557
|
+
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);
|
|
64558
|
+
const awaitingOperator = attentionEligibleState && Boolean(row.next_move_owner_id && requesterIdSet.has(row.next_move_owner_id));
|
|
64067
64559
|
const updatedAt = normalizeTimestampMs(row.status_ts ?? row.completed_at ?? row.started_at ?? row.work_updated_at ?? row.created_at) ?? Date.now();
|
|
64068
64560
|
const dismissedAt = normalizeTimestampMs(row.flight_dismissed_at);
|
|
64069
64561
|
const recoveredAfterFailureAt = normalizeTimestampMs(row.recovered_after_failure_at);
|
|
@@ -64076,10 +64568,10 @@ function projectFleetAsk(row, requesterIdSet) {
|
|
|
64076
64568
|
status = queuedUntilOnline ? "failed" : "queued";
|
|
64077
64569
|
} else if (isActiveFlight) {
|
|
64078
64570
|
status = "working";
|
|
64079
|
-
} else if (awaitingOperator) {
|
|
64080
|
-
status = "needs_attention";
|
|
64081
64571
|
} else if (failed || staleActiveFlight) {
|
|
64082
64572
|
status = "failed";
|
|
64573
|
+
} else if (awaitingOperator) {
|
|
64574
|
+
status = "needs_attention";
|
|
64083
64575
|
} else {
|
|
64084
64576
|
status = "completed";
|
|
64085
64577
|
}
|
|
@@ -64123,34 +64615,7 @@ function queryFleetAttentionRows(requesterIds, limit) {
|
|
|
64123
64615
|
(cr.kind = 'work_item' AND cr.state IN ('open', 'working', 'waiting', 'review'))
|
|
64124
64616
|
OR (cr.kind = 'question' AND cr.state IN ('open', 'answered'))
|
|
64125
64617
|
)
|
|
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
|
-
)
|
|
64618
|
+
AND cr.next_move_owner_id IN (${requesterClause})
|
|
64154
64619
|
AND NOT EXISTS (
|
|
64155
64620
|
SELECT 1
|
|
64156
64621
|
FROM collaboration_events dismissed
|
|
@@ -66101,7 +66566,7 @@ var init_service2 = __esm(() => {
|
|
|
66101
66566
|
// packages/web/server/service-budgets.ts
|
|
66102
66567
|
import { createHash as createHash8 } from "crypto";
|
|
66103
66568
|
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";
|
|
66569
|
+
import { open as open2, readdir as readdir4, stat as stat10 } from "fs/promises";
|
|
66105
66570
|
import { homedir as homedir45 } from "os";
|
|
66106
66571
|
import { dirname as dirname35, join as join63 } from "path";
|
|
66107
66572
|
import { createInterface as createInterface2 } from "readline";
|
|
@@ -66181,12 +66646,14 @@ async function loadCodexGauge(forceRefresh = false) {
|
|
|
66181
66646
|
const root = join63(homeDir(), ".codex", "sessions");
|
|
66182
66647
|
if (!existsSync45(root))
|
|
66183
66648
|
return fallback;
|
|
66184
|
-
const
|
|
66185
|
-
if (
|
|
66649
|
+
const candidates = await findRecentCodexJsonl(root, CODEX_LOOKBACK_DAYS);
|
|
66650
|
+
if (candidates.length === 0)
|
|
66186
66651
|
return fallback;
|
|
66187
|
-
const observations = (await
|
|
66652
|
+
const observations = (await harvestRecentCodexRateLimits(candidates)).sort((left, right) => left.capturedAt - right.capturedAt);
|
|
66188
66653
|
if (observations.length === 0)
|
|
66189
66654
|
return fallback;
|
|
66655
|
+
if (!observations.some(isCodexAccountPoolObservation))
|
|
66656
|
+
return fallback;
|
|
66190
66657
|
const snapshots = bindingCodexPoolSnapshots(observations.flatMap((observation) => codexQuotaSnapshotsFromObservation(observation.usage, observation.capturedAt)));
|
|
66191
66658
|
persistQuotaSnapshots(snapshots);
|
|
66192
66659
|
const persisted = loadPersistedProviderQuotaGauge({
|
|
@@ -66243,9 +66710,11 @@ function bindingCodexPoolSnapshots(snapshots) {
|
|
|
66243
66710
|
const usedPercent = quotaSnapshotUsage(row)?.fill;
|
|
66244
66711
|
if (usedPercent === undefined)
|
|
66245
66712
|
continue;
|
|
66713
|
+
const poolId = poolIdOf(row);
|
|
66714
|
+
const accountPool = isCodexAccountPoolId(poolId);
|
|
66246
66715
|
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
|
|
66716
|
+
if (!best || usedPercent > best.usedPercent || usedPercent === best.usedPercent && accountPool && !best.accountPool || usedPercent === best.usedPercent && accountPool === best.accountPool && row.capturedAt > best.capturedAt) {
|
|
66717
|
+
bindingPoolByLabel.set(row.label, { poolId, usedPercent, capturedAt: row.capturedAt, accountPool });
|
|
66249
66718
|
}
|
|
66250
66719
|
}
|
|
66251
66720
|
return snapshots.filter((row) => bindingPoolByLabel.get(row.label)?.poolId === poolIdOf(row));
|
|
@@ -66262,37 +66731,83 @@ function formatQuotaWindowLabel(windowMinutes, fallback) {
|
|
|
66262
66731
|
}
|
|
66263
66732
|
return `${windowMinutes}m`;
|
|
66264
66733
|
}
|
|
66265
|
-
function findRecentCodexJsonl(root, lookbackDays) {
|
|
66734
|
+
async function findRecentCodexJsonl(root, lookbackDays) {
|
|
66266
66735
|
const cutoffMs = Date.now() - lookbackDays * 86400 * 1000;
|
|
66267
66736
|
const paths2 = [];
|
|
66268
|
-
const
|
|
66737
|
+
const pending = [root];
|
|
66738
|
+
while (pending.length > 0) {
|
|
66739
|
+
const dir = pending.pop();
|
|
66740
|
+
if (!dir)
|
|
66741
|
+
continue;
|
|
66269
66742
|
let entries2;
|
|
66270
66743
|
try {
|
|
66271
|
-
entries2 =
|
|
66744
|
+
entries2 = await readdir4(dir, { withFileTypes: true });
|
|
66272
66745
|
} catch {
|
|
66273
|
-
|
|
66746
|
+
continue;
|
|
66274
66747
|
}
|
|
66275
66748
|
for (const entry of entries2) {
|
|
66276
66749
|
const full = join63(dir, entry.name);
|
|
66277
66750
|
if (entry.isDirectory()) {
|
|
66278
|
-
|
|
66751
|
+
pending.push(full);
|
|
66279
66752
|
} else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
66280
|
-
|
|
66281
|
-
|
|
66282
|
-
|
|
66283
|
-
|
|
66753
|
+
try {
|
|
66754
|
+
const fileStat = await stat10(full);
|
|
66755
|
+
if (fileStat.mtimeMs < cutoffMs)
|
|
66756
|
+
continue;
|
|
66757
|
+
paths2.push({ path: full, mtimeMs: fileStat.mtimeMs });
|
|
66758
|
+
} catch {}
|
|
66284
66759
|
}
|
|
66285
66760
|
}
|
|
66286
|
-
}
|
|
66287
|
-
|
|
66288
|
-
|
|
66761
|
+
}
|
|
66762
|
+
return paths2.sort((left, right) => right.mtimeMs - left.mtimeMs).slice(0, CODEX_RECENT_CANDIDATE_LIMIT);
|
|
66763
|
+
}
|
|
66764
|
+
async function harvestRecentCodexRateLimits(candidates) {
|
|
66765
|
+
const observations = await readCodexCandidateBatch(candidates.slice(0, CODEX_INITIAL_FILE_LIMIT));
|
|
66766
|
+
if (observations.some(isCodexAccountPoolObservation))
|
|
66767
|
+
return observations;
|
|
66768
|
+
const overflow = candidates.slice(CODEX_INITIAL_FILE_LIMIT, CODEX_RECENT_CANDIDATE_LIMIT);
|
|
66769
|
+
for (let index2 = 0;index2 < overflow.length; index2 += CODEX_JSONL_READ_CONCURRENCY) {
|
|
66770
|
+
observations.push(...await readCodexCandidateBatch(overflow.slice(index2, index2 + CODEX_JSONL_READ_CONCURRENCY)));
|
|
66771
|
+
if (observations.some(isCodexAccountPoolObservation))
|
|
66772
|
+
break;
|
|
66773
|
+
}
|
|
66774
|
+
return observations;
|
|
66775
|
+
}
|
|
66776
|
+
async function readCodexCandidateBatch(candidates) {
|
|
66777
|
+
return (await Promise.all(candidates.map(async (candidate) => {
|
|
66778
|
+
try {
|
|
66779
|
+
return await readLatestCodexRateLimits(candidate.path);
|
|
66780
|
+
} catch {
|
|
66781
|
+
return [];
|
|
66782
|
+
}
|
|
66783
|
+
}))).flat();
|
|
66784
|
+
}
|
|
66785
|
+
function isCodexAccountPoolObservation(observation) {
|
|
66786
|
+
return isCodexAccountPoolId(observation.usage.limitId);
|
|
66787
|
+
}
|
|
66788
|
+
function isCodexAccountPoolId(limitId) {
|
|
66789
|
+
const normalized = limitId?.trim().toLowerCase();
|
|
66790
|
+
return !normalized || normalized === "codex";
|
|
66289
66791
|
}
|
|
66290
66792
|
async function readLatestCodexRateLimits(path2) {
|
|
66291
66793
|
const handle = await open2(path2, "r");
|
|
66292
66794
|
try {
|
|
66293
|
-
const
|
|
66795
|
+
const fileStat = await handle.stat();
|
|
66796
|
+
const start = Math.max(0, fileStat.size - CODEX_JSONL_TAIL_MAX_BYTES);
|
|
66797
|
+
const rl = createInterface2({
|
|
66798
|
+
input: handle.createReadStream({
|
|
66799
|
+
encoding: "utf8",
|
|
66800
|
+
start,
|
|
66801
|
+
autoClose: false
|
|
66802
|
+
})
|
|
66803
|
+
});
|
|
66294
66804
|
const latestByPool = new Map;
|
|
66805
|
+
let firstLine = start > 0;
|
|
66295
66806
|
for await (const line of rl) {
|
|
66807
|
+
if (firstLine) {
|
|
66808
|
+
firstLine = false;
|
|
66809
|
+
continue;
|
|
66810
|
+
}
|
|
66296
66811
|
if (!line.includes('"rate_limits"'))
|
|
66297
66812
|
continue;
|
|
66298
66813
|
try {
|
|
@@ -66369,8 +66884,8 @@ function loadClaudeStatuslineQuotaSnapshots() {
|
|
|
66369
66884
|
}
|
|
66370
66885
|
function readClaudeStatuslineHistory(minCapturedAt) {
|
|
66371
66886
|
const path2 = join63(claudeStatuslineDir(), "claude-history.jsonl");
|
|
66372
|
-
const
|
|
66373
|
-
if (!
|
|
66887
|
+
const stat11 = safeStat(path2);
|
|
66888
|
+
if (!stat11)
|
|
66374
66889
|
return [];
|
|
66375
66890
|
let content;
|
|
66376
66891
|
try {
|
|
@@ -66378,7 +66893,7 @@ function readClaudeStatuslineHistory(minCapturedAt) {
|
|
|
66378
66893
|
} catch {
|
|
66379
66894
|
return [];
|
|
66380
66895
|
}
|
|
66381
|
-
if (
|
|
66896
|
+
if (stat11.size > CLAUDE_STATUSLINE_HISTORY_MAX_BYTES) {
|
|
66382
66897
|
content = content.slice(-CLAUDE_STATUSLINE_HISTORY_MAX_BYTES);
|
|
66383
66898
|
const firstNewline = content.indexOf(`
|
|
66384
66899
|
`);
|
|
@@ -67078,11 +67593,11 @@ async function loadGrokGauge() {
|
|
|
67078
67593
|
}
|
|
67079
67594
|
async function loadGrokBillingQuotaSnapshots() {
|
|
67080
67595
|
const path2 = join63(homeDir(), ".grok", "logs", "unified.jsonl");
|
|
67081
|
-
const
|
|
67082
|
-
if (!
|
|
67596
|
+
const stat11 = safeStat(path2);
|
|
67597
|
+
if (!stat11 || stat11.size <= 0)
|
|
67083
67598
|
return [];
|
|
67084
|
-
const length = Math.min(
|
|
67085
|
-
const start = Math.max(0,
|
|
67599
|
+
const length = Math.min(stat11.size, GROK_BILLING_LOG_MAX_BYTES);
|
|
67600
|
+
const start = Math.max(0, stat11.size - length);
|
|
67086
67601
|
let content = "";
|
|
67087
67602
|
let handle;
|
|
67088
67603
|
try {
|
|
@@ -67609,11 +68124,13 @@ function persistQuotaSnapshots(snapshots) {
|
|
|
67609
68124
|
return;
|
|
67610
68125
|
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
68126
|
};
|
|
67612
|
-
|
|
67613
|
-
|
|
67614
|
-
|
|
67615
|
-
|
|
67616
|
-
|
|
68127
|
+
writer.transaction(() => {
|
|
68128
|
+
for (const snapshot of snapshots) {
|
|
68129
|
+
writeSnapshot(quotaSnapshotId(snapshot), snapshot, snapshot.metadata);
|
|
68130
|
+
writeSnapshot(quotaHistorySnapshotId(snapshot), snapshot, quotaHistoryMetadata(snapshot));
|
|
68131
|
+
}
|
|
68132
|
+
pruneHistory.run(createdAt - QUOTA_HISTORY_LOOKBACK_MS - QUOTA_HISTORY_BUCKET_MS2);
|
|
68133
|
+
})();
|
|
67617
68134
|
} catch {}
|
|
67618
68135
|
}
|
|
67619
68136
|
function quotaSnapshotMayReplace(existing, incoming) {
|
|
@@ -67718,7 +68235,7 @@ function safeStat(path2) {
|
|
|
67718
68235
|
return null;
|
|
67719
68236
|
}
|
|
67720
68237
|
}
|
|
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;
|
|
68238
|
+
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
68239
|
var init_service_budgets = __esm(() => {
|
|
67723
68240
|
init_src2();
|
|
67724
68241
|
init_src();
|
|
@@ -67728,6 +68245,7 @@ var init_service_budgets = __esm(() => {
|
|
|
67728
68245
|
init_db2();
|
|
67729
68246
|
CACHE_TTL_MS = 60 * 1000;
|
|
67730
68247
|
WEEK_MS = 7 * 24 * 3600 * 1000;
|
|
68248
|
+
CODEX_JSONL_TAIL_MAX_BYTES = 2 * 1024 * 1024;
|
|
67731
68249
|
LOCAL_QUOTA_FRESH_MS = 2 * 60 * 1000;
|
|
67732
68250
|
REMOTE_QUOTA_FRESH_MS = 5 * 60 * 1000;
|
|
67733
68251
|
QUOTA_HISTORY_BUCKET_MS2 = 60 * 60 * 1000;
|
|
@@ -69159,9 +69677,9 @@ function readFilePreview(input) {
|
|
|
69159
69677
|
}
|
|
69160
69678
|
const { realPath, root } = resolved;
|
|
69161
69679
|
try {
|
|
69162
|
-
const
|
|
69680
|
+
const stat12 = statSync22(realPath);
|
|
69163
69681
|
const title = realPath === "/" ? "/" : realPath.split("/").pop() || realPath;
|
|
69164
|
-
if (
|
|
69682
|
+
if (stat12.isDirectory()) {
|
|
69165
69683
|
return {
|
|
69166
69684
|
ok: true,
|
|
69167
69685
|
content: {
|
|
@@ -69177,7 +69695,7 @@ function readFilePreview(input) {
|
|
|
69177
69695
|
}
|
|
69178
69696
|
};
|
|
69179
69697
|
}
|
|
69180
|
-
if (!
|
|
69698
|
+
if (!stat12.isFile()) {
|
|
69181
69699
|
return { ok: false, status: 415, error: "path is not a file or directory" };
|
|
69182
69700
|
}
|
|
69183
69701
|
const mediaType = mediaTypeFor(realPath);
|
|
@@ -69194,14 +69712,14 @@ function readFilePreview(input) {
|
|
|
69194
69712
|
title,
|
|
69195
69713
|
mediaType,
|
|
69196
69714
|
rawUrl,
|
|
69197
|
-
sizeBytes:
|
|
69715
|
+
sizeBytes: stat12.size,
|
|
69198
69716
|
previewReason: previewReasonFor(mediaType),
|
|
69199
69717
|
generatedAt: Date.now()
|
|
69200
69718
|
}
|
|
69201
69719
|
};
|
|
69202
69720
|
}
|
|
69203
|
-
const truncated =
|
|
69204
|
-
const readable = readPreviewBuffer(realPath, Math.min(
|
|
69721
|
+
const truncated = stat12.size > MAX_PREVIEW_BYTES;
|
|
69722
|
+
const readable = readPreviewBuffer(realPath, Math.min(stat12.size, MAX_PREVIEW_BYTES));
|
|
69205
69723
|
if (!looksTextual2(realPath, readable)) {
|
|
69206
69724
|
return {
|
|
69207
69725
|
ok: true,
|
|
@@ -69214,7 +69732,7 @@ function readFilePreview(input) {
|
|
|
69214
69732
|
title,
|
|
69215
69733
|
mediaType,
|
|
69216
69734
|
rawUrl,
|
|
69217
|
-
sizeBytes:
|
|
69735
|
+
sizeBytes: stat12.size,
|
|
69218
69736
|
previewReason: previewReasonFor(mediaType),
|
|
69219
69737
|
generatedAt: Date.now()
|
|
69220
69738
|
}
|
|
@@ -69232,7 +69750,7 @@ function readFilePreview(input) {
|
|
|
69232
69750
|
mediaType,
|
|
69233
69751
|
rawUrl,
|
|
69234
69752
|
content: readable.toString("utf8"),
|
|
69235
|
-
sizeBytes:
|
|
69753
|
+
sizeBytes: stat12.size,
|
|
69236
69754
|
truncated,
|
|
69237
69755
|
generatedAt: Date.now()
|
|
69238
69756
|
}
|
|
@@ -71432,7 +71950,7 @@ __export(exports_agent_definitions, {
|
|
|
71432
71950
|
resolveAgentProjectRoot: () => resolveAgentProjectRoot,
|
|
71433
71951
|
buildAgentDefinitions: () => buildAgentDefinitions
|
|
71434
71952
|
});
|
|
71435
|
-
import { access as access3, readdir as
|
|
71953
|
+
import { access as access3, readdir as readdir6, readFile as readFile19 } from "fs/promises";
|
|
71436
71954
|
import { join as join71 } from "path";
|
|
71437
71955
|
function excerptFromText2(raw2) {
|
|
71438
71956
|
const trimmed = raw2.trim();
|
|
@@ -71476,7 +71994,7 @@ function agentSlugFromHandle(handle, name2) {
|
|
|
71476
71994
|
return fromName || null;
|
|
71477
71995
|
}
|
|
71478
71996
|
async function listFolderFiles(folderPath, slug) {
|
|
71479
|
-
const entries2 = await
|
|
71997
|
+
const entries2 = await readdir6(folderPath, { withFileTypes: true });
|
|
71480
71998
|
const files = [];
|
|
71481
71999
|
for (const entry of entries2) {
|
|
71482
72000
|
if (!entry.isFile())
|
|
@@ -71516,7 +72034,7 @@ async function buildAgentDefinitions(input) {
|
|
|
71516
72034
|
const selectedSlug = agentSlugFromHandle(input.agentHandle, input.agentName ?? "");
|
|
71517
72035
|
const folders = [];
|
|
71518
72036
|
if (agentsRootExists) {
|
|
71519
|
-
const entries2 = await
|
|
72037
|
+
const entries2 = await readdir6(agentsRoot, { withFileTypes: true });
|
|
71520
72038
|
for (const entry of entries2) {
|
|
71521
72039
|
if (!entry.isDirectory() || SKIPPED_NAMES.has(entry.name) || entry.name.startsWith(".")) {
|
|
71522
72040
|
continue;
|
|
@@ -73133,8 +73651,55 @@ function assertIsolatedPairingRunStateWrite(path) {
|
|
|
73133
73651
|
}
|
|
73134
73652
|
|
|
73135
73653
|
// packages/web/server/pairing-pair-requests.ts
|
|
73654
|
+
var SCOUT_PAIR_CLIENT_HEADER = "x-scout-client";
|
|
73655
|
+
var SCOUT_PAIR_RELAY_HEADER = "x-scout-pair-relay";
|
|
73656
|
+
|
|
73657
|
+
class PairRequestCapacityError extends Error {
|
|
73658
|
+
retryAfterMs;
|
|
73659
|
+
constructor(retryAfterMs) {
|
|
73660
|
+
super("Too many live pairing requests");
|
|
73661
|
+
this.name = "PairRequestCapacityError";
|
|
73662
|
+
this.retryAfterMs = retryAfterMs;
|
|
73663
|
+
}
|
|
73664
|
+
}
|
|
73665
|
+
var PAIR_CLIENT_ID_PATTERN = /^[a-z0-9][a-z0-9-]{0,31}$/;
|
|
73666
|
+
var PAIR_CLIENT_LABELS = {
|
|
73667
|
+
"scout-ios": "Scout iOS",
|
|
73668
|
+
"scout-macos": "Scout macOS",
|
|
73669
|
+
"talkie-ios": "Talkie iOS",
|
|
73670
|
+
"talkie-macos": "Talkie macOS"
|
|
73671
|
+
};
|
|
73672
|
+
function parseScoutPairClient(headerValue, userAgent) {
|
|
73673
|
+
const raw2 = headerValue?.trim().toLowerCase() ?? "";
|
|
73674
|
+
if (PAIR_CLIENT_ID_PATTERN.test(raw2))
|
|
73675
|
+
return raw2;
|
|
73676
|
+
const ua = userAgent ?? "";
|
|
73677
|
+
if (/Scout/i.test(ua) && /iPhone|iPad|iOS/i.test(ua))
|
|
73678
|
+
return "scout-ios";
|
|
73679
|
+
if (/Talkie/i.test(ua) && /iPhone|iPad|iOS/i.test(ua))
|
|
73680
|
+
return "talkie-ios";
|
|
73681
|
+
return null;
|
|
73682
|
+
}
|
|
73683
|
+
function formatScoutPairClient(app) {
|
|
73684
|
+
const id = app?.trim() || null;
|
|
73685
|
+
if (!id)
|
|
73686
|
+
return null;
|
|
73687
|
+
return PAIR_CLIENT_LABELS[id] ?? id;
|
|
73688
|
+
}
|
|
73689
|
+
function pairRequesterDisplay(req) {
|
|
73690
|
+
const label = req.requesterLabel?.trim() || null;
|
|
73691
|
+
const app = formatScoutPairClient(req.requesterApp);
|
|
73692
|
+
if (label && app)
|
|
73693
|
+
return `${label} \xB7 ${app}`;
|
|
73694
|
+
return label || app || "A device";
|
|
73695
|
+
}
|
|
73136
73696
|
var DEFAULT_TTL_MS = 2 * 60 * 1000;
|
|
73697
|
+
var DEFAULT_MAX_LIVE_REQUESTS = 32;
|
|
73137
73698
|
var SWEEP_INTERVAL_MS = 30 * 1000;
|
|
73699
|
+
function boundedMetadata(value, maxLength) {
|
|
73700
|
+
const trimmed = value?.trim() || null;
|
|
73701
|
+
return trimmed ? trimmed.slice(0, maxLength) : null;
|
|
73702
|
+
}
|
|
73138
73703
|
var MAX_PUBLISH_ATTEMPTS = 32;
|
|
73139
73704
|
var PUBLISH_SPIN_ATTEMPTS = 8;
|
|
73140
73705
|
var PUBLISH_BACKOFF_CEILING_MS = 8;
|
|
@@ -73187,7 +73752,7 @@ function isPairRequest(value) {
|
|
|
73187
73752
|
if (!value || typeof value !== "object")
|
|
73188
73753
|
return false;
|
|
73189
73754
|
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";
|
|
73755
|
+
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
73756
|
}
|
|
73192
73757
|
function fileSignature(path) {
|
|
73193
73758
|
try {
|
|
@@ -73209,7 +73774,11 @@ function parseTerminalMarkers(value) {
|
|
|
73209
73774
|
continue;
|
|
73210
73775
|
if (typeof marker.collectAfter !== "number" || !Number.isFinite(marker.collectAfter))
|
|
73211
73776
|
continue;
|
|
73212
|
-
markers.push({
|
|
73777
|
+
markers.push({
|
|
73778
|
+
token: marker.token,
|
|
73779
|
+
collectAfter: marker.collectAfter,
|
|
73780
|
+
...typeof marker.claimId === "string" && marker.claimId.length > 0 ? { claimId: marker.claimId } : {}
|
|
73781
|
+
});
|
|
73213
73782
|
}
|
|
73214
73783
|
return markers;
|
|
73215
73784
|
}
|
|
@@ -73231,6 +73800,8 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73231
73800
|
const ttlMs = options.ttlMs ?? DEFAULT_TTL_MS;
|
|
73232
73801
|
const now = options.now ?? (() => Date.now());
|
|
73233
73802
|
const statePath = options.statePath;
|
|
73803
|
+
const maxLiveRequests = Math.max(1, Math.floor(options.maxLiveRequests ?? DEFAULT_MAX_LIVE_REQUESTS));
|
|
73804
|
+
const renewalWindowMs = Math.max(0, options.renewalWindowMs ?? Math.floor(ttlMs / 2));
|
|
73234
73805
|
const byToken = new Map;
|
|
73235
73806
|
let loadedGeneration = null;
|
|
73236
73807
|
let loadedSignature = null;
|
|
@@ -73239,6 +73810,7 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73239
73810
|
const unpersistedUpserts = new Set;
|
|
73240
73811
|
const unpersistedExpiries = new Map;
|
|
73241
73812
|
const fulfilledMarkers = new Map;
|
|
73813
|
+
const fulfilledClaims = new Map;
|
|
73242
73814
|
const unpublishedFulfilled = new Set;
|
|
73243
73815
|
const lastSeenInShared = new Map;
|
|
73244
73816
|
const tempPath = statePath ? `${statePath}.${process.pid}.${crypto.randomUUID().slice(0, 8)}.tmp` : null;
|
|
@@ -73256,6 +73828,17 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73256
73828
|
function latestGeneration() {
|
|
73257
73829
|
return statePath ? latestPairRequestGeneration(statePath) : null;
|
|
73258
73830
|
}
|
|
73831
|
+
function generationHasTerminalClaim(generation, claim) {
|
|
73832
|
+
const raw2 = readFileOrNull(generationPath(generation));
|
|
73833
|
+
if (raw2 === null)
|
|
73834
|
+
return false;
|
|
73835
|
+
try {
|
|
73836
|
+
const parsed = JSON.parse(raw2);
|
|
73837
|
+
return parseTerminalMarkers(parsed.fulfilled).some((marker) => marker.token === claim.token && marker.claimId === claim.claimId);
|
|
73838
|
+
} catch {
|
|
73839
|
+
return false;
|
|
73840
|
+
}
|
|
73841
|
+
}
|
|
73259
73842
|
function movedOnSince(sighting) {
|
|
73260
73843
|
if (loadedEpoch !== sighting.epoch)
|
|
73261
73844
|
return false;
|
|
@@ -73267,10 +73850,11 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73267
73850
|
function terminalMarkerHorizon(expiresAt) {
|
|
73268
73851
|
return Math.max(expiresAt, now()) + ttlMs;
|
|
73269
73852
|
}
|
|
73270
|
-
function markFulfilled(request) {
|
|
73853
|
+
function markFulfilled(request, claimId) {
|
|
73271
73854
|
const horizon = terminalMarkerHorizon(request.expiresAt);
|
|
73272
73855
|
const known = fulfilledMarkers.get(request.token);
|
|
73273
73856
|
fulfilledMarkers.set(request.token, known === undefined ? horizon : Math.max(known, horizon));
|
|
73857
|
+
fulfilledClaims.set(request.token, claimId);
|
|
73274
73858
|
if (statePath)
|
|
73275
73859
|
unpublishedFulfilled.add(request.token);
|
|
73276
73860
|
}
|
|
@@ -73279,8 +73863,10 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73279
73863
|
for (const [token, collectAfter] of fulfilledMarkers) {
|
|
73280
73864
|
if (unpublishedFulfilled.has(token))
|
|
73281
73865
|
continue;
|
|
73282
|
-
if (collectAfter < t)
|
|
73866
|
+
if (collectAfter < t) {
|
|
73283
73867
|
fulfilledMarkers.delete(token);
|
|
73868
|
+
fulfilledClaims.delete(token);
|
|
73869
|
+
}
|
|
73284
73870
|
}
|
|
73285
73871
|
}
|
|
73286
73872
|
function mergeUnpersisted(loaded) {
|
|
@@ -73340,6 +73926,8 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73340
73926
|
for (const marker of markers) {
|
|
73341
73927
|
const known = fulfilledMarkers.get(marker.token);
|
|
73342
73928
|
fulfilledMarkers.set(marker.token, known === undefined ? marker.collectAfter : Math.max(known, marker.collectAfter));
|
|
73929
|
+
if (marker.claimId !== undefined)
|
|
73930
|
+
fulfilledClaims.set(marker.token, marker.claimId);
|
|
73343
73931
|
}
|
|
73344
73932
|
for (const [token, row] of loaded) {
|
|
73345
73933
|
const known = fulfilledMarkers.get(token);
|
|
@@ -73406,7 +73994,10 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73406
73994
|
}
|
|
73407
73995
|
loadedEpoch = epoch;
|
|
73408
73996
|
loadedHasTerminalLedger = hasLedger;
|
|
73409
|
-
adopt(rows.filter(isPairRequest)
|
|
73997
|
+
adopt(rows.filter(isPairRequest).map((row) => ({
|
|
73998
|
+
...row,
|
|
73999
|
+
requesterApp: row.requesterApp ?? null
|
|
74000
|
+
})), markers);
|
|
73410
74001
|
return;
|
|
73411
74002
|
}
|
|
73412
74003
|
}
|
|
@@ -73417,7 +74008,7 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73417
74008
|
rmSync5(tempPath, { force: true });
|
|
73418
74009
|
} catch {}
|
|
73419
74010
|
}
|
|
73420
|
-
function publish(touched, expired) {
|
|
74011
|
+
function publish(touched, expired, terminalClaim) {
|
|
73421
74012
|
if (!statePath || !tempPath)
|
|
73422
74013
|
return "won";
|
|
73423
74014
|
if (touched.length === 0 && expired.length === 0 && !hasOutstandingWrites())
|
|
@@ -73433,7 +74024,11 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73433
74024
|
version: 1,
|
|
73434
74025
|
epoch,
|
|
73435
74026
|
requests: [...byToken.values()],
|
|
73436
|
-
fulfilled: [...fulfilledMarkers].map(([token, collectAfter]) => ({
|
|
74027
|
+
fulfilled: [...fulfilledMarkers].map(([token, collectAfter]) => ({
|
|
74028
|
+
token,
|
|
74029
|
+
collectAfter,
|
|
74030
|
+
...fulfilledClaims.has(token) ? { claimId: fulfilledClaims.get(token) } : {}
|
|
74031
|
+
}))
|
|
73437
74032
|
});
|
|
73438
74033
|
try {
|
|
73439
74034
|
mkdirSync11(dirname26(statePath), { recursive: true, mode: 448 });
|
|
@@ -73454,7 +74049,9 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73454
74049
|
discardTemp();
|
|
73455
74050
|
if (!landed || signature === null)
|
|
73456
74051
|
return "lost";
|
|
73457
|
-
|
|
74052
|
+
const frontier = latestGeneration();
|
|
74053
|
+
const inheritedClaim = terminalClaim !== undefined && frontier !== null && frontier > next && generationHasTerminalClaim(frontier, terminalClaim);
|
|
74054
|
+
if (frontier !== next && !inheritedClaim) {
|
|
73458
74055
|
try {
|
|
73459
74056
|
if (inodeOf(target2) === ours)
|
|
73460
74057
|
unlinkSync2(target2);
|
|
@@ -73472,7 +74069,7 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73472
74069
|
for (const token of byToken.keys())
|
|
73473
74070
|
lastSeenInShared.set(token, sighting);
|
|
73474
74071
|
forgetSightingsWeNoLongerHold();
|
|
73475
|
-
collectSuperseded(next);
|
|
74072
|
+
collectSuperseded(frontier ?? next);
|
|
73476
74073
|
return "won";
|
|
73477
74074
|
}
|
|
73478
74075
|
function collectSuperseded(published) {
|
|
@@ -73514,7 +74111,7 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73514
74111
|
function hasOutstandingWrites() {
|
|
73515
74112
|
return unpersistedUpserts.size > 0 || unpersistedExpiries.size > 0 || unpublishedFulfilled.size > 0;
|
|
73516
74113
|
}
|
|
73517
|
-
function commit(apply) {
|
|
74114
|
+
function commit(apply, options2 = {}) {
|
|
73518
74115
|
if (!statePath) {
|
|
73519
74116
|
pruneExpired();
|
|
73520
74117
|
collectTerminalMarkers();
|
|
@@ -73525,10 +74122,17 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73525
74122
|
const expired = pruneExpired();
|
|
73526
74123
|
collectTerminalMarkers();
|
|
73527
74124
|
const { value, touched } = apply();
|
|
73528
|
-
const outcome = publish(touched, expired);
|
|
74125
|
+
const outcome = publish(touched, expired, options2.terminalClaim);
|
|
73529
74126
|
if (outcome === "won")
|
|
73530
74127
|
return value;
|
|
74128
|
+
if (outcome === "lost")
|
|
74129
|
+
options2.rollback?.();
|
|
73531
74130
|
if (outcome === "failed" || attempt >= MAX_PUBLISH_ATTEMPTS) {
|
|
74131
|
+
if (options2.failClosed) {
|
|
74132
|
+
if (outcome === "failed")
|
|
74133
|
+
options2.rollback?.();
|
|
74134
|
+
return options2.failClosed();
|
|
74135
|
+
}
|
|
73532
74136
|
recordOutstanding(touched, expired);
|
|
73533
74137
|
return value;
|
|
73534
74138
|
}
|
|
@@ -73556,7 +74160,7 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73556
74160
|
return null;
|
|
73557
74161
|
const t = now();
|
|
73558
74162
|
for (const req of byToken.values()) {
|
|
73559
|
-
if (req.requesterIp === requesterIp && req.expiresAt > t
|
|
74163
|
+
if (req.requesterIp === requesterIp && req.expiresAt > t) {
|
|
73560
74164
|
return req;
|
|
73561
74165
|
}
|
|
73562
74166
|
}
|
|
@@ -73564,19 +74168,38 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73564
74168
|
}
|
|
73565
74169
|
return {
|
|
73566
74170
|
create(input) {
|
|
73567
|
-
const requesterIp = input.requesterIp
|
|
73568
|
-
const label = input.requesterLabel
|
|
74171
|
+
const requesterIp = boundedMetadata(input.requesterIp, 64);
|
|
74172
|
+
const label = boundedMetadata(input.requesterLabel, 96);
|
|
74173
|
+
const app = boundedMetadata(input.requesterApp, 32);
|
|
74174
|
+
const route = boundedMetadata(input.route, 16);
|
|
73569
74175
|
const token = crypto.randomUUID();
|
|
73570
|
-
|
|
74176
|
+
const result = commit(() => {
|
|
73571
74177
|
const existing = findReusable(requesterIp);
|
|
73572
74178
|
if (existing) {
|
|
73573
|
-
|
|
73574
|
-
existing.expiresAt
|
|
73575
|
-
if (
|
|
73576
|
-
existing.
|
|
73577
|
-
|
|
73578
|
-
|
|
73579
|
-
|
|
74179
|
+
const t2 = now();
|
|
74180
|
+
const renew = existing.status !== "denied" && existing.expiresAt - t2 <= renewalWindowMs;
|
|
74181
|
+
if (renew) {
|
|
74182
|
+
existing.updatedAt = t2;
|
|
74183
|
+
existing.expiresAt = t2 + ttlMs;
|
|
74184
|
+
if (route)
|
|
74185
|
+
existing.route = route;
|
|
74186
|
+
if (label)
|
|
74187
|
+
existing.requesterLabel = label;
|
|
74188
|
+
if (app)
|
|
74189
|
+
existing.requesterApp = app;
|
|
74190
|
+
}
|
|
74191
|
+
return { value: existing, touched: renew ? [existing.token] : [] };
|
|
74192
|
+
}
|
|
74193
|
+
if (byToken.size >= maxLiveRequests) {
|
|
74194
|
+
const t2 = now();
|
|
74195
|
+
const earliestExpiry = Math.min(...[...byToken.values()].map((request2) => request2.expiresAt));
|
|
74196
|
+
return {
|
|
74197
|
+
value: {
|
|
74198
|
+
capacity: true,
|
|
74199
|
+
retryAfterMs: Math.max(1000, earliestExpiry - t2)
|
|
74200
|
+
},
|
|
74201
|
+
touched: []
|
|
74202
|
+
};
|
|
73580
74203
|
}
|
|
73581
74204
|
const t = now();
|
|
73582
74205
|
const request = {
|
|
@@ -73584,7 +74207,8 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73584
74207
|
status: "pending",
|
|
73585
74208
|
requesterIp,
|
|
73586
74209
|
requesterLabel: label,
|
|
73587
|
-
|
|
74210
|
+
requesterApp: app,
|
|
74211
|
+
route,
|
|
73588
74212
|
createdAt: t,
|
|
73589
74213
|
updatedAt: t,
|
|
73590
74214
|
expiresAt: t + ttlMs
|
|
@@ -73592,6 +74216,10 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73592
74216
|
byToken.set(token, request);
|
|
73593
74217
|
return { value: request, touched: [token] };
|
|
73594
74218
|
});
|
|
74219
|
+
if ("capacity" in result) {
|
|
74220
|
+
throw new PairRequestCapacityError(result.retryAfterMs);
|
|
74221
|
+
}
|
|
74222
|
+
return result;
|
|
73595
74223
|
},
|
|
73596
74224
|
get(token) {
|
|
73597
74225
|
reload();
|
|
@@ -73601,8 +74229,9 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73601
74229
|
touch(token) {
|
|
73602
74230
|
commit(() => {
|
|
73603
74231
|
const req = byToken.get(token);
|
|
73604
|
-
const
|
|
73605
|
-
const
|
|
74232
|
+
const t = now();
|
|
74233
|
+
const extended = t + ttlMs;
|
|
74234
|
+
const extend = req !== undefined && (req.status === "pending" || req.status === "approved") && req.expiresAt - t <= renewalWindowMs && extended > req.expiresAt;
|
|
73606
74235
|
if (extend && req)
|
|
73607
74236
|
req.expiresAt = extended;
|
|
73608
74237
|
return { value: undefined, touched: extend ? [token] : [] };
|
|
@@ -73619,24 +74248,55 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73619
74248
|
return { value: null, touched: [] };
|
|
73620
74249
|
req.status = decision === "approve" ? "approved" : "denied";
|
|
73621
74250
|
req.updatedAt = now();
|
|
73622
|
-
|
|
73623
|
-
req.expiresAt = now() + ttlMs;
|
|
74251
|
+
req.expiresAt = now() + ttlMs;
|
|
73624
74252
|
return { value: req, touched: [token] };
|
|
73625
74253
|
});
|
|
73626
74254
|
},
|
|
73627
|
-
fulfill(token) {
|
|
73628
|
-
let
|
|
74255
|
+
fulfill(token, requiredStatus) {
|
|
74256
|
+
let proposal = null;
|
|
74257
|
+
const claim = { token, claimId: crypto.randomUUID() };
|
|
74258
|
+
let previousMarker;
|
|
74259
|
+
let previousClaim;
|
|
74260
|
+
let previouslyUnpublished = false;
|
|
74261
|
+
let previouslyUnpersisted = false;
|
|
74262
|
+
const rollback = () => {
|
|
74263
|
+
if (proposal === null)
|
|
74264
|
+
return;
|
|
74265
|
+
if (previousMarker === undefined)
|
|
74266
|
+
fulfilledMarkers.delete(token);
|
|
74267
|
+
else
|
|
74268
|
+
fulfilledMarkers.set(token, previousMarker);
|
|
74269
|
+
if (previousClaim === undefined)
|
|
74270
|
+
fulfilledClaims.delete(token);
|
|
74271
|
+
else
|
|
74272
|
+
fulfilledClaims.set(token, previousClaim);
|
|
74273
|
+
if (!previouslyUnpublished)
|
|
74274
|
+
unpublishedFulfilled.delete(token);
|
|
74275
|
+
byToken.set(token, proposal);
|
|
74276
|
+
if (previouslyUnpersisted)
|
|
74277
|
+
unpersistedUpserts.add(token);
|
|
74278
|
+
else
|
|
74279
|
+
unpersistedUpserts.delete(token);
|
|
74280
|
+
proposal = null;
|
|
74281
|
+
};
|
|
73629
74282
|
return commit(() => {
|
|
73630
|
-
|
|
73631
|
-
|
|
73632
|
-
|
|
73633
|
-
return { value: null, touched: [] };
|
|
73634
|
-
delivered = { ...request };
|
|
74283
|
+
const request = byToken.get(token);
|
|
74284
|
+
if (!request || !isLive(request) || requiredStatus !== undefined && request.status !== requiredStatus) {
|
|
74285
|
+
return { value: null, touched: [] };
|
|
73635
74286
|
}
|
|
73636
|
-
|
|
74287
|
+
proposal = { ...request };
|
|
74288
|
+
previousMarker = fulfilledMarkers.get(token);
|
|
74289
|
+
previousClaim = fulfilledClaims.get(token);
|
|
74290
|
+
previouslyUnpublished = unpublishedFulfilled.has(token);
|
|
74291
|
+
previouslyUnpersisted = unpersistedUpserts.has(token);
|
|
74292
|
+
markFulfilled(proposal, claim.claimId);
|
|
73637
74293
|
byToken.delete(token);
|
|
73638
74294
|
unpersistedUpserts.delete(token);
|
|
73639
|
-
return { value:
|
|
74295
|
+
return { value: proposal, touched: [] };
|
|
74296
|
+
}, {
|
|
74297
|
+
rollback,
|
|
74298
|
+
terminalClaim: claim,
|
|
74299
|
+
failClosed: () => null
|
|
73640
74300
|
});
|
|
73641
74301
|
},
|
|
73642
74302
|
dispose() {
|
|
@@ -73647,6 +74307,7 @@ function createPendingPairRequestStore(options = {}) {
|
|
|
73647
74307
|
unpersistedExpiries.clear();
|
|
73648
74308
|
unpublishedFulfilled.clear();
|
|
73649
74309
|
fulfilledMarkers.clear();
|
|
74310
|
+
fulfilledClaims.clear();
|
|
73650
74311
|
lastSeenInShared.clear();
|
|
73651
74312
|
}
|
|
73652
74313
|
};
|
|
@@ -73887,7 +74548,8 @@ init_agent_endpoints();
|
|
|
73887
74548
|
|
|
73888
74549
|
// packages/web/server/core/repo-identity.ts
|
|
73889
74550
|
init_system_probes();
|
|
73890
|
-
var REPO_KEY_TTL_MS = 60000;
|
|
74551
|
+
var REPO_KEY_TTL_MS = 10 * 60000;
|
|
74552
|
+
var REPO_KEY_PROBE_CONCURRENCY = 4;
|
|
73891
74553
|
function normalizeGitRemoteUrl(remote) {
|
|
73892
74554
|
const trimmed = remote?.trim() ?? "";
|
|
73893
74555
|
if (!trimmed)
|
|
@@ -73911,15 +74573,14 @@ function canonicalRepoKey(host, path2) {
|
|
|
73911
74573
|
}
|
|
73912
74574
|
var repoKeyCache = new Map;
|
|
73913
74575
|
var repoKeyInFlight = new Map;
|
|
74576
|
+
var queuedRepoKeyRoots = [];
|
|
74577
|
+
var queuedRepoKeyRootSet = new Set;
|
|
74578
|
+
var activeRepoKeyProbes = 0;
|
|
73914
74579
|
async function probeRepoKey(root) {
|
|
73915
74580
|
const remote = await gitRemoteGetUrlOrigin(root).catch(() => null);
|
|
73916
74581
|
return normalizeGitRemoteUrl(remote);
|
|
73917
74582
|
}
|
|
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
|
-
}
|
|
74583
|
+
function refreshRepoKeyForRoot(root) {
|
|
73923
74584
|
const inFlight = repoKeyInFlight.get(root);
|
|
73924
74585
|
if (inFlight)
|
|
73925
74586
|
return inFlight;
|
|
@@ -73933,10 +74594,38 @@ function resolveRepoKeyForRoot(root) {
|
|
|
73933
74594
|
repoKeyInFlight.set(root, promise);
|
|
73934
74595
|
return promise;
|
|
73935
74596
|
}
|
|
73936
|
-
|
|
74597
|
+
function drainRepoKeyProbeQueue() {
|
|
74598
|
+
while (activeRepoKeyProbes < REPO_KEY_PROBE_CONCURRENCY) {
|
|
74599
|
+
const root = queuedRepoKeyRoots.shift();
|
|
74600
|
+
if (!root)
|
|
74601
|
+
return;
|
|
74602
|
+
queuedRepoKeyRootSet.delete(root);
|
|
74603
|
+
activeRepoKeyProbes += 1;
|
|
74604
|
+
refreshRepoKeyForRoot(root).catch(() => null).finally(() => {
|
|
74605
|
+
activeRepoKeyProbes -= 1;
|
|
74606
|
+
drainRepoKeyProbeQueue();
|
|
74607
|
+
});
|
|
74608
|
+
}
|
|
74609
|
+
}
|
|
74610
|
+
function scheduleRepoKeyProbe(root) {
|
|
74611
|
+
if (repoKeyInFlight.has(root) || queuedRepoKeyRootSet.has(root))
|
|
74612
|
+
return;
|
|
74613
|
+
queuedRepoKeyRootSet.add(root);
|
|
74614
|
+
queuedRepoKeyRoots.push(root);
|
|
74615
|
+
drainRepoKeyProbeQueue();
|
|
74616
|
+
}
|
|
74617
|
+
function cachedRepoKeysByRoot(roots) {
|
|
74618
|
+
const now = Date.now();
|
|
73937
74619
|
const distinct = [...new Set(roots)];
|
|
73938
|
-
const
|
|
73939
|
-
|
|
74620
|
+
const result = new Map;
|
|
74621
|
+
for (const root of distinct) {
|
|
74622
|
+
const cached = repoKeyCache.get(root);
|
|
74623
|
+
result.set(root, cached?.key ?? null);
|
|
74624
|
+
if (!cached || now - cached.at >= REPO_KEY_TTL_MS) {
|
|
74625
|
+
scheduleRepoKeyProbe(root);
|
|
74626
|
+
}
|
|
74627
|
+
}
|
|
74628
|
+
return result;
|
|
73940
74629
|
}
|
|
73941
74630
|
|
|
73942
74631
|
// packages/web/server/terminal-session-discovery.ts
|
|
@@ -75353,6 +76042,50 @@ init_src();
|
|
|
75353
76042
|
init_legacy_ids();
|
|
75354
76043
|
init_service();
|
|
75355
76044
|
init_message_pagination();
|
|
76045
|
+
function provisionalScoutConversations(snapshot, filters = {}) {
|
|
76046
|
+
const allowedKinds = new Set(filters.kinds ?? DEFAULT_CONVERSATION_KINDS);
|
|
76047
|
+
const query = normalizeQuery(filters.query);
|
|
76048
|
+
const limit = Math.max(1, Math.floor(filters.limit ?? snapshot.items.length));
|
|
76049
|
+
return snapshot.items.filter((item) => item.entityKind === "scout_conversation" && item.visibilityState === "visible" && Boolean(item.conversationId) && allowedKinds.has(item.kind)).filter((item) => !query || [
|
|
76050
|
+
item.title,
|
|
76051
|
+
item.alias,
|
|
76052
|
+
item.agentName,
|
|
76053
|
+
item.preview,
|
|
76054
|
+
item.projectRoot
|
|
76055
|
+
].some((value) => value?.toLocaleLowerCase().includes(query))).slice(0, limit).map((item) => {
|
|
76056
|
+
const conversationId = item.conversationId;
|
|
76057
|
+
const participantIds = item.kind === "direct" && item.agentId ? ["operator", item.agentId] : [];
|
|
76058
|
+
return {
|
|
76059
|
+
id: conversationId,
|
|
76060
|
+
chatId: conversationId,
|
|
76061
|
+
equivalentConversationIds: [conversationId],
|
|
76062
|
+
kind: item.kind,
|
|
76063
|
+
title: item.title ?? item.agentName ?? item.alias ?? conversationId,
|
|
76064
|
+
alias: item.alias,
|
|
76065
|
+
naturalKey: item.naturalKey,
|
|
76066
|
+
participantIds,
|
|
76067
|
+
participants: [],
|
|
76068
|
+
participantCount: item.participantCount,
|
|
76069
|
+
authorityNodeId: item.authorityNodeId,
|
|
76070
|
+
authorityNodeName: item.authorityNodeName,
|
|
76071
|
+
agentId: item.agentId,
|
|
76072
|
+
agentName: item.agentName,
|
|
76073
|
+
harness: item.harness,
|
|
76074
|
+
model: item.model,
|
|
76075
|
+
reasoningEffort: item.effort,
|
|
76076
|
+
transport: null,
|
|
76077
|
+
sessionId: item.runtimeSessionId,
|
|
76078
|
+
currentBranch: item.currentBranch,
|
|
76079
|
+
parentConversationId: item.parentConversationId,
|
|
76080
|
+
anchorMessageId: item.anchorMessageId,
|
|
76081
|
+
preview: item.preview,
|
|
76082
|
+
messageCount: item.messageCount,
|
|
76083
|
+
lastMessageAt: item.lastMessageAt,
|
|
76084
|
+
workspaceRoot: item.projectRoot,
|
|
76085
|
+
unreadCount: item.unreadCount
|
|
76086
|
+
};
|
|
76087
|
+
});
|
|
76088
|
+
}
|
|
75356
76089
|
var DEFAULT_CONVERSATION_KINDS = [
|
|
75357
76090
|
"direct",
|
|
75358
76091
|
"channel",
|
|
@@ -75421,6 +76154,53 @@ function metadataObject2(metadata, key) {
|
|
|
75421
76154
|
function metadataSessionId(metadata) {
|
|
75422
76155
|
return metadataString9(metadata, "targetSessionId") ?? metadataString9(metadata, "responderSessionId") ?? metadataString9(metadata, "sessionId") ?? metadataString9(metadata, "externalSessionId") ?? metadataString9(metadata, "threadId") ?? metadataString9(metadataObject2(metadata, "returnAddress"), "sessionId");
|
|
75423
76156
|
}
|
|
76157
|
+
function executionResolutionDimension2(resolution, dimension) {
|
|
76158
|
+
const value = resolution?.[dimension];
|
|
76159
|
+
return value?.observed?.trim() || value?.resolved?.trim() || value?.requested?.trim() || null;
|
|
76160
|
+
}
|
|
76161
|
+
function executionResolutionFromUnknown(value) {
|
|
76162
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
76163
|
+
return null;
|
|
76164
|
+
const resolution = value;
|
|
76165
|
+
return resolution.schemaVersion === "openscout.execution-resolution.v1" ? resolution : null;
|
|
76166
|
+
}
|
|
76167
|
+
function flightSessionRuntime(flights, sessionId) {
|
|
76168
|
+
for (const flight of [...flights].reverse()) {
|
|
76169
|
+
const rawTrace = flight.metadata?.sessionTrace;
|
|
76170
|
+
if (!Array.isArray(rawTrace))
|
|
76171
|
+
continue;
|
|
76172
|
+
const entries2 = [...rawTrace].reverse();
|
|
76173
|
+
const candidate = entries2.find((entry) => {
|
|
76174
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry))
|
|
76175
|
+
return false;
|
|
76176
|
+
const id = metadataString9(entry, "sessionId");
|
|
76177
|
+
return sessionId ? id === sessionId : Boolean(id);
|
|
76178
|
+
});
|
|
76179
|
+
if (!candidate || typeof candidate !== "object" || Array.isArray(candidate))
|
|
76180
|
+
continue;
|
|
76181
|
+
const record2 = candidate;
|
|
76182
|
+
return {
|
|
76183
|
+
resolution: executionResolutionFromUnknown(record2.executionResolution),
|
|
76184
|
+
harness: metadataString9(record2, "harness"),
|
|
76185
|
+
transport: metadataString9(record2, "transport")
|
|
76186
|
+
};
|
|
76187
|
+
}
|
|
76188
|
+
return null;
|
|
76189
|
+
}
|
|
76190
|
+
function latestConversationRuntime(input) {
|
|
76191
|
+
const matchingParticipant = input.sessionId ? input.participants.find((participant) => participant.sessionId === input.sessionId) ?? null : null;
|
|
76192
|
+
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;
|
|
76193
|
+
const latestInvocation = input.invocations.at(-1) ?? null;
|
|
76194
|
+
const invocation = matchingInvocation ?? latestInvocation;
|
|
76195
|
+
const trace = flightSessionRuntime(input.flights, input.sessionId);
|
|
76196
|
+
const resolution = matchingInvocation?.executionResolution ?? trace?.resolution ?? invocation?.executionResolution ?? null;
|
|
76197
|
+
return {
|
|
76198
|
+
harness: executionResolutionDimension2(resolution, "harness") ?? trace?.harness ?? matchingParticipant?.harness ?? invocation?.execution?.harness?.trim() ?? input.endpoint?.harness ?? null,
|
|
76199
|
+
model: executionResolutionDimension2(resolution, "model") ?? matchingParticipant?.model ?? invocation?.execution?.model?.trim() ?? metadataString9(input.endpoint?.metadata, "observedModel") ?? metadataString9(input.endpoint?.metadata, "model"),
|
|
76200
|
+
reasoningEffort: executionResolutionDimension2(resolution, "reasoningEffort") ?? matchingParticipant?.reasoningEffort ?? invocation?.execution?.reasoningEffort?.trim() ?? metadataString9(input.endpoint?.metadata, "observedReasoningEffort") ?? metadataString9(input.endpoint?.metadata, "reasoningEffort"),
|
|
76201
|
+
transport: trace?.transport ?? matchingParticipant?.transport ?? input.endpoint?.transport ?? null
|
|
76202
|
+
};
|
|
76203
|
+
}
|
|
75424
76204
|
function formatChannelAlias2(value) {
|
|
75425
76205
|
const trimmed = value.trim();
|
|
75426
76206
|
if (!trimmed)
|
|
@@ -75751,6 +76531,8 @@ function buildScopedParticipants(snapshot, endpoints, operatorIds, conversationI
|
|
|
75751
76531
|
agentId: agent?.id ?? null,
|
|
75752
76532
|
sessionId: endpoint?.sessionId ?? metadataSessionId(endpoint?.metadata) ?? metadataSessionId(actor?.metadata) ?? (kind === "session" ? participantId : null),
|
|
75753
76533
|
harness: endpoint?.harness ?? metadataString9(actor?.metadata, "harness"),
|
|
76534
|
+
model: metadataString9(endpoint?.metadata, "observedModel") ?? metadataString9(endpoint?.metadata, "model") ?? metadataString9(actor?.metadata, "model"),
|
|
76535
|
+
reasoningEffort: metadataString9(endpoint?.metadata, "observedReasoningEffort") ?? metadataString9(endpoint?.metadata, "reasoningEffort") ?? metadataString9(actor?.metadata, "reasoningEffort"),
|
|
75754
76536
|
transport: endpoint?.transport ?? metadataString9(actor?.metadata, "transport"),
|
|
75755
76537
|
workspaceRoot: endpoint?.projectRoot ?? endpoint?.cwd ?? metadataString9(actor?.metadata, "projectRoot")
|
|
75756
76538
|
};
|
|
@@ -75772,6 +76554,9 @@ function includeConversation(summary, query) {
|
|
|
75772
76554
|
summary.title,
|
|
75773
76555
|
summary.agentId ?? "",
|
|
75774
76556
|
summary.agentName ?? "",
|
|
76557
|
+
summary.harness ?? "",
|
|
76558
|
+
summary.model ?? "",
|
|
76559
|
+
summary.reasoningEffort ?? "",
|
|
75775
76560
|
summary.preview ?? "",
|
|
75776
76561
|
summary.workspaceRoot ?? "",
|
|
75777
76562
|
...summary.participantIds,
|
|
@@ -75839,6 +76624,10 @@ function coalesceDuplicateNamedChannels(summaries, snapshot, endpoints, operator
|
|
|
75839
76624
|
preview: latest.preview,
|
|
75840
76625
|
lastMessageAt: latest.lastMessageAt,
|
|
75841
76626
|
sessionId: latest.sessionId ?? canonical2.sessionId,
|
|
76627
|
+
harness: latest.harness ?? canonical2.harness,
|
|
76628
|
+
model: latest.model ?? canonical2.model,
|
|
76629
|
+
reasoningEffort: latest.reasoningEffort ?? canonical2.reasoningEffort,
|
|
76630
|
+
transport: latest.transport ?? canonical2.transport,
|
|
75842
76631
|
messageCount: Math.max(...group.map((summary) => summary.messageCount)),
|
|
75843
76632
|
unreadCount: Math.max(...group.map((summary) => summary.unreadCount)),
|
|
75844
76633
|
...latestTurn ? { turn: latestTurn } : {}
|
|
@@ -75910,6 +76699,13 @@ async function getScoutConversations(filters = {}, brokerContext) {
|
|
|
75910
76699
|
}
|
|
75911
76700
|
const title = agentDisplayName(snapshot, endpointsByAgent, agentId);
|
|
75912
76701
|
const identityFields2 = conversationIdentityFields2(conversation);
|
|
76702
|
+
const runtime2 = latestConversationRuntime({
|
|
76703
|
+
sessionId,
|
|
76704
|
+
participants,
|
|
76705
|
+
invocations: invocations2,
|
|
76706
|
+
flights,
|
|
76707
|
+
endpoint
|
|
76708
|
+
});
|
|
75913
76709
|
return [{
|
|
75914
76710
|
id: conversation.id,
|
|
75915
76711
|
chatId: conversation.id,
|
|
@@ -75924,7 +76720,10 @@ async function getScoutConversations(filters = {}, brokerContext) {
|
|
|
75924
76720
|
authorityNodeName: snapshot.nodes?.[conversation.authorityNodeId]?.name ?? null,
|
|
75925
76721
|
agentId,
|
|
75926
76722
|
agentName: title,
|
|
75927
|
-
harness:
|
|
76723
|
+
harness: runtime2.harness,
|
|
76724
|
+
model: runtime2.model,
|
|
76725
|
+
reasoningEffort: runtime2.reasoningEffort,
|
|
76726
|
+
transport: runtime2.transport,
|
|
75928
76727
|
sessionId,
|
|
75929
76728
|
currentBranch: metadataString9(endpoint?.metadata, "branch") ?? metadataString9(endpoint?.metadata, "workspaceQualifier") ?? metadataString9(agent?.metadata, "branch") ?? metadataString9(agent?.metadata, "workspaceQualifier"),
|
|
75930
76729
|
parentConversationId: conversation.parentConversationId ?? null,
|
|
@@ -75951,6 +76750,13 @@ async function getScoutConversations(filters = {}, brokerContext) {
|
|
|
75951
76750
|
return [];
|
|
75952
76751
|
}
|
|
75953
76752
|
const identityFields = conversationIdentityFields2(conversation);
|
|
76753
|
+
const runtime = latestConversationRuntime({
|
|
76754
|
+
sessionId,
|
|
76755
|
+
participants,
|
|
76756
|
+
invocations: invocations2,
|
|
76757
|
+
flights,
|
|
76758
|
+
endpoint: null
|
|
76759
|
+
});
|
|
75954
76760
|
return [{
|
|
75955
76761
|
id: conversation.id,
|
|
75956
76762
|
chatId: conversation.id,
|
|
@@ -75965,7 +76771,10 @@ async function getScoutConversations(filters = {}, brokerContext) {
|
|
|
75965
76771
|
authorityNodeName: snapshot.nodes?.[conversation.authorityNodeId]?.name ?? null,
|
|
75966
76772
|
agentId: null,
|
|
75967
76773
|
agentName: null,
|
|
75968
|
-
harness:
|
|
76774
|
+
harness: runtime.harness,
|
|
76775
|
+
model: runtime.model,
|
|
76776
|
+
reasoningEffort: runtime.reasoningEffort,
|
|
76777
|
+
transport: runtime.transport,
|
|
75969
76778
|
sessionId,
|
|
75970
76779
|
currentBranch: null,
|
|
75971
76780
|
parentConversationId: conversation.parentConversationId ?? null,
|
|
@@ -75992,15 +76801,17 @@ function capSummaryRoster(summary, operatorIds, endpoints) {
|
|
|
75992
76801
|
if (summary.participantIds.length <= CHANNEL_ROSTER_CAP)
|
|
75993
76802
|
return summary;
|
|
75994
76803
|
const keep = new Set;
|
|
75995
|
-
|
|
75996
|
-
|
|
75997
|
-
keep.
|
|
75998
|
-
|
|
75999
|
-
|
|
76000
|
-
|
|
76001
|
-
|
|
76002
|
-
|
|
76003
|
-
|
|
76804
|
+
const fillFromTier = (matches) => {
|
|
76805
|
+
for (const id of summary.participantIds) {
|
|
76806
|
+
if (keep.size >= CHANNEL_ROSTER_CAP)
|
|
76807
|
+
return;
|
|
76808
|
+
if (matches(id))
|
|
76809
|
+
keep.add(id);
|
|
76810
|
+
}
|
|
76811
|
+
};
|
|
76812
|
+
fillFromTier((id) => operatorIds.has(id));
|
|
76813
|
+
fillFromTier((id) => !operatorIds.has(id) && participantEndpoint(endpoints, id) !== null);
|
|
76814
|
+
fillFromTier(() => true);
|
|
76004
76815
|
const keptIds = summary.participantIds.filter((id) => keep.has(id));
|
|
76005
76816
|
const droppedIds = summary.participantIds.filter((id) => !keep.has(id));
|
|
76006
76817
|
return {
|
|
@@ -76009,12 +76820,12 @@ function capSummaryRoster(summary, operatorIds, endpoints) {
|
|
|
76009
76820
|
participants: summary.participants.filter((participant) => keep.has(participant.actorId))
|
|
76010
76821
|
};
|
|
76011
76822
|
}
|
|
76012
|
-
async function getScoutConversationMessages(conversationId, limit = 80, beforeMessageId) {
|
|
76823
|
+
async function getScoutConversationMessages(conversationId, limit = 80, beforeMessageId, brokerContext) {
|
|
76013
76824
|
const normalizedId = conversationId.trim();
|
|
76014
76825
|
if (!normalizedId || !isOpaqueChannelId(normalizedId)) {
|
|
76015
76826
|
return [];
|
|
76016
76827
|
}
|
|
76017
|
-
const broker2 = await loadScoutBrokerContext(undefined, { scope: "conversations" });
|
|
76828
|
+
const broker2 = brokerContext === undefined ? await loadScoutBrokerContext(undefined, { scope: "conversations" }) : brokerContext;
|
|
76018
76829
|
if (!broker2)
|
|
76019
76830
|
return null;
|
|
76020
76831
|
const snapshot = broker2.snapshot;
|
|
@@ -76085,6 +76896,7 @@ import { basename as basename20, join as join54, resolve as resolve20 } from "pa
|
|
|
76085
76896
|
init_secret_redaction();
|
|
76086
76897
|
import { basename as basename19 } from "path";
|
|
76087
76898
|
import { open, stat as stat9 } from "fs/promises";
|
|
76899
|
+
import { StringDecoder } from "string_decoder";
|
|
76088
76900
|
|
|
76089
76901
|
// packages/runtime/src/tail/claude-source.ts
|
|
76090
76902
|
init_user_config();
|
|
@@ -78991,8 +79803,10 @@ function readPositiveIntEnv8(name2, fallback) {
|
|
|
78991
79803
|
const raw2 = Number.parseInt(process.env[name2] ?? "", 10);
|
|
78992
79804
|
return Number.isFinite(raw2) && raw2 > 0 ? raw2 : fallback;
|
|
78993
79805
|
}
|
|
78994
|
-
var
|
|
78995
|
-
var
|
|
79806
|
+
var DEFAULT_TAIL_POLL_INTERVAL_MS = 1e4;
|
|
79807
|
+
var DEFAULT_HOT_DISCOVERY_INTERVAL_MS = 60000;
|
|
79808
|
+
var TAIL_POLL_INTERVAL_MS = readPositiveIntEnv8("OPENSCOUT_TAIL_POLL_INTERVAL_MS", DEFAULT_TAIL_POLL_INTERVAL_MS);
|
|
79809
|
+
var HOT_DISCOVERY_INTERVAL_MS = readPositiveIntEnv8("OPENSCOUT_TAIL_HOT_DISCOVERY_INTERVAL_MS", DEFAULT_HOT_DISCOVERY_INTERVAL_MS);
|
|
78996
79810
|
var DISCOVERY_CACHE_MAX_AGE_MS = readPositiveIntEnv8("OPENSCOUT_TAIL_DISCOVERY_CACHE_MAX_AGE_MS", HOT_DISCOVERY_INTERVAL_MS);
|
|
78997
79811
|
var SHALLOW_DISCOVERY_INTERVAL_MS = readPositiveIntEnv8("OPENSCOUT_TAIL_SHALLOW_DISCOVERY_INTERVAL_MS", 10 * 60000);
|
|
78998
79812
|
var DEEP_DISCOVERY_INTERVAL_MS = readPositiveIntEnv8("OPENSCOUT_TAIL_DEEP_DISCOVERY_INTERVAL_MS", 60 * 60000);
|
|
@@ -79006,23 +79820,42 @@ var RAW_MAX_STRING_LEN = 1000;
|
|
|
79006
79820
|
var RAW_MAX_ARRAY_ITEMS = 25;
|
|
79007
79821
|
var RAW_MAX_OBJECT_KEYS = 50;
|
|
79008
79822
|
var RECENT_TRANSCRIPT_READ_BYTES = 512 * 1024;
|
|
79823
|
+
var WATCHER_READ_BYTES = readPositiveIntEnv8("OPENSCOUT_TAIL_WATCHER_READ_BYTES", 512 * 1024);
|
|
79824
|
+
var WATCHER_DRAIN_BYTES = Math.max(WATCHER_READ_BYTES, readPositiveIntEnv8("OPENSCOUT_TAIL_WATCHER_DRAIN_BYTES", 4 * 1024 * 1024));
|
|
79825
|
+
var WATCHER_PUMP_CONCURRENCY = readPositiveIntEnv8("OPENSCOUT_TAIL_WATCHER_PUMP_CONCURRENCY", 16);
|
|
79009
79826
|
var SESSION_TRANSCRIPT_READ_BYTES = 8 * 1024 * 1024;
|
|
79010
79827
|
var RECENT_TRANSCRIPT_KIND_SCAN_READ_BYTES = 32 * 1024 * 1024;
|
|
79011
79828
|
var RECENT_TRANSCRIPT_LINES_PER_FILE = 200;
|
|
79012
79829
|
var RECENT_TRANSCRIPT_KIND_SCAN_MAX_LINES = 65536;
|
|
79013
79830
|
var RECENT_TRANSCRIPT_MAX_FILES = readPositiveIntEnv8("OPENSCOUT_TAIL_RECENT_TRANSCRIPT_MAX_FILES", 24);
|
|
79831
|
+
var INTERNAL_RECONCILE_SESSIONS_PER_SOURCE = readPositiveIntEnv8("OPENSCOUT_TAIL_INTERNAL_RECONCILE_SESSIONS_PER_SOURCE", 12);
|
|
79832
|
+
var INTERNAL_RECONCILE_LINES_PER_SESSION = readPositiveIntEnv8("OPENSCOUT_TAIL_INTERNAL_RECONCILE_LINES_PER_SESSION", 128);
|
|
79833
|
+
var INTERNAL_RECONCILE_READ_BYTES = readPositiveIntEnv8("OPENSCOUT_TAIL_INTERNAL_RECONCILE_READ_BYTES", 256 * 1024);
|
|
79834
|
+
var INTERNAL_HOT_WATCHER_WINDOW_MS = readPositiveIntEnv8("OPENSCOUT_TAIL_INTERNAL_HOT_WATCHER_WINDOW_MS", 60000);
|
|
79835
|
+
var INTERNAL_IDLE_WATCHER_INTERVAL_MS = readPositiveIntEnv8("OPENSCOUT_TAIL_INTERNAL_IDLE_WATCHER_INTERVAL_MS", 15000);
|
|
79836
|
+
var INTERNAL_IDLE_WATCHER_BATCH_SIZE = readPositiveIntEnv8("OPENSCOUT_TAIL_INTERNAL_IDLE_WATCHER_BATCH_SIZE", 32);
|
|
79837
|
+
var INTERNAL_ACTIVE_STALE_AFTER_MS = readPositiveIntEnv8("OPENSCOUT_TAIL_INTERNAL_ACTIVE_STALE_AFTER_MS", 30 * 60000);
|
|
79838
|
+
var INTERNAL_STALE_CONFIRMATION_COUNT = 2;
|
|
79839
|
+
var AUTHORITATIVE_MISSING_CONFIRMATION_COUNT = 2;
|
|
79840
|
+
var INTERNAL_PERSISTED_OBSERVED_SEED_LIMIT = readPositiveIntEnv8("OPENSCOUT_TAIL_PERSISTED_OBSERVED_SEED_LIMIT", 4096);
|
|
79014
79841
|
var NATIVE_TAIL_SOURCES = new Set(["grok", "kimi", "opencode", "cursor"]);
|
|
79015
79842
|
var TRANSCRIPT_REPLAY_MEMO_MAX_ENTRIES = readPositiveIntEnv8("OPENSCOUT_TAIL_REPLAY_MEMO_MAX_ENTRIES", 256);
|
|
79016
79843
|
var TRANSCRIPT_REPLAY_ACTIVE_GRACE_MS = readPositiveIntEnv8("OPENSCOUT_TAIL_REPLAY_MEMO_ACTIVE_GRACE_MS", 2000);
|
|
79017
79844
|
var transcriptReplayMemo = new Map;
|
|
79018
79845
|
var transcriptReplayInFlight = new Map;
|
|
79846
|
+
var INTERNAL_TAIL_SESSION_OFFLINE_SUMMARY = "session lifecycle \xB7 confirmed offline";
|
|
79847
|
+
var INTERNAL_TAIL_SESSION_STALLED_SUMMARY = "session lifecycle \xB7 confirmed stale";
|
|
79019
79848
|
var sources = [GrokSource, KimiSource, ClaudeSource, CodexSource, CursorSource, OpenCodeSource, PiSource];
|
|
79020
79849
|
var watchers = new Map;
|
|
79021
79850
|
var aggregateBuffer = [];
|
|
79022
79851
|
var assistantBuffer = [];
|
|
79023
79852
|
var perSessionBuffer = new Map;
|
|
79024
79853
|
var subscribers = new Set;
|
|
79854
|
+
var internalSubscribers = new Set;
|
|
79855
|
+
var watcherPumpQueue = [];
|
|
79856
|
+
var activeWatcherPumps = 0;
|
|
79025
79857
|
var knownTranscripts = new Map;
|
|
79858
|
+
var persistedObservedSessions = new Map;
|
|
79026
79859
|
var quietEventLastSeen = new Map;
|
|
79027
79860
|
var pollTimer = null;
|
|
79028
79861
|
var hotDiscoveryTimer = null;
|
|
@@ -79219,10 +80052,19 @@ function shouldCoalesceQuietTailEvent(event) {
|
|
|
79219
80052
|
pruneQuietTailCoalescer(now);
|
|
79220
80053
|
return false;
|
|
79221
80054
|
}
|
|
79222
|
-
function
|
|
80055
|
+
function pushInternalEvent(rawEvent) {
|
|
79223
80056
|
const event = compactEvent(rawEvent);
|
|
80057
|
+
for (const subscriber of [...internalSubscribers]) {
|
|
80058
|
+
try {
|
|
80059
|
+
subscriber(event);
|
|
80060
|
+
} catch {}
|
|
80061
|
+
}
|
|
80062
|
+
return event;
|
|
80063
|
+
}
|
|
80064
|
+
function pushEvent(rawEvent) {
|
|
80065
|
+
const event = pushInternalEvent(rawEvent);
|
|
79224
80066
|
if (shouldCoalesceQuietTailEvent(event))
|
|
79225
|
-
return;
|
|
80067
|
+
return event;
|
|
79226
80068
|
aggregateBuffer.push(event);
|
|
79227
80069
|
if (aggregateBuffer.length > AGGREGATE_BUFFER_LIMIT) {
|
|
79228
80070
|
aggregateBuffer.splice(0, aggregateBuffer.length - AGGREGATE_BUFFER_LIMIT);
|
|
@@ -79247,15 +80089,114 @@ function pushEvent(rawEvent) {
|
|
|
79247
80089
|
subscriber(event);
|
|
79248
80090
|
} catch {}
|
|
79249
80091
|
}
|
|
80092
|
+
return event;
|
|
80093
|
+
}
|
|
80094
|
+
function rememberWatcherEvent(watcher, rawEvent, delivery) {
|
|
80095
|
+
if (watcher.emittedEventIds.has(rawEvent.id))
|
|
80096
|
+
return;
|
|
80097
|
+
watcher.emittedEventIds.add(rawEvent.id);
|
|
80098
|
+
const event = delivery === "all" ? pushEvent(rawEvent) : pushInternalEvent(rawEvent);
|
|
80099
|
+
watcher.internalObserved = true;
|
|
80100
|
+
watcher.lastInternalEvent = event;
|
|
80101
|
+
watcher.staleObservations = 0;
|
|
80102
|
+
watcher.lifecycleNotification = "none";
|
|
80103
|
+
const lifecycle = persistedObservedSessions.get(observedSessionLifecycleKey(watcher.source.name, event.sessionId));
|
|
80104
|
+
if (lifecycle) {
|
|
80105
|
+
lifecycle.missingAuthoritativePasses = 0;
|
|
80106
|
+
lifecycle.lifecycleNotification = "none";
|
|
80107
|
+
}
|
|
80108
|
+
}
|
|
80109
|
+
function observedSessionLifecycleKey(source, sourceSessionId) {
|
|
80110
|
+
return `${source.trim()}\x00${sourceSessionId.trim()}`;
|
|
80111
|
+
}
|
|
80112
|
+
function persistedSeedEvent(seed) {
|
|
80113
|
+
const source = seed.source.trim();
|
|
80114
|
+
const sourceSessionId = seed.sourceSessionId.trim();
|
|
80115
|
+
const timestamp = Number.isFinite(seed.lastActivityAt) && seed.lastActivityAt > 0 ? seed.lastActivityAt : 0;
|
|
80116
|
+
return {
|
|
80117
|
+
id: `tail-persisted-seed:${source}:${sourceSessionId}:${timestamp}`,
|
|
80118
|
+
ts: timestamp,
|
|
80119
|
+
source,
|
|
80120
|
+
sessionId: sourceSessionId,
|
|
80121
|
+
pid: virtualPidForPath(`${source}:${sourceSessionId}`),
|
|
80122
|
+
parentPid: null,
|
|
80123
|
+
project: seed.project?.trim() ?? "",
|
|
80124
|
+
cwd: seed.cwd?.trim() || seed.projectRoot?.trim() || "",
|
|
80125
|
+
harness: "unattributed",
|
|
80126
|
+
kind: "system",
|
|
80127
|
+
summary: "session lifecycle \xB7 restored persisted active identity",
|
|
80128
|
+
raw: { reason: "persisted_active_seed" }
|
|
80129
|
+
};
|
|
80130
|
+
}
|
|
80131
|
+
function applyPersistedObservedSeedToWatcher(watcher) {
|
|
80132
|
+
if (watcher.internalObserved)
|
|
80133
|
+
return;
|
|
80134
|
+
const sessionId = watcher.transcript.sessionId?.trim();
|
|
80135
|
+
if (!sessionId)
|
|
80136
|
+
return;
|
|
80137
|
+
const lifecycle = persistedObservedSessions.get(observedSessionLifecycleKey(watcher.source.name, sessionId));
|
|
80138
|
+
if (!lifecycle)
|
|
80139
|
+
return;
|
|
80140
|
+
watcher.internalObserved = true;
|
|
80141
|
+
watcher.lastInternalEvent = persistedSeedEvent(lifecycle.seed);
|
|
80142
|
+
watcher.missingAuthoritativePasses = lifecycle.missingAuthoritativePasses;
|
|
80143
|
+
watcher.lifecycleNotification = lifecycle.lifecycleNotification;
|
|
80144
|
+
}
|
|
80145
|
+
function watcherSessionId(watcher) {
|
|
80146
|
+
return watcher.lastInternalEvent?.sessionId.trim() || watcher.transcript.sessionId?.trim() || null;
|
|
80147
|
+
}
|
|
80148
|
+
function notifyWatcherLifecycle(watcher, reason, observedAt) {
|
|
80149
|
+
const nextNotification = reason === "missing" ? "offline" : "stalled";
|
|
80150
|
+
const sessionId = watcherSessionId(watcher);
|
|
80151
|
+
if (!sessionId)
|
|
80152
|
+
return;
|
|
80153
|
+
const lifecycleKey = observedSessionLifecycleKey(watcher.source.name, sessionId);
|
|
80154
|
+
const persistedLifecycle = persistedObservedSessions.get(lifecycleKey);
|
|
80155
|
+
if (!watcher.internalObserved || watcher.lifecycleNotification === nextNotification || watcher.lifecycleNotification === "offline" || persistedLifecycle?.lifecycleNotification === nextNotification || persistedLifecycle?.lifecycleNotification === "offline")
|
|
80156
|
+
return;
|
|
80157
|
+
watcher.lifecycleNotification = nextNotification;
|
|
80158
|
+
if (persistedLifecycle) {
|
|
80159
|
+
persistedLifecycle.lifecycleNotification = nextNotification;
|
|
80160
|
+
}
|
|
80161
|
+
pushInternalEvent({
|
|
80162
|
+
id: `tail-lifecycle:${watcher.source.name}:${sessionId}:${nextNotification}:${observedAt}`,
|
|
80163
|
+
ts: observedAt,
|
|
80164
|
+
source: watcher.source.name,
|
|
80165
|
+
sessionId,
|
|
80166
|
+
pid: watcher.process.pid,
|
|
80167
|
+
parentPid: watcher.process.ppid || null,
|
|
80168
|
+
project: watcher.transcript.project,
|
|
80169
|
+
cwd: watcher.transcript.cwd ?? watcher.process.cwd ?? "",
|
|
80170
|
+
harness: watcher.transcript.harness,
|
|
80171
|
+
kind: "system",
|
|
80172
|
+
summary: reason === "missing" ? INTERNAL_TAIL_SESSION_OFFLINE_SUMMARY : INTERNAL_TAIL_SESSION_STALLED_SUMMARY,
|
|
80173
|
+
raw: { reason }
|
|
80174
|
+
});
|
|
80175
|
+
if (nextNotification === "offline") {
|
|
80176
|
+
persistedObservedSessions.delete(lifecycleKey);
|
|
80177
|
+
}
|
|
80178
|
+
}
|
|
80179
|
+
function observeWatcherStaleness(watcher, observedAt) {
|
|
80180
|
+
if (watcher.lifecycleNotification !== "none" || !watcher.internalObserved || observedAt - watcher.lastObservedChangeAt < INTERNAL_ACTIVE_STALE_AFTER_MS) {
|
|
80181
|
+
watcher.staleObservations = 0;
|
|
80182
|
+
return;
|
|
80183
|
+
}
|
|
80184
|
+
watcher.staleObservations++;
|
|
80185
|
+
if (watcher.staleObservations >= INTERNAL_STALE_CONFIRMATION_COUNT) {
|
|
80186
|
+
notifyWatcherLifecycle(watcher, "stale", observedAt);
|
|
80187
|
+
}
|
|
79250
80188
|
}
|
|
79251
80189
|
async function readNew(handle, fromOffset, fileSize) {
|
|
79252
80190
|
if (fileSize <= fromOffset) {
|
|
79253
|
-
return {
|
|
80191
|
+
return { bytes: Buffer.alloc(0), nextOffset: fromOffset };
|
|
79254
80192
|
}
|
|
79255
|
-
const length = fileSize - fromOffset;
|
|
79256
|
-
const buffer = Buffer.
|
|
79257
|
-
await handle.read(buffer, 0, length, fromOffset);
|
|
79258
|
-
return {
|
|
80193
|
+
const length = Math.min(fileSize - fromOffset, WATCHER_READ_BYTES);
|
|
80194
|
+
const buffer = Buffer.allocUnsafe(length);
|
|
80195
|
+
const { bytesRead } = await handle.read(buffer, 0, length, fromOffset);
|
|
80196
|
+
return {
|
|
80197
|
+
bytes: buffer.subarray(0, bytesRead),
|
|
80198
|
+
nextOffset: fromOffset + bytesRead
|
|
80199
|
+
};
|
|
79259
80200
|
}
|
|
79260
80201
|
async function readTranscriptText(path2, maxBytes = RECENT_TRANSCRIPT_READ_BYTES) {
|
|
79261
80202
|
let handle = null;
|
|
@@ -79275,23 +80216,35 @@ async function readTranscriptText(path2, maxBytes = RECENT_TRANSCRIPT_READ_BYTES
|
|
|
79275
80216
|
await handle?.close().catch(() => {});
|
|
79276
80217
|
}
|
|
79277
80218
|
}
|
|
79278
|
-
async function
|
|
80219
|
+
async function runWatcherPump(watcher, observedAt) {
|
|
79279
80220
|
let handle = null;
|
|
80221
|
+
watcher.lastPumpAt = observedAt;
|
|
79280
80222
|
try {
|
|
79281
80223
|
const stats = await stat9(watcher.transcriptPath);
|
|
80224
|
+
const changed = stats.size !== watcher.lastKnownSize || stats.mtimeMs !== watcher.lastKnownMtimeMs;
|
|
80225
|
+
watcher.lastKnownSize = stats.size;
|
|
80226
|
+
watcher.lastKnownMtimeMs = stats.mtimeMs;
|
|
80227
|
+
if (changed) {
|
|
80228
|
+
watcher.lastObservedChangeAt = observedAt;
|
|
80229
|
+
watcher.staleObservations = 0;
|
|
80230
|
+
watcher.lifecycleNotification = "none";
|
|
80231
|
+
}
|
|
79282
80232
|
if (stats.size < watcher.offset) {
|
|
79283
80233
|
watcher.offset = 0;
|
|
79284
80234
|
watcher.carry = "";
|
|
80235
|
+
watcher.decoder = new StringDecoder("utf8");
|
|
79285
80236
|
watcher.emittedEventIds.clear();
|
|
79286
80237
|
}
|
|
79287
|
-
if (stats.size <= watcher.offset)
|
|
80238
|
+
if (stats.size <= watcher.offset) {
|
|
80239
|
+
observeWatcherStaleness(watcher, observedAt);
|
|
79288
80240
|
return;
|
|
80241
|
+
}
|
|
79289
80242
|
if (watcher.source.parseFile) {
|
|
79290
|
-
const
|
|
80243
|
+
const text4 = await readTranscriptText(watcher.transcriptPath);
|
|
79291
80244
|
watcher.offset = stats.size;
|
|
79292
|
-
if (!
|
|
80245
|
+
if (!text4)
|
|
79293
80246
|
return;
|
|
79294
|
-
const events2 = parsedEventsToArray(watcher.source.parseFile(
|
|
80247
|
+
const events2 = parsedEventsToArray(watcher.source.parseFile(text4, {
|
|
79295
80248
|
process: watcher.process,
|
|
79296
80249
|
transcript: watcher.transcript,
|
|
79297
80250
|
transcriptPath: watcher.transcriptPath,
|
|
@@ -79300,74 +80253,203 @@ async function pumpWatcher(watcher) {
|
|
|
79300
80253
|
}));
|
|
79301
80254
|
watcher.lineCounter += Math.max(1, events2.length);
|
|
79302
80255
|
for (const event of events2) {
|
|
79303
|
-
|
|
79304
|
-
continue;
|
|
79305
|
-
watcher.emittedEventIds.add(event.id);
|
|
79306
|
-
pushEvent(event);
|
|
80256
|
+
rememberWatcherEvent(watcher, event, "all");
|
|
79307
80257
|
}
|
|
79308
80258
|
return;
|
|
79309
80259
|
}
|
|
79310
|
-
|
|
79311
|
-
|
|
79312
|
-
|
|
79313
|
-
|
|
79314
|
-
|
|
79315
|
-
|
|
79316
|
-
|
|
79317
|
-
|
|
79318
|
-
|
|
79319
|
-
|
|
79320
|
-
if (!
|
|
80260
|
+
const drainEnd = Math.min(stats.size, watcher.offset + WATCHER_DRAIN_BYTES);
|
|
80261
|
+
while (watcher.offset < drainEnd) {
|
|
80262
|
+
handle = await open(watcher.transcriptPath, "r");
|
|
80263
|
+
const { bytes, nextOffset } = await readNew(handle, watcher.offset, drainEnd);
|
|
80264
|
+
await handle.close();
|
|
80265
|
+
handle = null;
|
|
80266
|
+
if (nextOffset <= watcher.offset)
|
|
80267
|
+
break;
|
|
80268
|
+
watcher.offset = nextOffset;
|
|
80269
|
+
const text4 = watcher.decoder.write(bytes);
|
|
80270
|
+
if (!text4)
|
|
79321
80271
|
continue;
|
|
79322
|
-
const
|
|
79323
|
-
|
|
79324
|
-
|
|
79325
|
-
|
|
79326
|
-
|
|
79327
|
-
|
|
79328
|
-
});
|
|
79329
|
-
watcher.lineCounter++;
|
|
79330
|
-
if (event) {
|
|
79331
|
-
if (watcher.emittedEventIds.has(event.id))
|
|
80272
|
+
const combined = watcher.carry + text4;
|
|
80273
|
+
const lines = combined.split(`
|
|
80274
|
+
`);
|
|
80275
|
+
watcher.carry = lines.pop() ?? "";
|
|
80276
|
+
for (const line of lines) {
|
|
80277
|
+
if (!line)
|
|
79332
80278
|
continue;
|
|
79333
|
-
watcher.
|
|
79334
|
-
|
|
80279
|
+
const event = watcher.source.parseLine(line, {
|
|
80280
|
+
process: watcher.process,
|
|
80281
|
+
transcript: watcher.transcript,
|
|
80282
|
+
transcriptPath: watcher.transcriptPath,
|
|
80283
|
+
lineOffset: watcher.lineCounter,
|
|
80284
|
+
state: watcher.state
|
|
80285
|
+
});
|
|
80286
|
+
watcher.lineCounter++;
|
|
80287
|
+
if (event) {
|
|
80288
|
+
rememberWatcherEvent(watcher, event, "all");
|
|
80289
|
+
}
|
|
79335
80290
|
}
|
|
79336
80291
|
}
|
|
80292
|
+
if (stats.size > watcher.offset) {
|
|
80293
|
+
const continuation = setTimeout(() => {
|
|
80294
|
+
pumpWatcher(watcher);
|
|
80295
|
+
}, 0);
|
|
80296
|
+
continuation.unref?.();
|
|
80297
|
+
}
|
|
79337
80298
|
} catch {} finally {
|
|
79338
80299
|
await handle?.close().catch(() => {});
|
|
79339
80300
|
}
|
|
79340
80301
|
}
|
|
79341
|
-
|
|
79342
|
-
|
|
80302
|
+
function scheduleWatcherPump(run) {
|
|
80303
|
+
return new Promise((resolve20, reject) => {
|
|
80304
|
+
const start = () => {
|
|
80305
|
+
activeWatcherPumps++;
|
|
80306
|
+
Promise.resolve().then(run).then(resolve20, reject).finally(() => {
|
|
80307
|
+
activeWatcherPumps--;
|
|
80308
|
+
watcherPumpQueue.shift()?.();
|
|
80309
|
+
});
|
|
80310
|
+
};
|
|
80311
|
+
if (activeWatcherPumps < WATCHER_PUMP_CONCURRENCY) {
|
|
80312
|
+
start();
|
|
80313
|
+
} else {
|
|
80314
|
+
watcherPumpQueue.push(start);
|
|
80315
|
+
}
|
|
80316
|
+
});
|
|
80317
|
+
}
|
|
80318
|
+
function pumpWatcher(watcher, observedAt = Date.now()) {
|
|
80319
|
+
if (watcher.pumpInFlight) {
|
|
80320
|
+
return watcher.pumpInFlight;
|
|
80321
|
+
}
|
|
80322
|
+
const request = scheduleWatcherPump(() => runWatcherPump(watcher, observedAt));
|
|
80323
|
+
watcher.pumpInFlight = request;
|
|
80324
|
+
request.finally(() => {
|
|
80325
|
+
if (watcher.pumpInFlight === request) {
|
|
80326
|
+
watcher.pumpInFlight = null;
|
|
80327
|
+
}
|
|
80328
|
+
}).catch(() => {});
|
|
80329
|
+
return request;
|
|
80330
|
+
}
|
|
80331
|
+
function selectWatchersForCurrentDemand(now = Date.now()) {
|
|
80332
|
+
const all = [...watchers.values()];
|
|
80333
|
+
if (subscribers.size > 0)
|
|
80334
|
+
return all;
|
|
80335
|
+
if (internalSubscribers.size === 0)
|
|
80336
|
+
return [];
|
|
80337
|
+
const hot = [];
|
|
80338
|
+
const coldDue = [];
|
|
80339
|
+
for (const watcher of all) {
|
|
80340
|
+
if (now - watcher.lastObservedChangeAt <= INTERNAL_HOT_WATCHER_WINDOW_MS) {
|
|
80341
|
+
hot.push(watcher);
|
|
80342
|
+
} else if (now - watcher.lastPumpAt >= INTERNAL_IDLE_WATCHER_INTERVAL_MS) {
|
|
80343
|
+
coldDue.push(watcher);
|
|
80344
|
+
}
|
|
80345
|
+
}
|
|
80346
|
+
coldDue.sort((left, right) => left.lastPumpAt - right.lastPumpAt);
|
|
80347
|
+
return [...hot, ...coldDue.slice(0, INTERNAL_IDLE_WATCHER_BATCH_SIZE)];
|
|
80348
|
+
}
|
|
80349
|
+
async function pumpWatchersForCurrentDemand(now = Date.now()) {
|
|
80350
|
+
const selected = selectWatchersForCurrentDemand(now);
|
|
80351
|
+
await Promise.allSettled(selected.map((watcher) => pumpWatcher(watcher, now)));
|
|
79343
80352
|
}
|
|
79344
|
-
async function seedTail(watcher) {
|
|
80353
|
+
async function seedTail(watcher, options = { reconcileInternal: false }) {
|
|
80354
|
+
let stats;
|
|
79345
80355
|
try {
|
|
79346
|
-
|
|
79347
|
-
|
|
79348
|
-
|
|
79349
|
-
|
|
80356
|
+
stats = await stat9(watcher.transcriptPath);
|
|
80357
|
+
} catch {
|
|
80358
|
+
watcher.offset = 0;
|
|
80359
|
+
return;
|
|
80360
|
+
}
|
|
80361
|
+
const seededAt = Date.now();
|
|
80362
|
+
watcher.offset = options.reconcileInternal || !watcher.source.parseFile ? stats.size : 0;
|
|
80363
|
+
watcher.lastPumpAt = seededAt;
|
|
80364
|
+
watcher.lastKnownSize = stats.size;
|
|
80365
|
+
watcher.lastKnownMtimeMs = stats.mtimeMs;
|
|
80366
|
+
watcher.lastObservedChangeAt = Math.max(watcher.transcript.lastEventAt ?? 0, watcher.transcript.mtimeMs, stats.mtimeMs);
|
|
80367
|
+
try {
|
|
80368
|
+
if (options.reconcileInternal && watcher.source.parseFile) {
|
|
80369
|
+
const text4 = await readTranscriptText(watcher.transcriptPath, INTERNAL_RECONCILE_READ_BYTES);
|
|
80370
|
+
if (!text4)
|
|
80371
|
+
return;
|
|
80372
|
+
const events2 = parsedEventsToArray(watcher.source.parseFile(text4, {
|
|
80373
|
+
process: watcher.process,
|
|
80374
|
+
transcript: watcher.transcript,
|
|
80375
|
+
transcriptPath: watcher.transcriptPath,
|
|
80376
|
+
lineOffset: 0,
|
|
80377
|
+
state: watcher.state
|
|
80378
|
+
}));
|
|
80379
|
+
watcher.lineCounter = Math.max(1, events2.length);
|
|
80380
|
+
for (const event of events2)
|
|
80381
|
+
rememberWatcherEvent(watcher, event, "internal");
|
|
80382
|
+
return;
|
|
80383
|
+
}
|
|
80384
|
+
if (!watcher.source.parseFile && (options.reconcileInternal || watcher.source.name === "codex")) {
|
|
80385
|
+
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
80386
|
lines.forEach((line, index2) => {
|
|
79351
|
-
watcher.source.parseLine(line, {
|
|
80387
|
+
const parsed = watcher.source.parseLine(line, {
|
|
79352
80388
|
process: watcher.process,
|
|
79353
80389
|
transcript: watcher.transcript,
|
|
79354
80390
|
transcriptPath: watcher.transcriptPath,
|
|
79355
80391
|
lineOffset: index2,
|
|
79356
80392
|
state: watcher.state
|
|
79357
80393
|
});
|
|
80394
|
+
if (options.reconcileInternal && parsed) {
|
|
80395
|
+
rememberWatcherEvent(watcher, parsed, "internal");
|
|
80396
|
+
}
|
|
79358
80397
|
});
|
|
80398
|
+
watcher.lineCounter = lines.length;
|
|
79359
80399
|
}
|
|
79360
|
-
} catch {
|
|
79361
|
-
|
|
80400
|
+
} catch {}
|
|
80401
|
+
}
|
|
80402
|
+
function reconcileMissingWatchers(seenSessionKeys, successfullyScannedSources, observedAt) {
|
|
80403
|
+
for (const [sessionKey4, watcher] of watchers) {
|
|
80404
|
+
if (seenSessionKeys.has(sessionKey4)) {
|
|
80405
|
+
watcher.missingAuthoritativePasses = 0;
|
|
80406
|
+
continue;
|
|
80407
|
+
}
|
|
80408
|
+
if (!successfullyScannedSources.has(watcher.source.name))
|
|
80409
|
+
continue;
|
|
80410
|
+
watcher.missingAuthoritativePasses++;
|
|
80411
|
+
if (watcher.missingAuthoritativePasses < AUTHORITATIVE_MISSING_CONFIRMATION_COUNT) {
|
|
80412
|
+
continue;
|
|
80413
|
+
}
|
|
80414
|
+
notifyWatcherLifecycle(watcher, "missing", observedAt);
|
|
80415
|
+
watchers.delete(sessionKey4);
|
|
80416
|
+
knownTranscripts.delete(sessionKey4);
|
|
80417
|
+
}
|
|
80418
|
+
}
|
|
80419
|
+
function reconcilePersistedObservedSessions(seenLifecycleKeys, successfullyScannedSources, observedAt) {
|
|
80420
|
+
for (const [lifecycleKey, lifecycle] of persistedObservedSessions) {
|
|
80421
|
+
if (seenLifecycleKeys.has(lifecycleKey)) {
|
|
80422
|
+
lifecycle.missingAuthoritativePasses = 0;
|
|
80423
|
+
continue;
|
|
80424
|
+
}
|
|
80425
|
+
if (!successfullyScannedSources.has(lifecycle.seed.source))
|
|
80426
|
+
continue;
|
|
80427
|
+
lifecycle.missingAuthoritativePasses++;
|
|
80428
|
+
if (lifecycle.missingAuthoritativePasses < AUTHORITATIVE_MISSING_CONFIRMATION_COUNT || lifecycle.lifecycleNotification === "offline") {
|
|
80429
|
+
continue;
|
|
80430
|
+
}
|
|
80431
|
+
lifecycle.lifecycleNotification = "offline";
|
|
80432
|
+
const seedEvent = persistedSeedEvent(lifecycle.seed);
|
|
80433
|
+
pushInternalEvent({
|
|
80434
|
+
...seedEvent,
|
|
80435
|
+
id: `tail-lifecycle:${lifecycle.seed.source}:${lifecycle.seed.sourceSessionId}:offline:${observedAt}`,
|
|
80436
|
+
ts: observedAt,
|
|
80437
|
+
summary: INTERNAL_TAIL_SESSION_OFFLINE_SUMMARY,
|
|
80438
|
+
raw: { reason: "missing" }
|
|
80439
|
+
});
|
|
80440
|
+
persistedObservedSessions.delete(lifecycleKey);
|
|
79362
80441
|
}
|
|
79363
80442
|
}
|
|
79364
80443
|
async function refreshDiscovery(scope = "shallow", options = { pruneMissing: scope !== "hot" }) {
|
|
79365
80444
|
const allProcesses = [];
|
|
79366
80445
|
const cachedProcesses = lastDiscovery?.processes ?? [];
|
|
79367
80446
|
const seenSessionKeys = new Set;
|
|
80447
|
+
const seenObservedLifecycleKeys = new Set;
|
|
80448
|
+
const successfullyScannedSources = new Set;
|
|
79368
80449
|
const discoveryIssues = [];
|
|
79369
80450
|
const discoveryIssueKeys = new Set;
|
|
79370
80451
|
for (const source of sources) {
|
|
80452
|
+
let remainingInternalReconciliations = internalSubscribers.size > 0 ? INTERNAL_RECONCILE_SESSIONS_PER_SOURCE : 0;
|
|
79371
80453
|
let processes = [];
|
|
79372
80454
|
if (scope === "hot" && cachedProcesses.length > 0) {
|
|
79373
80455
|
processes = cachedProcesses.filter((proc) => proc.source === source.name);
|
|
@@ -79382,14 +80464,19 @@ async function refreshDiscovery(scope = "shallow", options = { pruneMissing: sco
|
|
|
79382
80464
|
let transcripts = [];
|
|
79383
80465
|
try {
|
|
79384
80466
|
transcripts = await source.discoverTranscripts(processes, scope);
|
|
80467
|
+
successfullyScannedSources.add(source.name);
|
|
79385
80468
|
} catch {
|
|
79386
80469
|
transcripts = [];
|
|
79387
80470
|
}
|
|
79388
|
-
for (const transcript of transcripts) {
|
|
80471
|
+
for (const transcript of [...transcripts].sort((left, right) => right.mtimeMs - left.mtimeMs)) {
|
|
79389
80472
|
const primary = processForTranscript(transcript, processes);
|
|
79390
80473
|
const transcriptPath = transcript.transcriptPath;
|
|
79391
80474
|
const sessionKey4 = sessionRegistryKey(transcript);
|
|
79392
80475
|
seenSessionKeys.add(sessionKey4);
|
|
80476
|
+
const sourceSessionId = transcript.sessionId?.trim();
|
|
80477
|
+
if (sourceSessionId) {
|
|
80478
|
+
seenObservedLifecycleKeys.add(observedSessionLifecycleKey(source.name, sourceSessionId));
|
|
80479
|
+
}
|
|
79393
80480
|
const prior = knownTranscripts.get(sessionKey4);
|
|
79394
80481
|
if (transcript.source !== "cursor" && prior && prior.transcriptPath !== transcriptPath) {
|
|
79395
80482
|
const issueKey = `${sessionKey4}\x00${prior.transcriptPath}\x00${transcriptPath}`;
|
|
@@ -79417,10 +80504,25 @@ async function refreshDiscovery(scope = "shallow", options = { pruneMissing: sco
|
|
|
79417
80504
|
offset: 0,
|
|
79418
80505
|
lineCounter: 0,
|
|
79419
80506
|
carry: "",
|
|
80507
|
+
decoder: new StringDecoder("utf8"),
|
|
79420
80508
|
emittedEventIds: new Set,
|
|
79421
|
-
state: {}
|
|
80509
|
+
state: {},
|
|
80510
|
+
lastPumpAt: 0,
|
|
80511
|
+
lastObservedChangeAt: Math.max(transcript.lastEventAt ?? 0, transcript.mtimeMs),
|
|
80512
|
+
lastKnownSize: transcript.size,
|
|
80513
|
+
lastKnownMtimeMs: transcript.mtimeMs,
|
|
80514
|
+
missingAuthoritativePasses: 0,
|
|
80515
|
+
staleObservations: 0,
|
|
80516
|
+
lifecycleNotification: "none",
|
|
80517
|
+
internalObserved: false,
|
|
80518
|
+
lastInternalEvent: null,
|
|
80519
|
+
pumpInFlight: null
|
|
79422
80520
|
};
|
|
79423
|
-
|
|
80521
|
+
const reconcileInternal = remainingInternalReconciliations > 0;
|
|
80522
|
+
if (reconcileInternal)
|
|
80523
|
+
remainingInternalReconciliations--;
|
|
80524
|
+
await seedTail(watcher, { reconcileInternal });
|
|
80525
|
+
applyPersistedObservedSeedToWatcher(watcher);
|
|
79424
80526
|
watchers.set(sessionKey4, watcher);
|
|
79425
80527
|
continue;
|
|
79426
80528
|
}
|
|
@@ -79428,21 +80530,33 @@ async function refreshDiscovery(scope = "shallow", options = { pruneMissing: sco
|
|
|
79428
80530
|
watcher.transcriptPath = transcriptPath;
|
|
79429
80531
|
watcher.lineCounter = 0;
|
|
79430
80532
|
watcher.carry = "";
|
|
80533
|
+
watcher.decoder = new StringDecoder("utf8");
|
|
79431
80534
|
watcher.emittedEventIds = new Set;
|
|
79432
80535
|
watcher.state = {};
|
|
79433
|
-
|
|
80536
|
+
watcher.internalObserved = false;
|
|
80537
|
+
watcher.lastInternalEvent = null;
|
|
80538
|
+
const reconcileInternal = remainingInternalReconciliations > 0;
|
|
80539
|
+
if (reconcileInternal)
|
|
80540
|
+
remainingInternalReconciliations--;
|
|
80541
|
+
await seedTail(watcher, { reconcileInternal });
|
|
80542
|
+
}
|
|
80543
|
+
applyPersistedObservedSeedToWatcher(watcher);
|
|
80544
|
+
if (transcript.mtimeMs > watcher.transcript.mtimeMs) {
|
|
80545
|
+
watcher.lastObservedChangeAt = Date.now();
|
|
80546
|
+
watcher.staleObservations = 0;
|
|
80547
|
+
watcher.lifecycleNotification = "none";
|
|
80548
|
+
if (watcher.source.parseFile)
|
|
80549
|
+
watcher.offset = 0;
|
|
79434
80550
|
}
|
|
79435
80551
|
watcher.process = primary;
|
|
79436
80552
|
watcher.transcript = transcript;
|
|
80553
|
+
watcher.missingAuthoritativePasses = 0;
|
|
79437
80554
|
}
|
|
79438
80555
|
}
|
|
79439
80556
|
if (options.pruneMissing) {
|
|
79440
|
-
|
|
79441
|
-
|
|
79442
|
-
|
|
79443
|
-
knownTranscripts.delete(sessionKey4);
|
|
79444
|
-
}
|
|
79445
|
-
}
|
|
80557
|
+
const observedAt = Date.now();
|
|
80558
|
+
reconcileMissingWatchers(seenSessionKeys, successfullyScannedSources, observedAt);
|
|
80559
|
+
reconcilePersistedObservedSessions(seenObservedLifecycleKeys, successfullyScannedSources, observedAt);
|
|
79446
80560
|
}
|
|
79447
80561
|
const allTranscripts = [...knownTranscripts.values()].sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
79448
80562
|
let scoutManaged = 0;
|
|
@@ -79486,7 +80600,7 @@ function scheduleDiscovery(scope, options = { pruneMissing: scope !== "hot" }) {
|
|
|
79486
80600
|
function ensureLoopRunning() {
|
|
79487
80601
|
if (!pollTimer) {
|
|
79488
80602
|
pollTimer = setInterval(() => {
|
|
79489
|
-
|
|
80603
|
+
pumpWatchersForCurrentDemand();
|
|
79490
80604
|
}, TAIL_POLL_INTERVAL_MS);
|
|
79491
80605
|
}
|
|
79492
80606
|
if (!hotDiscoveryTimer) {
|
|
@@ -79506,7 +80620,7 @@ function ensureLoopRunning() {
|
|
|
79506
80620
|
}
|
|
79507
80621
|
}
|
|
79508
80622
|
function stopLoopIfIdle() {
|
|
79509
|
-
if (subscribers.size > 0)
|
|
80623
|
+
if (subscribers.size > 0 || internalSubscribers.size > 0)
|
|
79510
80624
|
return;
|
|
79511
80625
|
if (pollTimer) {
|
|
79512
80626
|
clearInterval(pollTimer);
|
|
@@ -79525,6 +80639,7 @@ function stopLoopIfIdle() {
|
|
|
79525
80639
|
deepDiscoveryTimer = null;
|
|
79526
80640
|
}
|
|
79527
80641
|
watchers.clear();
|
|
80642
|
+
persistedObservedSessions.clear();
|
|
79528
80643
|
}
|
|
79529
80644
|
function normalizeTailDiscoveryOptions(input = false) {
|
|
79530
80645
|
if (typeof input === "boolean") {
|
|
@@ -79550,18 +80665,19 @@ async function refreshTailDiscovery(scope = "shallow") {
|
|
|
79550
80665
|
}
|
|
79551
80666
|
function subscribeTail(handler) {
|
|
79552
80667
|
subscribers.add(handler);
|
|
80668
|
+
startTailLoopForSubscriber();
|
|
80669
|
+
return () => {
|
|
80670
|
+
subscribers.delete(handler);
|
|
80671
|
+
stopLoopIfIdle();
|
|
80672
|
+
};
|
|
80673
|
+
}
|
|
80674
|
+
function startTailLoopForSubscriber() {
|
|
79553
80675
|
ensureLoopRunning();
|
|
79554
80676
|
if (watchers.size === 0) {
|
|
79555
|
-
runDiscovery("shallow", { pruneMissing: true }).then(() =>
|
|
80677
|
+
runDiscovery("shallow", { pruneMissing: true }).then(() => pumpWatchersForCurrentDemand()).catch(() => {});
|
|
79556
80678
|
} else {
|
|
79557
|
-
|
|
80679
|
+
pumpWatchersForCurrentDemand();
|
|
79558
80680
|
}
|
|
79559
|
-
return () => {
|
|
79560
|
-
subscribers.delete(handler);
|
|
79561
|
-
if (subscribers.size === 0) {
|
|
79562
|
-
stopLoopIfIdle();
|
|
79563
|
-
}
|
|
79564
|
-
};
|
|
79565
80681
|
}
|
|
79566
80682
|
function snapshotRecentEvents(limit = 500) {
|
|
79567
80683
|
return aggregateBuffer.slice(-limit);
|
|
@@ -79755,7 +80871,7 @@ async function readRecentTranscriptEvents(limit = 50, options) {
|
|
|
79755
80871
|
const lineLimit = options?.perTranscriptLineLimit ?? RECENT_TRANSCRIPT_LINES_PER_FILE;
|
|
79756
80872
|
const kinds = options?.kinds?.length ? new Set(options.kinds) : null;
|
|
79757
80873
|
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);
|
|
80874
|
+
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
80875
|
for (const watcher of activeWatchers) {
|
|
79760
80876
|
seenTranscriptPaths.add(watcher.transcriptPath);
|
|
79761
80877
|
await appendWatcherTranscriptEvents(events2, seenEvents, watcher, {
|
|
@@ -79765,7 +80881,7 @@ async function readRecentTranscriptEvents(limit = 50, options) {
|
|
|
79765
80881
|
});
|
|
79766
80882
|
}
|
|
79767
80883
|
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);
|
|
80884
|
+
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
80885
|
for (const transcript of discoveryTranscripts) {
|
|
79770
80886
|
const parsed = await parseTranscriptSessionEvents(transcript, options.discovery.processes, lineLimit, {
|
|
79771
80887
|
kinds,
|
|
@@ -79778,7 +80894,7 @@ async function readRecentTranscriptEvents(limit = 50, options) {
|
|
|
79778
80894
|
seenTranscriptPaths.add(transcript.transcriptPath);
|
|
79779
80895
|
}
|
|
79780
80896
|
}
|
|
79781
|
-
return events2.filter((event) => !kinds || kinds.has(event.kind)).sort((left, right) => right.ts - left.ts).slice(0, limit);
|
|
80897
|
+
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
80898
|
}
|
|
79783
80899
|
function normalizeTailSessionRef(value) {
|
|
79784
80900
|
const trimmed = value?.trim();
|
|
@@ -80105,7 +81221,7 @@ function buildObserveDataFromTail(transcript, events2, current) {
|
|
|
80105
81221
|
var HISTORY_SNAPSHOT_CACHE_LIMIT = 128;
|
|
80106
81222
|
var historySnapshotCache = new Map;
|
|
80107
81223
|
var OBSERVE_SUMMARY_TAIL_SIZE = 8;
|
|
80108
|
-
var SESSION_REF_LOOKUP_TTL_MS =
|
|
81224
|
+
var SESSION_REF_LOOKUP_TTL_MS = 60000;
|
|
80109
81225
|
var sessionRefLookupCache = null;
|
|
80110
81226
|
var AMBIGUOUS_TAIL_SESSION_REF = Symbol("ambiguous-tail-session-ref");
|
|
80111
81227
|
function normalizedComparableString2(value) {
|
|
@@ -80194,6 +81310,23 @@ function tailSessionRefTranscripts(discovery, normalizedRef, harness2) {
|
|
|
80194
81310
|
return refs.includes(normalizedRef);
|
|
80195
81311
|
});
|
|
80196
81312
|
}
|
|
81313
|
+
function bestTailSessionRefLookupEntry(transcripts, normalizedRef) {
|
|
81314
|
+
const matches = [];
|
|
81315
|
+
for (const transcript of transcripts) {
|
|
81316
|
+
const adapterType = adapterTypeFromTailSource(transcript.source);
|
|
81317
|
+
if (!adapterType || !supportsHistorySessionSnapshotForPath(transcript.transcriptPath, adapterType)) {
|
|
81318
|
+
continue;
|
|
81319
|
+
}
|
|
81320
|
+
matches.push({
|
|
81321
|
+
refId: normalizedRef,
|
|
81322
|
+
historyPath: transcript.transcriptPath,
|
|
81323
|
+
adapterType,
|
|
81324
|
+
mtimeMs: transcript.mtimeMs,
|
|
81325
|
+
size: transcript.size
|
|
81326
|
+
});
|
|
81327
|
+
}
|
|
81328
|
+
return matches.sort((left, right) => right.mtimeMs - left.mtimeMs)[0] ?? null;
|
|
81329
|
+
}
|
|
80197
81330
|
function hasAmbiguousTailHarness(transcripts) {
|
|
80198
81331
|
const sources2 = new Set(transcripts.map((transcript) => canonicalSessionHarness(transcript.source) ?? transcript.source.trim().toLowerCase()));
|
|
80199
81332
|
return sources2.size > 1;
|
|
@@ -80270,23 +81403,7 @@ async function findTailSessionRefLookupEntry(normalizedRef, harness2 = null) {
|
|
|
80270
81403
|
const transcripts = tailSessionRefTranscripts(discovery, normalizedRef, harness2);
|
|
80271
81404
|
if (!harness2 && hasAmbiguousTailHarness(transcripts))
|
|
80272
81405
|
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;
|
|
81406
|
+
return bestTailSessionRefLookupEntry(transcripts, normalizedRef);
|
|
80290
81407
|
}
|
|
80291
81408
|
function historyAdapterAlias(value) {
|
|
80292
81409
|
const normalized = value?.trim().toLowerCase();
|
|
@@ -81707,11 +82824,12 @@ async function loadSessionRefObservePayload(refId) {
|
|
|
81707
82824
|
return null;
|
|
81708
82825
|
}
|
|
81709
82826
|
let [discovery, brokerContext] = await Promise.all([
|
|
81710
|
-
|
|
82827
|
+
readScoutBrokerTailDiscovery().catch(() => null),
|
|
81711
82828
|
loadScoutBrokerContext().catch(() => null)
|
|
81712
82829
|
]);
|
|
81713
82830
|
let matchingTranscripts = discovery ? tailSessionRefTranscripts(discovery, normalizedRef, requestedHarness) : [];
|
|
81714
|
-
const
|
|
82831
|
+
const discoveredHistoryEntry = bestTailSessionRefLookupEntry(matchingTranscripts, normalizedRef);
|
|
82832
|
+
const cachedHistoryEntry = !discoveredHistoryEntry && matchingTranscripts.length === 0 && (!requestedHarness || requestedHarness === "claude") ? sessionRefLookup().get(normalizedRef) ?? null : null;
|
|
81715
82833
|
const matchingAgents = queryAgents(200).filter((agent) => normalizeSessionRefId(agent.harnessSessionId) === normalizedRef && sessionHarnessMatches(requestedHarness, agent.harness));
|
|
81716
82834
|
const matchingAgentOwners = new Set(matchingAgents.map((agent) => agent.id));
|
|
81717
82835
|
if (matchingAgentOwners.size > 1)
|
|
@@ -81778,7 +82896,7 @@ async function loadSessionRefObservePayload(refId) {
|
|
|
81778
82896
|
}
|
|
81779
82897
|
if (!requestedHarness && hasAmbiguousTailHarness(matchingTranscripts))
|
|
81780
82898
|
return null;
|
|
81781
|
-
const tailHistoryEntry = await findTailSessionRefLookupEntry(normalizedRef, requestedHarness);
|
|
82899
|
+
const tailHistoryEntry = discoveredHistoryEntry ?? await findTailSessionRefLookupEntry(normalizedRef, requestedHarness);
|
|
81782
82900
|
if (tailHistoryEntry === AMBIGUOUS_TAIL_SESSION_REF)
|
|
81783
82901
|
return null;
|
|
81784
82902
|
const historyEntry = tailHistoryEntry ?? (requestedHarness === "claude" || !requestedHarness && (!discovery || matchingTranscripts.length === 0) ? cachedHistoryEntry : null);
|
|
@@ -86450,6 +87568,7 @@ var MAX_EVENTS_PER_SESSION = 200;
|
|
|
86450
87568
|
var sessions4 = new Map;
|
|
86451
87569
|
var hosts = new Map;
|
|
86452
87570
|
var sessionSubscribers = new Map;
|
|
87571
|
+
var hostCommandWaiters = new Map;
|
|
86453
87572
|
var nextHostPollId = 1;
|
|
86454
87573
|
var DEFAULT_VOICE_SETTINGS = {
|
|
86455
87574
|
preference: "auto",
|
|
@@ -86464,6 +87583,9 @@ function registerScoutVoiceHost(input) {
|
|
|
86464
87583
|
const now = Date.now();
|
|
86465
87584
|
const previous = hosts.get(hostId);
|
|
86466
87585
|
const instanceId = input.instanceId?.trim() || null;
|
|
87586
|
+
if (previous && previous.instanceId !== instanceId) {
|
|
87587
|
+
finishScoutVoiceHostCommandWaiter(hostId, null);
|
|
87588
|
+
}
|
|
86467
87589
|
const settings = mergeVoiceSettings(previous?.settings ?? DEFAULT_VOICE_SETTINGS, input.settings);
|
|
86468
87590
|
hosts.set(hostId, {
|
|
86469
87591
|
hostId,
|
|
@@ -86545,6 +87667,7 @@ function awaitScoutVoiceHostCommand(hostId, timeoutMs = 25000, instanceId, signa
|
|
|
86545
87667
|
if (host.instanceId !== normalizedInstanceId) {
|
|
86546
87668
|
return Promise.resolve({ command: null });
|
|
86547
87669
|
}
|
|
87670
|
+
finishScoutVoiceHostCommandWaiter(normalizedHostId, null);
|
|
86548
87671
|
const pollId = nextHostPollId++;
|
|
86549
87672
|
host.activePollId = pollId;
|
|
86550
87673
|
touchScoutVoiceHost(normalizedHostId);
|
|
@@ -86559,40 +87682,37 @@ function awaitScoutVoiceHostCommand(hostId, timeoutMs = 25000, instanceId, signa
|
|
|
86559
87682
|
return Promise.resolve({ command: null });
|
|
86560
87683
|
}
|
|
86561
87684
|
return new Promise((resolve23) => {
|
|
86562
|
-
const startedAt = Date.now();
|
|
86563
87685
|
let settled = false;
|
|
87686
|
+
let timeout = null;
|
|
86564
87687
|
const finish = (command) => {
|
|
86565
87688
|
if (settled)
|
|
86566
87689
|
return;
|
|
86567
87690
|
settled = true;
|
|
86568
|
-
|
|
87691
|
+
if (timeout)
|
|
87692
|
+
clearTimeout(timeout);
|
|
86569
87693
|
signal?.removeEventListener("abort", abort);
|
|
87694
|
+
const waiter = hostCommandWaiters.get(normalizedHostId);
|
|
87695
|
+
if (waiter?.pollId === pollId)
|
|
87696
|
+
hostCommandWaiters.delete(normalizedHostId);
|
|
86570
87697
|
const current = hosts.get(normalizedHostId);
|
|
86571
87698
|
if (current?.activePollId === pollId)
|
|
86572
87699
|
current.activePollId = null;
|
|
86573
87700
|
resolve23({ command });
|
|
86574
87701
|
};
|
|
86575
87702
|
const abort = () => finish(null);
|
|
86576
|
-
|
|
87703
|
+
hostCommandWaiters.set(normalizedHostId, {
|
|
87704
|
+
pollId,
|
|
87705
|
+
instanceId: normalizedInstanceId,
|
|
87706
|
+
finish
|
|
87707
|
+
});
|
|
87708
|
+
timeout = setTimeout(() => {
|
|
86577
87709
|
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;
|
|
87710
|
+
if (current && current.instanceId === normalizedInstanceId && current.activePollId === pollId) {
|
|
87711
|
+
current.lastSeenAt = Date.now();
|
|
86591
87712
|
}
|
|
86592
|
-
|
|
86593
|
-
|
|
86594
|
-
|
|
86595
|
-
}, 100);
|
|
87713
|
+
finish(null);
|
|
87714
|
+
}, timeoutMs);
|
|
87715
|
+
timeout.unref?.();
|
|
86596
87716
|
signal?.addEventListener("abort", abort, { once: true });
|
|
86597
87717
|
if (signal?.aborted)
|
|
86598
87718
|
abort();
|
|
@@ -86813,6 +87933,22 @@ function queueHostCommand(hostId, command) {
|
|
|
86813
87933
|
}
|
|
86814
87934
|
host.pendingCommands.push(command);
|
|
86815
87935
|
host.lastSeenAt = Date.now();
|
|
87936
|
+
deliverPendingScoutVoiceHostCommand(host);
|
|
87937
|
+
}
|
|
87938
|
+
function finishScoutVoiceHostCommandWaiter(hostId, command) {
|
|
87939
|
+
hostCommandWaiters.get(hostId)?.finish(command);
|
|
87940
|
+
}
|
|
87941
|
+
function deliverPendingScoutVoiceHostCommand(host) {
|
|
87942
|
+
const waiter = hostCommandWaiters.get(host.hostId);
|
|
87943
|
+
if (!waiter)
|
|
87944
|
+
return;
|
|
87945
|
+
if (waiter.instanceId !== host.instanceId || waiter.pollId !== host.activePollId) {
|
|
87946
|
+
waiter.finish(null);
|
|
87947
|
+
return;
|
|
87948
|
+
}
|
|
87949
|
+
const command = host.pendingCommands.shift();
|
|
87950
|
+
if (command)
|
|
87951
|
+
waiter.finish(command);
|
|
86816
87952
|
}
|
|
86817
87953
|
function dispatchSessionCommand(session3, command) {
|
|
86818
87954
|
const hostId = session3.assignedHostId ?? pickLiveVoiceHost()?.hostId;
|
|
@@ -87226,6 +88362,127 @@ function defaultVoiceForModel(providers2, modelId2) {
|
|
|
87226
88362
|
return firstNonEmptyString7(provider?.env.VOX_MLX_AUDIO_TTS_DEFAULT_VOICE);
|
|
87227
88363
|
}
|
|
87228
88364
|
|
|
88365
|
+
// packages/web/server/nvidia-speech.ts
|
|
88366
|
+
var NVIDIA_MAGPIE_SPEECH_URL = "https://877104f7-e885-42b9-8de8-f6e4c6303969.invocation.api.nvcf.nvidia.com/v1/audio/synthesize";
|
|
88367
|
+
var NVIDIA_MAGPIE_VOICES_URL = "https://877104f7-e885-42b9-8de8-f6e4c6303969.invocation.api.nvcf.nvidia.com/v1/audio/list_voices";
|
|
88368
|
+
var NVIDIA_MAGPIE_MODEL = "magpie-tts-multilingual";
|
|
88369
|
+
var NVIDIA_MAGPIE_DEFAULT_VOICE = "Magpie-Multilingual.EN-US.Aria";
|
|
88370
|
+
var NVIDIA_MAGPIE_TIMEOUT_MS = 60000;
|
|
88371
|
+
var NVIDIA_MAGPIE_MAX_CHARACTERS = 2000;
|
|
88372
|
+
function resolveNvidiaApiKey(env = process.env) {
|
|
88373
|
+
return firstNonEmptyString8(env.NV_API_KEY, env.NVIDIA_API_KEY);
|
|
88374
|
+
}
|
|
88375
|
+
function isNvidiaMagpieSpeechModel(modelId2) {
|
|
88376
|
+
return modelId2?.trim() === NVIDIA_MAGPIE_MODEL;
|
|
88377
|
+
}
|
|
88378
|
+
async function listNvidiaMagpieVoices(input) {
|
|
88379
|
+
const timeout = AbortSignal.timeout(NVIDIA_MAGPIE_TIMEOUT_MS);
|
|
88380
|
+
const signal = input.signal ? AbortSignal.any([input.signal, timeout]) : timeout;
|
|
88381
|
+
const response = await fetch(input.endpoint ?? NVIDIA_MAGPIE_VOICES_URL, {
|
|
88382
|
+
method: "GET",
|
|
88383
|
+
headers: { authorization: `Bearer ${input.apiKey}` },
|
|
88384
|
+
signal
|
|
88385
|
+
});
|
|
88386
|
+
if (!response.ok) {
|
|
88387
|
+
const detail = await response.text().catch(() => "");
|
|
88388
|
+
throw new Error(`NVIDIA Magpie voice discovery failed (${response.status})${detail ? `: ${detail.slice(0, 200)}` : ""}`);
|
|
88389
|
+
}
|
|
88390
|
+
const voices = parseNvidiaMagpieVoices(await response.json());
|
|
88391
|
+
if (voices.length === 0) {
|
|
88392
|
+
throw new Error("NVIDIA Magpie voice discovery returned no voices.");
|
|
88393
|
+
}
|
|
88394
|
+
return voices;
|
|
88395
|
+
}
|
|
88396
|
+
async function synthesizeNvidiaMagpieSpeech(input) {
|
|
88397
|
+
const text4 = Array.from(input.text).slice(0, NVIDIA_MAGPIE_MAX_CHARACTERS).join("");
|
|
88398
|
+
const voiceId = input.voiceId?.trim() || NVIDIA_MAGPIE_DEFAULT_VOICE;
|
|
88399
|
+
const language = magpieLanguageForVoice(voiceId);
|
|
88400
|
+
const form = new FormData;
|
|
88401
|
+
form.set("text", text4);
|
|
88402
|
+
form.set("language", language);
|
|
88403
|
+
form.set("voice", voiceId);
|
|
88404
|
+
form.set("encoding", "LINEAR_PCM");
|
|
88405
|
+
form.set("sample_rate_hz", "44100");
|
|
88406
|
+
const timeout = AbortSignal.timeout(NVIDIA_MAGPIE_TIMEOUT_MS);
|
|
88407
|
+
const signal = input.signal ? AbortSignal.any([input.signal, timeout]) : timeout;
|
|
88408
|
+
const response = await fetch(input.endpoint ?? NVIDIA_MAGPIE_SPEECH_URL, {
|
|
88409
|
+
method: "POST",
|
|
88410
|
+
headers: { authorization: `Bearer ${input.apiKey}` },
|
|
88411
|
+
body: form,
|
|
88412
|
+
signal
|
|
88413
|
+
});
|
|
88414
|
+
if (!response.ok) {
|
|
88415
|
+
const detail = await response.text().catch(() => "");
|
|
88416
|
+
throw new Error(`NVIDIA Magpie speech failed (${response.status})${detail ? `: ${detail.slice(0, 200)}` : ""}`);
|
|
88417
|
+
}
|
|
88418
|
+
const audio = new Uint8Array(await response.arrayBuffer());
|
|
88419
|
+
if (audio.byteLength === 0) {
|
|
88420
|
+
throw new Error("NVIDIA Magpie returned no audio.");
|
|
88421
|
+
}
|
|
88422
|
+
const responseContentType = response.headers.get("content-type")?.split(";")[0];
|
|
88423
|
+
return {
|
|
88424
|
+
contentType: responseContentType?.startsWith("audio/") ? responseContentType : "audio/wav",
|
|
88425
|
+
audioBase64: Buffer.from(audio).toString("base64"),
|
|
88426
|
+
modelId: NVIDIA_MAGPIE_MODEL,
|
|
88427
|
+
voiceId,
|
|
88428
|
+
audioBytes: audio.byteLength
|
|
88429
|
+
};
|
|
88430
|
+
}
|
|
88431
|
+
function magpieLanguageForVoice(voiceId) {
|
|
88432
|
+
const locale = magpieLocaleSegment(voiceId);
|
|
88433
|
+
if (!locale)
|
|
88434
|
+
return "en-US";
|
|
88435
|
+
const [language, region] = locale.split("-");
|
|
88436
|
+
return `${language.toLowerCase()}-${region.toUpperCase()}`;
|
|
88437
|
+
}
|
|
88438
|
+
function parseNvidiaMagpieVoices(value) {
|
|
88439
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
88440
|
+
return [];
|
|
88441
|
+
const ids = new Set;
|
|
88442
|
+
for (const group of Object.values(value)) {
|
|
88443
|
+
if (!group || typeof group !== "object" || Array.isArray(group))
|
|
88444
|
+
continue;
|
|
88445
|
+
const voices = group.voices;
|
|
88446
|
+
if (!Array.isArray(voices))
|
|
88447
|
+
continue;
|
|
88448
|
+
for (const voice of voices) {
|
|
88449
|
+
if (typeof voice !== "string")
|
|
88450
|
+
continue;
|
|
88451
|
+
const id = voice.trim();
|
|
88452
|
+
if (id)
|
|
88453
|
+
ids.add(id);
|
|
88454
|
+
}
|
|
88455
|
+
}
|
|
88456
|
+
return Array.from(ids, voiceDetails).sort((left, right) => left.language.localeCompare(right.language) || left.name.localeCompare(right.name) || left.id.localeCompare(right.id));
|
|
88457
|
+
}
|
|
88458
|
+
function voiceDetails(id) {
|
|
88459
|
+
const parts = id.split(".");
|
|
88460
|
+
const language = magpieLanguageForVoice(id);
|
|
88461
|
+
const localeIndex = parts.findIndex(isLocaleSegment);
|
|
88462
|
+
const nameParts = localeIndex >= 0 ? parts.slice(localeIndex + 1) : [];
|
|
88463
|
+
const name2 = nameParts.length > 0 ? nameParts.join(" \xB7 ") : parts.at(-1) || id;
|
|
88464
|
+
return {
|
|
88465
|
+
id,
|
|
88466
|
+
name: name2,
|
|
88467
|
+
language,
|
|
88468
|
+
isDefault: id === NVIDIA_MAGPIE_DEFAULT_VOICE
|
|
88469
|
+
};
|
|
88470
|
+
}
|
|
88471
|
+
function magpieLocaleSegment(voiceId) {
|
|
88472
|
+
return voiceId.split(".").find(isLocaleSegment);
|
|
88473
|
+
}
|
|
88474
|
+
function isLocaleSegment(value) {
|
|
88475
|
+
return /^[a-z]{2,3}-[a-z]{2}$/i.test(value);
|
|
88476
|
+
}
|
|
88477
|
+
function firstNonEmptyString8(...values) {
|
|
88478
|
+
for (const value of values) {
|
|
88479
|
+
const trimmed = value?.trim();
|
|
88480
|
+
if (trimmed)
|
|
88481
|
+
return trimmed;
|
|
88482
|
+
}
|
|
88483
|
+
return;
|
|
88484
|
+
}
|
|
88485
|
+
|
|
87229
88486
|
// packages/web/server/scout-voice.ts
|
|
87230
88487
|
var SCOUT_VOICE_CLIENT_ID = "openscout-web";
|
|
87231
88488
|
var DEFAULT_SCOUT_VOICE_ASR_URL = "http://127.0.0.1:43115";
|
|
@@ -87268,14 +88525,16 @@ async function getScoutSpeechCatalog(input = {}) {
|
|
|
87268
88525
|
let models = [];
|
|
87269
88526
|
let voices = [];
|
|
87270
88527
|
let source = "fallback";
|
|
87271
|
-
|
|
87272
|
-
|
|
87273
|
-
|
|
87274
|
-
|
|
87275
|
-
|
|
87276
|
-
|
|
87277
|
-
|
|
87278
|
-
|
|
88528
|
+
if (requestedModelId !== NVIDIA_MAGPIE_MODEL) {
|
|
88529
|
+
try {
|
|
88530
|
+
[models, voices] = await Promise.all([
|
|
88531
|
+
listVoxSpeechModels(input.signal),
|
|
88532
|
+
listVoxSpeechVoices(requestedModelId, input.signal)
|
|
88533
|
+
]);
|
|
88534
|
+
if (models.length > 0)
|
|
88535
|
+
source = "vox";
|
|
88536
|
+
} catch {}
|
|
88537
|
+
}
|
|
87279
88538
|
const fallback = fallbackScoutSpeechCatalog(requestedModelId, defaults);
|
|
87280
88539
|
for (const model2 of fallback.models) {
|
|
87281
88540
|
if (!models.some((candidate) => candidate.id === model2.id)) {
|
|
@@ -87289,6 +88548,25 @@ async function getScoutSpeechCatalog(input = {}) {
|
|
|
87289
88548
|
models = models.map((model2) => model2.provider === "openai" ? { ...model2, available: true } : model2);
|
|
87290
88549
|
voices = voices.map((voice) => voice.provider === "openai" ? { ...voice, available: true } : voice);
|
|
87291
88550
|
}
|
|
88551
|
+
if (input.directNvidiaAvailable || input.directNvidiaApiKey) {
|
|
88552
|
+
models = models.map((model2) => model2.provider === "nvidia" ? { ...model2, available: true } : model2);
|
|
88553
|
+
voices = voices.map((voice) => voice.provider === "nvidia" ? { ...voice, available: true } : voice);
|
|
88554
|
+
}
|
|
88555
|
+
if (input.directNvidiaApiKey && requestedModelId === NVIDIA_MAGPIE_MODEL) {
|
|
88556
|
+
try {
|
|
88557
|
+
const discovered = await listNvidiaMagpieVoices({
|
|
88558
|
+
apiKey: input.directNvidiaApiKey,
|
|
88559
|
+
signal: input.signal
|
|
88560
|
+
});
|
|
88561
|
+
voices = discovered.map((voice) => ({
|
|
88562
|
+
...voice,
|
|
88563
|
+
provider: "nvidia",
|
|
88564
|
+
modelId: NVIDIA_MAGPIE_MODEL,
|
|
88565
|
+
available: true
|
|
88566
|
+
}));
|
|
88567
|
+
source = "nvidia-developer-inference";
|
|
88568
|
+
} catch {}
|
|
88569
|
+
}
|
|
87292
88570
|
return {
|
|
87293
88571
|
defaultModelId: defaults.modelId,
|
|
87294
88572
|
...defaults.voiceId ? { defaultVoiceId: defaults.voiceId } : {},
|
|
@@ -87300,7 +88578,8 @@ async function getScoutSpeechCatalog(input = {}) {
|
|
|
87300
88578
|
function fallbackScoutSpeechCatalog(modelId2, defaults = resolveScoutSpeechDefaults()) {
|
|
87301
88579
|
const models = [
|
|
87302
88580
|
{ 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 }
|
|
88581
|
+
{ id: "eleven_multilingual_v2", name: "Eleven Multilingual v2", provider: "elevenlabs", available: true },
|
|
88582
|
+
{ id: NVIDIA_MAGPIE_MODEL, name: "Magpie TTS Multilingual", provider: "nvidia", available: true }
|
|
87304
88583
|
];
|
|
87305
88584
|
const openAIVoices = ["alloy", "ash", "ballad", "cedar", "coral", "echo", "fable", "marin", "nova", "onyx", "sage", "shimmer", "verse"].map((id) => ({
|
|
87306
88585
|
id,
|
|
@@ -87318,11 +88597,20 @@ function fallbackScoutSpeechCatalog(modelId2, defaults = resolveScoutSpeechDefau
|
|
|
87318
88597
|
available: true,
|
|
87319
88598
|
isDefault: true
|
|
87320
88599
|
}];
|
|
88600
|
+
const nvidiaVoices = [{
|
|
88601
|
+
id: NVIDIA_MAGPIE_DEFAULT_VOICE,
|
|
88602
|
+
name: "Aria",
|
|
88603
|
+
language: "en-US",
|
|
88604
|
+
provider: "nvidia",
|
|
88605
|
+
modelId: NVIDIA_MAGPIE_MODEL,
|
|
88606
|
+
available: true,
|
|
88607
|
+
isDefault: true
|
|
88608
|
+
}];
|
|
87321
88609
|
return {
|
|
87322
88610
|
defaultModelId: defaults.modelId,
|
|
87323
88611
|
...defaults.voiceId ? { defaultVoiceId: defaults.voiceId } : {},
|
|
87324
88612
|
models,
|
|
87325
|
-
voices: modelId2 === "eleven_multilingual_v2" ? elevenLabsVoices : openAIVoices,
|
|
88613
|
+
voices: modelId2 === "eleven_multilingual_v2" ? elevenLabsVoices : modelId2 === NVIDIA_MAGPIE_MODEL ? nvidiaVoices : openAIVoices,
|
|
87326
88614
|
source: "fallback"
|
|
87327
88615
|
};
|
|
87328
88616
|
}
|
|
@@ -87337,9 +88625,9 @@ function createScoutVoiceAsrClient(probeTimeout) {
|
|
|
87337
88625
|
});
|
|
87338
88626
|
}
|
|
87339
88627
|
function resolveScoutVoiceAsrUrl(env = process.env) {
|
|
87340
|
-
return
|
|
88628
|
+
return firstNonEmptyString9(env.OPENSCOUT_VOICE_ASR_URL, env.OPENSCOUT_VOICE_BRIDGE_URL, env.VOX_COMPANION_URL) ?? DEFAULT_SCOUT_VOICE_ASR_URL;
|
|
87341
88629
|
}
|
|
87342
|
-
function
|
|
88630
|
+
function firstNonEmptyString9(...values) {
|
|
87343
88631
|
for (const value of values) {
|
|
87344
88632
|
const trimmed = value?.trim();
|
|
87345
88633
|
if (trimmed)
|
|
@@ -87528,9 +88816,9 @@ class ScoutRealtimeVoiceAdmission {
|
|
|
87528
88816
|
}
|
|
87529
88817
|
function resolveScoutRealtimeVoiceConfig(env = process.env) {
|
|
87530
88818
|
return {
|
|
87531
|
-
model:
|
|
87532
|
-
voice:
|
|
87533
|
-
instructions:
|
|
88819
|
+
model: firstNonEmptyString10(env.OPENSCOUT_REALTIME_MODEL) ?? DEFAULT_REALTIME_MODEL,
|
|
88820
|
+
voice: firstNonEmptyString10(env.OPENSCOUT_REALTIME_VOICE) ?? DEFAULT_REALTIME_VOICE,
|
|
88821
|
+
instructions: firstNonEmptyString10(env.OPENSCOUT_REALTIME_INSTRUCTIONS) ?? SCOUT_REALTIME_INSTRUCTIONS
|
|
87534
88822
|
};
|
|
87535
88823
|
}
|
|
87536
88824
|
function scoutRealtimeVoiceEnvironmentOverride(env = process.env) {
|
|
@@ -87668,7 +88956,7 @@ function positiveInteger3(value, fallback) {
|
|
|
87668
88956
|
function secondsUntil(timestamp, now) {
|
|
87669
88957
|
return Math.max(1, Math.ceil((timestamp - now) / 1000));
|
|
87670
88958
|
}
|
|
87671
|
-
function
|
|
88959
|
+
function firstNonEmptyString10(value) {
|
|
87672
88960
|
const trimmed = value?.trim();
|
|
87673
88961
|
return trimmed || undefined;
|
|
87674
88962
|
}
|
|
@@ -88035,10 +89323,13 @@ function mountScoutVoiceRoutes(app, deps = {}) {
|
|
|
88035
89323
|
const directOpenAIAvailable = Boolean(await deps.resolveOpenAIApiKey?.().catch(() => {
|
|
88036
89324
|
return;
|
|
88037
89325
|
}) ?? process.env.OPENAI_API_KEY?.trim());
|
|
89326
|
+
const directNvidiaApiKey = resolveNvidiaApiKey();
|
|
88038
89327
|
return c.json(await getScoutSpeechCatalog({
|
|
88039
89328
|
modelId: c.req.query("modelId"),
|
|
88040
89329
|
signal: c.req.raw.signal,
|
|
88041
|
-
directOpenAIAvailable
|
|
89330
|
+
directOpenAIAvailable,
|
|
89331
|
+
directNvidiaAvailable: Boolean(directNvidiaApiKey),
|
|
89332
|
+
directNvidiaApiKey
|
|
88042
89333
|
}));
|
|
88043
89334
|
});
|
|
88044
89335
|
app.post("/api/voice/engage", async (c) => {
|
|
@@ -88254,6 +89545,28 @@ function mountScoutVoiceRoutes(app, deps = {}) {
|
|
|
88254
89545
|
if (speechTiming === null) {
|
|
88255
89546
|
return c.json({ error: "speechTiming is invalid" }, 400);
|
|
88256
89547
|
}
|
|
89548
|
+
const defaults = resolveScoutSpeechDefaults();
|
|
89549
|
+
const requestedModelId = body.modelId ?? defaults.modelId;
|
|
89550
|
+
if (isNvidiaMagpieSpeechModel(requestedModelId)) {
|
|
89551
|
+
const nvidiaApiKey = resolveNvidiaApiKey();
|
|
89552
|
+
if (!nvidiaApiKey) {
|
|
89553
|
+
return c.json({ error: "NV_API_KEY is required for hosted NVIDIA Developer Inference." }, 503);
|
|
89554
|
+
}
|
|
89555
|
+
try {
|
|
89556
|
+
return c.json({
|
|
89557
|
+
...await synthesizeNvidiaMagpieSpeech({
|
|
89558
|
+
text: text4,
|
|
89559
|
+
apiKey: nvidiaApiKey,
|
|
89560
|
+
voiceId: body.voiceId,
|
|
89561
|
+
signal: c.req.raw.signal
|
|
89562
|
+
}),
|
|
89563
|
+
route: "nvidia-developer-inference"
|
|
89564
|
+
});
|
|
89565
|
+
} catch (error) {
|
|
89566
|
+
const message = error instanceof Error ? error.message : "NVIDIA Magpie speech failed";
|
|
89567
|
+
return c.json({ error: message }, 503);
|
|
89568
|
+
}
|
|
89569
|
+
}
|
|
88257
89570
|
try {
|
|
88258
89571
|
return c.json(await synthesizeScoutSpeech({
|
|
88259
89572
|
text: text4,
|
|
@@ -88271,13 +89584,12 @@ function mountScoutVoiceRoutes(app, deps = {}) {
|
|
|
88271
89584
|
return;
|
|
88272
89585
|
}) ?? process.env.OPENAI_API_KEY?.trim();
|
|
88273
89586
|
if (apiKey && !c.req.raw.signal.aborted) {
|
|
88274
|
-
const defaults = resolveScoutSpeechDefaults();
|
|
88275
89587
|
try {
|
|
88276
89588
|
return c.json({
|
|
88277
89589
|
...await synthesizeOpenAISpeech({
|
|
88278
89590
|
text: text4,
|
|
88279
89591
|
apiKey,
|
|
88280
|
-
modelId:
|
|
89592
|
+
modelId: requestedModelId,
|
|
88281
89593
|
voiceId: body.voiceId ?? defaults.voiceId,
|
|
88282
89594
|
speed: body.speed,
|
|
88283
89595
|
instructions: optionalString(body.instructions),
|
|
@@ -89300,8 +90612,8 @@ function normalizeExistingPath(value) {
|
|
|
89300
90612
|
return null;
|
|
89301
90613
|
}
|
|
89302
90614
|
try {
|
|
89303
|
-
const
|
|
89304
|
-
return
|
|
90615
|
+
const stat11 = statSync21(absolute);
|
|
90616
|
+
return stat11.isDirectory() ? absolute : dirname37(absolute);
|
|
89305
90617
|
} catch {
|
|
89306
90618
|
return null;
|
|
89307
90619
|
}
|
|
@@ -90050,8 +91362,8 @@ async function resolveTrustedMaterialPath(work, materialId) {
|
|
|
90050
91362
|
if (!pathInsideRoot(realPath, realRoot)) {
|
|
90051
91363
|
return { ok: false, status: 403, error: "material path is outside its trusted root" };
|
|
90052
91364
|
}
|
|
90053
|
-
const
|
|
90054
|
-
if (!
|
|
91365
|
+
const stat11 = statSync21(realPath);
|
|
91366
|
+
if (!stat11.isFile()) {
|
|
90055
91367
|
return { ok: false, status: 415, error: "material is not a file" };
|
|
90056
91368
|
}
|
|
90057
91369
|
return { ok: true, material, realPath };
|
|
@@ -90065,12 +91377,12 @@ async function readWorkMaterialRaw(work, materialId) {
|
|
|
90065
91377
|
return resolved;
|
|
90066
91378
|
}
|
|
90067
91379
|
try {
|
|
90068
|
-
const
|
|
91380
|
+
const stat11 = statSync21(resolved.realPath);
|
|
90069
91381
|
return {
|
|
90070
91382
|
ok: true,
|
|
90071
91383
|
realPath: resolved.realPath,
|
|
90072
91384
|
mediaType: materialMediaType(resolved.realPath),
|
|
90073
|
-
sizeBytes:
|
|
91385
|
+
sizeBytes: stat11.size
|
|
90074
91386
|
};
|
|
90075
91387
|
} catch {
|
|
90076
91388
|
return { ok: false, status: 404, error: "material could not be read" };
|
|
@@ -90100,8 +91412,8 @@ async function readWorkMaterialContent(work, materialId) {
|
|
|
90100
91412
|
if (!pathInsideRoot(realPath, realRoot)) {
|
|
90101
91413
|
return { ok: false, status: 403, error: "material path is outside its trusted root" };
|
|
90102
91414
|
}
|
|
90103
|
-
const
|
|
90104
|
-
if (!
|
|
91415
|
+
const stat11 = statSync21(realPath);
|
|
91416
|
+
if (!stat11.isFile()) {
|
|
90105
91417
|
return { ok: false, status: 415, error: "material is not a file" };
|
|
90106
91418
|
}
|
|
90107
91419
|
const buffer = readFileSync29(realPath);
|
|
@@ -90133,7 +91445,7 @@ async function readWorkMaterialContent(work, materialId) {
|
|
|
90133
91445
|
|
|
90134
91446
|
// packages/web/server/plan-documents.ts
|
|
90135
91447
|
import { createHash as createHash9 } from "crypto";
|
|
90136
|
-
import { readdir as
|
|
91448
|
+
import { readdir as readdir5, readFile as readFile17, stat as stat11 } from "fs/promises";
|
|
90137
91449
|
import { homedir as homedir49 } from "os";
|
|
90138
91450
|
import { basename as basename25, isAbsolute as isAbsolute10, join as join65, relative as relative8, resolve as resolve27 } from "path";
|
|
90139
91451
|
var HOME3 = homedir49();
|
|
@@ -90216,7 +91528,7 @@ async function walkMarkdownFiles(directory, remaining = { count: MAX_FILES_PER_R
|
|
|
90216
91528
|
return [];
|
|
90217
91529
|
let entries2;
|
|
90218
91530
|
try {
|
|
90219
|
-
entries2 = await
|
|
91531
|
+
entries2 = await readdir5(directory, { withFileTypes: true });
|
|
90220
91532
|
} catch (error) {
|
|
90221
91533
|
if (error.code === "ENOENT")
|
|
90222
91534
|
return [];
|
|
@@ -90249,7 +91561,7 @@ async function discoverPlanFiles(root) {
|
|
|
90249
91561
|
const fromPlanDirs = (await Promise.all(PLAN_SUBDIRECTORIES.map((subdir) => walkMarkdownFiles(join65(root.root, subdir))))).flat();
|
|
90250
91562
|
let directPlanFiles = [];
|
|
90251
91563
|
try {
|
|
90252
|
-
const entries2 = await
|
|
91564
|
+
const entries2 = await readdir5(root.root, { withFileTypes: true });
|
|
90253
91565
|
directPlanFiles = entries2.filter((entry) => entry.isFile() && /\.plan\.md$/i.test(entry.name)).map((entry) => join65(root.root, entry.name));
|
|
90254
91566
|
} catch {
|
|
90255
91567
|
directPlanFiles = [];
|
|
@@ -90432,7 +91744,7 @@ function idForPlan(root, filePath) {
|
|
|
90432
91744
|
return `plan-doc:${hash}`;
|
|
90433
91745
|
}
|
|
90434
91746
|
async function readPlanDocument(root, filePath) {
|
|
90435
|
-
const fileStats = await
|
|
91747
|
+
const fileStats = await stat11(filePath).catch(() => null);
|
|
90436
91748
|
if (!fileStats || !fileStats.isFile() || fileStats.size > MAX_DOCUMENT_BYTES) {
|
|
90437
91749
|
return null;
|
|
90438
91750
|
}
|
|
@@ -92101,7 +93413,8 @@ function brokerCardAgentsForWeb(broker2) {
|
|
|
92101
93413
|
}
|
|
92102
93414
|
var AGENT_ATTENTION_TTL_MS2 = 1e4;
|
|
92103
93415
|
var AGENT_BACKGROUND_REFRESH_DELAY_MS = 500;
|
|
92104
|
-
var AGENT_BROKER_CONTEXT_TTL_MS =
|
|
93416
|
+
var AGENT_BROKER_CONTEXT_TTL_MS = 60000;
|
|
93417
|
+
var AGENT_BROKER_CONTEXT_COLD_BUDGET_MS = 75;
|
|
92105
93418
|
var agentAttentionCache = null;
|
|
92106
93419
|
var agentAttentionInFlight = null;
|
|
92107
93420
|
function queryAgentAttentionIndex(broker2, capture = defaultCaptureTmuxPane) {
|
|
@@ -92151,8 +93464,12 @@ function createAgentBrokerContextReader() {
|
|
|
92151
93464
|
return promise;
|
|
92152
93465
|
};
|
|
92153
93466
|
return () => {
|
|
92154
|
-
if (!cache)
|
|
92155
|
-
return
|
|
93467
|
+
if (!cache) {
|
|
93468
|
+
return Promise.race([
|
|
93469
|
+
refresh(0),
|
|
93470
|
+
delay2(AGENT_BROKER_CONTEXT_COLD_BUDGET_MS).then(() => null)
|
|
93471
|
+
]);
|
|
93472
|
+
}
|
|
92156
93473
|
if (Date.now() - cache.at >= AGENT_BROKER_CONTEXT_TTL_MS && !inFlight) {
|
|
92157
93474
|
refresh(AGENT_BACKGROUND_REFRESH_DELAY_MS);
|
|
92158
93475
|
}
|
|
@@ -92246,24 +93563,37 @@ function withPinnedMeshPeerAgents(agents, broker2, limit) {
|
|
|
92246
93563
|
if (!localNodeId)
|
|
92247
93564
|
return mostRecentAgents(agents, limit);
|
|
92248
93565
|
const peerNodeIds = pinnedMeshPeerNodeIds(broker2);
|
|
92249
|
-
const
|
|
93566
|
+
const representativeCardByNode = new Map;
|
|
93567
|
+
for (const agent of Object.values(broker2.snapshot.agents ?? {})) {
|
|
93568
|
+
const homeNodeId = agent.homeNodeId;
|
|
93569
|
+
if (!homeNodeId || !peerNodeIds.has(homeNodeId) || !isBrokerAgentVisibleInWeb(agent))
|
|
93570
|
+
continue;
|
|
93571
|
+
const existing = representativeCardByNode.get(homeNodeId);
|
|
93572
|
+
if (!existing || (latestBrokerAgentTimestamp(agent, null) ?? 0) > (latestBrokerAgentTimestamp(existing, null) ?? 0)) {
|
|
93573
|
+
representativeCardByNode.set(homeNodeId, agent);
|
|
93574
|
+
}
|
|
93575
|
+
}
|
|
93576
|
+
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
93577
|
if (peerAgents.length === 0)
|
|
92251
93578
|
return mostRecentAgents(agents, limit);
|
|
92252
93579
|
const byId = new Map(agents.map((agent) => [agent.id, agent]));
|
|
92253
93580
|
for (const peer of peerAgents) {
|
|
92254
|
-
byId.
|
|
93581
|
+
if (!byId.has(peer.id))
|
|
93582
|
+
byId.set(peer.id, peer);
|
|
92255
93583
|
}
|
|
92256
93584
|
const merged = [...byId.values()];
|
|
92257
93585
|
if (limit === undefined)
|
|
92258
93586
|
return merged;
|
|
92259
|
-
const
|
|
92260
|
-
const included = new Set(
|
|
92261
|
-
|
|
92262
|
-
|
|
92263
|
-
|
|
92264
|
-
|
|
93587
|
+
const representatives = peerAgents.map((peer) => byId.get(peer.id) ?? peer).slice(0, limit);
|
|
93588
|
+
const included = new Set(representatives.map((agent) => agent.id));
|
|
93589
|
+
const limited = [...representatives];
|
|
93590
|
+
for (const agent of mostRecentAgents(merged, undefined)) {
|
|
93591
|
+
if (limited.length >= limit)
|
|
93592
|
+
break;
|
|
93593
|
+
if (included.add(agent.id))
|
|
93594
|
+
limited.push(agent);
|
|
92265
93595
|
}
|
|
92266
|
-
return limited;
|
|
93596
|
+
return mostRecentAgents(limited, undefined);
|
|
92267
93597
|
}
|
|
92268
93598
|
function agentListSummary(agent) {
|
|
92269
93599
|
return {
|
|
@@ -92313,13 +93643,11 @@ function agentListSummary(agent) {
|
|
|
92313
93643
|
createdAt: agent.createdAt
|
|
92314
93644
|
};
|
|
92315
93645
|
}
|
|
92316
|
-
|
|
93646
|
+
function withAgentRepoKeys(agents) {
|
|
92317
93647
|
const roots = agents.map((agent) => agent.projectRoot).filter((root) => Boolean(root));
|
|
92318
93648
|
if (roots.length === 0)
|
|
92319
93649
|
return agents;
|
|
92320
|
-
const keys =
|
|
92321
|
-
if (!keys)
|
|
92322
|
-
return agents;
|
|
93650
|
+
const keys = cachedRepoKeysByRoot(roots);
|
|
92323
93651
|
return agents.map((agent) => {
|
|
92324
93652
|
const repoKey = agent.projectRoot ? keys.get(agent.projectRoot) ?? null : null;
|
|
92325
93653
|
return repoKey ? { ...agent, repoKey } : agent;
|
|
@@ -92403,11 +93731,11 @@ async function queryAgentsIncludingBrokerCards(limit, includeRichBrokerContext =
|
|
|
92403
93731
|
const brokerById2 = new Map(brokerAgents2.map((agent) => [agent.id, agent]));
|
|
92404
93732
|
const mergedAgents2 = agents.map((agent) => mergeBrokerAgentProjection(agent, brokerById2.get(agent.id)));
|
|
92405
93733
|
const existingIds2 = new Set(mergedAgents2.map((agent) => agent.id));
|
|
92406
|
-
const
|
|
92407
|
-
const roster2 =
|
|
93734
|
+
const attention2 = includeAttention ? await queryAgentAttentionIndex(null, capture) : new Map;
|
|
93735
|
+
const roster2 = mostRecentAgents(applyAgentAttention([
|
|
92408
93736
|
...mergedAgents2,
|
|
92409
93737
|
...brokerAgents2.filter((agent) => !existingIds2.has(agent.id))
|
|
92410
|
-
],
|
|
93738
|
+
], attention2), limit);
|
|
92411
93739
|
return withAgentRepoKeys(roster2);
|
|
92412
93740
|
}
|
|
92413
93741
|
const broker2 = await loadBrokerContext();
|
|
@@ -94039,13 +95367,11 @@ function dedupeHudRunnerProjects(projects) {
|
|
|
94039
95367
|
return result;
|
|
94040
95368
|
}
|
|
94041
95369
|
async function buildHudRunnerOptions(currentDirectory, input = {}) {
|
|
94042
|
-
const [settingsResult,
|
|
95370
|
+
const [settingsResult, runtimeCatalogResult] = await Promise.allSettled([
|
|
94043
95371
|
readOpenScoutSettings({ currentDirectory }),
|
|
94044
|
-
loadHarnessCatalogSnapshot(),
|
|
94045
95372
|
loadBrokerRuntimeCatalog()
|
|
94046
95373
|
]);
|
|
94047
95374
|
const settings = settingsResult.status === "fulfilled" ? settingsResult.value : null;
|
|
94048
|
-
const catalog = catalogResult.status === "fulfilled" ? catalogResult.value : null;
|
|
94049
95375
|
const liveRuntimeCatalog = runtimeCatalogResult.status === "fulfilled" ? runtimeCatalogResult.value : null;
|
|
94050
95376
|
const runtimeCatalog = liveRuntimeCatalog?.catalog ?? SCOUT_RUNTIME_CATALOG;
|
|
94051
95377
|
const allAgents = queryAgents(50);
|
|
@@ -94058,19 +95384,17 @@ async function buildHudRunnerOptions(currentDirectory, input = {}) {
|
|
|
94058
95384
|
const configuredDefaultHarness = settings?.agents.defaultHarness?.trim() ?? "";
|
|
94059
95385
|
const defaultHarness = isScoutRuntimeHarnessEnabled(configuredDefaultHarness, runtimeCatalog) ? configuredDefaultHarness : scoutRuntimeDefaultHarness(runtimeCatalog) ?? "claude";
|
|
94060
95386
|
const harnessesById = new Map;
|
|
94061
|
-
const readinessByHarness = new Map((catalog?.entries ?? []).map((entry) => [entry.harness, entry]));
|
|
94062
95387
|
for (const entry of runtimeCatalog.harnesses) {
|
|
94063
95388
|
if (!entry.enabled || entry.listed === false)
|
|
94064
95389
|
continue;
|
|
94065
|
-
const readiness = readinessByHarness.get(entry.id);
|
|
94066
95390
|
harnessesById.set(entry.id, {
|
|
94067
95391
|
id: entry.id,
|
|
94068
95392
|
name: entry.id,
|
|
94069
95393
|
label: entry.label,
|
|
94070
95394
|
description: null,
|
|
94071
|
-
state:
|
|
94072
|
-
ready:
|
|
94073
|
-
detail:
|
|
95395
|
+
state: null,
|
|
95396
|
+
ready: null,
|
|
95397
|
+
detail: null
|
|
94074
95398
|
});
|
|
94075
95399
|
}
|
|
94076
95400
|
const projectOptions = allAgents.map((agent) => agent.projectRoot ?? agent.cwd).filter((root) => typeof root === "string" && root.trim().length > 0).map((root) => {
|
|
@@ -94266,6 +95590,7 @@ function fallbackOpenScoutHostInfo(options, currentDirectory) {
|
|
|
94266
95590
|
async function createOpenScoutWebServer(options) {
|
|
94267
95591
|
const shellTtl = options.shellStateCacheTtlMs ?? 15000;
|
|
94268
95592
|
const currentDirectory = options.currentDirectory;
|
|
95593
|
+
const lanAccessScope = options.lanAccessScope ?? resolveScoutWebLanAccessScope(process.env);
|
|
94269
95594
|
const pendingPairRequests = createPendingPairRequestStore({
|
|
94270
95595
|
statePath: pairRequestStatePath(localConfigHome())
|
|
94271
95596
|
});
|
|
@@ -94281,8 +95606,28 @@ async function createOpenScoutWebServer(options) {
|
|
|
94281
95606
|
startGlobalHeuristicsWatcher();
|
|
94282
95607
|
}
|
|
94283
95608
|
const app = new Hono2;
|
|
95609
|
+
app.use("*", async (c, next) => {
|
|
95610
|
+
const peerAddress = (options.resolvePeerAddress ?? resolveScoutRequestPeerAddress)(c);
|
|
95611
|
+
if (!isScoutWebRequestAllowedFromPeer(c.req.raw, peerAddress, lanAccessScope)) {
|
|
95612
|
+
return c.text("Not Found", 404);
|
|
95613
|
+
}
|
|
95614
|
+
await next();
|
|
95615
|
+
});
|
|
94284
95616
|
installHttpsEdgeSecurityHeaders(app, options.publicOrigin);
|
|
94285
95617
|
const shellStateCache = createCachedSnapshot(loadOpenScoutWebShellState, shellTtl);
|
|
95618
|
+
const readAgentConfigurationSnapshot = coalesce(() => buildAgentConfigurationSnapshot(currentDirectory), 30000);
|
|
95619
|
+
const runnerOptionsReaders = new Map;
|
|
95620
|
+
const readRunnerOptions = (scope, projectRoot) => {
|
|
95621
|
+
const key = `${scope}\x00${projectRoot}`;
|
|
95622
|
+
let read = runnerOptionsReaders.get(key);
|
|
95623
|
+
if (!read) {
|
|
95624
|
+
if (runnerOptionsReaders.size >= 32)
|
|
95625
|
+
runnerOptionsReaders.clear();
|
|
95626
|
+
read = coalesce(() => buildHudRunnerOptions(currentDirectory, { scope, projectRoot }), 30000);
|
|
95627
|
+
runnerOptionsReaders.set(key, read);
|
|
95628
|
+
}
|
|
95629
|
+
return read();
|
|
95630
|
+
};
|
|
94286
95631
|
const agentBrokerContextReader = createAgentBrokerContextReader();
|
|
94287
95632
|
const agentBrokerHomeReader = createAgentBrokerHomeReader();
|
|
94288
95633
|
const dispatchBrokerSnapshotCache = createCachedSnapshot(async () => {
|
|
@@ -94339,7 +95684,8 @@ async function createOpenScoutWebServer(options) {
|
|
|
94339
95684
|
installScoutApiMiddleware(app, "openscout-web api", {
|
|
94340
95685
|
trustedHosts: options.trustedHosts,
|
|
94341
95686
|
trustedOrigins: options.trustedOrigins,
|
|
94342
|
-
authToken: options.authToken
|
|
95687
|
+
authToken: options.authToken,
|
|
95688
|
+
resolvePeerAddress: options.resolvePeerAddress
|
|
94343
95689
|
});
|
|
94344
95690
|
mountScoutDeckSurfaceRoutes(app, {
|
|
94345
95691
|
currentDirectory,
|
|
@@ -94666,33 +96012,68 @@ async function createOpenScoutWebServer(options) {
|
|
|
94666
96012
|
const route = c.req.query("route")?.trim().toLowerCase() ?? null;
|
|
94667
96013
|
const token = c.req.query("token")?.trim() || null;
|
|
94668
96014
|
const wantsJson = (c.req.header("accept") ?? "").includes("application/json");
|
|
94669
|
-
const
|
|
96015
|
+
const peerAddress = (options.resolvePeerAddress ?? resolveScoutRequestPeerAddress)(c);
|
|
96016
|
+
const xff = c.req.header("x-forwarded-for");
|
|
96017
|
+
const forwardedIp = (xff ? xff.split(",").at(-1)?.trim() : null) || c.req.header("x-real-ip")?.trim() || null;
|
|
96018
|
+
const loopbackPeer = Boolean(peerAddress && isLoopbackScoutAddress(peerAddress));
|
|
96019
|
+
const sameMacRequest = isSameMacScoutRequest(c.req.raw, peerAddress);
|
|
96020
|
+
const relayedLanRequest = Boolean(loopbackPeer && c.req.header(SCOUT_PAIR_RELAY_HEADER) === "1");
|
|
96021
|
+
const directLanRequest = Boolean(peerAddress && !isLoopbackScoutAddress(peerAddress));
|
|
96022
|
+
const proxiedLanRequest = Boolean(loopbackPeer && !relayedLanRequest && !sameMacRequest);
|
|
96023
|
+
const unidentifiedPairingIngress = !peerAddress;
|
|
96024
|
+
const requiresApproval = relayedLanRequest || directLanRequest || proxiedLanRequest || unidentifiedPairingIngress;
|
|
96025
|
+
const requesterApp = parseScoutPairClient(c.req.header(SCOUT_PAIR_CLIENT_HEADER), c.req.header("user-agent"));
|
|
96026
|
+
const state = await loadPairingState(currentDirectory, false);
|
|
94670
96027
|
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
96028
|
if (token) {
|
|
94678
|
-
const
|
|
94679
|
-
if (!
|
|
96029
|
+
const request2 = pendingPairRequests.get(token);
|
|
96030
|
+
if (!request2) {
|
|
94680
96031
|
return wantsJson ? c.json({ status: "expired", token }, 410) : c.text("Pairing request expired.", 410);
|
|
94681
96032
|
}
|
|
94682
|
-
if (
|
|
96033
|
+
if (request2.status === "denied") {
|
|
94683
96034
|
return wantsJson ? c.json({ status: "denied", token }, 403) : c.text("Pairing request was denied.", 403);
|
|
94684
96035
|
}
|
|
96036
|
+
if (location && request2.status === "approved") {
|
|
96037
|
+
if (!pendingPairRequests.fulfill(token, "approved")) {
|
|
96038
|
+
const current = pendingPairRequests.get(token);
|
|
96039
|
+
if (current?.status === "approved" || current?.status === "pending") {
|
|
96040
|
+
return c.json({ status: current.status, token, pollAfterMs: 1200 }, 202);
|
|
96041
|
+
}
|
|
96042
|
+
if (current?.status === "denied") {
|
|
96043
|
+
return wantsJson ? c.json({ status: "denied", token }, 403) : c.text("Pairing request was denied.", 403);
|
|
96044
|
+
}
|
|
96045
|
+
return wantsJson ? c.json({ status: "expired", token }, 410) : c.text("Pairing request expired.", 410);
|
|
96046
|
+
}
|
|
96047
|
+
return c.redirect(location, 302);
|
|
96048
|
+
}
|
|
94685
96049
|
pendingPairRequests.touch(token);
|
|
94686
|
-
return c.json({ status:
|
|
96050
|
+
return c.json({ status: request2.status, token, pollAfterMs: 1200 }, 202);
|
|
94687
96051
|
}
|
|
94688
|
-
|
|
94689
|
-
|
|
94690
|
-
|
|
94691
|
-
|
|
94692
|
-
|
|
94693
|
-
|
|
94694
|
-
}
|
|
94695
|
-
|
|
96052
|
+
if (location && !requiresApproval) {
|
|
96053
|
+
return c.redirect(location, 302);
|
|
96054
|
+
}
|
|
96055
|
+
const requesterIp = unidentifiedPairingIngress ? null : relayedLanRequest || proxiedLanRequest ? forwardedIp : directLanRequest ? peerAddress ?? null : forwardedIp;
|
|
96056
|
+
if (requiresApproval && !requesterIp) {
|
|
96057
|
+
return wantsJson ? c.json({ status: "unavailable" }, 503) : c.text("Unable to identify pairing requester.", 503);
|
|
96058
|
+
}
|
|
96059
|
+
let request;
|
|
96060
|
+
try {
|
|
96061
|
+
request = pendingPairRequests.create({
|
|
96062
|
+
requesterIp,
|
|
96063
|
+
requesterLabel: c.req.header("x-scout-device-name")?.trim() || null,
|
|
96064
|
+
requesterApp,
|
|
96065
|
+
route
|
|
96066
|
+
});
|
|
96067
|
+
} catch (error) {
|
|
96068
|
+
if (!(error instanceof PairRequestCapacityError))
|
|
96069
|
+
throw error;
|
|
96070
|
+
c.header("retry-after", String(Math.ceil(error.retryAfterMs / 1000)));
|
|
96071
|
+
return wantsJson ? c.json({ status: "busy", retryAfterMs: error.retryAfterMs }, 429) : c.text("Too many pairing requests. Try again shortly.", 429);
|
|
96072
|
+
}
|
|
96073
|
+
if (request.status === "denied") {
|
|
96074
|
+
return wantsJson ? c.json({ status: "denied", token: request.token }, 403) : c.text("Pairing request was denied.", 403);
|
|
96075
|
+
}
|
|
96076
|
+
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
96077
|
});
|
|
94697
96078
|
app.get("/api/notifications", (c) => {
|
|
94698
96079
|
const rawType = c.req.query("type") ?? "";
|
|
@@ -94701,7 +96082,7 @@ async function createOpenScoutWebServer(options) {
|
|
|
94701
96082
|
const notifications = includePairingRequests ? pendingPairRequests.list().filter((request) => request.status === "pending").map((request) => ({
|
|
94702
96083
|
id: `pairing_request:${request.token}`,
|
|
94703
96084
|
type: "pairing_request",
|
|
94704
|
-
title: `${request
|
|
96085
|
+
title: `${pairRequesterDisplay(request)} wants to pair`,
|
|
94705
96086
|
body: `On your network${request.requesterIp ? ` \xB7 ${request.requesterIp}` : ""}.`,
|
|
94706
96087
|
createdAt: request.createdAt,
|
|
94707
96088
|
updatedAt: request.updatedAt,
|
|
@@ -94791,14 +96172,11 @@ async function createOpenScoutWebServer(options) {
|
|
|
94791
96172
|
});
|
|
94792
96173
|
app.get("/api/shell-state", async (c) => c.json(await shellStateCache.get()));
|
|
94793
96174
|
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
|
|
96175
|
+
app.get("/api/agent-config/snapshot", async (c) => c.json(await readAgentConfigurationSnapshot()));
|
|
94795
96176
|
app.get("/api/runner/options", async (c) => {
|
|
94796
96177
|
const requestedScope = c.req.query("scope");
|
|
94797
96178
|
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
|
-
}));
|
|
96179
|
+
return c.json(await readRunnerOptions(scope, c.req.query("projectRoot") || currentDirectory));
|
|
94802
96180
|
});
|
|
94803
96181
|
const agentsResponseCache = new Map;
|
|
94804
96182
|
const readAgentsResponse = (limit, summary, attentionRequested) => {
|
|
@@ -94807,7 +96185,7 @@ async function createOpenScoutWebServer(options) {
|
|
|
94807
96185
|
if (!entry) {
|
|
94808
96186
|
if (agentsResponseCache.size >= 32)
|
|
94809
96187
|
agentsResponseCache.clear();
|
|
94810
|
-
entry = coalesce(() => queryAgentsIncludingBrokerCards(limit, !summary
|
|
96188
|
+
entry = coalesce(() => queryAgentsIncludingBrokerCards(limit, !summary, attentionRequested, options.captureTmuxPane ?? defaultCaptureTmuxPane, agentBrokerContextReader, agentBrokerHomeReader), 3000);
|
|
94811
96189
|
agentsResponseCache.set(key, entry);
|
|
94812
96190
|
}
|
|
94813
96191
|
return entry();
|
|
@@ -95580,7 +96958,12 @@ async function createOpenScoutWebServer(options) {
|
|
|
95580
96958
|
let messages2;
|
|
95581
96959
|
try {
|
|
95582
96960
|
parseMessageHistoryCursor(beforeMessageId);
|
|
95583
|
-
const
|
|
96961
|
+
const brokerContext = cId ? await loadScoutBrokerContext(undefined, {
|
|
96962
|
+
scope: "conversations",
|
|
96963
|
+
waitForInitial: false,
|
|
96964
|
+
initialRefreshDelayMs: 750
|
|
96965
|
+
}).catch(() => null) : null;
|
|
96966
|
+
const brokerMessages = cId ? await getScoutConversationMessages(cId, limit, beforeMessageId, brokerContext) : null;
|
|
95584
96967
|
if (cId && brokerMessages && brokerMessages.length > 0 && brokerMessages.length < limit) {
|
|
95585
96968
|
const oldest = brokerMessages[0];
|
|
95586
96969
|
const seen = new Set(brokerMessages.map((message) => message.id));
|
|
@@ -95953,7 +97336,11 @@ async function createOpenScoutWebServer(options) {
|
|
|
95953
97336
|
if (flights.length > 0) {
|
|
95954
97337
|
return c.json(flights);
|
|
95955
97338
|
}
|
|
95956
|
-
const broker2 = await loadScoutBrokerContext(
|
|
97339
|
+
const broker2 = await loadScoutBrokerContext(undefined, {
|
|
97340
|
+
scope: "conversations",
|
|
97341
|
+
waitForInitial: false,
|
|
97342
|
+
initialRefreshDelayMs: 750
|
|
97343
|
+
}).catch(() => null);
|
|
95957
97344
|
return c.json(broker2 ? queryBrokerFlightsForWeb(broker2, query) : flights);
|
|
95958
97345
|
});
|
|
95959
97346
|
app.get("/api/follow", (c) => {
|
|
@@ -95970,7 +97357,7 @@ async function createOpenScoutWebServer(options) {
|
|
|
95970
97357
|
targetAgentId: c.req.query("targetAgentId") || undefined
|
|
95971
97358
|
}));
|
|
95972
97359
|
});
|
|
95973
|
-
const readCommsList = async (c) => {
|
|
97360
|
+
const readCommsList = async (c, options2 = {}) => {
|
|
95974
97361
|
const rawLimit = Number(c.req.query("limit"));
|
|
95975
97362
|
const rawKinds = c.req.query("kinds")?.trim();
|
|
95976
97363
|
const filters = {
|
|
@@ -95979,11 +97366,43 @@ async function createOpenScoutWebServer(options) {
|
|
|
95979
97366
|
kinds: parseConversationKinds(rawKinds),
|
|
95980
97367
|
machineId: c.req.query("machineId") || undefined
|
|
95981
97368
|
};
|
|
95982
|
-
const
|
|
97369
|
+
const preferredProjection = options2.preferMaterialized && !filters.machineId ? await readScoutConversationProjection(160) : undefined;
|
|
97370
|
+
if (preferredProjection?.items.some((item) => item.entityKind === "scout_conversation")) {
|
|
97371
|
+
return {
|
|
97372
|
+
items: provisionalScoutConversations(preferredProjection, filters),
|
|
97373
|
+
listReady: true
|
|
97374
|
+
};
|
|
97375
|
+
}
|
|
97376
|
+
const broker2 = await loadScoutBrokerContext(undefined, filters.machineId ? {} : {
|
|
97377
|
+
scope: "conversations",
|
|
97378
|
+
waitForInitial: false,
|
|
97379
|
+
initialRefreshDelayMs: 750
|
|
97380
|
+
}).catch(() => null);
|
|
95983
97381
|
if (broker2) {
|
|
95984
97382
|
const items = await getScoutConversations(filters, broker2);
|
|
95985
97383
|
return { items, listReady: true };
|
|
95986
97384
|
}
|
|
97385
|
+
if (!filters.machineId) {
|
|
97386
|
+
const launchProjection = preferredProjection === undefined ? await readScoutConversationProjection(Math.min(160, filters.limit ?? 160)) : preferredProjection;
|
|
97387
|
+
if (launchProjection?.items.some((item) => item.entityKind === "scout_conversation")) {
|
|
97388
|
+
return {
|
|
97389
|
+
items: provisionalScoutConversations(launchProjection, filters),
|
|
97390
|
+
listReady: true
|
|
97391
|
+
};
|
|
97392
|
+
}
|
|
97393
|
+
const projected = querySessions(250);
|
|
97394
|
+
if (projected.length > 0) {
|
|
97395
|
+
const query = filters.query?.trim().toLocaleLowerCase() ?? "";
|
|
97396
|
+
const kinds = filters.kinds ? new Set(filters.kinds) : null;
|
|
97397
|
+
const items = projected.filter((item) => !kinds || kinds.has(item.kind)).filter((item) => !query || [
|
|
97398
|
+
item.title,
|
|
97399
|
+
item.alias,
|
|
97400
|
+
item.agentName,
|
|
97401
|
+
item.preview
|
|
97402
|
+
].some((value) => value?.toLocaleLowerCase().includes(query))).slice(0, filters.limit ?? projected.length);
|
|
97403
|
+
return { items, listReady: true };
|
|
97404
|
+
}
|
|
97405
|
+
}
|
|
95987
97406
|
const health = await readScoutBrokerHealth(resolveScoutBrokerUrl(), {
|
|
95988
97407
|
signal: AbortSignal.timeout(2000)
|
|
95989
97408
|
});
|
|
@@ -95996,7 +97415,7 @@ async function createOpenScoutWebServer(options) {
|
|
|
95996
97415
|
retryable: true
|
|
95997
97416
|
}, 503);
|
|
95998
97417
|
app.get("/api/comms", async (c) => {
|
|
95999
|
-
const { items, listReady } = await readCommsList(c);
|
|
97418
|
+
const { items, listReady } = await readCommsList(c, { preferMaterialized: true });
|
|
96000
97419
|
if (!listReady) {
|
|
96001
97420
|
return unavailableConversationList(c);
|
|
96002
97421
|
}
|
|
@@ -96176,10 +97595,10 @@ async function createOpenScoutWebServer(options) {
|
|
|
96176
97595
|
session: conversation
|
|
96177
97596
|
});
|
|
96178
97597
|
}
|
|
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
97598
|
const payload = await loadSessionRefObservePayload(refId);
|
|
96182
97599
|
if (payload) {
|
|
97600
|
+
const parsedRef = payload.agentId ? parseSessionRouteRef(refId) : null;
|
|
97601
|
+
const harnessSession = parsedRef ? querySessions(200).find((session3) => sessionHarnessMatches(parsedRef.harness, session3.harness) && parseSessionRouteRef(session3.harnessSessionId)?.refId === parsedRef.refId) : null;
|
|
96183
97602
|
return c.json({
|
|
96184
97603
|
kind: "observe",
|
|
96185
97604
|
refId,
|
|
@@ -96204,7 +97623,12 @@ async function createOpenScoutWebServer(options) {
|
|
|
96204
97623
|
return c.json({ error: "chatId must be an opaque chat id" }, 400);
|
|
96205
97624
|
}
|
|
96206
97625
|
const session3 = querySessionById(resolvedChatId);
|
|
96207
|
-
const
|
|
97626
|
+
const broker2 = session3 ? await loadScoutBrokerContext(undefined, {
|
|
97627
|
+
scope: "conversations",
|
|
97628
|
+
waitForInitial: false,
|
|
97629
|
+
initialRefreshDelayMs: 750
|
|
97630
|
+
}).catch(() => null) : undefined;
|
|
97631
|
+
const conversation = broker2 === null ? null : broker2 ? (await getScoutConversations({ conversationId: resolvedChatId, limit: 1 }, broker2))[0] ?? null : await getScoutConversationById(resolvedChatId);
|
|
96208
97632
|
if (session3 && conversation) {
|
|
96209
97633
|
return c.json({ ...session3, ...conversation });
|
|
96210
97634
|
}
|
|
@@ -97093,6 +98517,8 @@ async function createOpenScoutWebServer(options) {
|
|
|
97093
98517
|
const limitParam = parseOptionalPositiveInt3(c.req.query("limit"), 500) ?? 500;
|
|
97094
98518
|
const includeTranscripts = c.req.query("transcripts") === "true" || c.req.query("transcripts") === "1";
|
|
97095
98519
|
const mode = c.req.query("mode") === "assistant-replies" ? "assistant-replies" : null;
|
|
98520
|
+
const requestedWindowMs = parseOptionalPositiveInt3(c.req.query("windowMs"));
|
|
98521
|
+
const windowMs = requestedWindowMs === undefined ? undefined : Math.min(requestedWindowMs, 86400000);
|
|
97096
98522
|
const url = new URL(scoutBrokerPaths.v1.tailRecent, resolveScoutBrokerUrl());
|
|
97097
98523
|
url.searchParams.set("limit", String(limitParam));
|
|
97098
98524
|
if (includeTranscripts) {
|
|
@@ -97101,7 +98527,10 @@ async function createOpenScoutWebServer(options) {
|
|
|
97101
98527
|
if (mode) {
|
|
97102
98528
|
url.searchParams.set("mode", mode);
|
|
97103
98529
|
}
|
|
97104
|
-
|
|
98530
|
+
if (windowMs !== undefined) {
|
|
98531
|
+
url.searchParams.set("windowMs", String(windowMs));
|
|
98532
|
+
}
|
|
98533
|
+
const cacheKey = `limit=${limitParam};transcripts=${includeTranscripts ? "1" : "0"};mode=${mode ?? "all"};window=${windowMs ?? "all"}`;
|
|
97105
98534
|
let cache = tailRecentCaches.get(cacheKey);
|
|
97106
98535
|
if (!cache) {
|
|
97107
98536
|
cache = createBrokerJsonCache();
|
|
@@ -97811,6 +99240,7 @@ function startProcessParentWatchdog(expectedParentPidRaw, options = {}) {
|
|
|
97811
99240
|
process.title = "scout-web";
|
|
97812
99241
|
var port = Number.parseInt(process.env.OPENSCOUT_WEB_PORT ?? process.env.SCOUT_WEB_PORT ?? String(resolveWebPort()), 10);
|
|
97813
99242
|
var hostname2 = resolveScoutWebBindHost(process.env);
|
|
99243
|
+
var lanAccessScope = resolveScoutWebLanAccessScope(process.env);
|
|
97814
99244
|
var webAuthToken = resolveWebAuthToken(process.env);
|
|
97815
99245
|
var currentDirectory = resolveOpenScoutSetupContextRoot({
|
|
97816
99246
|
env: process.env,
|
|
@@ -97820,6 +99250,7 @@ var shellStateCacheTtlMs = Number.parseInt(process.env.OPENSCOUT_WEB_SHELL_CACHE
|
|
|
97820
99250
|
var providerTelemetryBootstrapEnabled = process.env.OPENSCOUT_WEB_PROVIDER_TELEMETRY_BOOTSTRAP?.trim() === "1";
|
|
97821
99251
|
var startupWarmupEnabled = process.env.OPENSCOUT_WEB_STARTUP_WARMUP?.trim() === "1";
|
|
97822
99252
|
var routes = resolveOpenScoutWebRoutes(process.env);
|
|
99253
|
+
var requestPeerAddresses = createScoutRequestPeerAddressRegistry();
|
|
97823
99254
|
function resolveStaticRoot2() {
|
|
97824
99255
|
if (process.env.OPENSCOUT_WEB_STATIC_ROOT?.trim()) {
|
|
97825
99256
|
return process.env.OPENSCOUT_WEB_STATIC_ROOT.trim();
|
|
@@ -97909,6 +99340,7 @@ var web = await createOpenScoutWebServer({
|
|
|
97909
99340
|
trustedHosts: applicationServerIdentity.trustedHosts,
|
|
97910
99341
|
trustedOrigins: applicationServerIdentity.trustedOrigins,
|
|
97911
99342
|
authToken: webAuthToken,
|
|
99343
|
+
resolvePeerAddress: requestPeerAddresses.resolve,
|
|
97912
99344
|
runTerminalCommand: async (request) => {
|
|
97913
99345
|
const relay = await ensureTerminalRelay();
|
|
97914
99346
|
if (!relay) {
|
|
@@ -97948,6 +99380,9 @@ try {
|
|
|
97948
99380
|
async fetch(req, server2) {
|
|
97949
99381
|
const url = new URL(req.url);
|
|
97950
99382
|
const peerAddress = server2.requestIP(req)?.address;
|
|
99383
|
+
if (!isScoutWebRequestAllowedFromPeer(req, peerAddress, lanAccessScope)) {
|
|
99384
|
+
return new Response("Not Found", { status: 404 });
|
|
99385
|
+
}
|
|
97951
99386
|
if (req.headers.get("upgrade")?.toLowerCase() === "websocket") {
|
|
97952
99387
|
let upstreamUrl = null;
|
|
97953
99388
|
const guardsOrigin = url.pathname === routes.terminalRelayPath || url.pathname === routes.tailStreamPath || url.pathname === routes.eventsStreamPath;
|
|
@@ -98003,6 +99438,7 @@ try {
|
|
|
98003
99438
|
return headers2;
|
|
98004
99439
|
})()
|
|
98005
99440
|
}) : req;
|
|
99441
|
+
requestPeerAddresses.remember(honoRequest, peerAddress);
|
|
98006
99442
|
const response = await honoFetch(honoRequest, server2);
|
|
98007
99443
|
if (!bootstrapEligible)
|
|
98008
99444
|
return response;
|