@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
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const ALL = ['web', 'ios'];
|
|
2
|
+
const client = (name, description, extra = {}) => ({ name, description, aliases: [], handler: 'client', clients: ALL, ...extra });
|
|
3
|
+
const webOnly = (unsupported_message) => ({ clients: ['web'], unsupported_message });
|
|
4
|
+
/** Commands a client handles itself, in display order. Every entry outside a client's `clients` carries `unsupported_message`. */
|
|
5
|
+
export const CLIENT_COMMANDS = [
|
|
6
|
+
client('help', 'Show available commands'),
|
|
7
|
+
client('new', 'Start a new conversation'),
|
|
8
|
+
client('clear', 'Clear this conversation'),
|
|
9
|
+
client('stop', 'Stop the running response'),
|
|
10
|
+
client('interrupt', 'Interrupt and send', { args_hint: '<message>' }),
|
|
11
|
+
client('queue', 'Queue a follow-up', { args_hint: '<message>' }),
|
|
12
|
+
client('steer', 'Steer the running response', { args_hint: '<message>' }),
|
|
13
|
+
client('model', 'Switch the conversation model', { args_hint: '<id>' }),
|
|
14
|
+
client('workspace', 'Switch workspace', { args_hint: '<path>' }),
|
|
15
|
+
client('terminal', 'Toggle the workspace terminal', webOnly('Terminal is not available in the mobile app.')),
|
|
16
|
+
client('title', 'Rename this conversation', { args_hint: '<text>' }),
|
|
17
|
+
client('retry', 'Retry the last turn'),
|
|
18
|
+
client('undo', 'Undo the last turn'),
|
|
19
|
+
client('compress', 'Compress the context', { aliases: ['compact'] }),
|
|
20
|
+
client('usage', 'Show token usage', webOnly('Token usage is not available in the mobile app.')),
|
|
21
|
+
client('theme', 'Switch theme', { args_hint: '<light|dark|system>', ...webOnly('Theme switching is not available from mobile slash commands.') }),
|
|
22
|
+
client('yolo', 'Toggle YOLO mode (skip approvals)', webOnly('YOLO mode is not available in the mobile app.')),
|
|
23
|
+
client('branch', 'Branch the conversation', { aliases: ['fork'] }),
|
|
24
|
+
client('voice', 'Toggle voice mode', webOnly('Voice commands are not available in the mobile app.')),
|
|
25
|
+
client('reasoning', 'Set reasoning effort', { args_hint: '<level>' }),
|
|
26
|
+
client('personality', 'Set the personality', { args_hint: '<name>' }),
|
|
27
|
+
client('goal', 'Set or show the goal', { args_hint: '<text>' }),
|
|
28
|
+
client('status', 'Show session status'),
|
|
29
|
+
client('btw', 'Side question without affecting the run', { args_hint: '<question>' }),
|
|
30
|
+
client('background', 'Run in the background', { args_hint: '<message>', aliases: ['bg'] }),
|
|
31
|
+
client('skills', 'List skills'),
|
|
32
|
+
client('use', 'Use a skill', { args_hint: '<skill>', ...webOnly('Use `/skills [query]` to search skills.') }),
|
|
33
|
+
];
|
|
34
|
+
/**
|
|
35
|
+
* The client table followed by the Agent registry. An Agent command whose name is already a client name or alias is
|
|
36
|
+
* dropped, and client-claimed aliases are removed from the rest, so every typed name resolves to one entry.
|
|
37
|
+
* Gateway-only commands never reach a client; CLI-only ones stay listed for no client.
|
|
38
|
+
*/
|
|
39
|
+
export function commandCatalog(agent) {
|
|
40
|
+
const claimed = new Set(CLIENT_COMMANDS.flatMap((c) => [c.name, ...c.aliases]));
|
|
41
|
+
const rows = agent.flatMap((c) => {
|
|
42
|
+
if (c.gateway_only || claimed.has(c.name))
|
|
43
|
+
return [];
|
|
44
|
+
claimed.add(c.name);
|
|
45
|
+
const aliases = c.aliases.filter((a) => !claimed.has(a));
|
|
46
|
+
for (const a of aliases)
|
|
47
|
+
claimed.add(a);
|
|
48
|
+
return [{ ...c, aliases, handler: 'agent', clients: c.cli_only ? [] : ALL, ...(c.cli_only ? { unsupported_message: `/${c.name} runs only in the Hermes CLI.` } : {}) }];
|
|
49
|
+
});
|
|
50
|
+
return [...CLIENT_COMMANDS, ...rows];
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/tools/commands.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/crons.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import type { CronRecentCompletion, CronContextSources } from '@maudecode/talaria-web-contracts';
|
|
2
2
|
import type { SidecarLike } from '../sidecar/client.js';
|
|
3
|
-
import type
|
|
3
|
+
import { type Dict } from '../config/agent-config.js';
|
|
4
4
|
export interface CronDeps {
|
|
5
5
|
sidecar: () => SidecarLike | null;
|
|
6
6
|
profileHome: (name: string) => string;
|
|
@@ -13,14 +13,26 @@ export interface CronDeps {
|
|
|
13
13
|
log: (line: string) => void;
|
|
14
14
|
/** Python `_publish_session_list_changed("cron_complete", profile=...)` once a manual run finishes. */
|
|
15
15
|
publishSessionsChanged?: (reason: string, profile: string | null) => void;
|
|
16
|
+
/** TAL-301: the catalog entry id a job's stored `(model, provider)` selects in a profile home's picker catalog. */
|
|
17
|
+
modelOptionFor?: (home: string, model: string | null, provider: string | null) => Promise<string | null>;
|
|
16
18
|
/** Python `_RUNNING_CRON_JOBS`: job id → start time, read by the session list's `cron_running` stamp. */
|
|
17
19
|
runningJobs?: Map<string, number>;
|
|
18
20
|
}
|
|
19
|
-
/** Python `_cron_job_for_api
|
|
20
|
-
export declare function jobForApi(job: Dict): Dict;
|
|
21
|
+
/** Python `_cron_job_for_api`, plus the derived status every client renders (TAL-296). */
|
|
22
|
+
export declare function jobForApi(job: Dict, running?: boolean): Dict;
|
|
21
23
|
/** Python `_cron_job_field_updates`. */
|
|
22
24
|
export declare function jobFieldUpdates(body: Dict, currentContextFrom?: unknown): Dict;
|
|
23
25
|
export declare function validJobId(id: string): boolean;
|
|
26
|
+
/** Python `float(since)` with its ValueError mapped to 0: a malformed `since` means "from the epoch", never a 500. */
|
|
27
|
+
export declare function parseSince(raw: string | undefined): number;
|
|
28
|
+
/**
|
|
29
|
+
* Python `_handle_cron_recent`'s `last_run_at` read (`datetime.fromisoformat` after `Z` → `+00:00`, or a number).
|
|
30
|
+
* Only ISO-shaped strings count, so `Date.parse` leniency ("Jan 2 2026") never invents a completion; a time without
|
|
31
|
+
* an offset is server-local, as in Python. Anything else is skipped.
|
|
32
|
+
*/
|
|
33
|
+
export declare function completedAtSeconds(value: unknown): number | null;
|
|
34
|
+
/** The one place a job's `last_status` becomes the success/failure the clients render. */
|
|
35
|
+
export declare function completionOutcome(status: unknown): CronRecentCompletion['outcome'];
|
|
24
36
|
export declare class CronService {
|
|
25
37
|
private readonly deps;
|
|
26
38
|
constructor(deps: CronDeps);
|
|
@@ -28,8 +40,30 @@ export declare class CronService {
|
|
|
28
40
|
private profileNames;
|
|
29
41
|
availableProfileNames(): Promise<Set<string>>;
|
|
30
42
|
normalizeProfile(value: unknown): Promise<string | null>;
|
|
43
|
+
private profileForHome;
|
|
44
|
+
/** The physical store owns execution. Additive owner_profile metadata lets the creator manage a new job there. */
|
|
45
|
+
private storedJobs;
|
|
46
|
+
/** `pickerHome` is the profile whose `/api/models` catalog the requesting client shows. */
|
|
47
|
+
private view;
|
|
48
|
+
private requireExecutionStore;
|
|
49
|
+
private validateContext;
|
|
50
|
+
private resolveStore;
|
|
51
|
+
contextSources(home: string, input: {
|
|
52
|
+
profile?: string | undefined;
|
|
53
|
+
editing_job_id?: string | undefined;
|
|
54
|
+
exclude_job_id?: string | undefined;
|
|
55
|
+
selected_refs?: string[] | undefined;
|
|
56
|
+
}): Promise<CronContextSources>;
|
|
31
57
|
/** Python `/api/crons`: the active profile's rows plus foreign rows (hidden unless `all_profiles`). */
|
|
32
58
|
list(active: string, allProfiles: boolean): Promise<Dict>;
|
|
59
|
+
/**
|
|
60
|
+
* Python `/api/crons/recent`: each active-profile job's latest completion after `since`, newest first (ties by
|
|
61
|
+
* `job_id`), with the server's `outcome` and the newest cron session for that job. One row per job, not a run archive.
|
|
62
|
+
*/
|
|
63
|
+
recent(home: string, rawSince: string | undefined): Promise<{
|
|
64
|
+
completions: CronRecentCompletion[];
|
|
65
|
+
since: number;
|
|
66
|
+
}>;
|
|
33
67
|
create(home: string, body: Dict): Promise<Dict>;
|
|
34
68
|
update(home: string, body: Dict): Promise<Dict>;
|
|
35
69
|
private simple;
|
package/dist/tools/crons.js
CHANGED
|
@@ -1,18 +1,87 @@
|
|
|
1
|
+
/** Cron jobs across profiles through the sidecar `cron.*` namespace (Python `api/routes.py` cron section). */
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { parseProviderQualifiedModel } from '../config/agent-config.js';
|
|
1
4
|
import { HttpFailure } from '../sessions/service.js';
|
|
2
5
|
import { SidecarError } from '../sidecar/client.js';
|
|
6
|
+
import { latestCronSessionInfo } from '../sessions/state-db.js';
|
|
7
|
+
import { stripToolCallXml } from '../sessions/merge.js';
|
|
3
8
|
import { str } from '../util.js';
|
|
4
9
|
const JOB_ID_RE = /^[A-Za-z0-9_-][A-Za-z0-9_.-]{0,63}$/;
|
|
5
10
|
const PASSTHROUGH_FIELDS = ['script', 'no_agent', 'context_from', 'reasoning_effort'];
|
|
6
|
-
/**
|
|
7
|
-
|
|
11
|
+
/** TAL-301: a picked catalog id (`@provider:model`) names its own provider, exactly as a chat request does; a bare id keeps the explicit one. */
|
|
12
|
+
function modelSelection(model, provider) {
|
|
13
|
+
const raw = str(model).trim();
|
|
14
|
+
const explicit = str(provider).trim() || null;
|
|
15
|
+
if (!raw)
|
|
16
|
+
return [null, explicit];
|
|
17
|
+
return parseProviderQualifiedModel(raw) ?? [raw, explicit];
|
|
18
|
+
}
|
|
19
|
+
/** Python `_cron_job_for_api`, plus the derived status every client renders (TAL-296). */
|
|
20
|
+
export function jobForApi(job, running = false) {
|
|
8
21
|
const payload = { ...job };
|
|
22
|
+
// TAL-301: a job stored with a provider-qualified id (older clients) still reads back as a bare model and its provider.
|
|
23
|
+
const qualified = parseProviderQualifiedModel(job.model);
|
|
24
|
+
if (qualified)
|
|
25
|
+
[payload.model, payload.provider] = qualified;
|
|
9
26
|
if (!('profile' in payload))
|
|
10
27
|
payload.profile = null;
|
|
11
28
|
payload.toast_notifications = payload.toast_notifications !== false;
|
|
12
29
|
payload.monitor = str(payload.monitor_url) || str(payload.monitor_script) || '';
|
|
13
30
|
payload.continuity = (Array.isArray(payload.context_from) ? payload.context_from : []).some((r) => str(r).trim().toLowerCase() === 'self');
|
|
31
|
+
const state = cronDerivedState(job);
|
|
32
|
+
payload.derived_state = state;
|
|
33
|
+
payload.needs_attention = state === 'needs_attention' || state === 'schedule_error';
|
|
34
|
+
payload.resumable = payload.needs_attention || state === 'paused' || state === 'off';
|
|
35
|
+
payload.running = running || job.running === true;
|
|
36
|
+
Object.assign(payload, scheduleText(job));
|
|
14
37
|
return payload;
|
|
15
38
|
}
|
|
39
|
+
/** TAL-298: the schedule's display text and the editor's prefill, in the scheduler's own vocabulary (not localized copy). */
|
|
40
|
+
function scheduleText(job) {
|
|
41
|
+
const schedule = job.schedule;
|
|
42
|
+
const legacy = typeof schedule === 'string' ? schedule : '';
|
|
43
|
+
const s = typeof schedule === 'object' && schedule ? schedule : {};
|
|
44
|
+
const minutes = typeof s.minutes === 'number' && s.minutes > 0 ? s.minutes : 0;
|
|
45
|
+
const runAt = str(s.run_at);
|
|
46
|
+
let input = '';
|
|
47
|
+
let built = '';
|
|
48
|
+
if (s.kind === 'cron')
|
|
49
|
+
input = built = str(s.expr);
|
|
50
|
+
else if (s.kind === 'interval' && minutes)
|
|
51
|
+
[input, built] = [`every ${minutes}m`, minutes % 60 ? `every ${minutes}m` : `every ${minutes / 60}h`];
|
|
52
|
+
else if (s.kind === 'once' && runAt)
|
|
53
|
+
[input, built] = [runAt, `once at ${runAt}`];
|
|
54
|
+
const display = str(job.schedule_display) || str(s.display) || legacy || built;
|
|
55
|
+
return { schedule_display: display, schedule_input: input || legacy || display };
|
|
56
|
+
}
|
|
57
|
+
/** `repeat.times == null` means "forever" in the store; a missing record is not unlimited. */
|
|
58
|
+
function hasUnlimitedRepeat(job) {
|
|
59
|
+
return !!job.repeat && typeof job.repeat === 'object' && job.repeat.times == null;
|
|
60
|
+
}
|
|
61
|
+
function isRecurring(job) {
|
|
62
|
+
const schedule = job.schedule;
|
|
63
|
+
if (typeof schedule === 'object' && schedule)
|
|
64
|
+
return schedule.kind === 'cron' || schedule.kind === 'interval';
|
|
65
|
+
// Legacy string schedules carry no kind; an unlimited repeat record marks the job recurring (a one-shot has times: 1).
|
|
66
|
+
return typeof schedule === 'string' && hasUnlimitedRepeat(job);
|
|
67
|
+
}
|
|
68
|
+
/** Older agents report `paused` / `status` / `next_run` instead of `state` / `last_status` / `next_run_at`; all stay supported. */
|
|
69
|
+
function cronDerivedState(job) {
|
|
70
|
+
const errored = job.state === 'error' || completionOutcome(job.last_status) === 'failed' || job.status === 'error';
|
|
71
|
+
const nextRun = job.next_run_at ?? (typeof job.next_run === 'number' || typeof job.next_run === 'string' ? job.next_run : null);
|
|
72
|
+
if (isRecurring(job) && hasUnlimitedRepeat(job) && job.enabled === false && job.state === 'completed' && !nextRun)
|
|
73
|
+
return 'needs_attention';
|
|
74
|
+
// A paused job keeps the last run's error and has no next run; that is not a schedule failure.
|
|
75
|
+
if (job.state === 'paused' || job.paused)
|
|
76
|
+
return 'paused';
|
|
77
|
+
if (isRecurring(job) && !nextRun && errored)
|
|
78
|
+
return 'schedule_error';
|
|
79
|
+
if (job.enabled === false)
|
|
80
|
+
return 'off';
|
|
81
|
+
if (errored)
|
|
82
|
+
return 'error';
|
|
83
|
+
return 'active';
|
|
84
|
+
}
|
|
16
85
|
function monitorStorage(monitor) {
|
|
17
86
|
const value = str(monitor).trim();
|
|
18
87
|
if (!value)
|
|
@@ -53,6 +122,50 @@ export function jobFieldUpdates(body, currentContextFrom = null) {
|
|
|
53
122
|
export function validJobId(id) {
|
|
54
123
|
return JOB_ID_RE.test(id) && id !== '.' && id !== '..';
|
|
55
124
|
}
|
|
125
|
+
const PY_FLOAT_RE = /^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/;
|
|
126
|
+
/** Python `float(since)` with its ValueError mapped to 0: a malformed `since` means "from the epoch", never a 500. */
|
|
127
|
+
export function parseSince(raw) {
|
|
128
|
+
const t = (raw ?? '').trim();
|
|
129
|
+
const n = PY_FLOAT_RE.test(t) ? Number(t) : 0;
|
|
130
|
+
return Number.isFinite(n) ? n : 0;
|
|
131
|
+
}
|
|
132
|
+
const ISO_RE = /^(\d{4})-(\d{2})-(\d{2})(?:[T ](\d{2})(?::(\d{2})(?::(\d{2})(?:\.(\d{1,6}))?)?)?)?(Z|[+-]\d{2}(?::?\d{2})?)?$/;
|
|
133
|
+
/**
|
|
134
|
+
* Python `_handle_cron_recent`'s `last_run_at` read (`datetime.fromisoformat` after `Z` → `+00:00`, or a number).
|
|
135
|
+
* Only ISO-shaped strings count, so `Date.parse` leniency ("Jan 2 2026") never invents a completion; a time without
|
|
136
|
+
* an offset is server-local, as in Python. Anything else is skipped.
|
|
137
|
+
*/
|
|
138
|
+
export function completedAtSeconds(value) {
|
|
139
|
+
if (typeof value === 'number')
|
|
140
|
+
return value && Number.isFinite(value) ? value : null;
|
|
141
|
+
if (typeof value !== 'string')
|
|
142
|
+
return null;
|
|
143
|
+
const m = ISO_RE.exec(value);
|
|
144
|
+
if (!m)
|
|
145
|
+
return null;
|
|
146
|
+
const [y, mo, d, h, mi, sec] = [1, 2, 3, 4, 5, 6].map((i) => Number(m[i] ?? 0));
|
|
147
|
+
const ms = Number((m[7] ?? '').padEnd(3, '0').slice(0, 3));
|
|
148
|
+
if (mo < 1 || mo > 12 || d < 1 || new Date(Date.UTC(y, mo - 1, d)).getUTCDate() !== d || h > 23 || mi > 59 || sec > 59)
|
|
149
|
+
return null;
|
|
150
|
+
const offset = m[8];
|
|
151
|
+
if (offset === undefined)
|
|
152
|
+
return new Date(y, mo - 1, d, h, mi, sec, ms).getTime() / 1000;
|
|
153
|
+
let offsetMinutes = 0;
|
|
154
|
+
if (offset !== 'Z') {
|
|
155
|
+
const digits = offset.slice(1).replace(':', '');
|
|
156
|
+
offsetMinutes = (offset.startsWith('-') ? -1 : 1) * (Number(digits.slice(0, 2)) * 60 + Number(digits.slice(2) || 0));
|
|
157
|
+
}
|
|
158
|
+
return (Date.UTC(y, mo - 1, d, h, mi, sec, ms) - offsetMinutes * 60_000) / 1000;
|
|
159
|
+
}
|
|
160
|
+
/** The one place a job's `last_status` becomes the success/failure the clients render. */
|
|
161
|
+
export function completionOutcome(status) {
|
|
162
|
+
const s = str(status).trim().toLowerCase();
|
|
163
|
+
if (s === 'error' || s === 'failed')
|
|
164
|
+
return 'failed';
|
|
165
|
+
if (s === 'ok' || s === 'success' || s === 'completed')
|
|
166
|
+
return 'succeeded';
|
|
167
|
+
return 'unknown';
|
|
168
|
+
}
|
|
56
169
|
export class CronService {
|
|
57
170
|
deps;
|
|
58
171
|
constructor(deps) {
|
|
@@ -72,6 +185,8 @@ export class CronService {
|
|
|
72
185
|
names.push(n);
|
|
73
186
|
} };
|
|
74
187
|
add(active);
|
|
188
|
+
if (this.deps.isolatedProfileMode())
|
|
189
|
+
return names;
|
|
75
190
|
for (const row of await this.deps.profileNames())
|
|
76
191
|
if (row.visible || this.deps.profilesMatch(row.name, active))
|
|
77
192
|
add(row.name);
|
|
@@ -97,51 +212,195 @@ export class CronService {
|
|
|
97
212
|
throw new HttpFailure(400, `Unknown profile: ${profile}`);
|
|
98
213
|
return profile;
|
|
99
214
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
215
|
+
async profileForHome(home) {
|
|
216
|
+
const names = this.deps.isolatedProfileMode() ? (await this.deps.profileNames()).map((row) => row.name) : await this.availableProfileNames();
|
|
217
|
+
for (const profile of names)
|
|
218
|
+
if (this.deps.profileHome(profile) === home)
|
|
219
|
+
return profile;
|
|
220
|
+
throw new HttpFailure(403, 'Unknown cron profile home');
|
|
221
|
+
}
|
|
222
|
+
/** The physical store owns execution. Additive owner_profile metadata lets the creator manage a new job there. */
|
|
223
|
+
async storedJobs(active) {
|
|
224
|
+
// ponytail: scan visible stores per request; add an index only if profile/job counts make this expensive.
|
|
225
|
+
const rows = [];
|
|
226
|
+
const seen = new Set();
|
|
227
|
+
for (const profile of await this.profileNames(active)) {
|
|
228
|
+
const home = this.deps.profileHome(profile);
|
|
229
|
+
if (seen.has(home))
|
|
109
230
|
continue;
|
|
110
|
-
|
|
111
|
-
const
|
|
231
|
+
seen.add(home);
|
|
232
|
+
const local = this.deps.profilesMatch(profile, active);
|
|
112
233
|
let jobs;
|
|
113
234
|
try {
|
|
114
|
-
jobs = (await sidecar.call('cron.list', { profile_home: home })).jobs
|
|
235
|
+
jobs = (await this.sidecar().call('cron.list', { profile_home: home })).jobs;
|
|
115
236
|
}
|
|
116
237
|
catch (error) {
|
|
117
|
-
if (
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
238
|
+
if (local)
|
|
239
|
+
throw error;
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
for (const job of jobs) {
|
|
243
|
+
const creator = str(job.owner_profile).trim();
|
|
244
|
+
rows.push({ home, profile, job, managed: local || Boolean(creator && this.deps.profilesMatch(creator, active)) });
|
|
122
245
|
}
|
|
123
|
-
|
|
124
|
-
|
|
246
|
+
}
|
|
247
|
+
return rows;
|
|
248
|
+
}
|
|
249
|
+
/** `pickerHome` is the profile whose `/api/models` catalog the requesting client shows. */
|
|
250
|
+
async view(row, pickerHome) {
|
|
251
|
+
const payload = { ...jobForApi(row.job, this.deps.runningJobs?.has(str(row.job.id)) ?? false), profile: str(row.job.profile).trim() || row.profile, owner_profile: row.profile, read_only: !row.managed };
|
|
252
|
+
payload.model_option_id = (await this.deps.modelOptionFor?.(pickerHome, str(payload.model) || null, str(payload.provider) || null)) ?? null;
|
|
253
|
+
return payload;
|
|
254
|
+
}
|
|
255
|
+
requireExecutionStore(row) {
|
|
256
|
+
const profile = str(row.job.profile).trim();
|
|
257
|
+
if (profile && !this.deps.profilesMatch(profile, row.profile))
|
|
258
|
+
throw new HttpFailure(409, 'This legacy task must be recreated in its execution profile before it can run or resume');
|
|
259
|
+
}
|
|
260
|
+
async validateContext(home, fields) {
|
|
261
|
+
const refs = continuityRefs(fields.context_from, false);
|
|
262
|
+
if (!refs.length)
|
|
263
|
+
return;
|
|
264
|
+
const ids = new Set((await this.sidecar().call('cron.list', { profile_home: home })).jobs.map((job) => job.id));
|
|
265
|
+
if (refs.some((ref) => !ids.has(str(ref))))
|
|
266
|
+
throw new HttpFailure(400, 'Context jobs must belong to the execution profile');
|
|
267
|
+
}
|
|
268
|
+
async resolveStore(home, ref) {
|
|
269
|
+
const active = await this.profileForHome(home);
|
|
270
|
+
const allRows = await this.storedJobs(active);
|
|
271
|
+
const rows = allRows.filter((row) => row.managed);
|
|
272
|
+
const exact = rows.filter((row) => row.job.id === ref);
|
|
273
|
+
const matches = exact.length ? exact : rows.filter((row) => row.job.name === ref);
|
|
274
|
+
if (!matches.length)
|
|
275
|
+
throw new HttpFailure(404, 'Job not found');
|
|
276
|
+
if (matches.length !== 1)
|
|
277
|
+
throw new HttpFailure(409, 'Ambiguous cron job reference');
|
|
278
|
+
const match = matches[0];
|
|
279
|
+
if (allRows.filter((row) => row.home === match.home && row.job.id === match.job.id).length !== 1)
|
|
280
|
+
throw new HttpFailure(409, 'Ambiguous cron job reference');
|
|
281
|
+
return match;
|
|
282
|
+
}
|
|
283
|
+
async contextSources(home, input) {
|
|
284
|
+
const active = await this.profileForHome(home);
|
|
285
|
+
const editing = input.editing_job_id ? await this.resolveStore(home, input.editing_job_id) : null;
|
|
286
|
+
const profile = await this.normalizeProfile(input.profile);
|
|
287
|
+
if (profile && !(await this.profileNames(active)).some((name) => this.deps.profilesMatch(name, profile)))
|
|
288
|
+
throw new HttpFailure(403, 'Execution profile is not accessible');
|
|
289
|
+
const executionHome = profile ? this.deps.profileHome(profile) : editing?.home ?? home;
|
|
290
|
+
const rows = await this.storedJobs(active);
|
|
291
|
+
const inStore = rows.filter((row) => row.home === executionHome);
|
|
292
|
+
const excludeId = editing ? str(editing.job.id) : input.exclude_job_id;
|
|
293
|
+
const counts = new Map();
|
|
294
|
+
for (const row of inStore)
|
|
295
|
+
counts.set(str(row.job.id), (counts.get(str(row.job.id)) ?? 0) + 1);
|
|
296
|
+
const sources = [];
|
|
297
|
+
const included = new Set();
|
|
298
|
+
for (const row of inStore) {
|
|
299
|
+
const id = str(row.job.id).trim();
|
|
300
|
+
if (!row.managed || !id || id === excludeId || counts.get(id) !== 1)
|
|
301
|
+
continue;
|
|
302
|
+
sources.push({ job_id: id, label: str(row.job.name).trim() || id, selectable: true });
|
|
303
|
+
included.add(id);
|
|
304
|
+
}
|
|
305
|
+
for (const raw of input.selected_refs ?? []) {
|
|
306
|
+
const id = raw.trim();
|
|
307
|
+
if (!id || id.toLowerCase() === 'self' || included.has(id))
|
|
308
|
+
continue;
|
|
309
|
+
const owned = rows.find((row) => row.managed && row.job.id === id);
|
|
310
|
+
sources.push({ job_id: id, label: str(owned?.job.name).trim() || id, selectable: false });
|
|
311
|
+
included.add(id);
|
|
312
|
+
}
|
|
313
|
+
return { profile: profile ?? editing?.profile ?? active, sources };
|
|
314
|
+
}
|
|
315
|
+
/** Python `/api/crons`: the active profile's rows plus foreign rows (hidden unless `all_profiles`). */
|
|
316
|
+
async list(active, allProfiles) {
|
|
317
|
+
const activeJobs = [];
|
|
318
|
+
const otherJobs = [];
|
|
319
|
+
const pickerHome = this.deps.profileHome(active);
|
|
320
|
+
try {
|
|
321
|
+
for (const row of await this.storedJobs(active))
|
|
322
|
+
(row.managed ? activeJobs : otherJobs).push(await this.view(row, pickerHome));
|
|
323
|
+
}
|
|
324
|
+
catch (error) {
|
|
325
|
+
if (error instanceof SidecarError && error.condition === 'cron_unavailable')
|
|
326
|
+
return { jobs: [], cron_unavailable: true };
|
|
327
|
+
throw error;
|
|
125
328
|
}
|
|
126
329
|
const all = allProfiles && !this.deps.isolatedProfileMode();
|
|
127
330
|
return { jobs: all ? [...activeJobs, ...otherJobs] : activeJobs, all_profiles: all, active_profile: active, other_profile_count: all ? 0 : otherJobs.length };
|
|
128
331
|
}
|
|
332
|
+
/**
|
|
333
|
+
* Python `/api/crons/recent`: each active-profile job's latest completion after `since`, newest first (ties by
|
|
334
|
+
* `job_id`), with the server's `outcome` and the newest cron session for that job. One row per job, not a run archive.
|
|
335
|
+
*/
|
|
336
|
+
async recent(home, rawSince) {
|
|
337
|
+
const since = parseSince(rawSince);
|
|
338
|
+
let rows;
|
|
339
|
+
try {
|
|
340
|
+
rows = (await this.storedJobs(await this.profileForHome(home))).filter((row) => row.managed);
|
|
341
|
+
}
|
|
342
|
+
catch (error) {
|
|
343
|
+
if (error instanceof SidecarError && error.condition === 'cron_unavailable')
|
|
344
|
+
return { completions: [], since };
|
|
345
|
+
throw error;
|
|
346
|
+
}
|
|
347
|
+
const completions = [];
|
|
348
|
+
for (const { job } of rows) {
|
|
349
|
+
const jobId = str(job.id).trim();
|
|
350
|
+
const completedAt = completedAtSeconds(job.last_run_at);
|
|
351
|
+
if (!jobId || completedAt === null || completedAt <= since)
|
|
352
|
+
continue;
|
|
353
|
+
const status = 'last_status' in job ? (job.last_status === null ? null : str(job.last_status)) : 'unknown';
|
|
354
|
+
completions.push({
|
|
355
|
+
job_id: jobId,
|
|
356
|
+
name: 'name' in job ? (job.name === null ? null : str(job.name)) : 'Unknown',
|
|
357
|
+
status,
|
|
358
|
+
outcome: completionOutcome(status),
|
|
359
|
+
completed_at: completedAt,
|
|
360
|
+
toast_notifications: job.toast_notifications !== false,
|
|
361
|
+
session_id: '',
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
completions.sort((a, b) => b.completed_at - a.completed_at || (a.job_id < b.job_id ? -1 : a.job_id > b.job_id ? 1 : 0));
|
|
365
|
+
for (const storeHome of new Set(rows.map((row) => row.home))) {
|
|
366
|
+
const ids = rows.filter((row) => row.home === storeHome).map((row) => str(row.job.id));
|
|
367
|
+
const sessions = latestCronSessionInfo(join(storeHome, 'state.db'), ids, completions.filter((c) => ids.includes(c.job_id)).map((c) => c.job_id));
|
|
368
|
+
for (const completion of completions) {
|
|
369
|
+
if (!ids.includes(completion.job_id))
|
|
370
|
+
continue;
|
|
371
|
+
const info = sessions.get(completion.job_id);
|
|
372
|
+
if (!info)
|
|
373
|
+
continue;
|
|
374
|
+
completion.session_id = info.session_id;
|
|
375
|
+
if (info.message_count !== null)
|
|
376
|
+
completion.message_count = info.message_count;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
return { completions, since };
|
|
380
|
+
}
|
|
129
381
|
async create(home, body) {
|
|
130
382
|
if (!('schedule' in body) || body.schedule === null || body.schedule === undefined)
|
|
131
383
|
throw new HttpFailure(400, 'Missing required field(s): schedule');
|
|
132
384
|
if (!body.prompt && !body.script && !body.skills)
|
|
133
385
|
throw new HttpFailure(400, 'Missing required field(s): prompt');
|
|
134
386
|
const profile = await this.normalizeProfile(body.profile);
|
|
135
|
-
const
|
|
387
|
+
const active = await this.profileForHome(home);
|
|
388
|
+
if (profile && !(await this.profileNames(active)).some((name) => this.deps.profilesMatch(name, profile)))
|
|
389
|
+
throw new HttpFailure(403, 'Execution profile is not accessible');
|
|
390
|
+
const executionHome = profile ? this.deps.profileHome(profile) : home;
|
|
391
|
+
const [model, provider] = modelSelection(body.model, body.provider);
|
|
392
|
+
const job = { prompt: body.prompt ?? '', schedule: body.schedule, name: body.name ?? null, deliver: body.deliver ?? 'local', skills: body.skills ?? [], model, provider, ...jobFieldUpdates(body) };
|
|
136
393
|
if (body.repeat !== null && body.repeat !== undefined)
|
|
137
394
|
job.repeat = body.repeat;
|
|
138
395
|
if (profile !== null)
|
|
139
396
|
job.profile = profile;
|
|
140
397
|
if (body.toast_notifications === false)
|
|
141
398
|
job.toast_notifications = false;
|
|
399
|
+
job.owner_profile = active;
|
|
400
|
+
await this.validateContext(executionHome, job);
|
|
142
401
|
try {
|
|
143
|
-
const result = await this.sidecar().call('cron.create', { profile_home:
|
|
144
|
-
return { ok: true, job:
|
|
402
|
+
const result = await this.sidecar().call('cron.create', { profile_home: executionHome, job, execution_home: profile ? executionHome : null });
|
|
403
|
+
return { ok: true, job: await this.view({ home: executionHome, profile: profile ?? active, job: result.job, managed: true }, home) };
|
|
145
404
|
}
|
|
146
405
|
catch (error) {
|
|
147
406
|
throw new HttpFailure(400, str(error.message));
|
|
@@ -151,32 +410,47 @@ export class CronService {
|
|
|
151
410
|
const jobId = str(body.job_id);
|
|
152
411
|
if (!jobId)
|
|
153
412
|
throw new HttpFailure(400, 'Missing required field(s): job_id');
|
|
413
|
+
const store = await this.resolveStore(home, jobId);
|
|
414
|
+
const storedId = str(store.job.id);
|
|
415
|
+
const pickerHome = home;
|
|
416
|
+
home = store.home;
|
|
154
417
|
const updates = {};
|
|
155
418
|
for (const [k, v] of Object.entries(body)) {
|
|
156
|
-
if (k === 'job_id')
|
|
419
|
+
if (k === 'job_id' || k === 'id' || k === 'owner_profile')
|
|
157
420
|
continue;
|
|
158
|
-
if (k === 'profile')
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
421
|
+
if (k === 'profile') {
|
|
422
|
+
const profile = await this.normalizeProfile(v);
|
|
423
|
+
if (profile && !this.deps.profilesMatch(profile, store.profile))
|
|
424
|
+
throw new HttpFailure(400, 'To change the execution profile, duplicate the task in that profile and delete the old task');
|
|
425
|
+
updates.profile = profile;
|
|
426
|
+
}
|
|
427
|
+
else if (k === 'model' || k === 'provider' || k === 'monitor' || k === 'continuity' || k === 'repeat')
|
|
163
428
|
continue;
|
|
164
429
|
else if (v !== null && v !== undefined)
|
|
165
430
|
updates[k] = v;
|
|
166
431
|
}
|
|
432
|
+
if ('model' in body) {
|
|
433
|
+
const [model, provider] = modelSelection(body.model, body.provider);
|
|
434
|
+
updates.model = model;
|
|
435
|
+
if (provider !== null || 'provider' in body)
|
|
436
|
+
updates.provider = provider;
|
|
437
|
+
}
|
|
438
|
+
else if ('provider' in body)
|
|
439
|
+
updates.provider = str(body.provider).trim() || null;
|
|
167
440
|
let currentContextFrom = null;
|
|
168
441
|
if ('continuity' in body && !('context_from' in body)) {
|
|
169
442
|
try {
|
|
170
|
-
currentContextFrom = (await this.sidecar().call('cron.get', { profile_home: home, job_id:
|
|
443
|
+
currentContextFrom = (await this.sidecar().call('cron.get', { profile_home: home, job_id: storedId })).job?.context_from ?? null;
|
|
171
444
|
}
|
|
172
445
|
catch {
|
|
173
446
|
currentContextFrom = null;
|
|
174
447
|
}
|
|
175
448
|
}
|
|
176
449
|
Object.assign(updates, jobFieldUpdates(body, currentContextFrom));
|
|
450
|
+
await this.validateContext(home, updates);
|
|
177
451
|
try {
|
|
178
|
-
const result = await this.sidecar().call('cron.update', { profile_home: home, job_id:
|
|
179
|
-
return { ok: true, job:
|
|
452
|
+
const result = await this.sidecar().call('cron.update', { profile_home: home, job_id: storedId, updates });
|
|
453
|
+
return { ok: true, job: await this.view({ ...store, job: result.job }, pickerHome) };
|
|
180
454
|
}
|
|
181
455
|
catch (error) {
|
|
182
456
|
if (error instanceof SidecarError && error.condition === 'not_found')
|
|
@@ -187,10 +461,13 @@ export class CronService {
|
|
|
187
461
|
async simple(method, home, jobId, extra = {}) {
|
|
188
462
|
if (!jobId)
|
|
189
463
|
throw new HttpFailure(400, method === 'cron.delete' ? 'Missing required field(s): job_id' : 'job_id required');
|
|
464
|
+
const store = await this.resolveStore(home, jobId);
|
|
465
|
+
if (method === 'cron.resume')
|
|
466
|
+
this.requireExecutionStore(store);
|
|
190
467
|
try {
|
|
191
|
-
const result = await this.sidecar().call(method, { profile_home: home, job_id:
|
|
468
|
+
const result = await this.sidecar().call(method, { profile_home: store.home, job_id: str(store.job.id), ...extra });
|
|
192
469
|
// Python returned the raw `pause_job`/`resume_job` record and `{ok, job_id}` for delete.
|
|
193
|
-
return 'job' in result ? { ok: true, job: result.job } : { ok: true, job_id: jobId };
|
|
470
|
+
return 'job' in result ? { ok: true, job: await this.view({ ...store, job: result.job }, home) } : { ok: true, job_id: jobId };
|
|
194
471
|
}
|
|
195
472
|
catch (error) {
|
|
196
473
|
if (error instanceof SidecarError && error.condition === 'not_found')
|
|
@@ -216,6 +493,11 @@ export class CronService {
|
|
|
216
493
|
running?.set(jobId, Date.now() / 1000);
|
|
217
494
|
try {
|
|
218
495
|
const sidecar = this.sidecar();
|
|
496
|
+
const store = await this.resolveStore(home, jobId);
|
|
497
|
+
if (store.job.id !== jobId)
|
|
498
|
+
throw new HttpFailure(404, 'Job not found');
|
|
499
|
+
this.requireExecutionStore(store);
|
|
500
|
+
home = store.home;
|
|
219
501
|
let job;
|
|
220
502
|
try {
|
|
221
503
|
job = (await sidecar.call('cron.get', { profile_home: home, job_id: jobId })).job;
|
|
@@ -287,6 +569,7 @@ export class CronService {
|
|
|
287
569
|
const l = pyInt(limit, 50);
|
|
288
570
|
if (!Number.isFinite(o) || !Number.isFinite(l))
|
|
289
571
|
throw new HttpFailure(400, 'offset and limit must be integers');
|
|
572
|
+
home = (await this.resolveStore(home, jobId)).home;
|
|
290
573
|
return this.sidecar().call('cron.history', { profile_home: home, job_id: jobId, offset: Math.max(0, o), limit: Math.max(1, Math.min(500, l)) });
|
|
291
574
|
}
|
|
292
575
|
async runDetail(home, jobId, filename) {
|
|
@@ -296,8 +579,11 @@ export class CronService {
|
|
|
296
579
|
throw new HttpFailure(400, 'invalid job_id');
|
|
297
580
|
if (filename.includes('/') || filename.includes('\\') || filename === '..')
|
|
298
581
|
throw new HttpFailure(400, 'invalid filename');
|
|
582
|
+
home = (await this.resolveStore(home, jobId)).home;
|
|
299
583
|
try {
|
|
300
|
-
|
|
584
|
+
const detail = await this.sidecar().call('cron.run_detail', { profile_home: home, job_id: jobId, filename });
|
|
585
|
+
// Leaked tool-call XML is removed from the run's text, as from a transcript reply (TAL-302).
|
|
586
|
+
return { ...detail, content: stripToolCallXml(detail.content), snippet: stripToolCallXml(detail.snippet) };
|
|
301
587
|
}
|
|
302
588
|
catch (error) {
|
|
303
589
|
if (error instanceof SidecarError && error.condition === 'not_found')
|
|
@@ -311,6 +597,7 @@ export class CronService {
|
|
|
311
597
|
if (!JOB_ID_RE.test(jobId))
|
|
312
598
|
throw new HttpFailure(400, 'invalid job_id');
|
|
313
599
|
const l = Number.parseInt(limit ?? '5', 10);
|
|
600
|
+
home = (await this.resolveStore(home, jobId)).home;
|
|
314
601
|
return this.sidecar().call('cron.output', { profile_home: home, job_id: jobId, limit: Number.isFinite(l) ? Math.max(1, Math.min(500, l)) : 5 });
|
|
315
602
|
}
|
|
316
603
|
async deliveryOptions() {
|