@maudecode/talaria-web 1.19.0 → 1.21.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/_release.json +8 -8
- package/dist/api/automation-raw.js +61 -6
- package/dist/api/automation-raw.js.map +1 -1
- package/dist/api/automation-router.d.ts +309 -2
- package/dist/api/automation-router.js +28 -2
- package/dist/api/automation-router.js.map +1 -1
- package/dist/api/chat-router.d.ts +646 -24
- package/dist/api/chat-router.js +54 -167
- package/dist/api/chat-router.js.map +1 -1
- package/dist/api/git-router.d.ts +54 -0
- package/dist/api/git-router.js +18 -5
- package/dist/api/git-router.js.map +1 -1
- package/dist/api/raw-routes.js +13 -1
- package/dist/api/raw-routes.js.map +1 -1
- package/dist/api/router.d.ts +3 -3
- package/dist/api/session-visibility.js +2 -2
- package/dist/api/session-visibility.js.map +1 -1
- package/dist/api/sessions-router.d.ts +1868 -79
- package/dist/api/sessions-router.js +72 -43
- package/dist/api/sessions-router.js.map +1 -1
- package/dist/api/settings-router.d.ts +34 -13
- package/dist/api/settings-router.js +54 -17
- package/dist/api/settings-router.js.map +1 -1
- package/dist/api/sse-routes.js +45 -21
- package/dist/api/sse-routes.js.map +1 -1
- package/dist/api/tools-router.d.ts +773 -39
- package/dist/api/tools-router.js +167 -45
- package/dist/api/tools-router.js.map +1 -1
- package/dist/app.js +15 -11
- package/dist/app.js.map +1 -1
- package/dist/auth/crypto.d.ts +3 -0
- package/dist/auth/crypto.js +18 -0
- package/dist/auth/crypto.js.map +1 -1
- package/dist/auth/gate.js +5 -1
- package/dist/auth/gate.js.map +1 -1
- package/dist/cli/ctl.js +6 -1
- package/dist/cli/ctl.js.map +1 -1
- package/dist/cli/main.js +23 -18
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/supervise.d.ts +22 -0
- package/dist/cli/supervise.js +80 -2
- package/dist/cli/supervise.js.map +1 -1
- package/dist/config/agent-config.d.ts +3 -0
- package/dist/config/agent-config.js +36 -9
- package/dist/config/agent-config.js.map +1 -1
- package/dist/fs/atomic.d.ts +3 -0
- package/dist/fs/atomic.js +19 -5
- package/dist/fs/atomic.js.map +1 -1
- package/dist/fs/stat.d.ts +6 -0
- package/dist/fs/stat.js +18 -2
- package/dist/fs/stat.js.map +1 -1
- package/dist/http/context.d.ts +16 -0
- package/dist/http/context.js +48 -5
- package/dist/http/context.js.map +1 -1
- package/dist/profiles/profiles.d.ts +2 -0
- package/dist/profiles/profiles.js +1 -0
- package/dist/profiles/profiles.js.map +1 -1
- package/dist/providers/catalog.d.ts +11 -6
- package/dist/providers/catalog.js +76 -24
- package/dist/providers/catalog.js.map +1 -1
- package/dist/redact.d.ts +2 -0
- package/dist/redact.js +55 -16
- package/dist/redact.js.map +1 -1
- package/dist/release.js +5 -3
- package/dist/release.js.map +1 -1
- package/dist/runtime.js +118 -26
- package/dist/runtime.js.map +1 -1
- package/dist/server.js +25 -21
- package/dist/server.js.map +1 -1
- package/dist/sessions/admission.d.ts +21 -0
- package/dist/sessions/admission.js +176 -0
- package/dist/sessions/admission.js.map +1 -0
- package/dist/sessions/anchor.d.ts +4 -1
- package/dist/sessions/anchor.js +9 -5
- package/dist/sessions/anchor.js.map +1 -1
- package/dist/sessions/background-tasks.d.ts +41 -3
- package/dist/sessions/background-tasks.js +110 -10
- package/dist/sessions/background-tasks.js.map +1 -1
- package/dist/sessions/cli-sessions.d.ts +9 -2
- package/dist/sessions/cli-sessions.js +38 -57
- package/dist/sessions/cli-sessions.js.map +1 -1
- package/dist/sessions/completions.d.ts +8 -0
- package/dist/sessions/completions.js +55 -25
- package/dist/sessions/completions.js.map +1 -1
- package/dist/sessions/events.d.ts +3 -0
- package/dist/sessions/events.js +4 -0
- package/dist/sessions/events.js.map +1 -1
- package/dist/sessions/export.d.ts +2 -0
- package/dist/sessions/export.js +6 -2
- package/dist/sessions/export.js.map +1 -1
- package/dist/sessions/gateway-sessions.d.ts +92 -4
- package/dist/sessions/gateway-sessions.js +762 -93
- package/dist/sessions/gateway-sessions.js.map +1 -1
- package/dist/sessions/gateway-watcher.d.ts +10 -11
- package/dist/sessions/gateway-watcher.js +25 -21
- package/dist/sessions/gateway-watcher.js.map +1 -1
- package/dist/sessions/list.d.ts +9 -2
- package/dist/sessions/list.js +38 -26
- package/dist/sessions/list.js.map +1 -1
- package/dist/sessions/merge.d.ts +12 -5
- package/dist/sessions/merge.js +65 -18
- package/dist/sessions/merge.js.map +1 -1
- package/dist/sessions/prefix-index.d.ts +15 -4
- package/dist/sessions/prefix-index.js +35 -13
- package/dist/sessions/prefix-index.js.map +1 -1
- package/dist/sessions/prompt-queues.d.ts +36 -0
- package/dist/sessions/prompt-queues.js +318 -0
- package/dist/sessions/prompt-queues.js.map +1 -0
- package/dist/sessions/recovery.d.ts +1 -1
- package/dist/sessions/recovery.js +4 -3
- package/dist/sessions/recovery.js.map +1 -1
- package/dist/sessions/relay.d.ts +12 -1
- package/dist/sessions/relay.js +75 -17
- package/dist/sessions/relay.js.map +1 -1
- package/dist/sessions/service.d.ts +132 -37
- package/dist/sessions/service.js +688 -160
- package/dist/sessions/service.js.map +1 -1
- package/dist/sessions/session.d.ts +2 -0
- package/dist/sessions/session.js +5 -0
- package/dist/sessions/session.js.map +1 -1
- package/dist/sessions/state-db-worker.js +22 -5
- package/dist/sessions/state-db-worker.js.map +1 -1
- package/dist/sessions/state-db.d.ts +106 -15
- package/dist/sessions/state-db.js +651 -236
- package/dist/sessions/state-db.js.map +1 -1
- package/dist/sessions/state-saved.d.ts +1 -1
- package/dist/sessions/state-saved.js +35 -11
- package/dist/sessions/state-saved.js.map +1 -1
- package/dist/sessions/storage/backend.d.ts +10 -1
- package/dist/sessions/storage/backend.js.map +1 -1
- package/dist/sessions/storage/conformance.js +1 -1
- package/dist/sessions/storage/conformance.js.map +1 -1
- package/dist/sessions/storage/json-documents.d.ts +2 -0
- package/dist/sessions/storage/json-documents.js +71 -26
- package/dist/sessions/storage/json-documents.js.map +1 -1
- package/dist/sessions/storage/json-files.d.ts +13 -2
- package/dist/sessions/storage/json-files.js +126 -6
- package/dist/sessions/storage/json-files.js.map +1 -1
- package/dist/sessions/storage/json-journal.d.ts +6 -7
- package/dist/sessions/storage/json-journal.js +143 -73
- package/dist/sessions/storage/json-journal.js.map +1 -1
- package/dist/sessions/storage/json.d.ts +15 -1
- package/dist/sessions/storage/json.js +125 -33
- package/dist/sessions/storage/json.js.map +1 -1
- package/dist/sessions/store.d.ts +6 -1
- package/dist/sessions/store.js +68 -27
- package/dist/sessions/store.js.map +1 -1
- package/dist/sessions/streams.d.ts +10 -7
- package/dist/sessions/streams.js +49 -14
- package/dist/sessions/streams.js.map +1 -1
- package/dist/sessions/tool-display.d.ts +11 -2
- package/dist/sessions/tool-display.js +45 -4
- package/dist/sessions/tool-display.js.map +1 -1
- package/dist/sessions/turn-context.js +6 -2
- package/dist/sessions/turn-context.js.map +1 -1
- package/dist/sessions/turn.d.ts +27 -6
- package/dist/sessions/turn.js +186 -89
- package/dist/sessions/turn.js.map +1 -1
- package/dist/sidecar/client.d.ts +24 -1
- package/dist/sidecar/client.js +118 -38
- package/dist/sidecar/client.js.map +1 -1
- package/dist/sidecar/fake.d.ts +6 -2
- package/dist/sidecar/fake.js +15 -2
- package/dist/sidecar/fake.js.map +1 -1
- package/dist/spa.d.ts +9 -4
- package/dist/spa.js +36 -12
- package/dist/spa.js.map +1 -1
- package/dist/startup-timing.d.ts +66 -0
- package/dist/startup-timing.js +129 -0
- package/dist/startup-timing.js.map +1 -0
- package/dist/test/fs-handles.d.ts +11 -0
- package/dist/test/fs-handles.js +31 -0
- package/dist/test/fs-handles.js.map +1 -0
- package/dist/tools/connectors.d.ts +1 -1
- package/dist/tools/connectors.js +2 -2
- package/dist/tools/connectors.js.map +1 -1
- package/dist/tools/crons.d.ts +8 -4
- package/dist/tools/crons.js +25 -18
- package/dist/tools/crons.js.map +1 -1
- package/dist/tools/dashboard-plugins.d.ts +29 -0
- package/dist/tools/dashboard-plugins.js +132 -0
- package/dist/tools/dashboard-plugins.js.map +1 -1
- package/dist/tools/gateway-restart.d.ts +25 -5
- package/dist/tools/gateway-restart.js +103 -23
- package/dist/tools/gateway-restart.js.map +1 -1
- package/dist/tools/health.d.ts +13 -1
- package/dist/tools/health.js +80 -22
- package/dist/tools/health.js.map +1 -1
- package/dist/tools/insights.d.ts +1 -1
- package/dist/tools/insights.js +2 -2
- package/dist/tools/insights.js.map +1 -1
- package/dist/tools/kanban.d.ts +10 -1
- package/dist/tools/kanban.js +73 -1
- package/dist/tools/kanban.js.map +1 -1
- package/dist/tools/mcp-health.js +74 -24
- package/dist/tools/mcp-health.js.map +1 -1
- package/dist/tools/mcp.d.ts +3 -1
- package/dist/tools/mcp.js +92 -1
- package/dist/tools/mcp.js.map +1 -1
- package/dist/tools/memory.d.ts +28 -0
- package/dist/tools/memory.js +120 -14
- package/dist/tools/memory.js.map +1 -1
- package/dist/tools/plugin-oauth.d.ts +14 -0
- package/dist/tools/plugin-oauth.js +53 -0
- package/dist/tools/plugin-oauth.js.map +1 -0
- package/dist/tools/prune-advice.d.ts +50 -0
- package/dist/tools/prune-advice.js +114 -0
- package/dist/tools/prune-advice.js.map +1 -0
- package/dist/tools/skills.d.ts +5 -2
- package/dist/tools/skills.js +9 -6
- package/dist/tools/skills.js.map +1 -1
- package/dist/tools/update-notifications.d.ts +77 -9
- package/dist/tools/update-notifications.js +390 -46
- package/dist/tools/update-notifications.js.map +1 -1
- package/dist/tools/updates.d.ts +29 -3
- package/dist/tools/updates.js +166 -34
- package/dist/tools/updates.js.map +1 -1
- package/dist/workspace/managed-buffers.d.ts +58 -0
- package/dist/workspace/managed-buffers.js +76 -0
- package/dist/workspace/managed-buffers.js.map +1 -0
- package/dist/workspace/media.js +69 -20
- package/dist/workspace/media.js.map +1 -1
- package/dist/workspace/preview.js +4 -14
- package/dist/workspace/preview.js.map +1 -1
- package/dist/workspace/rollback.d.ts +6 -2
- package/dist/workspace/rollback.js +18 -8
- package/dist/workspace/rollback.js.map +1 -1
- package/package.json +3 -3
- package/sidecar/agent_dependency.json +4 -4
- package/sidecar/agent_support.json +30 -15
- package/sidecar/scripts/suite_runner.py +183 -27
- package/sidecar/scripts/test.sh +5 -7
- package/sidecar/talaria_sidecar/__init__.py +1 -1
- package/sidecar/talaria_sidecar/__main__.py +10 -3
- package/sidecar/talaria_sidecar/agent_mutation.py +246 -32
- package/sidecar/talaria_sidecar/agent_services.py +157 -34
- package/sidecar/talaria_sidecar/context_detail.py +59 -0
- package/sidecar/talaria_sidecar/home.py +97 -20
- package/sidecar/talaria_sidecar/methods/__init__.py +2 -2
- package/sidecar/talaria_sidecar/methods/aux.py +80 -18
- package/sidecar/talaria_sidecar/methods/chat.py +571 -106
- package/sidecar/talaria_sidecar/methods/checkpoints.py +29 -4
- package/sidecar/talaria_sidecar/methods/commands.py +277 -16
- package/sidecar/talaria_sidecar/methods/config.py +73 -3
- package/sidecar/talaria_sidecar/methods/connectors.py +45 -13
- package/sidecar/talaria_sidecar/methods/cron.py +8 -2
- package/sidecar/talaria_sidecar/methods/dashboard_plugins.py +301 -0
- package/sidecar/talaria_sidecar/methods/gateway.py +24 -4
- package/sidecar/talaria_sidecar/methods/gateway_sessions.py +304 -30
- package/sidecar/talaria_sidecar/methods/kanban.py +50 -3
- package/sidecar/talaria_sidecar/methods/managed_buffers.py +110 -0
- package/sidecar/talaria_sidecar/methods/mcp.py +55 -0
- package/sidecar/talaria_sidecar/methods/oauth.py +139 -11
- package/sidecar/talaria_sidecar/methods/outbound_drafts.py +165 -0
- package/sidecar/talaria_sidecar/methods/plugin_catalog.py +198 -0
- package/sidecar/talaria_sidecar/methods/plugin_oauth.py +234 -0
- package/sidecar/talaria_sidecar/methods/process.py +70 -6
- package/sidecar/talaria_sidecar/methods/profiles.py +4 -3
- package/sidecar/talaria_sidecar/methods/runtime.py +2 -0
- package/sidecar/talaria_sidecar/methods/skills.py +22 -7
- package/sidecar/talaria_sidecar/methods/state_db.py +128 -42
- package/sidecar/talaria_sidecar/methods/toolsets.py +4 -2
- package/sidecar/talaria_sidecar/methods/worktree.py +121 -2
- package/sidecar/talaria_sidecar/rpc.py +25 -3
- package/sidecar/talaria_sidecar/runtime.py +42 -3
- package/sidecar/talaria_sidecar/speed.py +13 -1
- package/sidecar/talaria_sidecar/startup_timing.py +119 -0
- package/static/dist/FILES.txt +240 -213
- package/static/dist/THIRD_PARTY_LICENSES.md +6 -22
- package/static/dist/assets/AppShell-c5989995.js +8 -0
- package/static/dist/assets/Button-nuaikybd.js +1 -0
- package/static/dist/assets/ChatPage-bfg4khph.js +6 -0
- package/static/dist/assets/ConnectTargets-k5wo9yo8.js +1 -0
- package/static/dist/assets/Dialog-o8vo2aws.js +1 -0
- package/static/dist/assets/ExtensionRoute-l1yjrso4.js +1 -0
- package/static/dist/assets/Field-j7o8cfps.js +1 -0
- package/static/dist/assets/HubRoute-efnwe4xz.js +2 -0
- package/static/dist/assets/LinkCheckContext-ix6zqqkk.js +1 -0
- package/static/dist/assets/Markdown-clqf5m22.js +2 -0
- package/static/dist/assets/MarkdownRenderer-ccgqrza3.js +302 -0
- package/static/dist/assets/MarkdownRenderer-i9o6nr38.css +1 -0
- package/static/dist/assets/OAuthSignIn-h7bjaqp6.js +1 -0
- package/static/dist/assets/ResourceSwitch-oai2zqaj.js +1 -0
- package/static/dist/assets/RightPanel-ho161a45.js +1 -0
- package/static/dist/assets/Select-d1g5a8bm.js +1 -0
- package/static/dist/assets/SessionListPanel-i7kaokhi.js +1 -0
- package/static/dist/assets/SettingsLayout-lnecm87w.js +1 -0
- package/static/dist/assets/States-easntmry.js +1 -0
- package/static/dist/assets/TerminalPanel-lxhwd4jl.js +16 -0
- package/static/dist/assets/Toaster-l4sciy8t.js +1 -0
- package/static/dist/assets/_app-mqexqbg8.js +1 -0
- package/static/dist/assets/_app.ext._extensionId-n797jp72.js +1 -0
- package/static/dist/assets/_app.index-ne43mdw2.js +1 -0
- package/static/dist/assets/_app.insights-fqonovb4.js +1 -0
- package/static/dist/assets/_app.kanban-kysliv19.js +1 -0
- package/static/dist/assets/_app.logs-febut82r.js +1 -0
- package/static/dist/assets/_app.memory-ha86oj1c.js +1 -0
- package/static/dist/assets/_app.profiles-cnu3gxxq.js +1 -0
- package/static/dist/assets/_app.session._sessionId-ifzjpcgn.js +1 -0
- package/static/dist/assets/_app.settings-nmakdiaf.js +1 -0
- package/static/dist/assets/_app.settings._section-djglnjmi.js +3 -0
- package/static/dist/assets/_app.skills-f3wad8yo.js +1 -0
- package/static/dist/assets/_app.tasks-l10py1c0.js +1 -0
- package/static/dist/assets/_app.todos-bml1m3r1.js +1 -0
- package/static/dist/assets/_app.workspaces-f3d066lx.js +1 -0
- package/static/dist/assets/abnfDiagram-VCTEODGH-i53jc4yp.js +1 -0
- package/static/dist/assets/{angular-html-nu6l31w3.js → angular-html-l28bd5fo.js} +1 -1
- package/static/dist/assets/{angular-ts-fbx4f8mm.js → angular-ts-ffzx1vj0.js} +1 -1
- package/static/dist/assets/{apl-bx2xr7dh.js → apl-b7h7mmy4.js} +1 -1
- package/static/dist/assets/{arc-7popfhbk.js → arc-fk1b21lm.js} +1 -1
- package/static/dist/assets/architecture-7GRP2DOG-e3bv5m6f.js +1 -0
- package/static/dist/assets/architectureDiagram-5GKGNRK7-pakekxu2.js +36 -0
- package/static/dist/assets/archive-ihqi7z2x.js +1 -0
- package/static/dist/assets/{astro-g77i97cb.js → astro-k117fy0t.js} +1 -1
- package/static/dist/assets/back-gu3nu279.js +1 -0
- package/static/dist/assets/{blade-boo0u92y.js → blade-npefsmn8.js} +1 -1
- package/static/dist/assets/{blockDiagram-I7D4REHJ-joedghi3.js → blockDiagram-I7D4REHJ-bc6bo1n6.js} +4 -4
- package/static/dist/assets/{c-cat0w3sc.js → c-2umg6kbn.js} +1 -1
- package/static/dist/assets/{c4Diagram-7LVT6UL2-hyrjrohe.js → c4Diagram-7LVT6UL2-btvwk2qx.js} +1 -1
- package/static/dist/assets/channel-jn4f8443.js +1 -0
- package/static/dist/assets/{chunk-4HAMMTFA-koouqbut.js → chunk-4HAMMTFA-dlwab11c.js} +20 -20
- package/static/dist/assets/{chunk-75Z2AOVW-bl4bhdnt.js → chunk-75Z2AOVW-dp5gh7i8.js} +1 -1
- package/static/dist/assets/chunk-DU6HZSFF-bi06zl1c.js +128 -0
- package/static/dist/assets/{chunk-F27PBJKO-d8xxi0zi.js → chunk-F27PBJKO-kvv1rnlh.js} +1 -1
- package/static/dist/assets/{chunk-FOHPRMQF-opuflp73.js → chunk-FOHPRMQF-ipewusgj.js} +8 -8
- package/static/dist/assets/{chunk-GMAD6QVW-jro0hl73.js → chunk-GMAD6QVW-ji0rx9by.js} +6 -6
- package/static/dist/assets/{chunk-GVQU2GXP-djn6gbyu.js → chunk-GVQU2GXP-nmz0j82p.js} +1 -1
- package/static/dist/assets/{chunk-IMKFNOWR-vw4p5p7o.js → chunk-IMKFNOWR-kmi1qx88.js} +5 -5
- package/static/dist/assets/{chunk-L3NEJ4N5-n1hj77q8.js → chunk-L3NEJ4N5-xhb7mebj.js} +1 -1
- package/static/dist/assets/chunk-OSK3NFVY-5a9sgscq.js +10 -0
- package/static/dist/assets/{chunk-P2QGCYS3-onf1hz6c.js → chunk-P2QGCYS3-dfezp4vu.js} +1 -1
- package/static/dist/assets/{chunk-POPQ4Y6H-m8sqn7cs.js → chunk-POPQ4Y6H-gd2vq3c0.js} +1 -1
- package/static/dist/assets/{chunk-PWAF6VOD-ek4smc8x.js → chunk-PWAF6VOD-wvw2nksf.js} +1 -1
- package/static/dist/assets/{chunk-SHT3W25Y-g9gfvefo.js → chunk-SHT3W25Y-f58q97px.js} +13 -13
- package/static/dist/assets/{chunk-SVP7TREG-f9nfv2cu.js → chunk-SVP7TREG-abgwpyz9.js} +4 -4
- package/static/dist/assets/{chunk-TICWLB2K-bnk3m1mq.js → chunk-TICWLB2K-h4sbs8ds.js} +6 -6
- package/static/dist/assets/{chunk-XXDRQBXY-n40pf9vy.js → chunk-XXDRQBXY-jkmnqu65.js} +1 -1
- package/static/dist/assets/classDiagram-ZZMXUADV-dzrw66se.js +1 -0
- package/static/dist/assets/classDiagram-v2-VYDZK3BY-dzrw66se.js +1 -0
- package/static/dist/assets/{cobol-go622aep.js → cobol-ssf9hkh7.js} +1 -1
- package/static/dist/assets/{coffee-jwo1xjhq.js → coffee-lsi9fwae.js} +1 -1
- package/static/dist/assets/completionAudio-ce86msbu.js +1 -0
- package/static/dist/assets/copied-bz3gkazh.js +1 -0
- package/static/dist/assets/copy-m9h56qa8.js +1 -0
- package/static/dist/assets/cose-bilkent-JH36ORCC-layy2r27.js +1 -0
- package/static/dist/assets/{cpp-nre7j0kq.js → cpp-lfrh4y55.js} +1 -1
- package/static/dist/assets/{crystal-lviso2je.js → crystal-efh4pte7.js} +1 -1
- package/static/dist/assets/{css-ywz9j4hb.js → css-i82qdo89.js} +1 -1
- package/static/dist/assets/cynefin-OW5HDTMX-g081vffs.js +1 -0
- package/static/dist/assets/cynefinDiagram-5FMLGOSQ-odxvjesk.js +62 -0
- package/static/dist/assets/cytoscape.esm-fjn2algp.js +321 -0
- package/static/dist/assets/dagre-GXQ25YYZ-cpdwzjs4.js +4 -0
- package/static/dist/assets/dagre-o5jmjz46.js +1 -0
- package/static/dist/assets/{diagram-S7CK7UJ4-m6aeoe7c.js → diagram-S7CK7UJ4-clv5mxvu.js} +4 -4
- package/static/dist/assets/diagram-UQ7AKVKN-m2ia1mbf.js +41 -0
- package/static/dist/assets/{diagram-VSXAHHWV-hbawi7hn.js → diagram-VSXAHHWV-ea6zv636.js} +1 -1
- package/static/dist/assets/diagram-VX7I27RA-oqlef685.js +24 -0
- package/static/dist/assets/diagram-Z3DM3KII-kjubcbwu.js +24 -0
- package/static/dist/assets/dist-carq1azj.js +44 -0
- package/static/dist/assets/dist-crc46di9.js +7 -0
- package/static/dist/assets/{dist-c4c2m3kv.js → dist-nb670eu6.js} +1 -1
- package/static/dist/assets/ebnfDiagram-PWID7BFC-fg0zri3e.js +1 -0
- package/static/dist/assets/{edge-dvv35byi.js → edge-lrob635n.js} +1 -1
- package/static/dist/assets/{elixir-i2f1ki1g.js → elixir-kdpxeq93.js} +1 -1
- package/static/dist/assets/{elm-cpepyjm4.js → elm-c8irj9uh.js} +1 -1
- package/static/dist/assets/erDiagram-RLTQ6QDP-eb7pmk3x.js +99 -0
- package/static/dist/assets/{erb-idlyfheg.js → erb-flwsv146.js} +1 -1
- package/static/dist/assets/eventmodeling-NTZA5JFV-gvi1fxhn.js +1 -0
- package/static/dist/assets/flowDiagram-HODETNUW-abekab15.js +1 -0
- package/static/dist/assets/folder-plus-ksaons88.js +1 -0
- package/static/dist/assets/{ganttDiagram-EL5Y4UJY-ma6jxj5i.js → ganttDiagram-EL5Y4UJY-jmisowrc.js} +1 -1
- package/static/dist/assets/{git-rebase-d9lpfpbn.js → git-rebase-bli19aoq.js} +1 -1
- package/static/dist/assets/gitGraph-4MIJSDKK-m7kt3u6e.js +1 -0
- package/static/dist/assets/{gitGraphDiagram-WWUBYQGX-hzltvsod.js → gitGraphDiagram-WWUBYQGX-nq7vfzh2.js} +1 -1
- package/static/dist/assets/{glimmer-js-39i0urfb.js → glimmer-js-d4icg38p.js} +1 -1
- package/static/dist/assets/{glimmer-ts-gdtd6n73.js → glimmer-ts-bk75772u.js} +1 -1
- package/static/dist/assets/{glsl-o1djm5pp.js → glsl-lqormp2b.js} +1 -1
- package/static/dist/assets/{graphql-kj6rz55t.js → graphql-hw6s5qzd.js} +1 -1
- package/static/dist/assets/{hack-pe1qqr2i.js → hack-ozrv6l4d.js} +1 -1
- package/static/dist/assets/{haml-cknnbcqs.js → haml-gytfosdt.js} +1 -1
- package/static/dist/assets/{handlebars-hwq64orh.js → handlebars-b6g7jffd.js} +1 -1
- package/static/dist/assets/highlighted-body-KPVGNVTW-gcu017ay.js +1 -0
- package/static/dist/assets/host-ipp4e84c.js +1 -0
- package/static/dist/assets/{html-derivative-h2i2pyjc.js → html-derivative-f1tqcroo.js} +1 -1
- package/static/dist/assets/{html-ha05xtvt.js → html-on6oj6yj.js} +1 -1
- package/static/dist/assets/{http-cf94zu27.js → http-odhufsl7.js} +1 -1
- package/static/dist/assets/{hurl-lslax568.js → hurl-mu680336.js} +1 -1
- package/static/dist/assets/index-d6vbxlra.js +13 -0
- package/static/dist/assets/index-ey6qo0zx.css +2 -0
- package/static/dist/assets/info-A6RAGUB7-idazwfqe.js +1 -0
- package/static/dist/assets/infoDiagram-27XIBGKW-bb9jh8gl.js +2 -0
- package/static/dist/assets/{ishikawaDiagram-5VMMS53U-e7bnwq7h.js → ishikawaDiagram-5VMMS53U-nqc132rv.js} +6 -6
- package/static/dist/assets/{java-ndjf2o89.js → java-nxbe8uju.js} +1 -1
- package/static/dist/assets/{javascript-coftlwy3.js → javascript-lz3kxcyz.js} +1 -1
- package/static/dist/assets/{jinja-etei9wy7.js → jinja-l5pk84gt.js} +1 -1
- package/static/dist/assets/{jison-hyekgft1.js → jison-jdutdwyy.js} +1 -1
- package/static/dist/assets/{journeyDiagram-3NMN7TZE-etd1bi6p.js → journeyDiagram-3NMN7TZE-fpvnhy44.js} +1 -1
- package/static/dist/assets/{json-lok0yaho.js → json-dnge4ssf.js} +1 -1
- package/static/dist/assets/{jsx-b64w0nbx.js → jsx-c3lwhkep.js} +1 -1
- package/static/dist/assets/{jsx-runtime-eu92a5pu.js → jsx-runtime-o40ukmjl.js} +1 -1
- package/static/dist/assets/{julia-jxxzz2yn.js → julia-hwd4rrcb.js} +1 -1
- package/static/dist/assets/{just-mc29iw9t.js → just-nka3oxdx.js} +1 -1
- package/static/dist/assets/{kanban-definition-UXKFOSKX-emb1g9dz.js → kanban-definition-UXKFOSKX-ndzqm6fu.js} +28 -28
- package/static/dist/assets/katex-cbdd1ohw.css +1 -0
- package/static/dist/assets/katex-pbij2oo6.js +257 -0
- package/static/dist/assets/{latex-pafa03ft.js → latex-iqmr7e40.js} +1 -1
- package/static/dist/assets/lazyRouteComponent-javud235.js +1 -0
- package/static/dist/assets/{line-h0ojzsvs.js → line-g625e7cj.js} +1 -1
- package/static/dist/assets/linear-jlwrvvy6.js +1 -0
- package/static/dist/assets/link-gfdaho08.js +2 -0
- package/static/dist/assets/{liquid-hz5c2pov.js → liquid-okmk9tbp.js} +1 -1
- package/static/dist/assets/locale-cs-n41hptse.js +5 -0
- package/static/dist/assets/locale-de-k7ht47ew.js +5 -0
- package/static/dist/assets/locale-es-ih078lco.js +5 -0
- package/static/dist/assets/locale-fr-ojabnf41.js +5 -0
- package/static/dist/assets/locale-it-kb96jufy.js +5 -0
- package/static/dist/assets/locale-ja-jpsp3xs1.js +7 -0
- package/static/dist/assets/locale-ko-cpzuy0n7.js +5 -0
- package/static/dist/assets/locale-pl-dbap4leu.js +5 -0
- package/static/dist/assets/locale-pt-nci7w72x.js +5 -0
- package/static/dist/assets/locale-ru-soghe4cs.js +7 -0
- package/static/dist/assets/locale-tr-ks00mu68.js +5 -0
- package/static/dist/assets/locale-vi-ij7twfm6.js +5 -0
- package/static/dist/assets/locale-zh-Hant-feakwr7a.js +5 -0
- package/static/dist/assets/locale-zh-ren0vjyv.js +7 -0
- package/static/dist/assets/login-iv6yq4xf.js +1 -0
- package/static/dist/assets/{lua-leyf8mlb.js → lua-krx4xj5h.js} +1 -1
- package/static/dist/assets/{marko-cn1fzpdv.js → marko-gbvpfehz.js} +1 -1
- package/static/dist/assets/{mdc-huhy88df.js → mdc-c21zlyi5.js} +1 -1
- package/static/dist/assets/mermaid-HWGCJPDP-cwj5cl6k.js +1 -0
- package/static/dist/assets/mermaid-parser.core-plzkuzov.js +7 -0
- package/static/dist/assets/micromark-factory-space-fnmnpi6s.js +1 -0
- package/static/dist/assets/{mindmap-definition-YA3MSWOX-o1vathns.js → mindmap-definition-YA3MSWOX-ojrgs569.js} +28 -28
- package/static/dist/assets/{nginx-e7lvhsmn.js → nginx-f3d68ed4.js} +1 -1
- package/static/dist/assets/{nim-dun5d8mk.js → nim-dw0jcy70.js} +1 -1
- package/static/dist/assets/onboarding-ff4emacu.js +1 -0
- package/static/dist/assets/packet-AYTQ26CC-gyaf9s8h.js +1 -0
- package/static/dist/assets/pegDiagram-XKGWAZYB-bf6xj8mq.js +1 -0
- package/static/dist/assets/{perl-bj3oqtet.js → perl-3c0r45c8.js} +1 -1
- package/static/dist/assets/{php-buzp12r0.js → php-rznhidvp.js} +1 -1
- package/static/dist/assets/pie-WAS4IAKB-f5ymzelo.js +1 -0
- package/static/dist/assets/pieDiagram-E7YTZNPT-d0qjl3zi.js +39 -0
- package/static/dist/assets/{pug-mjad7he9.js → pug-f2le4f3y.js} +1 -1
- package/static/dist/assets/{qml-d1gdp10s.js → qml-e2wbq9cr.js} +1 -1
- package/static/dist/assets/{quadrantDiagram-AXDQQJYC-owqc4uqn.js → quadrantDiagram-AXDQQJYC-oqy1mras.js} +1 -1
- package/static/dist/assets/queryKeys-x8fjxhut.js +9 -0
- package/static/dist/assets/{r-o3r9c7ao.js → r-epfzuw6q.js} +1 -1
- package/static/dist/assets/radar-RG4KPBEZ-b6jcjvda.js +1 -0
- package/static/dist/assets/railroad-74A4TZTK-e3a6lk5k.js +1 -0
- package/static/dist/assets/railroad-abnf-HS5TGJTU-ff5hocrx.js +1 -0
- package/static/dist/assets/railroad-ebnf-LZEXJU2U-exkhyw4n.js +1 -0
- package/static/dist/assets/railroad-peg-WCYAUIDC-jefk9b7c.js +1 -0
- package/static/dist/assets/railroadDiagram-O6MQD6OU-e4amks1i.js +1 -0
- package/static/dist/assets/{razor-ilc585yr.js → razor-pea1u1d0.js} +1 -1
- package/static/dist/assets/refresh-cw-lfp4u1oh.js +1 -0
- package/static/dist/assets/{regexp-mpjtcvwm.js → regexp-hzte0a5x.js} +1 -1
- package/static/dist/assets/registry-g7w3353u.js +1 -0
- package/static/dist/assets/requirementDiagram-BXWQKSXE-c77k1e2y.js +84 -0
- package/static/dist/assets/rolldown-runtime-bnnw9q4a.js +1 -0
- package/static/dist/assets/{rst-jrkwjdyi.js → rst-m6tugj5o.js} +1 -1
- package/static/dist/assets/{ruby-n4tjcbpz.js → ruby-l19vq3w1.js} +1 -1
- package/static/dist/assets/runtime-nlxpnegr.js +1 -0
- package/static/dist/assets/{sankeyDiagram-P5KCCOFB-iqc02emv.js → sankeyDiagram-P5KCCOFB-oa1cc52s.js} +1 -1
- package/static/dist/assets/{sas-hjo6y93k.js → sas-ktdxo397.js} +1 -1
- package/static/dist/assets/{scss-ncidjv48.js → scss-kn3oxfwf.js} +1 -1
- package/static/dist/assets/{sequenceDiagram-WJ2MYXX4-i0v116q0.js → sequenceDiagram-WJ2MYXX4-j20gqt22.js} +11 -11
- package/static/dist/assets/settings_section_extensions_title-fadc7o65.js +1 -0
- package/static/dist/assets/share._token-kmfoflw6.js +2 -0
- package/static/dist/assets/{shellscript-m8whjpqd.js → shellscript-l100jtrg.js} +1 -1
- package/static/dist/assets/{shellsession-i5bj6syz.js → shellsession-m5qukwow.js} +1 -1
- package/static/dist/assets/sizeCapture-INFHLROL-dk1io13w.js +1 -0
- package/static/dist/assets/sliders-horizontal-g5jkzd9k.js +1 -0
- package/static/dist/assets/{soy-hhh36ysq.js → soy-mexlscur.js} +1 -1
- package/static/dist/assets/{sql-j21bzcl6.js → sql-o0ho5suh.js} +1 -1
- package/static/dist/assets/src-h89s0hs4.js +1 -0
- package/static/dist/assets/{stata-bbu2onh1.js → stata-be9ck1q3.js} +1 -1
- package/static/dist/assets/stateDiagram-D77RDMKH-co2ghkdp.js +1 -0
- package/static/dist/assets/stateDiagram-v2-MP3YSRHH-faw1opgh.js +1 -0
- package/static/dist/assets/{surrealql-l5vczuco.js → surrealql-gk1xkkyy.js} +1 -1
- package/static/dist/assets/{svelte-idn422g6.js → svelte-k6ecjilf.js} +1 -1
- package/static/dist/assets/swimlanes-42K2YHIH-m30cktqe.js +1 -0
- package/static/dist/assets/swimlanesDiagram-VR7AAH4N-hfil433g.js +8 -0
- package/static/dist/assets/{templ-e22qou3c.js → templ-gf3bftk6.js} +1 -1
- package/static/dist/assets/{tex-deqpc5ee.js → tex-d21fqv1z.js} +1 -1
- package/static/dist/assets/{timeline-definition-24CTP7MA-ol2hnvma.js → timeline-definition-24CTP7MA-liuep6fl.js} +8 -8
- package/static/dist/assets/toast-zmb35u3r.js +56 -0
- package/static/dist/assets/treeView-Q6P3EWNA-np5d2jv2.js +1 -0
- package/static/dist/assets/treemap-WGGIJYW6-cmpltxh1.js +1 -0
- package/static/dist/assets/{ts-tags-ctnibc27.js → ts-tags-n0g61gr6.js} +1 -1
- package/static/dist/assets/{tsx-i163n32g.js → tsx-cvv7wv6q.js} +1 -1
- package/static/dist/assets/{twig-x0fi7wm8.js → twig-n1f67204.js} +1 -1
- package/static/dist/assets/{typescript-g18c34xz.js → typescript-og7o55cx.js} +1 -1
- package/static/dist/assets/untitled-mj86r4gz.js +1 -0
- package/static/dist/assets/useDebounced-g8r0ggve.js +1 -0
- package/static/dist/assets/useForm-f1udzsjf.js +1 -0
- package/static/dist/assets/{useParams-gjc70qru.js → useParams-ierevvts.js} +1 -1
- package/static/dist/assets/{useSearch-e6ae539u.js → useSearch-i7nr9ypl.js} +1 -1
- package/static/dist/assets/vennDiagram-4TSXK5OY-b2g42qrg.js +34 -0
- package/static/dist/assets/{vue-mwu5l1bb.js → vue-ej4xpwqw.js} +1 -1
- package/static/dist/assets/{vue-html-nskj3du0.js → vue-html-d48xsjuo.js} +1 -1
- package/static/dist/assets/{vue-vine-cqe77smq.js → vue-vine-pev88ip6.js} +1 -1
- package/static/dist/assets/wardley-WFR3VGLG-lb0eqbff.js +1 -0
- package/static/dist/assets/wardleyDiagram-VM6X3IG4-ermwaqha.js +78 -0
- package/static/dist/assets/with-selector-nu1b5z0v.js +1 -0
- package/static/dist/assets/{xml-gau7gvrv.js → xml-ifxp6gqb.js} +1 -1
- package/static/dist/assets/{xsl-ew09zq8b.js → xsl-fug2cckc.js} +1 -1
- package/static/dist/assets/{xychartDiagram-S5SC5T6Z-aqbgvujg.js → xychartDiagram-S5SC5T6Z-dll0jldk.js} +6 -6
- package/static/dist/assets/{yaml-ofnrxtvf.js → yaml-fjmafnlo.js} +1 -1
- package/static/dist/extension-sdk.js +1 -1
- package/static/dist/index.html +1 -1
- package/static/dist/sw.js +180 -136
- package/static/dist/assets/AppShell-cey33v9s.js +0 -8
- package/static/dist/assets/ChatPage-i8wnugr7.js +0 -18
- package/static/dist/assets/ConnectTargets-hg19553x.js +0 -1
- package/static/dist/assets/ExtensionRoute-cly4apm5.js +0 -1
- package/static/dist/assets/Field-j8uqoigz.js +0 -9
- package/static/dist/assets/HubRoute-e4bgz41j.js +0 -2
- package/static/dist/assets/Markdown-lahuichm.js +0 -598
- package/static/dist/assets/Markdown-lwviulmg.css +0 -1
- package/static/dist/assets/RightPanel-lbo4i0fn.js +0 -1
- package/static/dist/assets/Select-gqatm2e0.js +0 -1
- package/static/dist/assets/SessionListPanel-mfqayfjh.js +0 -1
- package/static/dist/assets/SettingsLayout-b8980u7k.js +0 -1
- package/static/dist/assets/States-e7dkgtxf.js +0 -1
- package/static/dist/assets/Toaster-bfqqy786.js +0 -1
- package/static/dist/assets/_app-n1n6pfx1.js +0 -1
- package/static/dist/assets/_app.ext._extensionId-buxjxav3.js +0 -1
- package/static/dist/assets/_app.index-jt8zwiu2.js +0 -1
- package/static/dist/assets/_app.insights-cv76ml71.js +0 -1
- package/static/dist/assets/_app.kanban-h6ts53j7.js +0 -1
- package/static/dist/assets/_app.logs-dm873z90.js +0 -1
- package/static/dist/assets/_app.memory-glk5y6m8.js +0 -1
- package/static/dist/assets/_app.profiles-ka6zpstq.js +0 -1
- package/static/dist/assets/_app.session._sessionId-g2vzghvc.js +0 -1
- package/static/dist/assets/_app.settings-hgjdhzcd.js +0 -1
- package/static/dist/assets/_app.settings._section-jf2kmhae.js +0 -3
- package/static/dist/assets/_app.skills-cii852yq.js +0 -1
- package/static/dist/assets/_app.tasks-fp9q7atm.js +0 -1
- package/static/dist/assets/_app.todos-dw94qzue.js +0 -1
- package/static/dist/assets/_app.workspaces-inyygzze.js +0 -1
- package/static/dist/assets/abnfDiagram-VCTEODGH-gjayq3ra.js +0 -1
- package/static/dist/assets/architecture-7GRP2DOG-lp56972r.js +0 -1
- package/static/dist/assets/architectureDiagram-5GKGNRK7-nwb3xovn.js +0 -36
- package/static/dist/assets/archive-b1j004vn.js +0 -1
- package/static/dist/assets/back-g74gkozu.js +0 -1
- package/static/dist/assets/channel-es95o4y8.js +0 -1
- package/static/dist/assets/chunk-DU6HZSFF-gpedttsp.js +0 -128
- package/static/dist/assets/chunk-OSK3NFVY-oy0gwn2n.js +0 -10
- package/static/dist/assets/classDiagram-ZZMXUADV-kmihoqxh.js +0 -1
- package/static/dist/assets/classDiagram-v2-VYDZK3BY-kmihoqxh.js +0 -1
- package/static/dist/assets/copied-bli9tbcx.js +0 -1
- package/static/dist/assets/copy-jamtd1pf.js +0 -1
- package/static/dist/assets/cose-bilkent-JH36ORCC-eclcy6ja.js +0 -1
- package/static/dist/assets/cynefin-OW5HDTMX-f8xfdd3f.js +0 -1
- package/static/dist/assets/cynefinDiagram-5FMLGOSQ-n9lb99h9.js +0 -62
- package/static/dist/assets/cytoscape.esm-bqu53u12.js +0 -321
- package/static/dist/assets/dagre-GXQ25YYZ-dgailddi.js +0 -4
- package/static/dist/assets/dagre-lkoknbjn.js +0 -1
- package/static/dist/assets/diagram-UQ7AKVKN-jall3j0x.js +0 -41
- package/static/dist/assets/diagram-VX7I27RA-hendl2tt.js +0 -24
- package/static/dist/assets/diagram-Z3DM3KII-igwc35p3.js +0 -24
- package/static/dist/assets/ebnfDiagram-PWID7BFC-c64knz08.js +0 -1
- package/static/dist/assets/erDiagram-RLTQ6QDP-brdu9lcm.js +0 -99
- package/static/dist/assets/eventmodeling-NTZA5JFV-njk1j8wl.js +0 -1
- package/static/dist/assets/flowDiagram-HODETNUW-nma6f0ga.js +0 -1
- package/static/dist/assets/folder-plus-lvt9kudb.js +0 -1
- package/static/dist/assets/gitGraph-4MIJSDKK-naa9w6xa.js +0 -1
- package/static/dist/assets/highlighted-body-KPVGNVTW-ghoavj8d.js +0 -1
- package/static/dist/assets/host-hzm8n85n.js +0 -1
- package/static/dist/assets/index-drdcaqeq.css +0 -2
- package/static/dist/assets/index-jzm844he.js +0 -11
- package/static/dist/assets/info-A6RAGUB7-mn2ut5ko.js +0 -1
- package/static/dist/assets/infoDiagram-27XIBGKW-h6kuqvsb.js +0 -2
- package/static/dist/assets/lazyRouteComponent-o816ytzl.js +0 -1
- package/static/dist/assets/linear-becwlnhk.js +0 -1
- package/static/dist/assets/link-k01ryaf9.js +0 -1
- package/static/dist/assets/login-bsae49ew.js +0 -1
- package/static/dist/assets/mermaid-HWGCJPDP-ihl34s74.js +0 -1
- package/static/dist/assets/mermaid-parser.core-bnre27u8.js +0 -7
- package/static/dist/assets/not-found-ccnnac39.js +0 -1
- package/static/dist/assets/onboarding-c65tysya.js +0 -1
- package/static/dist/assets/onboarding_model_label-gpn28uix.js +0 -1
- package/static/dist/assets/packet-AYTQ26CC-hatq7m2e.js +0 -1
- package/static/dist/assets/pegDiagram-XKGWAZYB-gwisz8jv.js +0 -1
- package/static/dist/assets/pie-WAS4IAKB-fpftf0mk.js +0 -1
- package/static/dist/assets/pieDiagram-E7YTZNPT-khm1o9a6.js +0 -39
- package/static/dist/assets/radar-RG4KPBEZ-cntfwjpq.js +0 -1
- package/static/dist/assets/railroad-74A4TZTK-a7t5eibp.js +0 -1
- package/static/dist/assets/railroad-abnf-HS5TGJTU-ol8cdktf.js +0 -1
- package/static/dist/assets/railroad-ebnf-LZEXJU2U-i8vzd429.js +0 -1
- package/static/dist/assets/railroad-peg-WCYAUIDC-nw3ulewz.js +0 -1
- package/static/dist/assets/railroadDiagram-O6MQD6OU-etuh0qa0.js +0 -1
- package/static/dist/assets/refresh-cw-mqbkv2a3.js +0 -1
- package/static/dist/assets/refresh-l29ljp76.js +0 -1
- package/static/dist/assets/requirementDiagram-BXWQKSXE-oq2ulk22.js +0 -84
- package/static/dist/assets/rolldown-runtime-b9miacsj.js +0 -1
- package/static/dist/assets/root-mbklpuv4.js +0 -1
- package/static/dist/assets/saved-ndd4t2xb.js +0 -1
- package/static/dist/assets/settings_section_extensions_title-jhfo6o8z.js +0 -1
- package/static/dist/assets/share._token-c1ri0hy1.js +0 -2
- package/static/dist/assets/sizeCapture-INFHLROL-g612l48j.js +0 -1
- package/static/dist/assets/sliders-horizontal-j3jjt9tv.js +0 -1
- package/static/dist/assets/src-hjyib4mu.js +0 -1
- package/static/dist/assets/stateDiagram-D77RDMKH-dnpt1ato.js +0 -1
- package/static/dist/assets/stateDiagram-v2-MP3YSRHH-bxjacpk6.js +0 -1
- package/static/dist/assets/swimlanes-42K2YHIH-loqbdazb.js +0 -1
- package/static/dist/assets/swimlanesDiagram-VR7AAH4N-id62p9hz.js +0 -8
- package/static/dist/assets/toast-i3h34v6o.js +0 -64
- package/static/dist/assets/treeView-Q6P3EWNA-idrj6iox.js +0 -1
- package/static/dist/assets/treemap-WGGIJYW6-lzr49vv5.js +0 -1
- package/static/dist/assets/untitled-oaoya4qj.js +0 -1
- package/static/dist/assets/useForm-nfaxgmsk.js +0 -1
- package/static/dist/assets/vennDiagram-4TSXK5OY-bvwr9o2z.js +0 -34
- package/static/dist/assets/wardley-WFR3VGLG-31ui8tma.js +0 -1
- package/static/dist/assets/wardleyDiagram-VM6X3IG4-k5wqtx4b.js +0 -78
- /package/static/dist/assets/{ChatPage-gmu5c7lf.css → TerminalPanel-gmu5c7lf.css} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Authenticated observations
|
|
1
|
+
"""Authenticated observations, fenced controls and diagnostic creation through an existing native owner.
|
|
2
2
|
|
|
3
3
|
Never ensure/start a gateway, build an Agent, or write its transcript locally.
|
|
4
4
|
Each call owns its connection and subscription; cancellation only detaches it.
|
|
@@ -7,20 +7,47 @@ from __future__ import annotations
|
|
|
7
7
|
|
|
8
8
|
import asyncio
|
|
9
9
|
from contextlib import asynccontextmanager, closing, suppress
|
|
10
|
+
from importlib.util import find_spec
|
|
10
11
|
import json
|
|
11
12
|
from pathlib import Path
|
|
13
|
+
import re
|
|
12
14
|
import sqlite3
|
|
13
15
|
|
|
14
16
|
from ..errors import InvalidParams
|
|
15
17
|
from ..home import profile_home_param, scoped_home
|
|
16
18
|
|
|
17
|
-
_ACTIONS = {"snapshot", "watch", "submit", "receipt", "cancel", "
|
|
19
|
+
_ACTIONS = {"snapshot", "watch", "context_detail", "submit", "receipt", "cancel", "steer_queued", "replace_queued", "interrupt", "approval", "clarify",
|
|
20
|
+
"clarify_lock", "discard", "mutate", "export", "checkpoint_diff", "terminal_info", "shell_exec", "react"}
|
|
21
|
+
_OWNER_READ_MAX_BYTES = 4 * 1024 * 1024
|
|
22
|
+
_REACTION_EMOJIS = {"👍", "👎", "❤️", "😂", "😮", "🎉"}
|
|
23
|
+
# A restart's after-turn wait keeps the owner reachable only to finish its parked turn (the owner's
|
|
24
|
+
# RESTART_WAIT_WS_METHODS); new work waits for the next owner.
|
|
25
|
+
_RESTART_ACTIONS = {"snapshot", "watch", "receipt", "approval", "clarify", "clarify_lock", "interrupt"}
|
|
18
26
|
_CAPABILITIES = {"durable-admission-v1", "event-replay-v1"}
|
|
19
27
|
_CONTROL_REFUSALS = {"native_clarify_batch_unavailable", "owner_controls_unverified"}
|
|
28
|
+
_CREATE_FIELDS = {"request_id", "source", "cwd", "model", "provider", "base_url", "toolsets", "safe_mode", "ignore_user_config"}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _batch_locks() -> bool:
|
|
32
|
+
"""v0.22.3 owners serve ``clarify.lock``, so an attached viewer can answer a clarify batch per question."""
|
|
33
|
+
return find_spec("gateway.session_clarify_lock") is not None
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _restart_wait(home: Path) -> bool:
|
|
37
|
+
"""Whether the owner has entered a restart's after-turn wait since a watch attached. The owner announces
|
|
38
|
+
it on no socket, and the watch must not send on its own: a socket opened before the wait is cut when it does."""
|
|
39
|
+
from hermes_cli import gateway_runtime
|
|
40
|
+
if not hasattr(gateway_runtime, "attachable"):
|
|
41
|
+
return False
|
|
42
|
+
try:
|
|
43
|
+
found = gateway_runtime.discover_gateway_endpoint(home)
|
|
44
|
+
except Exception: # noqa: BLE001 - a failed probe leaves the watch as it was; every action rediscovers anyway
|
|
45
|
+
return False
|
|
46
|
+
return found.state != "ready" and gateway_runtime.attachable(found)
|
|
20
47
|
|
|
21
48
|
|
|
22
49
|
def _control_refusal(home: Path, sid: str) -> str | None:
|
|
23
|
-
"""Only canonical PendingControls can be recovered
|
|
50
|
+
"""Only canonical PendingControls can be recovered before v0.22.3. Never infer a missing batch.
|
|
24
51
|
|
|
25
52
|
Read the owner's committed admission in a read-only connection; opening SessionDB here
|
|
26
53
|
would run its schema writer alongside the owner. Compression keeps the logical target.
|
|
@@ -36,7 +63,7 @@ def _control_refusal(home: Path, sid: str) -> str | None:
|
|
|
36
63
|
return "owner_controls_unverified"
|
|
37
64
|
if "clarify_batch" in policy and not isinstance(policy["clarify_batch"], bool):
|
|
38
65
|
return "owner_controls_unverified"
|
|
39
|
-
if policy.get("clarify_batch") is True:
|
|
66
|
+
if policy.get("clarify_batch") is True and not _batch_locks():
|
|
40
67
|
return "native_clarify_batch_unavailable"
|
|
41
68
|
except (sqlite3.Error, OSError, ValueError, TypeError, AttributeError):
|
|
42
69
|
return "owner_controls_unverified"
|
|
@@ -48,9 +75,16 @@ def _snapshot(value: dict) -> dict:
|
|
|
48
75
|
# display rows, not those bindings or the inventory's system prompt and credential hint.
|
|
49
76
|
message_keys = {"role", "content", "tool_calls", "tool_call_id", "name", "timestamp", "message_id", "row_id",
|
|
50
77
|
"reasoning", "reasoning_content", "display_kind", "finish_reason"}
|
|
51
|
-
info_keys = {"title", "model", "cwd", "source", "provider"}
|
|
52
|
-
|
|
53
|
-
|
|
78
|
+
info_keys = {"title", "model", "cwd", "source", "provider", "config_warning"}
|
|
79
|
+
rows = []
|
|
80
|
+
for row in value["messages"]:
|
|
81
|
+
metadata = row.get("display_metadata")
|
|
82
|
+
reactions = metadata.get("reactions", []) if isinstance(metadata, dict) else []
|
|
83
|
+
rows.append({**{k: v for k, v in row.items() if k in message_keys}, "reactions": [
|
|
84
|
+
{"author": reaction["author"], "emoji": reaction["emoji"]} for reaction in reactions
|
|
85
|
+
if isinstance(reaction, dict) and reaction.get("author") in ("user", "agent")
|
|
86
|
+
and isinstance(reaction.get("emoji"), str) and reaction["emoji"] in _REACTION_EMOJIS] if isinstance(reactions, list) else []})
|
|
87
|
+
return {**value, "messages": rows, "info": {k: v for k, v in value["info"].items() if k in info_keys}}
|
|
54
88
|
|
|
55
89
|
|
|
56
90
|
def _refused(state: str, reason: str) -> dict:
|
|
@@ -89,23 +123,83 @@ async def _connect(home: Path, endpoint):
|
|
|
89
123
|
await reader
|
|
90
124
|
|
|
91
125
|
|
|
126
|
+
def _served(home: Path, endpoint, *, allow_verified: bool = False) -> bool:
|
|
127
|
+
if not endpoint.control_home or Path(endpoint.control_home).resolve() == home:
|
|
128
|
+
return False
|
|
129
|
+
if not allow_verified:
|
|
130
|
+
return True
|
|
131
|
+
return not _verified_contract(endpoint, "served-local-policy-v1")
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _verified_contract(endpoint, name: str) -> bool:
|
|
135
|
+
# The private control socket reports the owner's boot revision, not the sidecar's
|
|
136
|
+
# checkout or a version label. The authenticated describe must still match below.
|
|
137
|
+
try:
|
|
138
|
+
record = json.loads((Path(__file__).resolve().parents[2] / "agent_support.json").read_text())
|
|
139
|
+
revisions = record["nativeContracts"][name]
|
|
140
|
+
return (isinstance(revisions, list)
|
|
141
|
+
and all(isinstance(sha, str) and re.fullmatch(r"[0-9a-f]{40}", sha) for sha in revisions)
|
|
142
|
+
and getattr(endpoint, "code_sha", None) in revisions)
|
|
143
|
+
except (OSError, ValueError, KeyError, TypeError):
|
|
144
|
+
return False
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def _owner_refusal(described: dict, endpoint) -> dict | None:
|
|
148
|
+
if (not isinstance(described, dict)
|
|
149
|
+
or described.get("instance_id") != endpoint.instance_id
|
|
150
|
+
or described.get("profile_id") != endpoint.profile_id
|
|
151
|
+
or type(described.get("authority_epoch")) is not int
|
|
152
|
+
or described.get("authority_epoch") != endpoint.authority_epoch
|
|
153
|
+
or not isinstance(described.get("capabilities"), list)
|
|
154
|
+
or not all(isinstance(capability, str) for capability in described["capabilities"])
|
|
155
|
+
or not _CAPABILITIES.issubset(described.get("capabilities", []))):
|
|
156
|
+
return _refused("incompatible", "owner_capabilities")
|
|
157
|
+
return None
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def _checkpoint_read(value, *, no_baseline=False):
|
|
161
|
+
comparison = {"provenance": "native_owner", "baseline": "earliest_retained_project_checkpoint",
|
|
162
|
+
"available": False, "reason": None, "truncated": False}
|
|
163
|
+
result = {"diff": "", "stat": "", "comparison": comparison}
|
|
164
|
+
reason = None
|
|
165
|
+
if not isinstance(value, dict) or type(value.get("enabled")) is not bool:
|
|
166
|
+
reason = "invalid_payload"
|
|
167
|
+
elif not value["enabled"]:
|
|
168
|
+
reason = "checkpoints_disabled"
|
|
169
|
+
elif value.get("success") is not True:
|
|
170
|
+
reason = "checkpoint_unavailable"
|
|
171
|
+
elif (not isinstance(value.get("diff"), str) or not isinstance(value.get("stat"), str)
|
|
172
|
+
or type(value.get("diff_lines")) is not int or value["diff_lines"] < 0
|
|
173
|
+
or type(value.get("empty")) is not bool):
|
|
174
|
+
reason = "invalid_payload"
|
|
175
|
+
elif sum(len(json.dumps(value[key], ensure_ascii=False).encode("utf-8", "surrogatepass")) - 2
|
|
176
|
+
for key in ("stat", "diff")) > _OWNER_READ_MAX_BYTES:
|
|
177
|
+
reason = "payload_too_large"
|
|
178
|
+
elif no_baseline:
|
|
179
|
+
reason = "no_baseline"
|
|
180
|
+
else:
|
|
181
|
+
result.update(diff=value["diff"], stat=value["stat"])
|
|
182
|
+
comparison.update(available=True, truncated=value["diff_lines"] > len(value["diff"].splitlines()))
|
|
183
|
+
comparison["reason"] = reason
|
|
184
|
+
return result
|
|
185
|
+
|
|
186
|
+
|
|
92
187
|
async def _run(ctx, params: dict, home: Path, discovery) -> dict:
|
|
93
188
|
from hermes_cli.gateway_client import GatewayRPCError
|
|
94
189
|
|
|
95
190
|
endpoint = discovery.endpoint
|
|
96
|
-
|
|
97
|
-
# transport identity. A dedicated owner's profile is isolated; a served profile
|
|
98
|
-
# needs a verified execution contract before Talaria may submit through it.
|
|
99
|
-
if endpoint.control_home and Path(endpoint.control_home).resolve() != home:
|
|
191
|
+
if _served(home, endpoint, allow_verified=True):
|
|
100
192
|
return _refused("incompatible", "served_profile_sessions_unavailable")
|
|
193
|
+
if params["action"] in {"terminal_info", "shell_exec"} and not _verified_contract(endpoint, "captured-command-v1"):
|
|
194
|
+
return _refused("incompatible", "owner_shell_unsupported")
|
|
195
|
+
restarting = discovery.state != "ready"
|
|
196
|
+
if restarting and params["action"] not in _RESTART_ACTIONS:
|
|
197
|
+
return _refused("refused", "gateway_restarting")
|
|
101
198
|
subscription = None
|
|
102
199
|
async with _connect(home, endpoint) as (client, events):
|
|
103
200
|
described = await client.rpc("runtime.describe")
|
|
104
|
-
if (described
|
|
105
|
-
|
|
106
|
-
or described.get("authority_epoch") != endpoint.authority_epoch
|
|
107
|
-
or not _CAPABILITIES.issubset(described.get("capabilities", []))):
|
|
108
|
-
return _refused("incompatible", "owner_capabilities")
|
|
201
|
+
if refusal := _owner_refusal(described, endpoint):
|
|
202
|
+
return refusal
|
|
109
203
|
sid = params["session_id"]
|
|
110
204
|
|
|
111
205
|
async def snapshot():
|
|
@@ -117,13 +211,73 @@ async def _run(ctx, params: dict, home: Path, discovery) -> dict:
|
|
|
117
211
|
subscription = value["subscription_id"]
|
|
118
212
|
if reason := await asyncio.to_thread(_control_refusal, home, sid):
|
|
119
213
|
raise GatewayRPCError(reason)
|
|
120
|
-
return _snapshot(value)
|
|
214
|
+
return {**_snapshot(value), "reactions_supported": _verified_contract(endpoint, "message-reactions-v1")}
|
|
121
215
|
|
|
122
|
-
receipt = None
|
|
216
|
+
receipt = lock = None
|
|
123
217
|
try:
|
|
218
|
+
if params["action"] == "checkpoint_diff":
|
|
219
|
+
# The owner resolves the physical target and frozen policy. Never resume or read host files.
|
|
220
|
+
value = await asyncio.wait_for(client.rpc("rollback.session_diff", session_id=sid, _timeout=25), timeout=30)
|
|
221
|
+
read = _checkpoint_read(value)
|
|
222
|
+
if read["comparison"]["available"] and value["empty"] and not value["diff"] and not value["stat"]:
|
|
223
|
+
listed = await asyncio.wait_for(client.rpc("rollback.list", session_id=sid, _timeout=3), timeout=3)
|
|
224
|
+
if (not isinstance(listed, dict) or listed.get("enabled") is not True
|
|
225
|
+
or not isinstance(listed.get("checkpoints"), list)):
|
|
226
|
+
read = _checkpoint_read(None)
|
|
227
|
+
elif not listed["checkpoints"]:
|
|
228
|
+
read = _checkpoint_read(value, no_baseline=True)
|
|
229
|
+
return {"state": "attached", "reason": None, "snapshot": None, "receipt": None, "checkpoint_diff": read}
|
|
230
|
+
if params["action"] == "export":
|
|
231
|
+
# No resume/subscription or mutation: the owner selects its current physical target.
|
|
232
|
+
fmt = "md" if params["format"] == "markdown" else params["format"]
|
|
233
|
+
value = await asyncio.wait_for(client.rpc("session.export", session_id=sid,
|
|
234
|
+
format=fmt, redact=params["redact"], _timeout=25), timeout=30)
|
|
235
|
+
if (not isinstance(value, dict) or value.get("format") != fmt
|
|
236
|
+
or not isinstance(value.get("filename"), str) or not 0 < len(value["filename"]) <= 255
|
|
237
|
+
or not isinstance(value.get("content"), str)):
|
|
238
|
+
return _refused("refused", "owner_export_invalid")
|
|
239
|
+
if len(value["content"]) > _OWNER_READ_MAX_BYTES or len(value["content"].encode("utf-8")) > _OWNER_READ_MAX_BYTES:
|
|
240
|
+
return _refused("refused", "export_too_large")
|
|
241
|
+
return {"state": "attached", "reason": None, "snapshot": None, "receipt": None,
|
|
242
|
+
"export": {"format": params["format"], "filename": value["filename"], "content": value["content"]}}
|
|
124
243
|
snap = await snapshot()
|
|
125
244
|
action = params["action"]
|
|
126
245
|
common = {"session_id": sid}
|
|
246
|
+
if action == "terminal_info":
|
|
247
|
+
return {"state": "attached", "reason": None, "snapshot": snap, "receipt": None}
|
|
248
|
+
if action == "shell_exec":
|
|
249
|
+
if (snap.get("session_id") != params["session_id"] or snap.get("authority_epoch") != params["authority_epoch"]
|
|
250
|
+
or snap.get("replay_epoch") != params["replay_epoch"]):
|
|
251
|
+
return _refused("refused", "owner_changed")
|
|
252
|
+
# The native owner alone authorizes the frozen backend/cwd and redacts before bounding.
|
|
253
|
+
# No second observation may discard a received result; no retry after an unknown ACK.
|
|
254
|
+
value = await client.rpc("shell.exec", **common, command=params["command"], _timeout=35)
|
|
255
|
+
if (not isinstance(value, dict) or not isinstance(value.get("stdout"), str)
|
|
256
|
+
or not isinstance(value.get("stderr"), str) or type(value.get("code")) is not int
|
|
257
|
+
or len(value["stdout"]) > 4000 or len(value["stderr"]) > 2000):
|
|
258
|
+
return _refused("refused", "owner_shell_invalid")
|
|
259
|
+
return {"state": "attached", "reason": None, "snapshot": None, "receipt": None, "shell": value}
|
|
260
|
+
if action == "react":
|
|
261
|
+
if not snap["reactions_supported"]:
|
|
262
|
+
return _refused("refused", "owner_reactions_unsupported")
|
|
263
|
+
if not any(row.get("row_id") == params["row_id"] and row.get("role") in {"user", "assistant"} for row in snap["messages"]):
|
|
264
|
+
return _refused("refused", "reaction_row_unavailable")
|
|
265
|
+
await client.rpc("message.react", **common, row_id=params["row_id"], emoji=params["emoji"], author="user")
|
|
266
|
+
elif action == "context_detail":
|
|
267
|
+
from ..context_detail import project, unavailable
|
|
268
|
+
# The authorized native read owns lookup and prompt interpretation. No local Agent is built.
|
|
269
|
+
try:
|
|
270
|
+
payload = await client.rpc("session.context_breakdown", **common)
|
|
271
|
+
usage = None
|
|
272
|
+
with suppress(Exception):
|
|
273
|
+
usage = await client.rpc("session.stats", **common)
|
|
274
|
+
after = await snapshot()
|
|
275
|
+
marks = ("session_id", "stored_session_id", "authority_epoch", "replay_epoch", "revision", "execution_generation", "running", "last_sequence")
|
|
276
|
+
stable = all(snap.get(k) == after.get(k) for k in marks) and snap.get("info") == after.get("info")
|
|
277
|
+
detail = project(payload, usage=usage, running=after.get("running") is True) if stable else unavailable("changed")
|
|
278
|
+
except Exception: # unsupported owners and failed reads never authorize a fallback Agent
|
|
279
|
+
detail = unavailable("unsupported")
|
|
280
|
+
return {"state": "attached", "reason": None, "snapshot": snap, "receipt": None, "context_detail": detail}
|
|
127
281
|
if action == "submit":
|
|
128
282
|
# The caller retains this identity across lost ACKs. An ambiguous error never
|
|
129
283
|
# causes this adapter to generate a replacement or replay started work.
|
|
@@ -134,37 +288,68 @@ async def _run(ctx, params: dict, home: Path, discovery) -> dict:
|
|
|
134
288
|
method = "prompt.cancel" if action == "cancel" else "prompt.resolve_unknown"
|
|
135
289
|
receipt = await client.rpc(method, **common, admission_id=params["admission_id"],
|
|
136
290
|
**({"execution_generation": params["execution_generation"]} if action == "discard" else {}))
|
|
291
|
+
elif action in {"steer_queued", "replace_queued"}:
|
|
292
|
+
receipt = await client.rpc("prompt." + action, **common, admission_id=params["admission_id"],
|
|
293
|
+
**({"submission_id": params["submission_id"], "text": params["text"]} if action == "replace_queued" else {}))
|
|
137
294
|
elif action == "interrupt":
|
|
138
295
|
await client.rpc("session.interrupt", **common, execution_generation=params["execution_generation"])
|
|
296
|
+
elif action == "clarify_lock":
|
|
297
|
+
# The lock that answers the last question settles the batch with every locked answer.
|
|
298
|
+
lock = await client.rpc("clarify.lock", request_id=params["request_id"],
|
|
299
|
+
question_id=params["question_id"], answer=params["answer"])
|
|
139
300
|
elif action in {"approval", "clarify"}:
|
|
140
301
|
await client.rpc(action + ".respond", **common, prompt_id=params["prompt_id"],
|
|
141
302
|
execution_generation=params["execution_generation"],
|
|
142
303
|
**({"choice": params["choice"]} if action == "approval" else {"answer": params["text"]}))
|
|
143
304
|
elif action == "mutate":
|
|
144
|
-
await client.rpc("session.mutate", **common, request_id=params["request_id"],
|
|
305
|
+
receipt = await client.rpc("session.mutate", **common, request_id=params["request_id"],
|
|
145
306
|
expected_revision=params["expected_revision"], expected_generation=params["execution_generation"],
|
|
146
307
|
operation=params["operation"], payload=params["payload"], _timeout=660)
|
|
147
308
|
if action not in {"snapshot", "watch"}:
|
|
148
309
|
snap = await snapshot()
|
|
149
|
-
result = {"state": "attached", "reason": None, "snapshot": snap, "receipt": receipt
|
|
310
|
+
result = {"state": "attached", "reason": None, "snapshot": snap, "receipt": receipt, "restarting": restarting,
|
|
311
|
+
**({"lock": lock} if action == "clarify_lock" else {})}
|
|
150
312
|
if action != "watch":
|
|
151
313
|
return result
|
|
152
|
-
|
|
314
|
+
# Display negotiation is best effort on older owners. It changes no persisted config.
|
|
315
|
+
if isinstance(params.get("show_reasoning"), bool):
|
|
316
|
+
with suppress(GatewayRPCError, TimeoutError):
|
|
317
|
+
await client.rpc("config.set", **common, key="show_reasoning",
|
|
318
|
+
value="1" if params["show_reasoning"] else "0", _timeout=10)
|
|
319
|
+
ctx.emit("snapshot", {**result, "replaying": True})
|
|
153
320
|
epoch, sequence = snap["replay_epoch"], snap["last_sequence"]
|
|
154
321
|
# Rebuild the active turn's display from retained events, even when its initial
|
|
155
322
|
# tokens predate this viewer. A gap replaces the subscription, never invents replay.
|
|
156
323
|
replay = await client.rpc("session.events.since", **common, replay_epoch=epoch, last_sequence=0)
|
|
157
324
|
if replay.get("snapshot_required"):
|
|
158
325
|
snap = await snapshot()
|
|
159
|
-
ctx.emit("snapshot", {**result, "snapshot": snap, "replay_gap": True})
|
|
326
|
+
ctx.emit("snapshot", {**result, "snapshot": snap, "replay_gap": True, "replaying": True})
|
|
160
327
|
epoch, sequence = snap["replay_epoch"], snap["last_sequence"]
|
|
161
328
|
else:
|
|
162
329
|
for event in replay["events"]:
|
|
163
|
-
if
|
|
330
|
+
if event.get("session_id") != sid or event.get("replay_epoch") != epoch:
|
|
331
|
+
continue
|
|
332
|
+
if (event.get("type") in {"session.updated", "notification.show", "notification.clear"}
|
|
333
|
+
or event.get("execution_generation") == snap["execution_generation"]
|
|
164
334
|
or event.get("type") == "session.info" and event.get("payload", {}).get("execution_generation") == snap["execution_generation"]):
|
|
165
335
|
ctx.emit("event", event)
|
|
166
336
|
sequence = replay["last_sequence"]
|
|
337
|
+
ctx.emit("replay_complete", {})
|
|
338
|
+
checked = asyncio.get_running_loop().time()
|
|
167
339
|
while not ctx.cancelled:
|
|
340
|
+
now = asyncio.get_running_loop().time()
|
|
341
|
+
if not restarting and now - checked >= 2:
|
|
342
|
+
checked = now
|
|
343
|
+
if restarting := await asyncio.to_thread(_restart_wait, home):
|
|
344
|
+
result["restarting"] = True
|
|
345
|
+
ctx.emit("restarting", {"restarting": True})
|
|
346
|
+
if not restarting and snap.get("reactions_supported"):
|
|
347
|
+
# The owner emits no reaction event. Read through this viewer's existing subscription,
|
|
348
|
+
# including while tokens keep the event queue busy.
|
|
349
|
+
current = await snapshot()
|
|
350
|
+
if [(r.get("row_id"), r.get("reactions")) for r in current["messages"] if r.get("reactions")] != [(r.get("row_id"), r.get("reactions")) for r in snap["messages"] if r.get("reactions")]:
|
|
351
|
+
ctx.emit("snapshot", {**result, "snapshot": current, "reaction_only": True})
|
|
352
|
+
snap = current
|
|
168
353
|
try:
|
|
169
354
|
frame = await asyncio.wait_for(events.get(), .25)
|
|
170
355
|
except TimeoutError:
|
|
@@ -172,7 +357,15 @@ async def _run(ctx, params: dict, home: Path, discovery) -> dict:
|
|
|
172
357
|
if isinstance(frame, Exception):
|
|
173
358
|
raise frame
|
|
174
359
|
if frame.get("method") == "clarify" and "id" in frame:
|
|
175
|
-
|
|
360
|
+
if not _batch_locks():
|
|
361
|
+
raise GatewayRPCError("native_clarify_batch_unavailable")
|
|
362
|
+
# The owner asks attached viewers only, once; its later request.cancel event settles it.
|
|
363
|
+
request = frame.get("params", {})
|
|
364
|
+
if request.get("session_id") == sid:
|
|
365
|
+
ctx.emit("clarify_batch", {"request_id": frame["id"], "questions": request.get("questions", [])})
|
|
366
|
+
continue
|
|
367
|
+
if frame.get("method") != "event":
|
|
368
|
+
continue
|
|
176
369
|
event = frame.get("params", {})
|
|
177
370
|
if event.get("session_id") != sid:
|
|
178
371
|
continue
|
|
@@ -181,7 +374,12 @@ async def _run(ctx, params: dict, home: Path, discovery) -> dict:
|
|
|
181
374
|
raise GatewayRPCError(reason)
|
|
182
375
|
if (event.get("type") == "session.replay_gap" or event.get("replay_epoch") != epoch
|
|
183
376
|
or event.get("seq", sequence + 1) > sequence + 1):
|
|
184
|
-
|
|
377
|
+
current = await snapshot()
|
|
378
|
+
# A queued frame from an obsolete epoch is not a gap in the current subscription.
|
|
379
|
+
if (event.get("type") != "session.replay_gap" and event.get("replay_epoch") != epoch
|
|
380
|
+
and current["replay_epoch"] == epoch):
|
|
381
|
+
continue
|
|
382
|
+
snap = current
|
|
185
383
|
ctx.emit("snapshot", {**result, "snapshot": snap, "replay_gap": True})
|
|
186
384
|
epoch, sequence = snap["replay_epoch"], snap["last_sequence"]
|
|
187
385
|
continue
|
|
@@ -191,6 +389,10 @@ async def _run(ctx, params: dict, home: Path, discovery) -> dict:
|
|
|
191
389
|
ctx.emit("event", event)
|
|
192
390
|
return result
|
|
193
391
|
except GatewayRPCError as exc:
|
|
392
|
+
if params["action"] == "react" and str(exc) not in {"invalid_params", "not_found", "permission_denied", "profile_mismatch"}:
|
|
393
|
+
return _refused("unavailable", "reaction_outcome_unknown")
|
|
394
|
+
if params["action"] == "export":
|
|
395
|
+
return _refused("refused", "export_too_large" if str(exc) == "export_too_large" else "owner_export_unsupported")
|
|
194
396
|
return {**_refused("incompatible" if str(exc) in _CONTROL_REFUSALS else "refused", str(exc)), "receipt": receipt}
|
|
195
397
|
except Exception: # noqa: BLE001 - native transport/contract failures never authorize another writer
|
|
196
398
|
# A received receipt remains admission proof even if the following observation
|
|
@@ -209,26 +411,98 @@ def session(ctx, params: dict) -> dict:
|
|
|
209
411
|
if action not in _ACTIONS or not isinstance(sid, str) or not sid.strip() or sid != sid.strip():
|
|
210
412
|
raise InvalidParams("session_id and supported action are required")
|
|
211
413
|
params = {**params, "action": action}
|
|
414
|
+
if action == "react" and (set(params) - {"profile_home", "session_id", "action", "row_id", "emoji"}
|
|
415
|
+
or type(params.get("row_id")) is not int or params["row_id"] <= 0
|
|
416
|
+
or "emoji" not in params or (params["emoji"] is not None and (not isinstance(params["emoji"], str) or params["emoji"] not in _REACTION_EMOJIS))):
|
|
417
|
+
raise InvalidParams("react requires a visible row and an allowed emoji")
|
|
418
|
+
if action == "export" and (params.get("format") not in ("json", "markdown", "html")
|
|
419
|
+
or not isinstance(params.get("redact"), bool)):
|
|
420
|
+
raise InvalidParams("export requires an allowed format and redaction policy")
|
|
421
|
+
if action == "shell_exec" and (not isinstance(params.get("command"), str)
|
|
422
|
+
or not params["command"].strip() or len(params["command"]) > 8192
|
|
423
|
+
or type(params.get("authority_epoch")) is not int or params["authority_epoch"] < 0
|
|
424
|
+
or not isinstance(params.get("replay_epoch"), str) or not params["replay_epoch"]):
|
|
425
|
+
raise InvalidParams("captured command requires command and owner identity")
|
|
212
426
|
required = {
|
|
213
427
|
"submit": ("request_id", "text"), "receipt": ("admission_id",), "cancel": ("admission_id",),
|
|
428
|
+
"steer_queued": ("admission_id",), "replace_queued": ("admission_id", "submission_id", "text"),
|
|
214
429
|
"interrupt": ("execution_generation",), "approval": ("execution_generation", "prompt_id", "choice"),
|
|
215
|
-
"clarify": ("execution_generation", "prompt_id", "text"), "discard": ("execution_generation", "admission_id"),
|
|
430
|
+
"clarify": ("execution_generation", "prompt_id", "text"), "clarify_lock": ("request_id", "question_id", "answer"), "discard": ("execution_generation", "admission_id"),
|
|
216
431
|
"mutate": ("request_id", "expected_revision", "execution_generation", "operation", "payload"),
|
|
217
432
|
}.get(action, ())
|
|
218
433
|
if any(key not in params for key in required):
|
|
219
434
|
raise InvalidParams("missing gateway session action fields")
|
|
435
|
+
return _with_owner(home, lambda discovery: _run(ctx, params, home, discovery))
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
def _with_owner(home: Path, run) -> dict:
|
|
220
439
|
try:
|
|
221
440
|
from hermes_constants import set_hermes_home_override, reset_hermes_home_override # noqa: F401
|
|
222
|
-
from hermes_cli
|
|
441
|
+
from hermes_cli import gateway_runtime
|
|
223
442
|
from hermes_cli.gateway_client import connect_gateway # noqa: F401
|
|
224
443
|
except ImportError:
|
|
225
444
|
return _refused("incompatible", "native_sessions_unavailable")
|
|
445
|
+
# v0.22.3 also admits a restart's after-turn wait, so a parked approval or clarify can still be answered.
|
|
446
|
+
attachable = getattr(gateway_runtime, "attachable", lambda found: found.state == "ready")
|
|
226
447
|
with scoped_home(home):
|
|
227
|
-
discovery = discover_gateway_endpoint(home)
|
|
228
|
-
if discovery.
|
|
448
|
+
discovery = gateway_runtime.discover_gateway_endpoint(home)
|
|
449
|
+
if discovery.endpoint is None or not attachable(discovery):
|
|
229
450
|
return _refused("stopped" if discovery.state in {"stopped", "absent"} else "unavailable", discovery.reason_code or discovery.state)
|
|
230
451
|
try:
|
|
231
|
-
return asyncio.run(
|
|
452
|
+
return asyncio.run(run(discovery))
|
|
232
453
|
except Exception: # noqa: BLE001 - native transport/contract failures never authorize another writer
|
|
233
454
|
# Do not expose peer diagnostics, endpoint paths or bootstrap credentials.
|
|
234
455
|
return _refused("unavailable", "owner_connection_lost")
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
async def _create(params: dict, home: Path, discovery) -> dict:
|
|
459
|
+
"""Mint one diagnostic session through the owner, which freezes the bypass in its creation
|
|
460
|
+
policy and runs every turn in a fresh private worker. Talaria never imports the Agent with
|
|
461
|
+
that policy, flips a process global or passes it through the environment."""
|
|
462
|
+
from hermes_cli.gateway_client import GatewayRPCError
|
|
463
|
+
|
|
464
|
+
endpoint = discovery.endpoint
|
|
465
|
+
if _served(home, endpoint):
|
|
466
|
+
return _refused("incompatible", "served_profile_sessions_unavailable")
|
|
467
|
+
if discovery.state != "ready":
|
|
468
|
+
return _refused("unavailable", "gateway_restarting")
|
|
469
|
+
async with _connect(home, endpoint) as (client, _):
|
|
470
|
+
described = await client.rpc("runtime.describe")
|
|
471
|
+
if refusal := _owner_refusal(described, endpoint):
|
|
472
|
+
return refusal
|
|
473
|
+
accepted = set((described.get("session_create") or {}).get("parameters", []))
|
|
474
|
+
if "local-cli-create-v1" not in described.get("capabilities", []) or not _CREATE_FIELDS.issubset(accepted):
|
|
475
|
+
return _refused("incompatible", "execution_mode_unavailable")
|
|
476
|
+
if params.get("probe") is True:
|
|
477
|
+
return {"state": "attached", "reason": None, "snapshot": None, "receipt": None}
|
|
478
|
+
fields = {key: params[key] for key in ("cwd", "model", "provider", "base_url", "toolsets") if params.get(key) is not None}
|
|
479
|
+
try:
|
|
480
|
+
# Safe implies config-only; the owner normalizes it too. No credential is sent or receipted.
|
|
481
|
+
created = await client.rpc("session.create", request_id=params["request_id"], source="cli", **fields,
|
|
482
|
+
safe_mode=params["execution_mode"] == "safe", ignore_user_config=True)
|
|
483
|
+
except GatewayRPCError as exc:
|
|
484
|
+
return _refused("refused", str(exc))
|
|
485
|
+
with suppress(Exception):
|
|
486
|
+
await client.rpc("session.detach", session_id=created["session_id"], subscription_id=created["subscription_id"])
|
|
487
|
+
return {"state": "attached", "reason": None, "snapshot": _snapshot(created), "receipt": None}
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
def _text(params: dict, key: str, required: bool = True) -> bool:
|
|
491
|
+
value = params.get(key)
|
|
492
|
+
if value is None:
|
|
493
|
+
return not required
|
|
494
|
+
return isinstance(value, str) and bool(value) and value == value.strip()
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
def create(params: dict) -> dict:
|
|
498
|
+
"""``probe`` answers whether this owner can create diagnostic sessions, without creating one."""
|
|
499
|
+
home = profile_home_param(params).resolve()
|
|
500
|
+
toolsets = params.get("toolsets")
|
|
501
|
+
if params.get("probe") is not True and (
|
|
502
|
+
params.get("execution_mode") not in {"ignore_config", "safe"}
|
|
503
|
+
or not _text(params, "request_id") or len(params["request_id"]) > 128
|
|
504
|
+
or not _text(params, "model") or not _text(params, "cwd") or not Path(params["cwd"]).is_absolute()
|
|
505
|
+
or not _text(params, "provider", False) or not _text(params, "base_url", False)
|
|
506
|
+
or toolsets is not None and (not isinstance(toolsets, list) or not all(isinstance(t, str) and t for t in toolsets))):
|
|
507
|
+
raise InvalidParams("execution_mode, request_id, model and an absolute cwd are required")
|
|
508
|
+
return _with_owner(home, lambda discovery: _create(params, home, discovery))
|
|
@@ -10,8 +10,11 @@ from __future__ import annotations
|
|
|
10
10
|
import functools
|
|
11
11
|
import json
|
|
12
12
|
import secrets
|
|
13
|
+
import sqlite3
|
|
13
14
|
import time
|
|
15
|
+
from contextlib import closing
|
|
14
16
|
from dataclasses import asdict, is_dataclass
|
|
17
|
+
from pathlib import Path
|
|
15
18
|
from typing import Any, NamedTuple
|
|
16
19
|
|
|
17
20
|
from ..errors import InvalidParams, RpcError
|
|
@@ -97,8 +100,6 @@ def _connect_module():
|
|
|
97
100
|
|
|
98
101
|
|
|
99
102
|
def _conn(board=None):
|
|
100
|
-
kb = _kb()
|
|
101
|
-
kb.init_db(board=board)
|
|
102
103
|
module = _connect_module()
|
|
103
104
|
closing = getattr(module, "connect_closing", None)
|
|
104
105
|
return closing(board=board) if closing is not None else module.connect(board=board)
|
|
@@ -465,6 +466,50 @@ def _bool(params: dict, key: str, default: bool = False) -> bool:
|
|
|
465
466
|
|
|
466
467
|
# ── payload builders ──────────────────────────────────────────────────────
|
|
467
468
|
|
|
469
|
+
def inspection_payload(params: dict) -> dict:
|
|
470
|
+
"""Read only the selected profile's live boards, with shared global row/edge budgets."""
|
|
471
|
+
kb = _kb()
|
|
472
|
+
selected = _board(params)
|
|
473
|
+
boards = sorted((b for b in kb.list_boards(include_archived=False) if not b.get("archived")), key=lambda b: b["slug"])
|
|
474
|
+
if selected is not None:
|
|
475
|
+
boards = [b for b in boards if b["slug"] == selected]
|
|
476
|
+
if not boards:
|
|
477
|
+
raise NotFound("board not found")
|
|
478
|
+
nodes, edges = [], []
|
|
479
|
+
truncated = len(boards) > 32
|
|
480
|
+
for meta in boards[:32]:
|
|
481
|
+
slug = _normalize_existing_slug(meta["slug"])
|
|
482
|
+
if len(nodes) >= 500:
|
|
483
|
+
truncated = True
|
|
484
|
+
break
|
|
485
|
+
# An inspection must never initialize a missing database or run migrations.
|
|
486
|
+
uri = Path(kb.kanban_db_path(slug)).resolve().as_uri() + "?mode=ro"
|
|
487
|
+
with closing(sqlite3.connect(uri, uri=True)) as conn:
|
|
488
|
+
conn.row_factory = sqlite3.Row
|
|
489
|
+
conn.execute("BEGIN")
|
|
490
|
+
where = "" if _bool(params, "include_archived") else "WHERE t.status != 'archived'"
|
|
491
|
+
rows = conn.execute(
|
|
492
|
+
f"SELECT t.*, r.started_at AS current_run_started_at FROM tasks t LEFT JOIN task_runs r ON r.id = t.current_run_id {where} ORDER BY t.id LIMIT ?",
|
|
493
|
+
(501 - len(nodes),),
|
|
494
|
+
).fetchall()
|
|
495
|
+
remaining = 500 - len(nodes)
|
|
496
|
+
truncated = truncated or len(rows) > remaining
|
|
497
|
+
rows = rows[:remaining]
|
|
498
|
+
ids = [row["id"] for row in rows]
|
|
499
|
+
for row in rows:
|
|
500
|
+
task = _task_dict(dict(row), conn)
|
|
501
|
+
nodes.append({"key": f"{slug}/{row['id']}", "board": slug, "board_name": meta.get("name") or slug, "task": task})
|
|
502
|
+
if ids:
|
|
503
|
+
placeholders = ",".join("?" for _ in ids)
|
|
504
|
+
links = conn.execute(
|
|
505
|
+
f"SELECT parent_id, child_id FROM task_links WHERE parent_id IN ({placeholders}) AND child_id IN ({placeholders}) ORDER BY parent_id, child_id LIMIT ?",
|
|
506
|
+
[*ids, *ids, 2001 - len(edges)],
|
|
507
|
+
).fetchall()
|
|
508
|
+
remaining_edges = 2000 - len(edges)
|
|
509
|
+
truncated = truncated or len(links) > remaining_edges
|
|
510
|
+
edges.extend({"source": f"{slug}/{r['parent_id']}", "target": f"{slug}/{r['child_id']}"} for r in links[:remaining_edges])
|
|
511
|
+
return {"nodes": nodes, "edges": edges, "generated_at": time.time(), "truncated": truncated, "read_only": False}
|
|
512
|
+
|
|
468
513
|
def board_payload(params: dict) -> dict:
|
|
469
514
|
board = _board(params)
|
|
470
515
|
kb = _kb()
|
|
@@ -595,6 +640,7 @@ def task_detail_payload(params: dict) -> dict:
|
|
|
595
640
|
def events_payload(params: dict) -> dict:
|
|
596
641
|
since = _int(params, "since", 0, minimum=0)
|
|
597
642
|
limit = _int(params, "limit", 200, minimum=1, maximum=200)
|
|
643
|
+
kb = _kb()
|
|
598
644
|
with _conn(board=_board(params)) as conn:
|
|
599
645
|
rows = conn.execute(
|
|
600
646
|
"SELECT id, task_id, run_id, kind, payload, created_at FROM task_events WHERE id > ? ORDER BY id ASC LIMIT ?", (since, limit)
|
|
@@ -605,7 +651,7 @@ def events_payload(params: dict) -> dict:
|
|
|
605
651
|
payload = json.loads(row["payload"]) if row["payload"] else None
|
|
606
652
|
except Exception: # noqa: BLE001
|
|
607
653
|
payload = None
|
|
608
|
-
events.append({"id": row["id"], "task_id": row["task_id"], "run_id": row["run_id"], "kind": row["kind"], "payload": payload, "created_at": row["created_at"]})
|
|
654
|
+
events.append({"id": row["id"], "task_id": row["task_id"], "run_id": row["run_id"], "kind": row["kind"], "payload": payload, "created_at": kb._to_epoch(row["created_at"])})
|
|
609
655
|
cursor = int(row["id"])
|
|
610
656
|
latest = _latest_event_id(conn)
|
|
611
657
|
if not events:
|
|
@@ -853,6 +899,7 @@ def normalize_board_payload(params: dict) -> dict:
|
|
|
853
899
|
|
|
854
900
|
|
|
855
901
|
METHODS = {
|
|
902
|
+
"kanban.inspection": inspection_payload,
|
|
856
903
|
"kanban.normalize_board": normalize_board_payload,
|
|
857
904
|
"kanban.board": board_payload,
|
|
858
905
|
"kanban.boards": list_boards_payload,
|