@maudecode/talaria-web 1.15.0 → 1.16.1
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/_release.json +4 -4
- package/dist/api/automation-router.d.ts +21 -7
- package/dist/api/automation-router.js +3 -0
- package/dist/api/automation-router.js.map +1 -1
- package/dist/api/chat-router.d.ts +142 -6
- package/dist/api/chat-router.js +11 -5
- package/dist/api/chat-router.js.map +1 -1
- package/dist/api/git-router.js +44 -32
- package/dist/api/git-router.js.map +1 -1
- package/dist/api/raw-routes.js +5 -58
- package/dist/api/raw-routes.js.map +1 -1
- package/dist/api/router.d.ts +4 -2
- package/dist/api/router.js +8 -8
- package/dist/api/router.js.map +1 -1
- package/dist/api/sessions-router.d.ts +714 -42
- package/dist/api/sessions-router.js +57 -23
- package/dist/api/sessions-router.js.map +1 -1
- package/dist/api/settings-router.d.ts +153 -9
- package/dist/api/settings-router.js +61 -16
- package/dist/api/settings-router.js.map +1 -1
- package/dist/api/sse-routes.js +1 -1
- package/dist/api/sse-routes.js.map +1 -1
- package/dist/api/tools-router.d.ts +13 -1
- package/dist/api/tools-router.js +10 -8
- package/dist/api/tools-router.js.map +1 -1
- package/dist/app.d.ts +1047 -67
- package/dist/auth/gate.js +8 -4
- package/dist/auth/gate.js.map +1 -1
- package/dist/auth/oidc.d.ts +6 -2
- package/dist/auth/oidc.js +16 -11
- package/dist/auth/oidc.js.map +1 -1
- package/dist/auth/store.d.ts +14 -2
- package/dist/auth/store.js +26 -1
- package/dist/auth/store.js.map +1 -1
- package/dist/cli/dotenv.d.ts +1 -1
- package/dist/cli/dotenv.js +36 -3
- package/dist/cli/dotenv.js.map +1 -1
- package/dist/http/addresses.d.ts +6 -0
- package/dist/http/addresses.js +26 -0
- package/dist/http/addresses.js.map +1 -1
- package/dist/http/context.d.ts +3 -3
- package/dist/links.d.ts +26 -0
- package/dist/links.js +60 -0
- package/dist/links.js.map +1 -0
- package/dist/onboarding.js +26 -7
- package/dist/onboarding.js.map +1 -1
- package/dist/profiles/profiles.js +1 -1
- package/dist/profiles/profiles.js.map +1 -1
- package/dist/providers/catalog.d.ts +74 -1
- package/dist/providers/catalog.js +248 -42
- package/dist/providers/catalog.js.map +1 -1
- package/dist/providers/tables.d.ts +3 -1
- package/dist/providers/tables.js +9 -4
- package/dist/providers/tables.js.map +1 -1
- package/dist/redact.js +493 -13
- package/dist/redact.js.map +1 -1
- package/dist/runtime.js +52 -28
- package/dist/runtime.js.map +1 -1
- package/dist/sessions/anchor.d.ts +22 -3
- package/dist/sessions/anchor.js +87 -42
- package/dist/sessions/anchor.js.map +1 -1
- package/dist/sessions/background-tasks.d.ts +4 -1
- package/dist/sessions/background-tasks.js +7 -4
- package/dist/sessions/background-tasks.js.map +1 -1
- package/dist/sessions/completions.js +1 -1
- package/dist/sessions/completions.js.map +1 -1
- package/dist/sessions/list.d.ts +8 -4
- package/dist/sessions/list.js +24 -17
- package/dist/sessions/list.js.map +1 -1
- package/dist/sessions/merge.d.ts +70 -7
- package/dist/sessions/merge.js +331 -23
- package/dist/sessions/merge.js.map +1 -1
- package/dist/sessions/pending.d.ts +5 -0
- package/dist/sessions/pending.js +30 -10
- package/dist/sessions/pending.js.map +1 -1
- package/dist/sessions/service.d.ts +57 -3
- package/dist/sessions/service.js +327 -56
- package/dist/sessions/service.js.map +1 -1
- package/dist/sessions/session.d.ts +6 -1
- package/dist/sessions/session.js +6 -0
- package/dist/sessions/session.js.map +1 -1
- package/dist/sessions/shares.js +11 -2
- package/dist/sessions/shares.js.map +1 -1
- package/dist/sessions/store.js +1 -1
- package/dist/sessions/store.js.map +1 -1
- package/dist/sessions/turn.d.ts +19 -1
- package/dist/sessions/turn.js +218 -113
- package/dist/sessions/turn.js.map +1 -1
- package/dist/settings.js +9 -0
- package/dist/settings.js.map +1 -1
- package/dist/sidecar/fake.js +2 -0
- package/dist/sidecar/fake.js.map +1 -1
- package/dist/tools/commands.d.ts +15 -0
- package/dist/tools/commands.js +52 -0
- package/dist/tools/commands.js.map +1 -0
- package/dist/tools/crons.d.ts +4 -1
- package/dist/tools/crons.js +58 -11
- package/dist/tools/crons.js.map +1 -1
- package/dist/tools/mcp.js +5 -1
- package/dist/tools/mcp.js.map +1 -1
- package/dist/tools/update-notifications.d.ts +1 -1
- package/dist/tools/update-notifications.js +1 -1
- package/dist/tools/update-notifications.js.map +1 -1
- package/dist/tools/updates.d.ts +8 -3
- package/dist/tools/updates.js +133 -34
- package/dist/tools/updates.js.map +1 -1
- package/dist/workspace/git.d.ts +57 -10
- package/dist/workspace/git.js +302 -195
- package/dist/workspace/git.js.map +1 -1
- package/dist/workspace/media-refs.d.ts +13 -0
- package/dist/workspace/media-refs.js +165 -0
- package/dist/workspace/media-refs.js.map +1 -0
- package/dist/workspace/media.d.ts +19 -0
- package/dist/workspace/media.js +61 -2
- package/dist/workspace/media.js.map +1 -1
- package/dist/workspace/workspaces.d.ts +7 -1
- package/dist/workspace/workspaces.js +30 -21
- package/dist/workspace/workspaces.js.map +1 -1
- package/dist/workspace/worktrees.d.ts +2 -4
- package/dist/workspace/worktrees.js +28 -33
- package/dist/workspace/worktrees.js.map +1 -1
- package/package.json +4 -2
- package/sidecar/scripts/replay_sidecar.py +3 -1
- package/sidecar/talaria_sidecar/__init__.py +1 -1
- package/sidecar/talaria_sidecar/home.py +59 -2
- package/sidecar/talaria_sidecar/methods/__init__.py +2 -2
- package/sidecar/talaria_sidecar/methods/aux.py +19 -3
- package/sidecar/talaria_sidecar/methods/chat.py +129 -23
- package/sidecar/talaria_sidecar/methods/commands.py +46 -31
- package/sidecar/talaria_sidecar/methods/config.py +14 -10
- package/sidecar/talaria_sidecar/methods/oauth.py +439 -0
- package/sidecar/talaria_sidecar/methods/profiles.py +5 -4
- package/sidecar/talaria_sidecar/methods/providers.py +161 -1
- package/sidecar/talaria_sidecar/methods/runtime.py +2 -0
- package/sidecar/talaria_sidecar/methods/text.py +1 -20
- package/sidecar/talaria_sidecar/methods/usage.py +7 -1
- package/static/dist/FILES.txt +124 -120
- package/static/dist/assets/AppShell-ef3bhu32.js +1 -0
- package/static/dist/assets/Button-nx37f4u1.js +1 -0
- package/static/dist/assets/ChatPage-cdcpykcg.js +25 -0
- package/static/dist/assets/Dialog-mec42hvb.js +1 -0
- package/static/dist/assets/HubRoute-ecb65zpr.js +2 -0
- package/static/dist/assets/{Markdown-dy8t4dy7.js → Markdown-jqrx5es0.js} +125 -125
- package/static/dist/assets/RightPanel-d1lgvk4s.js +1 -0
- package/static/dist/assets/Select-h4ivl9qf.js +1 -0
- package/static/dist/assets/SessionListPanel-ewib046b.js +1 -0
- package/static/dist/assets/SettingsLayout-lx654cup.js +1 -0
- package/static/dist/assets/States-ehsb6lzo.js +1 -0
- package/static/dist/assets/Toaster-mch1pa3t.js +1 -0
- package/static/dist/assets/_app-m8d961ef.js +1 -0
- package/static/dist/assets/_app.ext._extensionId-mp33hbzi.js +1 -0
- package/static/dist/assets/_app.index-dk6zp7e0.js +1 -0
- package/static/dist/assets/_app.insights-jt2fk4i1.js +1 -0
- package/static/dist/assets/_app.kanban-if4pubeu.js +1 -0
- package/static/dist/assets/_app.logs-mfaw9m6g.js +1 -0
- package/static/dist/assets/_app.memory-h3eaarb6.js +1 -0
- package/static/dist/assets/_app.profiles-ienktovs.js +1 -0
- package/static/dist/assets/{_app.session._sessionId-gyoh5ylx.js → _app.session._sessionId-hh27wwu2.js} +1 -1
- package/static/dist/assets/_app.settings-dpoe0bzf.js +1 -0
- package/static/dist/assets/_app.settings._section-l468ynag.js +3 -0
- package/static/dist/assets/_app.skills-kcbncc8i.js +1 -0
- package/static/dist/assets/_app.tasks-occdrqhw.js +2 -0
- package/static/dist/assets/_app.todos-nnke2rcc.js +1 -0
- package/static/dist/assets/_app.workspaces-cdlatvwj.js +1 -0
- package/static/dist/assets/{abnfDiagram-VCTEODGH-cjqletra.js → abnfDiagram-VCTEODGH-oity9y4o.js} +1 -1
- package/static/dist/assets/architecture-7GRP2DOG-hj11333z.js +1 -0
- package/static/dist/assets/architectureDiagram-5GKGNRK7-ceaepnyr.js +36 -0
- package/static/dist/assets/{back-e4m6nsnm.js → back-eu64w89w.js} +1 -1
- package/static/dist/assets/{blockDiagram-I7D4REHJ-b195z021.js → blockDiagram-I7D4REHJ-n79st4pj.js} +1 -1
- package/static/dist/assets/{c4Diagram-7LVT6UL2-olu212k1.js → c4Diagram-7LVT6UL2-mi73akzk.js} +1 -1
- package/static/dist/assets/cancel-mzvkdjg8.js +1 -0
- package/static/dist/assets/channel-mbvmf2vv.js +1 -0
- package/static/dist/assets/{chunk-4HAMMTFA-b8o1nufs.js → chunk-4HAMMTFA-laat0g1q.js} +1 -1
- package/static/dist/assets/{chunk-75Z2AOVW-l1seddto.js → chunk-75Z2AOVW-0psy1tr2.js} +1 -1
- package/static/dist/assets/{chunk-DU6HZSFF-lo5zg15v.js → chunk-DU6HZSFF-lw8uox8x.js} +3 -3
- package/static/dist/assets/{chunk-F27PBJKO-dsdzrp16.js → chunk-F27PBJKO-erassib3.js} +1 -1
- package/static/dist/assets/{chunk-GMAD6QVW-f3fxqq8b.js → chunk-GMAD6QVW-fz7rx619.js} +1 -1
- package/static/dist/assets/{chunk-GVQU2GXP-h8egxtf6.js → chunk-GVQU2GXP-gdb0epb2.js} +1 -1
- package/static/dist/assets/{chunk-IMKFNOWR-iolwd8s0.js → chunk-IMKFNOWR-ea8t26qw.js} +1 -1
- package/static/dist/assets/{chunk-L3NEJ4N5-b88bbtwi.js → chunk-L3NEJ4N5-mb1gu9kz.js} +1 -1
- package/static/dist/assets/{chunk-OSK3NFVY-e3e7nr6s.js → chunk-OSK3NFVY-eovmccvy.js} +1 -1
- package/static/dist/assets/{chunk-P2QGCYS3-mdc46rt1.js → chunk-P2QGCYS3-bo55zjo5.js} +1 -1
- package/static/dist/assets/{chunk-POPQ4Y6H-kqlllrrm.js → chunk-POPQ4Y6H-ja7ohe4h.js} +1 -1
- package/static/dist/assets/{chunk-PWAF6VOD-he585k2x.js → chunk-PWAF6VOD-e30g9nus.js} +1 -1
- package/static/dist/assets/{chunk-SHT3W25Y-gh94y9a4.js → chunk-SHT3W25Y-gbb798f7.js} +3 -3
- package/static/dist/assets/{chunk-SVP7TREG-euxp9y7e.js → chunk-SVP7TREG-h2iw8urm.js} +1 -1
- package/static/dist/assets/{chunk-TICWLB2K-c8cxes1q.js → chunk-TICWLB2K-fd2cottz.js} +1 -1
- package/static/dist/assets/classDiagram-ZZMXUADV-o8r05k0n.js +1 -0
- package/static/dist/assets/classDiagram-v2-VYDZK3BY-o8r05k0n.js +1 -0
- package/static/dist/assets/{copied-kq0u3ht7.js → copied-h65fc3cx.js} +1 -1
- package/static/dist/assets/copy-e6977uwq.js +1 -0
- package/static/dist/assets/{cynefin-OW5HDTMX-lxd44ux4.js → cynefin-OW5HDTMX-lbltyl5j.js} +1 -1
- package/static/dist/assets/{cynefinDiagram-5FMLGOSQ-njpiwat8.js → cynefinDiagram-5FMLGOSQ-lxhsqq4a.js} +1 -1
- package/static/dist/assets/{dagre-GXQ25YYZ-nvgy6yju.js → dagre-GXQ25YYZ-gn4nnaln.js} +4 -4
- package/static/dist/assets/{diagram-S7CK7UJ4-g98nyv72.js → diagram-S7CK7UJ4-pa3ij6q7.js} +3 -3
- package/static/dist/assets/{diagram-UQ7AKVKN-ovgm6lvv.js → diagram-UQ7AKVKN-zbipyz57.js} +1 -1
- package/static/dist/assets/{diagram-VSXAHHWV-pb2bn2e4.js → diagram-VSXAHHWV-d1kbpzgf.js} +1 -1
- package/static/dist/assets/{diagram-VX7I27RA-6j4mvfqo.js → diagram-VX7I27RA-i3ty14xl.js} +1 -1
- package/static/dist/assets/{diagram-Z3DM3KII-dqmb982r.js → diagram-Z3DM3KII-m8xefqa7.js} +1 -1
- package/static/dist/assets/{ebnfDiagram-PWID7BFC-ozbpzb6d.js → ebnfDiagram-PWID7BFC-nz7wj05l.js} +1 -1
- package/static/dist/assets/endpoints-k7yf25m0.js +64 -0
- package/static/dist/assets/{erDiagram-RLTQ6QDP-hl7m8vua.js → erDiagram-RLTQ6QDP-fa41ib83.js} +1 -1
- package/static/dist/assets/eventmodeling-NTZA5JFV-kpbq09bx.js +1 -0
- package/static/dist/assets/flowDiagram-HODETNUW-lcz0kx14.js +1 -0
- package/static/dist/assets/{ganttDiagram-EL5Y4UJY-ompixqmh.js → ganttDiagram-EL5Y4UJY-n7zq01qu.js} +1 -1
- package/static/dist/assets/{gitGraph-4MIJSDKK-b6vxwp9q.js → gitGraph-4MIJSDKK-c89emb07.js} +1 -1
- package/static/dist/assets/{gitGraphDiagram-WWUBYQGX-k98f57on.js → gitGraphDiagram-WWUBYQGX-cz7cgr6w.js} +1 -1
- package/static/dist/assets/{highlighted-body-KPVGNVTW-cd3ff6ge.js → highlighted-body-KPVGNVTW-d9bapmni.js} +1 -1
- package/static/dist/assets/{index-nqed3oum.js → index-h00usru2.js} +3 -3
- package/static/dist/assets/index-n73ijkv2.css +2 -0
- package/static/dist/assets/{info-A6RAGUB7-hjcwjami.js → info-A6RAGUB7-ndddhhhh.js} +1 -1
- package/static/dist/assets/infoDiagram-27XIBGKW-ccxigcpf.js +2 -0
- package/static/dist/assets/{ishikawaDiagram-5VMMS53U-bxak4mwu.js → ishikawaDiagram-5VMMS53U-le0z9vtc.js} +1 -1
- package/static/dist/assets/{journeyDiagram-3NMN7TZE-khmihclr.js → journeyDiagram-3NMN7TZE-ivsmb26o.js} +1 -1
- package/static/dist/assets/{kanban-definition-UXKFOSKX-h1r32wdx.js → kanban-definition-UXKFOSKX-h6n2awt0.js} +1 -1
- package/static/dist/assets/lazyRouteComponent-m1rtyk4t.js +1 -0
- package/static/dist/assets/{line-friyjof3.js → line-dmzlfe0u.js} +1 -1
- package/static/dist/assets/link-budeg5t9.js +1 -0
- package/static/dist/assets/login-kjhasvp8.js +1 -0
- package/static/dist/assets/mermaid-HWGCJPDP-jb5d211j.js +1 -0
- package/static/dist/assets/{mermaid-parser.core-f1gvpwrt.js → mermaid-parser.core-gwyd5bnq.js} +3 -3
- package/static/dist/assets/{mindmap-definition-YA3MSWOX-mt2oxwue.js → mindmap-definition-YA3MSWOX-l68gg5h7.js} +1 -1
- package/static/dist/assets/onboarding-cdfrk0pj.js +1 -0
- package/static/dist/assets/{packet-AYTQ26CC-jik4ixlf.js → packet-AYTQ26CC-gpv06065.js} +1 -1
- package/static/dist/assets/{pegDiagram-XKGWAZYB-erxlv6cc.js → pegDiagram-XKGWAZYB-e52vs23u.js} +1 -1
- package/static/dist/assets/{pie-WAS4IAKB-mnkoldfl.js → pie-WAS4IAKB-l6m7nz5s.js} +1 -1
- package/static/dist/assets/{pieDiagram-E7YTZNPT-i7lwrada.js → pieDiagram-E7YTZNPT-b4is36bq.js} +3 -3
- package/static/dist/assets/{quadrantDiagram-AXDQQJYC-fr8ejdoy.js → quadrantDiagram-AXDQQJYC-m8vt2788.js} +1 -1
- package/static/dist/assets/{radar-RG4KPBEZ-otarjte2.js → radar-RG4KPBEZ-nxbrhiov.js} +1 -1
- package/static/dist/assets/{railroad-74A4TZTK-lw362oto.js → railroad-74A4TZTK-222mu9hi.js} +1 -1
- package/static/dist/assets/railroad-abnf-HS5TGJTU-kdvgl6x8.js +1 -0
- package/static/dist/assets/railroad-ebnf-LZEXJU2U-itiqslby.js +1 -0
- package/static/dist/assets/railroad-peg-WCYAUIDC-go7kov78.js +1 -0
- package/static/dist/assets/{railroadDiagram-O6MQD6OU-esyn75pw.js → railroadDiagram-O6MQD6OU-o8lldfzv.js} +1 -1
- package/static/dist/assets/{refresh-cw-k66keho6.js → refresh-cw-kbcje1uy.js} +1 -1
- package/static/dist/assets/{requirementDiagram-BXWQKSXE-cyhi5u29.js → requirementDiagram-BXWQKSXE-ovyq38kv.js} +1 -1
- package/static/dist/assets/{sankeyDiagram-P5KCCOFB-jljpbo0h.js → sankeyDiagram-P5KCCOFB-ou7lznor.js} +1 -1
- package/static/dist/assets/{saved-do49si3v.js → saved-bazmcup9.js} +1 -1
- package/static/dist/assets/search-jen74z4u.js +1 -0
- package/static/dist/assets/{sequenceDiagram-WJ2MYXX4-fz0dhlu7.js → sequenceDiagram-WJ2MYXX4-ovckdzf2.js} +1 -1
- package/static/dist/assets/{settings_section_extensions_title-b7lojn0o.js → settings_section_extensions_title-ertwwhlx.js} +1 -1
- package/static/dist/assets/share._token-dan9hgvj.js +2 -0
- package/static/dist/assets/{sliders-horizontal-c4wya4dy.js → sliders-horizontal-f9cb3lh3.js} +1 -1
- package/static/dist/assets/{stateDiagram-D77RDMKH-kdnithdx.js → stateDiagram-D77RDMKH-fcrexkkv.js} +1 -1
- package/static/dist/assets/stateDiagram-v2-MP3YSRHH-lcfraua2.js +1 -0
- package/static/dist/assets/{swimlanes-42K2YHIH-esd6gmz3.js → swimlanes-42K2YHIH-f7usu8fw.js} +1 -1
- package/static/dist/assets/swimlanesDiagram-VR7AAH4N-ogmanni0.js +8 -0
- package/static/dist/assets/{timeline-definition-24CTP7MA-g0qygccv.js → timeline-definition-24CTP7MA-gp1hvz9f.js} +1 -1
- package/static/dist/assets/todoStore-eqtid4r4.js +1 -0
- package/static/dist/assets/{treeView-Q6P3EWNA-ndchzkuu.js → treeView-Q6P3EWNA-gb9gf11u.js} +1 -1
- package/static/dist/assets/{treemap-WGGIJYW6-hwjxj0zz.js → treemap-WGGIJYW6-nuvfnvvi.js} +1 -1
- package/static/dist/assets/{untitled-mbr6tuhu.js → untitled-htelhc68.js} +1 -1
- package/static/dist/assets/useForm-h2t0u14e.js +1 -0
- package/static/dist/assets/useLocale-hcsb84pj.js +1 -0
- package/static/dist/assets/useNavigate-nwy70ztj.js +1 -0
- package/static/dist/assets/{useParams-lo9u33d1.js → useParams-dqd64jv7.js} +1 -1
- package/static/dist/assets/{useSearch-lq1mr090.js → useSearch-j30pvsy7.js} +1 -1
- package/static/dist/assets/{vennDiagram-4TSXK5OY-gubovd1r.js → vennDiagram-4TSXK5OY-fzchbzaj.js} +1 -1
- package/static/dist/assets/{wardley-WFR3VGLG-ir3om65j.js → wardley-WFR3VGLG-m47mhfbh.js} +1 -1
- package/static/dist/assets/{wardleyDiagram-VM6X3IG4-ce0or1ie.js → wardleyDiagram-VM6X3IG4-odg6ct1z.js} +2 -2
- package/static/dist/assets/{xychartDiagram-S5SC5T6Z-dexylcjg.js → xychartDiagram-S5SC5T6Z-mrhms5um.js} +1 -1
- package/static/dist/index.html +1 -1
- package/static/dist/sw.js +1 -1
- package/static/dist/assets/AppShell-orat1s43.js +0 -1
- package/static/dist/assets/ChatPage-ojhka3hy.js +0 -22
- package/static/dist/assets/HubRoute-gxgw1t33.js +0 -2
- package/static/dist/assets/RightPanel-c66ani1s.js +0 -1
- package/static/dist/assets/Select-fswf66up.js +0 -1
- package/static/dist/assets/SessionListPanel-goh5mtt8.js +0 -1
- package/static/dist/assets/SettingsLayout-n5d4wq4m.js +0 -1
- package/static/dist/assets/States-kxyu50at.js +0 -1
- package/static/dist/assets/Toaster-6zmbcqgg.js +0 -1
- package/static/dist/assets/_app-fowyruiu.js +0 -1
- package/static/dist/assets/_app.ext._extensionId-nvjyrwhy.js +0 -1
- package/static/dist/assets/_app.index-c9zv4y7w.js +0 -1
- package/static/dist/assets/_app.insights-jf12nofo.js +0 -1
- package/static/dist/assets/_app.kanban-lri5a4yu.js +0 -1
- package/static/dist/assets/_app.logs-md1p0zqo.js +0 -1
- package/static/dist/assets/_app.memory-bzvf2e28.js +0 -1
- package/static/dist/assets/_app.profiles-jpg7zmbn.js +0 -1
- package/static/dist/assets/_app.settings-mpuwlx4j.js +0 -1
- package/static/dist/assets/_app.settings._section-knz8rwoj.js +0 -1
- package/static/dist/assets/_app.skills-fwu1dkir.js +0 -1
- package/static/dist/assets/_app.tasks-h9gphtl3.js +0 -2
- package/static/dist/assets/_app.todos-hd1dnvrh.js +0 -1
- package/static/dist/assets/_app.workspaces-l8toyn5f.js +0 -1
- package/static/dist/assets/architecture-7GRP2DOG-cavnusaw.js +0 -1
- package/static/dist/assets/architectureDiagram-5GKGNRK7-k5a7v36n.js +0 -36
- package/static/dist/assets/channel-gozy3dp3.js +0 -1
- package/static/dist/assets/classDiagram-ZZMXUADV-n0vs2f2q.js +0 -1
- package/static/dist/assets/classDiagram-v2-VYDZK3BY-n0vs2f2q.js +0 -1
- package/static/dist/assets/endpoints-k8agnro8.js +0 -9
- package/static/dist/assets/eventmodeling-NTZA5JFV-j1y2ekec.js +0 -1
- package/static/dist/assets/flowDiagram-HODETNUW-g2cvcbm5.js +0 -1
- package/static/dist/assets/index-nfy0ezs6.css +0 -2
- package/static/dist/assets/infoDiagram-27XIBGKW-fm06rj36.js +0 -2
- package/static/dist/assets/lazyRouteComponent-b2eg0fws.js +0 -1
- package/static/dist/assets/link-m90ahx3n.js +0 -1
- package/static/dist/assets/login-bw7m2fzo.js +0 -1
- package/static/dist/assets/mermaid-HWGCJPDP-njwcl62n.js +0 -1
- package/static/dist/assets/onboarding-ret37j1e.js +0 -1
- package/static/dist/assets/railroad-abnf-HS5TGJTU-m741owar.js +0 -1
- package/static/dist/assets/railroad-ebnf-LZEXJU2U-noa4fbia.js +0 -1
- package/static/dist/assets/railroad-peg-WCYAUIDC-o4bpw4nb.js +0 -1
- package/static/dist/assets/search-j5ki6a9o.js +0 -1
- package/static/dist/assets/share._token-kg8w647b.js +0 -2
- package/static/dist/assets/stateDiagram-v2-MP3YSRHH-k2wg2645.js +0 -1
- package/static/dist/assets/swimlanesDiagram-VR7AAH4N-n5kvjtgr.js +0 -8
- package/static/dist/assets/tabBuild-bjmyvmn5.js +0 -56
- package/static/dist/assets/todoStore-kjk5l0sy.js +0 -1
- package/static/dist/assets/useForm-ocxu460f.js +0 -1
- package/static/dist/assets/useLocale-fzy5jhg6.js +0 -1
|
@@ -14,12 +14,19 @@ fall through to another profile's process environment. Agent 0.21.3 has the
|
|
|
14
14
|
multiplex switch and secret scopes but not the launch-profile policy module, so
|
|
15
15
|
the sidecar mirrors that policy for it. If the installed Agent has no secret
|
|
16
16
|
scope, named-profile calls fail closed instead.
|
|
17
|
+
|
|
18
|
+
Terminal policy follows the same split. Under a home override the Agent skips its
|
|
19
|
+
config-to-env terminal bridge, so every call also binds the profile's complete
|
|
20
|
+
``TERMINAL_*`` scope from its own ``.env`` and ``config.yaml``; the launch profile layers
|
|
21
|
+
its launch-process ``TERMINAL_*`` under those files.
|
|
17
22
|
"""
|
|
18
23
|
|
|
19
24
|
from __future__ import annotations
|
|
20
25
|
|
|
21
26
|
import contextlib
|
|
27
|
+
import importlib
|
|
22
28
|
import os
|
|
29
|
+
import sys
|
|
23
30
|
import threading
|
|
24
31
|
from pathlib import Path
|
|
25
32
|
|
|
@@ -47,6 +54,24 @@ def _frozen_launch_env() -> dict[str, str]:
|
|
|
47
54
|
return dict(_LAUNCH_ENV)
|
|
48
55
|
|
|
49
56
|
|
|
57
|
+
def edit_launch_env(to_set: dict[str, str], to_unset: list[str]) -> None:
|
|
58
|
+
"""Carry a Web-owned ``.env`` edit into the frozen launch environments, so a removed credential stops resolving for the launch profile."""
|
|
59
|
+
|
|
60
|
+
def edit(snapshot: dict[str, str] | None) -> None:
|
|
61
|
+
if snapshot is not None:
|
|
62
|
+
for name in to_unset:
|
|
63
|
+
snapshot.pop(name, None)
|
|
64
|
+
snapshot.update(to_set)
|
|
65
|
+
|
|
66
|
+
with _LAUNCH_ENV_LOCK:
|
|
67
|
+
edit(_LAUNCH_ENV)
|
|
68
|
+
# Only an imported policy module can hold a frozen snapshot; importing it waits out a first import still running elsewhere.
|
|
69
|
+
if sys.modules.get("tui_gateway.launch_profile_policy") is not None:
|
|
70
|
+
policy = importlib.import_module("tui_gateway.launch_profile_policy")
|
|
71
|
+
with policy._lock:
|
|
72
|
+
edit(policy._snapshot)
|
|
73
|
+
|
|
74
|
+
|
|
50
75
|
def _activate_multi_profile_hosting() -> None:
|
|
51
76
|
"""Agent 0.21.3 twin of ``tui_gateway.launch_profile_policy.activate_multi_profile_hosting``."""
|
|
52
77
|
from agent.secret_scope import set_multiplex_active
|
|
@@ -99,6 +124,38 @@ def _secret_scope(home: Path):
|
|
|
99
124
|
reset_secret_scope(scope_token)
|
|
100
125
|
|
|
101
126
|
|
|
127
|
+
@contextlib.contextmanager
|
|
128
|
+
def _terminal_scope(home: Path):
|
|
129
|
+
"""Install ``home``'s terminal policy for the call; a policy file that cannot be read refuses terminal execution."""
|
|
130
|
+
named = _is_named_profile(home)
|
|
131
|
+
try:
|
|
132
|
+
from tools.terminal_scope import install_profile_terminal_scope, reset_terminal_scope
|
|
133
|
+
except Exception: # noqa: BLE001 - older Agent without terminal scopes
|
|
134
|
+
if named:
|
|
135
|
+
raise RpcError(
|
|
136
|
+
"profile terminal isolation is unavailable in this Hermes Agent; named-profile calls are refused",
|
|
137
|
+
condition="agent_incompatible",
|
|
138
|
+
)
|
|
139
|
+
yield
|
|
140
|
+
return
|
|
141
|
+
if named:
|
|
142
|
+
token = install_profile_terminal_scope(home)
|
|
143
|
+
else:
|
|
144
|
+
try:
|
|
145
|
+
from agent.secret_scope import is_multiplex_active
|
|
146
|
+
from tui_gateway.launch_profile_policy import launch_terminal_env
|
|
147
|
+
except ImportError: # Agent 0.21.3 cannot layer the launch env, so the launch profile keeps the process env
|
|
148
|
+
yield
|
|
149
|
+
return
|
|
150
|
+
# Like the launch secret scope: the live process env until multiplexing freezes it.
|
|
151
|
+
launch = launch_terminal_env() if is_multiplex_active() else {k: v for k, v in os.environ.items() if k.startswith("TERMINAL_")}
|
|
152
|
+
token = install_profile_terminal_scope(home, env_overlay=launch)
|
|
153
|
+
try:
|
|
154
|
+
yield
|
|
155
|
+
finally:
|
|
156
|
+
reset_terminal_scope(token)
|
|
157
|
+
|
|
158
|
+
|
|
102
159
|
def profile_home_param(params: dict, key: str = "profile_home") -> Path:
|
|
103
160
|
raw = params.get(key)
|
|
104
161
|
if not isinstance(raw, str) or not raw.strip():
|
|
@@ -117,7 +174,7 @@ def scoped_home(home: Path):
|
|
|
117
174
|
if set_hermes_home_override is not None:
|
|
118
175
|
token = set_hermes_home_override(home)
|
|
119
176
|
try:
|
|
120
|
-
with _secret_scope(home):
|
|
177
|
+
with _secret_scope(home), _terminal_scope(home):
|
|
121
178
|
yield home
|
|
122
179
|
finally:
|
|
123
180
|
reset_hermes_home_override(token)
|
|
@@ -126,7 +183,7 @@ def scoped_home(home: Path):
|
|
|
126
183
|
previous = os.environ.get("HERMES_HOME")
|
|
127
184
|
os.environ["HERMES_HOME"] = str(home)
|
|
128
185
|
try:
|
|
129
|
-
with _secret_scope(home):
|
|
186
|
+
with _secret_scope(home), _terminal_scope(home):
|
|
130
187
|
yield home
|
|
131
188
|
finally:
|
|
132
189
|
if previous is None:
|
|
@@ -29,9 +29,9 @@ class Registry:
|
|
|
29
29
|
|
|
30
30
|
def build_methods(runtime: AgentRuntime) -> dict[str, Handler]:
|
|
31
31
|
registry = Registry(runtime)
|
|
32
|
-
from . import aux, chat, commands, config, cron, gateway, goals, kanban, mcp, process, profiles, providers, skills, state_db, stt, text, usage, worktree # noqa: WPS433
|
|
32
|
+
from . import aux, chat, commands, config, cron, gateway, goals, kanban, mcp, oauth, process, profiles, providers, skills, state_db, stt, text, usage, worktree # noqa: WPS433
|
|
33
33
|
from . import runtime as runtime_methods
|
|
34
34
|
|
|
35
|
-
for module in (runtime_methods, goals, commands, kanban, state_db, profiles, skills, mcp, stt, cron, providers, aux, text, process, usage, gateway, worktree, chat, config):
|
|
35
|
+
for module in (runtime_methods, goals, commands, kanban, state_db, profiles, skills, mcp, stt, cron, providers, oauth, aux, text, process, usage, gateway, worktree, chat, config):
|
|
36
36
|
module.register(registry)
|
|
37
37
|
return registry.methods
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import contextlib
|
|
5
6
|
import logging
|
|
6
7
|
import threading
|
|
7
8
|
import uuid
|
|
@@ -39,8 +40,10 @@ def resolve_main_runtime(hint: dict | None) -> dict | None:
|
|
|
39
40
|
|
|
40
41
|
|
|
41
42
|
def _main_model_completion(messages: list, runtime: dict, *, task: str) -> dict:
|
|
42
|
-
"""Predecessor fallback: run the main model through ``AIAgent`` with no tools when no auxiliary client answers.
|
|
43
|
-
|
|
43
|
+
"""Predecessor fallback: run the main model through ``AIAgent`` with no tools when no auxiliary client answers.
|
|
44
|
+
|
|
45
|
+
The throwaway agent never touches long-term memory (the prompt is a raw git diff) and is always closed."""
|
|
46
|
+
from .chat import _agent_class, _supported
|
|
44
47
|
|
|
45
48
|
AIAgent = _agent_class()
|
|
46
49
|
|
|
@@ -51,8 +54,21 @@ def _main_model_completion(messages: list, runtime: dict, *, task: str) -> dict:
|
|
|
51
54
|
for name in ("api_mode", "acp_command", "acp_args", "credential_pool"):
|
|
52
55
|
if runtime.get(name) is not None:
|
|
53
56
|
kwargs[name] = runtime[name]
|
|
57
|
+
for name in ("skip_memory", "skip_background_review"):
|
|
58
|
+
if _supported(AIAgent, name):
|
|
59
|
+
kwargs[name] = True
|
|
54
60
|
agent = AIAgent(**kwargs)
|
|
55
|
-
|
|
61
|
+
try:
|
|
62
|
+
result = agent.run_conversation(user_message=user, system_message=system, conversation_history=[], task_id=kwargs["session_id"])
|
|
63
|
+
finally:
|
|
64
|
+
with contextlib.suppress(Exception):
|
|
65
|
+
agent._end_session_on_close = False
|
|
66
|
+
close = getattr(agent, "close", None)
|
|
67
|
+
if callable(close):
|
|
68
|
+
try:
|
|
69
|
+
close()
|
|
70
|
+
except Exception: # noqa: BLE001
|
|
71
|
+
log.debug("%s fallback agent close failed", task, exc_info=True)
|
|
56
72
|
return {"model": str(runtime.get("model") or ""), "text": str((result or {}).get("final_response") or "").strip(), "usage": None}
|
|
57
73
|
|
|
58
74
|
|
|
@@ -11,6 +11,7 @@ through ``approval.respond`` / ``clarify.respond``; ``rpc.cancel`` or
|
|
|
11
11
|
from __future__ import annotations
|
|
12
12
|
|
|
13
13
|
import contextlib
|
|
14
|
+
import contextvars
|
|
14
15
|
import hashlib
|
|
15
16
|
import inspect
|
|
16
17
|
import json
|
|
@@ -372,7 +373,7 @@ def _resolve_runtime(provider: str | None, model: str) -> dict:
|
|
|
372
373
|
def _turn_identity(session_id: str, workspace: str):
|
|
373
374
|
"""Bind this turn's identity to the calling context the way the predecessor's ``_set_turn_session_identity`` did:
|
|
374
375
|
the approval session key (so ``register_gateway_notify`` cards reach this turn and dangerous commands are gated
|
|
375
|
-
instead of auto-approved), the gateway session vars (platform ``webui``, chat/ui session ids), and the session cwd
|
|
376
|
+
instead of auto-approved), the gateway session vars (platform ``webui``, chat/ui session ids, profile), and the session cwd
|
|
376
377
|
(so terminals and AGENTS.md discovery run in the selected workspace, not the sidecar's launch directory). Every
|
|
377
378
|
binding is a context variable, so concurrent turns cannot overwrite each other. Missing Agent surfaces are logged,
|
|
378
379
|
not fatal."""
|
|
@@ -388,10 +389,14 @@ def _turn_identity(session_id: str, workspace: str):
|
|
|
388
389
|
log.debug("per-turn approval session-key bind failed", exc_info=True)
|
|
389
390
|
try:
|
|
390
391
|
from gateway import session_context as sc
|
|
392
|
+
from hermes_cli.profiles import get_active_profile_name
|
|
393
|
+
from hermes_constants import get_hermes_home, profile_name_for_home
|
|
391
394
|
|
|
395
|
+
# The persistent Docker sandbox is keyed by the profile name; unbound, every profile reuses "default".
|
|
396
|
+
profile = profile_name_for_home(get_hermes_home()) or get_active_profile_name()
|
|
392
397
|
pairs = [
|
|
393
398
|
(sc._SESSION_KEY, session_id), (sc._SESSION_UI_SESSION_ID, session_id), (sc._SESSION_PLATFORM, "webui"),
|
|
394
|
-
(sc._SESSION_CHAT_ID, session_id), (sc._SESSION_ID, session_id),
|
|
399
|
+
(sc._SESSION_CHAT_ID, session_id), (sc._SESSION_ID, session_id), (sc._SESSION_PROFILE, profile),
|
|
395
400
|
]
|
|
396
401
|
for var, value in pairs:
|
|
397
402
|
tok = var.set(value)
|
|
@@ -415,6 +420,63 @@ def _turn_identity(session_id: str, workspace: str):
|
|
|
415
420
|
log.debug("per-turn identity reset failed", exc_info=True)
|
|
416
421
|
|
|
417
422
|
|
|
423
|
+
#: Older configs named the CLI composite ``hermes``; the Agent registers it split in two (predecessor
|
|
424
|
+
#: ``_LEGACY_CLI_TOOLSET_ALIASES``).
|
|
425
|
+
_LEGACY_TOOLSET_ALIASES = {"hermes": ("hermes-cli", "hermes-api-server")}
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
def _turn_toolsets(toolsets) -> list[str]:
|
|
429
|
+
"""The session's override as sent, else the profile's configured toolsets. ``None`` would hand the Agent every
|
|
430
|
+
registered toolset."""
|
|
431
|
+
return toolsets if isinstance(toolsets, list) else _profile_toolsets()
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
def _profile_toolsets() -> list[str]:
|
|
435
|
+
"""The profile's ``platform_toolsets.cli`` through the Agent's own resolver (default-off toolsets stay off), like
|
|
436
|
+
``hermes chat``. Runs under the call's ``scoped_home``."""
|
|
437
|
+
from hermes_cli.config import load_config
|
|
438
|
+
from hermes_cli.tools_config import _get_platform_tools
|
|
439
|
+
|
|
440
|
+
resolved = sorted(_get_platform_tools(load_config() or {}, "cli"))
|
|
441
|
+
return list(dict.fromkeys(name for raw in resolved for name in _LEGACY_TOOLSET_ALIASES.get(raw, (raw,))))
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
def _discover_mcp_tools(run: _Run) -> None:
|
|
445
|
+
"""Connect the profile's MCP servers before the turn's agent snapshots its tools, like the predecessor's turn start.
|
|
446
|
+
The Agent keys connections by profile scope and skips live ones, so later turns are cheap. Runs under the call's
|
|
447
|
+
``scoped_home``; a failure leaves the turn without MCP tools rather than failing it. A Stop does not wait for a slow
|
|
448
|
+
server: the turn moves on to its cancelled end while the connect finishes in the background."""
|
|
449
|
+
from .commands import retire_unscoped_launch_mcp_servers
|
|
450
|
+
|
|
451
|
+
done = threading.Event()
|
|
452
|
+
|
|
453
|
+
def discover() -> None:
|
|
454
|
+
try:
|
|
455
|
+
from tools.mcp_tool_discovery import discover_mcp_tools
|
|
456
|
+
|
|
457
|
+
retire_unscoped_launch_mcp_servers()
|
|
458
|
+
discover_mcp_tools()
|
|
459
|
+
except Exception: # noqa: BLE001
|
|
460
|
+
log.warning("MCP discovery failed", exc_info=True)
|
|
461
|
+
finally:
|
|
462
|
+
done.set()
|
|
463
|
+
|
|
464
|
+
# The copied context carries the turn's home override and secret scope into the worker.
|
|
465
|
+
threading.Thread(target=contextvars.copy_context().run, args=(discover,), daemon=True, name=f"chat-mcp-{run.stream_id[:8]}").start()
|
|
466
|
+
while not done.wait(0.25):
|
|
467
|
+
if run.cancel.is_set() or run.ctx.cancelled:
|
|
468
|
+
return
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
def _profile_fallback_chain() -> list[dict] | None:
|
|
472
|
+
"""The profile's fallback routes (``fallback_providers`` first, then legacy ``fallback_model``, deduplicated)
|
|
473
|
+
through the Agent's own resolver, like the CLI and gateway. Runs under the call's ``scoped_home``."""
|
|
474
|
+
from hermes_cli.config import load_config
|
|
475
|
+
from hermes_cli.fallback_config import get_fallback_chain
|
|
476
|
+
|
|
477
|
+
return get_fallback_chain(load_config() or {}) or None
|
|
478
|
+
|
|
479
|
+
|
|
418
480
|
def _agent_signature(model: str, provider, runtime: dict, toolsets, home: str, kwargs: dict) -> str:
|
|
419
481
|
"""Cache identity of an ``AIAgent``: everything its constructor bound from the resolved runtime, so a rotated key,
|
|
420
482
|
a different API mode, ACP command, or credential pool never reuses an agent built for the old bundle. The key
|
|
@@ -430,6 +492,8 @@ def _agent_signature(model: str, provider, runtime: dict, toolsets, home: str, k
|
|
|
430
492
|
"max_iterations": kwargs.get("max_iterations"), "max_tokens": kwargs.get("max_tokens"),
|
|
431
493
|
# Bound at construction too: a reasoning-effort change from the composer must build a fresh agent.
|
|
432
494
|
"reasoning_config": kwargs.get("reasoning_config"),
|
|
495
|
+
# Entries may carry their own ``api_key``.
|
|
496
|
+
"fallback_model": hashlib.sha256(json.dumps(kwargs.get("fallback_model"), sort_keys=True, default=str).encode("utf-8")).hexdigest()[:16],
|
|
433
497
|
}
|
|
434
498
|
return json.dumps(bundle, sort_keys=True, default=str)
|
|
435
499
|
|
|
@@ -472,6 +536,34 @@ def _supported(cls, name: str) -> bool:
|
|
|
472
536
|
return name in parameters or any(p.kind is inspect.Parameter.VAR_KEYWORD for p in parameters.values())
|
|
473
537
|
|
|
474
538
|
|
|
539
|
+
def _approval_notifier(session_id: str, emit):
|
|
540
|
+
"""The Agent's gateway notify callback for one turn: emits each parked approval, then ``approval_resolved``
|
|
541
|
+
(id plus the Agent's reason) once its wait ends by any path, an ``approvals.timeout`` expiry included (TAL-514)."""
|
|
542
|
+
try:
|
|
543
|
+
from tools.approval import register_gateway_settle
|
|
544
|
+
except Exception: # noqa: BLE001
|
|
545
|
+
register_gateway_settle = None
|
|
546
|
+
|
|
547
|
+
def notify(data):
|
|
548
|
+
payload = dict(data or {})
|
|
549
|
+
payload.setdefault("session_id", session_id)
|
|
550
|
+
payload.setdefault("approval_id", str(payload.get("request_id") or uuid.uuid4().hex))
|
|
551
|
+
emit("approval", payload)
|
|
552
|
+
request_id = str(payload.get("request_id") or "")
|
|
553
|
+
if register_gateway_settle is None or not request_id:
|
|
554
|
+
return
|
|
555
|
+
approval_id = payload["approval_id"]
|
|
556
|
+
|
|
557
|
+
def settle(reason):
|
|
558
|
+
emit("approval_resolved", {"approval_id": approval_id, "session_id": session_id, "reason": str(reason or "")})
|
|
559
|
+
|
|
560
|
+
# False: the wait already ended between the emit and this registration.
|
|
561
|
+
if not register_gateway_settle(session_id, request_id, settle):
|
|
562
|
+
settle("resolved")
|
|
563
|
+
|
|
564
|
+
return notify
|
|
565
|
+
|
|
566
|
+
|
|
475
567
|
def start(ctx: CallContext, params: dict) -> dict: # noqa: PLR0915 - one turn, one function
|
|
476
568
|
session_id = str(params.get("session_id") or "").strip()
|
|
477
569
|
stream_id = str(params.get("stream_id") or "").strip()
|
|
@@ -487,7 +579,7 @@ def start(ctx: CallContext, params: dict) -> dict: # noqa: PLR0915 - one turn,
|
|
|
487
579
|
history = []
|
|
488
580
|
if not isinstance(history, list):
|
|
489
581
|
raise InvalidParams("conversation_history must be a list")
|
|
490
|
-
toolsets = params.get("enabled_toolsets")
|
|
582
|
+
toolsets = _turn_toolsets(params.get("enabled_toolsets"))
|
|
491
583
|
system_message = params.get("system_message")
|
|
492
584
|
run = _Run(stream_id, session_id, ctx)
|
|
493
585
|
with _RUNS_LOCK:
|
|
@@ -510,6 +602,7 @@ def start(ctx: CallContext, params: dict) -> dict: # noqa: PLR0915 - one turn,
|
|
|
510
602
|
raw_emit("steer_pending", {"text": pending})
|
|
511
603
|
raw_emit(event, data)
|
|
512
604
|
try:
|
|
605
|
+
_discover_mcp_tools(run)
|
|
513
606
|
runtime = _resolve_runtime(provider, model)
|
|
514
607
|
resolved_model = model or str(runtime.get("model") or "")
|
|
515
608
|
resolved_provider = provider or runtime.get("provider")
|
|
@@ -626,15 +719,7 @@ def start(ctx: CallContext, params: dict) -> dict: # noqa: PLR0915 - one turn,
|
|
|
626
719
|
from tools.approval import register_gateway_notify, unregister_gateway_notify
|
|
627
720
|
except Exception: # noqa: BLE001
|
|
628
721
|
register_gateway_notify = unregister_gateway_notify = None
|
|
629
|
-
if register_gateway_notify is not None
|
|
630
|
-
def _approval_cb(data):
|
|
631
|
-
payload = dict(data or {})
|
|
632
|
-
payload.setdefault("session_id", session_id)
|
|
633
|
-
payload.setdefault("approval_id", str(payload.get("request_id") or uuid.uuid4().hex))
|
|
634
|
-
emit("approval", payload)
|
|
635
|
-
approval_cb = _approval_cb
|
|
636
|
-
else:
|
|
637
|
-
approval_cb = None
|
|
722
|
+
approval_cb = _approval_notifier(session_id, emit) if register_gateway_notify is not None else None
|
|
638
723
|
|
|
639
724
|
kwargs: dict = dict(
|
|
640
725
|
model=resolved_model,
|
|
@@ -643,7 +728,7 @@ def start(ctx: CallContext, params: dict) -> dict: # noqa: PLR0915 - one turn,
|
|
|
643
728
|
api_key=runtime.get("api_key"),
|
|
644
729
|
platform="webui",
|
|
645
730
|
quiet_mode=True,
|
|
646
|
-
enabled_toolsets=toolsets
|
|
731
|
+
enabled_toolsets=toolsets,
|
|
647
732
|
session_id=session_id,
|
|
648
733
|
stream_delta_callback=on_token,
|
|
649
734
|
reasoning_callback=on_reasoning,
|
|
@@ -671,6 +756,9 @@ def start(ctx: CallContext, params: dict) -> dict: # noqa: PLR0915 - one turn,
|
|
|
671
756
|
reasoning_config = params.get("reasoning_config")
|
|
672
757
|
if isinstance(reasoning_config, dict) and _supported(AIAgent, "reasoning_config"):
|
|
673
758
|
kwargs["reasoning_config"] = reasoning_config
|
|
759
|
+
fallback_chain = _profile_fallback_chain()
|
|
760
|
+
if fallback_chain and _supported(AIAgent, "fallback_model"):
|
|
761
|
+
kwargs["fallback_model"] = fallback_chain
|
|
674
762
|
signature = _agent_signature(resolved_model, resolved_provider, runtime, toolsets, str(params.get("profile_home")), kwargs)
|
|
675
763
|
agent = None
|
|
676
764
|
if not session_busy:
|
|
@@ -772,14 +860,22 @@ def start(ctx: CallContext, params: dict) -> dict: # noqa: PLR0915 - one turn,
|
|
|
772
860
|
error = str(last_error)
|
|
773
861
|
if not error and isinstance(result.get("error"), str) and result.get("error"):
|
|
774
862
|
error = str(result["error"])
|
|
775
|
-
|
|
863
|
+
# The Agent ends a failed turn with ``failed``/``partial`` (never ``status``), often after text streamed and with
|
|
864
|
+
# the turn's messages; a failed turn is an error whatever it carries.
|
|
865
|
+
failed = bool(result.get("failed"))
|
|
866
|
+
partial = bool(result.get("partial"))
|
|
867
|
+
if not error and failed and result.get("final_response"):
|
|
868
|
+
error = str(result["final_response"])
|
|
869
|
+
status = "cancelled" if cancelled else ("error" if failed or (error and not result.get("messages")) else "completed")
|
|
776
870
|
pending_steer = str(result.get("pending_steer") or "") if isinstance(result, dict) else ""
|
|
777
871
|
return {
|
|
778
872
|
"status": status,
|
|
779
873
|
"messages": [m for m in (result.get("messages") or []) if isinstance(m, dict)],
|
|
780
874
|
"final_response": str(result.get("final_response") or ""),
|
|
781
875
|
"error": error,
|
|
782
|
-
"
|
|
876
|
+
"failed": failed,
|
|
877
|
+
"partial": partial,
|
|
878
|
+
"compression_exhausted": bool(result.get("compression_exhausted")),
|
|
783
879
|
"tool_limit_reached": bool(result.get("tool_limit_reached") or result.get("max_iterations_reached")),
|
|
784
880
|
"usage": _usage(agent),
|
|
785
881
|
"context": _context_length(agent),
|
|
@@ -861,7 +957,7 @@ def compress(ctx: CallContext, params: dict) -> dict:
|
|
|
861
957
|
model = str(params.get("model") or "").strip()
|
|
862
958
|
provider = str(params.get("model_provider") or "").strip() or None
|
|
863
959
|
focus_topic = str(params.get("focus_topic") or "").strip()[:500] or None
|
|
864
|
-
toolsets = params.get("enabled_toolsets")
|
|
960
|
+
toolsets = _turn_toolsets(params.get("enabled_toolsets"))
|
|
865
961
|
runtime = _resolve_runtime(provider, model)
|
|
866
962
|
if not runtime.get("api_key"):
|
|
867
963
|
raise RpcError("No provider configured -- cannot compress.", condition="credential_missing")
|
|
@@ -875,7 +971,7 @@ def compress(ctx: CallContext, params: dict) -> dict:
|
|
|
875
971
|
api_key=runtime.get("api_key"),
|
|
876
972
|
platform="webui",
|
|
877
973
|
quiet_mode=True,
|
|
878
|
-
enabled_toolsets=toolsets
|
|
974
|
+
enabled_toolsets=toolsets,
|
|
879
975
|
session_id=session_id,
|
|
880
976
|
)
|
|
881
977
|
for name, value in (
|
|
@@ -1017,14 +1113,22 @@ def register(registry) -> None:
|
|
|
1017
1113
|
|
|
1018
1114
|
@registry.method("chat.evict_agent", requires_agent=False)
|
|
1019
1115
|
def evict_(ctx: CallContext, params: dict) -> dict:
|
|
1116
|
+
"""Drop a session's cached agent. Only delete/clear (``clear_session``) end its approval grants, parked
|
|
1117
|
+
approvals and kernels; a model switch, truncate or compress leaves a running turn's agent in place."""
|
|
1020
1118
|
session_id = str(params.get("session_id") or "").strip()
|
|
1119
|
+
end_session = params.get("clear_session") is True
|
|
1021
1120
|
with _AGENT_CACHE_LOCK:
|
|
1121
|
+
with _RUNS_LOCK:
|
|
1122
|
+
run = _RUNS.get(_RUNS_BY_SESSION.get(session_id) or "")
|
|
1123
|
+
if not end_session and run is not None and not run.finished.is_set():
|
|
1124
|
+
return {"evicted": False}
|
|
1022
1125
|
evicted = _AGENT_CACHE.pop(session_id, None) is not None
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1126
|
+
if end_session:
|
|
1127
|
+
try:
|
|
1128
|
+
from tools.approval import clear_session
|
|
1129
|
+
clear_session(session_id)
|
|
1130
|
+
except Exception: # noqa: BLE001
|
|
1131
|
+
pass
|
|
1028
1132
|
return {"evicted": evicted}
|
|
1029
1133
|
|
|
1030
1134
|
@registry.method("chat.commit_memory", requires_agent=False)
|
|
@@ -1101,7 +1205,9 @@ def register(registry) -> None:
|
|
|
1101
1205
|
except Exception as exc: # noqa: BLE001
|
|
1102
1206
|
raise RpcError(f"approval module unavailable: {exc}", condition="agent_unavailable") from exc
|
|
1103
1207
|
(enable_session_yolo if enabled else disable_session_yolo)(session_id)
|
|
1104
|
-
released
|
|
1208
|
+
# Parked approvals are released `once`: a `session` or `always` grant would keep their patterns approved after
|
|
1209
|
+
# YOLO turns off, whatever choice the card that enabled it carried.
|
|
1210
|
+
released = resolve_gateway_approval(session_id, "once", resolve_all=True) if enabled else 0
|
|
1105
1211
|
return {"yolo_enabled": bool(is_session_yolo_enabled(session_id)), "released": int(released or 0)}
|
|
1106
1212
|
|
|
1107
1213
|
@registry.method("clarify.respond", requires_agent=False)
|
|
@@ -7,8 +7,9 @@ import threading
|
|
|
7
7
|
from typing import Any
|
|
8
8
|
|
|
9
9
|
from ..errors import InvalidParams, RpcError
|
|
10
|
-
from ..home import profile_home_param, scoped_home
|
|
10
|
+
from ..home import _is_named_profile, profile_home_param, scoped_home
|
|
11
11
|
from ..rpc import CallContext
|
|
12
|
+
from .providers import plugin_providers
|
|
12
13
|
|
|
13
14
|
log = logging.getLogger("talaria_sidecar.commands")
|
|
14
15
|
|
|
@@ -60,19 +61,54 @@ def list_commands() -> list[dict[str, Any]]:
|
|
|
60
61
|
return out
|
|
61
62
|
|
|
62
63
|
|
|
64
|
+
def retire_unscoped_launch_mcp_servers() -> set[str]:
|
|
65
|
+
"""Close the launch profile's connections opened before multiplexing started; returns their server names.
|
|
66
|
+
|
|
67
|
+
Until the first named-profile call, the launch profile's connections and tools are unscoped (process-wide). Once
|
|
68
|
+
multiplexing is active, a scoped shutdown never selects them and scoped discovery opens duplicates beside them, so
|
|
69
|
+
the launch profile's own calls close them first and its scope reconnects them from the current config."""
|
|
70
|
+
from agent.secret_scope import is_multiplex_active
|
|
71
|
+
from hermes_constants import get_hermes_home
|
|
72
|
+
from tools.mcp_tool import _lock, _servers
|
|
73
|
+
from tools.mcp_tool_lifecycle import shutdown_mcp_servers
|
|
74
|
+
from tools.mcp_tool_scope import _key_name, _key_scope
|
|
75
|
+
|
|
76
|
+
if not is_multiplex_active() or _is_named_profile(get_hermes_home()):
|
|
77
|
+
return set()
|
|
78
|
+
with _lock:
|
|
79
|
+
names = {_key_name(key) for key in _servers if _key_scope(key) is None}
|
|
80
|
+
if names:
|
|
81
|
+
shutdown_mcp_servers(scope=None, names=names)
|
|
82
|
+
return names
|
|
83
|
+
|
|
84
|
+
|
|
63
85
|
def _reload_mcp() -> str:
|
|
64
86
|
with _RELOAD_MCP_LOCK:
|
|
65
87
|
try:
|
|
66
|
-
from
|
|
88
|
+
from agent.secret_scope import is_multiplex_active
|
|
89
|
+
from tools.mcp_tool import _lock, _mcp_tool_server_names, _server_visible_in_scope, _servers
|
|
90
|
+
from tools.mcp_tool_discovery import discover_mcp_tools
|
|
91
|
+
from tools.mcp_tool_lifecycle import shutdown_mcp_servers
|
|
92
|
+
from tools.mcp_tool_scope import _key_name
|
|
93
|
+
from tools.registry import registry
|
|
67
94
|
except Exception as exc: # noqa: BLE001
|
|
68
95
|
raise RpcError("MCP runtime unavailable", condition="mcp_unavailable") from exc
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
96
|
+
# Like the gateway's ``_execute_mcp_reload``: under multiplexing only this profile's connections go down and
|
|
97
|
+
# come back. The bare shutdown is the process-wide wildcard, which would drop every other profile's servers.
|
|
98
|
+
scope = registry.current_scope_key() if is_multiplex_active() else None
|
|
99
|
+
|
|
100
|
+
def server_names() -> set[str]:
|
|
74
101
|
with _lock:
|
|
75
|
-
|
|
102
|
+
return {_key_name(key) for key in _servers if _server_visible_in_scope(key, scope)}
|
|
103
|
+
|
|
104
|
+
try:
|
|
105
|
+
old = server_names() | retire_unscoped_launch_mcp_servers()
|
|
106
|
+
shutdown_mcp_servers(scope=scope)
|
|
107
|
+
tools = discover_mcp_tools() or []
|
|
108
|
+
connected = server_names()
|
|
109
|
+
if scope is not None:
|
|
110
|
+
with _lock:
|
|
111
|
+
tools = [name for name in tools if _mcp_tool_server_names.get(name) in connected]
|
|
76
112
|
except Exception as exc: # noqa: BLE001
|
|
77
113
|
log.warning("Failed to reload MCP servers", exc_info=True)
|
|
78
114
|
raise RpcError("Failed to reload MCP servers", condition="mcp_reload_failed") from exc
|
|
@@ -84,7 +120,7 @@ def _reload_mcp() -> str:
|
|
|
84
120
|
lines.append(f"Added: {', '.join(sorted(added))}")
|
|
85
121
|
if removed:
|
|
86
122
|
lines.append(f"Removed: {', '.join(sorted(removed))}")
|
|
87
|
-
lines.append(f"{len(tools
|
|
123
|
+
lines.append(f"{len(tools)} tool(s) available across {len(connected)} server(s)" if connected else "No MCP servers connected")
|
|
88
124
|
if not reconnected and not added and not removed:
|
|
89
125
|
lines.append("Tooling state was already current")
|
|
90
126
|
return "\n".join(lines)
|
|
@@ -230,27 +266,6 @@ def resolve_moa_config(preset: str | None) -> dict:
|
|
|
230
266
|
return resolved
|
|
231
267
|
|
|
232
268
|
|
|
233
|
-
def plugin_provider_profiles() -> list[dict]:
|
|
234
|
-
"""Model-provider plugins registered with the Agent's provider registry."""
|
|
235
|
-
try:
|
|
236
|
-
from providers import list_providers
|
|
237
|
-
except Exception: # noqa: BLE001
|
|
238
|
-
return []
|
|
239
|
-
out = []
|
|
240
|
-
try:
|
|
241
|
-
for profile in list_providers():
|
|
242
|
-
name = str(getattr(profile, "name", "") or "").strip().lower()
|
|
243
|
-
if not name:
|
|
244
|
-
continue
|
|
245
|
-
env_vars = [str(v) for v in (getattr(profile, "env_vars", ()) or ())]
|
|
246
|
-
api_key_env = next((v for v in env_vars if not v.upper().endswith(("_BASE_URL", "_URL", "_FOLDER_ID"))), None)
|
|
247
|
-
out.append({"name": name, "display_name": str(getattr(profile, "display_name", "") or name).strip(), "env_vars": env_vars, "api_key_env": api_key_env})
|
|
248
|
-
except Exception: # noqa: BLE001
|
|
249
|
-
log.debug("Failed to enumerate model-provider plugins", exc_info=True)
|
|
250
|
-
return []
|
|
251
|
-
return out
|
|
252
|
-
|
|
253
|
-
|
|
254
269
|
PLUGIN_VISIBILITY_HOOKS = ("pre_tool_call", "post_tool_call", "pre_llm_call", "post_llm_call")
|
|
255
270
|
|
|
256
271
|
|
|
@@ -332,7 +347,7 @@ def register(registry) -> None:
|
|
|
332
347
|
@registry.method("plugins.providers")
|
|
333
348
|
def providers(ctx: CallContext, params: dict) -> dict:
|
|
334
349
|
with scoped_home(profile_home_param(params)):
|
|
335
|
-
return {"providers":
|
|
350
|
+
return {"providers": plugin_providers()}
|
|
336
351
|
|
|
337
352
|
@registry.method("plugins.list")
|
|
338
353
|
def list_(ctx: CallContext, params: dict) -> dict:
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
Agent's per-model reasoning capability.
|
|
3
3
|
|
|
4
4
|
The TypeScript server owns every config.yaml *policy* (which keys mean what);
|
|
5
|
-
the sidecar only parses and serialises YAML with the Agent's
|
|
6
|
-
side needs no YAML dependency. Writes are atomic and keep the file's mode.
|
|
5
|
+
the sidecar only parses and serialises YAML with the Agent's own parser so the
|
|
6
|
+
Node side needs no YAML dependency. Writes are atomic and keep the file's mode.
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
from __future__ import annotations
|
|
10
10
|
|
|
11
|
+
import importlib
|
|
11
12
|
import logging
|
|
12
13
|
import os
|
|
13
14
|
import tempfile
|
|
@@ -20,12 +21,15 @@ from ..rpc import CallContext
|
|
|
20
21
|
log = logging.getLogger("talaria_sidecar.config")
|
|
21
22
|
|
|
22
23
|
|
|
23
|
-
def
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
def yaml_parser():
|
|
25
|
+
"""The Agent's YAML module: ``hermes_yaml`` on Agents that ship it, PyYAML on released Agents."""
|
|
26
|
+
failures = []
|
|
27
|
+
for name in ("hermes_yaml", "yaml"):
|
|
28
|
+
try:
|
|
29
|
+
return importlib.import_module(name)
|
|
30
|
+
except Exception as exc: # noqa: BLE001
|
|
31
|
+
failures.append(f"{name}: {exc}")
|
|
32
|
+
raise RpcError(f"No YAML parser available ({'; '.join(failures)})", condition="yaml_unavailable")
|
|
29
33
|
|
|
30
34
|
|
|
31
35
|
def config_path_param(params: dict) -> Path:
|
|
@@ -45,7 +49,7 @@ def read_config(path: Path) -> dict:
|
|
|
45
49
|
if not path.exists():
|
|
46
50
|
return {"path": str(path), "exists": False, "config": {}}
|
|
47
51
|
try:
|
|
48
|
-
data =
|
|
52
|
+
data = yaml_parser().safe_load(path.read_text(encoding="utf-8"))
|
|
49
53
|
except RpcError:
|
|
50
54
|
raise
|
|
51
55
|
except Exception as exc: # noqa: BLE001
|
|
@@ -70,7 +74,7 @@ def write_config(path: Path, config: dict) -> dict:
|
|
|
70
74
|
raise InvalidParams("config must be an object")
|
|
71
75
|
target = _write_target(path)
|
|
72
76
|
target.parent.mkdir(parents=True, exist_ok=True)
|
|
73
|
-
text =
|
|
77
|
+
text = yaml_parser().safe_dump(config, sort_keys=False, allow_unicode=True)
|
|
74
78
|
mode = None
|
|
75
79
|
try:
|
|
76
80
|
mode = target.stat().st_mode & 0o777
|