@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
package/dist/api/tools-router.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/** Skills, memory, prompts, commands, notes, insights, logs, health, MCP, plugins, updates, diagnostics (Python `api/routes.py` handlers of the same paths). */
|
|
2
1
|
import { implement } from '@orpc/server';
|
|
3
2
|
import { createHash } from 'node:crypto';
|
|
4
3
|
import { join } from 'node:path';
|
|
@@ -6,24 +5,32 @@ import { toolsContract } from '@maudecode/talaria-web-contracts';
|
|
|
6
5
|
import { HttpError, requireFields } from './router.js';
|
|
7
6
|
import { requestSessionIdGuard } from './session-visibility.js';
|
|
8
7
|
import { activeProfileName, ensureTrustedAuthSession, sessionCanManageServer } from '../auth/gate.js';
|
|
9
|
-
import { HttpFailure } from '../sessions/service.js';
|
|
8
|
+
import { currentChatReadiness, HttpFailure } from '../sessions/service.js';
|
|
10
9
|
import { SessionNotFound } from '../sessions/store.js';
|
|
11
10
|
import { insightsSessionRows } from '../sessions/state-db.js';
|
|
12
11
|
import { ConfigUnavailable } from '../config/agent-config.js';
|
|
13
12
|
import { SidecarError } from '../sidecar/client.js';
|
|
14
13
|
import { createPrompt, deletePrompt, externalNotesEnabled, loadPrompts, readMemory, writeMemory } from '../tools/memory.js';
|
|
15
14
|
import { JoplinError, joplinNote, joplinSearch, notesSources } from '../tools/mcp.js';
|
|
15
|
+
import { catalogNames, connectorOperation, connectorsPage, connectorTools, rememberCatalogNames } from '../tools/connectors.js';
|
|
16
16
|
import { resolveWikiLocation, wikiPages } from '../tools/wiki.js';
|
|
17
17
|
import { buildInsights } from '../tools/insights.js';
|
|
18
|
-
import { commandCatalog } from '../tools/commands.js';
|
|
19
|
-
import {
|
|
18
|
+
import { commandCatalog, SESSION_EXEC_COMMANDS } from '../tools/commands.js';
|
|
19
|
+
import { spokenText } from './tools-raw.js';
|
|
20
|
+
import { agentHealth, applyDashboardConfig, dashboardConfig, dashboardStatus, gatewayStatus, parseDashboardConfig, readLogTail, remoteGatewayBaseUrl, systemHealth } from '../tools/health.js';
|
|
21
|
+
import { restartGateway } from '../tools/gateway-restart.js';
|
|
20
22
|
import { projectOsDashboard } from '../tools/project-os.js';
|
|
23
|
+
import { PluginSettingsInvalid, planPluginSettings, pluginSettingsView, serializePluginSettingsSave } from '../tools/plugin-settings.js';
|
|
24
|
+
import { credentialShadowed, RuntimeCredentialError, writeRuntimeCredential } from '../providers/runtime-env.js';
|
|
25
|
+
import { EnvWriteError, loadEnvFile } from '../providers/env-file.js';
|
|
21
26
|
import { loadGatewaySessionIdentityMap } from '../sessions/list.js';
|
|
22
27
|
import { gitBadge } from '../workspace/git.js';
|
|
23
28
|
import { sanitizeError } from '../workspace/media.js';
|
|
24
29
|
import { normalizeChannel, updatesCheckView } from '../tools/updates.js';
|
|
25
30
|
import { pyBool } from '../settings.js';
|
|
26
31
|
import { str } from '../util.js';
|
|
32
|
+
import { redactString } from '../redact.js';
|
|
33
|
+
import { GATEWAY_RESTART_NOW } from '../tools/update-notifications.js';
|
|
27
34
|
const os = implement(toolsContract).$context().use(requestSessionIdGuard);
|
|
28
35
|
function failure(error) {
|
|
29
36
|
if (error instanceof HttpError)
|
|
@@ -48,6 +55,8 @@ async function run(fn) {
|
|
|
48
55
|
}
|
|
49
56
|
}
|
|
50
57
|
const home = (ctx) => ctx.deps.profileHome(activeProfileName(ctx));
|
|
58
|
+
/** Profile homes with an `stt.warm` in flight (TAL-916). */
|
|
59
|
+
const warmingHomes = new Set();
|
|
51
60
|
function runningSidecar(ctx) {
|
|
52
61
|
const sidecar = ctx.deps.sidecar();
|
|
53
62
|
if (!sidecar)
|
|
@@ -62,14 +71,89 @@ function commandFailure(error, notFound, message) {
|
|
|
62
71
|
throw new HttpError(400, error.message);
|
|
63
72
|
return failure(error);
|
|
64
73
|
}
|
|
74
|
+
/** TAL-820: several profiles have third-party plugins and one of them loads its plugins into the shared sidecar process. */
|
|
75
|
+
async function pluginIsolationAdvisory(ctx) {
|
|
76
|
+
if (ctx.deps.isolatedProfileMode())
|
|
77
|
+
return false;
|
|
78
|
+
const { profiles } = await runningSidecar(ctx).call('plugins.isolation', { base_home: ctx.deps.profileHome('default') });
|
|
79
|
+
const withPlugins = profiles.filter((profile) => profile.third_party_plugins > 0);
|
|
80
|
+
return withPlugins.length > 1 && withPlugins.some((profile) => profile.isolation === 'in_process');
|
|
81
|
+
}
|
|
82
|
+
/** TAL-806: the active profile's plugins that declare settings; none on an Agent without the settings module. */
|
|
83
|
+
async function pluginSettingsList(ctx) {
|
|
84
|
+
const result = await runningSidecar(ctx).call('plugins.settings', { profile_home: home(ctx) });
|
|
85
|
+
return result.plugins.map((entry) => ({ key: entry.key, fields: pluginSettingsFieldsView(ctx, entry.fields) }));
|
|
86
|
+
}
|
|
87
|
+
const pluginSettingsFieldsView = (ctx, fields) => {
|
|
88
|
+
const rootProfile = ctx.deps.isRootProfile(activeProfileName(ctx));
|
|
89
|
+
return pluginSettingsView(fields, (envVar) => credentialShadowed(ctx.deps.config.env, rootProfile, envVar));
|
|
90
|
+
};
|
|
91
|
+
/** A refusal that proves nothing was written; a timeout or a sidecar exit leaves the outcome unknown. */
|
|
92
|
+
const definitiveRefusal = (error) => error instanceof SidecarError ? ['plugin_settings_managed', 'plugin_settings_changed', 'plugin_not_found'].includes(error.condition) || error.code === -32602
|
|
93
|
+
: error instanceof EnvWriteError ? error.condition !== 'sidecar_unavailable'
|
|
94
|
+
: error instanceof RuntimeCredentialError;
|
|
95
|
+
/** TAL-818: a sidecar `connectors.*` condition as the HTTP status the contract names; the body's `code` is the condition. */
|
|
96
|
+
const CONNECTOR_STATUS = {
|
|
97
|
+
connectors_unavailable: 404, connector_not_found: 404, connection_not_found: 404, operation_not_found: 404,
|
|
98
|
+
connectors_sign_in: 403, connectors_forbidden: 403, policy_invalid: 400, connectors_failed: 502,
|
|
99
|
+
policy_conflict: 409, connectors_org_required: 409, operation_settled: 409, operation_refused: 409,
|
|
100
|
+
};
|
|
101
|
+
async function connectorCall(ctx, method, params) {
|
|
102
|
+
try {
|
|
103
|
+
// A connect waits up to 31 s for its link; every portal request inside a call is bounded at 30 s.
|
|
104
|
+
return await runningSidecar(ctx).call(method, { ...params, profile_home: home(ctx) }, { timeoutMs: 90_000 });
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
const status = error instanceof SidecarError ? CONNECTOR_STATUS[error.condition] : undefined;
|
|
108
|
+
if (status !== undefined)
|
|
109
|
+
throw new HttpError(status, error.message, { code: error.condition });
|
|
110
|
+
if (error instanceof SidecarError && error.code === -32602)
|
|
111
|
+
throw new HttpError(400, error.message);
|
|
112
|
+
throw error;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/** The catalog's app names for the active profile: the last page read's, else one catalog read; none when it fails. */
|
|
116
|
+
async function connectorNames(ctx) {
|
|
117
|
+
return catalogNames(home(ctx)) ?? await connectorCall(ctx, 'connectors.catalog', {}).then((r) => rememberCatalogNames(home(ctx), r.connectors), () => ({}));
|
|
118
|
+
}
|
|
119
|
+
/** An operation as the contract shows it, with the apps' catalog names. */
|
|
120
|
+
const operationView = async (ctx, snapshot) => connectorOperation(snapshot, await connectorNames(ctx));
|
|
121
|
+
/** The rules, or why they cannot be read (a portal refusal or failure): the page then fails closed and says why. */
|
|
122
|
+
const connectorPolicy = (ctx) => connectorCall(ctx, 'connectors.policy.get', {}).then((policy) => ({ policy, error: null }), (error) => { if (error instanceof HttpError)
|
|
123
|
+
return { policy: null, error: error.message }; throw error; });
|
|
65
124
|
const health = (ctx) => agentHealth({ env: ctx.deps.config.env, hermesHome: ctx.deps.config.hermesHome, profileHome: () => home(ctx), fetch: () => ctx.deps.fetch, now: ctx.deps.nowSeconds });
|
|
125
|
+
/**
|
|
126
|
+
* TAL-805: the active profile's gateway mode from sidecar `gateway.mode`; null for a remote gateway. A named profile never
|
|
127
|
+
* borrows the root's health: when the sidecar cannot answer, it reads `stopped`, while the root profile reads null and keeps
|
|
128
|
+
* its health. The root profile's gateway in another container (`health` alive from its fresh runtime status) is invisible
|
|
129
|
+
* to the sidecar's process checks, so it stays `own`.
|
|
130
|
+
*/
|
|
131
|
+
async function gatewayMode(ctx, health) {
|
|
132
|
+
if (remoteGatewayBaseUrl(ctx.deps.config.env) !== null)
|
|
133
|
+
return null;
|
|
134
|
+
const sidecar = ctx.deps.sidecar();
|
|
135
|
+
const name = activeProfileName(ctx);
|
|
136
|
+
const isDefault = ctx.deps.isRootProfile(name);
|
|
137
|
+
let mode = null;
|
|
138
|
+
try {
|
|
139
|
+
if (sidecar)
|
|
140
|
+
mode = (await sidecar.call('gateway.mode', { profile_home: home(ctx), name, is_default: isDefault }, { timeoutMs: 10_000 })).gateway_mode;
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
mode = null;
|
|
144
|
+
}
|
|
145
|
+
if (mode === null)
|
|
146
|
+
return isDefault ? null : 'stopped';
|
|
147
|
+
return mode === 'stopped' && isDefault && health.alive === true ? 'own' : mode;
|
|
148
|
+
}
|
|
66
149
|
/** Python `_gateway_status_payload` for the active profile. */
|
|
67
150
|
async function currentGatewayStatus(ctx) {
|
|
68
151
|
const sessionsPath = join(home(ctx), 'sessions', 'sessions.json');
|
|
69
|
-
|
|
152
|
+
const probe = await health(ctx);
|
|
153
|
+
return gatewayStatus(probe, loadGatewaySessionIdentityMap(sessionsPath), sessionsPath, await gatewayMode(ctx, probe));
|
|
70
154
|
}
|
|
71
155
|
const GATEWAY_ACTION_TIMEOUT_S = 60;
|
|
72
|
-
/** Python `_handle_gateway_lifecycle` through sidecar `gateway.control`: 409 busy, 504 timeout, 500 failure;
|
|
156
|
+
/** Python `_handle_gateway_lifecycle` through sidecar `gateway.control`: 409 busy, 504 timeout, 500 failure; only the Agent's first error line (`reason`) leaves the server, never its CLI output (TAL-884). */
|
|
73
157
|
async function gatewayAction(ctx, action) {
|
|
74
158
|
const sidecar = ctx.deps.sidecar();
|
|
75
159
|
if (!sidecar)
|
|
@@ -85,8 +169,10 @@ async function gatewayAction(ctx, action) {
|
|
|
85
169
|
throw new HttpError(409, 'Another gateway action is already in progress; try again shortly.', { ok: false, action });
|
|
86
170
|
if (outcome.timed_out)
|
|
87
171
|
throw new HttpError(504, `Gateway ${action} timed out after ${String(GATEWAY_ACTION_TIMEOUT_S)} seconds`, { ok: false, action });
|
|
88
|
-
if (outcome.status === 'failed' && outcome.returncode !== undefined)
|
|
89
|
-
|
|
172
|
+
if (outcome.status === 'failed' && outcome.returncode !== undefined) {
|
|
173
|
+
const error = outcome.reason ? `Gateway ${action} failed: ${outcome.reason}` : `Gateway ${action} failed with exit code ${String(outcome.returncode)}`;
|
|
174
|
+
throw new HttpError(500, error, { ok: false, action, returncode: outcome.returncode });
|
|
175
|
+
}
|
|
90
176
|
if (outcome.status === 'failed')
|
|
91
177
|
throw new HttpError(500, outcome.message, { ok: false, action });
|
|
92
178
|
return { ok: true, action, message: `Gateway ${action} completed.`, status: await currentGatewayStatus(ctx) };
|
|
@@ -115,39 +201,54 @@ async function updateNotificationScope(ctx, tab) {
|
|
|
115
201
|
tab: tab ?? null,
|
|
116
202
|
};
|
|
117
203
|
}
|
|
118
|
-
async function applyWithNotification(ctx,
|
|
119
|
-
const
|
|
204
|
+
async function applyWithNotification(ctx, input, action) {
|
|
205
|
+
const target = updateTarget(input.target);
|
|
206
|
+
const confirmed = input.confirmed_agent_revision !== undefined || input.agent_refresh_token !== undefined;
|
|
207
|
+
const scope = await updateNotificationScope(ctx, input.tab_id);
|
|
120
208
|
const active = ctx.deps.updateNotifications.activeUpdate(scope, target);
|
|
121
209
|
if (active)
|
|
122
|
-
ctx.deps.updateNotifications.watch(scope, active.id);
|
|
210
|
+
(await ctx.deps.updateNotifications.watch(scope, active.id));
|
|
123
211
|
if (active && (active.phase === 'applying' || active.phase === 'restarting')) {
|
|
124
212
|
return { ok: false, status: 'already_in_progress', message: 'Update already in progress', notification_id: active.id };
|
|
125
213
|
}
|
|
126
|
-
const notification = active ?? ctx.deps.updateNotifications.begin(scope, target);
|
|
214
|
+
const notification = active ?? (await ctx.deps.updateNotifications.begin(scope, target));
|
|
127
215
|
if (active?.phase === 'awaiting_confirmation' && confirmed)
|
|
128
|
-
ctx.deps.updateNotifications.transition(notification.id, 'applying');
|
|
216
|
+
(await ctx.deps.updateNotifications.transition(notification.id, 'applying'));
|
|
129
217
|
try {
|
|
130
|
-
const
|
|
218
|
+
const options = { agentChannel: input.agent_channel, confirmedRevision: input.confirmed_agent_revision, version: input.version, refreshToken: input.agent_refresh_token, mutationIntent: principalHash(scope.owner, scope.profile, notification.id) };
|
|
219
|
+
const result = action === 'apply' ? await ctx.deps.updates.apply(target, bodyChannel(input.channel), () => true, options)
|
|
220
|
+
: action === 'force' ? await ctx.deps.updates.force(target, bodyChannel(input.channel), options)
|
|
221
|
+
: await ctx.deps.updates.clearLock(target, options);
|
|
131
222
|
const verifiedIdentity = typeof result.verified_revision === 'string'
|
|
132
223
|
? { revision: result.verified_revision, version: typeof result.verified_version === 'string' ? result.verified_version : null }
|
|
133
224
|
: undefined;
|
|
134
225
|
if (result.confirmation_required === true)
|
|
135
|
-
ctx.deps.updateNotifications.transition(notification.id, 'awaiting_confirmation', null, verifiedIdentity);
|
|
226
|
+
(await ctx.deps.updateNotifications.transition(notification.id, 'awaiting_confirmation', null, verifiedIdentity, result.message));
|
|
136
227
|
else if (result.restart_blocked === true)
|
|
137
|
-
ctx.deps.updateNotifications.transition(notification.id, 'blocked', null, verifiedIdentity, result.message);
|
|
228
|
+
(await ctx.deps.updateNotifications.transition(notification.id, 'blocked', null, verifiedIdentity, result.message));
|
|
138
229
|
else if (result.ok !== true)
|
|
139
|
-
ctx.deps.updateNotifications.transition(notification.id, 'failed', null, verifiedIdentity, result.message || result.error);
|
|
230
|
+
(await ctx.deps.updateNotifications.transition(notification.id, 'failed', null, verifiedIdentity, result.message || result.error));
|
|
140
231
|
else if (target === 'webui' && result.restart_scheduled === true) {
|
|
141
|
-
ctx.deps.updateNotifications.transition(notification.id, 'restarting', str(result.sourceRevision || result.candidate_revision), verifiedIdentity);
|
|
232
|
+
await ctx.deps.updateNotifications.transition(notification.id, 'restarting', str(result.sourceRevision || result.candidate_revision), verifiedIdentity);
|
|
233
|
+
}
|
|
234
|
+
else if (result.gateway_restart === 'waiting_for_idle' || (target === 'agent' && ctx.deps.gatewayRestarts.pendingId() !== null)) {
|
|
235
|
+
// TAL-953: the gateway restarts once its own work drains. A restart already waiting covers this update too, and a
|
|
236
|
+
// repeated request that found the Agent current follows that wait rather than reporting success before it.
|
|
237
|
+
const detail = result.stash_conflict === true ? str(result.message) : null;
|
|
238
|
+
await ctx.deps.updateNotifications.transition(notification.id, 'waiting_for_idle', null, verifiedIdentity, detail);
|
|
239
|
+
const pending = (await ctx.deps.gatewayRestarts.schedule(notification.id, scope.profile, detail));
|
|
240
|
+
if (pending !== notification.id)
|
|
241
|
+
(await ctx.deps.updateNotifications.watch(scope, pending));
|
|
242
|
+
return { ...result, notification_id: pending };
|
|
142
243
|
}
|
|
143
244
|
else {
|
|
144
245
|
// A kept Agent stash needs the user's attention; its recovery commands ride on the success record.
|
|
145
|
-
ctx.deps.updateNotifications.transition(notification.id, 'succeeded', null, verifiedIdentity, result.stash_conflict === true ? result.message : undefined);
|
|
246
|
+
await ctx.deps.updateNotifications.transition(notification.id, 'succeeded', null, verifiedIdentity, result.stash_conflict === true ? result.message : undefined);
|
|
146
247
|
}
|
|
147
248
|
return { ...result, notification_id: notification.id };
|
|
148
249
|
}
|
|
149
250
|
catch (error) {
|
|
150
|
-
ctx.deps.updateNotifications.transition(notification.id, 'failed', null, undefined, error instanceof Error ? error.message : null);
|
|
251
|
+
await ctx.deps.updateNotifications.transition(notification.id, 'failed', null, undefined, error instanceof Error ? error.message : null);
|
|
151
252
|
throw error;
|
|
152
253
|
}
|
|
153
254
|
}
|
|
@@ -225,10 +326,10 @@ export function sanitizeClientEvent(payload) {
|
|
|
225
326
|
out.event = 'unknown';
|
|
226
327
|
return out;
|
|
227
328
|
}
|
|
228
|
-
function memoryWorkspace(ctx, sessionId, workspace) {
|
|
329
|
+
async function memoryWorkspace(ctx, sessionId, workspace) {
|
|
229
330
|
if (sessionId) {
|
|
230
331
|
try {
|
|
231
|
-
const session = ctx.deps.sessionStore.get(sessionId, { metadataOnly: true });
|
|
332
|
+
const session = (await ctx.deps.sessionStore.get(sessionId, { metadataOnly: true }));
|
|
232
333
|
if (!ctx.deps.workspaces.profileSupportsLocalIo(session.profile))
|
|
233
334
|
return null;
|
|
234
335
|
const ws = str(session.workspace).trim();
|
|
@@ -241,11 +342,11 @@ function memoryWorkspace(ctx, sessionId, workspace) {
|
|
|
241
342
|
const profile = activeProfileName(ctx);
|
|
242
343
|
if (!ctx.deps.workspaces.profileSupportsLocalIo(profile))
|
|
243
344
|
return null;
|
|
244
|
-
const raw = workspace || (ctx.deps.config.env.TERMINAL_CWD ?? '') || ctx.deps.workspaces.lastWorkspace(profile);
|
|
345
|
+
const raw = workspace || (ctx.deps.config.env.TERMINAL_CWD ?? '') || (await ctx.deps.workspaces.lastWorkspace(profile));
|
|
245
346
|
if (!raw)
|
|
246
347
|
return null;
|
|
247
348
|
try {
|
|
248
|
-
return ctx.deps.workspaces.resolveTrusted(raw, profile);
|
|
349
|
+
return (await ctx.deps.workspaces.resolveTrusted(raw, profile));
|
|
249
350
|
}
|
|
250
351
|
catch {
|
|
251
352
|
return null;
|
|
@@ -277,7 +378,13 @@ async function wikiLocation(ctx) {
|
|
|
277
378
|
const config = await ctx.deps.agentConfig.read(profileHome).catch(() => ({}));
|
|
278
379
|
return resolveWikiLocation(ctx.deps.config.env, profileHome, config, ctx.deps.config.homeDir);
|
|
279
380
|
}
|
|
381
|
+
/** TAL-819: the Agent's review handler per write; its message can quote the entry text an approval replaced or removed. */
|
|
382
|
+
async function reviewPendingWrites(ctx, verb, input) {
|
|
383
|
+
const { results } = await runningSidecar(ctx).call(`write_approval.${verb}`, { profile_home: home(ctx), kind: input.kind, writes: input.writes });
|
|
384
|
+
return { results: results.map((r) => ({ ...r, message: redactString(r.message, ctx.deps.sessions.deps.redactEnabled()) })) };
|
|
385
|
+
}
|
|
280
386
|
export const toolsRouter = os.router({
|
|
387
|
+
toolsetsCatalog: os.toolsetsCatalog.handler(({ input, context: { ctx } }) => run(() => runningSidecar(ctx).call('toolsets.catalog', { profile_home: home(ctx), enabled_toolsets: input.toolsets }))),
|
|
281
388
|
skills: {
|
|
282
389
|
list: os.skills.list.handler(({ input, context: { ctx } }) => run(async () => ({ skills: await ctx.deps.skills.list(home(ctx), str(input.category).trim() || null) }))),
|
|
283
390
|
usage: os.skills.usage.handler(({ context: { ctx } }) => run(() => ctx.deps.skills.usage(home(ctx)))),
|
|
@@ -308,14 +415,31 @@ export const toolsRouter = os.router({
|
|
|
308
415
|
memory: {
|
|
309
416
|
get: os.memory.get.handler(({ input, context: { ctx } }) => run(async () => {
|
|
310
417
|
const config = await ctx.deps.agentConfig.read(home(ctx));
|
|
311
|
-
return readMemory(home(ctx), config, memoryWorkspace(ctx, str(input.session_id), str(input.workspace)), ctx.deps.config.env, ctx.deps.sessions.deps.redactEnabled());
|
|
418
|
+
return readMemory(home(ctx), config, (await memoryWorkspace(ctx, str(input.session_id), str(input.workspace))), ctx.deps.config.env, ctx.deps.sessions.deps.redactEnabled(), ctx.deps.auth.signingKey());
|
|
312
419
|
})),
|
|
313
420
|
write: os.memory.write.handler(({ input, context: { ctx } }) => run(async () => {
|
|
314
421
|
const section = input.section ?? input.target;
|
|
315
422
|
if (section === undefined || input.content === undefined)
|
|
316
423
|
throw new HttpError(400, 'Missing required field(s): section, content');
|
|
317
|
-
|
|
424
|
+
const profileHome = home(ctx);
|
|
425
|
+
return writeMemory(profileHome, await ctx.deps.agentConfig.read(profileHome), str(section), str(input.content), input.revision, {
|
|
426
|
+
key: ctx.deps.auth.signingKey(),
|
|
427
|
+
check: (target, content) => runningSidecar(ctx).call('memory.check', { profile_home: profileHome, target, content }),
|
|
428
|
+
write: (target, base, content) => runningSidecar(ctx).call('memory.write', { profile_home: profileHome, section: target, base, content }),
|
|
429
|
+
});
|
|
430
|
+
})),
|
|
431
|
+
},
|
|
432
|
+
pendingWrites: {
|
|
433
|
+
list: os.pendingWrites.list.handler(({ input, context: { ctx } }) => run(async () => {
|
|
434
|
+
// Without the Agent nothing can be reviewed, so the page shows no panel (the Agent's own status reports it down).
|
|
435
|
+
const sidecar = ctx.deps.sidecar();
|
|
436
|
+
const { enabled, items } = sidecar ? await sidecar.call('write_approval.pending', { profile_home: home(ctx), kind: input.kind }) : { enabled: false, items: [] };
|
|
437
|
+
const redact = (text) => redactString(text, ctx.deps.sessions.deps.redactEnabled());
|
|
438
|
+
// Display text is redacted like the memory page; `revision` stays the sidecar's hash of the raw diff it rechecks.
|
|
439
|
+
return { kind: input.kind, visible: items.length > 0, enabled, items: items.map((item) => ({ ...item, summary: redact(item.summary), diff: redact(item.diff) })) };
|
|
318
440
|
})),
|
|
441
|
+
approve: os.pendingWrites.approve.handler(({ input, context: { ctx } }) => run(() => reviewPendingWrites(ctx, 'approve', input))),
|
|
442
|
+
reject: os.pendingWrites.reject.handler(({ input, context: { ctx } }) => run(() => reviewPendingWrites(ctx, 'reject', input))),
|
|
319
443
|
},
|
|
320
444
|
prompts: {
|
|
321
445
|
list: os.prompts.list.handler(({ context: { ctx } }) => run(() => ({ prompts: loadPrompts(home(ctx)) }))),
|
|
@@ -337,8 +461,19 @@ export const toolsRouter = os.router({
|
|
|
337
461
|
const command = str(input.command).trim();
|
|
338
462
|
if (!command)
|
|
339
463
|
throw new HttpError(400, 'command is required');
|
|
464
|
+
const [, name = '', args = ''] = /^\/?(\S*)\s*([\s\S]*)$/.exec(command) ?? [];
|
|
465
|
+
const sessionId = str(input.session_id).trim();
|
|
466
|
+
if (sessionId)
|
|
467
|
+
(await ctx.deps.sessions.assertWritable(sessionId));
|
|
468
|
+
// TAL-902: a session command runs on the chat's own agent (the request guard already checked the chat's profile).
|
|
469
|
+
if (SESSION_EXEC_COMMANDS.has(name.toLowerCase())) {
|
|
470
|
+
return { output: await ctx.deps.turns.refine(sessionId ? (await ctx.deps.sessionStore.get(sessionId)) : null, args.trim()) };
|
|
471
|
+
}
|
|
472
|
+
// TAL-904: a chat's command runs under that chat's session and the workspace its next turn would use. An unknown
|
|
473
|
+
// chat (404) or a workspace that turn would refuse (400) refuses the command rather than run it half-bound.
|
|
474
|
+
const chat = sessionId ? { session_id: sessionId, workspace: (await ctx.deps.sessions.turnWorkspace((await ctx.deps.sessionStore.get(sessionId, { metadataOnly: true })))) } : {};
|
|
340
475
|
try {
|
|
341
|
-
return { output: (await runningSidecar(ctx).call('commands.exec', { profile_home: home(ctx), command }, { timeoutMs: 120_000 })).output };
|
|
476
|
+
return { output: (await runningSidecar(ctx).call('commands.exec', { profile_home: home(ctx), command, ...chat }, { timeoutMs: 120_000 })).output };
|
|
342
477
|
}
|
|
343
478
|
catch (error) {
|
|
344
479
|
return commandFailure(error, 'command_not_found', 'Plugin command not found');
|
|
@@ -401,10 +536,10 @@ export const toolsRouter = os.router({
|
|
|
401
536
|
browse: os.wiki.browse.handler(({ context: { ctx } }) => run(async () => wikiPages.browse(await wikiLocation(ctx)))),
|
|
402
537
|
page: os.wiki.page.handler(({ input, context: { ctx } }) => run(async () => wikiPages.page(await wikiLocation(ctx), str(input.path)))),
|
|
403
538
|
},
|
|
404
|
-
insights: os.insights.handler(({ input, context: { ctx } }) => run(() => {
|
|
539
|
+
insights: os.insights.handler(({ input, context: { ctx } }) => run(async () => {
|
|
405
540
|
let entries = [];
|
|
406
541
|
try {
|
|
407
|
-
entries = ctx.deps.sessionStore.readIndexEntries();
|
|
542
|
+
entries = (await ctx.deps.sessionStore.readIndexEntries());
|
|
408
543
|
}
|
|
409
544
|
catch {
|
|
410
545
|
entries = [];
|
|
@@ -413,13 +548,13 @@ export const toolsRouter = os.router({
|
|
|
413
548
|
})),
|
|
414
549
|
logs: os.logs.handler(({ input, context: { ctx } }) => run(() => readLogTail(home(ctx), input.file, input.tail))),
|
|
415
550
|
ops: {
|
|
416
|
-
agent: os.ops.agent.handler(({ context: { ctx } }) => run(() => health(ctx))),
|
|
551
|
+
agent: os.ops.agent.handler(({ context: { ctx } }) => run(async () => { const [gateway, chat] = await Promise.all([health(ctx), currentChatReadiness(ctx.deps.sidecar())]); return { ...gateway, chat }; })),
|
|
417
552
|
system: os.ops.system.handler(({ context: { ctx } }) => run(() => systemHealth(ctx.deps.config.homeDir, ctx.deps.runtimeDiagnostics()))),
|
|
418
553
|
restart: os.ops.restart.handler(({ context: { ctx } }) => run(async () => {
|
|
419
554
|
const sidecar = ctx.deps.sidecar();
|
|
420
555
|
if (!sidecar)
|
|
421
556
|
throw new HttpError(500, 'Hermes Agent sidecar is not running');
|
|
422
|
-
const outcome = await sidecar
|
|
557
|
+
const outcome = await restartGateway(sidecar, home(ctx));
|
|
423
558
|
if (outcome.status === 'completed')
|
|
424
559
|
return { ok: true, message: 'Gateway service restarted successfully' };
|
|
425
560
|
if (outcome.status === 'busy')
|
|
@@ -433,11 +568,11 @@ export const toolsRouter = os.router({
|
|
|
433
568
|
await ctx.deps.agentConfig.update(home(ctx), (config) => { applyDashboardConfig(config, next); });
|
|
434
569
|
return next;
|
|
435
570
|
})),
|
|
436
|
-
projectOs: os.ops.projectOs.handler(({ input, context: { ctx } }) => run(() => {
|
|
571
|
+
projectOs: os.ops.projectOs.handler(({ input, context: { ctx } }) => run(async () => {
|
|
437
572
|
const profile = activeProfileName(ctx);
|
|
438
573
|
return projectOsDashboard(str(input.board), {
|
|
439
574
|
localIo: ctx.deps.workspaces.profileSupportsLocalIo(profile),
|
|
440
|
-
lastWorkspace: ctx.deps.workspaces.lastWorkspace(profile),
|
|
575
|
+
lastWorkspace: (await ctx.deps.workspaces.lastWorkspace(profile)),
|
|
441
576
|
boards: async () => (await runningSidecar(ctx).call('kanban.boards', { profile_home: home(ctx), include_archived: true })).boards,
|
|
442
577
|
git: async (repoRoot) => gitBadge(await ctx.deps.git.status(repoRoot, { useCache: true })),
|
|
443
578
|
cwd: process.cwd(),
|
|
@@ -471,9 +606,48 @@ export const toolsRouter = os.router({
|
|
|
471
606
|
update: os.mcp.update.handler(({ input, context: { ctx } }) => run(() => { const { name, ...body } = input; return ctx.deps.mcp.update(home(ctx), decodeURIComponent(name), body); })),
|
|
472
607
|
delete: os.mcp.delete.handler(({ input, context: { ctx } }) => run(() => ctx.deps.mcp.delete(home(ctx), decodeURIComponent(input.name)))),
|
|
473
608
|
},
|
|
609
|
+
connectors: {
|
|
610
|
+
// Fails closed: no sidecar, or one that cannot answer, hides the page.
|
|
611
|
+
available: os.connectors.available.handler(({ context: { ctx } }) => run(async () => ({ available: ctx.deps.sidecar() ? await connectorCall(ctx, 'connectors.available', {}).then((r) => r.available, () => false) : false }))),
|
|
612
|
+
page: os.connectors.page.handler(({ context: { ctx } }) => run(async () => {
|
|
613
|
+
if (!ctx.deps.sidecar() || !(await connectorCall(ctx, 'connectors.available', {})).available)
|
|
614
|
+
return { available: false, connectors: [], policy_revision: null, rules_error: null };
|
|
615
|
+
const [catalog, accounts, policy] = await Promise.all([connectorCall(ctx, 'connectors.catalog', {}), connectorCall(ctx, 'connectors.accounts', {}), connectorPolicy(ctx)]);
|
|
616
|
+
rememberCatalogNames(home(ctx), catalog.connectors);
|
|
617
|
+
return connectorsPage(catalog.connectors, accounts.accounts, policy.policy, policy.error);
|
|
618
|
+
})),
|
|
619
|
+
tools: os.connectors.tools.handler(({ input, context: { ctx } }) => run(async () => {
|
|
620
|
+
const [listing, policy] = await Promise.all([connectorCall(ctx, 'connectors.tools', { connector: input.connector }), connectorPolicy(ctx)]);
|
|
621
|
+
return connectorTools(listing, policy.policy);
|
|
622
|
+
})),
|
|
623
|
+
setPolicy: os.connectors.setPolicy.handler(({ input, context: { ctx } }) => run(async () => {
|
|
624
|
+
const change = input.tool === undefined ? (typeof input.enabled === 'boolean' ? { enabled: input.enabled } : null)
|
|
625
|
+
: typeof input.tool_enabled === 'boolean' && input.enabled === undefined ? { tool: input.tool, tool_enabled: input.tool_enabled } : null;
|
|
626
|
+
if (!change)
|
|
627
|
+
throw new HttpError(400, 'Send `enabled`, or `tool` with `tool_enabled`.', { code: 'policy_invalid' });
|
|
628
|
+
const { revision } = await connectorCall(ctx, 'connectors.policy.set', { connector: input.connector, expected_revision: input.revision, ...change });
|
|
629
|
+
return { ok: true, revision };
|
|
630
|
+
})),
|
|
631
|
+
connect: os.connectors.connect.handler(({ input, context: { ctx } }) => run(async () => operationView(ctx, await connectorCall(ctx, 'connectors.connect', { connector: input.connector })))),
|
|
632
|
+
removeAccount: os.connectors.removeAccount.handler(({ input, context: { ctx } }) => run(async () => {
|
|
633
|
+
await connectorCall(ctx, 'connectors.remove', { connection_id: input.connection_id });
|
|
634
|
+
return { ok: true };
|
|
635
|
+
})),
|
|
636
|
+
operation: os.connectors.operation.handler(({ input, context: { ctx } }) => run(async () => operationView(ctx, await connectorCall(ctx, 'connectors.operation', { op_id: input.op_id })))),
|
|
637
|
+
respond: os.connectors.respond.handler(({ input, context: { ctx } }) => run(async () => {
|
|
638
|
+
// Only a move the operation offers now reaches the Agent: the view decides, the sidecar applies.
|
|
639
|
+
const view = connectorOperation(await connectorCall(ctx, 'connectors.operation', { op_id: input.op_id }));
|
|
640
|
+
const { action } = input;
|
|
641
|
+
const offered = action === 'continue' ? view.can_continue : view.targets.some((t) => t.name === input.target && t.actions.includes(action));
|
|
642
|
+
if (!offered)
|
|
643
|
+
throw new HttpError(409, 'That move is not open on this connection.', { code: 'operation_refused' });
|
|
644
|
+
return operationView(ctx, await connectorCall(ctx, 'connectors.respond', { op_id: input.op_id, action, ...(input.target ? { target: input.target } : {}), ...(input.env ? { env: input.env } : {}) }));
|
|
645
|
+
})),
|
|
646
|
+
},
|
|
474
647
|
plugins: os.plugins.handler(({ context: { ctx } }) => run(async () => {
|
|
475
648
|
const sidecar = ctx.deps.sidecar();
|
|
476
649
|
const hooks = ['pre_tool_call', 'post_tool_call', 'pre_llm_call', 'post_llm_call'];
|
|
650
|
+
const editable = await sessionCanManageServer(ctx, await ensureTrustedAuthSession(ctx));
|
|
477
651
|
if (!sidecar)
|
|
478
652
|
return { plugins: [], empty: true, supported_hooks: hooks, read_only: true, unavailable: true };
|
|
479
653
|
try {
|
|
@@ -483,22 +657,80 @@ export const toolsRouter = os.router({
|
|
|
483
657
|
if (v && typeof v === 'object' && !Array.isArray(v) && typeof v.provider === 'string')
|
|
484
658
|
selected[k] = str(v.provider).trim().toLowerCase();
|
|
485
659
|
const result = await sidecar.call('plugins.list', { profile_home: home(ctx), selected_providers: selected });
|
|
486
|
-
|
|
660
|
+
// A settings failure leaves the list itself readable.
|
|
661
|
+
const declared = await pluginSettingsList(ctx).catch((error) => { ctx.deps.log(`[plugins] settings fields failed: ${str(error.message)}`); return []; });
|
|
662
|
+
const settings = new Map(declared.map((entry) => [entry.key, entry.fields]));
|
|
663
|
+
const plugins = result.plugins.map((plugin) => settings.has(plugin.key) ? { ...plugin, settings: settings.get(plugin.key) } : plugin);
|
|
664
|
+
// An advisory failure leaves the list itself readable.
|
|
665
|
+
const advisory = await pluginIsolationAdvisory(ctx).catch((error) => { ctx.deps.log(`[plugins] isolation advisory failed: ${str(error.message)}`); return false; });
|
|
666
|
+
return { plugins, empty: plugins.length === 0, supported_hooks: result.supported_hooks, read_only: !editable, plugin_isolation_advisory: advisory };
|
|
487
667
|
}
|
|
488
668
|
catch (error) {
|
|
489
669
|
ctx.deps.log(`[plugins] visibility payload failed: ${str(error.message)}`);
|
|
490
670
|
return { plugins: [], empty: true, supported_hooks: hooks, read_only: true, unavailable: true };
|
|
491
671
|
}
|
|
492
672
|
})),
|
|
673
|
+
pluginSettings: os.pluginSettings.handler(({ input, context: { ctx } }) => run(() => serializePluginSettingsSave(async () => {
|
|
674
|
+
const sidecar = runningSidecar(ctx);
|
|
675
|
+
const fields = (await pluginSettingsList(ctx)).find((entry) => entry.key === input.key)?.fields;
|
|
676
|
+
if (!fields)
|
|
677
|
+
throw new HttpError(404, `Plugin '${input.key}' declares no settings`);
|
|
678
|
+
let plan;
|
|
679
|
+
try {
|
|
680
|
+
plan = planPluginSettings(fields, input.values ?? {}, input.secrets ?? {});
|
|
681
|
+
}
|
|
682
|
+
catch (error) {
|
|
683
|
+
if (error instanceof PluginSettingsInvalid)
|
|
684
|
+
throw new HttpError(400, error.message);
|
|
685
|
+
throw error;
|
|
686
|
+
}
|
|
687
|
+
const secretFields = fields.filter((field) => field.env && field.env in plan.secrets);
|
|
688
|
+
// Secrets never reach config.yaml: each goes to the profile `.env` under the name the manifest field declares. They are
|
|
689
|
+
// written first and restored if a later write fails, so a refused save changes neither file. The save call always runs:
|
|
690
|
+
// it resolves the plugin again and refuses (before writing) when a secret's `.env` name no longer matches its manifest.
|
|
691
|
+
const credential = (envVar, value) => writeRuntimeCredential({ env: ctx.deps.config.env, sidecar: ctx.deps.sidecar, log: ctx.deps.log }, ctx.deps.isRootProfile(activeProfileName(ctx)), home(ctx), envVar, value);
|
|
692
|
+
const previous = loadEnvFile(join(home(ctx), '.env'));
|
|
693
|
+
const applied = [];
|
|
694
|
+
let result;
|
|
695
|
+
try {
|
|
696
|
+
for (const [envVar, value] of Object.entries(plan.secrets)) {
|
|
697
|
+
await credential(envVar, value);
|
|
698
|
+
applied.push(envVar);
|
|
699
|
+
}
|
|
700
|
+
result = await sidecar.call('plugins.settings_save', { profile_home: home(ctx), key: input.key, values: plan.values, secret_envs: Object.fromEntries(secretFields.map((field) => [field.key, field.env])) });
|
|
701
|
+
}
|
|
702
|
+
catch (error) {
|
|
703
|
+
if (!definitiveRefusal(error)) {
|
|
704
|
+
throw new HttpError(503, 'The Agent sidecar stopped before confirming the save, so it may be partly applied; reload Settings to see what was saved', { condition: 'plugin_settings_unconfirmed' });
|
|
705
|
+
}
|
|
706
|
+
for (const envVar of applied.reverse()) {
|
|
707
|
+
await credential(envVar, previous[envVar] ?? null).catch((restore) => { ctx.deps.log(`[plugins] could not restore ${envVar} after a failed settings save: ${str(restore.message)}`); });
|
|
708
|
+
}
|
|
709
|
+
if (error instanceof SidecarError && error.condition === 'plugin_settings_managed')
|
|
710
|
+
throw new HttpError(403, error.message, { condition: error.condition });
|
|
711
|
+
if (error instanceof SidecarError && error.condition === 'plugin_settings_changed')
|
|
712
|
+
throw new HttpError(409, `${error.message}; reload and try again`, { condition: error.condition });
|
|
713
|
+
if (error instanceof SidecarError && error.condition === 'plugin_not_found')
|
|
714
|
+
throw new HttpError(404, error.message);
|
|
715
|
+
if (error instanceof SidecarError && error.code === -32602)
|
|
716
|
+
throw new HttpError(400, error.message);
|
|
717
|
+
if (error instanceof RuntimeCredentialError)
|
|
718
|
+
throw new HttpError(503, error.message);
|
|
719
|
+
if (error instanceof EnvWriteError)
|
|
720
|
+
throw new HttpError(error.status, `Failed to save a secret: ${error.message}`, { condition: error.condition });
|
|
721
|
+
throw error;
|
|
722
|
+
}
|
|
723
|
+
return { ok: true, key: result.key, written: [...result.written, ...secretFields.map((field) => field.key)], settings: pluginSettingsFieldsView(ctx, result.fields) };
|
|
724
|
+
}))),
|
|
493
725
|
updates: {
|
|
494
|
-
check: os.updates.check.handler(({ context: { ctx } }) => run(() => {
|
|
495
|
-
const settings = ctx.deps.settings.load();
|
|
726
|
+
check: os.updates.check.handler(({ context: { ctx } }) => run(async () => {
|
|
727
|
+
const settings = (await ctx.deps.settings.load());
|
|
496
728
|
if (settings.check_for_updates === false)
|
|
497
729
|
return updatesCheckView({ disabled: true });
|
|
498
730
|
return updatesCheckView(ctx.deps.updates.cachedStatus(!pyBool(settings.ignore_agent_updates)));
|
|
499
731
|
})),
|
|
500
732
|
checkNow: os.updates.checkNow.handler(({ input, context: { ctx } }) => run(async () => {
|
|
501
|
-
const settings = ctx.deps.settings.load();
|
|
733
|
+
const settings = (await ctx.deps.settings.load());
|
|
502
734
|
const force = pyBool(input.force);
|
|
503
735
|
if (settings.check_for_updates === false && !force)
|
|
504
736
|
return updatesCheckView({ disabled: true });
|
|
@@ -507,58 +739,83 @@ export const toolsRouter = os.router({
|
|
|
507
739
|
ctx.deps.log(`[updates] checking for updates (force=${String(force)}, channel=${channel})`);
|
|
508
740
|
return updatesCheckView(await ctx.deps.updates.check(force, !pyBool(settings.ignore_agent_updates), channel, input.agent_channel));
|
|
509
741
|
})),
|
|
510
|
-
apply: os.updates.apply.handler(({ input, context: { ctx } }) => run(() =>
|
|
511
|
-
force: os.updates.force.handler(({ input, context: { ctx } }) => run(() =>
|
|
512
|
-
clearLock: os.updates.clearLock.handler(({ input, context: { ctx } }) => run(() =>
|
|
513
|
-
summary: os.updates.summary.handler(({ input, context: { ctx } }) => run(() => ctx.deps.updates.summarize(input.target, ctx.deps.settings.load().check_for_updates === false))),
|
|
742
|
+
apply: os.updates.apply.handler(({ input, context: { ctx } }) => run(() => applyWithNotification(ctx, input, 'apply'))),
|
|
743
|
+
force: os.updates.force.handler(({ input, context: { ctx } }) => run(() => applyWithNotification(ctx, input, 'force'))),
|
|
744
|
+
clearLock: os.updates.clearLock.handler(({ input, context: { ctx } }) => run(() => applyWithNotification(ctx, input, 'clearLock'))),
|
|
745
|
+
summary: os.updates.summary.handler(({ input, context: { ctx } }) => run(async () => ctx.deps.updates.summarize(input.target, (await ctx.deps.settings.load()).check_for_updates === false))),
|
|
514
746
|
},
|
|
515
747
|
updateNotifications: {
|
|
516
748
|
list: os.updateNotifications.list.handler(({ input, context: { ctx } }) => run(async () => {
|
|
517
749
|
const scope = await updateNotificationScope(ctx, input.tab_id);
|
|
518
|
-
const frontendBuild = ctx.deps.updateNotifications.syncTabBuild(scope, input.loaded_build ?? null, ctx.deps.spa.buildId());
|
|
519
|
-
return { ...ctx.deps.updateNotifications.list(scope), frontend_build: frontendBuild };
|
|
750
|
+
const frontendBuild = (await ctx.deps.updateNotifications.syncTabBuild(scope, input.loaded_build ?? null, ctx.deps.spa.buildId()));
|
|
751
|
+
return { ...(await ctx.deps.updateNotifications.list(scope)), frontend_build: frontendBuild };
|
|
520
752
|
})),
|
|
521
753
|
read: os.updateNotifications.read.handler(({ input, context: { ctx } }) => run(async () => {
|
|
522
|
-
const notification = ctx.deps.updateNotifications.read(await updateNotificationScope(ctx, input.tab_id), input.id);
|
|
754
|
+
const notification = (await ctx.deps.updateNotifications.read(await updateNotificationScope(ctx, input.tab_id), input.id));
|
|
523
755
|
if (!notification)
|
|
524
756
|
throw new HttpError(404, 'Update notification not found');
|
|
525
757
|
return notification;
|
|
526
758
|
})),
|
|
527
759
|
dismiss: os.updateNotifications.dismiss.handler(({ input, context: { ctx } }) => run(async () => {
|
|
528
|
-
const result = ctx.deps.updateNotifications.dismiss(await updateNotificationScope(ctx, input.tab_id), input.id);
|
|
760
|
+
const result = (await ctx.deps.updateNotifications.dismiss(await updateNotificationScope(ctx, input.tab_id), input.id));
|
|
529
761
|
if (result === 'acknowledgement_required')
|
|
530
762
|
throw new HttpError(409, 'This notification requires acknowledgement before it can be dismissed');
|
|
531
763
|
return { ok: true };
|
|
532
764
|
})),
|
|
533
765
|
clear: os.updateNotifications.clear.handler(({ input, context: { ctx } }) => run(async () => {
|
|
534
766
|
const scope = await updateNotificationScope(ctx, input.tab_id);
|
|
535
|
-
const frontendBuild = ctx.deps.updateNotifications.syncTabBuild(scope, input.loaded_build ?? null, ctx.deps.spa.buildId());
|
|
536
|
-
return { ...ctx.deps.updateNotifications.clear(scope), frontend_build: frontendBuild };
|
|
767
|
+
const frontendBuild = (await ctx.deps.updateNotifications.syncTabBuild(scope, input.loaded_build ?? null, ctx.deps.spa.buildId()));
|
|
768
|
+
return { ...(await ctx.deps.updateNotifications.clear(scope)), frontend_build: frontendBuild };
|
|
537
769
|
})),
|
|
538
770
|
cancel: os.updateNotifications.cancel.handler(({ input, context: { ctx } }) => run(async () => {
|
|
539
|
-
const notification = ctx.deps.updateNotifications.cancelUpdate(await updateNotificationScope(ctx), input.id);
|
|
771
|
+
const notification = (await ctx.deps.updateNotifications.cancelUpdate(await updateNotificationScope(ctx), input.id));
|
|
540
772
|
if (!notification)
|
|
541
773
|
throw new HttpError(404, 'Awaiting update notification not found');
|
|
542
774
|
return notification;
|
|
543
775
|
})),
|
|
544
776
|
action: os.updateNotifications.action.handler(({ input, context: { ctx } }) => run(async () => {
|
|
545
|
-
const notification = ctx.deps.updateNotifications.action(await updateNotificationScope(ctx, input.tab_id), input.id, input.action_id);
|
|
777
|
+
const notification = (await ctx.deps.updateNotifications.action(await updateNotificationScope(ctx, input.tab_id), input.id, input.action_id));
|
|
546
778
|
if (!notification)
|
|
547
779
|
throw new HttpError(404, 'Notification action not found');
|
|
780
|
+
if (input.action_id === GATEWAY_RESTART_NOW)
|
|
781
|
+
ctx.deps.gatewayRestarts.restartNow(notification.id);
|
|
548
782
|
return notification;
|
|
549
783
|
})),
|
|
550
784
|
},
|
|
551
785
|
transcribeCapability: os.transcribeCapability.handler(({ context: { ctx } }) => run(async () => {
|
|
786
|
+
const unavailable = { ok: true, available: false, provider: 'none', streaming: false, warm_supported: false };
|
|
552
787
|
const sidecar = ctx.deps.sidecar();
|
|
553
788
|
if (!sidecar)
|
|
554
|
-
return
|
|
789
|
+
return unavailable;
|
|
555
790
|
try {
|
|
556
791
|
const cap = await sidecar.call('stt.capability', { profile_home: home(ctx) });
|
|
557
|
-
return { ok: true, available: cap.available, provider: cap.provider || 'none' };
|
|
792
|
+
return { ok: true, available: cap.available, provider: cap.provider || 'none', streaming: cap.available && cap.streaming, warm_supported: cap.available && cap.warm_supported };
|
|
558
793
|
}
|
|
559
794
|
catch {
|
|
560
|
-
return
|
|
795
|
+
return unavailable;
|
|
796
|
+
}
|
|
797
|
+
})),
|
|
798
|
+
speech: {
|
|
799
|
+
prepare: os.speech.prepare.handler(({ input, context: { ctx } }) => run(async () => ({ spoken_text: await spokenText(ctx, input.text.trim()) }))),
|
|
800
|
+
},
|
|
801
|
+
transcribeWarm: os.transcribeWarm.handler(({ context: { ctx } }) => run(() => {
|
|
802
|
+
const sidecar = ctx.deps.sidecar();
|
|
803
|
+
const profileHome = home(ctx);
|
|
804
|
+
// One load per profile at a time: a record start during a running load joins it rather than holding another sidecar slot.
|
|
805
|
+
if (sidecar && !warmingHomes.has(profileHome)) {
|
|
806
|
+
warmingHomes.add(profileHome);
|
|
807
|
+
// The load outlives this request's write lease: it is the profile's activity until it settles, so the profile
|
|
808
|
+
// cannot be deleted under it. Taken while the request's lease still refuses a deletion in progress.
|
|
809
|
+
const release = ctx.deps.profileActivity(activeProfileName(ctx));
|
|
810
|
+
// A first use downloads the model, and the Agent's load cannot be cancelled, so the call has no deadline: the entry
|
|
811
|
+
// lives exactly as long as the sidecar worker (a sidecar exit rejects it). Nobody waits on it.
|
|
812
|
+
void sidecar.call('stt.warm', { profile_home: profileHome }, { timeoutMs: 0 })
|
|
813
|
+
.then((result) => { if (result.action === 'error')
|
|
814
|
+
ctx.deps.log(`[stt] warm-up failed (${result.provider}): ${str(result.error)}`); })
|
|
815
|
+
.catch((error) => { ctx.deps.log(`[stt] warm-up failed: ${str(error.message)}`); })
|
|
816
|
+
.finally(() => { warmingHomes.delete(profileHome); release(); });
|
|
561
817
|
}
|
|
818
|
+
return { ok: true };
|
|
562
819
|
})),
|
|
563
820
|
clientEvents: os.clientEvents.handler(({ input, context: { ctx } }) => run(() => {
|
|
564
821
|
if (ctx.deps.clientEventLimiter.limited(ctx.peer || 'unknown'))
|