@maudecode/talaria-web 1.14.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 +123 -7
- package/dist/api/automation-router.js +5 -0
- package/dist/api/automation-router.js.map +1 -1
- package/dist/api/chat-router.d.ts +728 -55
- package/dist/api/chat-router.js +122 -126
- 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 +6 -3
- package/dist/api/router.js +10 -8
- package/dist/api/router.js.map +1 -1
- package/dist/api/sessions-router.d.ts +2583 -297
- package/dist/api/sessions-router.js +92 -47
- package/dist/api/sessions-router.js.map +1 -1
- package/dist/api/settings-router.d.ts +188 -17
- package/dist/api/settings-router.js +75 -26
- 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 +3620 -343
- 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/config/agent-config.js +20 -15
- package/dist/config/agent-config.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 +7 -5
- package/dist/http/context.js.map +1 -1
- package/dist/links.d.ts +26 -0
- package/dist/links.js +60 -0
- package/dist/links.js.map +1 -0
- package/dist/onboarding.d.ts +1 -1
- package/dist/onboarding.js +28 -8
- 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 +85 -1
- package/dist/providers/catalog.js +280 -43
- 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 +104 -42
- 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 +140 -0
- package/dist/sessions/background-tasks.js +352 -0
- package/dist/sessions/background-tasks.js.map +1 -0
- package/dist/sessions/background-updates.d.ts +56 -0
- package/dist/sessions/background-updates.js +152 -0
- package/dist/sessions/background-updates.js.map +1 -0
- package/dist/sessions/cli-sessions.d.ts +6 -0
- package/dist/sessions/cli-sessions.js +20 -7
- package/dist/sessions/cli-sessions.js.map +1 -1
- package/dist/sessions/completions.d.ts +17 -1
- package/dist/sessions/completions.js +84 -13
- package/dist/sessions/completions.js.map +1 -1
- package/dist/sessions/compress.d.ts +33 -0
- package/dist/sessions/compress.js +66 -0
- package/dist/sessions/compress.js.map +1 -0
- package/dist/sessions/list.d.ts +22 -4
- package/dist/sessions/list.js +113 -33
- package/dist/sessions/list.js.map +1 -1
- package/dist/sessions/merge.d.ts +81 -7
- package/dist/sessions/merge.js +391 -26
- 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/relay.d.ts +7 -1
- package/dist/sessions/relay.js +17 -4
- package/dist/sessions/relay.js.map +1 -1
- package/dist/sessions/service.d.ts +118 -6
- package/dist/sessions/service.js +564 -65
- package/dist/sessions/service.js.map +1 -1
- package/dist/sessions/session.d.ts +22 -1
- package/dist/sessions/session.js +29 -2
- 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/source-kind.d.ts +22 -0
- package/dist/sessions/source-kind.js +54 -0
- package/dist/sessions/source-kind.js.map +1 -0
- package/dist/sessions/state-db.d.ts +10 -1
- package/dist/sessions/state-db.js +48 -17
- package/dist/sessions/state-db.js.map +1 -1
- package/dist/sessions/store.d.ts +2 -0
- package/dist/sessions/store.js +24 -5
- package/dist/sessions/store.js.map +1 -1
- package/dist/sessions/streams.d.ts +3 -0
- package/dist/sessions/streams.js +0 -5
- package/dist/sessions/streams.js.map +1 -1
- package/dist/sessions/titles.d.ts +4 -0
- package/dist/sessions/titles.js +16 -0
- package/dist/sessions/titles.js.map +1 -1
- package/dist/sessions/turn-context.d.ts +1 -0
- package/dist/sessions/turn-context.js +3 -0
- package/dist/sessions/turn-context.js.map +1 -1
- package/dist/sessions/turn.d.ts +85 -7
- package/dist/sessions/turn.js +518 -170
- package/dist/sessions/turn.js.map +1 -1
- package/dist/settings.d.ts +2 -0
- package/dist/settings.js +13 -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 +38 -4
- package/dist/tools/crons.js +323 -36
- 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 +360 -27
- package/sidecar/talaria_sidecar/methods/commands.py +46 -31
- package/sidecar/talaria_sidecar/methods/config.py +14 -10
- package/sidecar/talaria_sidecar/methods/cron.py +22 -14
- package/sidecar/talaria_sidecar/methods/oauth.py +439 -0
- package/sidecar/talaria_sidecar/methods/process.py +318 -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 -119
- 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-emii55o0.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-m6nx9g8t.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-kejgxpil.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-eu64w89w.js +1 -0
- package/static/dist/assets/{blockDiagram-I7D4REHJ-l1466a7j.js → blockDiagram-I7D4REHJ-n79st4pj.js} +1 -1
- package/static/dist/assets/{c4Diagram-7LVT6UL2-gg3aq3sr.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-oalgz5l8.js → chunk-4HAMMTFA-laat0g1q.js} +1 -1
- package/static/dist/assets/{chunk-75Z2AOVW-babmzhdg.js → chunk-75Z2AOVW-0psy1tr2.js} +1 -1
- package/static/dist/assets/{chunk-DU6HZSFF-lagu350c.js → chunk-DU6HZSFF-lw8uox8x.js} +3 -3
- package/static/dist/assets/{chunk-F27PBJKO-gjh2tqif.js → chunk-F27PBJKO-erassib3.js} +1 -1
- package/static/dist/assets/{chunk-GMAD6QVW-ipdgja5c.js → chunk-GMAD6QVW-fz7rx619.js} +1 -1
- package/static/dist/assets/{chunk-GVQU2GXP-j8wkn1at.js → chunk-GVQU2GXP-gdb0epb2.js} +1 -1
- package/static/dist/assets/{chunk-IMKFNOWR-k00laqyk.js → chunk-IMKFNOWR-ea8t26qw.js} +1 -1
- package/static/dist/assets/{chunk-L3NEJ4N5-fju6xqj4.js → chunk-L3NEJ4N5-mb1gu9kz.js} +1 -1
- package/static/dist/assets/{chunk-OSK3NFVY-bi6widqt.js → chunk-OSK3NFVY-eovmccvy.js} +1 -1
- package/static/dist/assets/{chunk-P2QGCYS3-czr4tebv.js → chunk-P2QGCYS3-bo55zjo5.js} +1 -1
- package/static/dist/assets/{chunk-POPQ4Y6H-ktdhn67w.js → chunk-POPQ4Y6H-ja7ohe4h.js} +1 -1
- package/static/dist/assets/{chunk-PWAF6VOD-ii4dsu0d.js → chunk-PWAF6VOD-e30g9nus.js} +1 -1
- package/static/dist/assets/{chunk-SHT3W25Y-fpwk3xxp.js → chunk-SHT3W25Y-gbb798f7.js} +3 -3
- package/static/dist/assets/{chunk-SVP7TREG-k0jrvhei.js → chunk-SVP7TREG-h2iw8urm.js} +1 -1
- package/static/dist/assets/{chunk-TICWLB2K-nkqv9ot0.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-gpchexqu.js → copied-h65fc3cx.js} +1 -1
- package/static/dist/assets/copy-e6977uwq.js +1 -0
- package/static/dist/assets/{cynefin-OW5HDTMX-lqxt8rs3.js → cynefin-OW5HDTMX-lbltyl5j.js} +1 -1
- package/static/dist/assets/{cynefinDiagram-5FMLGOSQ-j9eqovf5.js → cynefinDiagram-5FMLGOSQ-lxhsqq4a.js} +1 -1
- package/static/dist/assets/{dagre-GXQ25YYZ-m9agobjm.js → dagre-GXQ25YYZ-gn4nnaln.js} +4 -4
- package/static/dist/assets/{diagram-S7CK7UJ4-itodc50c.js → diagram-S7CK7UJ4-pa3ij6q7.js} +3 -3
- package/static/dist/assets/{diagram-UQ7AKVKN-n1h2t4ah.js → diagram-UQ7AKVKN-zbipyz57.js} +1 -1
- package/static/dist/assets/{diagram-VSXAHHWV-lvtvm9bj.js → diagram-VSXAHHWV-d1kbpzgf.js} +1 -1
- package/static/dist/assets/{diagram-VX7I27RA-cgas58sy.js → diagram-VX7I27RA-i3ty14xl.js} +1 -1
- package/static/dist/assets/{diagram-Z3DM3KII-d0aeps1q.js → diagram-Z3DM3KII-m8xefqa7.js} +1 -1
- package/static/dist/assets/{ebnfDiagram-PWID7BFC-md345fyq.js → ebnfDiagram-PWID7BFC-nz7wj05l.js} +1 -1
- package/static/dist/assets/endpoints-k7yf25m0.js +64 -0
- package/static/dist/assets/{erDiagram-RLTQ6QDP-i4rua63b.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-geqx7zgl.js → ganttDiagram-EL5Y4UJY-n7zq01qu.js} +1 -1
- package/static/dist/assets/{gitGraph-4MIJSDKK-leoq0z8t.js → gitGraph-4MIJSDKK-c89emb07.js} +1 -1
- package/static/dist/assets/{gitGraphDiagram-WWUBYQGX-llrlxfha.js → gitGraphDiagram-WWUBYQGX-cz7cgr6w.js} +1 -1
- package/static/dist/assets/{highlighted-body-KPVGNVTW-kq2cnw6q.js → highlighted-body-KPVGNVTW-d9bapmni.js} +1 -1
- package/static/dist/assets/{index-f9bzglkn.js → index-h00usru2.js} +3 -3
- package/static/dist/assets/index-n73ijkv2.css +2 -0
- package/static/dist/assets/{info-A6RAGUB7-lkly4xj6.js → info-A6RAGUB7-ndddhhhh.js} +1 -1
- package/static/dist/assets/infoDiagram-27XIBGKW-ccxigcpf.js +2 -0
- package/static/dist/assets/{ishikawaDiagram-5VMMS53U-hq6jf374.js → ishikawaDiagram-5VMMS53U-le0z9vtc.js} +1 -1
- package/static/dist/assets/{journeyDiagram-3NMN7TZE-is03ntb0.js → journeyDiagram-3NMN7TZE-ivsmb26o.js} +1 -1
- package/static/dist/assets/{kanban-definition-UXKFOSKX-jmerizqb.js → kanban-definition-UXKFOSKX-h6n2awt0.js} +1 -1
- package/static/dist/assets/lazyRouteComponent-m1rtyk4t.js +1 -0
- package/static/dist/assets/{line-laaa8h99.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-ix4junux.js → mermaid-parser.core-gwyd5bnq.js} +3 -3
- package/static/dist/assets/{mindmap-definition-YA3MSWOX-o0e0adl1.js → mindmap-definition-YA3MSWOX-l68gg5h7.js} +1 -1
- package/static/dist/assets/onboarding-cdfrk0pj.js +1 -0
- package/static/dist/assets/{packet-AYTQ26CC-kl8pwsyg.js → packet-AYTQ26CC-gpv06065.js} +1 -1
- package/static/dist/assets/{pegDiagram-XKGWAZYB-bbqn9jo4.js → pegDiagram-XKGWAZYB-e52vs23u.js} +1 -1
- package/static/dist/assets/{pie-WAS4IAKB-cpyo8bkr.js → pie-WAS4IAKB-l6m7nz5s.js} +1 -1
- package/static/dist/assets/{pieDiagram-E7YTZNPT-pelug34f.js → pieDiagram-E7YTZNPT-b4is36bq.js} +3 -3
- package/static/dist/assets/{quadrantDiagram-AXDQQJYC-jds4jmr5.js → quadrantDiagram-AXDQQJYC-m8vt2788.js} +1 -1
- package/static/dist/assets/{radar-RG4KPBEZ-e02oxnvd.js → radar-RG4KPBEZ-nxbrhiov.js} +1 -1
- package/static/dist/assets/{railroad-74A4TZTK-kz3delwo.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-jgroj2ew.js → railroadDiagram-O6MQD6OU-o8lldfzv.js} +1 -1
- package/static/dist/assets/{refresh-cw-k7yxjdn3.js → refresh-cw-kbcje1uy.js} +1 -1
- package/static/dist/assets/{requirementDiagram-BXWQKSXE-m4az5e0j.js → requirementDiagram-BXWQKSXE-ovyq38kv.js} +1 -1
- package/static/dist/assets/{sankeyDiagram-P5KCCOFB-vlryqiv3.js → sankeyDiagram-P5KCCOFB-ou7lznor.js} +1 -1
- package/static/dist/assets/{saved-brdfjjnw.js → saved-bazmcup9.js} +1 -1
- package/static/dist/assets/search-jen74z4u.js +1 -0
- package/static/dist/assets/{sequenceDiagram-WJ2MYXX4-fr8hrpql.js → sequenceDiagram-WJ2MYXX4-ovckdzf2.js} +1 -1
- package/static/dist/assets/{settings_section_extensions_title-l0zodj0b.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-gcgscv8r.js → sliders-horizontal-f9cb3lh3.js} +1 -1
- package/static/dist/assets/{stateDiagram-D77RDMKH-bg548iyr.js → stateDiagram-D77RDMKH-fcrexkkv.js} +1 -1
- package/static/dist/assets/stateDiagram-v2-MP3YSRHH-lcfraua2.js +1 -0
- package/static/dist/assets/{swimlanes-42K2YHIH-hk5z3efh.js → swimlanes-42K2YHIH-f7usu8fw.js} +1 -1
- package/static/dist/assets/swimlanesDiagram-VR7AAH4N-ogmanni0.js +8 -0
- package/static/dist/assets/{timeline-definition-24CTP7MA-olvknr62.js → timeline-definition-24CTP7MA-gp1hvz9f.js} +1 -1
- package/static/dist/assets/todoStore-eqtid4r4.js +1 -0
- package/static/dist/assets/{treeView-Q6P3EWNA-ovvjsxtf.js → treeView-Q6P3EWNA-gb9gf11u.js} +1 -1
- package/static/dist/assets/{treemap-WGGIJYW6-ggkipj59.js → treemap-WGGIJYW6-nuvfnvvi.js} +1 -1
- package/static/dist/assets/{untitled-c8ydw0bu.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-katwvzil.js → useParams-dqd64jv7.js} +1 -1
- package/static/dist/assets/{useSearch-c70sgau1.js → useSearch-j30pvsy7.js} +1 -1
- package/static/dist/assets/{vennDiagram-4TSXK5OY-hzld7zt7.js → vennDiagram-4TSXK5OY-fzchbzaj.js} +1 -1
- package/static/dist/assets/{wardley-WFR3VGLG-hxkeoms8.js → wardley-WFR3VGLG-m47mhfbh.js} +1 -1
- package/static/dist/assets/{wardleyDiagram-VM6X3IG4-ljh90mb1.js → wardleyDiagram-VM6X3IG4-odg6ct1z.js} +2 -2
- package/static/dist/assets/{xychartDiagram-S5SC5T6Z-mnuaes03.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-haqi9qzu.js +0 -1
- package/static/dist/assets/ChatPage-hjyu2g64.js +0 -22
- package/static/dist/assets/HubRoute-gkd8o1vg.js +0 -2
- package/static/dist/assets/RightPanel-o73y98dn.js +0 -1
- package/static/dist/assets/Select-jld3yeni.js +0 -1
- package/static/dist/assets/SessionListPanel-d3qx4ric.js +0 -1
- package/static/dist/assets/SettingsLayout-lnn2wo2s.js +0 -1
- package/static/dist/assets/States-e5hv6gdh.js +0 -1
- package/static/dist/assets/Toaster-c4jq1i26.js +0 -1
- package/static/dist/assets/_app-bnip2pjg.js +0 -1
- package/static/dist/assets/_app.ext._extensionId-egptzrfy.js +0 -1
- package/static/dist/assets/_app.index-vdz13ul5.js +0 -1
- package/static/dist/assets/_app.insights-lgjshsba.js +0 -1
- package/static/dist/assets/_app.kanban-c18cjrpz.js +0 -1
- package/static/dist/assets/_app.logs-ezhojgeg.js +0 -1
- package/static/dist/assets/_app.memory-i00paisv.js +0 -1
- package/static/dist/assets/_app.profiles-kd02bwjx.js +0 -1
- package/static/dist/assets/_app.settings-giaudkuk.js +0 -1
- package/static/dist/assets/_app.settings._section-k4qtlexk.js +0 -1
- package/static/dist/assets/_app.skills-bby2uvl8.js +0 -1
- package/static/dist/assets/_app.tasks-1kz9bosm.js +0 -2
- package/static/dist/assets/_app.todos-izjdbkm2.js +0 -1
- package/static/dist/assets/_app.workspaces-lfh2kw7s.js +0 -1
- package/static/dist/assets/architecture-7GRP2DOG-b4u9z1w3.js +0 -1
- package/static/dist/assets/architectureDiagram-5GKGNRK7-hqnf84fc.js +0 -36
- package/static/dist/assets/channel-o77ioktg.js +0 -1
- package/static/dist/assets/classDiagram-ZZMXUADV-f5rvod26.js +0 -1
- package/static/dist/assets/classDiagram-v2-VYDZK3BY-f5rvod26.js +0 -1
- package/static/dist/assets/endpoints-e58saih3.js +0 -9
- package/static/dist/assets/eventmodeling-NTZA5JFV-bn3fjsaq.js +0 -1
- package/static/dist/assets/flowDiagram-HODETNUW-li70d120.js +0 -1
- package/static/dist/assets/index-gkh7kum4.css +0 -2
- package/static/dist/assets/infoDiagram-27XIBGKW-oo7kdyte.js +0 -2
- package/static/dist/assets/lazyRouteComponent-b1h2ykmb.js +0 -1
- package/static/dist/assets/link-d8f0788e.js +0 -1
- package/static/dist/assets/login-llkohrcg.js +0 -1
- package/static/dist/assets/mermaid-HWGCJPDP-id0ffk2r.js +0 -1
- package/static/dist/assets/onboarding-lx0d6b38.js +0 -1
- package/static/dist/assets/railroad-abnf-HS5TGJTU-l13ped2z.js +0 -1
- package/static/dist/assets/railroad-ebnf-LZEXJU2U-c7rg3g4g.js +0 -1
- package/static/dist/assets/railroad-peg-WCYAUIDC-od0b8niq.js +0 -1
- package/static/dist/assets/search-gt2ueyvg.js +0 -1
- package/static/dist/assets/share._token-oyjv046r.js +0 -2
- package/static/dist/assets/stateDiagram-v2-MP3YSRHH-j5v40qih.js +0 -1
- package/static/dist/assets/swimlanesDiagram-VR7AAH4N-grzefo9c.js +0 -8
- package/static/dist/assets/tabBuild-idliyw9f.js +0 -56
- package/static/dist/assets/todoStore-j4c2xq0b.js +0 -1
- package/static/dist/assets/useForm-kd759sjk.js +0 -1
- package/static/dist/assets/useLocale-hds4xmja.js +0 -1
package/dist/sessions/merge.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { buildActiveTurnToken } from '../redact.js';
|
|
7
7
|
import { str } from '../util.js';
|
|
8
|
+
import { stripAttachedFilesMarker } from './session.js';
|
|
8
9
|
export const WORKSPACE_PREFIX_RE = /^\s*\[Workspace::v1:\s*(?:\\.|[^\]\\])+\]\s*/;
|
|
9
10
|
const LEGACY_WORKSPACE_PREFIX_RE = /^\s*\[Workspace:[^\]]+\]\s*/;
|
|
10
11
|
const TOOL_RESULT_SNIPPET_MAX = 4000;
|
|
@@ -59,8 +60,15 @@ export function messageIdentity(msg) {
|
|
|
59
60
|
return null;
|
|
60
61
|
const role = str(msg.role);
|
|
61
62
|
let text = messageText(msg.content);
|
|
62
|
-
if (role === 'user')
|
|
63
|
-
|
|
63
|
+
if (role === 'user') {
|
|
64
|
+
const typed = userPromptText(text);
|
|
65
|
+
// An attachment-only prompt has no typed text; its whole attached-files line (never truncated) tells one such turn
|
|
66
|
+
// from the next.
|
|
67
|
+
const line = typed ? '' : stripWorkspacePrefix(text, true);
|
|
68
|
+
if (line)
|
|
69
|
+
return JSON.stringify([role, line, '', '[]']);
|
|
70
|
+
text = typed;
|
|
71
|
+
}
|
|
64
72
|
if (!text && !msg.tool_call_id && !msg.tool_calls) {
|
|
65
73
|
if (msg._partial)
|
|
66
74
|
return JSON.stringify([role, '', '', `__partial__${str(msg.reasoning).split(/\s+/).join(' ').slice(0, 200)}`]);
|
|
@@ -88,22 +96,57 @@ export function messagesHavePrefix(messages, prefix) {
|
|
|
88
96
|
return false;
|
|
89
97
|
return true;
|
|
90
98
|
}
|
|
91
|
-
|
|
99
|
+
const PRESERVED_TASK_LIST_PREFIX = '[your active task list was preserved across context compression]';
|
|
100
|
+
const hasPrefix = (text, prefix) => text.slice(0, prefix.length).toLowerCase() === prefix;
|
|
101
|
+
/**
|
|
102
|
+
* TAL-305: the one rule for the marker rows the Agent writes around context compaction. A flagged row, or a user or
|
|
103
|
+
* assistant row starting `[context compaction`, is a compaction summary; a user row starting with the preserved-task-list
|
|
104
|
+
* line is that list. Both ignore case and leading whitespace; prose that merely mentions compaction is no marker.
|
|
105
|
+
*/
|
|
106
|
+
export function markerKind(msg) {
|
|
92
107
|
if (!isDict(msg))
|
|
93
|
-
return
|
|
108
|
+
return null;
|
|
94
109
|
if (msg._context_compression_marker || msg._compression_marker || msg._compaction_marker)
|
|
95
|
-
return
|
|
96
|
-
const
|
|
97
|
-
|
|
110
|
+
return 'context_compaction';
|
|
111
|
+
const role = str(msg.role);
|
|
112
|
+
const text = messageText(msg.content).trimStart();
|
|
113
|
+
if (role === 'user' && hasPrefix(text, PRESERVED_TASK_LIST_PREFIX))
|
|
114
|
+
return 'preserved_task_list';
|
|
115
|
+
if ((role === 'user' || role === 'assistant') && hasPrefix(text, '[context compaction'))
|
|
116
|
+
return 'context_compaction';
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
export function isContextCompressionMarker(msg) {
|
|
120
|
+
return markerKind(msg) === 'context_compaction';
|
|
98
121
|
}
|
|
99
|
-
|
|
122
|
+
/**
|
|
123
|
+
* TAL-305: stamps `_marker_kind` on marker rows, and `_marker_body` (the list without its marker line) on a preserved
|
|
124
|
+
* task list, so clients render a marker card instead of a message. Returns copies; stored rows are untouched.
|
|
125
|
+
*/
|
|
126
|
+
export function withMarkerKinds(messages) {
|
|
127
|
+
return messages.map((m) => {
|
|
128
|
+
const kind = markerKind(m);
|
|
129
|
+
if (!kind || !isDict(m))
|
|
130
|
+
return m;
|
|
131
|
+
if (kind === 'context_compaction')
|
|
132
|
+
return { ...m, _marker_kind: kind };
|
|
133
|
+
const body = messageText(m.content).trim().slice(PRESERVED_TASK_LIST_PREFIX.length).trim();
|
|
134
|
+
return { ...m, _marker_kind: kind, _marker_body: body };
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
/** A user prompt as the user typed it: without the workspace prefix and the attached-files line the server adds. */
|
|
138
|
+
const userPromptText = (text) => stripWorkspacePrefix(stripAttachedFilesMarker(text), true);
|
|
139
|
+
const normalizeUserText = (text) => userPromptText(text).split(/\s+/).join(' ').trim();
|
|
100
140
|
export function looksLikeCurrentUserTurn(msg, msgText) {
|
|
101
141
|
// A persisted steer is display-only: it is never the prompt that opened a turn.
|
|
102
142
|
if (!isDict(msg) || str(msg.role) !== 'user' || isDict(msg._steer))
|
|
103
143
|
return false;
|
|
104
144
|
const candidate = normalizeUserText(messageText(msg.content));
|
|
105
145
|
const target = normalizeUserText(msgText);
|
|
106
|
-
|
|
146
|
+
// An attachment-only prompt (TAL-276) has no text: the Agent's row for it carries none either.
|
|
147
|
+
if (!target)
|
|
148
|
+
return !candidate;
|
|
149
|
+
if (!candidate)
|
|
107
150
|
return false;
|
|
108
151
|
return candidate === target || candidate.startsWith(`${target}\n`) || candidate.endsWith(target);
|
|
109
152
|
}
|
|
@@ -222,10 +265,13 @@ export function mergeDisplayMessagesAfterAgentResult(previousDisplay, previousCo
|
|
|
222
265
|
const merged = [...prev];
|
|
223
266
|
const seen = new Set(merged.map(messageIdentity).filter((k) => k !== null));
|
|
224
267
|
const currentUserKey = messageIdentity({ role: 'user', content: msgText });
|
|
225
|
-
const currentUserIn = candidates.some((m) => messageIdentity(m) === currentUserKey || looksLikeCurrentUserTurn(m, msgText));
|
|
268
|
+
const currentUserIn = candidates.some((m) => (currentUserKey !== null && messageIdentity(m) === currentUserKey) || looksLikeCurrentUserTurn(m, msgText));
|
|
226
269
|
const alreadyCheckpointed = Boolean(opts.activeTurnToken) && merged.some((m) => isDict(m) && m.role === 'user' && m._active_turn_token === opts.activeTurnToken);
|
|
227
|
-
|
|
270
|
+
const promptless = currentUserKey === null && Boolean(opts.attachments?.length);
|
|
271
|
+
if ((currentUserKey !== null || promptless) && !currentUserIn && !alreadyCheckpointed && candidates.some((m) => isDict(m) && (m.role === 'assistant' || m.role === 'tool'))) {
|
|
228
272
|
const user = { role: 'user', content: msgText, timestamp: opts.now ?? Date.now() / 1000 };
|
|
273
|
+
if (promptless)
|
|
274
|
+
user.attachments = [...opts.attachments];
|
|
229
275
|
if (opts.activeTurnToken)
|
|
230
276
|
user._active_turn_token = opts.activeTurnToken;
|
|
231
277
|
if (opts.turnId)
|
|
@@ -243,7 +289,7 @@ export function mergeDisplayMessagesAfterAgentResult(previousDisplay, previousCo
|
|
|
243
289
|
const key = messageIdentity(msg);
|
|
244
290
|
const isCurrentUser = looksLikeCurrentUserTurn(msg, msgText);
|
|
245
291
|
const last = merged[merged.length - 1];
|
|
246
|
-
if (((key !== null && key === currentUserKey) || isCurrentUser) && last && (messageIdentity(last) === currentUserKey || looksLikeCurrentUserTurn(last, msgText))) {
|
|
292
|
+
if (((key !== null && key === currentUserKey) || isCurrentUser) && last && ((currentUserKey !== null && messageIdentity(last) === currentUserKey) || looksLikeCurrentUserTurn(last, msgText))) {
|
|
247
293
|
if (isDict(msg) && msg.id !== undefined && isDict(last) && last.id === undefined)
|
|
248
294
|
last.id = msg.id;
|
|
249
295
|
continue;
|
|
@@ -298,10 +344,134 @@ function presentError(v) {
|
|
|
298
344
|
return v.length > 0;
|
|
299
345
|
return isDict(v) ? Object.keys(v).length > 0 : v === true;
|
|
300
346
|
}
|
|
347
|
+
const RESULT_TEXT_KEYS = ['result', 'results', 'preview', 'content', 'text', 'message', 'summary', 'data', 'items'];
|
|
348
|
+
const RESULT_VIEW_MAX_DEPTH = 8;
|
|
349
|
+
const tryJson = (text) => { try {
|
|
350
|
+
return JSON.parse(text);
|
|
351
|
+
}
|
|
352
|
+
catch {
|
|
353
|
+
return undefined;
|
|
354
|
+
} };
|
|
355
|
+
const prettyJson = (value) => { try {
|
|
356
|
+
return JSON.stringify(value, null, 2);
|
|
357
|
+
}
|
|
358
|
+
catch {
|
|
359
|
+
return str(value);
|
|
360
|
+
} };
|
|
361
|
+
/** Line breaks and tabs a JSON-encoded result left escaped (`\n`, `\\n`), as the characters they stand for. */
|
|
362
|
+
const unescapeResultText = (text) => text.replace(/\r\n/g, '\n').replace(/\\{1,2}r\\{1,2}n|\\{1,2}n/g, '\n').replace(/\\{1,2}t/g, '\t');
|
|
363
|
+
/** The JSON a result string holds: as written, else with its escaped quotes undone; nested JSON strings unwrap three levels. */
|
|
364
|
+
function resultJson(text) {
|
|
365
|
+
const trimmed = text.trim();
|
|
366
|
+
let value = tryJson(trimmed);
|
|
367
|
+
if (value === undefined && trimmed.includes('\\"'))
|
|
368
|
+
value = tryJson(trimmed.replaceAll('\\"', '"'));
|
|
369
|
+
for (let i = 0; i < 3 && typeof value === 'string'; i += 1) {
|
|
370
|
+
const inner = tryJson(value.trim());
|
|
371
|
+
if (inner === undefined)
|
|
372
|
+
break;
|
|
373
|
+
value = inner;
|
|
374
|
+
}
|
|
375
|
+
return value;
|
|
376
|
+
}
|
|
377
|
+
/** A section's text: a string unescaped, a scalar as written, a structure as pretty JSON; `undefined` when blank. */
|
|
378
|
+
function sectionText(value) {
|
|
379
|
+
const text = typeof value === 'string' ? unescapeResultText(value) : typeof value === 'number' || typeof value === 'boolean' ? String(value) : value === null || value === undefined ? '' : prettyJson(value);
|
|
380
|
+
return text.trim() || undefined;
|
|
381
|
+
}
|
|
382
|
+
/** An exit code: an integer, or a string of one; anything else is dropped. */
|
|
383
|
+
function exitCodeOf(value) {
|
|
384
|
+
const n = typeof value === 'number' ? Math.trunc(value) : typeof value === 'string' && /^\s*[+-]?\d+\s*$/.test(value) ? Number(value) : NaN;
|
|
385
|
+
return Number.isSafeInteger(n) ? n : undefined;
|
|
386
|
+
}
|
|
387
|
+
/** A terminal result's sections; the exit code only when it is non-zero or nothing else would show. */
|
|
388
|
+
function terminalView(data) {
|
|
389
|
+
const view = {};
|
|
390
|
+
const stdout = sectionText(data.output) ?? sectionText(data.stdout);
|
|
391
|
+
const stderr = sectionText(data.stderr);
|
|
392
|
+
const error = sectionText(data.error);
|
|
393
|
+
if (stdout)
|
|
394
|
+
view.stdout = stdout;
|
|
395
|
+
if (stderr)
|
|
396
|
+
view.stderr = stderr;
|
|
397
|
+
if (error)
|
|
398
|
+
view.error = error;
|
|
399
|
+
const exit = exitCodeOf(data.exit_code ?? data.exitCode);
|
|
400
|
+
if (exit !== undefined && (exit !== 0 || !Object.keys(view).length))
|
|
401
|
+
view.exit_code = exit;
|
|
402
|
+
return view;
|
|
403
|
+
}
|
|
404
|
+
/** Every item of a list is a text part (`text`, `content` or `message`): their texts, one per line. */
|
|
405
|
+
function textParts(items) {
|
|
406
|
+
const texts = items.map((item) => (isDict(item) ? sectionText(item.text) ?? sectionText(item.content) ?? sectionText(item.message) : undefined));
|
|
407
|
+
return texts.length && texts.every(Boolean) ? texts.join('\n') : undefined;
|
|
408
|
+
}
|
|
409
|
+
const isEmptyView = (view) => Object.keys(view).length === 0;
|
|
410
|
+
function resultView(value, depth) {
|
|
411
|
+
if (typeof value === 'string') {
|
|
412
|
+
const parsed = depth < RESULT_VIEW_MAX_DEPTH ? resultJson(value) : undefined;
|
|
413
|
+
if (parsed !== undefined && typeof parsed !== 'string') {
|
|
414
|
+
const view = resultView(parsed, depth + 1);
|
|
415
|
+
if (!isEmptyView(view))
|
|
416
|
+
return view;
|
|
417
|
+
}
|
|
418
|
+
// Top-level text that is not JSON shows exactly as written; strings inside JSON are unescaped.
|
|
419
|
+
const text = depth === 0 && parsed === undefined ? value.trim() : sectionText(typeof parsed === 'string' ? parsed : value);
|
|
420
|
+
return text ? { text } : {};
|
|
421
|
+
}
|
|
422
|
+
if (Array.isArray(value)) {
|
|
423
|
+
const text = textParts(value) ?? sectionText(value);
|
|
424
|
+
return text ? { text } : {};
|
|
425
|
+
}
|
|
426
|
+
if (!isDict(value)) {
|
|
427
|
+
const text = sectionText(value);
|
|
428
|
+
return text ? { text } : {};
|
|
429
|
+
}
|
|
430
|
+
if (depth >= RESULT_VIEW_MAX_DEPTH)
|
|
431
|
+
return { text: prettyJson(value) };
|
|
432
|
+
// A process result: its output streams, error and exit code.
|
|
433
|
+
if (sectionText(value.output) ?? sectionText(value.stdout) ?? sectionText(value.stderr))
|
|
434
|
+
return terminalView(value);
|
|
435
|
+
for (const key of RESULT_TEXT_KEYS) {
|
|
436
|
+
const view = resultView(value[key], depth + 1);
|
|
437
|
+
if (!isEmptyView(view))
|
|
438
|
+
return view;
|
|
439
|
+
}
|
|
440
|
+
const terminal = terminalView(value);
|
|
441
|
+
if (!isEmptyView(terminal))
|
|
442
|
+
return terminal;
|
|
443
|
+
return Object.keys(value).length ? { text: prettyJson(value) } : {};
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* The server's one result view rule (TAL-315), ported from the iOS formatter so every client renders the same sections:
|
|
447
|
+
* a JSON result (nested JSON strings unwrapped, escaped line breaks undone) with `output`/`stdout`/`stderr` maps to its
|
|
448
|
+
* terminal sections; any other object shows the first readable `result`, `results`, `preview`, `content`, `text`,
|
|
449
|
+
* `message`, `summary`, `data` or `items`, else its `error` and exit code, else pretty JSON. A list of text parts joins
|
|
450
|
+
* by line; a scalar shows as text, and a result that is not JSON exactly as written. Each field is capped like the snippet
|
|
451
|
+
* (`limit`; TAL-331's whole-result read passes `Infinity`).
|
|
452
|
+
*/
|
|
453
|
+
export function toolResultView(raw, limit = TOOL_RESULT_SNIPPET_MAX) {
|
|
454
|
+
// Content parts read as their text; a list with no text (`[{ title }]`) is the result itself.
|
|
455
|
+
const flat = Array.isArray(raw) ? messageText(raw) : raw;
|
|
456
|
+
const view = resultView(Array.isArray(raw) && !str(flat).trim() ? raw : flat, 0);
|
|
457
|
+
return Object.fromEntries(Object.entries(view).map(([key, field]) => [key, typeof field === 'string' ? toolResultSnippet(field, limit) : field]));
|
|
458
|
+
}
|
|
459
|
+
/** A view the server already decided (a built scene row, or one stored with its scene): its known fields, capped. */
|
|
460
|
+
export function decidedResultView(value) {
|
|
461
|
+
const view = {};
|
|
462
|
+
for (const key of ['text', 'stdout', 'stderr', 'error']) {
|
|
463
|
+
const field = value[key];
|
|
464
|
+
if (typeof field === 'string' && field)
|
|
465
|
+
view[key] = toolResultSnippet(field);
|
|
466
|
+
}
|
|
467
|
+
if (typeof value.exit_code === 'number' && Number.isSafeInteger(value.exit_code))
|
|
468
|
+
view.exit_code = value.exit_code;
|
|
469
|
+
return view;
|
|
470
|
+
}
|
|
301
471
|
/**
|
|
302
472
|
* The server's one tool outcome rule (TAL-313), for a live `raw_result` and a persisted tool-role content alike: a result
|
|
303
473
|
* is an error when it parses to an object with a non-empty `error`, a non-zero numeric `exit_code` / `exitCode`, or
|
|
304
|
-
* `success: false`. `result_text` is the result's display snippet.
|
|
474
|
+
* `success: false`. `result_text` is the result's display snippet; `result_view` its display sections (TAL-315).
|
|
305
475
|
*/
|
|
306
476
|
export function toolOutcome(raw) {
|
|
307
477
|
const value = Array.isArray(raw) ? messageText(raw) : raw;
|
|
@@ -316,7 +486,7 @@ export function toolOutcome(raw) {
|
|
|
316
486
|
}
|
|
317
487
|
const exit = isDict(data) ? data.exit_code ?? data.exitCode : undefined;
|
|
318
488
|
const isError = isDict(data) && (presentError(data.error) || (typeof exit === 'number' && exit !== 0) || data.success === false);
|
|
319
|
-
return { is_error: isError, result_text: toolResultSnippet(value) };
|
|
489
|
+
return { is_error: isError, result_text: toolResultSnippet(value), result_view: toolResultView(raw) };
|
|
320
490
|
}
|
|
321
491
|
const finiteOrNull = (v) => (typeof v === 'number' && Number.isFinite(v) ? v : null);
|
|
322
492
|
function nearestAssistantIdx(messages, msgIdx) {
|
|
@@ -428,7 +598,8 @@ export function extractToolCallsFromMessages(messages, liveToolCalls = [], recor
|
|
|
428
598
|
* a call only the session-level list recorded joins the row at its `assistant_msg_idx`, a failed or cancelled turn's
|
|
429
599
|
* partial snapshot shows the live calls it kept, and every call carries `done`
|
|
430
600
|
* (answered, or outside the running turn), `is_error` (`toolOutcome` of its result, else the recorded value), `duration`
|
|
431
|
-
* (recorded live, else `null`)
|
|
601
|
+
* (recorded live, else `null`), `result` (the result snippet, else `null`) and `result_view` (its display sections, TAL-315,
|
|
602
|
+
* else `null`). Returns copies; stored rows are untouched.
|
|
432
603
|
*/
|
|
433
604
|
export function withToolCallOutcomes(messages, sessionToolCalls, activeTurnId) {
|
|
434
605
|
// Every identifier a stored call may carry (`ToolCallSchema`).
|
|
@@ -505,6 +676,7 @@ export function withToolCallOutcomes(messages, sessionToolCalls, activeTurnId) {
|
|
|
505
676
|
return {
|
|
506
677
|
done: Boolean(reply) || answered || !running, is_error: outcome ? outcome.flagged || outcome.is_error : rec?.is_error === true,
|
|
507
678
|
duration: finiteOrNull(rec?.duration), result: outcome ? outcome.result_text : typeof rec?.snippet === 'string' ? rec.snippet : null,
|
|
679
|
+
result_view: outcome ? outcome.result_view : isDict(rec?.result_view) ? decidedResultView(rec.result_view) : typeof rec?.snippet === 'string' ? toolResultView(rec.snippet) : null,
|
|
508
680
|
};
|
|
509
681
|
};
|
|
510
682
|
const projected = [
|
|
@@ -537,21 +709,130 @@ export function buildPartialMessage(contentText, reasoningText, toolCalls, now =
|
|
|
537
709
|
msg._partial_tool_calls = [...toolCalls];
|
|
538
710
|
return msg;
|
|
539
711
|
}
|
|
540
|
-
|
|
541
|
-
|
|
712
|
+
const DSML = '(?:\\s*|\\s*DSML\\s*[||]\\s*)?';
|
|
713
|
+
/** Markdown code (fenced blocks, an unclosed one running to the end, and inline spans): markup written there is literal. */
|
|
714
|
+
function codeRanges(text) {
|
|
715
|
+
const code = /^ {0,3}(`{3,}|~{3,})[^\n]*(?:\n[\s\S]*?(?:\n {0,3}\1[^\n]*(?=\n|$)|(?![\s\S]))|(?![\s\S]))|(`+)(?!`)(?:[^\n]|\n(?!\n))*?(?<!`)\2(?!`)/gm;
|
|
716
|
+
return [...text.matchAll(code)].map((m) => [m.index, m.index + m[0].length]);
|
|
717
|
+
}
|
|
718
|
+
const inCode = (code, at) => code.some(([from, to]) => at >= from && at < to);
|
|
719
|
+
/** `re` matches removed, except the ones that start inside Markdown code. */
|
|
720
|
+
function removeOutsideCode(text, re) {
|
|
721
|
+
const code = codeRanges(text);
|
|
722
|
+
return text.replace(re, (match, ...rest) => (inCode(code, rest.find((x) => typeof x === 'number') ?? 0) ? match : ''));
|
|
542
723
|
}
|
|
543
|
-
/**
|
|
544
|
-
export function
|
|
545
|
-
const
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
return [
|
|
724
|
+
/** Remove provider tool-call XML (`<function_calls>…`, DSML variants, `<tool_call>`), closed or cut off, that leaks into text. */
|
|
725
|
+
export function stripToolCallXml(text) {
|
|
726
|
+
const lo = text.toLowerCase();
|
|
727
|
+
if (!lo.includes('function_calls') && !lo.includes('dsml') && !lo.includes('<tool_call'))
|
|
728
|
+
return text;
|
|
729
|
+
return [
|
|
730
|
+
new RegExp(`<${DSML}function_calls>[\\s\\S]*?<\\/${DSML}function_calls>`, 'gi'),
|
|
731
|
+
new RegExp(`<${DSML}function_calls(?:>|$)[\\s\\S]*$`, 'i'),
|
|
732
|
+
/<tool_call>[\s\S]*?<\/tool_call>/gi,
|
|
733
|
+
/<tool_call>[\s\S]*$/i,
|
|
734
|
+
/<\s*|\s*DSML\s*[||]\s*/gi,
|
|
735
|
+
].reduce(removeOutsideCode, text).replace(/^\s+/, '').trimEnd();
|
|
736
|
+
}
|
|
737
|
+
/** Inline thinking openers: `<think>`/`<thinking>` in any case and with attributes (as the Agent's own split), and the channel forms. */
|
|
738
|
+
const THINK_OPEN = /<think(?:ing)?(?:\s[^>]*)?>|<\|channel\|>thought|<\|turn\|>thinking/gi;
|
|
739
|
+
function thinkClose(open) {
|
|
740
|
+
if (open.toLowerCase().startsWith('<|channel|>'))
|
|
741
|
+
return /<channel\|>/gi;
|
|
742
|
+
if (open.toLowerCase().startsWith('<|turn|>'))
|
|
743
|
+
return /<turn\|>/gi;
|
|
744
|
+
return /<\/think(?:ing)?\s*>/gi;
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* Split assistant text into its visible prose and its inline thinking: every `<think>`, `<thinking>`,
|
|
748
|
+
* `<|channel|>thought` and `<|turn|>thinking` block anywhere in the text, an unterminated one running to the end.
|
|
749
|
+
* A tag written inside Markdown code is prose. Tool-call XML leaves both halves; both come back trimmed.
|
|
750
|
+
*/
|
|
751
|
+
export function splitDisplayText(text) {
|
|
752
|
+
const code = codeRanges(text);
|
|
753
|
+
let content = '';
|
|
754
|
+
const reasoning = [];
|
|
755
|
+
let cursor = 0;
|
|
756
|
+
while (cursor < text.length) {
|
|
757
|
+
THINK_OPEN.lastIndex = cursor;
|
|
758
|
+
let open = THINK_OPEN.exec(text);
|
|
759
|
+
while (open && inCode(code, open.index))
|
|
760
|
+
open = THINK_OPEN.exec(text);
|
|
761
|
+
if (!open) {
|
|
762
|
+
content += text.slice(cursor);
|
|
763
|
+
break;
|
|
764
|
+
}
|
|
765
|
+
content += text.slice(cursor, open.index);
|
|
766
|
+
const body = open.index + open[0].length;
|
|
767
|
+
const closer = thinkClose(open[0]);
|
|
768
|
+
closer.lastIndex = body;
|
|
769
|
+
const close = closer.exec(text);
|
|
770
|
+
reasoning.push(text.slice(body, close?.index));
|
|
771
|
+
if (!close)
|
|
772
|
+
break;
|
|
773
|
+
cursor = close.index + close[0].length;
|
|
774
|
+
}
|
|
775
|
+
return [stripToolCallXml(content).replace(/^\s+/, '').trimEnd(), joinReasoning(reasoning)];
|
|
776
|
+
}
|
|
777
|
+
/**
|
|
778
|
+
* Reasoning parts as one display string: tool-call XML removed, blank-line joined, each part once. A part that is
|
|
779
|
+
* whole paragraphs of another (a settled row's `reasoning` that already took in its `reasoning_content`) is dropped.
|
|
780
|
+
*/
|
|
781
|
+
export function joinReasoning(parts) {
|
|
782
|
+
const clean = parts.map((part) => stripToolCallXml(part).trim()).filter(Boolean);
|
|
783
|
+
const within = (outer, inner) => `\n\n${outer}\n\n`.includes(`\n\n${inner}\n\n`);
|
|
784
|
+
return clean.filter((p, i) => !clean.some((q, j) => j !== i && (q === p ? j < i : within(q, p)))).join('\n\n');
|
|
785
|
+
}
|
|
786
|
+
/** A message's reasoning fields as one string: `reasoning_content`, `reasoning` (text or a list of text parts), `thinking`. */
|
|
787
|
+
export function reasoningFieldsText(m) {
|
|
788
|
+
const listed = Array.isArray(m.reasoning) ? m.reasoning.map((part) => (isDict(part) ? reasoningBlockText(part) : str(part))) : [str(m.reasoning)];
|
|
789
|
+
return joinReasoning([str(m.reasoning_content), ...listed, str(m.thinking)]);
|
|
790
|
+
}
|
|
791
|
+
/**
|
|
792
|
+
* The one display shape of an assistant row: `content` without inline thinking or tool-call XML (typed `thinking` /
|
|
793
|
+
* `reasoning` parts leave a list), and every piece of reasoning in one `reasoning` string. `reasoning_content` and
|
|
794
|
+
* `thinking` are not sent. Idempotent; other rows pass through. A copy: stored rows and model history are untouched.
|
|
795
|
+
*/
|
|
796
|
+
export function normalizeAssistantDisplay(message) {
|
|
797
|
+
if (!isDict(message) || message.role !== 'assistant')
|
|
798
|
+
return message;
|
|
799
|
+
const m = { ...message };
|
|
800
|
+
delete m.reasoning_content;
|
|
801
|
+
delete m.thinking;
|
|
802
|
+
delete m.reasoning;
|
|
803
|
+
const parts = [reasoningFieldsText(message)];
|
|
804
|
+
if (typeof m.content === 'string') {
|
|
805
|
+
const [content, inline] = splitDisplayText(m.content);
|
|
806
|
+
// Only text something was taken out of is rewritten: plain prose keeps its exact whitespace (an indented code block).
|
|
807
|
+
if (content !== m.content.trim())
|
|
808
|
+
m.content = content;
|
|
809
|
+
parts.push(inline);
|
|
810
|
+
}
|
|
811
|
+
else if (Array.isArray(m.content)) {
|
|
812
|
+
m.content = m.content.flatMap((part) => {
|
|
813
|
+
if (!isDict(part))
|
|
814
|
+
return [part];
|
|
815
|
+
if (isReasoningBlock(part)) {
|
|
816
|
+
parts.push(reasoningBlockText(part));
|
|
817
|
+
return [];
|
|
818
|
+
}
|
|
819
|
+
if (typeof part.text !== 'string')
|
|
820
|
+
return [part];
|
|
821
|
+
const [text, inline] = splitDisplayText(part.text);
|
|
822
|
+
parts.push(inline);
|
|
823
|
+
return text === part.text.trim() ? [part] : text ? [{ ...part, text }] : [];
|
|
824
|
+
});
|
|
825
|
+
}
|
|
826
|
+
const reasoning = joinReasoning(parts);
|
|
827
|
+
return (reasoning ? { ...m, reasoning } : m);
|
|
549
828
|
}
|
|
550
829
|
/**
|
|
551
830
|
* Python `merge_session_messages_append_only`, bounded to its load-bearing rules: state.db rows never delete a local
|
|
552
831
|
* row; rows that replay the sidecar (same role, timestamp, and content) are skipped; rows at or before the sidecar's
|
|
553
832
|
* newest timestamp are already represented locally; a truncation watermark hides rows the user cut (0 blocks every
|
|
554
|
-
* replay)
|
|
833
|
+
* replay): rows at or before it, and, for a truncation cut, rows after it until the sidecar advances past it (TAL-504).
|
|
834
|
+
* A compression watermark only covers the compressed rows. Rows past the sidecar tail (a conversation continued from the
|
|
835
|
+
* CLI) are appended in state.db order.
|
|
555
836
|
* ponytail: the Python identity memo (api_content sidecars, message ids, workspace-prefix normalisation) is not ported;
|
|
556
837
|
* add it if a mixed WebUI/CLI transcript shows duplicated turns.
|
|
557
838
|
*/
|
|
@@ -570,7 +851,7 @@ export function mergeSessionMessagesAppendOnly(sidecar, state, opts = {}) {
|
|
|
570
851
|
}
|
|
571
852
|
if (watermark === 0)
|
|
572
853
|
return [];
|
|
573
|
-
return state.filter((m) => { const t = ts(m); return t !== null && t > watermark; });
|
|
854
|
+
return state.filter((m) => { const t = ts(m); return t !== null && (opts.compressedWatermark === true ? t > watermark : t <= watermark); });
|
|
574
855
|
}
|
|
575
856
|
const seen = new Set(sidecar.map(key));
|
|
576
857
|
let maxSidecar = null;
|
|
@@ -579,6 +860,8 @@ export function mergeSessionMessagesAppendOnly(sidecar, state, opts = {}) {
|
|
|
579
860
|
if (t !== null && (maxSidecar === null || t > maxSidecar))
|
|
580
861
|
maxSidecar = t;
|
|
581
862
|
}
|
|
863
|
+
// Until a new turn lands in the sidecar, every state.db row past the watermark is the deleted suffix.
|
|
864
|
+
const advanced = !hasWatermark || opts.compressedWatermark === true || (maxSidecar !== null && maxSidecar > watermark);
|
|
582
865
|
const merged = [...sidecar];
|
|
583
866
|
for (const m of state) {
|
|
584
867
|
const k = key(m);
|
|
@@ -587,7 +870,7 @@ export function mergeSessionMessagesAppendOnly(sidecar, state, opts = {}) {
|
|
|
587
870
|
const t = ts(m);
|
|
588
871
|
if (maxSidecar !== null && t !== null && t <= maxSidecar)
|
|
589
872
|
continue;
|
|
590
|
-
if (hasWatermark && t !== null && t <= watermark)
|
|
873
|
+
if (hasWatermark && t !== null && (t <= watermark || !advanced))
|
|
591
874
|
continue;
|
|
592
875
|
seen.add(k);
|
|
593
876
|
merged.push(m);
|
|
@@ -628,6 +911,88 @@ export function attachmentObjects(items) {
|
|
|
628
911
|
export function withAttachmentObjects(messages) {
|
|
629
912
|
return messages.map((m) => (isDict(m) && Array.isArray(m.attachments) && m.attachments.some((a) => typeof a === 'string') ? { ...m, attachments: attachmentObjects(m.attachments) } : m));
|
|
630
913
|
}
|
|
914
|
+
/** A scene's prose rows with `display_text` and `media` where `project` rewrites their text; the same array when none does. */
|
|
915
|
+
export function withSceneRowMedia(rows, project) {
|
|
916
|
+
if (!Array.isArray(rows))
|
|
917
|
+
return rows;
|
|
918
|
+
let changed = false;
|
|
919
|
+
const out = rows.map((row) => {
|
|
920
|
+
if (!isDict(row) || row.role !== 'prose' || typeof row.text !== 'string')
|
|
921
|
+
return row;
|
|
922
|
+
const projected = project(row.text);
|
|
923
|
+
if (!projected)
|
|
924
|
+
return row;
|
|
925
|
+
changed = true;
|
|
926
|
+
return { ...row, display_text: projected.text, media: projected.media };
|
|
927
|
+
});
|
|
928
|
+
return changed ? out : rows;
|
|
929
|
+
}
|
|
930
|
+
/**
|
|
931
|
+
* TAL-186: assistant rows with `_display_content` and `_media`, and their scenes with `final_answer_display` /
|
|
932
|
+
* `final_answer_media` and prose rows' `display_text` / `media`, wherever `project` rewrites media references in the
|
|
933
|
+
* text. Runs after scene hydration and before body excerpts, which are cut from the display text. Returns copies.
|
|
934
|
+
*/
|
|
935
|
+
export function withDisplayMedia(messages, project) {
|
|
936
|
+
return messages.map((m) => {
|
|
937
|
+
if (!isDict(m) || m.role !== 'assistant')
|
|
938
|
+
return m;
|
|
939
|
+
let out = m;
|
|
940
|
+
const projected = project(messageText(m.content));
|
|
941
|
+
if (projected)
|
|
942
|
+
out = { ...out, _display_content: projected.text, _media: projected.media };
|
|
943
|
+
const scene = m._anchor_activity_scene;
|
|
944
|
+
if (isDict(scene)) {
|
|
945
|
+
const final = typeof scene.final_answer === 'string' ? project(scene.final_answer) : null;
|
|
946
|
+
const rows = withSceneRowMedia(scene.activity_rows, project);
|
|
947
|
+
if (final || rows !== scene.activity_rows) {
|
|
948
|
+
out = { ...out, _anchor_activity_scene: { ...scene, activity_rows: rows, ...(final ? { final_answer_display: final.text, final_answer_media: final.media } : {}) } };
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
return out;
|
|
952
|
+
});
|
|
953
|
+
}
|
|
954
|
+
/** TAL-456: a settled user or assistant body longer than this ships a collapsed excerpt for clients to render. */
|
|
955
|
+
export const BODY_EXCERPT_LIMIT = 3000;
|
|
956
|
+
const graphemes = new Intl.Segmenter(undefined, { granularity: 'grapheme' });
|
|
957
|
+
/** The first `BODY_EXCERPT_LIMIT` characters, never splitting a grapheme, cut back to a line break (else a space) in the second half. */
|
|
958
|
+
function bodyExcerpt(text) {
|
|
959
|
+
let end = 0;
|
|
960
|
+
for (const { segment } of graphemes.segment(text.slice(0, BODY_EXCERPT_LIMIT + 16))) {
|
|
961
|
+
if (end + segment.length > BODY_EXCERPT_LIMIT)
|
|
962
|
+
break;
|
|
963
|
+
end += segment.length;
|
|
964
|
+
}
|
|
965
|
+
const head = text.slice(0, end);
|
|
966
|
+
const floor = BODY_EXCERPT_LIMIT / 2;
|
|
967
|
+
const lineBreak = head.lastIndexOf('\n');
|
|
968
|
+
const space = head.lastIndexOf(' ');
|
|
969
|
+
const cut = lineBreak >= floor ? lineBreak : space >= floor ? space : end;
|
|
970
|
+
return head.slice(0, cut).trimEnd();
|
|
971
|
+
}
|
|
972
|
+
/**
|
|
973
|
+
* TAL-456: stamps `_display_excerpt` and `_display_truncated` on settled user and assistant rows whose display text is longer than
|
|
974
|
+
* `BODY_EXCERPT_LIMIT`, and `final_answer_excerpt` on a settled scene whose final answer is, so clients render a bounded
|
|
975
|
+
* excerpt instead of laying out the whole body. Full text stays for copy and edit; the running turn's rows are left alone.
|
|
976
|
+
* Runs after scene hydration. Returns copies; stored rows are untouched.
|
|
977
|
+
*/
|
|
978
|
+
export function withBodyExcerpts(messages, activeTurnId) {
|
|
979
|
+
return messages.map((m) => {
|
|
980
|
+
if (!isDict(m) || (m.role !== 'user' && m.role !== 'assistant'))
|
|
981
|
+
return m;
|
|
982
|
+
if (activeTurnId && m._turn_id === activeTurnId)
|
|
983
|
+
return m;
|
|
984
|
+
let out = m;
|
|
985
|
+
const text = typeof m._display_content === 'string' ? m._display_content : messageText(m.content);
|
|
986
|
+
if (text.length > BODY_EXCERPT_LIMIT)
|
|
987
|
+
out = { ...out, _display_excerpt: bodyExcerpt(text), _display_truncated: true };
|
|
988
|
+
const scene = m._anchor_activity_scene;
|
|
989
|
+
const finalAnswer = isDict(scene) ? (typeof scene.final_answer_display === 'string' ? scene.final_answer_display : scene.final_answer) : null;
|
|
990
|
+
if (isDict(scene) && typeof finalAnswer === 'string' && finalAnswer.length > BODY_EXCERPT_LIMIT) {
|
|
991
|
+
out = { ...out, _anchor_activity_scene: { ...scene, final_answer_excerpt: bodyExcerpt(finalAnswer) } };
|
|
992
|
+
}
|
|
993
|
+
return out;
|
|
994
|
+
});
|
|
995
|
+
}
|
|
631
996
|
/** The running turn's prompt as eager save checkpoints it (Python `_checkpoint_user_message_for_eager_session_save`). */
|
|
632
997
|
export function pendingUserRow(msg, attachments, startedAt, source, turnId) {
|
|
633
998
|
const user = { role: 'user', content: msg, _turn_id: turnId };
|