@maudecode/talaria-web 1.17.2 → 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.d.ts +1 -1
- package/dist/api/auth-raw.js +20 -20
- package/dist/api/auth-raw.js.map +1 -1
- package/dist/api/automation-raw.d.ts +7 -1
- package/dist/api/automation-raw.js +74 -27
- package/dist/api/automation-raw.js.map +1 -1
- package/dist/api/automation-router.d.ts +128 -23
- package/dist/api/automation-router.js +29 -13
- package/dist/api/automation-router.js.map +1 -1
- package/dist/api/chat-router.d.ts +1845 -40
- package/dist/api/chat-router.js +196 -114
- package/dist/api/chat-router.js.map +1 -1
- package/dist/api/git-router.d.ts +37 -3
- package/dist/api/git-router.js +47 -48
- package/dist/api/git-router.js.map +1 -1
- package/dist/api/raw-routes.d.ts +9 -1
- package/dist/api/raw-routes.js +286 -73
- package/dist/api/raw-routes.js.map +1 -1
- package/dist/api/router.d.ts +16 -6
- package/dist/api/router.js +28 -26
- 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 +3312 -131
- package/dist/api/sessions-router.js +287 -157
- package/dist/api/sessions-router.js.map +1 -1
- package/dist/api/settings-router.d.ts +457 -8
- package/dist/api/settings-router.js +54 -33
- package/dist/api/settings-router.js.map +1 -1
- package/dist/api/sse-routes.d.ts +7 -2
- package/dist/api/sse-routes.js +109 -62
- package/dist/api/sse-routes.js.map +1 -1
- package/dist/api/tools-raw.d.ts +5 -0
- package/dist/api/tools-raw.js +63 -55
- package/dist/api/tools-raw.js.map +1 -1
- package/dist/api/tools-router.d.ts +998 -85
- package/dist/api/tools-router.js +447 -61
- 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 +98 -59
- package/dist/app.js.map +1 -1
- package/dist/auth/gate.js +15 -11
- package/dist/auth/gate.js.map +1 -1
- package/dist/auth/oidc.d.ts +5 -2
- package/dist/auth/oidc.js +8 -7
- package/dist/auth/oidc.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 +15 -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 +116 -60
- package/dist/config/agent-config.js.map +1 -1
- package/dist/config.d.ts +4 -0
- package/dist/config.js +19 -6
- 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 +31 -12
- package/dist/http/context.js +60 -24
- package/dist/http/context.js.map +1 -1
- package/dist/http/csp.d.ts +2 -1
- package/dist/http/csp.js +3 -2
- package/dist/http/csp.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 +20 -4
- package/dist/profiles/profiles.js +115 -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 +84 -14
- package/dist/providers/catalog.js +474 -151
- 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/raster-image.d.ts +7 -0
- package/dist/raster-image.js +267 -0
- package/dist/raster-image.js.map +1 -0
- package/dist/redact.js +342 -46
- 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 +305 -96
- package/dist/runtime.js.map +1 -1
- package/dist/server.js +15 -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 -27
- package/dist/sessions/background-tasks.js +89 -97
- 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 +27 -6
- package/dist/sessions/cli-sessions.js +152 -42
- package/dist/sessions/cli-sessions.js.map +1 -1
- package/dist/sessions/completions.d.ts +77 -9
- package/dist/sessions/completions.js +482 -45
- 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/export.d.ts +5 -0
- package/dist/sessions/export.js +30 -0
- package/dist/sessions/export.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/gateway-watcher.d.ts +7 -3
- package/dist/sessions/gateway-watcher.js +31 -19
- package/dist/sessions/gateway-watcher.js.map +1 -1
- 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/handoff.d.ts +32 -0
- package/dist/sessions/handoff.js +114 -0
- package/dist/sessions/handoff.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 +31 -16
- package/dist/sessions/list.js +139 -129
- package/dist/sessions/list.js.map +1 -1
- package/dist/sessions/merge.d.ts +69 -13
- package/dist/sessions/merge.js +265 -64
- 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 +19 -0
- package/dist/sessions/recovery.js +322 -0
- package/dist/sessions/recovery.js.map +1 -0
- package/dist/sessions/relay.d.ts +38 -19
- package/dist/sessions/relay.js +302 -79
- package/dist/sessions/relay.js.map +1 -1
- package/dist/sessions/service.d.ts +260 -55
- package/dist/sessions/service.js +1448 -462
- package/dist/sessions/service.js.map +1 -1
- package/dist/sessions/session.d.ts +24 -2
- package/dist/sessions/session.js +69 -7
- 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.d.ts +1 -0
- package/dist/sessions/state-db-worker.js +35 -0
- package/dist/sessions/state-db-worker.js.map +1 -0
- package/dist/sessions/state-db.d.ts +113 -7
- package/dist/sessions/state-db.js +861 -44
- 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 +65 -68
- package/dist/sessions/store.js +305 -602
- 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.d.ts +2 -0
- package/dist/sessions/titles.js +5 -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 +30 -50
- package/dist/sessions/tool-display.js.map +1 -1
- package/dist/sessions/turn-context.d.ts +11 -2
- package/dist/sessions/turn-context.js +18 -11
- package/dist/sessions/turn-context.js.map +1 -1
- package/dist/sessions/turn.d.ts +122 -17
- package/dist/sessions/turn.js +939 -358
- package/dist/sessions/turn.js.map +1 -1
- package/dist/sessions/wakeup-pause.d.ts +54 -0
- package/dist/sessions/wakeup-pause.js +163 -0
- package/dist/sessions/wakeup-pause.js.map +1 -0
- 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 +178 -184
- 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.d.ts +2 -2
- package/dist/sidecar/fake.js +19 -2
- package/dist/sidecar/fake.js.map +1 -1
- package/dist/startup.d.ts +13 -5
- package/dist/startup.js +48 -0
- package/dist/startup.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/test/ts-worker-hooks.d.ts +1 -0
- package/dist/test/ts-worker-hooks.js +24 -0
- package/dist/test/ts-worker-hooks.js.map +1 -0
- package/dist/text/diff.d.ts +9 -14
- package/dist/text/diff.js +74 -108
- package/dist/text/diff.js.map +1 -1
- 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 +122 -18
- package/dist/tools/crons.js.map +1 -1
- package/dist/tools/dashboard-plugins.d.ts +53 -0
- package/dist/tools/dashboard-plugins.js +188 -0
- package/dist/tools/dashboard-plugins.js.map +1 -0
- package/dist/tools/extensions.d.ts +18 -5
- package/dist/tools/extensions.js +344 -266
- 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 +44 -0
- package/dist/tools/health.js +201 -46
- 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/mcp.d.ts +13 -0
- package/dist/tools/mcp.js +88 -0
- package/dist/tools/mcp.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/project-os.d.ts +11 -0
- package/dist/tools/project-os.js +267 -0
- package/dist/tools/project-os.js.map +1 -0
- package/dist/tools/skills.d.ts +14 -5
- package/dist/tools/skills.js +49 -16
- 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 +110 -32
- package/dist/tools/updates.js +1112 -294
- package/dist/tools/updates.js.map +1 -1
- package/dist/tools/wiki.d.ts +68 -0
- package/dist/tools/wiki.js +413 -0
- package/dist/tools/wiki.js.map +1 -0
- package/dist/util.d.ts +2 -0
- package/dist/util.js +5 -0
- package/dist/util.js.map +1 -1
- package/dist/workspace/escape.d.ts +61 -0
- package/dist/workspace/escape.js +149 -0
- package/dist/workspace/escape.js.map +1 -0
- package/dist/workspace/extract.d.ts +22 -0
- package/dist/workspace/extract.js +308 -0
- package/dist/workspace/extract.js.map +1 -0
- package/dist/workspace/fs.d.ts +12 -0
- package/dist/workspace/fs.js +92 -23
- package/dist/workspace/fs.js.map +1 -1
- package/dist/workspace/git.d.ts +34 -1
- package/dist/workspace/git.js +328 -35
- package/dist/workspace/git.js.map +1 -1
- package/dist/workspace/media.d.ts +16 -13
- package/dist/workspace/media.js +43 -61
- package/dist/workspace/media.js.map +1 -1
- package/dist/workspace/rollback.d.ts +36 -22
- package/dist/workspace/rollback.js +178 -272
- package/dist/workspace/rollback.js.map +1 -1
- package/dist/workspace/unzip.js +4 -1
- package/dist/workspace/unzip.js.map +1 -1
- package/dist/workspace/upload.d.ts +7 -4
- package/dist/workspace/upload.js +5 -2
- package/dist/workspace/upload.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.d.ts +2 -1
- package/dist/workspace/worktrees.js +179 -42
- package/dist/workspace/worktrees.js.map +1 -1
- package/package.json +7 -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 +32 -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 +56 -3
- package/sidecar/talaria_sidecar/methods/__init__.py +2 -2
- package/sidecar/talaria_sidecar/methods/aux.py +166 -24
- package/sidecar/talaria_sidecar/methods/chat.py +852 -135
- package/sidecar/talaria_sidecar/methods/checkpoints.py +89 -0
- package/sidecar/talaria_sidecar/methods/commands.py +294 -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 +395 -36
- package/sidecar/talaria_sidecar/methods/cron_execution.py +284 -0
- package/sidecar/talaria_sidecar/methods/gateway.py +212 -55
- 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 +108 -34
- package/sidecar/talaria_sidecar/methods/mcp.py +1 -1
- 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 +218 -15
- package/sidecar/talaria_sidecar/methods/profiles.py +121 -13
- package/sidecar/talaria_sidecar/methods/providers.py +217 -28
- 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 +316 -75
- 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 +98 -13
- package/sidecar/talaria_sidecar/speed.py +35 -0
- package/static/dist/FILES.txt +126 -126
- 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-opyh9y0v.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-bfd4h3id.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-b2x1lqot.js → abnfDiagram-VCTEODGH-gjayq3ra.js} +1 -1
- package/static/dist/assets/architecture-7GRP2DOG-lp56972r.js +1 -0
- package/static/dist/assets/{architectureDiagram-5GKGNRK7-h38o5l7b.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-bqquxv2u.js → blockDiagram-I7D4REHJ-joedghi3.js} +1 -1
- package/static/dist/assets/{c4Diagram-7LVT6UL2-f3fb8w6z.js → c4Diagram-7LVT6UL2-hyrjrohe.js} +1 -1
- package/static/dist/assets/channel-es95o4y8.js +1 -0
- package/static/dist/assets/{chunk-4HAMMTFA-bzfyyzp3.js → chunk-4HAMMTFA-koouqbut.js} +1 -1
- package/static/dist/assets/{chunk-75Z2AOVW-ly99rfx5.js → chunk-75Z2AOVW-bl4bhdnt.js} +1 -1
- package/static/dist/assets/{chunk-DU6HZSFF-bg6ecfqf.js → chunk-DU6HZSFF-gpedttsp.js} +3 -3
- package/static/dist/assets/{chunk-F27PBJKO-e8k7mmqw.js → chunk-F27PBJKO-d8xxi0zi.js} +1 -1
- package/static/dist/assets/{chunk-GMAD6QVW-cmalnoaj.js → chunk-GMAD6QVW-jro0hl73.js} +1 -1
- package/static/dist/assets/{chunk-GVQU2GXP-gmif5o01.js → chunk-GVQU2GXP-djn6gbyu.js} +1 -1
- package/static/dist/assets/{chunk-IMKFNOWR-f1nwwh6u.js → chunk-IMKFNOWR-vw4p5p7o.js} +1 -1
- package/static/dist/assets/{chunk-L3NEJ4N5-oktfh5v7.js → chunk-L3NEJ4N5-n1hj77q8.js} +1 -1
- package/static/dist/assets/{chunk-OSK3NFVY-b1sdx96z.js → chunk-OSK3NFVY-oy0gwn2n.js} +1 -1
- package/static/dist/assets/{chunk-P2QGCYS3-fhu4nzxt.js → chunk-P2QGCYS3-onf1hz6c.js} +1 -1
- package/static/dist/assets/{chunk-POPQ4Y6H-em31rnef.js → chunk-POPQ4Y6H-m8sqn7cs.js} +1 -1
- package/static/dist/assets/{chunk-PWAF6VOD-bxhhyftw.js → chunk-PWAF6VOD-ek4smc8x.js} +1 -1
- package/static/dist/assets/{chunk-SHT3W25Y-fmrvwcav.js → chunk-SHT3W25Y-g9gfvefo.js} +3 -3
- package/static/dist/assets/{chunk-SVP7TREG-lymukl2j.js → chunk-SVP7TREG-f9nfv2cu.js} +1 -1
- package/static/dist/assets/{chunk-TICWLB2K-lmza6k23.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-fw5b1pc6.js → copy-jamtd1pf.js} +1 -1
- package/static/dist/assets/{cynefin-OW5HDTMX-czlhbyhs.js → cynefin-OW5HDTMX-f8xfdd3f.js} +1 -1
- package/static/dist/assets/{cynefinDiagram-5FMLGOSQ-gq7mvswb.js → cynefinDiagram-5FMLGOSQ-n9lb99h9.js} +1 -1
- package/static/dist/assets/{dagre-GXQ25YYZ-cqdbf7dr.js → dagre-GXQ25YYZ-dgailddi.js} +4 -4
- package/static/dist/assets/{diagram-S7CK7UJ4-o6arxa58.js → diagram-S7CK7UJ4-m6aeoe7c.js} +1 -1
- package/static/dist/assets/{diagram-UQ7AKVKN-nhnd68tz.js → diagram-UQ7AKVKN-jall3j0x.js} +1 -1
- package/static/dist/assets/{diagram-VSXAHHWV-dk2sclzn.js → diagram-VSXAHHWV-hbawi7hn.js} +1 -1
- package/static/dist/assets/{diagram-VX7I27RA-n3k5nyx3.js → diagram-VX7I27RA-hendl2tt.js} +1 -1
- package/static/dist/assets/{diagram-Z3DM3KII-m6q9cwdh.js → diagram-Z3DM3KII-igwc35p3.js} +1 -1
- package/static/dist/assets/{ebnfDiagram-PWID7BFC-lsa5641p.js → ebnfDiagram-PWID7BFC-c64knz08.js} +1 -1
- package/static/dist/assets/{erDiagram-RLTQ6QDP-fo2ckbe6.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-nzqz6x9g.js → ganttDiagram-EL5Y4UJY-ma6jxj5i.js} +1 -1
- package/static/dist/assets/{gitGraph-4MIJSDKK-gukvcxe6.js → gitGraph-4MIJSDKK-naa9w6xa.js} +1 -1
- package/static/dist/assets/{gitGraphDiagram-WWUBYQGX-lqhdp8f0.js → gitGraphDiagram-WWUBYQGX-hzltvsod.js} +1 -1
- package/static/dist/assets/{highlighted-body-KPVGNVTW-igw6cp39.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-gvu7a93l.js → info-A6RAGUB7-mn2ut5ko.js} +1 -1
- package/static/dist/assets/{infoDiagram-27XIBGKW-m8t8g6w1.js → infoDiagram-27XIBGKW-h6kuqvsb.js} +1 -1
- package/static/dist/assets/{ishikawaDiagram-5VMMS53U-l07vkbgj.js → ishikawaDiagram-5VMMS53U-e7bnwq7h.js} +1 -1
- package/static/dist/assets/{journeyDiagram-3NMN7TZE-hybkgj8l.js → journeyDiagram-3NMN7TZE-etd1bi6p.js} +1 -1
- package/static/dist/assets/{kanban-definition-UXKFOSKX-by13uvtn.js → kanban-definition-UXKFOSKX-emb1g9dz.js} +4 -4
- package/static/dist/assets/lazyRouteComponent-o816ytzl.js +1 -0
- package/static/dist/assets/{line-osxq6fq7.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-i91oxmou.js → mermaid-parser.core-bnre27u8.js} +3 -3
- package/static/dist/assets/{mindmap-definition-YA3MSWOX-m82mx8ww.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-nbtgge2o.js → packet-AYTQ26CC-hatq7m2e.js} +1 -1
- package/static/dist/assets/pcmTap.worklet-74EKjWAZ.js +1 -0
- package/static/dist/assets/{pegDiagram-XKGWAZYB-f1zxzga1.js → pegDiagram-XKGWAZYB-gwisz8jv.js} +1 -1
- package/static/dist/assets/{pie-WAS4IAKB-of8vuhxs.js → pie-WAS4IAKB-fpftf0mk.js} +1 -1
- package/static/dist/assets/{pieDiagram-E7YTZNPT-o7y8ftio.js → pieDiagram-E7YTZNPT-khm1o9a6.js} +1 -1
- package/static/dist/assets/{quadrantDiagram-AXDQQJYC-iqiwia1t.js → quadrantDiagram-AXDQQJYC-owqc4uqn.js} +1 -1
- package/static/dist/assets/{radar-RG4KPBEZ-delnsy2v.js → radar-RG4KPBEZ-cntfwjpq.js} +1 -1
- package/static/dist/assets/{railroad-74A4TZTK-nspnyq9u.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-z41tqx5z.js → railroadDiagram-O6MQD6OU-etuh0qa0.js} +1 -1
- package/static/dist/assets/{refresh-cw-nt1dtsx4.js → refresh-cw-mqbkv2a3.js} +1 -1
- package/static/dist/assets/refresh-l29ljp76.js +1 -0
- package/static/dist/assets/{requirementDiagram-BXWQKSXE-bdvif194.js → requirementDiagram-BXWQKSXE-oq2ulk22.js} +1 -1
- package/static/dist/assets/{sankeyDiagram-P5KCCOFB-h73e0rol.js → sankeyDiagram-P5KCCOFB-iqc02emv.js} +1 -1
- package/static/dist/assets/saved-ndd4t2xb.js +1 -0
- package/static/dist/assets/{sequenceDiagram-WJ2MYXX4-iv95mb1z.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-k417ixmf.js → stateDiagram-D77RDMKH-dnpt1ato.js} +1 -1
- package/static/dist/assets/stateDiagram-v2-MP3YSRHH-bxjacpk6.js +1 -0
- package/static/dist/assets/{swimlanes-42K2YHIH-esola70w.js → swimlanes-42K2YHIH-loqbdazb.js} +1 -1
- package/static/dist/assets/swimlanesDiagram-VR7AAH4N-id62p9hz.js +8 -0
- package/static/dist/assets/{timeline-definition-24CTP7MA-getrz2y8.js → timeline-definition-24CTP7MA-ol2hnvma.js} +1 -1
- package/static/dist/assets/toast-i3h34v6o.js +64 -0
- package/static/dist/assets/{treeView-Q6P3EWNA-hc7ap1q7.js → treeView-Q6P3EWNA-idrj6iox.js} +1 -1
- package/static/dist/assets/{treemap-WGGIJYW6-b7k1syy5.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-lhg566ew.js → useParams-gjc70qru.js} +1 -1
- package/static/dist/assets/{useSearch-lbrh6ejn.js → useSearch-e6ae539u.js} +1 -1
- package/static/dist/assets/{vennDiagram-4TSXK5OY-n6pcy5qb.js → vennDiagram-4TSXK5OY-bvwr9o2z.js} +1 -1
- package/static/dist/assets/{wardley-WFR3VGLG-lpa18vz1.js → wardley-WFR3VGLG-31ui8tma.js} +1 -1
- package/static/dist/assets/{wardleyDiagram-VM6X3IG4-kpclwwg7.js → wardleyDiagram-VM6X3IG4-k5wqtx4b.js} +1 -1
- package/static/dist/assets/{xychartDiagram-S5SC5T6Z-paa2n8y0.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-fb2td9zi.js +0 -1
- package/static/dist/assets/ChatPage-cj96kiy9.js +0 -25
- package/static/dist/assets/Dialog-kxcg7ard.js +0 -1
- package/static/dist/assets/ExtensionRoute-jf7h0754.js +0 -1
- package/static/dist/assets/HubRoute-gmanpd5y.js +0 -2
- package/static/dist/assets/Markdown-mdwlvj3w.js +0 -598
- package/static/dist/assets/RightPanel-ftvrjlcp.js +0 -1
- package/static/dist/assets/Select-bilaypej.js +0 -1
- package/static/dist/assets/SessionListPanel-og8n36qs.js +0 -1
- package/static/dist/assets/SettingsLayout-jonjefmj.js +0 -1
- package/static/dist/assets/States-nmejrwrm.js +0 -1
- package/static/dist/assets/Toaster-nnl8zkt9.js +0 -1
- package/static/dist/assets/_app-gdidzd94.js +0 -1
- package/static/dist/assets/_app.index-hbarzbjx.js +0 -1
- package/static/dist/assets/_app.insights-luywlarz.js +0 -1
- package/static/dist/assets/_app.kanban-kincnbr8.js +0 -1
- package/static/dist/assets/_app.logs-oi2gr3gs.js +0 -1
- package/static/dist/assets/_app.memory-b6jfivt6.js +0 -1
- package/static/dist/assets/_app.profiles-lpvixmqp.js +0 -1
- package/static/dist/assets/_app.settings-vowx3iq0.js +0 -1
- package/static/dist/assets/_app.settings._section-cnntg1tu.js +0 -3
- package/static/dist/assets/_app.skills-fb57lpau.js +0 -1
- package/static/dist/assets/_app.tasks-eszpx1q7.js +0 -2
- package/static/dist/assets/_app.todos-nr05ac6w.js +0 -1
- package/static/dist/assets/_app.workspaces-d2luomu6.js +0 -1
- package/static/dist/assets/architecture-7GRP2DOG-hd0o7bde.js +0 -1
- package/static/dist/assets/back-bemaer09.js +0 -1
- package/static/dist/assets/cancel-drd0g6d9.js +0 -1
- package/static/dist/assets/channel-cpdgf867.js +0 -1
- package/static/dist/assets/classDiagram-ZZMXUADV-ko09sguk.js +0 -1
- package/static/dist/assets/classDiagram-v2-VYDZK3BY-ko09sguk.js +0 -1
- package/static/dist/assets/copied-ima3pysb.js +0 -1
- package/static/dist/assets/endpoints-d33siokx.js +0 -64
- package/static/dist/assets/eventmodeling-NTZA5JFV-emctlo64.js +0 -1
- package/static/dist/assets/flowDiagram-HODETNUW-bfi3moqa.js +0 -1
- package/static/dist/assets/index-cxq58xb1.js +0 -11
- package/static/dist/assets/index-hgtx08n5.css +0 -2
- package/static/dist/assets/lazyRouteComponent-af0lvgjx.js +0 -1
- package/static/dist/assets/link-jyxicdhg.js +0 -1
- package/static/dist/assets/login-ec21t39x.js +0 -1
- package/static/dist/assets/mermaid-HWGCJPDP-gfl8z3ep.js +0 -1
- package/static/dist/assets/onboarding-btnltvyz.js +0 -1
- package/static/dist/assets/onboarding_model_label-dp7xffoh.js +0 -1
- package/static/dist/assets/railroad-abnf-HS5TGJTU-nst1qxyn.js +0 -1
- package/static/dist/assets/railroad-ebnf-LZEXJU2U-ci37x8qy.js +0 -1
- package/static/dist/assets/railroad-peg-WCYAUIDC-aimkk07z.js +0 -1
- package/static/dist/assets/refresh-b4uams1i.js +0 -1
- package/static/dist/assets/saved-kg52csy7.js +0 -1
- package/static/dist/assets/settings_section_extensions_title-ej0iapxe.js +0 -1
- package/static/dist/assets/share._token-f97e94r0.js +0 -2
- package/static/dist/assets/sliders-horizontal-fj18it47.js +0 -1
- package/static/dist/assets/sse-fwpqtzbg.js +0 -1
- package/static/dist/assets/stateDiagram-v2-MP3YSRHH-hwn4apct.js +0 -1
- package/static/dist/assets/swimlanesDiagram-VR7AAH4N-d1h97oyg.js +0 -8
- package/static/dist/assets/todoStore-eginf9h4.js +0 -1
- package/static/dist/assets/tts-lxdxnmjd.js +0 -1
- package/static/dist/assets/untitled-ovpfthg4.js +0 -1
- package/static/dist/assets/useForm-bcblv1rx.js +0 -1
- package/static/dist/assets/useLocale-fi5jb8ma.js +0 -1
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""``checkpoints.*``: a workspace's filesystem checkpoints through the Agent's own ``CheckpointManager`` (TAL-913).
|
|
2
|
+
|
|
3
|
+
The Agent keeps every project's checkpoints as refs in one shared git store under the profile home; listing, diffing and
|
|
4
|
+
restoring go through its manager so the store layout, the nested-repository refusal and the pre-rollback snapshot stay
|
|
5
|
+
the Agent's.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from ..errors import InvalidParams, RpcError
|
|
11
|
+
from ..home import profile_home_param, scoped_home
|
|
12
|
+
from ..rpc import CallContext
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def checkpoint_kwargs() -> dict:
|
|
16
|
+
"""The profile's ``checkpoints`` config as ``AIAgent`` kwargs, resolved as the Agent's gateway does
|
|
17
|
+
(``gateway/run.py::_checkpoint_agent_kwargs``): the legacy ``checkpoints: true`` form, else the section over
|
|
18
|
+
``DEFAULT_CONFIG``. Only a real ``true`` turns them on, so a quoted ``"false"`` stays off."""
|
|
19
|
+
from hermes_cli.config import DEFAULT_CONFIG, load_config
|
|
20
|
+
|
|
21
|
+
section = (load_config() or {}).get("checkpoints", {})
|
|
22
|
+
if isinstance(section, bool):
|
|
23
|
+
section = {"enabled": section}
|
|
24
|
+
elif not isinstance(section, dict):
|
|
25
|
+
section = {}
|
|
26
|
+
defaults = DEFAULT_CONFIG["checkpoints"]
|
|
27
|
+
return {
|
|
28
|
+
"checkpoints_enabled": section.get("enabled", defaults["enabled"]) is True,
|
|
29
|
+
"checkpoint_max_snapshots": section.get("max_snapshots", defaults["max_snapshots"]),
|
|
30
|
+
"checkpoint_max_total_size_mb": section.get("max_total_size_mb", defaults["max_total_size_mb"]),
|
|
31
|
+
"checkpoint_max_file_size_mb": section.get("max_file_size_mb", defaults["max_file_size_mb"]),
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _manager():
|
|
36
|
+
from tools.checkpoint_manager import CheckpointManager
|
|
37
|
+
|
|
38
|
+
kwargs = checkpoint_kwargs()
|
|
39
|
+
return CheckpointManager(enabled=kwargs["checkpoints_enabled"], max_snapshots=kwargs["checkpoint_max_snapshots"],
|
|
40
|
+
max_total_size_mb=kwargs["checkpoint_max_total_size_mb"], max_file_size_mb=kwargs["checkpoint_max_file_size_mb"])
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _param(params: dict, name: str) -> str:
|
|
44
|
+
value = params.get(name)
|
|
45
|
+
if not isinstance(value, str) or not value.strip():
|
|
46
|
+
raise InvalidParams(f"{name} is required")
|
|
47
|
+
return value
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _agent_result(result: dict) -> dict:
|
|
51
|
+
"""The Agent answers a refusal (unknown checkpoint, uncaptured nested repository, failed checkout) as ``success: False``."""
|
|
52
|
+
if not result.get("success"):
|
|
53
|
+
raise RpcError(str(result.get("error") or "checkpoint operation failed"), condition="checkpoint_failed")
|
|
54
|
+
return result
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _owned(manager, workspace: str, checkpoint: str) -> str:
|
|
58
|
+
"""The full hash of ``checkpoint`` among ``workspace``'s own checkpoints. The store is shared by every project and the
|
|
59
|
+
Agent's diff and restore accept any commit in it, so another workspace's hash would check that tree out here."""
|
|
60
|
+
matches = [c["hash"] for c in manager.list_checkpoints(workspace) if c.get("hash") and str(c["hash"]).startswith(checkpoint.lower())]
|
|
61
|
+
if len(matches) != 1:
|
|
62
|
+
raise RpcError(f"Checkpoint '{checkpoint}' is not a checkpoint of this workspace", condition="checkpoint_failed")
|
|
63
|
+
return matches[0]
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def register(registry) -> None:
|
|
67
|
+
@registry.method("checkpoints.list")
|
|
68
|
+
def list_(ctx: CallContext, params: dict) -> dict:
|
|
69
|
+
workspace = _param(params, "workspace")
|
|
70
|
+
with scoped_home(profile_home_param(params)):
|
|
71
|
+
from tools.checkpoint_manager import _store_path
|
|
72
|
+
|
|
73
|
+
return {"checkpoints": _manager().list_checkpoints(workspace), "store": str(_store_path())}
|
|
74
|
+
|
|
75
|
+
@registry.method("checkpoints.diff")
|
|
76
|
+
def diff(ctx: CallContext, params: dict) -> dict:
|
|
77
|
+
workspace, checkpoint = _param(params, "workspace"), _param(params, "checkpoint")
|
|
78
|
+
with scoped_home(profile_home_param(params)):
|
|
79
|
+
manager = _manager()
|
|
80
|
+
result = _agent_result(manager.diff(workspace, _owned(manager, workspace, checkpoint)))
|
|
81
|
+
return {"stat": str(result.get("stat") or ""), "diff": str(result.get("diff") or "")}
|
|
82
|
+
|
|
83
|
+
@registry.method("checkpoints.restore")
|
|
84
|
+
def restore(ctx: CallContext, params: dict) -> dict:
|
|
85
|
+
workspace, checkpoint = _param(params, "workspace"), _param(params, "checkpoint")
|
|
86
|
+
with scoped_home(profile_home_param(params)):
|
|
87
|
+
manager = _manager()
|
|
88
|
+
result = _agent_result(manager.restore(workspace, _owned(manager, workspace, checkpoint)))
|
|
89
|
+
return {"restored_to": str(result.get("restored_to") or ""), "reason": str(result.get("reason") or "")}
|
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import contextlib
|
|
6
|
+
import importlib.util
|
|
5
7
|
import logging
|
|
8
|
+
import os
|
|
9
|
+
import pathlib
|
|
6
10
|
import threading
|
|
7
11
|
from typing import Any
|
|
8
12
|
|
|
@@ -40,6 +44,103 @@ def parse_slash_command(command: str) -> tuple[str, str]:
|
|
|
40
44
|
return _ALIASES.get(base, base), parts[1] if len(parts) > 1 else ""
|
|
41
45
|
|
|
42
46
|
|
|
47
|
+
def _expand_plan(args: str, **_turn) -> str:
|
|
48
|
+
from agent.plan_prompt import build_plan_prompt
|
|
49
|
+
|
|
50
|
+
return build_plan_prompt(args)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _expand_learn(args: str, **_turn) -> str:
|
|
54
|
+
from agent.learn_prompt import build_learn_prompt
|
|
55
|
+
|
|
56
|
+
return build_learn_prompt(args)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _expand_init(args: str, *, workspace: str, **_turn) -> str:
|
|
60
|
+
from hermes_cli.init_command import build_init_prompt_for_cwd
|
|
61
|
+
|
|
62
|
+
# The Agent falls back to the process cwd for a missing directory; the sidecar's is never the user's project.
|
|
63
|
+
if not workspace or not os.path.isdir(workspace):
|
|
64
|
+
raise InvalidParams("workspace is not a directory")
|
|
65
|
+
return build_init_prompt_for_cwd(cwd=workspace, extra=args)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _expand_initiate_setup(_args: str, *, enabled_toolsets, **_turn) -> str:
|
|
69
|
+
from agent.initiate_setup_prompt import build_initiate_setup_prompt
|
|
70
|
+
from hermes_cli.setup_profile import primary_profile
|
|
71
|
+
from hermes_constants import get_hermes_home
|
|
72
|
+
from model_tools import get_tool_definitions
|
|
73
|
+
|
|
74
|
+
from .chat import _turn_toolsets
|
|
75
|
+
from .toolsets import disabled_toolsets
|
|
76
|
+
|
|
77
|
+
# The gateway's ``_hm_cmd_initiate_setup``: the tools this turn's agent gets, by name. MCP servers connect first, as
|
|
78
|
+
# chat start connects them before its agent snapshots tools; a failure leaves them out, as it does for the turn.
|
|
79
|
+
try:
|
|
80
|
+
discover_profile_mcp_tools()
|
|
81
|
+
except Exception: # noqa: BLE001
|
|
82
|
+
log.warning("MCP discovery failed", exc_info=True)
|
|
83
|
+
tools = get_tool_definitions(enabled_toolsets=_turn_toolsets(enabled_toolsets), disabled_toolsets=disabled_toolsets(),
|
|
84
|
+
quiet_mode=True, skip_tool_search_assembly=True)
|
|
85
|
+
return build_initiate_setup_prompt("webui", [tool["function"]["name"] for tool in tools], primary_profile(get_hermes_home()))
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
# The Agent built-ins every surface answers by rewriting the turn to a builder's prompt (the gateway's
|
|
89
|
+
# ``_hm_rewrite_turn_to_prompt``), with the Agent module each expander needs. ``None``: no expander yet, so no client
|
|
90
|
+
# offers it (``/blueprint`` seeds a turn only after its own slot parsing and job wiring).
|
|
91
|
+
_PROMPT_BUILTINS: dict[str, tuple[Any, str] | None] = {
|
|
92
|
+
"plan": (_expand_plan, "agent.plan_prompt"),
|
|
93
|
+
"learn": (_expand_learn, "agent.learn_prompt"),
|
|
94
|
+
"init": (_expand_init, "hermes_cli.init_command"),
|
|
95
|
+
"initiate-setup": (_expand_initiate_setup, "agent.initiate_setup_prompt"),
|
|
96
|
+
"blueprint": None,
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _prompt_expander(name: str):
|
|
101
|
+
"""The expander for a prompt built-in this Agent ships the builder for; None when it has none."""
|
|
102
|
+
entry = _PROMPT_BUILTINS.get(name)
|
|
103
|
+
if entry is None:
|
|
104
|
+
return None
|
|
105
|
+
try:
|
|
106
|
+
found = importlib.util.find_spec(entry[1]) is not None
|
|
107
|
+
except (ImportError, ValueError):
|
|
108
|
+
found = False
|
|
109
|
+
return entry[0] if found else None
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _prompt_mode(name: str) -> str | None:
|
|
113
|
+
if name not in _PROMPT_BUILTINS:
|
|
114
|
+
return None
|
|
115
|
+
return "expand" if _prompt_expander(name) else "unsupported"
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def expand_prompt(command: str, workspace: str, enabled_toolsets) -> dict[str, Any]:
|
|
119
|
+
"""``/<prompt built-in> [args]`` as the turn text the Agent's own builder writes. ``name`` is the built-in's (None
|
|
120
|
+
when the command is not one) and ``message`` None when this Agent has no builder for it."""
|
|
121
|
+
try:
|
|
122
|
+
name, args = parse_slash_command(command)
|
|
123
|
+
from hermes_cli.commands import resolve_command
|
|
124
|
+
except (InvalidParams, ImportError):
|
|
125
|
+
return {"name": None, "message": None}
|
|
126
|
+
cmd = resolve_command(name)
|
|
127
|
+
if cmd is None or cmd.name not in _PROMPT_BUILTINS:
|
|
128
|
+
return {"name": None, "message": None}
|
|
129
|
+
expander = _prompt_expander(cmd.name)
|
|
130
|
+
if expander is None:
|
|
131
|
+
return {"name": cmd.name, "message": None}
|
|
132
|
+
try:
|
|
133
|
+
message = str(expander(args, workspace=workspace, enabled_toolsets=enabled_toolsets) or "").strip()
|
|
134
|
+
except InvalidParams:
|
|
135
|
+
raise
|
|
136
|
+
except Exception as exc: # noqa: BLE001
|
|
137
|
+
log.warning("Failed to expand /%s", cmd.name, exc_info=True)
|
|
138
|
+
raise RpcError(f"Couldn't start /{cmd.name}", condition="prompt_expand_failed") from exc
|
|
139
|
+
if not message:
|
|
140
|
+
raise RpcError(f"Couldn't start /{cmd.name}", condition="prompt_expand_failed")
|
|
141
|
+
return {"name": cmd.name, "message": message}
|
|
142
|
+
|
|
143
|
+
|
|
43
144
|
def list_commands() -> list[dict[str, Any]]:
|
|
44
145
|
try:
|
|
45
146
|
from hermes_cli.commands import COMMAND_REGISTRY
|
|
@@ -53,13 +154,13 @@ def list_commands() -> list[dict[str, Any]]:
|
|
|
53
154
|
out.append({
|
|
54
155
|
"name": cmd.name, "description": cmd.description, "category": cmd.category, "aliases": list(cmd.aliases),
|
|
55
156
|
"args_hint": cmd.args_hint, "subcommands": list(cmd.subcommands), "cli_only": bool(cmd.cli_only), "gateway_only": bool(cmd.gateway_only),
|
|
56
|
-
"exec": cmd.name in _ALLOWED,
|
|
157
|
+
"exec": cmd.name in _ALLOWED, "prompt": _prompt_mode(cmd.name),
|
|
57
158
|
})
|
|
58
159
|
listed = {c["name"] for c in out}
|
|
59
160
|
for name, (description, category, args_hint) in _RUNTIME_COMMANDS.items():
|
|
60
161
|
if name not in listed:
|
|
61
162
|
out.append({"name": name, "description": description, "category": category, "aliases": [a for a, n in _ALIASES.items() if n == name],
|
|
62
|
-
"args_hint": args_hint, "subcommands": [], "cli_only": False, "gateway_only": False, "exec": True})
|
|
163
|
+
"args_hint": args_hint, "subcommands": [], "cli_only": False, "gateway_only": False, "exec": True, "prompt": None})
|
|
63
164
|
try:
|
|
64
165
|
from hermes_cli.plugins import get_plugin_commands
|
|
65
166
|
|
|
@@ -68,7 +169,7 @@ def list_commands() -> list[dict[str, Any]]:
|
|
|
68
169
|
if name in existing or name in _NEVER_EXPOSE:
|
|
69
170
|
continue
|
|
70
171
|
out.append({"name": name, "description": str(info.get("description", "Plugin command")), "category": "Plugin", "aliases": [],
|
|
71
|
-
"args_hint": str(info.get("args_hint", "")), "subcommands": [], "cli_only": False, "gateway_only": False, "exec": True})
|
|
172
|
+
"args_hint": str(info.get("args_hint", "")), "subcommands": [], "cli_only": False, "gateway_only": False, "exec": True, "prompt": None})
|
|
72
173
|
except Exception: # noqa: BLE001 - plugin registry is optional
|
|
73
174
|
log.debug("plugin command listing failed", exc_info=True)
|
|
74
175
|
return out
|
|
@@ -95,15 +196,27 @@ def retire_unscoped_launch_mcp_servers() -> set[str]:
|
|
|
95
196
|
return names
|
|
96
197
|
|
|
97
198
|
|
|
199
|
+
def discover_profile_mcp_tools() -> list[str]:
|
|
200
|
+
"""Connect this profile's configured servers, retiring pre-multiplex launch connections first."""
|
|
201
|
+
from tools.mcp_tool_discovery import discover_mcp_tools
|
|
202
|
+
|
|
203
|
+
retire_unscoped_launch_mcp_servers()
|
|
204
|
+
return discover_mcp_tools()
|
|
205
|
+
|
|
206
|
+
|
|
98
207
|
def _reload_mcp() -> str:
|
|
99
208
|
with _RELOAD_MCP_LOCK:
|
|
100
209
|
try:
|
|
101
210
|
from agent.secret_scope import is_multiplex_active
|
|
211
|
+
from hermes_constants import get_hermes_home
|
|
102
212
|
from tools.mcp_tool import _lock, _mcp_tool_server_names, _server_visible_in_scope, _servers
|
|
213
|
+
from tools.mcp_tool_agent import reprobe_tool_availability
|
|
103
214
|
from tools.mcp_tool_discovery import discover_mcp_tools
|
|
104
215
|
from tools.mcp_tool_lifecycle import shutdown_mcp_servers
|
|
105
216
|
from tools.mcp_tool_scope import _key_name
|
|
106
217
|
from tools.registry import registry
|
|
218
|
+
|
|
219
|
+
from .chat import refresh_profile_agents_mcp_tools
|
|
107
220
|
except Exception as exc: # noqa: BLE001
|
|
108
221
|
raise RpcError("MCP runtime unavailable", condition="mcp_unavailable") from exc
|
|
109
222
|
# Like the gateway's ``_execute_mcp_reload``: under multiplexing only this profile's connections go down and
|
|
@@ -117,7 +230,11 @@ def _reload_mcp() -> str:
|
|
|
117
230
|
try:
|
|
118
231
|
old = server_names() | retire_unscoped_launch_mcp_servers()
|
|
119
232
|
shutdown_mcp_servers(scope=scope)
|
|
233
|
+
# As the gateway does: drop the cached tool availability verdicts, then hand the profile's open chats the
|
|
234
|
+
# rediscovered tools.
|
|
235
|
+
reprobe_tool_availability()
|
|
120
236
|
tools = discover_mcp_tools() or []
|
|
237
|
+
refresh_profile_agents_mcp_tools(get_hermes_home())
|
|
121
238
|
connected = server_names()
|
|
122
239
|
if scope is not None:
|
|
123
240
|
with _lock:
|
|
@@ -244,6 +361,77 @@ def execute_plugin_command(command: str) -> str | None:
|
|
|
244
361
|
return f"Plugin command error: {type(exc).__name__}"
|
|
245
362
|
|
|
246
363
|
|
|
364
|
+
def _profile_bundles(skill_bundles) -> dict[str, dict[str, Any]]:
|
|
365
|
+
"""The scoped profile's bundles keyed ``/slug``, read from disk the way ``scan_bundles`` reads them.
|
|
366
|
+
|
|
367
|
+
``scan_bundles``/``get_skill_bundles`` publish one profile's bundles in a process-wide cache keyed only by mtime,
|
|
368
|
+
which cron jobs in other profiles read concurrently, so the sidecar never fills it."""
|
|
369
|
+
out: dict[str, dict[str, Any]] = {}
|
|
370
|
+
for path in skill_bundles._iter_bundle_files():
|
|
371
|
+
info = skill_bundles._load_bundle_file(path)
|
|
372
|
+
if info:
|
|
373
|
+
out.setdefault(f"/{info['slug']}", info)
|
|
374
|
+
return out
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
def list_command_bundles() -> list[dict[str, Any]]:
|
|
378
|
+
"""The profile's skill bundles as slash-command rows; [] when the bundle runtime is missing or fails."""
|
|
379
|
+
try:
|
|
380
|
+
import agent.skill_bundles as skill_bundles
|
|
381
|
+
except ImportError:
|
|
382
|
+
return []
|
|
383
|
+
try:
|
|
384
|
+
bundles = sorted(_profile_bundles(skill_bundles).values(), key=lambda b: b["slug"])
|
|
385
|
+
except Exception: # noqa: BLE001
|
|
386
|
+
log.warning("Failed to list skill bundles", exc_info=True)
|
|
387
|
+
return []
|
|
388
|
+
return [{"name": str(b["slug"]).strip().lower(), "description": str(b.get("description") or "").strip() or "Skill bundle",
|
|
389
|
+
"skill_count": len(b.get("skills") or []), "source": "bundle"} for b in bundles if str(b.get("slug") or "").strip()]
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
def _bundle_invocation(info: dict[str, Any], instruction: str) -> tuple[str, list[str], list[str]] | None:
|
|
393
|
+
"""``build_bundle_invocation_message`` for a bundle read by ``_profile_bundles`` (that one looks it up in the shared cache),
|
|
394
|
+
skipping the skills disabled for Web chat (``skills.platform_disabled.webui``)."""
|
|
395
|
+
from agent.skill_commands import _disabled_skill_names, _load_skill_blocks, _load_skill_payload, _scaffold_header
|
|
396
|
+
|
|
397
|
+
name = info["name"]
|
|
398
|
+
loaded, missing, disabled, blocks = _load_skill_blocks(
|
|
399
|
+
[(skill or "").strip() for skill in info["skills"]], _load_skill_payload, lambda _skill: f'[Loaded as part of the "{name}" skill bundle.]',
|
|
400
|
+
None, disabled_names=_disabled_skill_names("webui"))
|
|
401
|
+
if not blocks:
|
|
402
|
+
return None
|
|
403
|
+
header = _scaffold_header(f'"{name}" skill bundle', loaded, lead_lines=[f"Bundle: {name}"], missing=missing, disabled=disabled,
|
|
404
|
+
extra_instruction=info.get("instruction") or "", user_instruction=instruction)
|
|
405
|
+
return "\n\n".join([header, *blocks]), loaded, missing
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
def resolve_bundle_command(command: str) -> dict[str, Any]:
|
|
409
|
+
"""Expand ``/<bundle> [instruction]`` into the user message that loads the bundle's skills."""
|
|
410
|
+
name, instruction = parse_slash_command(command)
|
|
411
|
+
try:
|
|
412
|
+
import agent.skill_bundles as skill_bundles
|
|
413
|
+
from agent.skill_commands import resolve_slash_key
|
|
414
|
+
except ImportError as exc:
|
|
415
|
+
raise RpcError("Skill bundle runtime unavailable", condition="bundle_unavailable") from exc
|
|
416
|
+
try:
|
|
417
|
+
bundles = _profile_bundles(skill_bundles)
|
|
418
|
+
key = resolve_slash_key(name, bundles)
|
|
419
|
+
result = _bundle_invocation(bundles[key], instruction) if key else None
|
|
420
|
+
except ValueError as exc:
|
|
421
|
+
raise InvalidParams(str(exc)) from exc
|
|
422
|
+
except Exception as exc: # noqa: BLE001
|
|
423
|
+
log.warning("Failed to resolve skill bundle command", exc_info=True)
|
|
424
|
+
raise RpcError("Skill bundle command unavailable", condition="bundle_unavailable") from exc
|
|
425
|
+
if key is None:
|
|
426
|
+
raise RpcError("Bundle command not found", condition="bundle_not_found")
|
|
427
|
+
message, loaded, missing = result or ("", [], [])
|
|
428
|
+
message = str(message or "").strip()
|
|
429
|
+
if not message:
|
|
430
|
+
raise RpcError("Bundle command returned no invocation text", condition="bundle_unavailable")
|
|
431
|
+
return {"name": key.lstrip("/"), "source": "bundle", "message": message, "loaded_skills": [str(s) for s in loaded or []],
|
|
432
|
+
"missing_skills": [str(s) for s in missing or []]}
|
|
433
|
+
|
|
434
|
+
|
|
247
435
|
def resolve_moa_config(preset: str | None) -> dict:
|
|
248
436
|
try:
|
|
249
437
|
from hermes_cli.moa_config import moa_usage, normalize_moa_config
|
|
@@ -333,6 +521,74 @@ def plugin_visibility(selected_providers: dict) -> dict:
|
|
|
333
521
|
return {"plugins": rows, "supported_hooks": list(PLUGIN_VISIBILITY_HOOKS)}
|
|
334
522
|
|
|
335
523
|
|
|
524
|
+
def isolation_survey(base_home: pathlib.Path) -> list[dict]:
|
|
525
|
+
"""Each profile's ``plugins.isolation`` and installed third-party plugin count, read from disk without loading a plugin."""
|
|
526
|
+
from hermes_cli.plugin_isolation import isolation_mode
|
|
527
|
+
from hermes_cli.plugins_cmd import _scan_level
|
|
528
|
+
|
|
529
|
+
from .profiles import _yaml_load, named_profile_homes
|
|
530
|
+
|
|
531
|
+
rows = []
|
|
532
|
+
for name, home in [("default", base_home), *named_profile_homes(base_home)]:
|
|
533
|
+
seen: dict = {}
|
|
534
|
+
_scan_level(home / "plugins", "user", set(), "", 0, seen)
|
|
535
|
+
rows.append({"name": name, "isolation": isolation_mode(_yaml_load(home / "config.yaml") or {}), "third_party_plugins": len(seen)})
|
|
536
|
+
return rows
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+
def _plugin_settings_modules():
|
|
540
|
+
"""The Agent's manifest ``config_schema`` reader/writer (v0.21.6+) and its plugin resolver; ``None`` on older Agents."""
|
|
541
|
+
try:
|
|
542
|
+
import hermes_cli.plugins_cmd as plugins_cmd
|
|
543
|
+
import hermes_cli.plugins_settings as plugins_settings
|
|
544
|
+
except ImportError:
|
|
545
|
+
return None
|
|
546
|
+
return plugins_cmd, plugins_settings
|
|
547
|
+
|
|
548
|
+
|
|
549
|
+
def plugin_settings() -> dict:
|
|
550
|
+
"""Every discovered plugin whose manifest declares settings, with its fields (secrets as ``env`` + ``has_value`` only)."""
|
|
551
|
+
modules = _plugin_settings_modules()
|
|
552
|
+
if modules is None:
|
|
553
|
+
return {"supported": False, "plugins": []}
|
|
554
|
+
plugins_cmd, plugins_settings = modules
|
|
555
|
+
rows = []
|
|
556
|
+
for _name, _version, _desc, _source, plugin_dir, key in plugins_cmd._discover_all_plugins():
|
|
557
|
+
fields = plugins_settings.plugin_settings_fields(key, pathlib.Path(str(plugin_dir)) if plugin_dir else None)
|
|
558
|
+
if fields:
|
|
559
|
+
rows.append({"key": key, "fields": fields})
|
|
560
|
+
return {"supported": True, "plugins": rows}
|
|
561
|
+
|
|
562
|
+
|
|
563
|
+
def save_plugin_settings(key: str, values: Any, secret_envs: Any = None) -> dict:
|
|
564
|
+
"""Write manifest-declared, non-secret settings through the Agent's locked writer; returns the refreshed fields.
|
|
565
|
+
|
|
566
|
+
``secret_envs`` (secret key -> ``.env`` name the caller wrote) must still match the manifest before anything is written.
|
|
567
|
+
"""
|
|
568
|
+
if not key or not isinstance(values, dict) or not isinstance(secret_envs or {}, dict):
|
|
569
|
+
raise InvalidParams("plugins.settings_save requires a 'key' and a 'values' mapping")
|
|
570
|
+
modules = _plugin_settings_modules()
|
|
571
|
+
if modules is None:
|
|
572
|
+
raise RpcError("This Hermes Agent cannot edit plugin settings", condition="plugin_settings_unsupported")
|
|
573
|
+
plugins_cmd, plugins_settings = modules
|
|
574
|
+
found = plugins_cmd._find_plugin_entry(key)
|
|
575
|
+
if found is None:
|
|
576
|
+
raise RpcError(f"plugin {key!r} not found", condition="plugin_not_found")
|
|
577
|
+
plugin_dir = pathlib.Path(str(found[4])) if found[4] else None
|
|
578
|
+
current = {field["key"]: field for field in plugins_settings.plugin_settings_fields(found[5], plugin_dir)}
|
|
579
|
+
for secret, env in (secret_envs or {}).items():
|
|
580
|
+
field = current.get(str(secret))
|
|
581
|
+
if field is None or field.get("type") != "secret" or field.get("env") != env:
|
|
582
|
+
raise RpcError(f"{secret!r} is no longer stored in {env}", condition="plugin_settings_changed")
|
|
583
|
+
try:
|
|
584
|
+
written = plugins_settings.save_plugin_settings(found[5], plugin_dir, values)
|
|
585
|
+
except PermissionError as exc:
|
|
586
|
+
raise RpcError(str(exc), condition="plugin_settings_managed") from exc
|
|
587
|
+
except ValueError as exc:
|
|
588
|
+
raise InvalidParams(str(exc)) from exc
|
|
589
|
+
return {"key": found[5], "written": written, "fields": plugins_settings.plugin_settings_fields(found[5], plugin_dir)}
|
|
590
|
+
|
|
591
|
+
|
|
336
592
|
def register(registry) -> None:
|
|
337
593
|
@registry.method("commands.registry")
|
|
338
594
|
def registry_(ctx: CallContext, params: dict) -> dict:
|
|
@@ -346,12 +602,32 @@ def register(registry) -> None:
|
|
|
346
602
|
output = execute_agent_command(command)
|
|
347
603
|
source = "agent"
|
|
348
604
|
if output is None:
|
|
349
|
-
|
|
605
|
+
from .chat import _turn_identity
|
|
606
|
+
|
|
607
|
+
# TAL-904: a chat's plugin command runs under that chat's session and workspace, as its turns do.
|
|
608
|
+
session_id = str(params.get("session_id") or "").strip()
|
|
609
|
+
with _turn_identity(session_id, str(params.get("workspace") or "")) if session_id else contextlib.nullcontext():
|
|
610
|
+
output = execute_plugin_command(command)
|
|
350
611
|
source = "plugin"
|
|
351
612
|
if output is None:
|
|
352
613
|
raise RpcError(f"unknown command {parse_slash_command(command)[0]!r}", condition="command_not_found")
|
|
353
614
|
return {"output": output, "source": source}
|
|
354
615
|
|
|
616
|
+
@registry.method("commands.expand_prompt")
|
|
617
|
+
def expand_prompt_(ctx: CallContext, params: dict) -> dict:
|
|
618
|
+
with scoped_home(profile_home_param(params)):
|
|
619
|
+
return expand_prompt(str(params.get("command") or ""), str(params.get("workspace") or ""), params.get("enabled_toolsets"))
|
|
620
|
+
|
|
621
|
+
@registry.method("commands.bundles")
|
|
622
|
+
def bundles(ctx: CallContext, params: dict) -> dict:
|
|
623
|
+
with scoped_home(profile_home_param(params)):
|
|
624
|
+
return {"bundles": list_command_bundles()}
|
|
625
|
+
|
|
626
|
+
@registry.method("commands.bundle_resolve")
|
|
627
|
+
def bundle_resolve(ctx: CallContext, params: dict) -> dict:
|
|
628
|
+
with scoped_home(profile_home_param(params)):
|
|
629
|
+
return resolve_bundle_command(str(params.get("command") or ""))
|
|
630
|
+
|
|
355
631
|
@registry.method("commands.moa_preset")
|
|
356
632
|
def moa(ctx: CallContext, params: dict) -> dict:
|
|
357
633
|
with scoped_home(profile_home_param(params)):
|
|
@@ -366,3 +642,17 @@ def register(registry) -> None:
|
|
|
366
642
|
def list_(ctx: CallContext, params: dict) -> dict:
|
|
367
643
|
with scoped_home(profile_home_param(params)):
|
|
368
644
|
return plugin_visibility(params.get("selected_providers") if isinstance(params.get("selected_providers"), dict) else {})
|
|
645
|
+
|
|
646
|
+
@registry.method("plugins.isolation")
|
|
647
|
+
def isolation(ctx: CallContext, params: dict) -> dict:
|
|
648
|
+
return {"profiles": isolation_survey(profile_home_param(params, "base_home"))}
|
|
649
|
+
|
|
650
|
+
@registry.method("plugins.settings")
|
|
651
|
+
def settings(ctx: CallContext, params: dict) -> dict:
|
|
652
|
+
with scoped_home(profile_home_param(params)):
|
|
653
|
+
return plugin_settings()
|
|
654
|
+
|
|
655
|
+
@registry.method("plugins.settings_save")
|
|
656
|
+
def settings_save(ctx: CallContext, params: dict) -> dict:
|
|
657
|
+
with scoped_home(profile_home_param(params)):
|
|
658
|
+
return save_plugin_settings(str(params.get("key") or "").strip(), params.get("values"), params.get("secret_envs"))
|
|
@@ -1,16 +1,20 @@
|
|
|
1
|
-
"""``config
|
|
2
|
-
Agent's per-model reasoning capability.
|
|
1
|
+
"""``config.*``, ``models.reasoning_efforts`` and ``personalities.list``: a profile's ``config.yaml`` and ``.env``,
|
|
2
|
+
the Agent's per-model reasoning capability, and the personalities the Agent offers for a config.
|
|
3
3
|
|
|
4
4
|
The TypeScript server owns every config.yaml *policy* (which keys mean what);
|
|
5
5
|
the sidecar only parses and serialises YAML with the Agent's own parser so the
|
|
6
6
|
Node side needs no YAML dependency. Writes are atomic and keep the file's mode.
|
|
7
|
+
``.env`` edits use the Agent's own line helpers under the ``<.env>.lock`` the
|
|
8
|
+
gateway, CLI and plugins also take, so concurrent writers never drop a key.
|
|
7
9
|
"""
|
|
8
10
|
|
|
9
11
|
from __future__ import annotations
|
|
10
12
|
|
|
13
|
+
import contextlib
|
|
11
14
|
import importlib
|
|
12
15
|
import logging
|
|
13
16
|
import os
|
|
17
|
+
import re
|
|
14
18
|
import tempfile
|
|
15
19
|
from pathlib import Path
|
|
16
20
|
|
|
@@ -74,7 +78,11 @@ def write_config(path: Path, config: dict) -> dict:
|
|
|
74
78
|
raise InvalidParams("config must be an object")
|
|
75
79
|
target = _write_target(path)
|
|
76
80
|
target.parent.mkdir(parents=True, exist_ok=True)
|
|
77
|
-
|
|
81
|
+
try:
|
|
82
|
+
replace = getattr(importlib.import_module("hermes_cli.config"), "atomic_config_replace", None)
|
|
83
|
+
except Exception: # noqa: BLE001
|
|
84
|
+
# Operator config must remain writable even when Agent imports are broken.
|
|
85
|
+
replace = None
|
|
78
86
|
mode = None
|
|
79
87
|
try:
|
|
80
88
|
mode = target.stat().st_mode & 0o777
|
|
@@ -83,9 +91,20 @@ def write_config(path: Path, config: dict) -> dict:
|
|
|
83
91
|
fd, tmp = tempfile.mkstemp(dir=str(target.parent), prefix=".config_", suffix=".tmp")
|
|
84
92
|
try:
|
|
85
93
|
with os.fdopen(fd, "w", encoding="utf-8") as handle:
|
|
86
|
-
|
|
94
|
+
if replace is not None:
|
|
95
|
+
# Stage the original document so the Agent retains comments; check the real link before committing.
|
|
96
|
+
try:
|
|
97
|
+
handle.write(target.read_text(encoding="utf-8"))
|
|
98
|
+
except FileNotFoundError:
|
|
99
|
+
pass
|
|
100
|
+
else:
|
|
101
|
+
parser = yaml_parser()
|
|
102
|
+
handle.write(parser.safe_dump(config, sort_keys=False, allow_unicode=True,
|
|
103
|
+
width=getattr(parser, "ROUNDTRIP_YAML_WIDTH", 2**31 - 1)))
|
|
87
104
|
handle.flush()
|
|
88
105
|
os.fsync(handle.fileno())
|
|
106
|
+
if replace is not None:
|
|
107
|
+
replace(Path(tmp), config)
|
|
89
108
|
if mode is not None:
|
|
90
109
|
os.chmod(tmp, mode)
|
|
91
110
|
# A link retargeted while the temp file was being written would otherwise send the write to the wrong file.
|
|
@@ -101,6 +120,88 @@ def write_config(path: Path, config: dict) -> dict:
|
|
|
101
120
|
return {"ok": True, "path": str(path)}
|
|
102
121
|
|
|
103
122
|
|
|
123
|
+
_ENV_NAME = re.compile(r"^[A-Za-z_][A-Za-z0-9_]*$")
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _env_refusal(agent_config, key: str, action: str) -> str | None:
|
|
127
|
+
"""The Agent's ``.env`` write-lock refusal (package-managed install or administrator-managed key)."""
|
|
128
|
+
refusal = getattr(agent_config, "env_write_refusal", None)
|
|
129
|
+
if refusal is not None:
|
|
130
|
+
return refusal(key, action)
|
|
131
|
+
# Agent 0.21.5 only reports the refusal on stderr.
|
|
132
|
+
return f"Cannot {action} {key}: this Hermes installation manages it" if agent_config._env_write_blocked(key, action) else None
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def _env_lock(agent_config, path: Path):
|
|
136
|
+
"""The Agent's ``<.env>.lock`` (Agent 0.21.6+); older Agents have none to share."""
|
|
137
|
+
lock = getattr(agent_config, "_env_write_lock", None)
|
|
138
|
+
return lock(path) if lock is not None else contextlib.nullcontext()
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def env_write(home: Path, updates) -> dict:
|
|
142
|
+
"""Upsert ``updates`` into ``home``'s ``.env`` (``None`` removes a key) with the Agent's own line helpers, under
|
|
143
|
+
the lock its ``save_env_value`` / ``remove_env_value`` take, in one atomic replace.
|
|
144
|
+
|
|
145
|
+
Unlike those two, nothing is published into ``os.environ``: other threads (a gateway spawn snapshotting the
|
|
146
|
+
environment) must never see another profile's key, and ``runtime.env`` alone owns this process's environment.
|
|
147
|
+
Values are trimmed and an empty one is skipped; a value the Agent would strip or quote is refused. Every key is
|
|
148
|
+
checked against the Agent's refusals before the write, and the file ends 0600.
|
|
149
|
+
"""
|
|
150
|
+
if not isinstance(updates, dict) or not all(isinstance(k, str) and _ENV_NAME.match(k) and (v is None or isinstance(v, str)) for k, v in updates.items()):
|
|
151
|
+
raise InvalidParams("updates must map variable names to strings or null")
|
|
152
|
+
changes: dict[str, str | None] = {}
|
|
153
|
+
for key, value in updates.items():
|
|
154
|
+
if value is not None:
|
|
155
|
+
value = value.strip()
|
|
156
|
+
if not value:
|
|
157
|
+
continue
|
|
158
|
+
if "\n" in value or "\r" in value:
|
|
159
|
+
raise InvalidParams("API key must not contain newline characters.")
|
|
160
|
+
# The Agent would strip non-ASCII and quote the rest; refused instead, so the running process and the
|
|
161
|
+
# server's reader see exactly the bytes the file holds.
|
|
162
|
+
if any(not "!" <= c <= "~" or c in "#\"'" for c in value):
|
|
163
|
+
raise InvalidParams("API key must not contain spaces, quotes, '#' or non-ASCII characters.")
|
|
164
|
+
changes[key] = value
|
|
165
|
+
from hermes_cli import config as agent_config
|
|
166
|
+
|
|
167
|
+
with scoped_home(home):
|
|
168
|
+
for key, value in changes.items():
|
|
169
|
+
refusal = _env_refusal(agent_config, key, "remove" if value is None else "set")
|
|
170
|
+
if refusal:
|
|
171
|
+
raise RpcError(refusal, condition="env_write_refused")
|
|
172
|
+
try:
|
|
173
|
+
agent_config.ensure_hermes_home()
|
|
174
|
+
path = agent_config.get_env_path()
|
|
175
|
+
with _env_lock(agent_config, path):
|
|
176
|
+
existed = path.exists()
|
|
177
|
+
lines = agent_config._read_env_lines(path) if existed else []
|
|
178
|
+
before = list(lines)
|
|
179
|
+
for key, value in changes.items():
|
|
180
|
+
defines = agent_config._env_line_defines_key
|
|
181
|
+
if value is None:
|
|
182
|
+
lines = [line for line in lines if not defines(line, key)]
|
|
183
|
+
continue
|
|
184
|
+
agent_config.validate_env_var_name_for_write(key)
|
|
185
|
+
entry = f"{key}={value}\n"
|
|
186
|
+
at = next((i for i, line in enumerate(lines) if defines(line, key)), None)
|
|
187
|
+
if at is not None:
|
|
188
|
+
lines[at] = entry
|
|
189
|
+
else:
|
|
190
|
+
if lines and not lines[-1].endswith("\n"):
|
|
191
|
+
lines[-1] += "\n"
|
|
192
|
+
lines.append(entry)
|
|
193
|
+
if lines != before:
|
|
194
|
+
agent_config._write_env_lines(path, lines, preserve_mode=existed)
|
|
195
|
+
except TimeoutError as exc:
|
|
196
|
+
raise RpcError(str(exc), condition="env_locked") from exc
|
|
197
|
+
except ValueError as exc:
|
|
198
|
+
raise RpcError(str(exc), condition="env_write_refused") from exc
|
|
199
|
+
agent_config.invalidate_env_cache()
|
|
200
|
+
if path.exists():
|
|
201
|
+
os.chmod(path, 0o600)
|
|
202
|
+
return {"ok": True, "path": str(path)}
|
|
203
|
+
|
|
204
|
+
|
|
104
205
|
def reasoning_efforts(model: str, provider: str) -> dict:
|
|
105
206
|
"""Levels the Agent would offer for ``model`` on ``provider`` (``hermes_cli.main_provider_setup``)."""
|
|
106
207
|
efforts: list[str] | None = None
|
|
@@ -122,6 +223,16 @@ def reasoning_efforts(model: str, provider: str) -> dict:
|
|
|
122
223
|
return {"efforts": [str(e) for e in (efforts or [])], "supports_reasoning": supports_reasoning}
|
|
123
224
|
|
|
124
225
|
|
|
226
|
+
def personalities(config) -> list[dict]:
|
|
227
|
+
"""TAL-901: ``config``'s personalities as the Agent offers them (``hermes_cli.personality``), with its list preview
|
|
228
|
+
and rendered prompt."""
|
|
229
|
+
from hermes_cli.personality import available_personalities, describe_personality, render_personality_prompt
|
|
230
|
+
|
|
231
|
+
if not isinstance(config, dict):
|
|
232
|
+
raise InvalidParams("config must be a mapping")
|
|
233
|
+
return [{"name": name, "description": describe_personality(value), "prompt": render_personality_prompt(value)} for name, value in available_personalities(config).items()]
|
|
234
|
+
|
|
235
|
+
|
|
125
236
|
def register(registry) -> None:
|
|
126
237
|
@registry.method("config.get", requires_agent=False)
|
|
127
238
|
def get(ctx: CallContext, params: dict) -> dict:
|
|
@@ -131,7 +242,15 @@ def register(registry) -> None:
|
|
|
131
242
|
def set_(ctx: CallContext, params: dict) -> dict:
|
|
132
243
|
return write_config(config_path_param(params), params.get("config"))
|
|
133
244
|
|
|
245
|
+
@registry.method("config.env_write")
|
|
246
|
+
def env_write_(ctx: CallContext, params: dict) -> dict:
|
|
247
|
+
return env_write(profile_home_param(params), params.get("updates"))
|
|
248
|
+
|
|
134
249
|
@registry.method("models.reasoning_efforts")
|
|
135
250
|
def efforts(ctx: CallContext, params: dict) -> dict:
|
|
136
251
|
with scoped_home(profile_home_param(params)):
|
|
137
252
|
return reasoning_efforts(str(params.get("model") or ""), str(params.get("provider") or ""))
|
|
253
|
+
|
|
254
|
+
@registry.method("personalities.list")
|
|
255
|
+
def personalities_(ctx: CallContext, params: dict) -> dict:
|
|
256
|
+
return {"personalities": personalities(params.get("config"))}
|