@maudecode/talaria-web 1.11.0 → 1.13.0
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/LICENSE +22 -0
- package/_release.json +4 -4
- package/dist/api/chat-router.d.ts +68 -4
- package/dist/api/chat-router.js +11 -8
- package/dist/api/chat-router.js.map +1 -1
- package/dist/api/router.d.ts +10 -0
- package/dist/api/router.js +2 -1
- package/dist/api/router.js.map +1 -1
- package/dist/api/sessions-router.d.ts +407 -51
- package/dist/api/sessions-router.js +2 -2
- package/dist/api/sessions-router.js.map +1 -1
- package/dist/api/sse-routes.js +52 -8
- package/dist/api/sse-routes.js.map +1 -1
- package/dist/api/tools-router.d.ts +443 -0
- package/dist/api/tools-router.js +99 -4
- package/dist/api/tools-router.js.map +1 -1
- package/dist/app.d.ts +926 -55
- package/dist/auth/oidc.js +2 -0
- package/dist/auth/oidc.js.map +1 -1
- package/dist/auth/passkeys.js +1 -1
- package/dist/auth/passkeys.js.map +1 -1
- package/dist/auth/store.d.ts +17 -0
- package/dist/auth/store.js +77 -19
- package/dist/auth/store.js.map +1 -1
- package/dist/cli/ctl.d.ts +6 -3
- package/dist/cli/ctl.js +25 -16
- package/dist/cli/ctl.js.map +1 -1
- package/dist/cli/launcher.js +2 -2
- package/dist/cli/launcher.js.map +1 -1
- package/dist/fs/atomic.d.ts +8 -1
- package/dist/fs/atomic.js +52 -3
- package/dist/fs/atomic.js.map +1 -1
- package/dist/http/context.d.ts +2 -0
- package/dist/http/context.js.map +1 -1
- package/dist/mcp/server.js +1 -1
- package/dist/mcp/server.js.map +1 -1
- package/dist/redact.d.ts +15 -0
- package/dist/redact.js +1393 -9
- package/dist/redact.js.map +1 -1
- package/dist/release.js +3 -1
- package/dist/release.js.map +1 -1
- package/dist/runtime.js +20 -9
- package/dist/runtime.js.map +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +12 -6
- package/dist/server.js.map +1 -1
- package/dist/sessions/anchor.d.ts +2 -0
- package/dist/sessions/anchor.js +22 -17
- package/dist/sessions/anchor.js.map +1 -1
- package/dist/sessions/export.js +1 -1
- package/dist/sessions/export.js.map +1 -1
- package/dist/sessions/file-changes.d.ts +15 -0
- package/dist/sessions/file-changes.js +58 -0
- package/dist/sessions/file-changes.js.map +1 -0
- package/dist/sessions/journal.d.ts +6 -1
- package/dist/sessions/journal.js +9 -15
- package/dist/sessions/journal.js.map +1 -1
- package/dist/sessions/list.d.ts +21 -1
- package/dist/sessions/list.js +81 -17
- package/dist/sessions/list.js.map +1 -1
- package/dist/sessions/merge.d.ts +66 -2
- package/dist/sessions/merge.js +291 -9
- package/dist/sessions/merge.js.map +1 -1
- package/dist/sessions/pending.d.ts +11 -2
- package/dist/sessions/pending.js +52 -3
- package/dist/sessions/pending.js.map +1 -1
- package/dist/sessions/relay.js +1 -1
- package/dist/sessions/relay.js.map +1 -1
- package/dist/sessions/service.d.ts +16 -3
- package/dist/sessions/service.js +92 -54
- package/dist/sessions/service.js.map +1 -1
- package/dist/sessions/state-db.d.ts +5 -0
- package/dist/sessions/state-db.js +34 -0
- package/dist/sessions/state-db.js.map +1 -1
- package/dist/sessions/streams.d.ts +4 -1
- package/dist/sessions/streams.js +3 -0
- package/dist/sessions/streams.js.map +1 -1
- package/dist/sessions/tool-display.d.ts +21 -0
- package/dist/sessions/tool-display.js +113 -0
- package/dist/sessions/tool-display.js.map +1 -0
- package/dist/sessions/turn.d.ts +25 -7
- package/dist/sessions/turn.js +153 -90
- package/dist/sessions/turn.js.map +1 -1
- package/dist/spa.d.ts +2 -0
- package/dist/spa.js +9 -0
- package/dist/spa.js.map +1 -1
- package/dist/test/harness.d.ts +2 -0
- package/dist/test/harness.js +1 -1
- package/dist/test/harness.js.map +1 -1
- package/dist/tools/terminal.d.ts +6 -0
- package/dist/tools/terminal.js +24 -3
- package/dist/tools/terminal.js.map +1 -1
- package/dist/tools/update-notifications.d.ts +133 -0
- package/dist/tools/update-notifications.js +407 -0
- package/dist/tools/update-notifications.js.map +1 -0
- package/dist/tools/updates.d.ts +53 -16
- package/dist/tools/updates.js +314 -351
- package/dist/tools/updates.js.map +1 -1
- package/package.json +3 -2
- package/sidecar/scripts/replay_sidecar.py +17 -0
- package/sidecar/talaria_sidecar/__init__.py +1 -1
- package/sidecar/talaria_sidecar/home.py +39 -16
- package/sidecar/talaria_sidecar/methods/chat.py +113 -4
- package/static/dist/FILES.txt +116 -116
- package/static/dist/THIRD_PARTY_LICENSES.md +5170 -0
- package/static/dist/assets/AppShell-irdqom6e.js +1 -0
- package/static/dist/assets/ChatPage-ldhqevjn.js +20 -0
- package/static/dist/assets/HubRoute-hq24vhj8.js +2 -0
- package/static/dist/assets/{Markdown-ftyfzds0.js → Markdown-bx4n7qs4.js} +7 -7
- package/static/dist/assets/{RightPanel-febk3dkd.js → RightPanel-ds4majj3.js} +1 -1
- package/static/dist/assets/Select-gpqmt6x1.js +1 -0
- package/static/dist/assets/SessionListPanel-hkvipik4.js +1 -0
- package/static/dist/assets/{SettingsLayout-pdpmhy1o.js → SettingsLayout-oigbg9rl.js} +1 -1
- package/static/dist/assets/States-fn4o2wdf.js +1 -0
- package/static/dist/assets/Toaster-cwnut53k.js +1 -0
- package/static/dist/assets/_app-h6ago6y6.js +1 -0
- package/static/dist/assets/_app.ext._extensionId-erqnfff5.js +1 -0
- package/static/dist/assets/_app.index-cq2fxmda.js +1 -0
- package/static/dist/assets/_app.insights-nzhld9gu.js +1 -0
- package/static/dist/assets/_app.kanban-m5uggety.js +1 -0
- package/static/dist/assets/_app.logs-d2kk9lza.js +1 -0
- package/static/dist/assets/_app.memory-gcmop1e7.js +1 -0
- package/static/dist/assets/_app.profiles-e9b2my7x.js +1 -0
- package/static/dist/assets/{_app.session._sessionId-n1ggcf5e.js → _app.session._sessionId-ciix6itb.js} +1 -1
- package/static/dist/assets/_app.settings-kcjum3c1.js +1 -0
- package/static/dist/assets/_app.settings._section-bi4jjex0.js +1 -0
- package/static/dist/assets/_app.skills-e4e61l23.js +1 -0
- package/static/dist/assets/_app.tasks-f1evdhbl.js +2 -0
- package/static/dist/assets/_app.todos-o7ijtk42.js +1 -0
- package/static/dist/assets/_app.workspaces-o18voh0w.js +1 -0
- package/static/dist/assets/{abnfDiagram-VCTEODGH-i4bgzu83.js → abnfDiagram-VCTEODGH-krt0yaru.js} +1 -1
- package/static/dist/assets/architecture-7GRP2DOG-notdhmpv.js +1 -0
- package/static/dist/assets/{architectureDiagram-5GKGNRK7-mx21lwqa.js → architectureDiagram-5GKGNRK7-i54t9ywl.js} +1 -1
- package/static/dist/assets/{blockDiagram-I7D4REHJ-o1hhchxv.js → blockDiagram-I7D4REHJ-fevbz4mz.js} +1 -1
- package/static/dist/assets/{c4Diagram-7LVT6UL2-jygqtvd8.js → c4Diagram-7LVT6UL2-np8eclmc.js} +1 -1
- package/static/dist/assets/channel-jpk1nas2.js +1 -0
- package/static/dist/assets/{chunk-4HAMMTFA-hjcpubgk.js → chunk-4HAMMTFA-owoi036m.js} +1 -1
- package/static/dist/assets/{chunk-75Z2AOVW-eibnex6m.js → chunk-75Z2AOVW-md44zf1n.js} +1 -1
- package/static/dist/assets/{chunk-DU6HZSFF-k1tp3qnp.js → chunk-DU6HZSFF-ka3rw8d6.js} +3 -3
- package/static/dist/assets/{chunk-F27PBJKO-lvcgn16f.js → chunk-F27PBJKO-iasnjsky.js} +1 -1
- package/static/dist/assets/{chunk-GMAD6QVW-ldlzruv1.js → chunk-GMAD6QVW-ex1up6tz.js} +1 -1
- package/static/dist/assets/{chunk-GVQU2GXP-hs1mva9d.js → chunk-GVQU2GXP-d4kmmg9p.js} +1 -1
- package/static/dist/assets/{chunk-IMKFNOWR-o7eqx3yb.js → chunk-IMKFNOWR-mwy42t85.js} +1 -1
- package/static/dist/assets/{chunk-L3NEJ4N5-bp1ofl70.js → chunk-L3NEJ4N5-fv7ry213.js} +1 -1
- package/static/dist/assets/{chunk-OSK3NFVY-o8m6mdz5.js → chunk-OSK3NFVY-jg9ir8ac.js} +1 -1
- package/static/dist/assets/{chunk-P2QGCYS3-kx83fti2.js → chunk-P2QGCYS3-pe9ms3ua.js} +1 -1
- package/static/dist/assets/{chunk-POPQ4Y6H-mwl99e9y.js → chunk-POPQ4Y6H-dimsjrn1.js} +1 -1
- package/static/dist/assets/{chunk-PWAF6VOD-oriuokxy.js → chunk-PWAF6VOD-m4hv98dy.js} +1 -1
- package/static/dist/assets/{chunk-SHT3W25Y-ab5cf00v.js → chunk-SHT3W25Y-gkjgl6qe.js} +1 -1
- package/static/dist/assets/{chunk-SVP7TREG-kqdrpr17.js → chunk-SVP7TREG-bc8qss5l.js} +1 -1
- package/static/dist/assets/{chunk-TICWLB2K-kfbnjabk.js → chunk-TICWLB2K-k9wzw38w.js} +1 -1
- package/static/dist/assets/classDiagram-ZZMXUADV-hld301gc.js +1 -0
- package/static/dist/assets/classDiagram-v2-VYDZK3BY-hld301gc.js +1 -0
- package/static/dist/assets/{copied-dp33szhq.js → copied-d5joolw7.js} +1 -1
- package/static/dist/assets/{cynefin-OW5HDTMX-mm5sj9s7.js → cynefin-OW5HDTMX-hueklikk.js} +1 -1
- package/static/dist/assets/{cynefinDiagram-5FMLGOSQ-nfon5q38.js → cynefinDiagram-5FMLGOSQ-e83o1wr1.js} +1 -1
- package/static/dist/assets/{dagre-GXQ25YYZ-dzdp9ypb.js → dagre-GXQ25YYZ-ir1tj2ar.js} +1 -1
- package/static/dist/assets/{diagram-S7CK7UJ4-ckxzqo01.js → diagram-S7CK7UJ4-o5218p2q.js} +1 -1
- package/static/dist/assets/{diagram-UQ7AKVKN-hw16h1um.js → diagram-UQ7AKVKN-ciad4o1i.js} +1 -1
- package/static/dist/assets/{diagram-VSXAHHWV-mu7wu2zg.js → diagram-VSXAHHWV-oharqjbt.js} +1 -1
- package/static/dist/assets/{diagram-VX7I27RA-k9uprwtj.js → diagram-VX7I27RA-wkwy62iv.js} +1 -1
- package/static/dist/assets/{diagram-Z3DM3KII-csdjzrg9.js → diagram-Z3DM3KII-bl252i7r.js} +1 -1
- package/static/dist/assets/{ebnfDiagram-PWID7BFC-n8mbw2jj.js → ebnfDiagram-PWID7BFC-nm0rcly7.js} +1 -1
- package/static/dist/assets/endpoints-d8n28yf3.js +64 -0
- package/static/dist/assets/{erDiagram-RLTQ6QDP-fsfe1uj0.js → erDiagram-RLTQ6QDP-m1w0vta2.js} +1 -1
- package/static/dist/assets/eventmodeling-NTZA5JFV-eaqs19mj.js +1 -0
- package/static/dist/assets/flowDiagram-HODETNUW-eli5764n.js +1 -0
- package/static/dist/assets/{ganttDiagram-EL5Y4UJY-gsba3iq9.js → ganttDiagram-EL5Y4UJY-czxo6iew.js} +1 -1
- package/static/dist/assets/{gitGraph-4MIJSDKK-na86q1pu.js → gitGraph-4MIJSDKK-ip9j1rph.js} +1 -1
- package/static/dist/assets/{gitGraphDiagram-WWUBYQGX-g72ew3xz.js → gitGraphDiagram-WWUBYQGX-kalxdole.js} +1 -1
- package/static/dist/assets/{highlighted-body-KPVGNVTW-okn18cp1.js → highlighted-body-KPVGNVTW-lgsj6fsk.js} +1 -1
- package/static/dist/assets/index-l08181vr.js +11 -0
- package/static/dist/assets/index-pdtcl20t.css +2 -0
- package/static/dist/assets/{info-A6RAGUB7-i01jeltk.js → info-A6RAGUB7-fv4fbc5m.js} +1 -1
- package/static/dist/assets/{infoDiagram-27XIBGKW-cayiv6fa.js → infoDiagram-27XIBGKW-kinx5jsl.js} +1 -1
- package/static/dist/assets/{ishikawaDiagram-5VMMS53U-g4rf14bv.js → ishikawaDiagram-5VMMS53U-kozvlqdv.js} +1 -1
- package/static/dist/assets/{journeyDiagram-3NMN7TZE-fusb2424.js → journeyDiagram-3NMN7TZE-lgpouxoe.js} +1 -1
- package/static/dist/assets/{kanban-definition-UXKFOSKX-g831pwlr.js → kanban-definition-UXKFOSKX-b320wo7b.js} +1 -1
- package/static/dist/assets/{lazyRouteComponent-ol965zwk.js → lazyRouteComponent-hy8doeye.js} +1 -1
- package/static/dist/assets/{line-md6em6gc.js → line-gxfwyhjq.js} +1 -1
- package/static/dist/assets/{login-kfclsqd2.js → login-llplsuey.js} +1 -1
- package/static/dist/assets/mermaid-HWGCJPDP-f3scrlds.js +1 -0
- package/static/dist/assets/{mermaid-parser.core-mq3uns9m.js → mermaid-parser.core-loxeqsu3.js} +3 -3
- package/static/dist/assets/{mindmap-definition-YA3MSWOX-oxafrned.js → mindmap-definition-YA3MSWOX-edi534gc.js} +1 -1
- package/static/dist/assets/{onboarding-fo6hnkyv.js → onboarding-n1xhlgym.js} +1 -1
- package/static/dist/assets/{packet-AYTQ26CC-ggxyvbym.js → packet-AYTQ26CC-gmb3yy71.js} +1 -1
- package/static/dist/assets/{pegDiagram-XKGWAZYB-nk7xcqgp.js → pegDiagram-XKGWAZYB-fxy5j8cx.js} +1 -1
- package/static/dist/assets/{pie-WAS4IAKB-ito2razh.js → pie-WAS4IAKB-do2pm4s6.js} +1 -1
- package/static/dist/assets/{pieDiagram-E7YTZNPT-g02xexar.js → pieDiagram-E7YTZNPT-mgjvb365.js} +1 -1
- package/static/dist/assets/{quadrantDiagram-AXDQQJYC-d4jn4xq5.js → quadrantDiagram-AXDQQJYC-dhok6m1j.js} +1 -1
- package/static/dist/assets/{radar-RG4KPBEZ-nebvfdzt.js → radar-RG4KPBEZ-n5giw3vb.js} +1 -1
- package/static/dist/assets/{railroad-74A4TZTK-ny3gebse.js → railroad-74A4TZTK-h6nfs9bj.js} +1 -1
- package/static/dist/assets/railroad-abnf-HS5TGJTU-d5gaaud9.js +1 -0
- package/static/dist/assets/railroad-ebnf-LZEXJU2U-ihudnbec.js +1 -0
- package/static/dist/assets/railroad-peg-WCYAUIDC-lgpvhel7.js +1 -0
- package/static/dist/assets/{railroadDiagram-O6MQD6OU-m09mmu67.js → railroadDiagram-O6MQD6OU-lfwg92r4.js} +1 -1
- package/static/dist/assets/{refresh-cw-eitd7yva.js → refresh-cw-bg6oc499.js} +1 -1
- package/static/dist/assets/{requirementDiagram-BXWQKSXE-evggpcbk.js → requirementDiagram-BXWQKSXE-c5k5pg07.js} +1 -1
- package/static/dist/assets/{sankeyDiagram-P5KCCOFB-bun89039.js → sankeyDiagram-P5KCCOFB-o9auio4y.js} +1 -1
- package/static/dist/assets/{saved-culx14ii.js → saved-j5wyhbik.js} +1 -1
- package/static/dist/assets/{search-nu6kzq55.js → search-ipa17zlr.js} +1 -1
- package/static/dist/assets/{sequenceDiagram-WJ2MYXX4-hhs9f09o.js → sequenceDiagram-WJ2MYXX4-pfgodnmk.js} +1 -1
- package/static/dist/assets/{settings_section_extensions_title-mj0gcozh.js → settings_section_extensions_title-fcfjf6l8.js} +1 -1
- package/static/dist/assets/share._token-i339gqj4.js +2 -0
- package/static/dist/assets/{sliders-horizontal-b9ljga1o.js → sliders-horizontal-bfrh4rch.js} +1 -1
- package/static/dist/assets/{stateDiagram-D77RDMKH-gi7t1tro.js → stateDiagram-D77RDMKH-m1y2cr3q.js} +1 -1
- package/static/dist/assets/stateDiagram-v2-MP3YSRHH-hehvfv55.js +1 -0
- package/static/dist/assets/{swimlanes-42K2YHIH-ea5urvph.js → swimlanes-42K2YHIH-hzai6fwo.js} +1 -1
- package/static/dist/assets/swimlanesDiagram-VR7AAH4N-nfk9mtst.js +8 -0
- package/static/dist/assets/{timeline-definition-24CTP7MA-mq64rm3b.js → timeline-definition-24CTP7MA-gwefy9gi.js} +1 -1
- package/static/dist/assets/todoStore-fhvdsen0.js +1 -0
- package/static/dist/assets/{treeView-Q6P3EWNA-cimbtxlz.js → treeView-Q6P3EWNA-7q91p0dn.js} +1 -1
- package/static/dist/assets/{treemap-WGGIJYW6-wig5gi1y.js → treemap-WGGIJYW6-occom39a.js} +1 -1
- package/static/dist/assets/{untitled-mbwemvxf.js → untitled-cgw2enra.js} +1 -1
- package/static/dist/assets/{useForm-li4bljlv.js → useForm-jwbfla68.js} +1 -1
- package/static/dist/assets/useLocale-gieo1fn7.js +1 -0
- package/static/dist/assets/{vennDiagram-4TSXK5OY-ez63kh7n.js → vennDiagram-4TSXK5OY-ew4bhldi.js} +1 -1
- package/static/dist/assets/{wardley-WFR3VGLG-r7rftz31.js → wardley-WFR3VGLG-njdacy0u.js} +1 -1
- package/static/dist/assets/{wardleyDiagram-VM6X3IG4-mvqg9eqc.js → wardleyDiagram-VM6X3IG4-mkvxx7u9.js} +1 -1
- package/static/dist/assets/{xychartDiagram-S5SC5T6Z-eqxdfc91.js → xychartDiagram-S5SC5T6Z-8uriotdw.js} +1 -1
- package/static/dist/index.html +1 -1
- package/static/dist/manifest.webmanifest +1 -1
- package/static/dist/sw.js +114 -152
- package/static/dist/assets/AppShell-hikzkcql.js +0 -1
- package/static/dist/assets/ChatPage-ofqn89h9.js +0 -21
- package/static/dist/assets/HubRoute-f2zrs9si.js +0 -2
- package/static/dist/assets/Select-lvx8gihl.js +0 -1
- package/static/dist/assets/SessionListPanel-o70ljmik.js +0 -1
- package/static/dist/assets/States-i46tz8an.js +0 -1
- package/static/dist/assets/Toaster-fklyeeyh.js +0 -1
- package/static/dist/assets/_app-j3rors25.js +0 -1
- package/static/dist/assets/_app.ext._extensionId-c0ey5ec9.js +0 -1
- package/static/dist/assets/_app.index-coy9jrto.js +0 -1
- package/static/dist/assets/_app.insights-ebd2k0i5.js +0 -1
- package/static/dist/assets/_app.kanban-e2p7ypi5.js +0 -1
- package/static/dist/assets/_app.logs-ml21mfyz.js +0 -1
- package/static/dist/assets/_app.memory-lhu5mm47.js +0 -1
- package/static/dist/assets/_app.profiles-egx0fgjo.js +0 -1
- package/static/dist/assets/_app.settings-d0vqtyid.js +0 -1
- package/static/dist/assets/_app.settings._section-cnzj6pli.js +0 -1
- package/static/dist/assets/_app.skills-kkug8obu.js +0 -1
- package/static/dist/assets/_app.tasks-nf285d2o.js +0 -2
- package/static/dist/assets/_app.todos-dxalqp1e.js +0 -1
- package/static/dist/assets/_app.workspaces-bqtduujs.js +0 -1
- package/static/dist/assets/architecture-7GRP2DOG-o8zqevhv.js +0 -1
- package/static/dist/assets/channel-mw8l793e.js +0 -1
- package/static/dist/assets/classDiagram-ZZMXUADV-egajr1wp.js +0 -1
- package/static/dist/assets/classDiagram-v2-VYDZK3BY-egajr1wp.js +0 -1
- package/static/dist/assets/endpoints-f6ngsyu5.js +0 -64
- package/static/dist/assets/eventmodeling-NTZA5JFV-k3zhqcyl.js +0 -1
- package/static/dist/assets/flowDiagram-HODETNUW-bdxes51f.js +0 -1
- package/static/dist/assets/index-ab0wj9ik.css +0 -2
- package/static/dist/assets/index-fd27xooo.js +0 -11
- package/static/dist/assets/mermaid-HWGCJPDP-ejk0d88t.js +0 -1
- package/static/dist/assets/railroad-abnf-HS5TGJTU-gtd38edw.js +0 -1
- package/static/dist/assets/railroad-ebnf-LZEXJU2U-o238oax2.js +0 -1
- package/static/dist/assets/railroad-peg-WCYAUIDC-c4acqp2j.js +0 -1
- package/static/dist/assets/share._token-k4pcnxqu.js +0 -2
- package/static/dist/assets/stateDiagram-v2-MP3YSRHH-jtadbol7.js +0 -1
- package/static/dist/assets/swimlanesDiagram-VR7AAH4N-ki7weepw.js +0 -8
- package/static/dist/assets/todoStore-azvfuqbv.js +0 -1
- package/static/dist/assets/trash-osyo895g.js +0 -1
- package/static/dist/assets/useLocale-kdew6auf.js +0 -1
package/dist/sessions/service.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { str } from '../util.js';
|
|
2
2
|
import { randomUUID } from 'node:crypto';
|
|
3
3
|
import { rmSync } from 'node:fs';
|
|
4
|
-
import { copyJson, redactSessionData, redactValue, stripPublicInternalFields } from '../redact.js';
|
|
4
|
+
import { buildActiveTurnToken, copyJson, redactSessionData, redactValue, stripPublicInternalFields, withSceneToolDisplay } from '../redact.js';
|
|
5
5
|
import { DraftVersionConflict, normalizeDraftVersion } from './drafts.js';
|
|
6
|
-
import { allSessions, buildSessionListPayload, isMessagingSessionRecord, lineageRootId, mergeCliSidebarMetadata, sessionListResponse, sessionSearchMessageText, sessionSearchPreview } from './list.js';
|
|
6
|
+
import { allSessions, buildSessionListPayload, isClaimableCliSource, isMessagingSessionRecord, withOwnerLocks, withSessionWireFlags, lineageRootId, mergeCliSidebarMetadata, sessionListResponse, sessionSearchMessageText, sessionSearchPreview } from './list.js';
|
|
7
7
|
import { anchorSceneIntOrNull, hydrateAnchorActivityScenes, normalizeAnchorSceneMessageRef, readAnchorSceneRows, storeAnchorScene, withTurnIds } from './anchor.js';
|
|
8
8
|
import { isSafeSessionId, lastMessageTimestamp, Session, titleFrom } from './session.js';
|
|
9
9
|
import { SessionBusy, SessionNotFound, statSignature } from './store.js';
|
|
10
10
|
import { attachTodoState } from './todo.js';
|
|
11
|
-
import { stateDbSessionMessages, stateDbSessionRow } from './state-db.js';
|
|
12
|
-
import { mergeSessionMessagesAppendOnly } from './merge.js';
|
|
11
|
+
import { stateDbSessionMessages, stateDbSessionRow, stateDbSessionSources } from './state-db.js';
|
|
12
|
+
import { mergeSessionMessagesAppendOnly, pendingUserRow, withPendingUserTurn, withToolCallOutcomes, withoutRunningTurnOutput } from './merge.js';
|
|
13
13
|
import { messagesForLimitedPayload, messageWindowForDisplay, MAX_MSG_LIMIT, parseMsgLimit, toolCallsForMessageWindow } from './window.js';
|
|
14
14
|
import { redactText } from '../redact.js';
|
|
15
15
|
import { buildShareSnapshot } from './shares.js';
|
|
@@ -62,7 +62,7 @@ export class SessionService {
|
|
|
62
62
|
isReadOnlyImport(sid) {
|
|
63
63
|
try {
|
|
64
64
|
const s = this.store.get(sid, { metadataOnly: true });
|
|
65
|
-
if (s
|
|
65
|
+
if (this.isReadOnly(s))
|
|
66
66
|
return true;
|
|
67
67
|
}
|
|
68
68
|
catch {
|
|
@@ -85,11 +85,20 @@ export class SessionService {
|
|
|
85
85
|
const meta = this.lookupCliMeta(sid);
|
|
86
86
|
return meta !== null && str(meta.source_tag || meta.raw_source || meta.source).trim().toLowerCase() === 'subagent';
|
|
87
87
|
}
|
|
88
|
+
/** TAL-358: batched `sessions.source` owners from the active profile's state.db. */
|
|
89
|
+
stateDbSources = (ids) => stateDbSessionSources(join(this.deps.profileHome(this.deps.activeProfile()), 'state.db'), ids);
|
|
90
|
+
/** The persisted flag folded with the state.db owner lock (TAL-358): the one read-only rule for mutation gates and the wire. */
|
|
91
|
+
isReadOnly(s) {
|
|
92
|
+
if (s.read_only)
|
|
93
|
+
return true;
|
|
94
|
+
const [row] = withOwnerLocks([{ session_id: s.session_id, source_tag: s.source_tag, raw_source: s.raw_source, session_source: s.session_source }], this.stateDbSources);
|
|
95
|
+
return Boolean(row?.read_only);
|
|
96
|
+
}
|
|
88
97
|
/** Full session for mutation, refusing read-only imports (Python `_get_or_materialize_session`). */
|
|
89
98
|
getForMutation(sid) {
|
|
90
99
|
let s = this.get404(sid);
|
|
91
100
|
s = this.store.ensureFull(sid, s);
|
|
92
|
-
if (s
|
|
101
|
+
if (this.isReadOnly(s))
|
|
93
102
|
throw new HttpFailure(403, 'Read-only imported sessions cannot be modified from WebUI');
|
|
94
103
|
if (str(s.source_tag || s.raw_source).trim().toLowerCase() === 'subagent')
|
|
95
104
|
throw new HttpFailure(403, 'Read-only subagent child session');
|
|
@@ -141,23 +150,6 @@ export class SessionService {
|
|
|
141
150
|
return null;
|
|
142
151
|
}
|
|
143
152
|
}
|
|
144
|
-
/** Python `_is_claimable_cli_source`: a denylist of foreign families that own their sessions. */
|
|
145
|
-
claimableCliSource(meta, stateDbSource) {
|
|
146
|
-
if (meta.read_only)
|
|
147
|
-
return false;
|
|
148
|
-
const sessionSource = str(meta.session_source).trim().toLowerCase();
|
|
149
|
-
if (['messaging', 'external_agent'].includes(sessionSource))
|
|
150
|
-
return false;
|
|
151
|
-
const tag = str(meta.source_tag || meta.raw_source).trim().toLowerCase();
|
|
152
|
-
const refused = new Set(['claude_code', 'cron', 'external_agent', 'gateway', 'messaging', 'subagent', 'unknown']);
|
|
153
|
-
if (tag && refused.has(tag))
|
|
154
|
-
return false;
|
|
155
|
-
if (isMessagingSessionRecord(meta))
|
|
156
|
-
return false;
|
|
157
|
-
if (!tag && stateDbSource && refused.has(stateDbSource.trim().toLowerCase()))
|
|
158
|
-
return false;
|
|
159
|
-
return true;
|
|
160
|
-
}
|
|
161
153
|
/** Python `_session_index_marks_was_webui`: an index row that once owned a WebUI sidecar (self-heal 404). */
|
|
162
154
|
indexMarksWasWebui(sid) {
|
|
163
155
|
let entries;
|
|
@@ -214,7 +206,7 @@ export class SessionService {
|
|
|
214
206
|
if (!meta.updated_at && (row.ended_at || row.started_at))
|
|
215
207
|
meta.updated_at = row.ended_at || row.started_at;
|
|
216
208
|
}
|
|
217
|
-
const claimable =
|
|
209
|
+
const claimable = isClaimableCliSource(meta, stateDbSource);
|
|
218
210
|
const workspace = str(meta.workspace || meta.cwd).trim() || this.deps.workspaces.lastWorkspace(profile);
|
|
219
211
|
const defaults = this.store.deps.defaults(profile);
|
|
220
212
|
const session = new Session({
|
|
@@ -243,12 +235,16 @@ export class SessionService {
|
|
|
243
235
|
}
|
|
244
236
|
/** `compact()` plus messages, redacted for the wire (Python `_public_session_projection`). */
|
|
245
237
|
publicSession(s, withMessages = true) {
|
|
246
|
-
const payload =
|
|
238
|
+
const payload = this.wireRow(s);
|
|
247
239
|
// Mutation replies replace a client's transcript, so they carry the same server-built scenes as the detail.
|
|
248
240
|
if (withMessages)
|
|
249
|
-
payload.messages = hydrateAnchorActivityScenes(withTurnIds(s.messages), s.anchor_activity_scenes, { activeTurnId: s.active_stream_id });
|
|
241
|
+
payload.messages = hydrateAnchorActivityScenes(withToolCallOutcomes(withTurnIds(s.messages), s.tool_calls, s.active_stream_id), s.anchor_activity_scenes, { activeTurnId: s.active_stream_id });
|
|
250
242
|
return redactSessionData(payload, this.deps.redactEnabled());
|
|
251
243
|
}
|
|
244
|
+
/** `compact()` with the wire streaming/read-only flags (TAL-312), for replies that return the session row. */
|
|
245
|
+
wireRow(s) {
|
|
246
|
+
return withSessionWireFlags({ ...s.compact(), read_only: this.isReadOnly(s) }, this.deps.runtime.activeStreamIds);
|
|
247
|
+
}
|
|
252
248
|
/** Python `public_session_projection(s.__dict__)`: every persisted field, redacted (session export). */
|
|
253
249
|
publicSessionDocument(s) {
|
|
254
250
|
return redactSessionData(s.toDocument(), this.deps.redactEnabled());
|
|
@@ -279,8 +275,15 @@ export class SessionService {
|
|
|
279
275
|
throw new HttpFailure(404, 'Session not found');
|
|
280
276
|
}
|
|
281
277
|
this.clearStaleStreamState(s);
|
|
282
|
-
|
|
283
|
-
|
|
278
|
+
const journaled = loadMessages ? this.journaledActiveTurn(s) : null;
|
|
279
|
+
let transcript = loadMessages ? this.mergedTranscript(s) : [];
|
|
280
|
+
const pending = loadMessages ? this.pendingTurn(s) : null;
|
|
281
|
+
if (pending)
|
|
282
|
+
transcript = withPendingUserTurn(transcript, pending);
|
|
283
|
+
if (journaled)
|
|
284
|
+
transcript = withoutRunningTurnOutput(transcript, { ...journaled, localCount: s.messages.length });
|
|
285
|
+
// Turn ids, tool outcomes and scenes are computed over the full transcript, so every window reports the same values.
|
|
286
|
+
const all = loadMessages ? hydrateAnchorActivityScenes(withToolCallOutcomes(withTurnIds(transcript), s.tool_calls, s.active_stream_id), s.anchor_activity_scenes, { activeTurnId: s.active_stream_id, clipToolResults: msgLimit !== null }) : [];
|
|
284
287
|
let truncated = [];
|
|
285
288
|
let offset = 0;
|
|
286
289
|
let summaryCount = null;
|
|
@@ -288,6 +291,14 @@ export class SessionService {
|
|
|
288
291
|
if (loadMessages) {
|
|
289
292
|
;
|
|
290
293
|
[truncated, offset] = messageWindowForDisplay(all, msgLimit, msgBefore);
|
|
294
|
+
// TAL-368: a tail window starts no later than the running turn's prompt, so a turn whose output stays in the
|
|
295
|
+
// transcript (no journal to replay it) keeps its prompt; older pages end before it, so it is never sent twice.
|
|
296
|
+
// ponytail: the window grows with that turn's persisted rows; clip the turn instead if degraded runs get long.
|
|
297
|
+
const prompt = pending && msgBefore === null ? all.findIndex((m) => isDict(m) && m.role === 'user' && m._active_turn_token === pending.activeTurnToken) : -1;
|
|
298
|
+
if (prompt >= 0 && prompt < offset) {
|
|
299
|
+
truncated = all.slice(prompt, offset + truncated.length);
|
|
300
|
+
offset = prompt;
|
|
301
|
+
}
|
|
291
302
|
if (msgLimit !== null)
|
|
292
303
|
truncated = messagesForLimitedPayload(truncated);
|
|
293
304
|
}
|
|
@@ -310,7 +321,6 @@ export class SessionService {
|
|
|
310
321
|
messages: truncated,
|
|
311
322
|
message_count: mergedCount,
|
|
312
323
|
tool_calls: toolCalls,
|
|
313
|
-
active_stream_id: s.active_stream_id,
|
|
314
324
|
pending_user_message: s.pending_user_message,
|
|
315
325
|
pending_attachments: loadMessages ? s.pending_attachments : [],
|
|
316
326
|
pending_started_at: s.pending_started_at,
|
|
@@ -319,6 +329,8 @@ export class SessionService {
|
|
|
319
329
|
threshold_tokens: Number(s.threshold_tokens ?? 0) || 0,
|
|
320
330
|
last_prompt_tokens: Number(s.last_prompt_tokens ?? 0) || 0,
|
|
321
331
|
};
|
|
332
|
+
if (loadMessages)
|
|
333
|
+
raw.transcript_seq = journaled ? { stream_id: journaled.turnId, seq: 0 } : null;
|
|
322
334
|
if (loadMessages && all.length)
|
|
323
335
|
attachTodoState(raw, all);
|
|
324
336
|
if (mergedLast) {
|
|
@@ -331,12 +343,34 @@ export class SessionService {
|
|
|
331
343
|
raw._msg_limit_max = MAX_MSG_LIMIT;
|
|
332
344
|
const revisionAfter = this.loadRevision(s);
|
|
333
345
|
raw._load_revision = revisionBefore !== null && revisionBefore === revisionAfter ? hashRevision(revisionBefore) : `unstable-${randomUUID().replace(/-/g, '')}`;
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
raw.read_only = true;
|
|
337
|
-
}
|
|
346
|
+
raw.read_only = this.isReadOnly(s);
|
|
347
|
+
withSessionWireFlags(raw, activeStreamIds);
|
|
338
348
|
return redactSessionData(raw, this.deps.redactEnabled());
|
|
339
349
|
}
|
|
350
|
+
/**
|
|
351
|
+
* TAL-316: the active run whose journal can replay its output from the start. The detail then leaves that output to the
|
|
352
|
+
* replay; with no active run, no identifiable prompt, or no complete journal, it returns the persisted transcript unchanged.
|
|
353
|
+
*/
|
|
354
|
+
journaledActiveTurn(s) {
|
|
355
|
+
const turnId = str(s.active_stream_id).trim();
|
|
356
|
+
const activeTurnToken = buildActiveTurnToken(turnId, s.pending_started_at);
|
|
357
|
+
if (!turnId || !activeTurnToken || this.deps.runtime.journalDegraded(turnId))
|
|
358
|
+
return null;
|
|
359
|
+
const summary = this.deps.journal?.findRunSummary(turnId);
|
|
360
|
+
if (summary?.session_id !== s.session_id || summary.journal_pruned)
|
|
361
|
+
return null;
|
|
362
|
+
return { turnId, startedAt: Number(s.pending_started_at), activeTurnToken };
|
|
363
|
+
}
|
|
364
|
+
/** TAL-368: the active run's prompt, which the detail shows until settlement persists it; null when idle or promptless. */
|
|
365
|
+
pendingTurn(s) {
|
|
366
|
+
const turnId = str(s.active_stream_id).trim();
|
|
367
|
+
const activeTurnToken = buildActiveTurnToken(turnId, s.pending_started_at);
|
|
368
|
+
const text = str(s.pending_user_message);
|
|
369
|
+
if (!turnId || !activeTurnToken || (!text && !s.pending_attachments.length))
|
|
370
|
+
return null;
|
|
371
|
+
const startedAt = Number(s.pending_started_at);
|
|
372
|
+
return { turnId, startedAt, activeTurnToken, localCount: s.messages.length, prompt: pendingUserRow(text, s.pending_attachments, startedAt, s.pending_user_source || 'webui', turnId) };
|
|
373
|
+
}
|
|
340
374
|
/** A session without a sidecar, synthesized from state.db for this profile; 404/409 like the detail. */
|
|
341
375
|
foreignSession(sid) {
|
|
342
376
|
const meta = this.lookupCliMeta(sid);
|
|
@@ -355,18 +389,18 @@ export class SessionService {
|
|
|
355
389
|
/** Python `_handle_session_get` without a sidecar: the state.db transcript as a (read-only or claimable) foreign stub. */
|
|
356
390
|
foreignSessionDetail(sid) {
|
|
357
391
|
const { synth, meta } = this.foreignSession(sid);
|
|
358
|
-
// The same turn projection as a WebUI session: turn ids, then each completed turn's scene.
|
|
359
|
-
const msgs = hydrateAnchorActivityScenes(withTurnIds(synth.messages), {});
|
|
392
|
+
// The same turn projection as a WebUI session: turn ids, tool outcomes, then each completed turn's scene.
|
|
393
|
+
const msgs = hydrateAnchorActivityScenes(withToolCallOutcomes(withTurnIds(synth.messages), [], null), {});
|
|
360
394
|
const lastTs = Number(msgs[msgs.length - 1]?.timestamp ?? 0) || 0;
|
|
361
395
|
const sess = {
|
|
362
396
|
session_id: synth.session_id, title: synth.title, workspace: synth.workspace, model: synth.model, message_count: msgs.length,
|
|
363
397
|
created_at: synth.created_at, updated_at: synth.updated_at, last_message_at: meta?.last_message_at || meta?.updated_at || lastTs,
|
|
364
398
|
pinned: synth.pinned, archived: synth.archived, project_id: synth.project_id ?? null, profile: synth.profile,
|
|
365
399
|
is_cli_session: synth.is_cli_session, source_tag: synth.source_tag, raw_source: synth.raw_source, session_source: synth.session_source,
|
|
366
|
-
source_label: synth.source_label, read_only: synth.read_only, messages: msgs, tool_calls: [],
|
|
400
|
+
source_label: synth.source_label, read_only: synth.read_only, can_duplicate: false, messages: msgs, tool_calls: [], transcript_seq: null,
|
|
367
401
|
};
|
|
368
402
|
attachTodoState(sess, msgs);
|
|
369
|
-
const merged = meta ? mergeCliSidebarMetadata(sess, meta) : sess;
|
|
403
|
+
const merged = withSessionWireFlags(meta ? mergeCliSidebarMetadata(sess, meta) : sess, this.deps.runtime.activeStreamIds);
|
|
370
404
|
return redactSessionData(merged, this.deps.redactEnabled());
|
|
371
405
|
}
|
|
372
406
|
/** Clear persisted streaming flags when no live stream backs them (Python `_clear_stale_stream_state`, no journal recovery). */
|
|
@@ -434,7 +468,7 @@ export class SessionService {
|
|
|
434
468
|
// Python reads every profile's state.db under all_profiles; this port projects the active profile only.
|
|
435
469
|
const cliRows = wantState ? this.deps.cliSessions(activeProfile, { sourceFilter: params.sourceFilter ?? null }) : undefined;
|
|
436
470
|
const gatewayIdentity = loadGatewaySessionIdentityMap(join(this.deps.profileHome(activeProfile), 'sessions', 'sessions.json'));
|
|
437
|
-
const payload = buildSessionListPayload(this.store, { ...params, ...(cliRows ? { cliRows } : {}), gatewayIdentity, activeProfile, isolatedProfileMode: this.deps.isolatedProfileMode(), profilesMatch: this.deps.profilesMatch });
|
|
471
|
+
const payload = buildSessionListPayload(this.store, { ...params, ...(cliRows ? { cliRows } : {}), gatewayIdentity, stateDbSources: this.stateDbSources, activeProfile, isolatedProfileMode: this.deps.isolatedProfileMode(), profilesMatch: this.deps.profilesMatch });
|
|
438
472
|
return sessionListResponse(payload, this.deps.runtime, this.deps.redactEnabled(), this.deps.now());
|
|
439
473
|
}
|
|
440
474
|
search(q, opts) {
|
|
@@ -442,8 +476,10 @@ export class SessionService {
|
|
|
442
476
|
let sessions = allSessions(this.store);
|
|
443
477
|
if (!opts.allProfiles)
|
|
444
478
|
sessions = sessions.filter((r) => this.deps.profilesMatch(str(r.profile) || null, activeProfile));
|
|
479
|
+
sessions = withOwnerLocks(sessions, this.stateDbSources);
|
|
445
480
|
const redact = this.deps.redactEnabled();
|
|
446
481
|
const redactRow = (item) => {
|
|
482
|
+
withSessionWireFlags(item, this.deps.runtime.activeStreamIds);
|
|
447
483
|
if (typeof item.title === 'string')
|
|
448
484
|
item.title = redactText(item.title, redact);
|
|
449
485
|
for (const f of ['display_title', '_state_db_title', 'parent_title'])
|
|
@@ -499,10 +535,10 @@ export class SessionService {
|
|
|
499
535
|
catch {
|
|
500
536
|
hermesHome = '';
|
|
501
537
|
}
|
|
502
|
-
const
|
|
538
|
+
const { is_streaming: streaming, active_stream_id: live, read_only: readOnly } = this.wireRow(full);
|
|
503
539
|
return {
|
|
504
540
|
session_id: full.session_id, title: full.title, model: full.model, profile, hermes_home: hermesHome, workspace: full.workspace, personality: full.personality,
|
|
505
|
-
message_count: full.messages.length, created_at: full.created_at, updated_at: full.updated_at, agent_running:
|
|
541
|
+
message_count: full.messages.length, created_at: full.created_at, updated_at: full.updated_at, agent_running: streaming, is_streaming: streaming, active_stream_id: live, read_only: readOnly,
|
|
506
542
|
input_tokens: inp, output_tokens: out, total_tokens: inp + out, estimated_cost: full.estimated_cost,
|
|
507
543
|
};
|
|
508
544
|
}
|
|
@@ -574,7 +610,7 @@ export class SessionService {
|
|
|
574
610
|
catch {
|
|
575
611
|
throw new HttpFailure(404, 'Session not found');
|
|
576
612
|
}
|
|
577
|
-
if (current
|
|
613
|
+
if (this.isReadOnly(current))
|
|
578
614
|
throw new HttpFailure(403, `Session ${sid} is read-only`);
|
|
579
615
|
await this.store.withLock(sid, () => {
|
|
580
616
|
current.title = title;
|
|
@@ -593,7 +629,7 @@ export class SessionService {
|
|
|
593
629
|
});
|
|
594
630
|
await this.deps.syncTitle(s);
|
|
595
631
|
this.publish('session_rename', s.profile, s.session_id);
|
|
596
|
-
return { session:
|
|
632
|
+
return { session: this.wireRow(s) };
|
|
597
633
|
}
|
|
598
634
|
// The pin quota is counted across sessions, so the count-and-save transaction runs on one process-wide chain;
|
|
599
635
|
// per-session locks alone would let two pins of different sessions both see the last free slot.
|
|
@@ -623,7 +659,7 @@ export class SessionService {
|
|
|
623
659
|
this.store.save(s);
|
|
624
660
|
});
|
|
625
661
|
this.publish('session_pin', s.profile, s.session_id);
|
|
626
|
-
return { ok: true, session:
|
|
662
|
+
return { ok: true, session: this.wireRow(s) };
|
|
627
663
|
}
|
|
628
664
|
async archive(sid, archived) {
|
|
629
665
|
this.rejectSubagent(sid, 'archived');
|
|
@@ -636,7 +672,7 @@ export class SessionService {
|
|
|
636
672
|
this.store.save(s, { touchUpdatedAt: false });
|
|
637
673
|
});
|
|
638
674
|
this.publish('session_archive', s.profile, s.session_id);
|
|
639
|
-
return { ok: true, session:
|
|
675
|
+
return { ok: true, session: this.wireRow(s), ...worktreeRetainedPayload(s) };
|
|
640
676
|
}
|
|
641
677
|
async move(sid, targetProjectId) {
|
|
642
678
|
const s = this.mutationTarget(sid, 'moved');
|
|
@@ -658,7 +694,7 @@ export class SessionService {
|
|
|
658
694
|
throw error;
|
|
659
695
|
}
|
|
660
696
|
this.publish('session_move', s.profile, s.session_id);
|
|
661
|
-
return { ok: true, session:
|
|
697
|
+
return { ok: true, session: this.wireRow(s) };
|
|
662
698
|
}
|
|
663
699
|
async update(sid, body) {
|
|
664
700
|
const s = this.mutationTarget(sid, 'updated');
|
|
@@ -696,7 +732,7 @@ export class SessionService {
|
|
|
696
732
|
async setToolsets(sid, toolsets) {
|
|
697
733
|
this.rejectSubagent(sid, 'modified');
|
|
698
734
|
const cleaned = this.validateToolsetsShape(toolsets);
|
|
699
|
-
const s = this.
|
|
735
|
+
const s = this.mutationTarget(sid, 'modified');
|
|
700
736
|
await this.store.withLock(sid, () => {
|
|
701
737
|
s.enabled_toolsets = cleaned;
|
|
702
738
|
this.store.save(s);
|
|
@@ -718,7 +754,7 @@ export class SessionService {
|
|
|
718
754
|
this.rejectSubagent(sid, 'modified');
|
|
719
755
|
if (keepRaw === null || keepRaw === undefined)
|
|
720
756
|
throw new HttpFailure(400, 'Missing required field(s): keep_count');
|
|
721
|
-
const s = this.
|
|
757
|
+
const s = this.mutationTarget(sid, 'modified');
|
|
722
758
|
// Python `int(body["keep_count"])`: a float truncates, a non-integer string is rejected.
|
|
723
759
|
let keep;
|
|
724
760
|
if (typeof keepRaw === 'number')
|
|
@@ -740,7 +776,7 @@ export class SessionService {
|
|
|
740
776
|
}
|
|
741
777
|
async clear(sid) {
|
|
742
778
|
this.rejectSubagent(sid, 'modified');
|
|
743
|
-
const s = this.
|
|
779
|
+
const s = this.mutationTarget(sid, 'modified');
|
|
744
780
|
await this.store.withLock(sid, () => {
|
|
745
781
|
const hadMessages = s.messages.length > 0;
|
|
746
782
|
truncateSessionAtKeep(s, 0);
|
|
@@ -775,12 +811,12 @@ export class SessionService {
|
|
|
775
811
|
}
|
|
776
812
|
});
|
|
777
813
|
this.deps.runtime.evictAgent(sid);
|
|
778
|
-
return { ok: true, session:
|
|
814
|
+
return { ok: true, session: this.wireRow(s) };
|
|
779
815
|
}
|
|
780
816
|
async retry(sid) {
|
|
781
817
|
this.rejectSubagent(sid, 'modified');
|
|
782
818
|
return this.store.withLock(sid, () => {
|
|
783
|
-
const s = this.
|
|
819
|
+
const s = this.mutationTarget(sid, 'modified');
|
|
784
820
|
const history = s.messages;
|
|
785
821
|
const lastUser = findLastUserIndex(history);
|
|
786
822
|
if (lastUser === null)
|
|
@@ -795,7 +831,7 @@ export class SessionService {
|
|
|
795
831
|
async undo(sid) {
|
|
796
832
|
this.rejectSubagent(sid, 'modified');
|
|
797
833
|
return this.store.withLock(sid, () => {
|
|
798
|
-
const s = this.
|
|
834
|
+
const s = this.mutationTarget(sid, 'modified');
|
|
799
835
|
const history = s.messages;
|
|
800
836
|
const lastUser = findLastUserIndex(history);
|
|
801
837
|
if (lastUser === null)
|
|
@@ -833,7 +869,7 @@ export class SessionService {
|
|
|
833
869
|
if (this.isSubagentViewOnly(sid))
|
|
834
870
|
throw new HttpFailure(400, 'Subagent sessions are view-only and cannot be branched from WebUI');
|
|
835
871
|
const source = this.get404(sid);
|
|
836
|
-
if (source
|
|
872
|
+
if (this.isReadOnly(source)) {
|
|
837
873
|
if (str(source.source_tag || source.raw_source).trim().toLowerCase() !== 'cron')
|
|
838
874
|
throw new HttpFailure(403, 'Read-only sessions cannot be branched from WebUI');
|
|
839
875
|
source.branchSourceReadonly = true;
|
|
@@ -1189,11 +1225,13 @@ export class SessionService {
|
|
|
1189
1225
|
session = this.foreignSession(sid).synth;
|
|
1190
1226
|
transcript = session.messages;
|
|
1191
1227
|
}
|
|
1192
|
-
const result = readAnchorSceneRows(session, { messageRef, messageIndex, before: anchorSceneIntOrNull(query.before), limit: anchorSceneIntOrNull(query.limit) }, withTurnIds(transcript));
|
|
1228
|
+
const result = readAnchorSceneRows(session, { messageRef, messageIndex, before: anchorSceneIntOrNull(query.before), limit: anchorSceneIntOrNull(query.limit) }, withToolCallOutcomes(withTurnIds(transcript), session.tool_calls, session.active_stream_id));
|
|
1193
1229
|
if (!result)
|
|
1194
1230
|
throw new HttpFailure(404, 'Anchor activity scene not found');
|
|
1195
1231
|
// Paged rows come from the raw transcript, so they take the same credential redaction as the detail's preview.
|
|
1196
|
-
|
|
1232
|
+
const enabled = this.deps.redactEnabled();
|
|
1233
|
+
const redacted = redactValue(result, enabled);
|
|
1234
|
+
return { ...redacted, rows: withSceneToolDisplay(result.rows, redacted.rows, enabled) };
|
|
1197
1235
|
}
|
|
1198
1236
|
// ── shares ───────────────────────────────────────────────────────────────
|
|
1199
1237
|
createShare(sid) {
|