@maudecode/talaria-web 1.18.0 → 1.19.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/auth-raw.js +16 -16
- package/dist/api/auth-raw.js.map +1 -1
- package/dist/api/automation-raw.d.ts +2 -2
- package/dist/api/automation-raw.js +32 -32
- package/dist/api/automation-raw.js.map +1 -1
- package/dist/api/automation-router.d.ts +102 -22
- package/dist/api/automation-router.js +15 -13
- package/dist/api/automation-router.js.map +1 -1
- package/dist/api/chat-router.d.ts +1205 -34
- package/dist/api/chat-router.js +158 -78
- package/dist/api/chat-router.js.map +1 -1
- package/dist/api/git-router.d.ts +2 -2
- package/dist/api/git-router.js +29 -29
- package/dist/api/git-router.js.map +1 -1
- package/dist/api/raw-routes.d.ts +3 -3
- package/dist/api/raw-routes.js +63 -61
- package/dist/api/raw-routes.js.map +1 -1
- package/dist/api/router.d.ts +6 -6
- package/dist/api/router.js +22 -22
- package/dist/api/router.js.map +1 -1
- package/dist/api/session-visibility.d.ts +4 -4
- package/dist/api/session-visibility.js +26 -16
- package/dist/api/session-visibility.js.map +1 -1
- package/dist/api/sessions-router.d.ts +1928 -124
- package/dist/api/sessions-router.js +177 -173
- package/dist/api/sessions-router.js.map +1 -1
- package/dist/api/settings-router.d.ts +427 -9
- package/dist/api/settings-router.js +48 -32
- package/dist/api/settings-router.js.map +1 -1
- package/dist/api/sse-routes.d.ts +2 -2
- package/dist/api/sse-routes.js +63 -63
- package/dist/api/sse-routes.js.map +1 -1
- package/dist/api/tools-raw.d.ts +5 -0
- package/dist/api/tools-raw.js +58 -33
- package/dist/api/tools-raw.js.map +1 -1
- package/dist/api/tools-router.d.ts +663 -91
- package/dist/api/tools-router.js +309 -52
- package/dist/api/tools-router.js.map +1 -1
- package/dist/api/transcribe-stream.d.ts +16 -0
- package/dist/api/transcribe-stream.js +172 -0
- package/dist/api/transcribe-stream.js.map +1 -0
- package/dist/app.d.ts +4 -1
- package/dist/app.js +66 -47
- package/dist/app.js.map +1 -1
- package/dist/auth/gate.js +10 -9
- package/dist/auth/gate.js.map +1 -1
- package/dist/auth/passkeys.d.ts +15 -14
- package/dist/auth/passkeys.js +89 -91
- package/dist/auth/passkeys.js.map +1 -1
- package/dist/auth/store.d.ts +17 -7
- package/dist/auth/store.js +93 -52
- package/dist/auth/store.js.map +1 -1
- package/dist/bin/talaria-web.js +12 -81
- package/dist/bin/talaria-web.js.map +1 -1
- package/dist/cli/ctl.js +2 -1
- package/dist/cli/ctl.js.map +1 -1
- package/dist/cli/dotenv.d.ts +5 -0
- package/dist/cli/dotenv.js +14 -2
- package/dist/cli/dotenv.js.map +1 -1
- package/dist/cli/launcher.js +5 -5
- package/dist/cli/launcher.js.map +1 -1
- package/dist/cli/main.d.ts +1 -0
- package/dist/cli/main.js +85 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/supervise.d.ts +2 -0
- package/dist/cli/supervise.js +67 -4
- package/dist/cli/supervise.js.map +1 -1
- package/dist/config/agent-config.d.ts +34 -11
- package/dist/config/agent-config.js +113 -58
- package/dist/config/agent-config.js.map +1 -1
- package/dist/config.d.ts +2 -0
- package/dist/config.js +14 -5
- package/dist/config.js.map +1 -1
- package/dist/fs/atomic.d.ts +1 -0
- package/dist/fs/atomic.js +4 -1
- package/dist/fs/atomic.js.map +1 -1
- package/dist/fs/stat.d.ts +1 -0
- package/dist/fs/stat.js +11 -0
- package/dist/fs/stat.js.map +1 -0
- package/dist/http/context.d.ts +14 -9
- package/dist/http/context.js +29 -20
- package/dist/http/context.js.map +1 -1
- package/dist/onboarding.d.ts +2 -2
- package/dist/onboarding.js +10 -8
- package/dist/onboarding.js.map +1 -1
- package/dist/profiles/profiles.d.ts +10 -4
- package/dist/profiles/profiles.js +77 -30
- package/dist/profiles/profiles.js.map +1 -1
- package/dist/projects.d.ts +15 -6
- package/dist/projects.js +55 -47
- package/dist/projects.js.map +1 -1
- package/dist/providers/catalog.d.ts +78 -12
- package/dist/providers/catalog.js +445 -141
- package/dist/providers/catalog.js.map +1 -1
- package/dist/providers/env-file.d.ts +10 -3
- package/dist/providers/env-file.js +24 -75
- package/dist/providers/env-file.js.map +1 -1
- package/dist/providers/runtime-env.d.ts +4 -2
- package/dist/providers/runtime-env.js +9 -6
- package/dist/providers/runtime-env.js.map +1 -1
- package/dist/providers/tables.d.ts +3 -1
- package/dist/providers/tables.js +4 -2
- package/dist/providers/tables.js.map +1 -1
- package/dist/redact.js +18 -9
- package/dist/redact.js.map +1 -1
- package/dist/release.d.ts +7 -0
- package/dist/release.js +14 -0
- package/dist/release.js.map +1 -1
- package/dist/runtime.d.ts +5 -1
- package/dist/runtime.js +233 -90
- package/dist/runtime.js.map +1 -1
- package/dist/server.js +10 -0
- package/dist/server.js.map +1 -1
- package/dist/sessions/anchor.d.ts +9 -3
- package/dist/sessions/anchor.js +28 -36
- package/dist/sessions/anchor.js.map +1 -1
- package/dist/sessions/background-events.d.ts +2 -0
- package/dist/sessions/background-events.js +10 -0
- package/dist/sessions/background-events.js.map +1 -0
- package/dist/sessions/background-tasks.d.ts +26 -20
- package/dist/sessions/background-tasks.js +88 -86
- package/dist/sessions/background-tasks.js.map +1 -1
- package/dist/sessions/background-updates.d.ts +15 -8
- package/dist/sessions/background-updates.js +101 -25
- package/dist/sessions/background-updates.js.map +1 -1
- package/dist/sessions/cli-sessions.d.ts +15 -5
- package/dist/sessions/cli-sessions.js +62 -43
- package/dist/sessions/cli-sessions.js.map +1 -1
- package/dist/sessions/completions.d.ts +30 -2
- package/dist/sessions/completions.js +294 -53
- package/dist/sessions/completions.js.map +1 -1
- package/dist/sessions/compress.d.ts +8 -0
- package/dist/sessions/compress.js +2 -2
- package/dist/sessions/compress.js.map +1 -1
- package/dist/sessions/drafts.d.ts +14 -10
- package/dist/sessions/drafts.js +38 -43
- package/dist/sessions/drafts.js.map +1 -1
- package/dist/sessions/gateway-sessions.d.ts +46 -0
- package/dist/sessions/gateway-sessions.js +378 -0
- package/dist/sessions/gateway-sessions.js.map +1 -0
- package/dist/sessions/goals.d.ts +31 -0
- package/dist/sessions/goals.js +75 -0
- package/dist/sessions/goals.js.map +1 -0
- package/dist/sessions/journal.d.ts +5 -79
- package/dist/sessions/journal.js +15 -606
- package/dist/sessions/journal.js.map +1 -1
- package/dist/sessions/list.d.ts +27 -18
- package/dist/sessions/list.js +133 -131
- package/dist/sessions/list.js.map +1 -1
- package/dist/sessions/merge.d.ts +68 -10
- package/dist/sessions/merge.js +259 -51
- package/dist/sessions/merge.js.map +1 -1
- package/dist/sessions/notices.d.ts +22 -0
- package/dist/sessions/notices.js +72 -0
- package/dist/sessions/notices.js.map +1 -0
- package/dist/sessions/pending.d.ts +10 -4
- package/dist/sessions/pending.js +83 -7
- package/dist/sessions/pending.js.map +1 -1
- package/dist/sessions/prefix-index.d.ts +82 -0
- package/dist/sessions/prefix-index.js +232 -0
- package/dist/sessions/prefix-index.js.map +1 -0
- package/dist/sessions/recovery.d.ts +4 -7
- package/dist/sessions/recovery.js +97 -281
- package/dist/sessions/recovery.js.map +1 -1
- package/dist/sessions/relay.d.ts +20 -20
- package/dist/sessions/relay.js +205 -127
- package/dist/sessions/relay.js.map +1 -1
- package/dist/sessions/service.d.ts +162 -59
- package/dist/sessions/service.js +1133 -521
- package/dist/sessions/service.js.map +1 -1
- package/dist/sessions/session.d.ts +18 -2
- package/dist/sessions/session.js +29 -5
- package/dist/sessions/session.js.map +1 -1
- package/dist/sessions/shares.d.ts +7 -6
- package/dist/sessions/shares.js +22 -45
- package/dist/sessions/shares.js.map +1 -1
- package/dist/sessions/source-kind.js +1 -0
- package/dist/sessions/source-kind.js.map +1 -1
- package/dist/sessions/state-db-identity.d.ts +18 -0
- package/dist/sessions/state-db-identity.js +67 -0
- package/dist/sessions/state-db-identity.js.map +1 -0
- package/dist/sessions/state-db-worker.js +3 -1
- package/dist/sessions/state-db-worker.js.map +1 -1
- package/dist/sessions/state-db.d.ts +53 -8
- package/dist/sessions/state-db.js +576 -50
- package/dist/sessions/state-db.js.map +1 -1
- package/dist/sessions/storage/backend.d.ts +162 -0
- package/dist/sessions/storage/backend.js +19 -0
- package/dist/sessions/storage/backend.js.map +1 -0
- package/dist/sessions/storage/conformance.d.ts +20 -0
- package/dist/sessions/storage/conformance.js +237 -0
- package/dist/sessions/storage/conformance.js.map +1 -0
- package/dist/sessions/storage/document.d.ts +16 -0
- package/dist/sessions/storage/document.js +44 -0
- package/dist/sessions/storage/document.js.map +1 -0
- package/dist/sessions/storage/json-documents.d.ts +23 -0
- package/dist/sessions/storage/json-documents.js +233 -0
- package/dist/sessions/storage/json-documents.js.map +1 -0
- package/dist/sessions/storage/json-files.d.ts +12 -0
- package/dist/sessions/storage/json-files.js +124 -0
- package/dist/sessions/storage/json-files.js.map +1 -0
- package/dist/sessions/storage/json-installation.d.ts +3 -0
- package/dist/sessions/storage/json-installation.js +31 -0
- package/dist/sessions/storage/json-installation.js.map +1 -0
- package/dist/sessions/storage/json-journal.d.ts +114 -0
- package/dist/sessions/storage/json-journal.js +686 -0
- package/dist/sessions/storage/json-journal.js.map +1 -0
- package/dist/sessions/storage/json-recovery.d.ts +4 -0
- package/dist/sessions/storage/json-recovery.js +195 -0
- package/dist/sessions/storage/json-recovery.js.map +1 -0
- package/dist/sessions/storage/json.d.ts +68 -0
- package/dist/sessions/storage/json.js +258 -0
- package/dist/sessions/storage/json.js.map +1 -0
- package/dist/sessions/storage/row.d.ts +6 -0
- package/dist/sessions/storage/row.js +49 -0
- package/dist/sessions/storage/row.js.map +1 -0
- package/dist/sessions/storage/search-text.d.ts +4 -0
- package/dist/sessions/storage/search-text.js +16 -0
- package/dist/sessions/storage/search-text.js.map +1 -0
- package/dist/sessions/store.d.ts +63 -73
- package/dist/sessions/store.js +305 -611
- package/dist/sessions/store.js.map +1 -1
- package/dist/sessions/streams.d.ts +4 -0
- package/dist/sessions/streams.js +9 -1
- package/dist/sessions/streams.js.map +1 -1
- package/dist/sessions/titles.js +1 -1
- package/dist/sessions/titles.js.map +1 -1
- package/dist/sessions/todo.d.ts +5 -0
- package/dist/sessions/todo.js +28 -21
- package/dist/sessions/todo.js.map +1 -1
- package/dist/sessions/tool-display.d.ts +5 -4
- package/dist/sessions/tool-display.js +22 -16
- package/dist/sessions/tool-display.js.map +1 -1
- package/dist/sessions/turn-context.d.ts +10 -1
- package/dist/sessions/turn-context.js +7 -4
- package/dist/sessions/turn-context.js.map +1 -1
- package/dist/sessions/turn.d.ts +87 -17
- package/dist/sessions/turn.js +795 -347
- package/dist/sessions/turn.js.map +1 -1
- package/dist/sessions/wakeup-pause.d.ts +8 -13
- package/dist/sessions/wakeup-pause.js +31 -49
- package/dist/sessions/wakeup-pause.js.map +1 -1
- package/dist/sessions/window.js +13 -12
- package/dist/sessions/window.js.map +1 -1
- package/dist/settings.d.ts +19 -7
- package/dist/settings.js +179 -183
- package/dist/settings.js.map +1 -1
- package/dist/sidecar/client.d.ts +17 -3
- package/dist/sidecar/client.js +78 -8
- package/dist/sidecar/client.js.map +1 -1
- package/dist/sidecar/discover.d.ts +2 -1
- package/dist/sidecar/discover.js +93 -10
- package/dist/sidecar/discover.js.map +1 -1
- package/dist/sidecar/env.d.ts +4 -0
- package/dist/sidecar/env.js +3 -0
- package/dist/sidecar/env.js.map +1 -0
- package/dist/sidecar/fake.js +19 -2
- package/dist/sidecar/fake.js.map +1 -1
- package/dist/test/env-file.d.ts +5 -0
- package/dist/test/env-file.js +88 -0
- package/dist/test/env-file.js.map +1 -0
- package/dist/test/harness.d.ts +1 -0
- package/dist/test/harness.js +1 -1
- package/dist/test/harness.js.map +1 -1
- package/dist/test/passkeys.d.ts +22 -0
- package/dist/test/passkeys.js +62 -0
- package/dist/test/passkeys.js.map +1 -0
- package/dist/test/storage.d.ts +15 -0
- package/dist/test/storage.js +26 -0
- package/dist/test/storage.js.map +1 -0
- package/dist/tools/commands.d.ts +6 -1
- package/dist/tools/commands.js +8 -2
- package/dist/tools/commands.js.map +1 -1
- package/dist/tools/connectors.d.ts +33 -0
- package/dist/tools/connectors.js +121 -0
- package/dist/tools/connectors.js.map +1 -0
- package/dist/tools/crons.d.ts +38 -1
- package/dist/tools/crons.js +82 -15
- package/dist/tools/crons.js.map +1 -1
- package/dist/tools/dashboard-plugins.d.ts +5 -5
- package/dist/tools/dashboard-plugins.js +14 -14
- package/dist/tools/dashboard-plugins.js.map +1 -1
- package/dist/tools/extensions.d.ts +5 -4
- package/dist/tools/extensions.js +213 -207
- package/dist/tools/extensions.js.map +1 -1
- package/dist/tools/gateway-restart.d.ts +62 -0
- package/dist/tools/gateway-restart.js +142 -0
- package/dist/tools/gateway-restart.js.map +1 -0
- package/dist/tools/health.d.ts +15 -3
- package/dist/tools/health.js +97 -34
- package/dist/tools/health.js.map +1 -1
- package/dist/tools/hygiene.d.ts +4 -3
- package/dist/tools/hygiene.js +23 -9
- package/dist/tools/hygiene.js.map +1 -1
- package/dist/tools/kanban.d.ts +4 -2
- package/dist/tools/kanban.js +28 -19
- package/dist/tools/kanban.js.map +1 -1
- package/dist/tools/memory-masks.d.ts +5 -0
- package/dist/tools/memory-masks.js +256 -0
- package/dist/tools/memory-masks.js.map +1 -0
- package/dist/tools/memory.d.ts +29 -3
- package/dist/tools/memory.js +69 -27
- package/dist/tools/memory.js.map +1 -1
- package/dist/tools/plugin-settings.d.ts +15 -0
- package/dist/tools/plugin-settings.js +90 -0
- package/dist/tools/plugin-settings.js.map +1 -0
- package/dist/tools/skills.d.ts +9 -4
- package/dist/tools/skills.js +44 -13
- package/dist/tools/skills.js.map +1 -1
- package/dist/tools/update-notifications.d.ts +34 -15
- package/dist/tools/update-notifications.js +141 -57
- package/dist/tools/update-notifications.js.map +1 -1
- package/dist/tools/update-rollback.d.ts +11 -0
- package/dist/tools/update-rollback.js +28 -0
- package/dist/tools/update-rollback.js.map +1 -0
- package/dist/tools/updates.d.ts +93 -33
- package/dist/tools/updates.js +1051 -345
- package/dist/tools/updates.js.map +1 -1
- package/dist/util.d.ts +2 -0
- package/dist/util.js +5 -0
- package/dist/util.js.map +1 -1
- package/dist/workspace/git.d.ts +16 -1
- package/dist/workspace/git.js +291 -11
- package/dist/workspace/git.js.map +1 -1
- package/dist/workspace/media.d.ts +12 -9
- package/dist/workspace/media.js +31 -20
- package/dist/workspace/media.js.map +1 -1
- package/dist/workspace/rollback.d.ts +2 -2
- package/dist/workspace/rollback.js +5 -5
- package/dist/workspace/rollback.js.map +1 -1
- package/dist/workspace/workspaces.d.ts +15 -19
- package/dist/workspace/workspaces.js +55 -127
- package/dist/workspace/workspaces.js.map +1 -1
- package/dist/workspace/worktrees.js +170 -32
- package/dist/workspace/worktrees.js.map +1 -1
- package/package.json +5 -3
- package/sidecar/agent_dependency.json +4 -4
- package/sidecar/agent_support.json +26 -0
- package/sidecar/scripts/record-fixtures.py +12 -3
- package/sidecar/scripts/replay_sidecar.py +8 -0
- package/sidecar/scripts/suite_runner.py +302 -0
- package/sidecar/scripts/test.sh +12 -4
- package/sidecar/talaria_sidecar/__init__.py +6 -1
- package/sidecar/talaria_sidecar/__main__.py +4 -2
- package/sidecar/talaria_sidecar/agent_mutation.py +975 -0
- package/sidecar/talaria_sidecar/agent_services.py +1053 -0
- package/sidecar/talaria_sidecar/dependency_sync.py +85 -0
- package/sidecar/talaria_sidecar/home.py +43 -1
- package/sidecar/talaria_sidecar/methods/__init__.py +2 -2
- package/sidecar/talaria_sidecar/methods/aux.py +139 -31
- package/sidecar/talaria_sidecar/methods/chat.py +847 -134
- package/sidecar/talaria_sidecar/methods/commands.py +213 -4
- package/sidecar/talaria_sidecar/methods/config.py +123 -4
- package/sidecar/talaria_sidecar/methods/connectors.py +343 -0
- package/sidecar/talaria_sidecar/methods/cron.py +366 -34
- package/sidecar/talaria_sidecar/methods/cron_execution.py +284 -0
- package/sidecar/talaria_sidecar/methods/gateway.py +194 -54
- package/sidecar/talaria_sidecar/methods/gateway_sessions.py +234 -0
- package/sidecar/talaria_sidecar/methods/goals.py +81 -41
- package/sidecar/talaria_sidecar/methods/kanban.py +80 -27
- package/sidecar/talaria_sidecar/methods/memory.py +84 -0
- package/sidecar/talaria_sidecar/methods/oauth.py +5 -2
- package/sidecar/talaria_sidecar/methods/process.py +160 -11
- package/sidecar/talaria_sidecar/methods/profiles.py +44 -6
- package/sidecar/talaria_sidecar/methods/providers.py +196 -26
- package/sidecar/talaria_sidecar/methods/runtime.py +69 -1
- package/sidecar/talaria_sidecar/methods/skills.py +67 -4
- package/sidecar/talaria_sidecar/methods/state_db.py +277 -70
- package/sidecar/talaria_sidecar/methods/stt.py +159 -78
- package/sidecar/talaria_sidecar/methods/text.py +14 -1
- package/sidecar/talaria_sidecar/methods/toolsets.py +49 -0
- package/sidecar/talaria_sidecar/methods/usage.py +113 -14
- package/sidecar/talaria_sidecar/methods/worktree.py +26 -19
- package/sidecar/talaria_sidecar/methods/write_approval.py +181 -0
- package/sidecar/talaria_sidecar/rpc.py +45 -4
- package/sidecar/talaria_sidecar/runtime.py +81 -12
- package/sidecar/talaria_sidecar/speed.py +35 -0
- package/static/dist/FILES.txt +126 -127
- package/static/dist/assets/AppShell-cey33v9s.js +8 -0
- package/static/dist/assets/ChatPage-i8wnugr7.js +18 -0
- package/static/dist/assets/ConnectTargets-hg19553x.js +1 -0
- package/static/dist/assets/ExtensionRoute-cly4apm5.js +1 -0
- package/static/dist/assets/Field-j8uqoigz.js +9 -0
- package/static/dist/assets/HubRoute-e4bgz41j.js +2 -0
- package/static/dist/assets/Markdown-lahuichm.js +598 -0
- package/static/dist/assets/RightPanel-lbo4i0fn.js +1 -0
- package/static/dist/assets/Select-gqatm2e0.js +1 -0
- package/static/dist/assets/SessionListPanel-mfqayfjh.js +1 -0
- package/static/dist/assets/SettingsLayout-b8980u7k.js +1 -0
- package/static/dist/assets/States-e7dkgtxf.js +1 -0
- package/static/dist/assets/Toaster-bfqqy786.js +1 -0
- package/static/dist/assets/_app-n1n6pfx1.js +1 -0
- package/static/dist/assets/{_app.ext._extensionId-gfbzpoou.js → _app.ext._extensionId-buxjxav3.js} +1 -1
- package/static/dist/assets/_app.index-jt8zwiu2.js +1 -0
- package/static/dist/assets/_app.insights-cv76ml71.js +1 -0
- package/static/dist/assets/_app.kanban-h6ts53j7.js +1 -0
- package/static/dist/assets/_app.logs-dm873z90.js +1 -0
- package/static/dist/assets/_app.memory-glk5y6m8.js +1 -0
- package/static/dist/assets/_app.profiles-ka6zpstq.js +1 -0
- package/static/dist/assets/{_app.session._sessionId-fn1bhde6.js → _app.session._sessionId-g2vzghvc.js} +1 -1
- package/static/dist/assets/_app.settings-hgjdhzcd.js +1 -0
- package/static/dist/assets/_app.settings._section-jf2kmhae.js +3 -0
- package/static/dist/assets/_app.skills-cii852yq.js +1 -0
- package/static/dist/assets/_app.tasks-fp9q7atm.js +1 -0
- package/static/dist/assets/_app.todos-dw94qzue.js +1 -0
- package/static/dist/assets/_app.workspaces-inyygzze.js +1 -0
- package/static/dist/assets/{abnfDiagram-VCTEODGH-c8kdixke.js → abnfDiagram-VCTEODGH-gjayq3ra.js} +1 -1
- package/static/dist/assets/architecture-7GRP2DOG-lp56972r.js +1 -0
- package/static/dist/assets/{architectureDiagram-5GKGNRK7-cku06x1p.js → architectureDiagram-5GKGNRK7-nwb3xovn.js} +1 -1
- package/static/dist/assets/archive-b1j004vn.js +1 -0
- package/static/dist/assets/back-g74gkozu.js +1 -0
- package/static/dist/assets/{blockDiagram-I7D4REHJ-jzthp1wa.js → blockDiagram-I7D4REHJ-joedghi3.js} +1 -1
- package/static/dist/assets/{c4Diagram-7LVT6UL2-mwr67mt8.js → c4Diagram-7LVT6UL2-hyrjrohe.js} +1 -1
- package/static/dist/assets/channel-es95o4y8.js +1 -0
- package/static/dist/assets/{chunk-4HAMMTFA-gpq1y228.js → chunk-4HAMMTFA-koouqbut.js} +1 -1
- package/static/dist/assets/{chunk-75Z2AOVW-ktje58c4.js → chunk-75Z2AOVW-bl4bhdnt.js} +1 -1
- package/static/dist/assets/{chunk-DU6HZSFF-ofajdixh.js → chunk-DU6HZSFF-gpedttsp.js} +3 -3
- package/static/dist/assets/{chunk-F27PBJKO-cmev85ti.js → chunk-F27PBJKO-d8xxi0zi.js} +1 -1
- package/static/dist/assets/{chunk-GMAD6QVW-htjgt22y.js → chunk-GMAD6QVW-jro0hl73.js} +1 -1
- package/static/dist/assets/{chunk-GVQU2GXP-qndvoxl7.js → chunk-GVQU2GXP-djn6gbyu.js} +1 -1
- package/static/dist/assets/{chunk-IMKFNOWR-e5bkd5q6.js → chunk-IMKFNOWR-vw4p5p7o.js} +1 -1
- package/static/dist/assets/{chunk-L3NEJ4N5-mj1155r6.js → chunk-L3NEJ4N5-n1hj77q8.js} +1 -1
- package/static/dist/assets/{chunk-OSK3NFVY-e7gkikcw.js → chunk-OSK3NFVY-oy0gwn2n.js} +1 -1
- package/static/dist/assets/{chunk-P2QGCYS3-f7t54xfm.js → chunk-P2QGCYS3-onf1hz6c.js} +1 -1
- package/static/dist/assets/{chunk-POPQ4Y6H-i927v9oa.js → chunk-POPQ4Y6H-m8sqn7cs.js} +1 -1
- package/static/dist/assets/{chunk-PWAF6VOD-m84lmnyt.js → chunk-PWAF6VOD-ek4smc8x.js} +1 -1
- package/static/dist/assets/{chunk-SHT3W25Y-mi0tlcu9.js → chunk-SHT3W25Y-g9gfvefo.js} +3 -3
- package/static/dist/assets/{chunk-SVP7TREG-dnau702j.js → chunk-SVP7TREG-f9nfv2cu.js} +1 -1
- package/static/dist/assets/{chunk-TICWLB2K-edem1gkg.js → chunk-TICWLB2K-bnk3m1mq.js} +1 -1
- package/static/dist/assets/classDiagram-ZZMXUADV-kmihoqxh.js +1 -0
- package/static/dist/assets/classDiagram-v2-VYDZK3BY-kmihoqxh.js +1 -0
- package/static/dist/assets/copied-bli9tbcx.js +1 -0
- package/static/dist/assets/{copy-magtofyp.js → copy-jamtd1pf.js} +1 -1
- package/static/dist/assets/{cynefin-OW5HDTMX-siqlulkl.js → cynefin-OW5HDTMX-f8xfdd3f.js} +1 -1
- package/static/dist/assets/{cynefinDiagram-5FMLGOSQ-i648tah9.js → cynefinDiagram-5FMLGOSQ-n9lb99h9.js} +1 -1
- package/static/dist/assets/{dagre-GXQ25YYZ-mwn6uc17.js → dagre-GXQ25YYZ-dgailddi.js} +4 -4
- package/static/dist/assets/{diagram-S7CK7UJ4-l8abxaes.js → diagram-S7CK7UJ4-m6aeoe7c.js} +1 -1
- package/static/dist/assets/{diagram-UQ7AKVKN-mekq7zgq.js → diagram-UQ7AKVKN-jall3j0x.js} +1 -1
- package/static/dist/assets/{diagram-VSXAHHWV-fnky6lvc.js → diagram-VSXAHHWV-hbawi7hn.js} +1 -1
- package/static/dist/assets/{diagram-VX7I27RA-xe6r5qfw.js → diagram-VX7I27RA-hendl2tt.js} +1 -1
- package/static/dist/assets/{diagram-Z3DM3KII-nq07dg7k.js → diagram-Z3DM3KII-igwc35p3.js} +1 -1
- package/static/dist/assets/{ebnfDiagram-PWID7BFC-c62ipm3g.js → ebnfDiagram-PWID7BFC-c64knz08.js} +1 -1
- package/static/dist/assets/{erDiagram-RLTQ6QDP-h39kmnzy.js → erDiagram-RLTQ6QDP-brdu9lcm.js} +1 -1
- package/static/dist/assets/eventmodeling-NTZA5JFV-njk1j8wl.js +1 -0
- package/static/dist/assets/flowDiagram-HODETNUW-nma6f0ga.js +1 -0
- package/static/dist/assets/folder-plus-lvt9kudb.js +1 -0
- package/static/dist/assets/{ganttDiagram-EL5Y4UJY-ngbsyp37.js → ganttDiagram-EL5Y4UJY-ma6jxj5i.js} +1 -1
- package/static/dist/assets/{gitGraph-4MIJSDKK-fr2i7caa.js → gitGraph-4MIJSDKK-naa9w6xa.js} +1 -1
- package/static/dist/assets/{gitGraphDiagram-WWUBYQGX-eravdti4.js → gitGraphDiagram-WWUBYQGX-hzltvsod.js} +1 -1
- package/static/dist/assets/{highlighted-body-KPVGNVTW-jwpop9p8.js → highlighted-body-KPVGNVTW-ghoavj8d.js} +1 -1
- package/static/dist/assets/host-hzm8n85n.js +1 -0
- package/static/dist/assets/index-drdcaqeq.css +2 -0
- package/static/dist/assets/index-jzm844he.js +11 -0
- package/static/dist/assets/{info-A6RAGUB7-h11x0dxo.js → info-A6RAGUB7-mn2ut5ko.js} +1 -1
- package/static/dist/assets/{infoDiagram-27XIBGKW-dfh47dw9.js → infoDiagram-27XIBGKW-h6kuqvsb.js} +1 -1
- package/static/dist/assets/{ishikawaDiagram-5VMMS53U-i6ypq351.js → ishikawaDiagram-5VMMS53U-e7bnwq7h.js} +1 -1
- package/static/dist/assets/{journeyDiagram-3NMN7TZE-lduf1z95.js → journeyDiagram-3NMN7TZE-etd1bi6p.js} +1 -1
- package/static/dist/assets/{kanban-definition-UXKFOSKX-e18bu4pg.js → kanban-definition-UXKFOSKX-emb1g9dz.js} +4 -4
- package/static/dist/assets/lazyRouteComponent-o816ytzl.js +1 -0
- package/static/dist/assets/{line-meizqsvn.js → line-h0ojzsvs.js} +1 -1
- package/static/dist/assets/link-k01ryaf9.js +1 -0
- package/static/dist/assets/login-bsae49ew.js +1 -0
- package/static/dist/assets/mermaid-HWGCJPDP-ihl34s74.js +1 -0
- package/static/dist/assets/{mermaid-parser.core-ntne45i9.js → mermaid-parser.core-bnre27u8.js} +3 -3
- package/static/dist/assets/{mindmap-definition-YA3MSWOX-27b26eok.js → mindmap-definition-YA3MSWOX-o1vathns.js} +1 -1
- package/static/dist/assets/onboarding-c65tysya.js +1 -0
- package/static/dist/assets/onboarding_model_label-gpn28uix.js +1 -0
- package/static/dist/assets/{packet-AYTQ26CC-l6jdka8p.js → packet-AYTQ26CC-hatq7m2e.js} +1 -1
- package/static/dist/assets/pcmTap.worklet-74EKjWAZ.js +1 -0
- package/static/dist/assets/{pegDiagram-XKGWAZYB-g1er3bxj.js → pegDiagram-XKGWAZYB-gwisz8jv.js} +1 -1
- package/static/dist/assets/{pie-WAS4IAKB-i0ylcrt9.js → pie-WAS4IAKB-fpftf0mk.js} +1 -1
- package/static/dist/assets/{pieDiagram-E7YTZNPT-fbz1e55z.js → pieDiagram-E7YTZNPT-khm1o9a6.js} +1 -1
- package/static/dist/assets/{quadrantDiagram-AXDQQJYC-hhue7d8o.js → quadrantDiagram-AXDQQJYC-owqc4uqn.js} +1 -1
- package/static/dist/assets/{radar-RG4KPBEZ-f9b70aa4.js → radar-RG4KPBEZ-cntfwjpq.js} +1 -1
- package/static/dist/assets/{railroad-74A4TZTK-lgsuoeda.js → railroad-74A4TZTK-a7t5eibp.js} +1 -1
- package/static/dist/assets/railroad-abnf-HS5TGJTU-ol8cdktf.js +1 -0
- package/static/dist/assets/railroad-ebnf-LZEXJU2U-i8vzd429.js +1 -0
- package/static/dist/assets/railroad-peg-WCYAUIDC-nw3ulewz.js +1 -0
- package/static/dist/assets/{railroadDiagram-O6MQD6OU-eqpy9fnz.js → railroadDiagram-O6MQD6OU-etuh0qa0.js} +1 -1
- package/static/dist/assets/{refresh-cw-hlwb02qv.js → refresh-cw-mqbkv2a3.js} +1 -1
- package/static/dist/assets/refresh-l29ljp76.js +1 -0
- package/static/dist/assets/{requirementDiagram-BXWQKSXE-ogf6puhi.js → requirementDiagram-BXWQKSXE-oq2ulk22.js} +1 -1
- package/static/dist/assets/{sankeyDiagram-P5KCCOFB-fqb8xcjf.js → sankeyDiagram-P5KCCOFB-iqc02emv.js} +1 -1
- package/static/dist/assets/saved-ndd4t2xb.js +1 -0
- package/static/dist/assets/{sequenceDiagram-WJ2MYXX4-dlcz6qjz.js → sequenceDiagram-WJ2MYXX4-i0v116q0.js} +2 -2
- package/static/dist/assets/settings_section_extensions_title-jhfo6o8z.js +1 -0
- package/static/dist/assets/share._token-c1ri0hy1.js +2 -0
- package/static/dist/assets/sliders-horizontal-j3jjt9tv.js +1 -0
- package/static/dist/assets/{stateDiagram-D77RDMKH-fyoznpcs.js → stateDiagram-D77RDMKH-dnpt1ato.js} +1 -1
- package/static/dist/assets/stateDiagram-v2-MP3YSRHH-bxjacpk6.js +1 -0
- package/static/dist/assets/{swimlanes-42K2YHIH-oefldhfy.js → swimlanes-42K2YHIH-loqbdazb.js} +1 -1
- package/static/dist/assets/swimlanesDiagram-VR7AAH4N-id62p9hz.js +8 -0
- package/static/dist/assets/{timeline-definition-24CTP7MA-b1vl2zil.js → timeline-definition-24CTP7MA-ol2hnvma.js} +1 -1
- package/static/dist/assets/toast-i3h34v6o.js +64 -0
- package/static/dist/assets/{treeView-Q6P3EWNA-f7hcci5o.js → treeView-Q6P3EWNA-idrj6iox.js} +1 -1
- package/static/dist/assets/{treemap-WGGIJYW6-nl85071a.js → treemap-WGGIJYW6-lzr49vv5.js} +1 -1
- package/static/dist/assets/untitled-oaoya4qj.js +1 -0
- package/static/dist/assets/useForm-nfaxgmsk.js +1 -0
- package/static/dist/assets/{useParams-b4dq6n4q.js → useParams-gjc70qru.js} +1 -1
- package/static/dist/assets/{useSearch-ipfmv3he.js → useSearch-e6ae539u.js} +1 -1
- package/static/dist/assets/{vennDiagram-4TSXK5OY-h5hzbk0n.js → vennDiagram-4TSXK5OY-bvwr9o2z.js} +1 -1
- package/static/dist/assets/{wardley-WFR3VGLG-jftvpm3e.js → wardley-WFR3VGLG-31ui8tma.js} +1 -1
- package/static/dist/assets/{wardleyDiagram-VM6X3IG4-hedh85ge.js → wardleyDiagram-VM6X3IG4-k5wqtx4b.js} +1 -1
- package/static/dist/assets/{xychartDiagram-S5SC5T6Z-e49523ab.js → xychartDiagram-S5SC5T6Z-aqbgvujg.js} +1 -1
- package/static/dist/index.html +1 -1
- package/static/dist/sw.js +1 -1
- package/static/dist/assets/AppShell-g3bkgnvt.js +0 -1
- package/static/dist/assets/ChatPage-oo7bdan6.js +0 -25
- package/static/dist/assets/Dialog-g355qxhp.js +0 -1
- package/static/dist/assets/ExtensionRoute-i2y9fvjm.js +0 -1
- package/static/dist/assets/HubRoute-lmkrbw47.js +0 -2
- package/static/dist/assets/Markdown-j4kut4j2.js +0 -598
- package/static/dist/assets/RightPanel-ohlsdzfl.js +0 -1
- package/static/dist/assets/Select-kddq75qc.js +0 -1
- package/static/dist/assets/SessionListPanel-lu3oy0hw.js +0 -1
- package/static/dist/assets/SettingsLayout-o9bv4mgb.js +0 -1
- package/static/dist/assets/States-eq6fe29m.js +0 -1
- package/static/dist/assets/Toaster-pc247u9f.js +0 -1
- package/static/dist/assets/_app-f8n1i0m1.js +0 -1
- package/static/dist/assets/_app.index-bzzv80hk.js +0 -1
- package/static/dist/assets/_app.insights-dzixbryi.js +0 -1
- package/static/dist/assets/_app.kanban-c6hep2us.js +0 -1
- package/static/dist/assets/_app.logs-i69qds98.js +0 -1
- package/static/dist/assets/_app.memory-kl4vf0gd.js +0 -1
- package/static/dist/assets/_app.profiles-b8zinmyp.js +0 -1
- package/static/dist/assets/_app.settings-cg8plwmf.js +0 -1
- package/static/dist/assets/_app.settings._section-bkwbi9zn.js +0 -3
- package/static/dist/assets/_app.skills-cs47sbvs.js +0 -1
- package/static/dist/assets/_app.tasks-dwvk64tc.js +0 -1
- package/static/dist/assets/_app.todos-c8xjm8p3.js +0 -1
- package/static/dist/assets/_app.workspaces-ehvd1gds.js +0 -1
- package/static/dist/assets/architecture-7GRP2DOG-6crvnylg.js +0 -1
- package/static/dist/assets/back-h7aun7ew.js +0 -1
- package/static/dist/assets/cancel-fhi0vcnu.js +0 -1
- package/static/dist/assets/channel-b2zo73z1.js +0 -1
- package/static/dist/assets/classDiagram-ZZMXUADV-oe99st8x.js +0 -1
- package/static/dist/assets/classDiagram-v2-VYDZK3BY-oe99st8x.js +0 -1
- package/static/dist/assets/copied-hcplv46p.js +0 -1
- package/static/dist/assets/endpoints-klbxod4t.js +0 -64
- package/static/dist/assets/eventmodeling-NTZA5JFV-obfede4u.js +0 -1
- package/static/dist/assets/flowDiagram-HODETNUW-kdpsp1je.js +0 -1
- package/static/dist/assets/host-i828xuo7.js +0 -1
- package/static/dist/assets/index-eh8zilnv.css +0 -2
- package/static/dist/assets/index-r648f4o1.js +0 -11
- package/static/dist/assets/lazyRouteComponent-e1y4t2i9.js +0 -1
- package/static/dist/assets/link-oot2yn73.js +0 -1
- package/static/dist/assets/login-gu28l9ou.js +0 -1
- package/static/dist/assets/mermaid-HWGCJPDP-mtwrj8fn.js +0 -1
- package/static/dist/assets/onboarding-lkphzu1s.js +0 -1
- package/static/dist/assets/onboarding_model_label-ftpjdwqk.js +0 -1
- package/static/dist/assets/railroad-abnf-HS5TGJTU-nf9d6pdx.js +0 -1
- package/static/dist/assets/railroad-ebnf-LZEXJU2U-f7ummkt5.js +0 -1
- package/static/dist/assets/railroad-peg-WCYAUIDC-oczq5tqs.js +0 -1
- package/static/dist/assets/refresh-abtu93ke.js +0 -1
- package/static/dist/assets/saved-girnabkf.js +0 -1
- package/static/dist/assets/settings_section_extensions_title-h14cwk6f.js +0 -1
- package/static/dist/assets/share._token-kl0r7ido.js +0 -2
- package/static/dist/assets/sliders-horizontal-n1zm34qq.js +0 -1
- package/static/dist/assets/sse-iwku0sjo.js +0 -1
- package/static/dist/assets/stateDiagram-v2-MP3YSRHH-ixhx8r46.js +0 -1
- package/static/dist/assets/swimlanesDiagram-VR7AAH4N-h9ersk2e.js +0 -8
- package/static/dist/assets/todoStore-jjr5yr78.js +0 -1
- package/static/dist/assets/units-kgxzxfhi.js +0 -1
- package/static/dist/assets/untitled-cikfjntn.js +0 -1
- package/static/dist/assets/useForm-kqoqg0k9.js +0 -1
- package/static/dist/assets/useLocale-o59tbiea.js +0 -1
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"""``write_approval.*``: the Agent's staged skill and memory writes (TAL-819).
|
|
2
|
+
|
|
3
|
+
With ``skills.write_approval`` or ``memory.write_approval`` on, the Agent stages writes under
|
|
4
|
+
``<home>/pending/<kind>/<id>.json`` instead of committing them. These methods list them with
|
|
5
|
+
the diff an approval would apply, and approve or reject them through the Agent's own
|
|
6
|
+
``/skills`` and ``/memory`` review handlers.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import contextlib
|
|
12
|
+
import difflib
|
|
13
|
+
import hashlib
|
|
14
|
+
import re
|
|
15
|
+
import tempfile
|
|
16
|
+
import threading
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
|
|
19
|
+
from ..errors import InvalidParams, RpcError
|
|
20
|
+
from ..home import profile_home_param, scoped_home
|
|
21
|
+
from ..rpc import CallContext
|
|
22
|
+
|
|
23
|
+
KINDS = ("skills", "memory")
|
|
24
|
+
# The Agent names records ``uuid4().hex[:8]`` and builds their path from the id; anything else could leave the pending dir.
|
|
25
|
+
_ID = re.compile(r"[A-Za-z0-9_-]{1,64}")
|
|
26
|
+
# One review at a time in this process, so two approvals of one record cannot both replay it.
|
|
27
|
+
_LOCK = threading.Lock()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _agent():
|
|
31
|
+
try:
|
|
32
|
+
from hermes_cli import write_approval_commands
|
|
33
|
+
from tools import write_approval
|
|
34
|
+
except ImportError as exc:
|
|
35
|
+
raise RpcError("This Hermes Agent cannot review staged writes", condition="write_approval_unavailable") from exc
|
|
36
|
+
return write_approval, write_approval_commands
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _kind(params: dict) -> str:
|
|
40
|
+
kind = str(params.get("kind") or "")
|
|
41
|
+
if kind not in KINDS:
|
|
42
|
+
raise InvalidParams("kind must be skills or memory")
|
|
43
|
+
return kind
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _memory_diff(payload: dict) -> str:
|
|
47
|
+
"""Replay the record on a scratch copy of its file through the Agent's approve path; the diff is what approval commits."""
|
|
48
|
+
from tools.memory_tool import ENTRY_DELIMITER, apply_memory_pending, load_on_disk_store
|
|
49
|
+
|
|
50
|
+
store = load_on_disk_store()
|
|
51
|
+
target = "user" if payload.get("target") == "user" else "memory"
|
|
52
|
+
real = store._path_for(target)
|
|
53
|
+
before = list(store._entries_for(target))
|
|
54
|
+
with tempfile.TemporaryDirectory(prefix="talaria-pending-") as scratch:
|
|
55
|
+
copy = Path(scratch) / real.name
|
|
56
|
+
if real.is_file():
|
|
57
|
+
copy.write_bytes(real.read_bytes())
|
|
58
|
+
# The store resolves every read, lock and write through ``self._path_for``.
|
|
59
|
+
store._path_for = lambda t: Path(scratch) / ("USER.md" if t == "user" else "MEMORY.md")
|
|
60
|
+
result = apply_memory_pending(payload, store)
|
|
61
|
+
after = list(store._entries_for(target))
|
|
62
|
+
if not result.get("success"):
|
|
63
|
+
raise _Unapprovable(f"(approve would fail: {result.get('error') or 'unknown error'})")
|
|
64
|
+
lines = lambda entries: ENTRY_DELIMITER.join(entries).splitlines(keepends=True) # noqa: E731
|
|
65
|
+
diff = difflib.unified_diff(lines(before), lines(after), fromfile=f"a/{real.name}", tofile=f"b/{real.name}")
|
|
66
|
+
return "".join(diff) or "(no textual change)"
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class _Unapprovable(Exception):
|
|
70
|
+
"""A write with no diff the user could review: its message replaces the diff and approval is refused."""
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _skill_names(payload: dict) -> list[str]:
|
|
74
|
+
ops = payload.get("operations") or [] if payload.get("action") == "batch" else [payload]
|
|
75
|
+
return list(dict.fromkeys(str(op.get("name")) for op in ops if isinstance(op, dict) and op.get("name")))
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _item(wa, kind: str, record: dict) -> dict:
|
|
79
|
+
payload = record.get("payload") if isinstance(record.get("payload"), dict) else {}
|
|
80
|
+
if kind == "memory":
|
|
81
|
+
target = "user" if payload.get("target") == "user" else "memory"
|
|
82
|
+
else:
|
|
83
|
+
target = ", ".join(_skill_names(payload))
|
|
84
|
+
diff, approvable = _diff(wa, kind, record)
|
|
85
|
+
return {
|
|
86
|
+
"id": str(record.get("id") or ""), "kind": kind, "target": target, "op": str(payload.get("action") or record.get("action") or ""),
|
|
87
|
+
"summary": str(record.get("summary") or ""), "origin": str(record.get("origin") or "foreground"),
|
|
88
|
+
"created_at": float(record.get("created_at") or 0), "diff": diff,
|
|
89
|
+
"approvable": approvable, "revision": _revision(diff) if approvable else "",
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _diff(wa, kind: str, record: dict) -> tuple[str, bool]:
|
|
94
|
+
"""The diff approving ``record`` applies and whether it may be approved; a diff that cannot be built is never approvable."""
|
|
95
|
+
payload = record.get("payload") if isinstance(record.get("payload"), dict) else {}
|
|
96
|
+
try:
|
|
97
|
+
return (_memory_diff(payload) if kind == "memory" else wa.skill_pending_diff(record)), True
|
|
98
|
+
except _Unapprovable as exc:
|
|
99
|
+
return str(exc), False
|
|
100
|
+
except Exception as exc: # noqa: BLE001 - one unreadable record must not hide the rest
|
|
101
|
+
return f"(diff unavailable: {exc})", False
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _apply_lock(kind: str, record: dict):
|
|
105
|
+
"""Hold the Agent's own per-skill locks across the revision check and the apply (they are re-entrant in this thread, so
|
|
106
|
+
the Agent's apply takes them again). Memory needs none: the Agent applies a staged remove/patch only to the exact entry
|
|
107
|
+
it pinned at staging and an add only appends, so a concurrent write can never be dropped by an approval."""
|
|
108
|
+
if kind != "skills":
|
|
109
|
+
return contextlib.nullcontext()
|
|
110
|
+
from tools.skill_manager_tool import _skill_mutation_locks
|
|
111
|
+
|
|
112
|
+
return _skill_mutation_locks(_skill_names(record.get("payload") if isinstance(record.get("payload"), dict) else {}))
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _revision(diff: str) -> str:
|
|
116
|
+
"""What the reviewer saw: the diff changes whenever the record or the file it applies to does."""
|
|
117
|
+
return hashlib.sha256(diff.encode("utf-8")).hexdigest()
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def pending(kind: str) -> dict:
|
|
121
|
+
try:
|
|
122
|
+
wa, _ = _agent()
|
|
123
|
+
except RpcError:
|
|
124
|
+
return {"supported": False, "enabled": False, "items": []}
|
|
125
|
+
items = [_item(wa, kind, record) for record in wa.list_pending(kind) if _ID.fullmatch(str(record.get("id") or ""))]
|
|
126
|
+
return {"supported": True, "enabled": wa.write_approval_enabled(kind), "items": items}
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def review(kind: str, verb: str, writes: list[dict]) -> dict:
|
|
130
|
+
"""``approve`` or ``reject`` each write through the Agent's handler; a record that is gone afterwards was applied or dropped.
|
|
131
|
+
|
|
132
|
+
An approval applies only while the write's diff still has the ``revision`` the reviewer saw; a changed file or record
|
|
133
|
+
is refused, so nothing lands that the user did not review.
|
|
134
|
+
"""
|
|
135
|
+
wa, commands = _agent()
|
|
136
|
+
if not writes or any(not (isinstance(w, dict) and _ID.fullmatch(str(w.get("id") or "")) and isinstance(w.get("revision"), str)) for w in writes):
|
|
137
|
+
raise InvalidParams("writes must be pending write ids with the revision reviewed")
|
|
138
|
+
results = []
|
|
139
|
+
with _LOCK:
|
|
140
|
+
for write in writes:
|
|
141
|
+
pending_id = write["id"]
|
|
142
|
+
record = wa.get_pending(kind, pending_id)
|
|
143
|
+
if record is None:
|
|
144
|
+
results.append({"id": pending_id, "done": False, "message": f"No pending {kind} write with id '{pending_id}'."})
|
|
145
|
+
continue
|
|
146
|
+
if verb == "reject":
|
|
147
|
+
message = commands.handle_pending_subcommand(kind, [verb, pending_id]) or ""
|
|
148
|
+
else:
|
|
149
|
+
with _apply_lock(kind, record):
|
|
150
|
+
diff, approvable = _diff(wa, kind, record)
|
|
151
|
+
if not approvable:
|
|
152
|
+
results.append({"id": pending_id, "done": False, "message": f"This write cannot be approved: {diff}"})
|
|
153
|
+
continue
|
|
154
|
+
if _revision(diff) != write["revision"]:
|
|
155
|
+
results.append({"id": pending_id, "done": False, "message": "This write's diff changed after you reviewed it. Review the new diff, then approve again."})
|
|
156
|
+
continue
|
|
157
|
+
store = None
|
|
158
|
+
if kind == "memory":
|
|
159
|
+
from tools.memory_tool import load_on_disk_store
|
|
160
|
+
|
|
161
|
+
store = load_on_disk_store()
|
|
162
|
+
message = commands.handle_pending_subcommand(kind, [verb, pending_id], memory_store=store) or ""
|
|
163
|
+
results.append({"id": pending_id, "done": wa.get_pending(kind, pending_id) is None, "message": message})
|
|
164
|
+
return {"results": results}
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def register(registry) -> None:
|
|
168
|
+
@registry.method("write_approval.pending")
|
|
169
|
+
def pending_(ctx: CallContext, params: dict) -> dict:
|
|
170
|
+
kind = _kind(params)
|
|
171
|
+
with scoped_home(profile_home_param(params)):
|
|
172
|
+
return pending(kind)
|
|
173
|
+
|
|
174
|
+
for verb in ("approve", "reject"):
|
|
175
|
+
def handler(ctx: CallContext, params: dict, verb: str = verb) -> dict:
|
|
176
|
+
kind = _kind(params)
|
|
177
|
+
writes = list(params.get("writes") or [])
|
|
178
|
+
with scoped_home(profile_home_param(params)):
|
|
179
|
+
return review(kind, verb, writes)
|
|
180
|
+
|
|
181
|
+
registry.method(f"write_approval.{verb}")(handler)
|
|
@@ -13,6 +13,9 @@ from __future__ import annotations
|
|
|
13
13
|
|
|
14
14
|
import json
|
|
15
15
|
import logging
|
|
16
|
+
import os
|
|
17
|
+
import queue
|
|
18
|
+
import time
|
|
16
19
|
import sys
|
|
17
20
|
import threading
|
|
18
21
|
import traceback
|
|
@@ -121,6 +124,9 @@ class RpcServer:
|
|
|
121
124
|
def request_shutdown(self, exit_code: int = 0) -> None:
|
|
122
125
|
self.exit_code = exit_code
|
|
123
126
|
self._closed.set()
|
|
127
|
+
with self._active_lock:
|
|
128
|
+
for ctx in self._active.values():
|
|
129
|
+
ctx.cancel_event.set()
|
|
124
130
|
|
|
125
131
|
# ── dispatch ──────────────────────────────────────────────────────────
|
|
126
132
|
def _register(self, request: dict) -> CallContext | None:
|
|
@@ -182,12 +188,38 @@ class RpcServer:
|
|
|
182
188
|
|
|
183
189
|
def serve_forever(self) -> int:
|
|
184
190
|
"""Read requests until stdin closes or shutdown is requested."""
|
|
185
|
-
|
|
191
|
+
incoming = queue.Queue(maxsize=1)
|
|
192
|
+
def read_input():
|
|
186
193
|
try:
|
|
187
|
-
|
|
194
|
+
try:
|
|
195
|
+
fd = self._in.fileno()
|
|
196
|
+
except (AttributeError, OSError, ValueError):
|
|
197
|
+
fd = None
|
|
198
|
+
if fd is None:
|
|
199
|
+
while raw := self._in.readline():
|
|
200
|
+
incoming.put(raw)
|
|
201
|
+
else:
|
|
202
|
+
# An unbuffered OS read cannot hold sys.stdin's Python buffer lock at interpreter exit.
|
|
203
|
+
pending = []
|
|
204
|
+
while chunk := os.read(fd, 65536):
|
|
205
|
+
lines = chunk.split(b"\n")
|
|
206
|
+
pending.append(lines[0])
|
|
207
|
+
for line in lines[1:]:
|
|
208
|
+
incoming.put(b"".join(pending))
|
|
209
|
+
pending = [line]
|
|
210
|
+
if pending:
|
|
211
|
+
incoming.put(b"".join(pending))
|
|
188
212
|
except (OSError, ValueError):
|
|
189
|
-
|
|
190
|
-
|
|
213
|
+
pass
|
|
214
|
+
finally:
|
|
215
|
+
incoming.put(None)
|
|
216
|
+
threading.Thread(target=read_input, name="rpc-input", daemon=True).start()
|
|
217
|
+
while not self._closed.is_set():
|
|
218
|
+
try:
|
|
219
|
+
raw = incoming.get(timeout=.1)
|
|
220
|
+
except queue.Empty:
|
|
221
|
+
continue
|
|
222
|
+
if raw is None or self._closed.is_set():
|
|
191
223
|
break
|
|
192
224
|
raw = raw.strip()
|
|
193
225
|
if not raw:
|
|
@@ -209,6 +241,15 @@ class RpcServer:
|
|
|
209
241
|
continue
|
|
210
242
|
ctx = self._register(request)
|
|
211
243
|
threading.Thread(target=self._dispatch_slot, args=(request, ctx), name=f"rpc-{request.get('method')}", daemon=True).start()
|
|
244
|
+
if self._closed.is_set():
|
|
245
|
+
# Let the terminal reply reach stdout before the process returns its final exit code.
|
|
246
|
+
deadline = time.monotonic() + 5
|
|
247
|
+
while time.monotonic() < deadline:
|
|
248
|
+
with self._active_lock:
|
|
249
|
+
terminal_reply = any(ctx.method in {"runtime.shutdown", "runtime.handshake"} for ctx in self._active.values())
|
|
250
|
+
if not terminal_reply:
|
|
251
|
+
break
|
|
252
|
+
threading.Event().wait(.01)
|
|
212
253
|
return self.exit_code
|
|
213
254
|
|
|
214
255
|
def _dispatch_slot(self, request: dict, ctx: CallContext | None) -> None:
|
|
@@ -10,12 +10,15 @@ from __future__ import annotations
|
|
|
10
10
|
|
|
11
11
|
import errno
|
|
12
12
|
import importlib
|
|
13
|
+
import hashlib
|
|
13
14
|
import json
|
|
14
15
|
import math
|
|
15
16
|
import os
|
|
17
|
+
import re
|
|
16
18
|
import stat
|
|
17
19
|
import subprocess
|
|
18
20
|
import sys
|
|
21
|
+
import sysconfig
|
|
19
22
|
import threading
|
|
20
23
|
import time
|
|
21
24
|
from pathlib import Path
|
|
@@ -24,11 +27,8 @@ from . import SIDECAR_RPC_VERSION
|
|
|
24
27
|
from .errors import RpcError
|
|
25
28
|
|
|
26
29
|
PIN_PATH = Path(__file__).resolve().parent.parent / "agent_dependency.json"
|
|
27
|
-
|
|
28
|
-
"
|
|
29
|
-
"Talaria Web cannot verify that the Agent update completed safely. "
|
|
30
|
-
"Check the Agent update outcome and environment first. "
|
|
31
|
-
"Restart Talaria Web manually before retrying this action."
|
|
30
|
+
_RUNTIME_UNAVAILABLE_MESSAGE = (
|
|
31
|
+
"Agent runtime is unavailable. Check the Agent update outcome before retrying this action."
|
|
32
32
|
)
|
|
33
33
|
_AGENT_UPDATE_MARKER = ".hermes-update-in-progress"
|
|
34
34
|
_AGENT_RECOVERY_MARKERS = (".update-incomplete", ".lazy-refresh-incomplete")
|
|
@@ -40,11 +40,16 @@ _MARKER_SAFE_OPEN_AVAILABLE = bool(_O_NOFOLLOW) and bool(_O_NONBLOCK)
|
|
|
40
40
|
|
|
41
41
|
|
|
42
42
|
class AgentRuntimeStale(RpcError):
|
|
43
|
-
def __init__(self, update_state: str | None):
|
|
44
|
-
data = {"retryable": True, "restart_scheduled": False}
|
|
43
|
+
def __init__(self, update_state: str | None, message: str | None = None, *, source_changed: bool = False):
|
|
44
|
+
data = {"retryable": True, "restart_scheduled": False, "agent_source_changed": source_changed}
|
|
45
45
|
if update_state is not None:
|
|
46
46
|
data["agent_update_state"] = update_state
|
|
47
|
-
|
|
47
|
+
if message is None:
|
|
48
|
+
message = {
|
|
49
|
+
"active": "Agent update is in progress. Wait for it to finish before starting new work.",
|
|
50
|
+
"incomplete": "Agent update recovery is incomplete. Finish the Agent update before starting new work.",
|
|
51
|
+
}.get(update_state, _RUNTIME_UNAVAILABLE_MESSAGE)
|
|
52
|
+
super().__init__(message, condition="agent_runtime_stale", data=data)
|
|
48
53
|
|
|
49
54
|
|
|
50
55
|
class AgentIncompatible(RpcError):
|
|
@@ -217,6 +222,45 @@ def installed_agent_version() -> str | None:
|
|
|
217
222
|
return get_version_info().base_version
|
|
218
223
|
|
|
219
224
|
|
|
225
|
+
def _python_abi(major: int | str, minor: int | str, free_threaded: bool) -> str:
|
|
226
|
+
"""``3.14`` or ``3.14t``: regular and free-threaded builds of one version load different native extensions."""
|
|
227
|
+
return f"{major}.{minor}{'t' if free_threaded else ''}"
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def _site_packages_python(entry: str) -> tuple[str, Path] | None:
|
|
231
|
+
"""The Python ABI a ``sys.path`` site-packages directory was built for, and that venv's interpreter."""
|
|
232
|
+
path = Path(entry)
|
|
233
|
+
if path.name != "site-packages" or not path.is_dir():
|
|
234
|
+
return None
|
|
235
|
+
match = re.fullmatch(r"python(\d+)\.(\d+)(t?)", path.parent.name)
|
|
236
|
+
if match and path.parent.parent.name in {"lib", "lib64"}:
|
|
237
|
+
return _python_abi(match[1], match[2], bool(match[3])), path.parent.parent.parent / "bin" / "python"
|
|
238
|
+
if path.parent.name.lower() == "lib":
|
|
239
|
+
venv = path.parent.parent
|
|
240
|
+
try:
|
|
241
|
+
config = (venv / "pyvenv.cfg").read_text(encoding="utf-8")
|
|
242
|
+
except OSError:
|
|
243
|
+
return None
|
|
244
|
+
found = re.search(r"^\s*version(?:_info)?\s*=\s*(\d+)\.(\d+)", config, re.MULTILINE)
|
|
245
|
+
if found:
|
|
246
|
+
free_threaded = re.search(r"^\s*executable\s*=.*python\d+\.\d+t(?:\.exe)?\s*$", config, re.MULTILINE | re.IGNORECASE)
|
|
247
|
+
return _python_abi(found[1], found[2], bool(free_threaded)), venv / "Scripts" / "python.exe"
|
|
248
|
+
return None
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def _check_site_packages_python() -> None:
|
|
252
|
+
"""Compiled Agent dependencies load lazily on the first chat; fail the handshake when ``sys.path`` holds
|
|
253
|
+
site-packages built for another Python (a stale ``HERMES_WEBUI_PYTHON`` after a PM environment update)."""
|
|
254
|
+
running = _python_abi(sys.version_info[0], sys.version_info[1], bool(sysconfig.get_config_var("Py_GIL_DISABLED")))
|
|
255
|
+
for entry in sys.path:
|
|
256
|
+
built = _site_packages_python(entry)
|
|
257
|
+
if built is not None and built[0] != running:
|
|
258
|
+
raise ImportError(
|
|
259
|
+
f"interpreter Python {running} cannot load Agent packages built for Python {built[0]} ({entry}); "
|
|
260
|
+
f"unset HERMES_WEBUI_PYTHON or point it at {built[1]}"
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
|
|
220
264
|
class AgentRuntime:
|
|
221
265
|
"""Loads the Agent once and guards against a changed checkout."""
|
|
222
266
|
|
|
@@ -224,6 +268,7 @@ class AgentRuntime:
|
|
|
224
268
|
self.hermes_home = Path(hermes_home)
|
|
225
269
|
self._stale_lock = threading.Lock()
|
|
226
270
|
self._stale = False
|
|
271
|
+
self._source_changed = False
|
|
227
272
|
self._stale_stamp: tuple | None = None
|
|
228
273
|
self.agent_dir = Path(agent_dir).resolve() if agent_dir else None
|
|
229
274
|
self.pin = read_pin()
|
|
@@ -239,12 +284,18 @@ class AgentRuntime:
|
|
|
239
284
|
if self.loaded:
|
|
240
285
|
return
|
|
241
286
|
try:
|
|
287
|
+
# Direct Agent imports skip CLI startup's PM tool PATH activation.
|
|
288
|
+
if self.agent_dir is not None and (self.agent_dir / "pm").is_dir():
|
|
289
|
+
compose_path = getattr(importlib.import_module("pm"), "store_first_path", None)
|
|
290
|
+
if compose_path is not None:
|
|
291
|
+
os.environ["PATH"] = compose_path(os.environ.get("PATH", ""))
|
|
242
292
|
module = importlib.import_module("run_agent")
|
|
243
293
|
getattr(module, "AIAgent")
|
|
244
294
|
# Agent 0.21.3 snapshots its auth provider registry, discovered plugins included, when hermes_cli.auth
|
|
245
295
|
# first imports. Take it here, under the launch profile and before any profile-scoped method runs, so
|
|
246
296
|
# a named profile's plugin loaded later never enters that process-wide snapshot.
|
|
247
297
|
importlib.import_module("hermes_cli.auth")
|
|
298
|
+
_check_site_packages_python()
|
|
248
299
|
except Exception as exc: # noqa: BLE001 - reported as a handshake condition
|
|
249
300
|
self.import_error = f"{type(exc).__name__}: {exc}"
|
|
250
301
|
raise AgentIncompatible(f"Hermes Agent could not be imported: {self.import_error}", import_error=self.import_error)
|
|
@@ -276,9 +327,12 @@ class AgentRuntime:
|
|
|
276
327
|
|
|
277
328
|
def update_transaction_state(self) -> str:
|
|
278
329
|
live = _read_live_agent_update(self.hermes_home / _AGENT_UPDATE_MARKER)
|
|
279
|
-
if live
|
|
330
|
+
if live in {"unknown", "active"}:
|
|
331
|
+
return live
|
|
332
|
+
repair = self.web_repair_state()
|
|
333
|
+
if repair == "unknown":
|
|
280
334
|
return "unknown"
|
|
281
|
-
recovery =
|
|
335
|
+
recovery = repair == "present"
|
|
282
336
|
for root in self._install_roots():
|
|
283
337
|
for name in _AGENT_RECOVERY_MARKERS:
|
|
284
338
|
presence = _marker_presence(root / name)
|
|
@@ -289,6 +343,16 @@ class AgentRuntime:
|
|
|
289
343
|
return "incomplete"
|
|
290
344
|
return "unverified" if live == "absent" else live
|
|
291
345
|
|
|
346
|
+
def web_repair_state(self) -> str:
|
|
347
|
+
if self.agent_dir is None:
|
|
348
|
+
return "absent"
|
|
349
|
+
from .agent_mutation import recovery_receipts
|
|
350
|
+
try:
|
|
351
|
+
receipts, _ = recovery_receipts(self)
|
|
352
|
+
return 'present' if receipts else 'absent'
|
|
353
|
+
except (OSError, UnicodeError):
|
|
354
|
+
return 'unknown'
|
|
355
|
+
|
|
292
356
|
def is_stale(self) -> bool:
|
|
293
357
|
"""True when the checkout revision no longer matches the loaded module.
|
|
294
358
|
|
|
@@ -310,14 +374,18 @@ class AgentRuntime:
|
|
|
310
374
|
fresh = None
|
|
311
375
|
if fresh is not None:
|
|
312
376
|
break
|
|
377
|
+
self._source_changed = fresh is not None and fresh != self.revision
|
|
313
378
|
self._stale = fresh != self.revision
|
|
314
379
|
self._stale_stamp = stamp if fresh is not None else None
|
|
315
380
|
return self._stale
|
|
316
381
|
|
|
317
382
|
def ensure_current(self) -> None:
|
|
318
|
-
"""
|
|
383
|
+
"""Refuse Agent work until source drift or a durable Web update obligation is reconciled."""
|
|
384
|
+
repair = self.web_repair_state()
|
|
385
|
+
if repair != "absent":
|
|
386
|
+
raise AgentRuntimeStale("unknown" if repair == "unknown" else self.update_transaction_state())
|
|
319
387
|
if self.is_stale():
|
|
320
|
-
raise AgentRuntimeStale(self.update_transaction_state())
|
|
388
|
+
raise AgentRuntimeStale(self.update_transaction_state(), source_changed=self._source_changed)
|
|
321
389
|
|
|
322
390
|
# ── handshake ─────────────────────────────────────────────────────────
|
|
323
391
|
def describe(self) -> dict:
|
|
@@ -335,6 +403,7 @@ class AgentRuntime:
|
|
|
335
403
|
"pinned_image": self.pin["image"],
|
|
336
404
|
"compatible": self.loaded,
|
|
337
405
|
"stale": self.is_stale(),
|
|
406
|
+
"agent_source_changed": self._source_changed,
|
|
338
407
|
"update_state": self.update_transaction_state(),
|
|
339
408
|
"import_error": self.import_error,
|
|
340
409
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""One route-aware speed gate for the model catalog and chat request overrides."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import inspect
|
|
6
|
+
import re
|
|
7
|
+
from urllib.parse import urlparse
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def fast_overrides(model: str, provider: str, base_url: str, tier: str) -> dict | None:
|
|
11
|
+
if tier not in ("priority", "ultrafast"):
|
|
12
|
+
return None
|
|
13
|
+
from hermes_cli import models
|
|
14
|
+
|
|
15
|
+
resolver = getattr(models, "resolve_fast_mode_overrides", None)
|
|
16
|
+
if resolver is not None:
|
|
17
|
+
if "tier" in inspect.signature(resolver).parameters:
|
|
18
|
+
return resolver(model, provider=provider, base_url=base_url, tier=tier)
|
|
19
|
+
return resolver(model, provider=provider, base_url=base_url) if tier == "priority" else None
|
|
20
|
+
# Older Agents have no resolver. Keep the former GPT-5/o-series gate, restricted to first-party routes.
|
|
21
|
+
hosts = {"openai": "api.openai.com", "openai-api": "api.openai.com", "openai-codex": "chatgpt.com"}
|
|
22
|
+
model = model.strip().lower().removeprefix("openai/")
|
|
23
|
+
host = urlparse(base_url).hostname if base_url else None
|
|
24
|
+
if tier == "priority" and provider in hosts and (not host or host == hosts[provider]) and (model.startswith("gpt-5") or re.match(r"o[0-9]", model)):
|
|
25
|
+
return {"service_tier": "priority"}
|
|
26
|
+
return None
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def supported_speed_tiers(model: str, provider: str, base_url: str) -> list[dict]:
|
|
30
|
+
tiers = []
|
|
31
|
+
for tier in ("priority", "ultrafast"):
|
|
32
|
+
override = fast_overrides(model, provider, base_url, tier)
|
|
33
|
+
if override:
|
|
34
|
+
tiers.append({"id": "fast" if override.get("speed") == "fast" else tier, "service_tier": tier})
|
|
35
|
+
return [{"id": "standard", "service_tier": "default"}, *tiers] if tiers else []
|