@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
package/dist/sessions/turn.js
CHANGED
|
@@ -24,17 +24,22 @@ import { withSessionWireFlags } from './list.js';
|
|
|
24
24
|
import { hydrateAnchorActivityScenes, turnTerminalState, withTurnIds } from './anchor.js';
|
|
25
25
|
import { persistentStateChanges, persistentStateSnapshot } from './state-saved.js';
|
|
26
26
|
import { maxIterationsFromConfig, maxTokensFromConfig, processWakeupMaxIterations, reasoningConfigFromConfig, webuiEphemeralSystemPrompt, workspaceSystemMessage } from './turn-context.js';
|
|
27
|
-
import { agentSteerText, assistantReplyAddedAfterCurrentTurn, buildPartialMessage, escapeWorkspacePrefixPath, checkpointTurnStart, extractToolCallsFromMessages, injectMaxIterationSummaryFallback, isDict, mergeDisplayMessagesAfterAgentResult, messageIdentity, messageText, pendingUserRow, sanitizeMessagesForApi, sessionLacksFinalAssistantAnswer,
|
|
27
|
+
import { agentSteerText, assistantReplyAddedAfterCurrentTurn, buildPartialMessage, escapeWorkspacePrefixPath, checkpointTurnStart, extractToolCallsFromMessages, injectMaxIterationSummaryFallback, isDict, mergeDisplayMessagesAfterAgentResult, messageIdentity, messageText, pendingUserRow, sanitizeMessagesForApi, sessionLacksFinalAssistantAnswer, splitDisplayText, joinReasoning, reasoningFieldsText, stoppedTurnContext, toolOutcome, withAttachmentObjects, withBodyExcerpts, withDisplayMedia, withMarkerKinds, withToolCallOutcomes, workspaceContextPrefix } from './merge.js';
|
|
28
28
|
import { mayBecomeSilentReply, turnOrigin, withBackgroundUpdates } from './background-updates.js';
|
|
29
29
|
import { fallbackTitleFromExchange, firstExchangeSnippets, isGenericFallbackTitle, latestExchangeSnippets, looksInvalidGeneratedTitle, looksLikeDefaultCliTitle, sanitizeGeneratedTitle, titleLanguageMismatch, titlePrompts } from './titles.js';
|
|
30
|
+
import { WORKSPACE_BUSY_MESSAGE } from '../workspace/git.js';
|
|
30
31
|
import { str } from '../util.js';
|
|
31
32
|
export const CHAT_LOCK_WAIT_SECONDS = 2;
|
|
32
33
|
const IMAGE_MODE_TIMEOUT_MS = 15_000;
|
|
33
34
|
const TERMINAL_SSE_VISIBLE_MESSAGE_LIMIT = 80;
|
|
34
35
|
/** How long a user's message waits for a stopped background turn to unwind before its own turn is admitted. */
|
|
35
36
|
const BACKGROUND_UNWIND_WAIT_MS = 30_000;
|
|
37
|
+
const COMPRESSION_EXHAUSTED = { label: 'Context compression exhausted', type: 'compression_exhausted', hint: 'The conversation context is too large to compress safely. Start a new conversation or retry with a narrower task.' };
|
|
38
|
+
/** `compressionExhausted`: the Agent flagged the turn itself, so its wording does not matter. */
|
|
36
39
|
export function classifyProviderError(errStr, opts = {}) {
|
|
37
40
|
const lower = errStr.toLowerCase();
|
|
41
|
+
if (opts.compressionExhausted)
|
|
42
|
+
return COMPRESSION_EXHAUSTED;
|
|
38
43
|
if (opts.condition === 'credential_missing')
|
|
39
44
|
return { label: 'Authentication failed', type: 'auth_mismatch', hint: 'The selected model may not be supported by your configured provider or your API key is invalid. Run `hermes model` in your terminal to update credentials, then restart the WebUI.' };
|
|
40
45
|
const cancelled = ['cancelled by user', 'canceled by user', 'user cancelled', 'user canceled', 'task cancelled', 'task canceled', 'cancellederror'].some((k) => lower.includes(k));
|
|
@@ -60,7 +65,7 @@ export function classifyProviderError(errStr, opts = {}) {
|
|
|
60
65
|
if (notFound)
|
|
61
66
|
return { label: 'Model not found', type: 'model_not_found', hint: 'The selected model was not found by the provider. Check the model ID in Settings or run `hermes model` to verify it exists for your provider.' };
|
|
62
67
|
if (compressionExhausted)
|
|
63
|
-
return
|
|
68
|
+
return COMPRESSION_EXHAUSTED;
|
|
64
69
|
if (opts.silentFailure)
|
|
65
70
|
return { label: 'No response from provider', type: 'no_response', hint: 'The provider returned no content and no error. This often means a usage/rate limit was hit silently. Check provider status, switch providers via `hermes model`, or try again in a moment.' };
|
|
66
71
|
return { label: 'Error', type: 'error', hint: '' };
|
|
@@ -180,6 +185,8 @@ export class TurnRunner {
|
|
|
180
185
|
return { error: 'Web is updating. Retry after it restarts.', _status: 503 };
|
|
181
186
|
if (this.deps.profileDeleting?.(s.profile ?? null))
|
|
182
187
|
return { error: `Profile '${str(s.profile)}' is being deleted.`, _status: 409 };
|
|
188
|
+
if (this.deps.workspaceBusy?.(opts.workspace))
|
|
189
|
+
return { error: WORKSPACE_BUSY_MESSAGE, _status: 409 };
|
|
183
190
|
const locked = s.active_stream_id;
|
|
184
191
|
if (locked) {
|
|
185
192
|
if (this.registry.liveIds.has(locked) || this.registry.activeRuns.has(locked))
|
|
@@ -424,15 +431,20 @@ export class TurnRunner {
|
|
|
424
431
|
return;
|
|
425
432
|
}
|
|
426
433
|
case 'tool_complete': {
|
|
427
|
-
// TAL-313: the server decides failure from the sidecar's raw result, which never leaves the server
|
|
434
|
+
// TAL-313: the server decides failure from the sidecar's raw result, which never leaves the server; TAL-315: so
|
|
435
|
+
// are its display sections, which keep the stderr and exit code the flat preview drops.
|
|
428
436
|
const { raw_result: rawResult, ...complete } = data;
|
|
429
|
-
|
|
437
|
+
const outcome = toolOutcome(rawResult);
|
|
438
|
+
complete.is_error = outcome.is_error;
|
|
439
|
+
if (rawResult !== undefined)
|
|
440
|
+
complete.result_view = outcome.result_view;
|
|
430
441
|
const tc = liveToolCalls[completedToolIndex(liveToolCalls, str(data.tid), data.name)];
|
|
431
442
|
if (tc) {
|
|
432
443
|
const startedAt = toolStartedAt.get(tc);
|
|
433
444
|
if (startedAt !== undefined)
|
|
434
445
|
complete.duration = Math.round(Math.max(0, deps.now() - startedAt) * 1000) / 1000;
|
|
435
|
-
|
|
446
|
+
// TAL-315: the decided view too, so a failed or cancelled turn's snapshot keeps the sections shown live.
|
|
447
|
+
Object.assign(tc, { done: true, snippet: data.preview, is_error: complete.is_error, duration: complete.duration ?? null, ...(complete.result_view ? { result_view: complete.result_view } : {}) });
|
|
436
448
|
}
|
|
437
449
|
const id = (tc && toolIds.get(tc)) || str(data.tid) || mintToolId();
|
|
438
450
|
this.lastCompletedTool.set(streamId, id);
|
|
@@ -447,6 +459,14 @@ export class TurnRunner {
|
|
|
447
459
|
put('approval', { ...(pending ?? data), pending_count });
|
|
448
460
|
return;
|
|
449
461
|
}
|
|
462
|
+
// TAL-514: the Agent stopped waiting on an approval (answer, timeout, or interrupt); withdraw its copy.
|
|
463
|
+
case 'approval_resolved': {
|
|
464
|
+
if (!str(data.approval_id))
|
|
465
|
+
return;
|
|
466
|
+
deps.pending.resolveApproval(sessionId, str(data.approval_id));
|
|
467
|
+
put(...this.approvalHeadFrame(sessionId));
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
450
470
|
case 'clarify': {
|
|
451
471
|
deps.pending.submitClarify(sessionId, { ...data, session_id: sessionId, kind: 'clarify' });
|
|
452
472
|
const head = deps.pending.clarifyHeadFrame(sessionId);
|
|
@@ -478,25 +498,6 @@ export class TurnRunner {
|
|
|
478
498
|
put('cancel', this.cancelFrame(sessionId));
|
|
479
499
|
return;
|
|
480
500
|
}
|
|
481
|
-
if (opts.ephemeral) {
|
|
482
|
-
let answer = '';
|
|
483
|
-
for (let i = result.messages.length - 1; i >= 0; i -= 1) {
|
|
484
|
-
const m = result.messages[i];
|
|
485
|
-
if (m.role === 'assistant') {
|
|
486
|
-
answer = str(m.content);
|
|
487
|
-
break;
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
opts.onDone?.(answer);
|
|
491
|
-
// Python `_ephemeral_session_payload`: only role and content leave the server for a btw turn.
|
|
492
|
-
put('done', { session: { session_id: sessionId, messages: (result.messages).map((m) => ({ role: m.role, content: m.content })) }, usage: { input_tokens: 0, output_tokens: 0 }, ephemeral: true, answer, terminal_state: answer.trim() ? 'completed' : 'no_response' });
|
|
493
|
-
try {
|
|
494
|
-
rmSync(deps.store.pathFor(sessionId), { force: true });
|
|
495
|
-
}
|
|
496
|
-
catch { /* ignore */ }
|
|
497
|
-
deps.store.sessions.delete(sessionId);
|
|
498
|
-
return;
|
|
499
|
-
}
|
|
500
501
|
// Writeback only while this stream still owns the session (Python `_stream_writeback_is_current`).
|
|
501
502
|
let current;
|
|
502
503
|
try {
|
|
@@ -518,12 +519,14 @@ export class TurnRunner {
|
|
|
518
519
|
// Python's second chance: a turn that emitted no new row still counts when the merged transcript it produced
|
|
519
520
|
// ends on a final answer (the current user row or trailing tool activity makes it "lacking").
|
|
520
521
|
const mergedForCheck = () => mergeDisplayMessagesAfterAgentResult(previousMessages, previousContext, resultMessages, msgText, { source: opts.source ?? 'webui', activeTurnToken, now: deps.now(), turnId: streamId, attachments: opts.attachments ?? [] });
|
|
521
|
-
|
|
522
|
+
// TAL-512: a btw answer must be a reply this turn added: everything before it is the parent's replayed history.
|
|
523
|
+
const assistantAdded = assistantReplyAddedAfterCurrentTurn(resultMessages, previousContext, msgText) || (!opts.ephemeral && !sessionLacksFinalAssistantAnswer(mergedForCheck()));
|
|
522
524
|
const lastErr = result.error ?? capturedTerminalError ?? '';
|
|
523
|
-
// Python `
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
525
|
+
// Python `_agent_result_terminal_failure`: the Agent's failed, partial, or compression-exhausted result ends the turn
|
|
526
|
+
// even after text streamed; only a partial with no error text and a final answer still completes.
|
|
527
|
+
const agentFailed = result.failed || result.compression_exhausted || (result.partial && (Boolean(lastErr) || !assistantAdded));
|
|
528
|
+
if (result.status === 'error' || agentFailed || (!assistantAdded && (!tokenSent || opts.ephemeral))) {
|
|
529
|
+
const classification = classifyProviderError(lastErr, { silentFailure: !lastErr, compressionExhausted: result.compression_exhausted });
|
|
527
530
|
const errStr = lastErr || `${classification.label}.`;
|
|
528
531
|
const payload = providerErrorPayload(errStr, classification.type, classification.hint, deps.redactEnabled());
|
|
529
532
|
// Settle the steers first so the persisted turn carries every consumed one; the Agent's pending text is sent next.
|
|
@@ -532,7 +535,9 @@ export class TurnRunner {
|
|
|
532
535
|
const { events: steerEvents, leftovers } = this.finalizeSteers(streamId, str(result.pending_steer), 'followup');
|
|
533
536
|
followUp = leftovers;
|
|
534
537
|
this.persistError(s, streamId, classification.label, payload, activeTurnToken);
|
|
535
|
-
|
|
538
|
+
// TAL-512: a btw error carries no session: its journaled frame must not keep a copy of the parent conversation.
|
|
539
|
+
if (!opts.ephemeral)
|
|
540
|
+
payload.session = redactSessionData(this.terminalSessionPayload(s), deps.redactEnabled());
|
|
536
541
|
payload.session_id = s.session_id;
|
|
537
542
|
payload.old_session_id = sessionId;
|
|
538
543
|
for (const [event, data] of steerEvents)
|
|
@@ -541,18 +546,32 @@ export class TurnRunner {
|
|
|
541
546
|
failed = true;
|
|
542
547
|
return;
|
|
543
548
|
}
|
|
549
|
+
// TAL-512: a btw turn passes the failure check above first, so its last assistant row is this turn's reply.
|
|
550
|
+
if (opts.ephemeral) {
|
|
551
|
+
let answer = '';
|
|
552
|
+
for (let i = result.messages.length - 1; i >= 0; i -= 1) {
|
|
553
|
+
const m = result.messages[i];
|
|
554
|
+
if (m.role === 'assistant') {
|
|
555
|
+
answer = str(m.content);
|
|
556
|
+
break;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
opts.onDone?.(answer);
|
|
560
|
+
// Python `_ephemeral_session_payload`: only role and content leave the server for a btw turn.
|
|
561
|
+
put('done', { session: { session_id: sessionId, messages: (result.messages).map((m) => ({ role: m.role, content: m.content })) }, usage: { input_tokens: 0, output_tokens: 0 }, ephemeral: true, answer, terminal_state: answer.trim() ? 'completed' : 'no_response' });
|
|
562
|
+
try {
|
|
563
|
+
rmSync(deps.store.pathFor(sessionId), { force: true });
|
|
564
|
+
}
|
|
565
|
+
catch { /* ignore */ }
|
|
566
|
+
deps.store.sessions.delete(sessionId);
|
|
567
|
+
return;
|
|
568
|
+
}
|
|
544
569
|
// ── settle the transcript ──
|
|
545
570
|
// The Agent's last pending-steer text settles the remaining steers before the turn is written back.
|
|
546
571
|
await this.steerRewrites.get(streamId);
|
|
547
572
|
const { events: steerEvents, leftovers } = this.finalizeSteers(streamId, result.pending_steer, 'followup');
|
|
548
573
|
s.messages = mergeDisplayMessagesAfterAgentResult(previousMessages, previousContext, resultMessages, msgText, { source: opts.source ?? 'webui', activeTurnToken, now: deps.now(), turnId: streamId, attachments: opts.attachments ?? [] });
|
|
549
574
|
s.context_messages = dedupeContext(resultMessages);
|
|
550
|
-
for (const m of s.messages) {
|
|
551
|
-
if (m.role !== 'assistant')
|
|
552
|
-
continue;
|
|
553
|
-
if (typeof m.content === 'string')
|
|
554
|
-
m.content = stripXmlToolCalls(m.content);
|
|
555
|
-
}
|
|
556
575
|
if (result.compressed) {
|
|
557
576
|
s.compression_anchor_visible_idx = Math.max(0, previousMessages.length - 1);
|
|
558
577
|
put('compressed', { session_id: sessionId, old_session_id: sessionId, new_session_id: sessionId, continuation_session_id: sessionId, message: 'Compression finished' });
|
|
@@ -611,12 +630,12 @@ export class TurnRunner {
|
|
|
611
630
|
asstIdx += 1;
|
|
612
631
|
if (turnIdx < prevAssistants)
|
|
613
632
|
continue;
|
|
614
|
-
|
|
633
|
+
// The settled row keeps its own fields: only its prose and its inline thinking (into `reasoning`) are rewritten.
|
|
615
634
|
if (typeof m.content === 'string' && m.content) {
|
|
616
|
-
const [content,
|
|
635
|
+
const [content, inline] = splitDisplayText(m.content);
|
|
617
636
|
m.content = content;
|
|
618
|
-
if (
|
|
619
|
-
m.reasoning =
|
|
637
|
+
if (inline)
|
|
638
|
+
m.reasoning = joinReasoning([reasoningFieldsText({ reasoning: m.reasoning }), inline]);
|
|
620
639
|
}
|
|
621
640
|
if (turnIdx === prevAssistants && reasoning.trim() && !m.reasoning)
|
|
622
641
|
m.reasoning = reasoning.trim();
|
|
@@ -690,22 +709,14 @@ export class TurnRunner {
|
|
|
690
709
|
this.registry.activeRuns.delete(streamId);
|
|
691
710
|
this.settledStreams.add(streamId);
|
|
692
711
|
this.startSteerFollowUp(sessionId, leftovers);
|
|
693
|
-
|
|
712
|
+
// Title work and the goal judge run side by side; `stream_end` follows both, so their frames reach the stream.
|
|
713
|
+
const work = await Promise.allSettled([this.backgroundTitle(s, put), this.continueGoal(s, streamId, put)]);
|
|
714
|
+
put('stream_end', { session_id: sessionId });
|
|
715
|
+
for (const r of work)
|
|
716
|
+
if (r.status === 'rejected')
|
|
717
|
+
throw r.reason;
|
|
694
718
|
// Python: the last non-error assistant reply with content, else "(no answer produced)".
|
|
695
|
-
|
|
696
|
-
let answer = '';
|
|
697
|
-
for (let i = s.messages.length - 1; i >= 0; i -= 1) {
|
|
698
|
-
const m = s.messages[i];
|
|
699
|
-
if (m.role !== 'assistant' || m._error)
|
|
700
|
-
continue;
|
|
701
|
-
const text = messageText(m.content).trim();
|
|
702
|
-
if (text) {
|
|
703
|
-
answer = text;
|
|
704
|
-
break;
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
opts.onDone(answer || '(no answer produced)');
|
|
708
|
-
}
|
|
719
|
+
opts.onDone?.(lastAnswer(s.messages) || '(no answer produced)');
|
|
709
720
|
}
|
|
710
721
|
catch (error) {
|
|
711
722
|
if (settledAt.value && !(error instanceof SidecarError)) {
|
|
@@ -737,7 +748,8 @@ export class TurnRunner {
|
|
|
737
748
|
for (const [event, data] of this.takeSteerEventsBefore(streamId, 'apperror'))
|
|
738
749
|
put(event, data);
|
|
739
750
|
this.persistError(current, streamId, classification.label, payload, activeTurnToken);
|
|
740
|
-
|
|
751
|
+
if (!opts.ephemeral)
|
|
752
|
+
payload.session = redactSessionData(this.terminalSessionPayload(current), deps.redactEnabled());
|
|
741
753
|
}
|
|
742
754
|
}
|
|
743
755
|
catch (persistError) {
|
|
@@ -835,11 +847,13 @@ export class TurnRunner {
|
|
|
835
847
|
* msg_limit=` (renderable rows, limited payload shape, windowed tool calls, todo state) with the full count.
|
|
836
848
|
*/
|
|
837
849
|
terminalSessionPayload(s) {
|
|
838
|
-
const payload = withSessionWireFlags(s.compact({ contextLengthFor: this.deps.service().deps.contextLengthFor }), this.registry.liveIds);
|
|
850
|
+
const payload = withSessionWireFlags(s.compact({ contextLengthFor: this.deps.service().deps.contextLengthFor, modelOptionFor: this.deps.service().deps.modelOptionFor }), this.registry.liveIds);
|
|
839
851
|
payload.assistant_name = this.deps.service().assistantName(s);
|
|
840
|
-
|
|
852
|
+
payload.workspace_name = this.deps.service().workspaceNames()(s);
|
|
853
|
+
const service = this.deps.service();
|
|
854
|
+
const scened = service.backgroundLinked(s, hydrateAnchorActivityScenes(withToolCallOutcomes(withBackgroundUpdates(withMarkerKinds(withTurnIds(withAttachmentObjects(s.messages))), s), s.tool_calls, s.active_stream_id), s.anchor_activity_scenes, { activeTurnId: s.active_stream_id, clipToolResults: true }));
|
|
841
855
|
const [window, offset] = messageWindowForDisplay(scened, TERMINAL_SSE_VISIBLE_MESSAGE_LIMIT, null);
|
|
842
|
-
const limited = messagesForLimitedPayload(window);
|
|
856
|
+
const limited = messagesForLimitedPayload(withBodyExcerpts(withDisplayMedia(window, service.mediaProjector(s)), s.active_stream_id));
|
|
843
857
|
payload.messages = limited;
|
|
844
858
|
payload.message_count = s.messages.length;
|
|
845
859
|
payload._messages_offset = offset;
|
|
@@ -1131,65 +1145,60 @@ export class TurnRunner {
|
|
|
1131
1145
|
const status = (status, reason = '', title = '', rawPreview = '') => {
|
|
1132
1146
|
put('title_status', { session_id: sessionId, status, ...(reason ? { reason } : {}), ...(title ? { title } : {}), ...(rawPreview ? { raw_preview: rawPreview } : {}) });
|
|
1133
1147
|
};
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1148
|
+
if (!eligible || (s.llm_title_generated && !invalidExisting) || !userText || !assistantText)
|
|
1149
|
+
return;
|
|
1150
|
+
if (s.manual_title) {
|
|
1151
|
+
status('skipped', 'manual_title', placeholder);
|
|
1152
|
+
return;
|
|
1153
|
+
}
|
|
1154
|
+
if (!this.deps.titleGenerationEnabled()) {
|
|
1155
|
+
status('skipped', 'title_generation_disabled', placeholder);
|
|
1156
|
+
return;
|
|
1157
|
+
}
|
|
1158
|
+
const generated = await this.llmTitle(s, userText, assistantText);
|
|
1159
|
+
const { status: llmStatus, rawPreview } = generated;
|
|
1160
|
+
let next = generated.title;
|
|
1161
|
+
let source = llmStatus;
|
|
1162
|
+
if (!next) {
|
|
1163
|
+
const fallback = fallbackTitleFromExchange(userText, assistantText);
|
|
1164
|
+
if (fallback && !isGenericFallbackTitle(fallback)) {
|
|
1165
|
+
next = fallback;
|
|
1166
|
+
source = 'fallback';
|
|
1140
1167
|
}
|
|
1141
|
-
|
|
1142
|
-
|
|
1168
|
+
}
|
|
1169
|
+
const fallbackReason = source === 'fallback' && llmStatus ? `local_summary:${llmStatus}` : 'local_summary';
|
|
1170
|
+
let current = s;
|
|
1171
|
+
try {
|
|
1172
|
+
current = this.deps.store.get(sessionId);
|
|
1173
|
+
}
|
|
1174
|
+
catch {
|
|
1175
|
+
current = s;
|
|
1176
|
+
}
|
|
1177
|
+
let effective = str(current.title).trim();
|
|
1178
|
+
let wrote = false;
|
|
1179
|
+
if (next) {
|
|
1180
|
+
const stillAuto = effective === placeholder || ['Untitled', 'New Chat', ''].includes(effective) || effective === titleFrom(current.messages, '') || looksInvalidGeneratedTitle(current.title) || defaultTitle(current);
|
|
1181
|
+
if (current.manual_title || !stillAuto) {
|
|
1182
|
+
status('skipped', 'manual_title', effective);
|
|
1143
1183
|
return;
|
|
1144
1184
|
}
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
}
|
|
1155
|
-
}
|
|
1156
|
-
const fallbackReason = source === 'fallback' && llmStatus ? `local_summary:${llmStatus}` : 'local_summary';
|
|
1157
|
-
let current = s;
|
|
1158
|
-
try {
|
|
1159
|
-
current = this.deps.store.get(sessionId);
|
|
1160
|
-
}
|
|
1161
|
-
catch {
|
|
1162
|
-
current = s;
|
|
1163
|
-
}
|
|
1164
|
-
let effective = str(current.title).trim();
|
|
1165
|
-
let wrote = false;
|
|
1166
|
-
if (next) {
|
|
1167
|
-
const stillAuto = effective === placeholder || ['Untitled', 'New Chat', ''].includes(effective) || effective === titleFrom(current.messages, '') || looksInvalidGeneratedTitle(current.title) || defaultTitle(current);
|
|
1168
|
-
if (current.manual_title || !stillAuto) {
|
|
1169
|
-
status('skipped', 'manual_title', effective);
|
|
1170
|
-
return;
|
|
1171
|
-
}
|
|
1172
|
-
if (next !== effective) {
|
|
1173
|
-
current.title = next;
|
|
1174
|
-
markSessionTitleGenerated(current);
|
|
1175
|
-
this.deps.store.save(current, { touchUpdatedAt: false });
|
|
1176
|
-
// Python `sync_session_title` after generation: the state.db row follows when `sync_to_insights` is on.
|
|
1177
|
-
await this.deps.syncTitle?.(current);
|
|
1178
|
-
this.deps.events.publish('title', { profile: current.profile, sessionId });
|
|
1179
|
-
effective = next;
|
|
1180
|
-
wrote = true;
|
|
1181
|
-
}
|
|
1182
|
-
}
|
|
1183
|
-
if (wrote) {
|
|
1184
|
-
status(source, source === 'fallback' ? fallbackReason : llmStatus, effective, rawPreview);
|
|
1185
|
-
put('title', { session_id: sessionId, title: effective });
|
|
1185
|
+
if (next !== effective) {
|
|
1186
|
+
current.title = next;
|
|
1187
|
+
markSessionTitleGenerated(current);
|
|
1188
|
+
this.deps.store.save(current, { touchUpdatedAt: false });
|
|
1189
|
+
// Python `sync_session_title` after generation: the state.db row follows when `sync_to_insights` is on.
|
|
1190
|
+
await this.deps.syncTitle?.(current);
|
|
1191
|
+
this.deps.events.publish('title', { profile: current.profile, sessionId });
|
|
1192
|
+
effective = next;
|
|
1193
|
+
wrote = true;
|
|
1186
1194
|
}
|
|
1187
|
-
else
|
|
1188
|
-
status('skipped', source || 'unchanged', effective, rawPreview);
|
|
1189
1195
|
}
|
|
1190
|
-
|
|
1191
|
-
|
|
1196
|
+
if (wrote) {
|
|
1197
|
+
status(source, source === 'fallback' ? fallbackReason : llmStatus, effective, rawPreview);
|
|
1198
|
+
put('title', { session_id: sessionId, title: effective });
|
|
1192
1199
|
}
|
|
1200
|
+
else
|
|
1201
|
+
status('skipped', source || 'unchanged', effective, rawPreview);
|
|
1193
1202
|
}
|
|
1194
1203
|
// ── cancel / steer ───────────────────────────────────────────────────────
|
|
1195
1204
|
/**
|
|
@@ -1503,6 +1512,60 @@ export class TurnRunner {
|
|
|
1503
1512
|
}
|
|
1504
1513
|
this.deps.log(`[webui] WARNING: steer follow-up for ${sessionId} not started (${String(started._status)}): ${str(started.error)}`);
|
|
1505
1514
|
}
|
|
1515
|
+
/**
|
|
1516
|
+
* TAL-396 (Agent gateway `_post_turn_goal_continuation`): after every turn settles, the Agent's GoalManager judges it
|
|
1517
|
+
* while a goal is active and the server starts the continuation turn it asks for. Any turn counts, so a resumed or
|
|
1518
|
+
* persisted goal picks up from the next user message. A user turn that took the session meanwhile runs first and is
|
|
1519
|
+
* judged next. A stopped or failed turn never gets here, so the run ends there.
|
|
1520
|
+
*/
|
|
1521
|
+
async continueGoal(s, streamId, put) {
|
|
1522
|
+
const sidecar = this.deps.sidecar();
|
|
1523
|
+
const lastResponse = lastAnswer(s.messages);
|
|
1524
|
+
// The Agent never drives a goal from an empty reply.
|
|
1525
|
+
if (!sidecar || !lastResponse)
|
|
1526
|
+
return;
|
|
1527
|
+
const sessionId = s.session_id;
|
|
1528
|
+
// Only a known goal turn shows progress up front; any other turn shows nothing unless a goal turns out to be active.
|
|
1529
|
+
const goalTurn = this.registry.goalRelated.has(streamId);
|
|
1530
|
+
if (goalTurn)
|
|
1531
|
+
put('goal', { session_id: sessionId, state: 'evaluating', message: 'Evaluating goal progress…', message_key: 'goal_evaluating_progress' });
|
|
1532
|
+
let decision;
|
|
1533
|
+
try {
|
|
1534
|
+
decision = await sidecar.call('goals.evaluate', { session_id: sessionId, profile_home: this.deps.profileHome(s.profile), last_response: lastResponse, user_initiated: true });
|
|
1535
|
+
}
|
|
1536
|
+
catch (error) {
|
|
1537
|
+
this.deps.log(`[webui] WARNING: goal evaluation failed for ${sessionId}: ${error.message}`);
|
|
1538
|
+
if (goalTurn)
|
|
1539
|
+
put('goal', { session_id: sessionId, state: 'idle', decision: 'error', message: '' });
|
|
1540
|
+
return;
|
|
1541
|
+
}
|
|
1542
|
+
if (!goalTurn && decision.verdict === 'inactive')
|
|
1543
|
+
return;
|
|
1544
|
+
const prompt = str(decision.continuation_prompt).trim();
|
|
1545
|
+
const proceed = decision.should_continue && Boolean(prompt);
|
|
1546
|
+
const status = { message: decision.message, message_key: decision.message_key, message_args: decision.message_args ?? [], decision: decision.verdict };
|
|
1547
|
+
put('goal', { session_id: sessionId, state: proceed ? 'continuing' : 'idle', ...status });
|
|
1548
|
+
if (!proceed)
|
|
1549
|
+
return;
|
|
1550
|
+
let current;
|
|
1551
|
+
try {
|
|
1552
|
+
current = this.deps.store.get(sessionId);
|
|
1553
|
+
}
|
|
1554
|
+
catch {
|
|
1555
|
+
return;
|
|
1556
|
+
}
|
|
1557
|
+
const started = this.start(current, { msg: prompt, attachments: [], workspace: current.workspace, model: current.model, modelProvider: current.model_provider, goalRelated: true });
|
|
1558
|
+
if (started._status === 409 && started.active_stream_id) {
|
|
1559
|
+
this.registry.goalRelated.add(started.active_stream_id);
|
|
1560
|
+
return;
|
|
1561
|
+
}
|
|
1562
|
+
if (started._status !== undefined && started._status >= 400) {
|
|
1563
|
+
this.deps.log(`[webui] WARNING: goal continuation for ${sessionId} not started (${String(started._status)}): ${str(started.error)}`);
|
|
1564
|
+
put('goal', { session_id: sessionId, state: 'idle', decision: 'error', message: '' });
|
|
1565
|
+
return;
|
|
1566
|
+
}
|
|
1567
|
+
put('goal_continue', { session_id: sessionId, state: 'continuing', continuation_prompt: prompt, text: prompt, stream_id: str(started.stream_id), ...status });
|
|
1568
|
+
}
|
|
1506
1569
|
/** The Agent's pending steer text settles which steers it has taken: those become `steer_consumed` and their rows. */
|
|
1507
1570
|
settleConsumedSteers(sessionId, streamId, pendingText) {
|
|
1508
1571
|
for (const record of this.takeConsumedSteers(streamId, pendingText, { keepLeftovers: true }))
|
|
@@ -1645,6 +1708,7 @@ export class TurnRunner {
|
|
|
1645
1708
|
}
|
|
1646
1709
|
const profileHome = this.deps.profileHome(s?.profile ?? null);
|
|
1647
1710
|
let resolved = false;
|
|
1711
|
+
let withdrawn = false;
|
|
1648
1712
|
if (entry) {
|
|
1649
1713
|
if (!sidecar)
|
|
1650
1714
|
return relayFailure('not running');
|
|
@@ -1656,8 +1720,13 @@ export class TurnRunner {
|
|
|
1656
1720
|
this.deps.log(`[webui] approval relay failed for ${sessionId}: ${error.message}`);
|
|
1657
1721
|
return relayFailure(str(error.message));
|
|
1658
1722
|
}
|
|
1659
|
-
if (resolved
|
|
1723
|
+
if (resolved)
|
|
1660
1724
|
this.deps.pending.resolveApproval(sessionId, str(entry.approval_id));
|
|
1725
|
+
else {
|
|
1726
|
+
// TAL-514: a rejected answer can mean the Agent already stopped waiting on this card; drop what it no longer holds.
|
|
1727
|
+
await this.reconcileApprovals(sessionId, sidecar);
|
|
1728
|
+
withdrawn = !this.deps.pending.hasApprovalId(sessionId, str(entry.approval_id));
|
|
1729
|
+
}
|
|
1661
1730
|
}
|
|
1662
1731
|
let yoloEnabled;
|
|
1663
1732
|
if (enableYolo) {
|
|
@@ -1680,10 +1749,34 @@ export class TurnRunner {
|
|
|
1680
1749
|
yoloEnabled = true;
|
|
1681
1750
|
this.deps.pending.clearApprovals(sessionId);
|
|
1682
1751
|
}
|
|
1752
|
+
if (withdrawn)
|
|
1753
|
+
return { ok: true, choice, stale_cleared: true, pending_count: this.deps.pending.approvalPending(sessionId).pending_count, ...(enableYolo ? { yolo_enabled: yoloEnabled } : {}) };
|
|
1683
1754
|
if (!found && !this.deps.pending.hasPendingApproval(sessionId))
|
|
1684
1755
|
return { ok: true, choice, stale_cleared: true, ...(enableYolo ? { yolo_enabled: yoloEnabled } : {}) };
|
|
1685
1756
|
return { ok: resolved || !approvalId, choice, ...(enableYolo && (resolved || !approvalId) ? { yolo_enabled: yoloEnabled } : {}) };
|
|
1686
1757
|
}
|
|
1758
|
+
/** The live chat frame after approvals were withdrawn: the new queue head, or `approval_cleared` once none is left. */
|
|
1759
|
+
approvalHeadFrame(sessionId) {
|
|
1760
|
+
const { pending, pending_count } = this.deps.pending.approvalPending(sessionId);
|
|
1761
|
+
return pending ? ['approval', { ...pending, pending_count }] : ['approval_cleared', { session_id: sessionId, pending_count: 0 }];
|
|
1762
|
+
}
|
|
1763
|
+
/**
|
|
1764
|
+
* Drop mirrored approvals the Agent no longer holds; a failed read keeps them (the card stays answerable). Only
|
|
1765
|
+
* entries queued before the read are candidates: one the Agent parks meanwhile can be missing from its snapshot.
|
|
1766
|
+
*/
|
|
1767
|
+
async reconcileApprovals(sessionId, sidecar) {
|
|
1768
|
+
const before = this.deps.pending.approvalRequestIds(sessionId);
|
|
1769
|
+
let live;
|
|
1770
|
+
try {
|
|
1771
|
+
live = new Set((await sidecar.call('approval.pending', { session_id: sessionId })).pending.map((p) => str(p.request_id)));
|
|
1772
|
+
}
|
|
1773
|
+
catch (error) {
|
|
1774
|
+
this.deps.log(`[webui] approval reconcile failed for ${sessionId}: ${error.message}`);
|
|
1775
|
+
return;
|
|
1776
|
+
}
|
|
1777
|
+
if (this.deps.pending.dropApprovals(sessionId, new Set(before.filter((id) => !live.has(id)))).length)
|
|
1778
|
+
this.emitToSession(sessionId, ...this.approvalHeadFrame(sessionId));
|
|
1779
|
+
}
|
|
1687
1780
|
withYoloLock(sessionId, fn) {
|
|
1688
1781
|
const run = (this.yoloChains.get(sessionId) ?? Promise.resolve()).then(fn);
|
|
1689
1782
|
const settled = run.catch(() => undefined).then(() => { if (this.yoloChains.get(sessionId) === settled)
|
|
@@ -1736,6 +1829,18 @@ export class TurnRunner {
|
|
|
1736
1829
|
return { ok: true, response };
|
|
1737
1830
|
}
|
|
1738
1831
|
}
|
|
1832
|
+
/** The turn's answer: the last non-error assistant reply with content. */
|
|
1833
|
+
function lastAnswer(messages) {
|
|
1834
|
+
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
|
1835
|
+
const m = messages[i];
|
|
1836
|
+
if (m.role !== 'assistant' || m._error)
|
|
1837
|
+
continue;
|
|
1838
|
+
const text = messageText(m.content).trim();
|
|
1839
|
+
if (text)
|
|
1840
|
+
return text;
|
|
1841
|
+
}
|
|
1842
|
+
return '';
|
|
1843
|
+
}
|
|
1739
1844
|
function previousStartedAt(s, run) {
|
|
1740
1845
|
return typeof s.pending_started_at === 'number' && s.pending_started_at > 0 ? s.pending_started_at : (run?.started_at ?? Date.now() / 1000);
|
|
1741
1846
|
}
|