@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
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"""Reviewed Agent catalog and disabled installs. Agent owns cache, scan and publication."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import hashlib
|
|
5
|
+
import inspect
|
|
6
|
+
import json
|
|
7
|
+
import os
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
import re
|
|
10
|
+
import secrets
|
|
11
|
+
import threading
|
|
12
|
+
import time
|
|
13
|
+
|
|
14
|
+
from ..errors import InvalidParams, RpcError
|
|
15
|
+
|
|
16
|
+
_receipts: dict[str, dict] = {}
|
|
17
|
+
_lock = threading.Lock()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _agent():
|
|
21
|
+
try:
|
|
22
|
+
from hermes_cli import plugin_catalog as source, plugins_cmd as pc, plugins_cmd_catalog as native
|
|
23
|
+
if 'before_swap' not in inspect.signature(native.install_catalog_entry).parameters:
|
|
24
|
+
return None
|
|
25
|
+
return source, pc, native
|
|
26
|
+
except (ImportError, AttributeError):
|
|
27
|
+
return None
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _refusal(entry, pc, native):
|
|
31
|
+
try:
|
|
32
|
+
native.raise_if_removed(entry.name, entry.repo)
|
|
33
|
+
native._refuse_unsupported_catalog_platform(entry)
|
|
34
|
+
from hermes_cli.plugins_manifest import requires_hermes_error
|
|
35
|
+
reason = requires_hermes_error({'requires_hermes': entry.requires_hermes})
|
|
36
|
+
if reason:
|
|
37
|
+
return reason
|
|
38
|
+
if not re.fullmatch(r'[a-f0-9]{40}', entry.sha):
|
|
39
|
+
return 'The catalog has no immutable reviewed pin.'
|
|
40
|
+
except pc.PluginOperationError as exc:
|
|
41
|
+
return str(exc)
|
|
42
|
+
return None
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _requirements(entry):
|
|
46
|
+
caps = entry.capabilities
|
|
47
|
+
values = []
|
|
48
|
+
for label, items in [('Hermes', [entry.requires_hermes] if entry.requires_hermes else []),
|
|
49
|
+
('Platforms', entry.platforms), ('Environment', caps.requires_env),
|
|
50
|
+
('Tools', caps.provides_tools), ('Hooks', caps.provides_hooks),
|
|
51
|
+
('Middleware', caps.provides_middleware)]:
|
|
52
|
+
if items:
|
|
53
|
+
values.append(f'{label}: {", ".join(items)}')
|
|
54
|
+
return values + list(entry.known_issues)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def catalog(query='', offset=0, limit=20):
|
|
58
|
+
if not isinstance(query, str) or len(query) > 200 or type(offset) is not int or not 0 <= offset <= 10000 or type(limit) is not int or not 1 <= limit <= 50:
|
|
59
|
+
raise InvalidParams('Invalid catalog search or page')
|
|
60
|
+
agent = _agent()
|
|
61
|
+
if agent is None:
|
|
62
|
+
return {'supported': False, 'entries': [], 'total': 0, 'next_offset': None}
|
|
63
|
+
source, pc, native = agent
|
|
64
|
+
# Read authoritative installer metadata only. Native discovery may load plugins or adopt old records.
|
|
65
|
+
metadata = pc._read_install_metadata()
|
|
66
|
+
rows = []
|
|
67
|
+
for entry in sorted(source.load_catalog_live(), key=lambda e: e.name)[:10000]:
|
|
68
|
+
if query.casefold() not in ' '.join([entry.name, entry.description, entry.tier, entry.category]).casefold():
|
|
69
|
+
continue
|
|
70
|
+
matches = [(key, record) for key, record in metadata.items() if isinstance(record, dict)
|
|
71
|
+
and isinstance(record.get('catalog'), dict) and record['catalog'].get('name') == entry.name
|
|
72
|
+
and (pc._plugins_dir() / key).is_dir()]
|
|
73
|
+
key, record = matches[0] if len(matches) == 1 else (None, {})
|
|
74
|
+
refusal = _refusal(entry, pc, native)
|
|
75
|
+
rows.append({'name': entry.name, 'title': entry.title or entry.name, 'description': entry.description,
|
|
76
|
+
'repo': entry.repo, 'sha': entry.sha, 'tier': entry.tier, 'category': entry.category,
|
|
77
|
+
'requirements': _requirements(entry), 'installed_key': key,
|
|
78
|
+
'installed_sha': str(record.get('revision') or '') or None,
|
|
79
|
+
'can_install': not matches and refusal is None, 'refusal': refusal})
|
|
80
|
+
end = offset + limit
|
|
81
|
+
return {'supported': True, 'entries': rows[offset:end], 'total': len(rows), 'next_offset': end if end < len(rows) else None}
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _tree_digest(tree):
|
|
85
|
+
# Git's mutable clone metadata is not part of the code being reviewed.
|
|
86
|
+
digest = hashlib.sha256()
|
|
87
|
+
count = total = 0
|
|
88
|
+
for root, dirs, files in os.walk(tree, followlinks=False):
|
|
89
|
+
base = Path(root)
|
|
90
|
+
links = [name for name in dirs if (base / name).is_symlink()]
|
|
91
|
+
dirs[:] = sorted(name for name in dirs if name not in {'.git', '__pycache__'} and name not in links)
|
|
92
|
+
for name in sorted(files + links):
|
|
93
|
+
path = base / name
|
|
94
|
+
info = path.lstat()
|
|
95
|
+
count += 1
|
|
96
|
+
total += info.st_size
|
|
97
|
+
if count > 10000 or total > 64 * 1024 * 1024:
|
|
98
|
+
raise RpcError('The plugin tree exceeds the bounded review size.', condition='plugin_install_refused')
|
|
99
|
+
digest.update(json.dumps([str(path.relative_to(tree)), info.st_mode, info.st_size]).encode() + b'\0')
|
|
100
|
+
if path.is_symlink():
|
|
101
|
+
digest.update(os.readlink(path).encode())
|
|
102
|
+
else:
|
|
103
|
+
with path.open('rb') as stream:
|
|
104
|
+
for chunk in iter(lambda: stream.read(1024 * 1024), b''):
|
|
105
|
+
digest.update(chunk)
|
|
106
|
+
return digest.hexdigest()
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def install(name, consent_token=None):
|
|
110
|
+
if not isinstance(name, str) or not re.fullmatch(r'[a-z0-9_-]{1,64}', name) or consent_token is not None and not isinstance(consent_token, str):
|
|
111
|
+
raise InvalidParams('Choose a catalog name, without a URL or ref override')
|
|
112
|
+
agent = _agent()
|
|
113
|
+
if agent is None:
|
|
114
|
+
raise RpcError('This Agent cannot install reviewed catalog plugins', condition='plugin_catalog_unsupported')
|
|
115
|
+
source, pc, native = agent
|
|
116
|
+
from hermes_constants import get_hermes_home
|
|
117
|
+
from pm.plugin_declarations import read_python_declaration
|
|
118
|
+
from pm.workspace import enabled_plugin_dirs
|
|
119
|
+
from hermes_cli.plugin_capabilities import VALID_CAPABILITY_IDS
|
|
120
|
+
|
|
121
|
+
with _lock:
|
|
122
|
+
now = time.monotonic()
|
|
123
|
+
for token in list(_receipts):
|
|
124
|
+
if _receipts[token]['expires'] <= now:
|
|
125
|
+
del _receipts[token]
|
|
126
|
+
receipt = _receipts.pop(consent_token, None) if consent_token else None
|
|
127
|
+
changed = 'Plugin confirmation expired or changed; review the plugin again.'
|
|
128
|
+
def refuse_changed():
|
|
129
|
+
raise RpcError(changed, condition='plugin_install_consent_changed')
|
|
130
|
+
if consent_token and receipt is None:
|
|
131
|
+
refuse_changed()
|
|
132
|
+
entry = next((e for e in source.load_catalog_live() if e.name == name), None)
|
|
133
|
+
if entry is None:
|
|
134
|
+
raise RpcError('This plugin is no longer in the catalog', condition='plugin_install_refused')
|
|
135
|
+
identity = [str(get_hermes_home().resolve()), entry.to_dict()]
|
|
136
|
+
if receipt and receipt['identity'] != identity:
|
|
137
|
+
refuse_changed()
|
|
138
|
+
refusal = _refusal(entry, pc, native)
|
|
139
|
+
if refusal:
|
|
140
|
+
return {'name': name, 'status': 'blocked', 'findings': refusal}
|
|
141
|
+
preview = {}
|
|
142
|
+
findings = ''
|
|
143
|
+
|
|
144
|
+
class ReviewNeeded(Exception):
|
|
145
|
+
pass
|
|
146
|
+
|
|
147
|
+
def check_tree(manifest, tree):
|
|
148
|
+
nonlocal preview, findings
|
|
149
|
+
key = manifest.get('name')
|
|
150
|
+
if not isinstance(key, str) or not key:
|
|
151
|
+
raise pc.PluginOperationError('The plugin needs an explicit manifest name for reviewed installation.')
|
|
152
|
+
target = pc._sanitize_plugin_name(key, pc._plugins_dir())
|
|
153
|
+
if target.exists() or target.is_symlink():
|
|
154
|
+
raise pc.PluginOperationError('This plugin is already installed; use its existing controls.')
|
|
155
|
+
if target.resolve() in enabled_plugin_dirs(installing=target):
|
|
156
|
+
raise pc.PluginOperationError('This plugin is already selected in the profile. Review that selection before installing.')
|
|
157
|
+
from hermes_cli.plugins_manifest import requires_hermes_error
|
|
158
|
+
reason = requires_hermes_error(manifest)
|
|
159
|
+
if reason:
|
|
160
|
+
raise pc.PluginOperationError(reason)
|
|
161
|
+
raw_caps = manifest.get('capabilities') or []
|
|
162
|
+
if not isinstance(raw_caps, list) or any(not isinstance(c, str) or c not in VALID_CAPABILITY_IDS for c in raw_caps):
|
|
163
|
+
raise pc.PluginOperationError('The plugin declares capabilities this Agent cannot verify.')
|
|
164
|
+
deps = list(read_python_declaration(tree).install_requirements)
|
|
165
|
+
preview = {'tree': _tree_digest(tree), 'key': key, 'dependencies': deps, 'capabilities': raw_caps}
|
|
166
|
+
findings = '\n'.join([f'{entry.name} · {entry.tier} · {entry.sha}', entry.repo, *_requirements(entry),
|
|
167
|
+
*([f'Python dependencies, not approved: {", ".join(deps)}'] if deps else []),
|
|
168
|
+
*([f'Host capabilities, not granted: {", ".join(raw_caps)}'] if raw_caps else []),
|
|
169
|
+
'Installs disabled. No dependency, host capability or sidecar permission is granted.',
|
|
170
|
+
'Native Desktop contributions are unverified and do not run in Talaria.'])
|
|
171
|
+
if not receipt:
|
|
172
|
+
raise ReviewNeeded()
|
|
173
|
+
if receipt['preview'] != preview:
|
|
174
|
+
refuse_changed()
|
|
175
|
+
# Revalidate removal/repin immediately before the native scan/publication path.
|
|
176
|
+
current = next((e for e in source.load_catalog_live() if e.name == name), None)
|
|
177
|
+
if current is None or current.to_dict() != entry.to_dict():
|
|
178
|
+
refuse_changed()
|
|
179
|
+
native.raise_if_removed(entry.name, entry.repo)
|
|
180
|
+
return []
|
|
181
|
+
|
|
182
|
+
try:
|
|
183
|
+
# Same native core as dashboard_install_plugin(enable=False), with its staging hook binding review.
|
|
184
|
+
target, _manifest, key = native.install_catalog_entry(entry, force=False, ref=entry.sha,
|
|
185
|
+
allow_removed=False, assume_deps_consent=False, before_swap=check_tree)
|
|
186
|
+
return {'name': name, 'key': key, 'status': 'installed', 'enabled': False}
|
|
187
|
+
except ReviewNeeded:
|
|
188
|
+
pass
|
|
189
|
+
except pc.PluginScanBlocked as exc:
|
|
190
|
+
return {'name': name, 'status': 'blocked', 'findings': str(exc)}
|
|
191
|
+
except pc.PluginOperationError as exc:
|
|
192
|
+
return {'name': name, 'status': 'blocked', 'findings': str(exc)}
|
|
193
|
+
token = secrets.token_urlsafe(32)
|
|
194
|
+
with _lock:
|
|
195
|
+
if len(_receipts) >= 64:
|
|
196
|
+
del _receipts[next(iter(_receipts))]
|
|
197
|
+
_receipts[token] = {'identity': identity, 'preview': preview, 'expires': time.monotonic() + 300}
|
|
198
|
+
return {'name': name, 'status': 'needs_consent', 'findings': findings, 'consent_token': token}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"""OAuth clients a plugin declares in ``plugin.yaml`` (Agent v0.22.3+, TAL-1276): status, sign-in and sign-out from Web.
|
|
2
|
+
|
|
3
|
+
``plugins.oauth_status`` and ``plugins.oauth_logout`` read and remove grants through the Agent's ``plugin_oauth``
|
|
4
|
+
helpers, mapped exactly as ``hermes auth status|logout <plugin>:<id>``. The sign-in is the ``oauth.*`` flow kind
|
|
5
|
+
``plugin:<key>:<id>``: the Agent's PKCE config, loopback listener, token request and grant store, with the waiting
|
|
6
|
+
that ``auth_oauth_pkce_plugin.login`` does in a terminal run here so a flow can be cancelled, can expire, and can also
|
|
7
|
+
finish from a pasted redirect address when the browser runs on another machine. The Agent's helpers are private, so
|
|
8
|
+
each is checked by name: an Agent without any of them offers no status and no sign-in.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import hmac
|
|
14
|
+
import logging
|
|
15
|
+
import secrets
|
|
16
|
+
import threading
|
|
17
|
+
import time
|
|
18
|
+
import types
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
from urllib.parse import parse_qs, urlencode, urlparse
|
|
21
|
+
|
|
22
|
+
from ..errors import InvalidParams, RpcError
|
|
23
|
+
from ..home import profile_home_param, scoped_home
|
|
24
|
+
from ..rpc import CallContext
|
|
25
|
+
|
|
26
|
+
log = logging.getLogger("talaria_sidecar.plugin_oauth")
|
|
27
|
+
|
|
28
|
+
PREFIX = "plugin:"
|
|
29
|
+
_NEEDED = {
|
|
30
|
+
"plugin_oauth": ("_declared_clients", "_read_grant", "_write_grant", "_usable_grant", "_pkce_config", "plugin_key", "_installed_client", "_logout_key"),
|
|
31
|
+
"auth_oauth_pkce_plugin": ("validate_config", "_post_token", "_err"),
|
|
32
|
+
"auth_device_flow": ("_make_loopback_callback_handler", "_bind_loopback_callback_server", "_pkce_code_verifier", "_pkce_code_challenge"),
|
|
33
|
+
"plugins_cmd": ("_discover_all_plugins",),
|
|
34
|
+
"plugin_provider_requests": ("ProviderNotSignedIn",),
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _agent() -> types.SimpleNamespace | None:
|
|
39
|
+
"""The Agent modules this needs, or None when one of them or one of their helpers is missing."""
|
|
40
|
+
import importlib
|
|
41
|
+
|
|
42
|
+
modules = {}
|
|
43
|
+
for name, attrs in _NEEDED.items():
|
|
44
|
+
try:
|
|
45
|
+
module = importlib.import_module(f"hermes_cli.{name}")
|
|
46
|
+
except ImportError:
|
|
47
|
+
return None
|
|
48
|
+
if not all(hasattr(module, attr) for attr in attrs):
|
|
49
|
+
return None
|
|
50
|
+
modules[name] = module
|
|
51
|
+
return types.SimpleNamespace(**modules)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _required() -> types.SimpleNamespace:
|
|
55
|
+
agent = _agent()
|
|
56
|
+
if agent is None:
|
|
57
|
+
raise RpcError("This Hermes Agent cannot sign in to plugin OAuth clients.", condition="oauth_unsupported")
|
|
58
|
+
return agent
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _hosts(client) -> dict:
|
|
62
|
+
"""The two hosts ``hermes auth add`` names before it signs in: the code is approved at one and exchanged at the other."""
|
|
63
|
+
return {"authorize_host": urlparse(client.authorize_url).hostname or "", "token_host": urlparse(client.token_url).hostname or ""}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _state(agent: types.SimpleNamespace, client, key: str) -> str:
|
|
67
|
+
"""``_cli_status``'s answer for one grant."""
|
|
68
|
+
row = agent.plugin_oauth._read_grant(key)
|
|
69
|
+
try:
|
|
70
|
+
agent.plugin_oauth._usable_grant(row, client, key)
|
|
71
|
+
except agent.plugin_provider_requests.ProviderNotSignedIn:
|
|
72
|
+
return "logged_out" if row is None else "revoked" if row.get("dead") else "sign_in_needed"
|
|
73
|
+
return "signed_in"
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def oauth_status() -> dict:
|
|
77
|
+
"""Every discovered plugin that declares OAuth clients, with each client's sign-in state."""
|
|
78
|
+
agent = _agent()
|
|
79
|
+
if agent is None:
|
|
80
|
+
return {"supported": False, "plugins": []}
|
|
81
|
+
rows = []
|
|
82
|
+
for _name, _version, _desc, _source, plugin_dir, key in agent.plugins_cmd._discover_all_plugins():
|
|
83
|
+
if not plugin_dir:
|
|
84
|
+
continue
|
|
85
|
+
directory = Path(str(plugin_dir))
|
|
86
|
+
try:
|
|
87
|
+
clients = agent.plugin_oauth._declared_clients(directory)
|
|
88
|
+
except ValueError: # a malformed oauth: block, which the Agent refuses to sign in to as well
|
|
89
|
+
log.warning("plugin %s declares an invalid oauth: block", key)
|
|
90
|
+
continue
|
|
91
|
+
if clients:
|
|
92
|
+
grant_base = agent.plugin_oauth.plugin_key(directory)
|
|
93
|
+
rows.append({"key": key, "clients": [{"id": c.id, "state": _state(agent, c, f"{grant_base}:{c.id}"), **_hosts(c)} for c in clients]})
|
|
94
|
+
return {"supported": True, "plugins": rows}
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def oauth_logout(key: str, oauth_id: str) -> dict:
|
|
98
|
+
"""``hermes auth logout <plugin>:<id>``: removes the stored grant, which needs no valid manifest entry."""
|
|
99
|
+
if not key or not oauth_id:
|
|
100
|
+
raise InvalidParams("plugins.oauth_logout requires 'key' and 'id'")
|
|
101
|
+
agent = _required()
|
|
102
|
+
grant = agent.plugin_oauth._logout_key(key, oauth_id)
|
|
103
|
+
if grant is not None:
|
|
104
|
+
agent.plugin_oauth._write_grant(grant, None)
|
|
105
|
+
return {"key": key, "id": oauth_id, "removed": grant is not None}
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
# ── the plugin:<key>:<id> flow kind for oauth.start ────────────────────
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def steps(provider: str):
|
|
112
|
+
"""``(begin, wait, save)`` for ``plugin:<key>:<id>``; None for every other provider."""
|
|
113
|
+
if not provider.startswith(PREFIX):
|
|
114
|
+
return None
|
|
115
|
+
plugin, _, oauth_id = provider[len(PREFIX):].rpartition(":")
|
|
116
|
+
if not plugin or not oauth_id:
|
|
117
|
+
raise InvalidParams("a plugin sign-in is 'plugin:<key>:<id>'")
|
|
118
|
+
return (lambda: _begin(plugin, oauth_id), _wait, _save)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def _begin(plugin: str, oauth_id: str) -> tuple[dict, dict]:
|
|
122
|
+
"""Bind the loopback listener and build the authorize link as ``login`` does; runs under the flow's home."""
|
|
123
|
+
agent = _required()
|
|
124
|
+
try:
|
|
125
|
+
found = agent.plugin_oauth._installed_client(plugin, oauth_id)
|
|
126
|
+
except ValueError as exc:
|
|
127
|
+
raise RpcError(str(exc), condition="oauth_failed") from exc
|
|
128
|
+
if found is None:
|
|
129
|
+
raise RpcError(f"Plugin '{plugin}' declares no OAuth client '{oauth_id}'.", condition="plugin_not_found")
|
|
130
|
+
plugin_dir, client = found
|
|
131
|
+
key = f"{agent.plugin_oauth.plugin_key(plugin_dir)}:{client.id}"
|
|
132
|
+
pkce, loopback = agent.auth_oauth_pkce_plugin, agent.auth_device_flow
|
|
133
|
+
cfg = agent.plugin_oauth._pkce_config(client, key)
|
|
134
|
+
pkce.validate_config(key, cfg)
|
|
135
|
+
path = cfg.redirect_path if cfg.redirect_path.startswith("/") else f"/{cfg.redirect_path}"
|
|
136
|
+
handler_cls, result = loopback._make_loopback_callback_handler(path, display_name=cfg.label or key)
|
|
137
|
+
server = loopback._bind_loopback_callback_server("127.0.0.1", int(cfg.redirect_port), handler_cls,
|
|
138
|
+
err=lambda message, code: pkce._err(key, message, code), bind_failed_code="oauth_callback_bind_failed")
|
|
139
|
+
port = server.server_address[1]
|
|
140
|
+
redirect_uri = f"http://127.0.0.1:{port}{path}"
|
|
141
|
+
verifier, state = loopback._pkce_code_verifier(), secrets.token_urlsafe(32)
|
|
142
|
+
params = {**cfg.extra_authorize_params, "client_id": cfg.client_id, "response_type": "code", "redirect_uri": redirect_uri, "state": state,
|
|
143
|
+
"code_challenge": loopback._pkce_code_challenge(verifier), "code_challenge_method": "S256"}
|
|
144
|
+
if cfg.scopes:
|
|
145
|
+
params["scope"] = " ".join(cfg.scopes)
|
|
146
|
+
if cfg.audience:
|
|
147
|
+
params["audience"] = cfg.audience
|
|
148
|
+
authorize_url = f"{cfg.authorize_url}{'&' if urlparse(cfg.authorize_url).query else '?'}{urlencode(params)}"
|
|
149
|
+
display = {"verification_url": authorize_url, "redirect_uri": redirect_uri, **_hosts(client), "expires_in": int(cfg.timeout_seconds), "interval": 2}
|
|
150
|
+
flow_state = {"agent": agent, "key": key, "client": client, "cfg": cfg, "server": server, "result": result, "port": port, "path": path,
|
|
151
|
+
"redirect_uri": redirect_uri, "verifier": verifier, "state": state, "answer_lock": threading.Lock(), "closed": threading.Event()}
|
|
152
|
+
flow_state["submit"] = lambda url: _submit(flow_state, url)
|
|
153
|
+
return display, flow_state
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def _submit(state: dict, url: str) -> None:
|
|
157
|
+
"""A pasted redirect address, delivered as the loopback listener would have received it."""
|
|
158
|
+
parsed = urlparse(str(url or "").strip())
|
|
159
|
+
try:
|
|
160
|
+
port = parsed.port
|
|
161
|
+
except ValueError:
|
|
162
|
+
port = None
|
|
163
|
+
if parsed.scheme != "http" or parsed.hostname != "127.0.0.1" or port != state["port"] or parsed.path != state["path"]:
|
|
164
|
+
raise RpcError("That is not the address this sign-in redirects to.", condition="oauth_redirect_invalid")
|
|
165
|
+
query = parse_qs(parsed.query)
|
|
166
|
+
if not (query.get("code") or query.get("error")):
|
|
167
|
+
raise RpcError("That address carries no sign-in answer.", condition="oauth_redirect_invalid")
|
|
168
|
+
result = state["result"]
|
|
169
|
+
with state["answer_lock"]:
|
|
170
|
+
if result["code"] or result["error"]:
|
|
171
|
+
return # the browser's own redirect already answered
|
|
172
|
+
# ``code`` and ``error`` go last: the waiting loop reads the answer once one of them is set.
|
|
173
|
+
for name in ("state", "error_description", "error", "code"):
|
|
174
|
+
result[name] = query.get(name, [None])[0]
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def _wait(flow, state: dict) -> dict:
|
|
178
|
+
from .oauth import _EXPIRED, _Stop
|
|
179
|
+
|
|
180
|
+
agent, server, result, key = state["agent"], state["server"], state["result"], state["key"]
|
|
181
|
+
pkce = agent.auth_oauth_pkce_plugin
|
|
182
|
+
thread = threading.Thread(target=server.serve_forever, kwargs={"poll_interval": 0.1}, daemon=True, name=f"oauth-loopback-{flow.flow_id[:6]}")
|
|
183
|
+
thread.start()
|
|
184
|
+
try:
|
|
185
|
+
# The Agent's ``_serve_loopback_callback`` cannot be stopped, so its loop runs here with the flow's cancel and deadline.
|
|
186
|
+
while not (result["code"] or result["error"]):
|
|
187
|
+
if flow.cancelled.wait(0.1):
|
|
188
|
+
raise _Stop()
|
|
189
|
+
if time.time() >= flow.expires_at:
|
|
190
|
+
raise TimeoutError(_EXPIRED)
|
|
191
|
+
finally:
|
|
192
|
+
# Once ``shutdown`` returns, a callback request in progress has finished writing the answer.
|
|
193
|
+
server.shutdown()
|
|
194
|
+
server.server_close()
|
|
195
|
+
thread.join(timeout=1.0)
|
|
196
|
+
state["closed"].set()
|
|
197
|
+
if flow.cancelled.is_set():
|
|
198
|
+
raise _Stop()
|
|
199
|
+
if result["error"]:
|
|
200
|
+
code = "access_denied" if result["error"] == "access_denied" else "oauth_authorization_denied"
|
|
201
|
+
raise pkce._err(key, f"authorization failed: {result.get('error_description') or result['error']}", code)
|
|
202
|
+
if not hmac.compare_digest(str(result.get("state") or ""), state["state"]):
|
|
203
|
+
raise pkce._err(key, "callback state mismatch — the redirect did not come from this login. Aborting.", "oauth_state_mismatch")
|
|
204
|
+
code = str(result.get("code") or "").strip()
|
|
205
|
+
if not code:
|
|
206
|
+
raise pkce._err(key, "callback carried no authorization code.", "oauth_no_code")
|
|
207
|
+
# The token request reads the client id (and secret) from the flow's profile at the moment it posts.
|
|
208
|
+
with scoped_home(flow.home):
|
|
209
|
+
return pkce._post_token(key, state["cfg"], {"grant_type": "authorization_code", "code": code, "redirect_uri": state["redirect_uri"],
|
|
210
|
+
"code_verifier": state["verifier"]}, code="oauth_token_exchange_failed")
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def _save(flow, state: dict, fields: dict) -> None:
|
|
214
|
+
state["agent"].plugin_oauth._write_grant(state["key"], {**fields, "fingerprint": state["client"].fingerprint})
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def discard(state: dict) -> None:
|
|
218
|
+
"""Close the listener of a begun sign-in that is never published."""
|
|
219
|
+
server = state.get("server")
|
|
220
|
+
if server is not None:
|
|
221
|
+
server.server_close()
|
|
222
|
+
state["closed"].set()
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def register(reg) -> None:
|
|
226
|
+
@reg.method("plugins.oauth_status")
|
|
227
|
+
def status_(ctx: CallContext, params: dict) -> dict:
|
|
228
|
+
with scoped_home(profile_home_param(params)):
|
|
229
|
+
return oauth_status()
|
|
230
|
+
|
|
231
|
+
@reg.method("plugins.oauth_logout")
|
|
232
|
+
def logout_(ctx: CallContext, params: dict) -> dict:
|
|
233
|
+
with scoped_home(profile_home_param(params)):
|
|
234
|
+
return oauth_logout(str(params.get("key") or "").strip(), str(params.get("id") or "").strip())
|
|
@@ -7,6 +7,7 @@ from __future__ import annotations
|
|
|
7
7
|
import json
|
|
8
8
|
import logging
|
|
9
9
|
import queue
|
|
10
|
+
import re
|
|
10
11
|
import sqlite3
|
|
11
12
|
import threading
|
|
12
13
|
import time
|
|
@@ -319,7 +320,7 @@ def claim_delivery(evt: dict, consumer: str) -> str | None:
|
|
|
319
320
|
home = Path(get_hermes_home()).resolve()
|
|
320
321
|
if evt.get("reconciliation_profile_home", str(home)) == str(home):
|
|
321
322
|
# A live queue copy can race the transcript-only consumer too. Recheck the same proof here.
|
|
322
|
-
transport = {"process_id", "consumed", "child_process", "restored", "reconciliation_profile_home"}
|
|
323
|
+
transport = {"process_id", "consumed", "child_process", "restored", "startup_replay", "reconciliation_profile_home"}
|
|
323
324
|
for candidate in _delivered_notifications(home, str(evt.get("delegation_id") or ""))[0]:
|
|
324
325
|
if {k: v for k, v in candidate.items() if k not in transport} == {k: v for k, v in evt.items() if k not in transport}:
|
|
325
326
|
return "" # Web's session receipt acknowledges this admission, not the Agent ledger.
|
|
@@ -449,7 +450,7 @@ def _live_delegations() -> dict[str, dict]:
|
|
|
449
450
|
items = list_async_delegations()
|
|
450
451
|
except Exception: # noqa: BLE001 - an Agent without the live registry reports from the ledger alone
|
|
451
452
|
return {}
|
|
452
|
-
return {str(i.get("delegation_id")):
|
|
453
|
+
return {str(i.get("delegation_id")): i for i in items if isinstance(i, dict) and i.get("delegation_id")}
|
|
453
454
|
|
|
454
455
|
|
|
455
456
|
def _owned_processes(session_ids: set[str]) -> list[dict]:
|
|
@@ -499,7 +500,7 @@ def _live_children() -> list[dict]:
|
|
|
499
500
|
return out
|
|
500
501
|
|
|
501
502
|
|
|
502
|
-
def _ledger_children(home: Path, owners: list[str]) -> list[dict]:
|
|
503
|
+
def _ledger_children(home: Path, owners: list[str], dispatched_at: float) -> list[dict]:
|
|
503
504
|
"""Finished subagents' own sessions in state.db: ``source = subagent`` rows tagged ``_delegate_from`` with their
|
|
504
505
|
parent's session, each with its start time and first user message (the child's goal, sent verbatim)."""
|
|
505
506
|
db_path = home / "state.db"
|
|
@@ -508,10 +509,11 @@ def _ledger_children(home: Path, owners: list[str]) -> list[dict]:
|
|
|
508
509
|
marks = ",".join("?" * len(owners))
|
|
509
510
|
with closing(sqlite3.connect(f"{db_path.resolve().as_uri()}?mode=ro", uri=True, timeout=5)) as conn:
|
|
510
511
|
try:
|
|
511
|
-
#
|
|
512
|
+
# Bound history before parsing owner JSON; allow 60 seconds of dispatch/start clock skew.
|
|
512
513
|
rows = conn.execute(
|
|
513
514
|
"SELECT s.id, s.model_config, s.started_at, (SELECT m.content FROM messages m WHERE m.session_id = s.id AND m.role = 'user' ORDER BY m.id LIMIT 1)"
|
|
514
|
-
f" FROM sessions s WHERE s.source = 'subagent' AND json_extract(s.model_config, '$._delegate_from') IN ({marks})",
|
|
515
|
+
f" FROM sessions s WHERE s.source = 'subagent' AND s.started_at >= ? AND json_extract(s.model_config, '$._delegate_from') IN ({marks})",
|
|
516
|
+
[dispatched_at - 60, *owners]).fetchall()
|
|
515
517
|
except sqlite3.OperationalError:
|
|
516
518
|
return []
|
|
517
519
|
out = []
|
|
@@ -583,7 +585,7 @@ def background_list(home: Path, session_ids: list[str]) -> dict:
|
|
|
583
585
|
live = _live_delegations()
|
|
584
586
|
delegations = _ledger_rows(home, session_ids)
|
|
585
587
|
live_children = _live_children()
|
|
586
|
-
finished = _ledger_children(home, session_ids) if delegations else []
|
|
588
|
+
finished = _ledger_children(home, session_ids, min(row["dispatched_at"] for row in delegations)) if delegations else []
|
|
587
589
|
now = time.time()
|
|
588
590
|
for row in delegations:
|
|
589
591
|
row["live_status"] = live.get(row["delegation_id"], {}).get("status")
|
|
@@ -630,6 +632,60 @@ def recover(base_home: Path) -> int:
|
|
|
630
632
|
return 1 + len(named)
|
|
631
633
|
|
|
632
634
|
|
|
635
|
+
def stop(home: Path, session_id: str, process_id: str) -> str:
|
|
636
|
+
"""Request cancellation only for work this profile/session owns; let Agent completions settle its row."""
|
|
637
|
+
registry = _registry()
|
|
638
|
+
proc = registry.get(process_id) if registry is not None else None
|
|
639
|
+
if proc is not None:
|
|
640
|
+
if str(getattr(proc, "session_key", "") or "") != session_id:
|
|
641
|
+
return "not_found"
|
|
642
|
+
if proc.exited:
|
|
643
|
+
return "not_running"
|
|
644
|
+
# Keep the completion visible to the parent, just like other autonomous exits.
|
|
645
|
+
result = registry.kill_process(process_id, consume_output=False)
|
|
646
|
+
if result.get("status") == "error" or result.get("error"):
|
|
647
|
+
raise RpcError(str(result.get("error") or "Process could not be stopped"))
|
|
648
|
+
if result.get("status") == "killed":
|
|
649
|
+
return "stopped"
|
|
650
|
+
if result.get("completion_reason") == "already_exited" or result.get("status") == "already_exited":
|
|
651
|
+
return "not_running"
|
|
652
|
+
raise RpcError("Process stop was not confirmed")
|
|
653
|
+
|
|
654
|
+
row = next((r for r in _ledger_rows(home, [session_id]) if r["delegation_id"] == process_id), None)
|
|
655
|
+
if row is None:
|
|
656
|
+
return "not_found"
|
|
657
|
+
if row["state"] not in {"running", "stalling", "finalizing"}:
|
|
658
|
+
return "not_running"
|
|
659
|
+
from tools.delegate_tool_registry import interrupt_subagent, list_active_subagents
|
|
660
|
+
|
|
661
|
+
live = _live_delegations().get(process_id)
|
|
662
|
+
if not live or live.get("origin_ui_session_id") != session_id:
|
|
663
|
+
return "not_running"
|
|
664
|
+
indexes = live.get("task_indexes")
|
|
665
|
+
# Independent-completion units are <call-id>-<unit-number>; slot_key is the first unit, not the call.
|
|
666
|
+
split = re.fullmatch(r"(.+)-[1-9][0-9]*", process_id) if indexes is not None else None
|
|
667
|
+
if indexes is not None and split is None:
|
|
668
|
+
raise RpcError("Delegation unit identity could not be confirmed")
|
|
669
|
+
call_id = split[1] if split else process_id
|
|
670
|
+
# The dispatch parent is the Agent execution id; compression can rotate it away from the stable Web id.
|
|
671
|
+
owner_id = live.get("parent_session_id") or session_id
|
|
672
|
+
|
|
673
|
+
def belongs(child: dict) -> bool:
|
|
674
|
+
if child.get("delegation_id") != call_id or child.get("owner_agent_session_id") != owner_id:
|
|
675
|
+
return False
|
|
676
|
+
# Split units share a call id; Agent subagent ids encode their original task index.
|
|
677
|
+
index = re.fullmatch(r"sa-(\d+)-[a-zA-Z0-9]+", str(child.get("subagent_id") or ""))
|
|
678
|
+
return indexes is None or (index is not None and int(index[1]) in indexes)
|
|
679
|
+
|
|
680
|
+
children = [r for r in list_active_subagents() if belongs(r)]
|
|
681
|
+
if not children:
|
|
682
|
+
return "not_running"
|
|
683
|
+
interrupted = [interrupt_subagent(r["subagent_id"]) for r in children]
|
|
684
|
+
if not all(interrupted):
|
|
685
|
+
raise RpcError("Some subagents could not be interrupted; refresh and retry")
|
|
686
|
+
return "stopped"
|
|
687
|
+
|
|
688
|
+
|
|
633
689
|
def register(registry_) -> None:
|
|
634
690
|
@registry_.method("process.drain")
|
|
635
691
|
def drain_(ctx: CallContext, params: dict) -> dict:
|
|
@@ -729,6 +785,14 @@ def register(registry_) -> None:
|
|
|
729
785
|
with scoped_home(profile_home_param(params)) as home:
|
|
730
786
|
return {"text": delegation_result(home, sid, did)}
|
|
731
787
|
|
|
788
|
+
@registry_.method("process.stop")
|
|
789
|
+
def stop_(ctx: CallContext, params: dict) -> dict:
|
|
790
|
+
sid, pid = params.get("session_id"), params.get("process_id")
|
|
791
|
+
if not isinstance(sid, str) or not sid.strip() or not isinstance(pid, str) or not pid.strip():
|
|
792
|
+
raise InvalidParams("session_id and process_id are required")
|
|
793
|
+
with scoped_home(profile_home_param(params)) as home:
|
|
794
|
+
return {"outcome": stop(home, sid, pid)}
|
|
795
|
+
|
|
732
796
|
@registry_.method("process.list")
|
|
733
797
|
def list_(ctx: CallContext, params: dict) -> dict:
|
|
734
798
|
with scoped_home(profile_home_param(params)):
|
|
@@ -352,10 +352,11 @@ def register(registry) -> None:
|
|
|
352
352
|
base_home, name = profile_home_param(params, "base_home"), str(params.get("name") or "").strip()
|
|
353
353
|
validate_name(name)
|
|
354
354
|
# Idle cached agents end their memory sessions while the profile's home still exists.
|
|
355
|
-
from .chat import release_profile_agents
|
|
355
|
+
from .chat import forget_profile_hooks, release_profile_agents
|
|
356
356
|
|
|
357
|
-
release_profile_agents(base_home / "profiles" / name)
|
|
358
|
-
|
|
357
|
+
with release_profile_agents(base_home / "profiles" / name):
|
|
358
|
+
forget_profile_hooks(base_home / "profiles" / name)
|
|
359
|
+
delete_profile(base_home, name)
|
|
359
360
|
return {"ok": True}
|
|
360
361
|
|
|
361
362
|
@registry.method("profiles.runtime_env")
|
|
@@ -39,6 +39,7 @@ def register(registry) -> None:
|
|
|
39
39
|
raise InvalidParams("agent_dir must match the sidecar's configured Agent checkout")
|
|
40
40
|
if not (root / "hermes_cli" / "venv_sync.py").is_file():
|
|
41
41
|
return {"ok": True, "skipped": True, "detail": ""}
|
|
42
|
+
runtime.retire()
|
|
42
43
|
env = _frozen_launch_env()
|
|
43
44
|
env.update(HERMES_HOME=str(runtime.hermes_home), HERMES_DISABLE_LAZY_INSTALLS="1",
|
|
44
45
|
PYTHONPATH=str(root) + (os.pathsep + env["PYTHONPATH"] if env.get("PYTHONPATH") else ""))
|
|
@@ -137,5 +138,6 @@ def register(registry) -> None:
|
|
|
137
138
|
|
|
138
139
|
close_all()
|
|
139
140
|
drain_agents()
|
|
141
|
+
runtime.retire()
|
|
140
142
|
ctx.server.request_shutdown(exit_code=code)
|
|
141
143
|
return {"ok": True}
|
|
@@ -19,6 +19,17 @@ from .profiles import disabled_skill_names
|
|
|
19
19
|
log = logging.getLogger("talaria_sidecar.skills")
|
|
20
20
|
|
|
21
21
|
|
|
22
|
+
def _skill_helper(name: str):
|
|
23
|
+
from tools import skills_tool
|
|
24
|
+
|
|
25
|
+
return getattr(skills_tool, name, None) or getattr(skills_tool, "_" + name, None)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _sort_skills(rows: list[dict]) -> list[dict]:
|
|
29
|
+
sort = _skill_helper("sort_skills")
|
|
30
|
+
return sort(rows) if sort else sorted(rows, key=lambda row: (row.get("category") or "", row["name"]))
|
|
31
|
+
|
|
32
|
+
|
|
22
33
|
def _within(base: Path, candidate: Path) -> bool:
|
|
23
34
|
try:
|
|
24
35
|
candidate.resolve().relative_to(base.resolve())
|
|
@@ -56,7 +67,7 @@ def _category(skill_md: Path, dirs: list[Path], local: Path) -> str | None:
|
|
|
56
67
|
def list_skills(profile_home: Path, category: str | None = None) -> dict:
|
|
57
68
|
try:
|
|
58
69
|
from agent.skill_utils import get_disabled_skill_names, is_disabled_entry
|
|
59
|
-
from tools.skills_tool import _skill_catalog
|
|
70
|
+
from tools.skills_tool import _skill_catalog
|
|
60
71
|
except ImportError:
|
|
61
72
|
return _legacy_list_skills(profile_home, category)
|
|
62
73
|
disabled = get_disabled_skill_names("webui")
|
|
@@ -76,7 +87,7 @@ def _legacy_list_skills(profile_home: Path, category: str | None = None) -> dict
|
|
|
76
87
|
skills_dir = profile_home / "skills"
|
|
77
88
|
try:
|
|
78
89
|
from agent.skill_utils import iter_skill_index_files
|
|
79
|
-
from tools.skills_tool import MAX_DESCRIPTION_LENGTH, _EXCLUDED_SKILL_DIRS, _parse_frontmatter,
|
|
90
|
+
from tools.skills_tool import MAX_DESCRIPTION_LENGTH, _EXCLUDED_SKILL_DIRS, _parse_frontmatter, skill_matches_platform
|
|
80
91
|
except ImportError:
|
|
81
92
|
return {"skills": [], "categories": [], "count": 0}
|
|
82
93
|
if not skills_dir.exists():
|
|
@@ -120,16 +131,20 @@ def _legacy_list_skills(profile_home: Path, category: str | None = None) -> dict
|
|
|
120
131
|
def find_skill(name: str, dirs: list[Path]) -> tuple[Path | None, Path | None]:
|
|
121
132
|
try:
|
|
122
133
|
from agent.skill_utils import resolve_skill_catalog # noqa: F401 - capability gate for the matching lookup API
|
|
123
|
-
|
|
134
|
+
locate_skill = _skill_helper("locate_skill")
|
|
135
|
+
skill_lookup_path_error = _skill_helper("skill_lookup_path_error")
|
|
136
|
+
skill_search_dirs = _skill_helper("skill_search_dirs")
|
|
124
137
|
except ImportError:
|
|
125
138
|
return _legacy_find_skill(name, dirs)
|
|
126
|
-
if
|
|
139
|
+
if not all((locate_skill, skill_lookup_path_error, skill_search_dirs)):
|
|
140
|
+
return _legacy_find_skill(name, dirs)
|
|
141
|
+
if error := skill_lookup_path_error(name):
|
|
127
142
|
raise InvalidParams(error)
|
|
128
143
|
local_name = name.replace(":", "/", 1) if ":" in name else None
|
|
129
|
-
if local_name and (error :=
|
|
144
|
+
if local_name and (error := skill_lookup_path_error(local_name)):
|
|
130
145
|
raise InvalidParams(error)
|
|
131
|
-
roots, _ =
|
|
132
|
-
error, skill_dir, skill_md =
|
|
146
|
+
roots, _ = skill_search_dirs()
|
|
147
|
+
error, skill_dir, skill_md = locate_skill(name, local_name, roots)
|
|
133
148
|
if error:
|
|
134
149
|
result = json.loads(error)
|
|
135
150
|
if result.get("matches"):
|