@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
|
@@ -29,6 +29,8 @@ _SESSIONS = {}
|
|
|
29
29
|
_SESSIONS_LOCK = threading.Lock()
|
|
30
30
|
_CONSENTS = {}
|
|
31
31
|
CONSENT_SECONDS = 300
|
|
32
|
+
# One lease exchange, including the worker's unwind after a refused drain.
|
|
33
|
+
LEASE_SECONDS = 330
|
|
32
34
|
|
|
33
35
|
|
|
34
36
|
def _close(session):
|
|
@@ -119,7 +121,59 @@ def _native_source_repair(root):
|
|
|
119
121
|
raise
|
|
120
122
|
|
|
121
123
|
|
|
122
|
-
def
|
|
124
|
+
def _receipt_candidates(path, pattern, cache):
|
|
125
|
+
"""Cache discovery, never receipt presence; missing paths watch their nearest existing ancestor."""
|
|
126
|
+
key = (path, pattern)
|
|
127
|
+
if cache is not None:
|
|
128
|
+
ancestor = path
|
|
129
|
+
while True:
|
|
130
|
+
try:
|
|
131
|
+
stat = ancestor.stat()
|
|
132
|
+
break
|
|
133
|
+
except FileNotFoundError:
|
|
134
|
+
if ancestor == ancestor.parent:
|
|
135
|
+
raise
|
|
136
|
+
ancestor = ancestor.parent
|
|
137
|
+
stamp = (ancestor, stat.st_dev, stat.st_ino, stat.st_mode, stat.st_mtime_ns, stat.st_ctime_ns, stat.st_size)
|
|
138
|
+
now = time.monotonic()
|
|
139
|
+
previous = cache.get(key)
|
|
140
|
+
if previous is not None and previous[0] == stamp and 0 <= now - previous[1] < 1:
|
|
141
|
+
return previous[2]
|
|
142
|
+
if pattern is not None:
|
|
143
|
+
try:
|
|
144
|
+
# glob suppresses enumeration errors, which cannot authorize Agent admission.
|
|
145
|
+
with os.scandir(path) as children:
|
|
146
|
+
found = tuple(path / child.name for child in children if Path(child.name).match(pattern))
|
|
147
|
+
except FileNotFoundError:
|
|
148
|
+
found = ()
|
|
149
|
+
else:
|
|
150
|
+
try:
|
|
151
|
+
found = (path,) if any(' refs/talaria/autostash/pending/' in line for line in path.read_text().splitlines()) else ()
|
|
152
|
+
except FileNotFoundError:
|
|
153
|
+
found = ()
|
|
154
|
+
if cache is not None:
|
|
155
|
+
if len(cache) >= 16:
|
|
156
|
+
cache.clear() # Bound retained paths if an installer repeatedly redirects Git metadata.
|
|
157
|
+
cache[key] = (stamp, now, found)
|
|
158
|
+
return found
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _process_presence(pid):
|
|
162
|
+
"""A stdlib rearm trigger only; native identity verification alone decides recovery."""
|
|
163
|
+
if os.name == 'nt' or pid <= 0:
|
|
164
|
+
return 'unknown'
|
|
165
|
+
try:
|
|
166
|
+
os.kill(pid, 0)
|
|
167
|
+
except ProcessLookupError:
|
|
168
|
+
return 'exited'
|
|
169
|
+
except PermissionError:
|
|
170
|
+
pass
|
|
171
|
+
except (OSError, OverflowError):
|
|
172
|
+
return 'unknown'
|
|
173
|
+
return 'present'
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def recovery_receipts(runtime, *, watch=False, discovery_cache=None):
|
|
123
177
|
"""Read only the configured checkout's receipts without importing its possibly torn code."""
|
|
124
178
|
root, home = runtime.agent_dir, runtime.hermes_home
|
|
125
179
|
if root is None:
|
|
@@ -133,24 +187,29 @@ def recovery_receipts(runtime, *, watch=False):
|
|
|
133
187
|
paths = [services.recovery_path(root, home), marker, native,
|
|
134
188
|
root / '.update-incomplete', root / '.lazy-refresh-incomplete',
|
|
135
189
|
gitdir / 'hermes-update-pull', root / '.hermes-update-zip-swap']
|
|
136
|
-
paths.extend(home
|
|
190
|
+
paths.extend(_receipt_candidates(home, native.name + '.*.claim', discovery_cache))
|
|
137
191
|
common = gitdir
|
|
138
192
|
try:
|
|
139
193
|
common = (gitdir / (gitdir / 'commondir').read_text().strip()).resolve()
|
|
140
194
|
except FileNotFoundError:
|
|
141
195
|
pass
|
|
142
|
-
paths.extend((common / 'refs/talaria/autostash/pending'
|
|
196
|
+
paths.extend(_receipt_candidates(common / 'refs/talaria/autostash/pending', '*', discovery_cache))
|
|
143
197
|
packed = common / 'packed-refs'
|
|
144
|
-
|
|
145
|
-
if any(' refs/talaria/autostash/pending/' in line for line in packed.read_text().splitlines()):
|
|
146
|
-
paths.append(packed)
|
|
147
|
-
except FileNotFoundError:
|
|
148
|
-
pass
|
|
198
|
+
paths.extend(_receipt_candidates(packed, None, discovery_cache))
|
|
149
199
|
def stamps(candidates):
|
|
150
200
|
result = []
|
|
151
201
|
for path in sorted(set(candidates)):
|
|
152
202
|
try:
|
|
153
203
|
stat = path.lstat()
|
|
204
|
+
if path == services.recovery_path(root, home):
|
|
205
|
+
# Completed correlation is history, not admission debt. Malformed evidence fails closed.
|
|
206
|
+
try:
|
|
207
|
+
state = services.ServiceRecovery(root, home, None, None, None).state
|
|
208
|
+
except RuntimeError:
|
|
209
|
+
state = {}
|
|
210
|
+
if (state.get('update_operation', {}).get('recovered_revision') and not state.get('transaction')
|
|
211
|
+
and not state['entries'] and not state.get('sync_failed')):
|
|
212
|
+
continue
|
|
154
213
|
result.append((str(path), stat.st_ino, stat.st_mtime_ns, stat.st_size))
|
|
155
214
|
except FileNotFoundError:
|
|
156
215
|
pass
|
|
@@ -169,15 +228,23 @@ def recovery_receipts(runtime, *, watch=False):
|
|
|
169
228
|
watched.append(common / ref)
|
|
170
229
|
except (OSError, UnicodeError):
|
|
171
230
|
pass
|
|
231
|
+
lifecycle = []
|
|
172
232
|
try:
|
|
173
233
|
body = json.loads(services.recovery_path(root, home).read_text())
|
|
174
234
|
for baseline in body.get('tree', {}).get('baselines', []):
|
|
175
235
|
changed = [*baseline.get('dirty_at_pause', []), *baseline.get('move_paths', [])]
|
|
176
236
|
changed.extend(path for paths in baseline.get('landed', {}).values() for path in paths)
|
|
177
237
|
watched.extend(root / path for path in changed if isinstance(path, str) and not Path(path).is_absolute() and '..' not in Path(path).parts)
|
|
238
|
+
# A retained gateway's exit or successor rearms exhausted recovery without changing any receipt.
|
|
239
|
+
for entry in body.get('entries', []):
|
|
240
|
+
if entry.get('purpose') == 'gateway' and isinstance(entry.get('home'), str):
|
|
241
|
+
watched.append(Path(entry['home']) / 'gateway.pid')
|
|
242
|
+
pids = {**entry.get('retired_processes', {}), **entry.get('processes', {})}
|
|
243
|
+
lifecycle.extend(('process', int(pid), _process_presence(int(pid))) for pid in sorted(pids, key=int))
|
|
178
244
|
except (OSError, ValueError, TypeError, AttributeError):
|
|
179
245
|
pass # The receipt's own stamp still rearms corrected evidence; the worker reports its exact refusal.
|
|
180
246
|
found.extend(stamps(watched))
|
|
247
|
+
found.extend(lifecycle)
|
|
181
248
|
return found, marker
|
|
182
249
|
|
|
183
250
|
|
|
@@ -186,6 +253,19 @@ def recover_retained(runtime, ctx, *, probe=False, complete_revision=None):
|
|
|
186
253
|
receipts, _ = recovery_receipts(runtime, watch=True)
|
|
187
254
|
fingerprint = hashlib.sha256(json.dumps(receipts).encode()).hexdigest() if receipts else ''
|
|
188
255
|
result = {'ok': not receipts, 'owed': bool(receipts), 'fingerprint': fingerprint, 'detail': ''}
|
|
256
|
+
def correlated():
|
|
257
|
+
if runtime.agent_dir is None:
|
|
258
|
+
return {}
|
|
259
|
+
try:
|
|
260
|
+
state = services.ServiceRecovery(runtime.agent_dir.resolve(), runtime.hermes_home, None, None, None).state
|
|
261
|
+
except RuntimeError:
|
|
262
|
+
return {} # Discovery retains malformed debt; the leased worker reports its refusal.
|
|
263
|
+
operation = state.get('update_operation')
|
|
264
|
+
if operation and ((state.get('transaction') or {}).get('operation_id') == operation['operation_id'] or (not recovery_receipts(runtime)[0] and operation.get('recovered_revision'))):
|
|
265
|
+
return {'operation': operation, **({'revision': operation['recovered_revision']} if operation.get('recovered_revision') else {})}
|
|
266
|
+
return {}
|
|
267
|
+
association = correlated()
|
|
268
|
+
result.update(association)
|
|
189
269
|
if complete_revision is not None:
|
|
190
270
|
if not isinstance(complete_revision, str) or not re.fullmatch(r'[a-f0-9]{40}', complete_revision):
|
|
191
271
|
raise InvalidParams('A verified loaded revision is required to complete recovery.')
|
|
@@ -203,6 +283,8 @@ def recover_retained(runtime, ctx, *, probe=False, complete_revision=None):
|
|
|
203
283
|
env.update(HERMES_HOME=str(runtime.hermes_home), HERMES_DISABLE_LAZY_INSTALLS='1',
|
|
204
284
|
PYTHONPATH=str(Path(__file__).parents[1]) + os.pathsep + str(root))
|
|
205
285
|
try:
|
|
286
|
+
if complete_revision is None:
|
|
287
|
+
runtime.retire()
|
|
206
288
|
with tempfile.TemporaryFile() as stdout, tempfile.TemporaryFile() as stderr:
|
|
207
289
|
child = subprocess.Popen([sys.executable, '-m', 'talaria_sidecar.agent_mutation', '--recover-current', str(root), complete_revision or ''],
|
|
208
290
|
cwd=root, env=env, stdin=subprocess.PIPE, stdout=stdout, stderr=stderr)
|
|
@@ -231,18 +313,28 @@ def recover_retained(runtime, ctx, *, probe=False, complete_revision=None):
|
|
|
231
313
|
child.kill()
|
|
232
314
|
child.wait()
|
|
233
315
|
remaining, _ = recovery_receipts(runtime, watch=True)
|
|
234
|
-
return {**result, **reply, 'owed': bool(remaining),
|
|
316
|
+
return {**result, **reply, **(correlated() if association else {}), 'owed': bool(remaining),
|
|
235
317
|
'fingerprint': hashlib.sha256(json.dumps(remaining).encode()).hexdigest() if remaining else ''}
|
|
236
318
|
finally:
|
|
237
319
|
_ACTION_LOCK.release()
|
|
238
320
|
|
|
239
321
|
|
|
322
|
+
def _drain_progress(result):
|
|
323
|
+
progress = result.get("progress") if isinstance(result, dict) and result.keys() == {"progress"} else None
|
|
324
|
+
if (not isinstance(progress, dict) or progress.get("phase") != "gateway_drain"
|
|
325
|
+
or not isinstance(progress.get("deadline_seconds"), (int, float)) or isinstance(progress["deadline_seconds"], bool)
|
|
326
|
+
or not 0 <= progress["deadline_seconds"] <= services.GATEWAY_DRAIN_CEILING
|
|
327
|
+
or not isinstance(progress.get("services"), list) or not all(isinstance(name, str) for name in progress["services"])):
|
|
328
|
+
return None
|
|
329
|
+
return {"phase": "gateway_drain", "deadline_seconds": progress["deadline_seconds"], "services": progress["services"]}
|
|
330
|
+
|
|
331
|
+
|
|
240
332
|
def _exchange(session, request, ctx):
|
|
241
333
|
with session["lock"]:
|
|
242
334
|
if request is not None:
|
|
243
335
|
session["proc"].stdin.write(json.dumps(request) + "\n")
|
|
244
336
|
session["proc"].stdin.flush()
|
|
245
|
-
deadline = time.monotonic() +
|
|
337
|
+
deadline = time.monotonic() + LEASE_SECONDS
|
|
246
338
|
while True:
|
|
247
339
|
ctx.check_cancelled()
|
|
248
340
|
if time.monotonic() >= deadline:
|
|
@@ -254,6 +346,14 @@ def _exchange(session, request, ctx):
|
|
|
254
346
|
if line is None:
|
|
255
347
|
raise RpcError("Agent writer lease exited; its pause journal retains recovery.", condition="agent_update_unsafe")
|
|
256
348
|
result = json.loads(line)
|
|
349
|
+
if isinstance(result, dict) and "progress" in result:
|
|
350
|
+
progress = _drain_progress(result)
|
|
351
|
+
if progress is None:
|
|
352
|
+
raise RpcError("Invalid Agent writer lease response.", condition="agent_update_unsafe")
|
|
353
|
+
# The worker's own drain deadline is bounded; unwind keeps the ordinary lease margin.
|
|
354
|
+
deadline = max(deadline, time.monotonic() + progress["deadline_seconds"] + LEASE_SECONDS)
|
|
355
|
+
ctx.emit("progress", progress)
|
|
356
|
+
continue
|
|
257
357
|
if not isinstance(result, dict) or not isinstance(result.get("ok"), bool):
|
|
258
358
|
raise RpcError("Invalid Agent writer lease response.", condition="agent_update_unsafe")
|
|
259
359
|
return {"ok": result["ok"], "skipped": result.get("skipped") is True, "detail": str(result.get("detail") or ""),
|
|
@@ -278,6 +378,11 @@ def call(runtime, ctx, params):
|
|
|
278
378
|
raise InvalidParams("resolved profile homes are required")
|
|
279
379
|
if any(Path(home).resolve().is_relative_to(root.resolve()) for home in homes):
|
|
280
380
|
raise InvalidParams("Agent profile homes must stay outside the source checkout to survive update cleanup")
|
|
381
|
+
operation_id = params.get('operation_id')
|
|
382
|
+
baseline = params.get('baseline_revision')
|
|
383
|
+
if operation_id is not None and (not isinstance(operation_id, str) or not re.fullmatch(r'[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}', operation_id)
|
|
384
|
+
or not isinstance(baseline, str) or not re.fullmatch(r'[a-f0-9]{40}', baseline)):
|
|
385
|
+
raise InvalidParams('An operation requires its immutable baseline revision.')
|
|
281
386
|
intent = params.get('intent', '')
|
|
282
387
|
refresh_token = params.get('refresh_token')
|
|
283
388
|
if not isinstance(intent, str) or len(intent) > 1024:
|
|
@@ -306,7 +411,7 @@ def call(runtime, ctx, params):
|
|
|
306
411
|
stderr.close()
|
|
307
412
|
return {"ok": False, "skipped": False, "detail": "A gateway lifecycle action is still running."}
|
|
308
413
|
try:
|
|
309
|
-
proc = subprocess.Popen([sys.executable, "-m", "talaria_sidecar.agent_mutation", str(root), revision, json.dumps(homes), binding or ""],
|
|
414
|
+
proc = subprocess.Popen([sys.executable, "-m", "talaria_sidecar.agent_mutation", str(root), revision, json.dumps(homes), binding or "", json.dumps({"operation_id": operation_id, "baseline_revision": baseline}) if operation_id else ""],
|
|
310
415
|
cwd=root, env=env, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=stderr, text=True)
|
|
311
416
|
except BaseException:
|
|
312
417
|
stderr.close()
|
|
@@ -357,7 +462,12 @@ def call(runtime, ctx, params):
|
|
|
357
462
|
_CONSENTS[nonce] = {key: session[key] for key in ('root', 'revision', 'homes', 'intent')}
|
|
358
463
|
_CONSENTS[nonce].update(binding=confirmation['binding'], expires=time.monotonic() + CONSENT_SECONDS)
|
|
359
464
|
result['refresh_confirmation'] = {'token': nonce, 'services': confirmation['services']}
|
|
465
|
+
if action == 'begin' and not result['ok'] and 'refresh_confirmation' not in result:
|
|
466
|
+
probe = recover_retained(runtime, ctx, probe=True)
|
|
467
|
+
correlation = probe.get('operation')
|
|
468
|
+
result['recovery_required'] = bool(correlation and correlation['operation_id'] == params.get('operation_id')) if params.get('operation_id') else probe['owed']
|
|
360
469
|
if action == "begin" and result["ok"]:
|
|
470
|
+
runtime.retire()
|
|
361
471
|
return {**result, "token": token}
|
|
362
472
|
if action != "finish" and result["ok"]:
|
|
363
473
|
return result
|
|
@@ -449,7 +559,7 @@ def _writer_ledger(root, identity):
|
|
|
449
559
|
return found
|
|
450
560
|
|
|
451
561
|
|
|
452
|
-
def _worker(root, revision, homes, requests, stopped, send, refresh_binding=None):
|
|
562
|
+
def _worker(root, revision, homes, requests, stopped, send, refresh_binding=None, operation=None):
|
|
453
563
|
if os.name not in {"posix", "nt"}:
|
|
454
564
|
raise RuntimeError("A cooperative Agent writer lease is unavailable on this platform; source was not changed.")
|
|
455
565
|
sys.path.insert(0, str(root))
|
|
@@ -478,6 +588,13 @@ def _worker(root, revision, homes, requests, stopped, send, refresh_binding=None
|
|
|
478
588
|
if not found["ok"]:
|
|
479
589
|
raise RuntimeError("The installed Agent revision could not be verified before quiescence.")
|
|
480
590
|
initial = found["detail"]
|
|
591
|
+
if operation and operation['baseline_revision'] != initial:
|
|
592
|
+
raise RuntimeError('The Agent baseline changed before the operation acquired its native lease.')
|
|
593
|
+
previous = recovery.state.get('update_operation')
|
|
594
|
+
if operation and previous and recovery.state.get('transaction') and previous['operation_id'] != operation['operation_id']:
|
|
595
|
+
raise RuntimeError('The previous update operation still owns native recovery.')
|
|
596
|
+
if operation and previous and previous['operation_id'] == operation['operation_id'] and (previous['target_revision'] != revision or previous['baseline_revision'] != operation['baseline_revision']):
|
|
597
|
+
raise RuntimeError('The immutable target or baseline changed within the same update operation.')
|
|
481
598
|
initial_tree = records.tree_state(root)
|
|
482
599
|
if initial_tree is None or initial_tree.get("pre_sha") != initial or initial_tree.get("dirty_at_pause") is None:
|
|
483
600
|
raise RuntimeError("The Agent source baseline could not be proved before quiescence.")
|
|
@@ -562,7 +679,10 @@ def _worker(root, revision, homes, requests, stopped, send, refresh_binding=None
|
|
|
562
679
|
unmapped_pids=[e["pid"] for e in gateway_entries if not e.get("kind")],
|
|
563
680
|
identities=owner_identities, resume_needed=bool(gateway_entries))
|
|
564
681
|
records.record_pause(token, adopted, claims)
|
|
565
|
-
recovery.state.setdefault('transaction', {'revision': revision, 'homes': sorted(map(str, homes))})
|
|
682
|
+
transaction = recovery.state.setdefault('transaction', {'revision': revision, 'homes': sorted(map(str, homes))})
|
|
683
|
+
if operation:
|
|
684
|
+
recovery.state['update_operation'] = {**operation, 'target_revision': revision, 'stage': 'install', 'source_moved': False}
|
|
685
|
+
transaction['operation_id'] = operation['operation_id']
|
|
566
686
|
recovery.save(token)
|
|
567
687
|
if legacy:
|
|
568
688
|
whole, why = records.tree_is_whole(token, root)
|
|
@@ -583,12 +703,16 @@ def _worker(root, revision, homes, requests, stopped, send, refresh_binding=None
|
|
|
583
703
|
records.mark_stop_requested(token, sorted({pid for e in gateway_entries for pid in (e['pid'], e.get('service_pid', e['pid']))}))
|
|
584
704
|
for entry in backend_entries:
|
|
585
705
|
recovery.stop(entry, stopped)
|
|
586
|
-
|
|
706
|
+
# Every profile shares the longest native drain; the lease reports it so its RPC keeps custody.
|
|
707
|
+
gateway_deadline = recovery.gateway_deadline(homes)
|
|
708
|
+
if gateway_entries:
|
|
709
|
+
send({'progress': {'phase': 'gateway_drain', 'deadline_seconds': round(max(gateway_deadline - time.monotonic(), 0), 3),
|
|
710
|
+
'services': sorted({services._name(e) for e in gateway_entries})}})
|
|
587
711
|
for entry in gateway_entries:
|
|
588
712
|
if stopped.is_set() or time.monotonic() >= gateway_deadline:
|
|
589
713
|
raise RuntimeError('Gateway drain has not completed; its durable resume obligation is retained.')
|
|
590
714
|
if entry.get('processes'):
|
|
591
|
-
|
|
715
|
+
recovery.verify_processes(entry)
|
|
592
716
|
recovery.gateway_requested(entry)
|
|
593
717
|
for pid in {entry['pid'], entry.get('service_pid', entry['pid'])}:
|
|
594
718
|
records.mark_stop_sent(token, pid)
|
|
@@ -670,6 +794,8 @@ def _worker(root, revision, homes, requests, stopped, send, refresh_binding=None
|
|
|
670
794
|
gate = modules["update_cmd_pause_gate"]._checkout_move(token, revision, paths=paths, revert=True) if mutating else contextlib.nullcontext({})
|
|
671
795
|
if mutating:
|
|
672
796
|
recovery.state['transaction']['dependencies_verified'] = False
|
|
797
|
+
if args[0] in {'merge', 'reset', 'checkout'} and recovery.state.get('update_operation'):
|
|
798
|
+
recovery.state['update_operation'].pop('source_moved', None)
|
|
673
799
|
move_marker = None
|
|
674
800
|
if args[0] == 'merge' and '--ff-only' in args or args[0] == 'reset' and '--hard' in args:
|
|
675
801
|
commit = modules['update_cmd_commit']
|
|
@@ -693,6 +819,8 @@ def _worker(root, revision, homes, requests, stopped, send, refresh_binding=None
|
|
|
693
819
|
recovery.state['transaction']['dependencies_verified'] = True
|
|
694
820
|
else:
|
|
695
821
|
result = {'ok': False, 'detail': 'The source move did not leave a verified whole target; native rollback remains owed.'}
|
|
822
|
+
if result['ok'] and move_marker is not None and recovery.state.get('update_operation'):
|
|
823
|
+
recovery.state['update_operation']['source_moved'] = revision != recovery.state['update_operation']['baseline_revision']
|
|
696
824
|
if result["ok"] and applying and whole_before:
|
|
697
825
|
after = records.tree_state(root)
|
|
698
826
|
if before is None or after is None or before["pre_sha"] != after["pre_sha"]:
|
|
@@ -703,11 +831,17 @@ def _worker(root, revision, homes, requests, stopped, send, refresh_binding=None
|
|
|
703
831
|
baseline.update(after)
|
|
704
832
|
records.write(token)
|
|
705
833
|
recovery.save(token)
|
|
834
|
+
if not result['ok'] and recovery.state.get('update_operation'):
|
|
835
|
+
recovery.state['update_operation'].setdefault('attempt_error', result.get('detail', '')[:2000])
|
|
836
|
+
recovery.state['update_operation'].setdefault('failed_stage', recovery.state['update_operation']['stage'])
|
|
837
|
+
recovery.save(token)
|
|
706
838
|
send(result)
|
|
707
839
|
except BaseException as exc:
|
|
708
840
|
error = str(exc)
|
|
709
841
|
finally:
|
|
710
842
|
try:
|
|
843
|
+
# Cancellation or a lost lease pipe ends the drain wait; the retained debt keeps the gateway owed.
|
|
844
|
+
unwind_deadline = time.monotonic() if stopped.is_set() else gateway_deadline
|
|
711
845
|
if token:
|
|
712
846
|
live = any(records.identity_is_live({"pid": int(pid), "ct": ct}) for pid, ct in token.get("identities", {}).items())
|
|
713
847
|
found = _command(modules["update_custody"].git_argv(["git"], ["rev-parse", "HEAD"]), root, 10, threading.Event(), modules["update_custody"])
|
|
@@ -720,7 +854,7 @@ def _worker(root, revision, homes, requests, stopped, send, refresh_binding=None
|
|
|
720
854
|
if live and not changed and not sync_failed and records.tree_is_whole(token, root)[0]:
|
|
721
855
|
# An untouched gateway must not strand a backend stopped earlier in a partial pause.
|
|
722
856
|
recovery.save(token)
|
|
723
|
-
recovery.resume(_writer_ledger, gateway_deadline=
|
|
857
|
+
recovery.resume(_writer_ledger, gateway_deadline=unwind_deadline)
|
|
724
858
|
if live or sync_failed or (changed and needs_sync and not locals().get("response", {}).get("ok")):
|
|
725
859
|
raise RuntimeError("Gateway resume remains owed until writer drain and dependency repair complete.")
|
|
726
860
|
whole, why = records.tree_is_whole(token, root)
|
|
@@ -729,6 +863,9 @@ def _worker(root, revision, homes, requests, stopped, send, refresh_binding=None
|
|
|
729
863
|
pending = _command(modules['update_custody'].git_argv(['git'], ['for-each-ref', '--format=%(objectname)', 'refs/talaria/autostash/pending/']), root, 10, threading.Event(), modules['update_custody'])
|
|
730
864
|
if not pending['ok'] or pending['detail']:
|
|
731
865
|
raise RuntimeError('Gateway resume remains owed until retained local Agent edits are restored.')
|
|
866
|
+
if recovery.state.get('update_operation'):
|
|
867
|
+
recovery.state['update_operation']['stage'] = 'gateway_restart'
|
|
868
|
+
recovery.save(token)
|
|
732
869
|
if token.get("resume_needed"):
|
|
733
870
|
if bootstrap_repair:
|
|
734
871
|
records.write({**token, "resume_needed": True}, owner=records.UNOWNED)
|
|
@@ -742,7 +879,7 @@ def _worker(root, revision, homes, requests, stopped, send, refresh_binding=None
|
|
|
742
879
|
if token.get("resume_needed") or token.get("resume_deferred"):
|
|
743
880
|
raise RuntimeError("Gateway resume could not be verified; its obligation is retained.")
|
|
744
881
|
recovery.save(token)
|
|
745
|
-
recovery.resume(_writer_ledger, gateway_deadline=
|
|
882
|
+
recovery.resume(_writer_ledger, gateway_deadline=unwind_deadline)
|
|
746
883
|
if token and not handed_off:
|
|
747
884
|
records.discharge(token)
|
|
748
885
|
from .runtime import AgentRuntime
|
|
@@ -751,6 +888,8 @@ def _worker(root, revision, homes, requests, stopped, send, refresh_binding=None
|
|
|
751
888
|
recovery.state['transaction']['runtime_revision'] = found['detail']
|
|
752
889
|
recovery.save(token)
|
|
753
890
|
else:
|
|
891
|
+
if recovery.state.get('update_operation'):
|
|
892
|
+
recovery.state['update_operation'].update(stage='agent_ready', recovered_revision=found['detail'])
|
|
754
893
|
recovery.state.pop('transaction', None)
|
|
755
894
|
recovery.save()
|
|
756
895
|
except BaseException as exc:
|
|
@@ -758,21 +897,31 @@ def _worker(root, revision, homes, requests, stopped, send, refresh_binding=None
|
|
|
758
897
|
if token and not handed_off:
|
|
759
898
|
records.write({**token, "resume_needed": True}, owner=records.UNOWNED)
|
|
760
899
|
finally:
|
|
761
|
-
|
|
900
|
+
try:
|
|
901
|
+
if error and token and recovery and recovery.state.get('update_operation') and (recovery.state.get('transaction') or {}).get('operation_id') == recovery.state['update_operation']['operation_id']:
|
|
902
|
+
operation = recovery.state['update_operation']
|
|
903
|
+
operation.setdefault('attempt_error', error[:2000])
|
|
904
|
+
operation.setdefault('failed_stage', operation['stage'])
|
|
905
|
+
recovery.save(token)
|
|
906
|
+
finally:
|
|
907
|
+
lock.release()
|
|
762
908
|
send({"ok": error is None, "detail": error or ""})
|
|
763
909
|
|
|
764
910
|
|
|
765
911
|
def _resume_current(root, custody, stopped=None, complete_revision=None):
|
|
912
|
+
# Resolve target PM code in a fresh stdlib process, after any source/dependency change.
|
|
766
913
|
try:
|
|
767
|
-
|
|
768
|
-
|
|
914
|
+
launchers = importlib.import_module('hermes_cli._launchers')
|
|
915
|
+
if not Path(launchers.__file__).resolve().is_relative_to(root):
|
|
916
|
+
raise RuntimeError('Recovery loaded another Agent bootstrap selector.')
|
|
917
|
+
bootstrap = launchers.resolve_store_python(root)
|
|
769
918
|
except ModuleNotFoundError as exc:
|
|
770
|
-
if exc.name !=
|
|
919
|
+
if exc.name != 'hermes_cli._launchers':
|
|
771
920
|
raise
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
result = _command([str(
|
|
921
|
+
bootstrap = None
|
|
922
|
+
# A copied macOS venv interpreter can be its own _base_executable and later be retired.
|
|
923
|
+
bootstrap = bootstrap or getattr(sys, '_base_executable', None) or sys.executable
|
|
924
|
+
result = _command([str(bootstrap), "-m", "talaria_sidecar.agent_mutation", "--select-resume", str(root), complete_revision or "", sys.executable], root, 660, stopped or threading.Event(), custody, cooperative=True)
|
|
776
925
|
try:
|
|
777
926
|
reply = json.loads(result["detail"]) if result["ok"] else {}
|
|
778
927
|
return {**reply, "ok": result["ok"] and reply.get("ok") is True, "detail": str(reply.get("detail") or result["detail"])}
|
|
@@ -780,6 +929,46 @@ def _resume_current(root, custody, stopped=None, complete_revision=None):
|
|
|
780
929
|
return {"ok": False, "detail": "The current Agent could not verify its retained gateway resume obligation."}
|
|
781
930
|
|
|
782
931
|
|
|
932
|
+
def _recovery_environment(root):
|
|
933
|
+
"""Reuse PM's selector and packaged launch policy without copying its facts/path rules."""
|
|
934
|
+
sys.path.insert(0, str(root))
|
|
935
|
+
environments = importlib.import_module('pm.environments')
|
|
936
|
+
if any(not Path(sys.modules[name].__file__).resolve().is_relative_to(root)
|
|
937
|
+
for name in ('pm', 'pm.environments', 'hermes_constants')):
|
|
938
|
+
raise RuntimeError('Recovery loaded another Agent environment selector.')
|
|
939
|
+
selected = environments.committed_venv(root)
|
|
940
|
+
if selected is None:
|
|
941
|
+
if environments.install_state_dir(root).exists():
|
|
942
|
+
raise RuntimeError('No dependency environment is committed for this Agent install; recovery remains owed.')
|
|
943
|
+
selected = environments.selected_venv(root)
|
|
944
|
+
return environments, selected
|
|
945
|
+
|
|
946
|
+
|
|
947
|
+
def _select_resume(root, complete_revision, legacy_python):
|
|
948
|
+
if (root / 'pm').exists():
|
|
949
|
+
environments, selected = _recovery_environment(root)
|
|
950
|
+
command = environments.venv_command(root, selected)
|
|
951
|
+
environment = str(selected)
|
|
952
|
+
else:
|
|
953
|
+
python = next((path for venv in ('.venv', 'venv')
|
|
954
|
+
for path in (root / venv / 'bin/python', root / venv / 'Scripts/python.exe') if path.is_file()), Path(legacy_python))
|
|
955
|
+
command, environment = [str(python)], ''
|
|
956
|
+
# Keep bin/python intact: realpath would turn a POSIX venv into its bare tool.
|
|
957
|
+
argv = [*command, '-m', 'talaria_sidecar.agent_mutation', '--resume-leased', str(root), complete_revision or '', environment]
|
|
958
|
+
os.execv(argv[0], argv)
|
|
959
|
+
|
|
960
|
+
|
|
961
|
+
def _verify_recovery_environment(root, expected):
|
|
962
|
+
from .runtime import _check_site_packages_python
|
|
963
|
+
environments, selected = _recovery_environment(root)
|
|
964
|
+
if str(selected) != expected or environments.venv_python_version(selected) != sys.version_info[:2]:
|
|
965
|
+
raise RuntimeError('Agent recovery dependency environment changed or has an incompatible Python ABI.')
|
|
966
|
+
site = environments.site_packages(selected)
|
|
967
|
+
if not site.is_dir() or site.resolve() not in {Path(entry).resolve() for entry in sys.path if entry}:
|
|
968
|
+
raise RuntimeError('Agent recovery did not enter its selected dependency environment.')
|
|
969
|
+
_check_site_packages_python()
|
|
970
|
+
|
|
971
|
+
|
|
783
972
|
def _resume_worker(root, stopped=None, complete_revision=None):
|
|
784
973
|
sys.path.insert(0, str(root))
|
|
785
974
|
from hermes_cli import update_lock, update_pause_record as records, process_identity, update_cmd_posix_pause
|
|
@@ -820,7 +1009,13 @@ def _resume_worker(root, stopped=None, complete_revision=None):
|
|
|
820
1009
|
if revision not in {r for b in tree.get('baselines', []) for r in [b.get('pre_sha'), *b.get('move_targets', []), *b.get('landed', {})]}:
|
|
821
1010
|
return {'ok': False, 'detail': 'Installed revision is outside the retained transaction; recovery was refused.'}
|
|
822
1011
|
moved = any(b.get('pre_sha') != revision for b in tree.get('baselines', []))
|
|
1012
|
+
operation = recovery.state.get('update_operation')
|
|
1013
|
+
if operation and any(sha != operation['baseline_revision'] for b in tree.get('baselines', []) for sha in b.get('landed', {})):
|
|
1014
|
+
operation['source_moved'] = True
|
|
823
1015
|
transaction = recovery.state.get('transaction') or {}
|
|
1016
|
+
operation = recovery.state.get('update_operation')
|
|
1017
|
+
if operation and transaction.get('operation_id') != operation['operation_id']:
|
|
1018
|
+
recovery.state.pop('update_operation', None)
|
|
824
1019
|
if recovery.state.get('sync_failed') or (moved and not transaction.get('dependencies_verified')) or (marker and marker.exists() and not transaction):
|
|
825
1020
|
if _writer_ledger(root, process_identity):
|
|
826
1021
|
return {'ok': False, 'detail': 'Recorded dependency repair is waiting for the existing writer drain; no additional stop was sent.'}
|
|
@@ -833,9 +1028,10 @@ def _resume_worker(root, stopped=None, complete_revision=None):
|
|
|
833
1028
|
if response.get('ok') is not True:
|
|
834
1029
|
return {'ok': False, 'detail': 'Recorded dependency repair failed: ' + str(response.get('detail') or synced['detail'])}
|
|
835
1030
|
recovery.state['sync_failed'] = False
|
|
836
|
-
|
|
837
|
-
|
|
1031
|
+
transaction = recovery.state.setdefault('transaction', {'revision': revision, 'homes': [str(runtime.hermes_home)]})
|
|
1032
|
+
transaction['dependencies_verified'] = True
|
|
838
1033
|
recovery.save(tree)
|
|
1034
|
+
return _resume_current(root, custody, stopped, complete_revision)
|
|
839
1035
|
elif recovery.state.get('sync_failed'):
|
|
840
1036
|
return {'ok': False, 'detail': 'The recorded dependency repair module is missing.'}
|
|
841
1037
|
whole, why = records.tree_is_whole(tree, root)
|
|
@@ -850,7 +1046,16 @@ def _resume_worker(root, stopped=None, complete_revision=None):
|
|
|
850
1046
|
if not Path(main_module.__file__).resolve().is_relative_to(root):
|
|
851
1047
|
raise RuntimeError("Gateway recovery loaded another Agent runtime.")
|
|
852
1048
|
records.recover(argv=[])
|
|
853
|
-
recovery.
|
|
1049
|
+
if recovery.state.get('update_operation'):
|
|
1050
|
+
recovery.state['update_operation']['stage'] = 'gateway_restart'
|
|
1051
|
+
recovery.save(tree)
|
|
1052
|
+
try:
|
|
1053
|
+
recovery.resume(_writer_ledger)
|
|
1054
|
+
except services.GatewayDraining as exc:
|
|
1055
|
+
return {'ok': False, 'draining': True, 'detail': str(exc)}
|
|
1056
|
+
final_head = _command(custody.git_argv(['git'], ['rev-parse', 'HEAD']), root, 10, stopped, custody)
|
|
1057
|
+
if not final_head['ok'] or final_head['detail'] != revision or not records.tree_is_whole(tree, root)[0]:
|
|
1058
|
+
return {'ok': False, 'detail': 'Recovered source identity changed before readiness was verified; its evidence is retained.'}
|
|
854
1059
|
owed = records.record_path().exists() or bool(records._claims(records.record_path())) or bool(recovery.state['entries'])
|
|
855
1060
|
runtime_pending = bool((marker and marker.exists()) or (recovery.state.get('transaction') or {}).get('runtime_revision'))
|
|
856
1061
|
if not owed and runtime_pending:
|
|
@@ -861,11 +1066,16 @@ def _resume_worker(root, stopped=None, complete_revision=None):
|
|
|
861
1066
|
transaction['runtime_revision'] = revision
|
|
862
1067
|
recovery.save(tree)
|
|
863
1068
|
if not owed and not runtime_pending:
|
|
1069
|
+
# Retain the transaction through durable marker removal, including a failed unlink or crash.
|
|
1070
|
+
if marker:
|
|
1071
|
+
marker.unlink(missing_ok=True)
|
|
1072
|
+
if marker.parent.is_dir():
|
|
1073
|
+
recovery._sync_directory(marker.parent)
|
|
1074
|
+
if recovery.state.get('update_operation'):
|
|
1075
|
+
recovery.state['update_operation'].update(stage='agent_ready', recovered_revision=revision)
|
|
864
1076
|
recovery.state.pop('transaction', None)
|
|
865
1077
|
recovery.state['sync_failed'] = False
|
|
866
1078
|
recovery.save()
|
|
867
|
-
if marker:
|
|
868
|
-
marker.unlink(missing_ok=True)
|
|
869
1079
|
return {"ok": not owed, "revision": revision, "runtime_pending": runtime_pending, "detail": "Gateway recovery remains durably recorded." if owed else ""}
|
|
870
1080
|
finally:
|
|
871
1081
|
lock.release()
|
|
@@ -926,9 +1136,11 @@ def _command(argv, root, timeout, stopped, custody, *, cooperative=False):
|
|
|
926
1136
|
def main():
|
|
927
1137
|
for key in ("GIT_DIR", "GIT_WORK_TREE", "GIT_COMMON_DIR", "GIT_INDEX_FILE"):
|
|
928
1138
|
os.environ.pop(key, None)
|
|
929
|
-
if len(sys.argv) > 2 and sys.argv[1] in {'--recover-current', '--resume', '--resume-leased'}:
|
|
1139
|
+
if len(sys.argv) > 2 and sys.argv[1] in {'--recover-current', '--resume', '--resume-leased', '--select-resume'}:
|
|
930
1140
|
try:
|
|
931
1141
|
_native_source_repair(Path(sys.argv[2]).resolve())
|
|
1142
|
+
if sys.argv[1] == '--select-resume':
|
|
1143
|
+
_select_resume(Path(sys.argv[2]).resolve(), sys.argv[3], sys.argv[4])
|
|
932
1144
|
except BaseException as exc:
|
|
933
1145
|
print(json.dumps({'ok': False, 'detail': str(exc) if str(exc) != '1' else 'Native recorded source repair could not complete; its receipt remains owed.'}), flush=True)
|
|
934
1146
|
return
|
|
@@ -962,11 +1174,13 @@ def main():
|
|
|
962
1174
|
return
|
|
963
1175
|
if sys.argv[1] in {"--resume", "--resume-leased"}:
|
|
964
1176
|
with contextlib.redirect_stdout(sys.stderr):
|
|
1177
|
+
if len(sys.argv) > 4 and sys.argv[4]:
|
|
1178
|
+
_verify_recovery_environment(Path(sys.argv[2]).resolve(), sys.argv[4])
|
|
965
1179
|
reply = _resume_worker(Path(sys.argv[2]).resolve(), stopped if sys.argv[1] == "--resume-leased" else None, sys.argv[3] if len(sys.argv) > 3 and sys.argv[3] else None)
|
|
966
1180
|
send(reply)
|
|
967
1181
|
return
|
|
968
1182
|
with contextlib.redirect_stdout(sys.stderr):
|
|
969
|
-
_worker(Path(sys.argv[1]).resolve(), sys.argv[2], {Path(h).resolve() for h in json.loads(sys.argv[3])}, requests, stopped, send, sys.argv[4] if len(sys.argv) > 4 else None)
|
|
1183
|
+
_worker(Path(sys.argv[1]).resolve(), sys.argv[2], {Path(h).resolve() for h in json.loads(sys.argv[3])}, requests, stopped, send, sys.argv[4] if len(sys.argv) > 4 else None, json.loads(sys.argv[5]) if len(sys.argv) > 5 and sys.argv[5] else None)
|
|
970
1184
|
except BaseException as exc:
|
|
971
1185
|
send({"ok": False, "detail": str(exc)})
|
|
972
1186
|
|