@maudecode/talaria-web 1.19.0 → 1.20.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 +8 -6
- package/dist/api/automation-router.js +7 -1
- package/dist/api/automation-router.js.map +1 -1
- package/dist/api/chat-router.d.ts +258 -33
- package/dist/api/chat-router.js +60 -25
- package/dist/api/chat-router.js.map +1 -1
- package/dist/api/git-router.d.ts +4 -0
- package/dist/api/git-router.js +1 -1
- 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 +2 -2
- package/dist/api/session-visibility.js +2 -2
- package/dist/api/session-visibility.js.map +1 -1
- package/dist/api/sessions-router.d.ts +787 -107
- package/dist/api/sessions-router.js +16 -4
- 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 +41 -19
- package/dist/api/sse-routes.js.map +1 -1
- package/dist/api/tools-router.d.ts +314 -32
- package/dist/api/tools-router.js +135 -38
- 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 +14 -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.js +38 -14
- package/dist/redact.js.map +1 -1
- package/dist/release.js +5 -3
- package/dist/release.js.map +1 -1
- package/dist/runtime.js +85 -21
- package/dist/runtime.js.map +1 -1
- package/dist/server.js +24 -21
- package/dist/server.js.map +1 -1
- package/dist/sessions/anchor.d.ts +2 -1
- package/dist/sessions/anchor.js +5 -1
- package/dist/sessions/anchor.js.map +1 -1
- package/dist/sessions/background-tasks.d.ts +23 -3
- package/dist/sessions/background-tasks.js +74 -4
- 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/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 +44 -4
- package/dist/sessions/gateway-sessions.js +626 -90
- 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 +11 -5
- package/dist/sessions/merge.js +59 -17
- package/dist/sessions/merge.js.map +1 -1
- package/dist/sessions/prefix-index.d.ts +7 -4
- package/dist/sessions/prefix-index.js +21 -10
- package/dist/sessions/prefix-index.js.map +1 -1
- 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/service.d.ts +107 -37
- package/dist/sessions/service.js +490 -156
- package/dist/sessions/service.js.map +1 -1
- package/dist/sessions/session.d.ts +2 -0
- package/dist/sessions/session.js +4 -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 +70 -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 +5 -1
- package/dist/sessions/store.js +67 -27
- package/dist/sessions/store.js.map +1 -1
- package/dist/sessions/streams.d.ts +8 -7
- package/dist/sessions/streams.js +49 -14
- package/dist/sessions/streams.js.map +1 -1
- package/dist/sessions/tool-display.d.ts +3 -1
- package/dist/sessions/tool-display.js +6 -0
- 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 +23 -5
- package/dist/sessions/turn.js +168 -78
- 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/mcp-health.js +74 -24
- package/dist/tools/mcp-health.js.map +1 -1
- package/dist/tools/mcp.js +19 -1
- package/dist/tools/mcp.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 +73 -7
- package/dist/tools/update-notifications.js +277 -43
- package/dist/tools/update-notifications.js.map +1 -1
- package/dist/tools/updates.d.ts +8 -1
- package/dist/tools/updates.js +51 -17
- package/dist/tools/updates.js.map +1 -1
- 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 +17 -7
- 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 +17 -14
- 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 +159 -23
- package/sidecar/talaria_sidecar/agent_services.py +74 -11
- 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 +211 -27
- package/sidecar/talaria_sidecar/methods/kanban.py +2 -3
- package/sidecar/talaria_sidecar/methods/oauth.py +139 -11
- 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 +241 -213
- package/static/dist/THIRD_PARTY_LICENSES.md +6 -22
- package/static/dist/assets/AppShell-3isgvoro.js +8 -0
- package/static/dist/assets/Button-f4n6dapf.js +1 -0
- package/static/dist/assets/ChatPage-k7b6xfax.js +4 -0
- package/static/dist/assets/ConnectTargets-juqvt5lm.js +1 -0
- package/static/dist/assets/Dialog-hta5utr3.js +1 -0
- package/static/dist/assets/ExtensionRoute-zrhjn0wm.js +1 -0
- package/static/dist/assets/Field-b6ez48oz.js +1 -0
- package/static/dist/assets/HubRoute-iwvso2tz.js +2 -0
- package/static/dist/assets/LinkCheckContext-ix6zqqkk.js +1 -0
- package/static/dist/assets/Markdown-jdeth7zq.js +2 -0
- package/static/dist/assets/MarkdownRenderer-fbswsgld.js +302 -0
- package/static/dist/assets/MarkdownRenderer-i9o6nr38.css +1 -0
- package/static/dist/assets/OAuthSignIn-bpd8hom3.js +1 -0
- package/static/dist/assets/ResourceSwitch-odi6dy2o.js +1 -0
- package/static/dist/assets/RightPanel-eu6enlo6.js +1 -0
- package/static/dist/assets/Select-kr07928w.js +1 -0
- package/static/dist/assets/SessionListPanel-etb2i54l.js +1 -0
- package/static/dist/assets/SettingsLayout-eu3xxp23.js +1 -0
- package/static/dist/assets/States-icab19yg.js +1 -0
- package/static/dist/assets/TerminalPanel-hngmsr8b.js +16 -0
- package/static/dist/assets/Toaster-nb2uzjw1.js +1 -0
- package/static/dist/assets/_app-ga1moszl.js +1 -0
- package/static/dist/assets/_app.ext._extensionId-na62087t.js +1 -0
- package/static/dist/assets/_app.index-jypgdqoi.js +1 -0
- package/static/dist/assets/_app.insights-kabejdtm.js +1 -0
- package/static/dist/assets/_app.kanban-m19kfcmx.js +1 -0
- package/static/dist/assets/_app.logs-iw4m96sz.js +1 -0
- package/static/dist/assets/_app.memory-jq5frwcg.js +1 -0
- package/static/dist/assets/_app.profiles-kwa3m7rp.js +1 -0
- package/static/dist/assets/_app.session._sessionId-o5lyeipj.js +1 -0
- package/static/dist/assets/_app.settings-ckl8hdll.js +1 -0
- package/static/dist/assets/_app.settings._section-dtdjk98a.js +3 -0
- package/static/dist/assets/_app.skills-n016rihd.js +1 -0
- package/static/dist/assets/_app.tasks-n8zuqsqe.js +1 -0
- package/static/dist/assets/_app.todos-btew5v2s.js +1 -0
- package/static/dist/assets/_app.workspaces-lnfk95ch.js +1 -0
- package/static/dist/assets/abnfDiagram-VCTEODGH-dttheegb.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-ic435919.js +1 -0
- package/static/dist/assets/architectureDiagram-5GKGNRK7-8r3glgiq.js +36 -0
- package/static/dist/assets/archive-il7c6053.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-jenyos6c.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-nzlx7yc4.js} +1 -1
- package/static/dist/assets/cancel-bsnfo36u.js +1 -0
- package/static/dist/assets/channel-dsbtk01y.js +1 -0
- package/static/dist/assets/{chunk-4HAMMTFA-koouqbut.js → chunk-4HAMMTFA-g0cru63b.js} +20 -20
- package/static/dist/assets/{chunk-75Z2AOVW-bl4bhdnt.js → chunk-75Z2AOVW-7rkswkjw.js} +1 -1
- package/static/dist/assets/chunk-DU6HZSFF-fn73jzdo.js +128 -0
- package/static/dist/assets/{chunk-F27PBJKO-d8xxi0zi.js → chunk-F27PBJKO-oey8e72m.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-l2a32wiy.js} +6 -6
- package/static/dist/assets/{chunk-GVQU2GXP-djn6gbyu.js → chunk-GVQU2GXP-o9dwzh8h.js} +1 -1
- package/static/dist/assets/{chunk-IMKFNOWR-vw4p5p7o.js → chunk-IMKFNOWR-eblwj20b.js} +5 -5
- package/static/dist/assets/{chunk-L3NEJ4N5-n1hj77q8.js → chunk-L3NEJ4N5-o2mufspb.js} +1 -1
- package/static/dist/assets/chunk-OSK3NFVY-ijp9pw29.js +10 -0
- package/static/dist/assets/{chunk-P2QGCYS3-onf1hz6c.js → chunk-P2QGCYS3-hs9hqwl4.js} +1 -1
- package/static/dist/assets/{chunk-POPQ4Y6H-m8sqn7cs.js → chunk-POPQ4Y6H-bp9rsqez.js} +1 -1
- package/static/dist/assets/{chunk-PWAF6VOD-ek4smc8x.js → chunk-PWAF6VOD-brkprov6.js} +1 -1
- package/static/dist/assets/{chunk-SHT3W25Y-g9gfvefo.js → chunk-SHT3W25Y-gmpv0pxz.js} +13 -13
- package/static/dist/assets/{chunk-SVP7TREG-f9nfv2cu.js → chunk-SVP7TREG-oldm08fu.js} +4 -4
- package/static/dist/assets/{chunk-TICWLB2K-bnk3m1mq.js → chunk-TICWLB2K-ooqilfv7.js} +6 -6
- package/static/dist/assets/{chunk-XXDRQBXY-n40pf9vy.js → chunk-XXDRQBXY-jkmnqu65.js} +1 -1
- package/static/dist/assets/classDiagram-ZZMXUADV-fvgcv24g.js +1 -0
- package/static/dist/assets/classDiagram-v2-VYDZK3BY-fvgcv24g.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/copied-bz3gkazh.js +1 -0
- package/static/dist/assets/copy-jo006coq.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-d47op7qs.js +1 -0
- package/static/dist/assets/cynefinDiagram-5FMLGOSQ-doa7594y.js +62 -0
- package/static/dist/assets/cytoscape.esm-fjn2algp.js +321 -0
- package/static/dist/assets/dagre-GXQ25YYZ-os768dp4.js +4 -0
- package/static/dist/assets/dagre-o5jmjz46.js +1 -0
- package/static/dist/assets/{diagram-S7CK7UJ4-m6aeoe7c.js → diagram-S7CK7UJ4-fyi81nxd.js} +4 -4
- package/static/dist/assets/diagram-UQ7AKVKN-j3exggaq.js +41 -0
- package/static/dist/assets/{diagram-VSXAHHWV-hbawi7hn.js → diagram-VSXAHHWV-omo1en2l.js} +1 -1
- package/static/dist/assets/diagram-VX7I27RA-oro2cyu0.js +24 -0
- package/static/dist/assets/diagram-Z3DM3KII-byt9vdb7.js +24 -0
- package/static/dist/assets/dist-crc46di9.js +7 -0
- package/static/dist/assets/dist-etpoyscq.js +44 -0
- package/static/dist/assets/{dist-c4c2m3kv.js → dist-nb670eu6.js} +1 -1
- package/static/dist/assets/ebnfDiagram-PWID7BFC-ee3haugh.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-d1e93yff.js +99 -0
- package/static/dist/assets/{erb-idlyfheg.js → erb-flwsv146.js} +1 -1
- package/static/dist/assets/eventmodeling-NTZA5JFV-i1ihb40c.js +1 -0
- package/static/dist/assets/flowDiagram-HODETNUW-jahfpiod.js +1 -0
- package/static/dist/assets/folder-plus-ivoglq98.js +1 -0
- package/static/dist/assets/{ganttDiagram-EL5Y4UJY-ma6jxj5i.js → ganttDiagram-EL5Y4UJY-m7g0jud4.js} +1 -1
- package/static/dist/assets/{git-rebase-d9lpfpbn.js → git-rebase-bli19aoq.js} +1 -1
- package/static/dist/assets/gitGraph-4MIJSDKK-hzdj07yy.js +1 -0
- package/static/dist/assets/{gitGraphDiagram-WWUBYQGX-hzltvsod.js → gitGraphDiagram-WWUBYQGX-dm9agbna.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-mmgz2czu.js +1 -0
- package/static/dist/assets/host-fr6lni1p.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-73649w7o.js +10 -0
- package/static/dist/assets/index-lhf1fsdf.css +2 -0
- package/static/dist/assets/info-A6RAGUB7-lll1dqmm.js +1 -0
- package/static/dist/assets/infoDiagram-27XIBGKW-k7esc639.js +2 -0
- package/static/dist/assets/{ishikawaDiagram-5VMMS53U-e7bnwq7h.js → ishikawaDiagram-5VMMS53U-lgr6k9wo.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-ndmbxuqk.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-mjxym0jp.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-cwb6l7xh.js +1 -0
- package/static/dist/assets/{line-h0ojzsvs.js → line-mtr5k6il.js} +1 -1
- package/static/dist/assets/linear-jlwrvvy6.js +1 -0
- package/static/dist/assets/link-iadw4ghw.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-lkhtzfcl.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-jx0q5dm2.js +1 -0
- package/static/dist/assets/mermaid-parser.core-k91vdnvi.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-ehztfea4.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-f67z0a2r.js +1 -0
- package/static/dist/assets/packet-AYTQ26CC-ok2xrblz.js +1 -0
- package/static/dist/assets/pegDiagram-XKGWAZYB-ec3rpj0m.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-iwkir23u.js +1 -0
- package/static/dist/assets/pieDiagram-E7YTZNPT-fcpqpekh.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-lqsync43.js} +1 -1
- package/static/dist/assets/queryKeys-ed4n2egc.js +9 -0
- package/static/dist/assets/{r-o3r9c7ao.js → r-epfzuw6q.js} +1 -1
- package/static/dist/assets/radar-RG4KPBEZ-hje4jbk6.js +1 -0
- package/static/dist/assets/railroad-74A4TZTK-gll9n6qi.js +1 -0
- package/static/dist/assets/railroad-abnf-HS5TGJTU-o6h6lpn4.js +1 -0
- package/static/dist/assets/railroad-ebnf-LZEXJU2U-juaefj6o.js +1 -0
- package/static/dist/assets/railroad-peg-WCYAUIDC-cgfhvpah.js +1 -0
- package/static/dist/assets/railroadDiagram-O6MQD6OU-lp3w7awf.js +1 -0
- package/static/dist/assets/{razor-ilc585yr.js → razor-pea1u1d0.js} +1 -1
- package/static/dist/assets/refresh-cw-iccm7a4e.js +1 -0
- package/static/dist/assets/refresh-i9ya9dvl.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-ha8eibcf.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-oxf31pr9.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-jiq8lhyo.js} +11 -11
- package/static/dist/assets/settings_section_extensions_title-fadc7o65.js +1 -0
- package/static/dist/assets/share._token-o76ki0ly.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-ddcs88av.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-f3fslnon.js +1 -0
- package/static/dist/assets/stateDiagram-v2-MP3YSRHH-hlt6yphw.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-k1hmk7jf.js +1 -0
- package/static/dist/assets/swimlanesDiagram-VR7AAH4N-hd5t9tnt.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-n3ncfy9r.js} +8 -8
- package/static/dist/assets/toast-liparz2j.js +56 -0
- package/static/dist/assets/treeView-Q6P3EWNA-l3y2pejt.js +1 -0
- package/static/dist/assets/treemap-WGGIJYW6-jown9axh.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-o4uu74mx.js +1 -0
- package/static/dist/assets/{useParams-gjc70qru.js → useParams-ftsveu84.js} +1 -1
- package/static/dist/assets/{useSearch-e6ae539u.js → useSearch-crqueqga.js} +1 -1
- package/static/dist/assets/vennDiagram-4TSXK5OY-dh59uq1c.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-e6d74b0j.js +1 -0
- package/static/dist/assets/wardleyDiagram-VM6X3IG4-hnofh78f.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-bpymjelb.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,5 @@
|
|
|
1
|
-
"""``oauth.*``: the Agent's device-code sign-ins for Nous Portal, OpenAI Codex, xAI and MiniMax (TAL-398)
|
|
1
|
+
"""``oauth.*``: the Agent's device-code sign-ins for Nous Portal, OpenAI Codex, xAI and MiniMax (TAL-398), and the
|
|
2
|
+
browser sign-in of a plugin-declared OAuth client (``plugin:<key>:<id>``, TAL-1276, in ``plugin_oauth``).
|
|
2
3
|
|
|
3
4
|
``oauth.start`` asks the provider for a code and answers what the user has to see; a daemon thread then waits for the
|
|
4
5
|
approval and saves the credential with the Agent's own auth-store helpers under the flow's profile home, the steps its
|
|
@@ -9,9 +10,12 @@ Flows live in this process only.
|
|
|
9
10
|
|
|
10
11
|
from __future__ import annotations
|
|
11
12
|
|
|
13
|
+
import contextlib
|
|
14
|
+
import inspect
|
|
12
15
|
import logging
|
|
13
16
|
import os
|
|
14
17
|
import secrets
|
|
18
|
+
import ssl
|
|
15
19
|
import threading
|
|
16
20
|
import time
|
|
17
21
|
from dataclasses import dataclass, field
|
|
@@ -22,6 +26,7 @@ from typing import Any, Callable
|
|
|
22
26
|
from ..errors import InvalidParams, RpcError
|
|
23
27
|
from ..home import profile_home_param, scoped_home
|
|
24
28
|
from ..rpc import CallContext
|
|
29
|
+
from . import plugin_oauth
|
|
25
30
|
|
|
26
31
|
log = logging.getLogger("talaria_sidecar.oauth")
|
|
27
32
|
|
|
@@ -31,6 +36,8 @@ _CODEX_EXPIRES_IN = 15 * 60 # OpenAI's device-code lifetime, as the Agent dashb
|
|
|
31
36
|
_ENDED_TTL = 10 * 60
|
|
32
37
|
# A pending flow past its code's expiry by this much ends expired even if its provider call has not returned yet.
|
|
33
38
|
_EXPIRY_GRACE = 60
|
|
39
|
+
# How long a start waits for the flows it replaces to close their loopback listeners.
|
|
40
|
+
_RELEASE_WAIT = 5.0
|
|
34
41
|
|
|
35
42
|
_DENIED = "Sign-in was declined."
|
|
36
43
|
_EXPIRED = "The sign-in code expired before it was approved."
|
|
@@ -55,6 +62,17 @@ class Flow:
|
|
|
55
62
|
cancelled: threading.Event = field(default_factory=threading.Event)
|
|
56
63
|
# Serialises the cancel check with the credential save: a cancel cannot land between them.
|
|
57
64
|
lock: threading.Lock = field(default_factory=threading.Lock)
|
|
65
|
+
# The credential is saved but the sign-in has not finished (a guest sign-in still settles the account): a cancel or
|
|
66
|
+
# an expiry can no longer undo it, and the flow stays pending until its own ending.
|
|
67
|
+
committed: bool = False
|
|
68
|
+
# A browser sign-in also finishes from the redirect address the user pastes (``oauth.submit_redirect``).
|
|
69
|
+
submit: Callable[[str], None] | None = None
|
|
70
|
+
# Set once a browser sign-in's loopback listener is closed, so a replacing start can bind the same fixed port.
|
|
71
|
+
closed: threading.Event | None = None
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def stoppable(self) -> bool:
|
|
75
|
+
return self.status == "pending" and not self.committed
|
|
58
76
|
|
|
59
77
|
def end(self, status: str, error: str | None = None) -> None:
|
|
60
78
|
self.status, self.error, self.ended_at = status, error, time.time()
|
|
@@ -107,9 +125,24 @@ def _now_z() -> str:
|
|
|
107
125
|
|
|
108
126
|
|
|
109
127
|
def _client(timeout: float, **kwargs: Any) -> Any:
|
|
128
|
+
"""Every flow's HTTP client, verifying TLS as the Agent's own sign-in does: the OS trust store, and (v0.22.3+) a
|
|
129
|
+
certifi bundle an install-environment rotation deleted under this process, re-derived process-wide."""
|
|
110
130
|
import httpx
|
|
111
131
|
|
|
112
|
-
return httpx.Client(timeout=httpx.Timeout(timeout), headers={"Accept": "application/json"}, **kwargs)
|
|
132
|
+
return httpx.Client(timeout=httpx.Timeout(timeout), headers={"Accept": "application/json"}, verify=_verify(), **kwargs)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def _verify() -> Any:
|
|
136
|
+
try:
|
|
137
|
+
from agent.ssl_verify import resolve_httpx_verify
|
|
138
|
+
except ImportError: # an Agent without it keeps httpx's default
|
|
139
|
+
return True
|
|
140
|
+
verify = resolve_httpx_verify()
|
|
141
|
+
# The resolver hands over the platform store alone when SSL_CERT_FILE/SSL_CERT_DIR is set; httpx's default trusted
|
|
142
|
+
# that bundle, so keep it, on top of the platform store the resolver installed (as ``platform_ssl_context`` does).
|
|
143
|
+
cafile, capath = os.environ.get("SSL_CERT_FILE", "").strip(), os.environ.get("SSL_CERT_DIR", "").strip()
|
|
144
|
+
cafile, capath = (cafile if os.path.isfile(cafile) else None), (capath if os.path.isdir(capath) else None)
|
|
145
|
+
return ssl.create_default_context(cafile=cafile, capath=capath) if cafile or capath else verify
|
|
113
146
|
|
|
114
147
|
|
|
115
148
|
# ── providers: (begin, wait, save) over the Agent's own steps ──────────
|
|
@@ -124,8 +157,9 @@ def _nous_begin() -> tuple[dict, dict]:
|
|
|
124
157
|
# v0.22.0 replaced ``guest_enabled`` with ``guest_allowed``; 0.21.x releases only have the former.
|
|
125
158
|
guest_gate = getattr(anon_auth, "guest_allowed", None) or getattr(anon_auth, "guest_enabled")
|
|
126
159
|
if guest_gate() and anon_auth.has_guest():
|
|
127
|
-
# The
|
|
128
|
-
|
|
160
|
+
# The native sign-in owns the guest's connector handoff for its installed protocol.
|
|
161
|
+
if hasattr(anon_auth, "run_sign_in"):
|
|
162
|
+
return _nous_sign_in(anon_auth)
|
|
129
163
|
hint = getattr(anon_auth, "UPGRADE_HINT", None) or "Sign in from Hermes with `hermes auth upgrade`."
|
|
130
164
|
raise RpcError(f"This profile uses the Nous free tier. {hint}", condition="oauth_unsupported")
|
|
131
165
|
pconfig = PROVIDER_REGISTRY["nous"]
|
|
@@ -136,7 +170,63 @@ def _nous_begin() -> tuple[dict, dict]:
|
|
|
136
170
|
return display, {"portal": portal, "client_id": pconfig.client_id, "scope": pconfig.scope, "device_code": str(data["device_code"])}
|
|
137
171
|
|
|
138
172
|
|
|
173
|
+
def _nous_sign_in(anon_auth: Any) -> tuple[dict, dict]:
|
|
174
|
+
"""Over a guest, the Agent's own sign-in (``anon_auth.run_sign_in``, as its dashboard runs it): it moves the guest's
|
|
175
|
+
connected apps to the account, then persists and settles the account itself. Its cancel check, persist guard and
|
|
176
|
+
home scope read the flow ``_nous_wait`` binds into the state; before that only ``start``'s first step runs, already
|
|
177
|
+
under the flow's home."""
|
|
178
|
+
state: dict = {}
|
|
179
|
+
|
|
180
|
+
def cancelled() -> bool:
|
|
181
|
+
flow = state.get("flow")
|
|
182
|
+
return flow is not None and flow.cancelled.is_set()
|
|
183
|
+
|
|
184
|
+
@contextlib.contextmanager
|
|
185
|
+
def persist_guard():
|
|
186
|
+
# As ``_run`` does for a plain save, the final cancel check and the save share the flow's lock; the flow ends
|
|
187
|
+
# approved only when the Agent has also settled the account, through ``_run``.
|
|
188
|
+
flow = state["flow"]
|
|
189
|
+
with flow.lock:
|
|
190
|
+
may_persist = flow.status == "pending"
|
|
191
|
+
yield may_persist
|
|
192
|
+
if may_persist:
|
|
193
|
+
flow.committed = True
|
|
194
|
+
|
|
195
|
+
def scope():
|
|
196
|
+
flow = state.get("flow")
|
|
197
|
+
return scoped_home(flow.home) if flow is not None else contextlib.nullcontext()
|
|
198
|
+
|
|
199
|
+
# Older Agents use promotion; v0.22.5 removed its option in favor of plain device login and native handoff.
|
|
200
|
+
options = {"cancel_wins_after_promotion": True} if "cancel_wins_after_promotion" in inspect.signature(anon_auth.run_sign_in).parameters else {}
|
|
201
|
+
sign_in = anon_auth.run_sign_in(cancelled=cancelled, persist_guard=persist_guard, scope=scope, **options)
|
|
202
|
+
first = next(sign_in)
|
|
203
|
+
if first.kind != "code":
|
|
204
|
+
sign_in.close()
|
|
205
|
+
raise RpcError(first.copy_terminal, condition="oauth_unsupported" if first.precondition else "oauth_failed")
|
|
206
|
+
state["sign_in"] = sign_in
|
|
207
|
+
return {"user_code": first.code, "verification_url": first.link, "expires_in": first.expires_in, "interval": first.interval}, state
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
class _SignInEnded(Exception):
|
|
211
|
+
"""A guest sign-in that ended without an account; ``code`` lets ``_ending`` classify a decline and an expiry."""
|
|
212
|
+
|
|
213
|
+
def __init__(self, ended: Any):
|
|
214
|
+
super().__init__(ended.copy)
|
|
215
|
+
self.code = {"declined": "access_denied", "timed_out": "expired_token"}.get(ended.kind, ended.kind)
|
|
216
|
+
|
|
217
|
+
|
|
139
218
|
def _nous_wait(flow: Flow, state: dict) -> dict:
|
|
219
|
+
sign_in = state.get("sign_in")
|
|
220
|
+
if sign_in is not None:
|
|
221
|
+
state["flow"] = flow
|
|
222
|
+
try:
|
|
223
|
+
for ended in sign_in: # the generator always ends on one terminal state
|
|
224
|
+
pass
|
|
225
|
+
finally:
|
|
226
|
+
sign_in.close()
|
|
227
|
+
if not ended.ok:
|
|
228
|
+
raise _SignInEnded(ended)
|
|
229
|
+
return {}
|
|
140
230
|
from hermes_cli.auth import _poll_for_token
|
|
141
231
|
|
|
142
232
|
with _client(15.0) as client:
|
|
@@ -145,6 +235,8 @@ def _nous_wait(flow: Flow, state: dict) -> dict:
|
|
|
145
235
|
|
|
146
236
|
|
|
147
237
|
def _nous_save(flow: Flow, state: dict, token_data: dict) -> None:
|
|
238
|
+
if "sign_in" in state: # the guest sign-in persisted and settled the account itself
|
|
239
|
+
return
|
|
148
240
|
from hermes_cli import anon_auth
|
|
149
241
|
from hermes_cli.auth import persist_nous_credentials, refresh_nous_oauth_from_state
|
|
150
242
|
|
|
@@ -213,8 +305,10 @@ def _codex_save(flow: Flow, state: dict, tokens: dict) -> None:
|
|
|
213
305
|
def _xai_begin() -> tuple[dict, dict]:
|
|
214
306
|
from hermes_cli.auth import _xai_oauth_discovery, _xai_oauth_request_device_code
|
|
215
307
|
|
|
216
|
-
discovery = _xai_oauth_discovery(20.0)
|
|
217
308
|
with _client(20.0) as client:
|
|
309
|
+
# The Agent's discovery is a bare ``httpx.get``: building the client first gives it the platform store and a
|
|
310
|
+
# certifi re-derived after a rotation.
|
|
311
|
+
discovery = _xai_oauth_discovery(20.0)
|
|
218
312
|
data = _xai_oauth_request_device_code(client)
|
|
219
313
|
display = {"user_code": str(data["user_code"]), "verification_url": str(data.get("verification_uri_complete") or data["verification_uri"]),
|
|
220
314
|
"expires_in": int(data["expires_in"]), "interval": int(data["interval"])}
|
|
@@ -323,9 +417,16 @@ def _run(flow: Flow, wait: Callable[[Flow, dict], dict], save: Callable[[Flow, d
|
|
|
323
417
|
log.info("oauth: %s sign-in ended %s (flow=%s)", flow.provider, flow.status, flow.flow_id[:6])
|
|
324
418
|
|
|
325
419
|
|
|
420
|
+
def _discard(state: dict) -> None:
|
|
421
|
+
"""Releases a begun sign-in that is never published: a guest sign-in's generator holds its HTTP client."""
|
|
422
|
+
if "sign_in" in state:
|
|
423
|
+
state["sign_in"].close()
|
|
424
|
+
plugin_oauth.discard(state)
|
|
425
|
+
|
|
426
|
+
|
|
326
427
|
def _cancel(flow: Flow) -> None:
|
|
327
428
|
with flow.lock:
|
|
328
|
-
if flow.
|
|
429
|
+
if flow.stoppable:
|
|
329
430
|
flow.cancelled.set()
|
|
330
431
|
flow.end("cancelled")
|
|
331
432
|
|
|
@@ -357,7 +458,7 @@ def _pending(home: Path, provider: str) -> list[Flow]:
|
|
|
357
458
|
|
|
358
459
|
|
|
359
460
|
def start(home: Path, provider: str, *, providers: dict[str, Provider] | None = None) -> dict:
|
|
360
|
-
steps = (providers or PROVIDERS).get(provider)
|
|
461
|
+
steps = (providers or PROVIDERS).get(provider) or plugin_oauth.steps(provider)
|
|
361
462
|
if steps is None:
|
|
362
463
|
raise InvalidParams(f"{provider} has no device-code sign-in")
|
|
363
464
|
begin, wait, save = steps
|
|
@@ -369,6 +470,11 @@ def start(home: Path, provider: str, *, providers: dict[str, Provider] | None =
|
|
|
369
470
|
# old code that lands while the provider answers can no longer save.
|
|
370
471
|
for old in _pending(home, provider):
|
|
371
472
|
_cancel(old)
|
|
473
|
+
# A cancelled browser sign-in closes its listener from its own thread; a fixed redirect port is free only after that.
|
|
474
|
+
with _FLOWS_LOCK:
|
|
475
|
+
listening = [f for f in _FLOWS.values() if f.provider == provider and f.closed is not None and not f.closed.is_set() and _same_home(f.home, home)]
|
|
476
|
+
for old in listening:
|
|
477
|
+
old.closed.wait(_RELEASE_WAIT)
|
|
372
478
|
try:
|
|
373
479
|
with scoped_home(home):
|
|
374
480
|
display, state = begin()
|
|
@@ -379,11 +485,13 @@ def start(home: Path, provider: str, *, providers: dict[str, Provider] | None =
|
|
|
379
485
|
raise RpcError(_first_line(exc), condition="oauth_failed") from exc
|
|
380
486
|
if not str(display["verification_url"]).lower().startswith(("https://", "http://")):
|
|
381
487
|
# The browser opens this link: anything but a web address is refused before a flow exists.
|
|
488
|
+
_discard(state)
|
|
382
489
|
raise RpcError("The provider answered an invalid sign-in link.", condition="oauth_failed")
|
|
383
|
-
flow = Flow(secrets.token_urlsafe(16), provider, home, time.time() + int(display["expires_in"]), max(1, int(display["interval"])))
|
|
490
|
+
flow = Flow(secrets.token_urlsafe(16), provider, home, time.time() + int(display["expires_in"]), max(1, int(display["interval"])), submit=state.get("submit"), closed=state.get("closed"))
|
|
384
491
|
with _FLOWS_LOCK:
|
|
385
492
|
if _GENERATIONS.get(key) != generation:
|
|
386
493
|
# A newer start for this home and provider began while this one waited on the provider: it owns the sign-in.
|
|
494
|
+
_discard(state)
|
|
387
495
|
raise RpcError("A newer sign-in for this provider replaced this one.", condition="oauth_superseded")
|
|
388
496
|
superseded = [f for f in _FLOWS.values() if f.provider == provider and f.status == "pending" and _same_home(f.home, home)]
|
|
389
497
|
_FLOWS[flow.flow_id] = flow
|
|
@@ -403,10 +511,10 @@ def _flow(home: Path, flow_id: str) -> Flow:
|
|
|
403
511
|
|
|
404
512
|
def poll(home: Path, flow_id: str) -> dict:
|
|
405
513
|
flow = _flow(home, flow_id)
|
|
406
|
-
if flow.
|
|
514
|
+
if flow.stoppable and time.time() > flow.expires_at + _EXPIRY_GRACE:
|
|
407
515
|
# The provider call outlived its code: end it now, and a late approval can no longer save.
|
|
408
516
|
with flow.lock:
|
|
409
|
-
if flow.
|
|
517
|
+
if flow.stoppable:
|
|
410
518
|
flow.cancelled.set()
|
|
411
519
|
flow.end("expired", _EXPIRED)
|
|
412
520
|
return flow.view()
|
|
@@ -418,6 +526,18 @@ def cancel(home: Path, flow_id: str) -> dict:
|
|
|
418
526
|
return flow.view()
|
|
419
527
|
|
|
420
528
|
|
|
529
|
+
def submit_redirect(home: Path, flow_id: str, url: str) -> dict:
|
|
530
|
+
"""Finish a browser sign-in with the address its redirect reached, when the browser runs on another machine."""
|
|
531
|
+
flow = _flow(home, flow_id)
|
|
532
|
+
if flow.submit is None:
|
|
533
|
+
raise InvalidParams("This sign-in takes no redirect address.")
|
|
534
|
+
with flow.lock:
|
|
535
|
+
if not flow.stoppable or time.time() >= flow.expires_at:
|
|
536
|
+
raise RpcError("This sign-in already ended.", condition="oauth_flow_ended")
|
|
537
|
+
flow.submit(url)
|
|
538
|
+
return flow.view()
|
|
539
|
+
|
|
540
|
+
|
|
421
541
|
def _flow_id(params: dict) -> str:
|
|
422
542
|
flow_id = str(params.get("flow_id") or "").strip()
|
|
423
543
|
if not flow_id:
|
|
@@ -428,7 +548,8 @@ def _flow_id(params: dict) -> str:
|
|
|
428
548
|
def register(reg) -> None:
|
|
429
549
|
@reg.method("oauth.start")
|
|
430
550
|
def start_(ctx: CallContext, params: dict) -> dict:
|
|
431
|
-
provider = str(params.get("provider") or "").strip()
|
|
551
|
+
provider = str(params.get("provider") or "").strip()
|
|
552
|
+
provider = provider if provider.startswith(plugin_oauth.PREFIX) else provider.lower()
|
|
432
553
|
if not provider:
|
|
433
554
|
raise InvalidParams("provider is required")
|
|
434
555
|
return start(profile_home_param(params), provider)
|
|
@@ -440,3 +561,10 @@ def register(reg) -> None:
|
|
|
440
561
|
@reg.method("oauth.cancel", requires_agent=False)
|
|
441
562
|
def cancel_(ctx: CallContext, params: dict) -> dict:
|
|
442
563
|
return cancel(profile_home_param(params), _flow_id(params))
|
|
564
|
+
|
|
565
|
+
@reg.method("oauth.submit_redirect", requires_agent=False)
|
|
566
|
+
def submit_(ctx: CallContext, params: dict) -> dict:
|
|
567
|
+
url = str(params.get("url") or "").strip()
|
|
568
|
+
if not url:
|
|
569
|
+
raise InvalidParams("url is required")
|
|
570
|
+
return submit_redirect(profile_home_param(params), _flow_id(params), url)
|
|
@@ -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}
|