@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
|
@@ -10,7 +10,7 @@ import { platform } from 'node:os';
|
|
|
10
10
|
import { spawn } from 'node:child_process';
|
|
11
11
|
import { ifNoneMatchMatches } from '../http/context.js';
|
|
12
12
|
import { SidecarError } from '../sidecar/client.js';
|
|
13
|
-
import { HttpError, requireFields } from './router.js';
|
|
13
|
+
import { HttpError, RawResponse, requireFields } from './router.js';
|
|
14
14
|
import { GitWorkspaceError, WORKSPACE_BUSY_MESSAGE } from '../workspace/git.js';
|
|
15
15
|
import { requestSessionIdGuard } from './session-visibility.js';
|
|
16
16
|
import { HttpFailure, sanitizePaths } from '../sessions/service.js';
|
|
@@ -25,6 +25,8 @@ import { randomUUID } from 'node:crypto';
|
|
|
25
25
|
import { pyOsError, pyRepr, str } from '../util.js';
|
|
26
26
|
import { ensureTrustedAuthSession, sessionCanManageServer } from '../auth/gate.js';
|
|
27
27
|
import { RelayPairingError } from '../sessions/relay.js';
|
|
28
|
+
import { EscapeGrantExpired } from '../workspace/escape.js';
|
|
29
|
+
import { ProfileError } from '../profiles/profiles.js';
|
|
28
30
|
const os = implement({ ...sessionsContract, ...workspacesContract }).$context().use(requestSessionIdGuard);
|
|
29
31
|
/** Map service failures to the Python-shaped error body. */
|
|
30
32
|
export function failure(error) {
|
|
@@ -32,6 +34,8 @@ export function failure(error) {
|
|
|
32
34
|
throw new HttpError(error.status, error.message, error.extra);
|
|
33
35
|
if (error instanceof SessionNotFound)
|
|
34
36
|
throw new HttpError(404, 'Session not found');
|
|
37
|
+
if (error instanceof ProfileError)
|
|
38
|
+
throw new HttpError(error.status, error.message);
|
|
35
39
|
throw error;
|
|
36
40
|
}
|
|
37
41
|
/** Handler boundary: contract outputs are pinned loose objects (index signatures), so the concrete return type is erased here like the `as never` casts elsewhere. */
|
|
@@ -62,18 +66,37 @@ function queryPositiveInt(value, fallback, maximum) {
|
|
|
62
66
|
}
|
|
63
67
|
const sanitizeError = sanitizePaths;
|
|
64
68
|
/** Python `_guard_request_session_visibility` for a body/query session id. */
|
|
65
|
-
function guardVisibility(ctx, sid) {
|
|
66
|
-
if (!ctx.deps.sessions.sessionIdVisible(sid))
|
|
69
|
+
async function guardVisibility(ctx, sid) {
|
|
70
|
+
if (!(await ctx.deps.sessions.sessionIdVisible(sid)))
|
|
67
71
|
throw new HttpError(404, 'Session not found');
|
|
68
72
|
}
|
|
73
|
+
/** Python `float(body["since"])` for the handoff dock: a unix time or numeric string; absent is null. */
|
|
74
|
+
function handoffSince(value) {
|
|
75
|
+
if (value === undefined || value === null)
|
|
76
|
+
return null;
|
|
77
|
+
const n = typeof value === 'number' ? value : typeof value === 'string' && value.trim() ? Number(value) : Number.NaN;
|
|
78
|
+
if (Number.isNaN(n))
|
|
79
|
+
throw new HttpError(400, 'since must be a unix timestamp (number)');
|
|
80
|
+
return n;
|
|
81
|
+
}
|
|
82
|
+
/** The handoff dock's session id and `since`, validated in the predecessor's order. */
|
|
83
|
+
async function handoffInput(ctx, input) {
|
|
84
|
+
requireFields(input, 'session_id');
|
|
85
|
+
const sid = str(input.session_id).trim();
|
|
86
|
+
if (!sid)
|
|
87
|
+
throw new HttpError(400, 'session_id is required');
|
|
88
|
+
const since = handoffSince(input.since);
|
|
89
|
+
await guardVisibility(ctx, sid);
|
|
90
|
+
return { sid, since };
|
|
91
|
+
}
|
|
69
92
|
function allProfilesEnabled(ctx, value) {
|
|
70
93
|
return queryFlag(value) && !ctx.deps.isolatedProfileMode();
|
|
71
94
|
}
|
|
72
95
|
/** Search inputs that select the sidebar rows rather than every stored session (TAL-308). */
|
|
73
96
|
const SIDEBAR_SEARCH_KEYS = ['project_id', 'sidebar_source', 'include_archived', 'exclude_hidden', 'show_cli_sessions', 'show_claude_code_sessions', 'show_cron_sessions', 'show_webhook_sessions', 'show_kanban_sessions'];
|
|
74
97
|
/** The `/api/sessions` row selection for a list or sidebar-search query (TAL-308 shares it). */
|
|
75
|
-
function sidebarListParams(ctx, input) {
|
|
76
|
-
const settings = ctx.deps.settings.load();
|
|
98
|
+
async function sidebarListParams(ctx, input) {
|
|
99
|
+
const settings = (await ctx.deps.settings.load());
|
|
77
100
|
const overrideKeys = ['show_cli_sessions', 'show_claude_code_sessions', 'show_cron_sessions', 'show_webhook_sessions', 'show_kanban_sessions'];
|
|
78
101
|
const sidebarSourceRaw = (input.sidebar_source ?? '').trim().toLowerCase();
|
|
79
102
|
return {
|
|
@@ -95,32 +118,33 @@ function sidebarListParams(ctx, input) {
|
|
|
95
118
|
}
|
|
96
119
|
export const sessionsRouter = os.router({
|
|
97
120
|
sessions: {
|
|
98
|
-
list: os.sessions.list.handler(({ input, context: { ctx } }) => run(() => {
|
|
99
|
-
const { body, etag } = ctx.deps.sessions.list(sidebarListParams(ctx, input));
|
|
121
|
+
list: os.sessions.list.handler(({ input, context: { ctx } }) => run(async () => {
|
|
122
|
+
const { body, etag } = await ctx.deps.sessions.list((await sidebarListParams(ctx, input)));
|
|
100
123
|
ctx.extraResponseHeaders = { etag };
|
|
101
124
|
if (ifNoneMatchMatches(ctx.header('if-none-match') ?? '', etag))
|
|
102
125
|
ctx.notModified = true;
|
|
103
126
|
return body;
|
|
104
127
|
})),
|
|
105
|
-
search: os.sessions.search.handler(({ input, context: { ctx } }) => run(() => {
|
|
128
|
+
search: os.sessions.search.handler(({ input, context: { ctx } }) => run(async () => {
|
|
106
129
|
// Python: `int(depth)` falls back to 5 when malformed.
|
|
107
130
|
const depthRaw = (input.depth ?? '5').trim();
|
|
108
131
|
const depth = /^[+-]?\d+$/.test(depthRaw) ? Math.max(0, Number.parseInt(depthRaw, 10)) : 5;
|
|
109
132
|
const opts = { content: (input.content ?? '1') === '1', depth, allProfiles: allProfilesEnabled(ctx, input.all_profiles) };
|
|
110
133
|
// TAL-308: any sidebar filter answers from the sidebar's own rows; without one the store-only search stays.
|
|
111
134
|
if (SIDEBAR_SEARCH_KEYS.some((k) => input[k] !== undefined)) {
|
|
112
|
-
return ctx.deps.sessions.sidebarSearch(input.q ?? '', sidebarListParams(ctx, input), { ...opts, projectId: input.project_id?.trim() || null });
|
|
135
|
+
return await ctx.deps.sessions.sidebarSearch(input.q ?? '', (await sidebarListParams(ctx, input)), { ...opts, projectId: input.project_id?.trim() || null });
|
|
113
136
|
}
|
|
114
|
-
return ctx.deps.sessions.search(input.q ?? '', opts);
|
|
137
|
+
return await ctx.deps.sessions.search(input.q ?? '', opts);
|
|
115
138
|
})),
|
|
116
|
-
|
|
139
|
+
cleanup: os.sessions.cleanup.handler(({ context: { ctx } }) => run(async () => (await ctx.deps.sessions.cleanup(false)))),
|
|
140
|
+
cleanupZeroMessage: os.sessions.cleanupZeroMessage.handler(({ context: { ctx } }) => run(async () => (await ctx.deps.sessions.cleanup(true)))),
|
|
117
141
|
// TAL-627: each id runs the single-session route's own guards, lock and cleanup, one at a time; a failure becomes
|
|
118
142
|
// that id's result and the rest still run.
|
|
119
143
|
bulk: os.sessions.bulk.handler(async ({ input, context: { ctx } }) => {
|
|
120
144
|
const results = [];
|
|
121
145
|
for (const sid of input.session_ids) {
|
|
122
146
|
try {
|
|
123
|
-
guardVisibility(ctx, sid);
|
|
147
|
+
await guardVisibility(ctx, sid);
|
|
124
148
|
if (input.action === 'delete') {
|
|
125
149
|
const { state_db_cleanup_failed } = await ctx.deps.sessions.delete(sid);
|
|
126
150
|
results.push({ session_id: sid, ok: true, state_db_cleanup_failed: Boolean(state_db_cleanup_failed) });
|
|
@@ -135,7 +159,8 @@ export const sessionsRouter = os.router({
|
|
|
135
159
|
: error instanceof HttpFailure ? [error.status, error.message]
|
|
136
160
|
: error instanceof SessionNotFound ? [404, 'Session not found']
|
|
137
161
|
: [500, sanitizeError(error)];
|
|
138
|
-
|
|
162
|
+
const refused = error instanceof HttpFailure ? error.extra.refused : undefined;
|
|
163
|
+
results.push({ session_id: sid, ok: false, status, error: message, ...(refused ? { refused } : {}) });
|
|
139
164
|
}
|
|
140
165
|
}
|
|
141
166
|
return { results };
|
|
@@ -145,35 +170,39 @@ export const sessionsRouter = os.router({
|
|
|
145
170
|
// No visibility guard here: `detail()` answers 409 `session_profile_mismatch` so the frontend can switch to the owning profile.
|
|
146
171
|
get: os.session.get.handler(({ input, context: { ctx } }) => run(async () => {
|
|
147
172
|
await ctx.deps.sessions.deps.warmModelOptions?.();
|
|
173
|
+
await ctx.deps.turns.loadGoal(input.session_id.trim());
|
|
148
174
|
try {
|
|
149
|
-
return { session: ctx.deps.sessions.detail(input.session_id, input) };
|
|
175
|
+
return { session: (await ctx.deps.sessions.detail(input.session_id, input)) };
|
|
150
176
|
}
|
|
151
177
|
catch (error) {
|
|
152
178
|
// Runs left on the relay by a deletion that predates `clearRelayCompletions` clear when the id is next requested.
|
|
153
179
|
const sid = input.session_id.trim();
|
|
154
|
-
if (error instanceof HttpFailure && error.status === 404 && ctx.deps.sessionStore.wasDeleted(sid))
|
|
155
|
-
ctx.deps.relay.clearDeleted(sid, ctx.deps.activeProfile());
|
|
180
|
+
if (error instanceof HttpFailure && error.status === 404 && (await ctx.deps.sessionStore.wasDeleted(sid)))
|
|
181
|
+
(await ctx.deps.relay.clearDeleted(sid, ctx.deps.activeProfile()));
|
|
156
182
|
throw error;
|
|
157
183
|
}
|
|
158
184
|
})),
|
|
159
|
-
status: os.session.status.handler(({ input, context: { ctx } }) => run(() => {
|
|
185
|
+
status: os.session.status.handler(({ input, context: { ctx } }) => run(async () => {
|
|
160
186
|
if (!input.session_id)
|
|
161
187
|
throw new HttpError(400, 'Missing session_id');
|
|
162
|
-
guardVisibility(ctx, input.session_id);
|
|
163
|
-
return ctx.deps.sessions.status(input.session_id);
|
|
188
|
+
await guardVisibility(ctx, input.session_id);
|
|
189
|
+
return (await ctx.deps.sessions.status(input.session_id));
|
|
164
190
|
})),
|
|
165
|
-
usage: os.session.usage.handler(({ input, context: { ctx } }) => run(() => {
|
|
191
|
+
usage: os.session.usage.handler(({ input, context: { ctx } }) => run(async () => {
|
|
166
192
|
if (!input.session_id)
|
|
167
193
|
throw new HttpError(400, 'Missing session_id');
|
|
168
|
-
guardVisibility(ctx, input.session_id);
|
|
169
|
-
return ctx.deps.sessions.usage(input.session_id);
|
|
194
|
+
await guardVisibility(ctx, input.session_id);
|
|
195
|
+
return (await ctx.deps.sessions.usage(input.session_id));
|
|
170
196
|
})),
|
|
171
197
|
new: os.session.new.handler(({ input, context: { ctx } }) => run(async () => {
|
|
172
198
|
// Python: an invisible prev_session_id is ignored (the service drops it), never an error (#5420).
|
|
173
199
|
const profile = input.profile || null;
|
|
174
200
|
// The middleware warms only the cookie profile's config; new-session defaults read the target's synchronously.
|
|
175
|
-
|
|
176
|
-
|
|
201
|
+
// `profileHome` refuses a profile whose home escapes the profiles root (400) before any warm-up failure is swallowed.
|
|
202
|
+
if (profile) {
|
|
203
|
+
const home = ctx.deps.profileHome(profile);
|
|
204
|
+
await ctx.deps.agentConfig.read(home).catch(() => undefined);
|
|
205
|
+
}
|
|
177
206
|
let worktree = null;
|
|
178
207
|
let worktreeSkipped = null;
|
|
179
208
|
const explicit = 'worktree' in input;
|
|
@@ -186,8 +215,8 @@ export const sessionsRouter = os.router({
|
|
|
186
215
|
}
|
|
187
216
|
if (requested) {
|
|
188
217
|
try {
|
|
189
|
-
let base = input.workspace ? ctx.deps.sessions.resolveNewSessionWorkspace(input, null, profile) : null;
|
|
190
|
-
base ??= ctx.deps.workspaces.resolveTrusted(ctx.deps.workspaces.lastWorkspace(profile), profile);
|
|
218
|
+
let base = input.workspace ? (await ctx.deps.sessions.resolveNewSessionWorkspace(input, null, profile)) : null;
|
|
219
|
+
base ??= (await ctx.deps.workspaces.resolveTrusted((await ctx.deps.workspaces.lastWorkspace(profile)), profile));
|
|
191
220
|
const repo = base;
|
|
192
221
|
worktree = await ctx.deps.git.holdWrite(repo, () => ctx.deps.worktrees.create(repo));
|
|
193
222
|
}
|
|
@@ -205,67 +234,69 @@ export const sessionsRouter = os.router({
|
|
|
205
234
|
worktreeSkipped = error.message;
|
|
206
235
|
}
|
|
207
236
|
}
|
|
208
|
-
const s = ctx.deps.sessions.create(input, { worktree });
|
|
209
|
-
const payload = { session: ctx.deps.sessions.publicSession(s) };
|
|
237
|
+
const s = (await ctx.deps.sessions.create(input, { worktree }));
|
|
238
|
+
const payload = { session: (await ctx.deps.sessions.publicSession(s)) };
|
|
210
239
|
if (worktreeSkipped)
|
|
211
240
|
payload.worktree_skipped = worktreeSkipped;
|
|
212
241
|
return payload;
|
|
213
242
|
})),
|
|
214
243
|
rename: os.session.rename.handler(({ input, context: { ctx } }) => run(async () => {
|
|
215
|
-
guardVisibility(ctx, input.session_id);
|
|
244
|
+
await guardVisibility(ctx, input.session_id);
|
|
216
245
|
if (!input.title)
|
|
217
246
|
throw new HttpError(400, 'Missing required field(s): title');
|
|
218
|
-
return ctx.deps.sessions.rename(input.session_id, input.title);
|
|
247
|
+
return (await ctx.deps.sessions.rename(input.session_id, input.title));
|
|
219
248
|
})),
|
|
220
249
|
delete: os.session.delete.handler(({ input, context: { ctx } }) => run(async () => {
|
|
221
|
-
guardVisibility(ctx, input.session_id);
|
|
222
|
-
return ctx.deps.sessions.delete(input.session_id);
|
|
250
|
+
await guardVisibility(ctx, input.session_id);
|
|
251
|
+
return (await ctx.deps.sessions.delete(input.session_id));
|
|
223
252
|
})),
|
|
224
253
|
pin: os.session.pin.handler(({ input, context: { ctx } }) => run(async () => {
|
|
225
|
-
guardVisibility(ctx, input.session_id);
|
|
254
|
+
await guardVisibility(ctx, input.session_id);
|
|
226
255
|
return ctx.deps.sessions.pin(input.session_id, input.pinned ?? true);
|
|
227
256
|
})),
|
|
228
257
|
archive: os.session.archive.handler(({ input, context: { ctx } }) => run(async () => {
|
|
229
|
-
guardVisibility(ctx, input.session_id);
|
|
230
|
-
return ctx.deps.sessions.archive(input.session_id, input.archived ?? true);
|
|
258
|
+
await guardVisibility(ctx, input.session_id);
|
|
259
|
+
return (await ctx.deps.sessions.archive(input.session_id, input.archived ?? true));
|
|
231
260
|
})),
|
|
232
261
|
move: os.session.move.handler(({ input, context: { ctx } }) => run(async () => {
|
|
233
|
-
guardVisibility(ctx, input.session_id);
|
|
234
|
-
return ctx.deps.sessions.move(input.session_id, input.project_id || null);
|
|
262
|
+
await guardVisibility(ctx, input.session_id);
|
|
263
|
+
return (await ctx.deps.sessions.move(input.session_id, input.project_id || null));
|
|
235
264
|
})),
|
|
236
|
-
duplicate: os.session.duplicate.handler(({ input, context: { ctx } }) => run(() => {
|
|
265
|
+
duplicate: os.session.duplicate.handler(({ input, context: { ctx } }) => run(async () => {
|
|
237
266
|
if (!input.session_id)
|
|
238
267
|
throw new HttpError(400, 'session_id is required');
|
|
239
|
-
guardVisibility(ctx, input.session_id);
|
|
240
|
-
return ctx.deps.sessions.duplicate(input.session_id);
|
|
268
|
+
await guardVisibility(ctx, input.session_id);
|
|
269
|
+
return (await ctx.deps.sessions.duplicate(input.session_id));
|
|
241
270
|
})),
|
|
242
|
-
branch: os.session.branch.handler(({ input, context: { ctx } }) => run(() => {
|
|
243
|
-
guardVisibility(ctx, input.session_id);
|
|
244
|
-
return ctx.deps.sessions.branch(input.session_id, input);
|
|
271
|
+
branch: os.session.branch.handler(({ input, context: { ctx } }) => run(async () => {
|
|
272
|
+
await guardVisibility(ctx, input.session_id);
|
|
273
|
+
return (await ctx.deps.sessions.branch(input.session_id, input));
|
|
245
274
|
})),
|
|
246
275
|
truncate: os.session.truncate.handler(({ input, context: { ctx } }) => run(async () => {
|
|
247
|
-
guardVisibility(ctx, input.session_id);
|
|
248
|
-
|
|
276
|
+
await guardVisibility(ctx, input.session_id);
|
|
277
|
+
// A body without `confirm_deep_truncate` is a released App's, which asked on the device before sending it.
|
|
278
|
+
const hold = input.confirm_deep_truncate === undefined ? null : { confirmToken: input.confirm_deep_truncate ? input.confirm_token ?? null : null };
|
|
279
|
+
return (await ctx.deps.sessions.truncate(input.session_id, input.keep_count, hold));
|
|
249
280
|
})),
|
|
250
281
|
clear: os.session.clear.handler(({ input, context: { ctx } }) => run(async () => {
|
|
251
|
-
guardVisibility(ctx, input.session_id);
|
|
252
|
-
return ctx.deps.sessions.clear(input.session_id);
|
|
282
|
+
await guardVisibility(ctx, input.session_id);
|
|
283
|
+
return (await ctx.deps.sessions.clear(input.session_id));
|
|
253
284
|
})),
|
|
254
285
|
retry: os.session.retry.handler(({ input, context: { ctx } }) => run(async () => {
|
|
255
|
-
guardVisibility(ctx, input.session_id);
|
|
256
|
-
return ctx.deps.sessions.retry(input.session_id);
|
|
286
|
+
await guardVisibility(ctx, input.session_id);
|
|
287
|
+
return (await ctx.deps.sessions.retry(input.session_id));
|
|
257
288
|
})),
|
|
258
289
|
undo: os.session.undo.handler(({ input, context: { ctx } }) => run(async () => {
|
|
259
|
-
guardVisibility(ctx, input.session_id);
|
|
260
|
-
return ctx.deps.sessions.undo(input.session_id);
|
|
290
|
+
await guardVisibility(ctx, input.session_id);
|
|
291
|
+
return (await ctx.deps.sessions.undo(input.session_id));
|
|
261
292
|
})),
|
|
262
293
|
update: os.session.update.handler(({ input, context: { ctx } }) => run(async () => {
|
|
263
|
-
guardVisibility(ctx, input.session_id);
|
|
264
|
-
return ctx.deps.sessions.update(input.session_id, input);
|
|
294
|
+
await guardVisibility(ctx, input.session_id);
|
|
295
|
+
return (await ctx.deps.sessions.update(input.session_id, input));
|
|
265
296
|
})),
|
|
266
297
|
toolsets: os.session.toolsets.handler(({ input, context: { ctx } }) => run(async () => {
|
|
267
|
-
guardVisibility(ctx, input.session_id);
|
|
268
|
-
return ctx.deps.sessions.setToolsets(input.session_id, input.toolsets);
|
|
298
|
+
await guardVisibility(ctx, input.session_id);
|
|
299
|
+
return (await ctx.deps.sessions.setToolsets(input.session_id, input.toolsets));
|
|
269
300
|
})),
|
|
270
301
|
yoloGet: os.session.yoloGet.handler(({ input, context: { ctx } }) => run(() => ctx.deps.sessions.yolo(input.session_id))),
|
|
271
302
|
yoloSet: os.session.yoloSet.handler(({ input, context: { ctx } }) => run(async () => {
|
|
@@ -285,29 +316,52 @@ export const sessionsRouter = os.router({
|
|
|
285
316
|
const released = await ctx.deps.turns.respondApproval(sid, 'once', '', true);
|
|
286
317
|
return { ok: true, yolo_enabled: Boolean(released.yolo_enabled ?? ctx.deps.sessions.yolo(sid).yolo_enabled), ...(released.stale_cleared ? { stale_cleared: true } : {}) };
|
|
287
318
|
})),
|
|
288
|
-
import: os.session.import.handler(({ input, context: { ctx } }) => run(() => ctx.deps.sessions.import(input))),
|
|
319
|
+
import: os.session.import.handler(({ input, context: { ctx } }) => run(async () => (await ctx.deps.sessions.import(input)))),
|
|
289
320
|
regenerateTitle: os.session.regenerateTitle.handler(({ input, context: { ctx } }) => run(async () => {
|
|
290
321
|
const sid = input.session_id;
|
|
291
322
|
let session;
|
|
292
323
|
try {
|
|
293
|
-
session = ctx.deps.sessionStore.get(sid);
|
|
324
|
+
session = (await ctx.deps.sessionStore.get(sid));
|
|
294
325
|
}
|
|
295
326
|
catch {
|
|
296
327
|
throw new HttpError(404, 'Session not found');
|
|
297
328
|
}
|
|
298
|
-
if (ctx.deps.sessions.isReadOnly(session) || ctx.deps.sessions.isSubagentViewOnly(sid))
|
|
329
|
+
if ((await ctx.deps.sessions.isReadOnly(session)) || (await ctx.deps.sessions.isSubagentViewOnly(sid)))
|
|
299
330
|
throw new HttpError(403, 'Read-only imported sessions cannot regenerate titles');
|
|
300
331
|
const generated = await ctx.deps.turns.generateTitle(session, { preferLatest: Boolean(input.prefer_latest) });
|
|
301
332
|
if (!generated.title)
|
|
302
333
|
throw new HttpError(422, `Could not generate a better title (${generated.status || 'empty'})`);
|
|
303
334
|
const current = await ctx.deps.sessions.persistGeneratedTitle(sid, generated.title, 'session_title_regenerate');
|
|
304
|
-
return { session: ctx.deps.sessions.wireRow(current), title: current.title, status: generated.status, raw_preview: generated.rawPreview.slice(0, 240) };
|
|
335
|
+
return { session: (await ctx.deps.sessions.wireRow(current)), title: current.title, status: generated.status, raw_preview: generated.rawPreview.slice(0, 240) };
|
|
336
|
+
})),
|
|
337
|
+
recoveryAudit: os.session.recoveryAudit.handler(({ context: { ctx } }) => run(async () => (await ctx.deps.sessions.recoveryAudit()))),
|
|
338
|
+
recoveryRepairSafe: os.session.recoveryRepairSafe.handler(({ context: { ctx } }) => run(async () => {
|
|
339
|
+
const result = await ctx.deps.sessions.recoveryRepairSafe();
|
|
340
|
+
if (!result.clean)
|
|
341
|
+
throw new RawResponse(409, result);
|
|
342
|
+
return result;
|
|
343
|
+
})),
|
|
344
|
+
lineageReport: os.session.lineageReport.handler(({ input, context: { ctx } }) => run(() => {
|
|
345
|
+
const sid = input.session_id ?? '';
|
|
346
|
+
if (!sid)
|
|
347
|
+
throw new HttpError(400, 'session_id required');
|
|
348
|
+
const report = ctx.deps.sessions.lineageReport(sid);
|
|
349
|
+
if (!report.found)
|
|
350
|
+
throw new HttpError(404, 'Session not found');
|
|
351
|
+
return report;
|
|
352
|
+
})),
|
|
353
|
+
compressionRecoveryStart: os.session.compressionRecoveryStart.handler(({ input, context: { ctx } }) => run(async () => {
|
|
354
|
+
requireFields(input, 'session_id');
|
|
355
|
+
const sid = str(input.session_id).trim();
|
|
356
|
+
if (!sid)
|
|
357
|
+
throw new HttpError(400, 'session_id is required');
|
|
358
|
+
return (await ctx.deps.sessions.compressionRecoveryStart(sid));
|
|
305
359
|
})),
|
|
306
360
|
// TAL-255: the iOS `/compress` route joins or starts the session's compression job and answers with its result.
|
|
307
361
|
compress: os.session.compress.handler(({ input, context: { ctx } }) => run(async () => {
|
|
308
362
|
requireFields(input, 'session_id');
|
|
309
363
|
const sid = str(input.session_id).trim();
|
|
310
|
-
guardVisibility(ctx, sid);
|
|
364
|
+
await guardVisibility(ctx, sid);
|
|
311
365
|
const job = await ctx.deps.sessions.startCompression(sid, input.focus_topic || input.topic);
|
|
312
366
|
await job.done;
|
|
313
367
|
if (job.status === 'error')
|
|
@@ -317,47 +371,56 @@ export const sessionsRouter = os.router({
|
|
|
317
371
|
compressStart: os.session.compressStart.handler(({ input, context: { ctx } }) => run(async () => {
|
|
318
372
|
requireFields(input, 'session_id');
|
|
319
373
|
const sid = str(input.session_id).trim();
|
|
320
|
-
guardVisibility(ctx, sid);
|
|
374
|
+
await guardVisibility(ctx, sid);
|
|
321
375
|
return compressionStatusPayload(await ctx.deps.sessions.startCompression(sid, input.focus_topic || input.topic));
|
|
322
376
|
})),
|
|
323
|
-
|
|
377
|
+
// TAL-258: the handoff dock. Rounds decides when to offer it; the summary is generated and appended to the transcript.
|
|
378
|
+
conversationRounds: os.session.conversationRounds.handler(({ input, context: { ctx } }) => run(async () => {
|
|
379
|
+
const { sid, since } = (await handoffInput(ctx, input));
|
|
380
|
+
return (await ctx.deps.sessions.conversationRounds(sid, since));
|
|
381
|
+
})),
|
|
382
|
+
handoffSummary: os.session.handoffSummary.handler(({ input, context: { ctx } }) => run(async () => {
|
|
383
|
+
const { sid, since } = (await handoffInput(ctx, input));
|
|
384
|
+
return (await ctx.deps.sessions.handoffSummary(sid, since));
|
|
385
|
+
})),
|
|
386
|
+
compressStatus: os.session.compressStatus.handler(({ input, context: { ctx } }) => run(async () => {
|
|
324
387
|
const sid = input.session_id.trim();
|
|
325
388
|
if (!sid)
|
|
326
389
|
throw new HttpError(400, 'session_id is required');
|
|
327
|
-
guardVisibility(ctx, sid);
|
|
328
|
-
const job = ctx.deps.sessions.compressionJob(sid);
|
|
390
|
+
await guardVisibility(ctx, sid);
|
|
391
|
+
const job = (await ctx.deps.sessions.compressionJob(sid));
|
|
329
392
|
return (job ? compressionStatusPayload(job) : { ok: true, status: 'idle', session_id: sid });
|
|
330
393
|
})),
|
|
331
|
-
draftGet: os.session.draftGet.handler(({ input, context: { ctx } }) => run(() => {
|
|
332
|
-
guardVisibility(ctx, input.session_id);
|
|
333
|
-
return ctx.deps.sessions.readDraft(input.session_id);
|
|
394
|
+
draftGet: os.session.draftGet.handler(({ input, context: { ctx } }) => run(async () => {
|
|
395
|
+
await guardVisibility(ctx, input.session_id);
|
|
396
|
+
return (await ctx.deps.sessions.readDraft(input.session_id));
|
|
334
397
|
})),
|
|
335
398
|
draftSave: os.session.draftSave.handler(({ input, context: { ctx } }) => run(async () => {
|
|
336
|
-
guardVisibility(ctx, input.session_id);
|
|
337
|
-
return ctx.deps.sessions.writeDraft(input);
|
|
399
|
+
await guardVisibility(ctx, input.session_id);
|
|
400
|
+
return (await ctx.deps.sessions.writeDraft(input));
|
|
338
401
|
})),
|
|
339
|
-
anchorSceneGet: os.session.anchorSceneGet.handler(({ input, context: { ctx } }) => run(() => {
|
|
340
|
-
guardVisibility(ctx, input.session_id);
|
|
341
|
-
return ctx.deps.sessions.readAnchorScene(input);
|
|
402
|
+
anchorSceneGet: os.session.anchorSceneGet.handler(({ input, context: { ctx } }) => run(async () => {
|
|
403
|
+
await guardVisibility(ctx, input.session_id);
|
|
404
|
+
return (await ctx.deps.sessions.readAnchorScene(input));
|
|
342
405
|
})),
|
|
343
|
-
toolResult: os.session.toolResult.handler(({ input, context: { ctx } }) => run(() => {
|
|
344
|
-
guardVisibility(ctx, input.session_id);
|
|
345
|
-
return ctx.deps.sessions.readToolResult(input);
|
|
406
|
+
toolResult: os.session.toolResult.handler(({ input, context: { ctx } }) => run(async () => {
|
|
407
|
+
await guardVisibility(ctx, input.session_id);
|
|
408
|
+
return (await ctx.deps.sessions.readToolResult(input));
|
|
346
409
|
})),
|
|
347
410
|
anchorSceneSave: os.session.anchorSceneSave.handler(({ input, context: { ctx } }) => run(async () => {
|
|
348
|
-
guardVisibility(ctx, input.session_id);
|
|
349
|
-
return ctx.deps.sessions.saveAnchorScene(input);
|
|
411
|
+
await guardVisibility(ctx, input.session_id);
|
|
412
|
+
return (await ctx.deps.sessions.saveAnchorScene(input));
|
|
350
413
|
})),
|
|
351
414
|
},
|
|
352
415
|
projects: {
|
|
353
|
-
list: os.projects.list.handler(({ input, context: { ctx } }) => run(() => {
|
|
416
|
+
list: os.projects.list.handler(({ input, context: { ctx } }) => run(async () => {
|
|
354
417
|
const activeProfile = ctx.deps.activeProfile();
|
|
355
|
-
const all = ctx.deps.projects.load();
|
|
418
|
+
const all = (await ctx.deps.projects.load());
|
|
356
419
|
const allProfiles = allProfilesEnabled(ctx, input.all_profiles);
|
|
357
420
|
const scoped = allProfiles ? all : all.filter((p) => ctx.deps.profilesMatch(p.profile ?? null, activeProfile));
|
|
358
421
|
return { projects: scoped, all_profiles: allProfiles, active_profile: activeProfile, other_profile_count: allProfiles || ctx.deps.isolatedProfileMode() ? 0 : all.length - scoped.length };
|
|
359
422
|
})),
|
|
360
|
-
create: os.projects.create.handler(({ input, context: { ctx } }) => run(() => {
|
|
423
|
+
create: os.projects.create.handler(({ input, context: { ctx } }) => run(async () => {
|
|
361
424
|
const name = input.name.trim().slice(0, 128);
|
|
362
425
|
if (!name)
|
|
363
426
|
throw new HttpError(400, 'name required');
|
|
@@ -367,43 +430,43 @@ export const sessionsRouter = os.router({
|
|
|
367
430
|
const requested = (input.profile ?? '').trim();
|
|
368
431
|
if (requested && requested !== 'default' && !/^[a-z0-9][a-z0-9_-]{0,63}$/.test(requested))
|
|
369
432
|
throw new HttpError(400, 'invalid profile');
|
|
370
|
-
const projects = ctx.deps.projects.load();
|
|
371
433
|
const proj = { project_id: randomUUID().replace(/-/g, '').slice(0, 12), name, color, profile: requested || ctx.deps.activeProfile() || 'default', created_at: ctx.deps.auth.now() };
|
|
372
|
-
projects.push(proj);
|
|
373
|
-
ctx.deps.projects.save(projects);
|
|
434
|
+
await ctx.deps.projects.mutate((projects) => { projects.push(proj); });
|
|
374
435
|
ctx.deps.events.publish('project_create', { profile: proj.profile });
|
|
375
436
|
return { ok: true, project: proj };
|
|
376
437
|
})),
|
|
377
|
-
rename: os.projects.rename.handler(({ input, context: { ctx } }) => run(() => {
|
|
378
|
-
const projects = ctx.deps.projects.load();
|
|
379
|
-
const proj = projects.find((p) => p.project_id === input.project_id);
|
|
438
|
+
rename: os.projects.rename.handler(({ input, context: { ctx } }) => run(async () => {
|
|
380
439
|
const activeProfile = ctx.deps.activeProfile();
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
if (color
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
440
|
+
const proj = await ctx.deps.projects.mutate((projects) => {
|
|
441
|
+
const proj = projects.find((p) => p.project_id === input.project_id);
|
|
442
|
+
if (!proj || !ctx.deps.profilesMatch(proj.profile ?? null, activeProfile))
|
|
443
|
+
throw new HttpError(404, 'Project not found');
|
|
444
|
+
requireFields(input, 'project_id', 'name');
|
|
445
|
+
proj.name = input.name.trim().slice(0, 128);
|
|
446
|
+
if ('color' in input) {
|
|
447
|
+
const color = input.color ?? null;
|
|
448
|
+
if (color && !/^#[0-9a-fA-F]{3,8}$/.test(color))
|
|
449
|
+
throw new HttpError(400, 'Invalid color format');
|
|
450
|
+
proj.color = color;
|
|
451
|
+
}
|
|
452
|
+
return proj;
|
|
453
|
+
});
|
|
392
454
|
ctx.deps.events.publish('project_rename', { profile: activeProfile });
|
|
393
455
|
return { ok: true, project: proj };
|
|
394
456
|
})),
|
|
395
|
-
delete: os.projects.delete.handler(({ input, context: { ctx } }) => run(() => {
|
|
396
|
-
let projects = ctx.deps.projects.load();
|
|
397
|
-
const proj = projects.find((p) => p.project_id === input.project_id);
|
|
457
|
+
delete: os.projects.delete.handler(({ input, context: { ctx } }) => run(async () => {
|
|
398
458
|
const activeProfile = ctx.deps.activeProfile();
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
459
|
+
await ctx.deps.projects.mutate((projects) => {
|
|
460
|
+
const position = projects.findIndex((p) => p.project_id === input.project_id);
|
|
461
|
+
const proj = projects[position];
|
|
462
|
+
if (!proj || !ctx.deps.profilesMatch(proj.profile ?? null, activeProfile))
|
|
463
|
+
throw new HttpError(404, 'Project not found');
|
|
464
|
+
projects.splice(position, 1);
|
|
465
|
+
});
|
|
403
466
|
const store = ctx.deps.sessionStore;
|
|
404
467
|
const activeIds = ctx.deps.sessions.deps.runtime.activeStreamIds;
|
|
405
468
|
try {
|
|
406
|
-
for (const entry of store.readIndexEntries()) {
|
|
469
|
+
for (const entry of (await store.readIndexEntries())) {
|
|
407
470
|
if (entry.project_id !== input.project_id)
|
|
408
471
|
continue;
|
|
409
472
|
const sid = str(entry.session_id);
|
|
@@ -415,9 +478,9 @@ export const sessionsRouter = os.router({
|
|
|
415
478
|
continue;
|
|
416
479
|
}
|
|
417
480
|
}
|
|
418
|
-
const s = store.get(sid);
|
|
481
|
+
const s = (await store.get(sid));
|
|
419
482
|
s.project_id = null;
|
|
420
|
-
store.save(s);
|
|
483
|
+
await store.save(s);
|
|
421
484
|
}
|
|
422
485
|
catch { /* one slow or failing session never aborts the request */ }
|
|
423
486
|
}
|
|
@@ -442,36 +505,36 @@ export const sessionsRouter = os.router({
|
|
|
442
505
|
const bound = str(session?.bound_profile).trim() || null;
|
|
443
506
|
return relayCall(() => Promise.resolve(ctx.deps.relay.presence.update(input, ctx.deps.isRootProfile(bound ?? ctx.deps.activeProfile()) ? 'default' : (bound ?? ctx.deps.activeProfile()))));
|
|
444
507
|
}),
|
|
445
|
-
viewed: os.talaria.viewed.handler(({ input, context: { ctx } }) => run(() => {
|
|
446
|
-
ctx.deps.relay.markViewed(input.session_id.trim());
|
|
508
|
+
viewed: os.talaria.viewed.handler(({ input, context: { ctx } }) => run(async () => {
|
|
509
|
+
await ctx.deps.relay.markViewed(input.session_id.trim());
|
|
447
510
|
return { ok: true };
|
|
448
511
|
})),
|
|
449
512
|
},
|
|
450
513
|
share: {
|
|
451
|
-
create: os.share.create.handler(({ input, context: { ctx } }) => run(() => {
|
|
514
|
+
create: os.share.create.handler(({ input, context: { ctx } }) => run(async () => {
|
|
452
515
|
const sid = input.session_id.trim();
|
|
453
516
|
if (!sid)
|
|
454
517
|
throw new HttpError(400, 'session_id is required');
|
|
455
|
-
return ctx.deps.sessions.createShare(sid);
|
|
518
|
+
return (await ctx.deps.sessions.createShare(sid));
|
|
456
519
|
})),
|
|
457
|
-
revoke: os.share.revoke.handler(({ input, context: { ctx } }) => run(() => {
|
|
520
|
+
revoke: os.share.revoke.handler(({ input, context: { ctx } }) => run(async () => {
|
|
458
521
|
const sid = input.session_id.trim();
|
|
459
522
|
if (!sid)
|
|
460
523
|
throw new HttpError(400, 'session_id is required');
|
|
461
|
-
return ctx.deps.sessions.revokeShare(sid);
|
|
524
|
+
return (await ctx.deps.sessions.revokeShare(sid));
|
|
462
525
|
})),
|
|
463
|
-
read: os.share.read.handler(({ input, context: { ctx } }) => run(() => {
|
|
526
|
+
read: os.share.read.handler(({ input, context: { ctx } }) => run(async () => {
|
|
464
527
|
ctx.extraResponseHeaders = { 'x-robots-tag': 'noindex, nofollow' };
|
|
465
|
-
return ctx.deps.sessions.loadShare(input.token.trim());
|
|
528
|
+
return (await ctx.deps.sessions.loadShare(input.token.trim()));
|
|
466
529
|
})),
|
|
467
530
|
},
|
|
468
531
|
workspaces: {
|
|
469
|
-
list: os.workspaces.list.handler(({ context: { ctx } }) => run(() => {
|
|
532
|
+
list: os.workspaces.list.handler(({ context: { ctx } }) => run(async () => {
|
|
470
533
|
const profile = ctx.deps.activeProfile();
|
|
471
|
-
return { workspaces: ctx.deps.workspaces.load(profile), last: ctx.deps.workspaces.lastWorkspace(profile), terminal_remote_backend: ctx.deps.features().terminal_remote_backend };
|
|
534
|
+
return { workspaces: (await ctx.deps.workspaces.load(profile)), last: (await ctx.deps.workspaces.lastWorkspace(profile)), terminal_remote_backend: ctx.deps.features().terminal_remote_backend };
|
|
472
535
|
})),
|
|
473
|
-
suggest: os.workspaces.suggest.handler(({ input, context: { ctx } }) => run(() => ({ suggestions: ctx.deps.workspaces.suggest(input.prefix ?? '', 12, ctx.deps.activeProfile()), prefix: input.prefix ?? '' }))),
|
|
474
|
-
add: os.workspaces.add.handler(({ input, context: { ctx } }) => run(() => {
|
|
536
|
+
suggest: os.workspaces.suggest.handler(({ input, context: { ctx } }) => run(async () => ({ suggestions: (await ctx.deps.workspaces.suggest(input.prefix ?? '', 12, ctx.deps.activeProfile())), prefix: input.prefix ?? '' }))),
|
|
537
|
+
add: os.workspaces.add.handler(({ input, context: { ctx } }) => run(async () => {
|
|
475
538
|
const ws = ctx.deps.workspaces;
|
|
476
539
|
const pathStr = stripSurroundingQuotes(input.path.trim());
|
|
477
540
|
const name = (input.name ?? '').trim();
|
|
@@ -510,42 +573,42 @@ export const sessionsRouter = os.router({
|
|
|
510
573
|
catch (error) {
|
|
511
574
|
throw new HttpError(400, error.message);
|
|
512
575
|
}
|
|
513
|
-
const list = ws.load(profile);
|
|
576
|
+
const list = (await ws.load(profile));
|
|
514
577
|
if (list.some((w) => w.path === p))
|
|
515
578
|
throw new HttpError(400, 'Workspace already in list');
|
|
516
579
|
list.push({ path: p, name: name || basename(p) });
|
|
517
|
-
ws.save(list, profile);
|
|
580
|
+
await ws.save(list, profile);
|
|
518
581
|
return { ok: true, workspaces: list };
|
|
519
582
|
})),
|
|
520
|
-
remove: os.workspaces.remove.handler(({ input, context: { ctx } }) => run(() => {
|
|
583
|
+
remove: os.workspaces.remove.handler(({ input, context: { ctx } }) => run(async () => {
|
|
521
584
|
const pathStr = input.path.trim();
|
|
522
585
|
if (!pathStr)
|
|
523
586
|
throw new HttpError(400, 'path is required');
|
|
524
587
|
const profile = ctx.deps.activeProfile();
|
|
525
|
-
const list = ctx.deps.workspaces.load(profile).filter((w) => w.path !== pathStr);
|
|
526
|
-
ctx.deps.workspaces.save(list, profile);
|
|
588
|
+
const list = (await ctx.deps.workspaces.load(profile)).filter((w) => w.path !== pathStr);
|
|
589
|
+
await ctx.deps.workspaces.save(list, profile);
|
|
527
590
|
return { ok: true, workspaces: list };
|
|
528
591
|
})),
|
|
529
|
-
rename: os.workspaces.rename.handler(({ input, context: { ctx } }) => run(() => {
|
|
592
|
+
rename: os.workspaces.rename.handler(({ input, context: { ctx } }) => run(async () => {
|
|
530
593
|
const pathStr = input.path.trim();
|
|
531
594
|
const name = input.name.trim();
|
|
532
595
|
if (!pathStr || !name)
|
|
533
596
|
throw new HttpError(400, 'path and name are required');
|
|
534
597
|
const profile = ctx.deps.activeProfile();
|
|
535
|
-
const list = ctx.deps.workspaces.load(profile);
|
|
598
|
+
const list = (await ctx.deps.workspaces.load(profile));
|
|
536
599
|
const entry = list.find((w) => w.path === pathStr);
|
|
537
600
|
if (!entry)
|
|
538
601
|
throw new HttpError(404, 'Workspace not found');
|
|
539
602
|
entry.name = name;
|
|
540
|
-
ctx.deps.workspaces.save(list, profile);
|
|
603
|
+
await ctx.deps.workspaces.save(list, profile);
|
|
541
604
|
return { ok: true, workspaces: list };
|
|
542
605
|
})),
|
|
543
|
-
reorder: os.workspaces.reorder.handler(({ input, context: { ctx } }) => run(() => {
|
|
606
|
+
reorder: os.workspaces.reorder.handler(({ input, context: { ctx } }) => run(async () => {
|
|
544
607
|
const paths = input.paths;
|
|
545
608
|
if (!Array.isArray(paths) || !paths.length)
|
|
546
609
|
throw new HttpError(400, 'paths is required and must be a list');
|
|
547
610
|
const profile = ctx.deps.activeProfile();
|
|
548
|
-
const list = ctx.deps.workspaces.load(profile);
|
|
611
|
+
const list = (await ctx.deps.workspaces.load(profile));
|
|
549
612
|
const byPath = new Map(list.map((w) => [w.path, w]));
|
|
550
613
|
const reordered = [];
|
|
551
614
|
const seen = new Set();
|
|
@@ -560,18 +623,18 @@ export const sessionsRouter = os.router({
|
|
|
560
623
|
for (const w of list)
|
|
561
624
|
if (!seen.has(w.path))
|
|
562
625
|
reordered.push(w);
|
|
563
|
-
ctx.deps.workspaces.save(reordered, profile);
|
|
626
|
+
await ctx.deps.workspaces.save(reordered, profile);
|
|
564
627
|
return { ok: true, workspaces: reordered };
|
|
565
628
|
})),
|
|
566
629
|
},
|
|
567
630
|
files: {
|
|
568
|
-
list: os.files.list.handler(({ input, context: { ctx } }) => run(() => {
|
|
631
|
+
list: os.files.list.handler(({ input, context: { ctx } }) => run(async () => {
|
|
569
632
|
if (!input.session_id)
|
|
570
633
|
throw new HttpError(400, 'session_id is required');
|
|
571
|
-
guardVisibility(ctx, input.session_id);
|
|
634
|
+
await guardVisibility(ctx, input.session_id);
|
|
572
635
|
// Python `_handle_list` resolved the workspace directly and answered 404 with the trust error; the POST file ops
|
|
573
636
|
// keep `get_session_for_file_ops`' lenient fallback.
|
|
574
|
-
const s = fileOpsSession(ctx, input.session_id, { strictWorkspace: true });
|
|
637
|
+
const s = (await fileOpsSession(ctx, input.session_id, { strictWorkspace: true }));
|
|
575
638
|
const rel = input.path ?? '.';
|
|
576
639
|
try {
|
|
577
640
|
const entries = listDir(s.workspace, rel);
|
|
@@ -581,11 +644,11 @@ export const sessionsRouter = os.router({
|
|
|
581
644
|
throw fileError(error, 404);
|
|
582
645
|
}
|
|
583
646
|
})),
|
|
584
|
-
read: os.files.read.handler(({ input, context: { ctx } }) => run(() => {
|
|
647
|
+
read: os.files.read.handler(({ input, context: { ctx } }) => run(async () => {
|
|
585
648
|
if (!input.session_id)
|
|
586
649
|
throw new HttpError(400, 'session_id is required');
|
|
587
|
-
guardVisibility(ctx, input.session_id);
|
|
588
|
-
const s = fileOpsSession(ctx, input.session_id);
|
|
650
|
+
await guardVisibility(ctx, input.session_id);
|
|
651
|
+
const s = (await fileOpsSession(ctx, input.session_id));
|
|
589
652
|
if (!input.path)
|
|
590
653
|
throw new HttpError(400, 'path is required');
|
|
591
654
|
try {
|
|
@@ -596,9 +659,9 @@ export const sessionsRouter = os.router({
|
|
|
596
659
|
throw fileError(error, 404);
|
|
597
660
|
}
|
|
598
661
|
})),
|
|
599
|
-
save: os.files.save.handler(({ input, context: { ctx } }) => run(() => {
|
|
662
|
+
save: os.files.save.handler(({ input, context: { ctx } }) => run(async () => {
|
|
600
663
|
requireFields(input, 'session_id', 'path');
|
|
601
|
-
const s = fileOpsSession(ctx, input.session_id);
|
|
664
|
+
const s = (await fileOpsSession(ctx, input.session_id));
|
|
602
665
|
try {
|
|
603
666
|
if (['.docx', '.xlsx', '.pptx'].includes(extname(input.path).toLowerCase()))
|
|
604
667
|
throw new HttpError(400, 'Office documents cannot be saved from the Web UI');
|
|
@@ -625,9 +688,9 @@ export const sessionsRouter = os.router({
|
|
|
625
688
|
throw fileError(error);
|
|
626
689
|
}
|
|
627
690
|
})),
|
|
628
|
-
create: os.files.create.handler(({ input, context: { ctx } }) => run(() => {
|
|
691
|
+
create: os.files.create.handler(({ input, context: { ctx } }) => run(async () => {
|
|
629
692
|
requireFields(input, 'session_id', 'path');
|
|
630
|
-
const s = fileOpsSession(ctx, input.session_id);
|
|
693
|
+
const s = (await fileOpsSession(ctx, input.session_id));
|
|
631
694
|
try {
|
|
632
695
|
const root = s.workspace;
|
|
633
696
|
assertWorkspaceFree(ctx, root);
|
|
@@ -650,9 +713,9 @@ export const sessionsRouter = os.router({
|
|
|
650
713
|
throw fileError(error);
|
|
651
714
|
}
|
|
652
715
|
})),
|
|
653
|
-
createDir: os.files.createDir.handler(({ input, context: { ctx } }) => run(() => {
|
|
716
|
+
createDir: os.files.createDir.handler(({ input, context: { ctx } }) => run(async () => {
|
|
654
717
|
requireFields(input, 'session_id', 'path');
|
|
655
|
-
const s = fileOpsSession(ctx, input.session_id);
|
|
718
|
+
const s = (await fileOpsSession(ctx, input.session_id));
|
|
656
719
|
try {
|
|
657
720
|
const root = s.workspace;
|
|
658
721
|
assertWorkspaceFree(ctx, root);
|
|
@@ -666,9 +729,9 @@ export const sessionsRouter = os.router({
|
|
|
666
729
|
throw fileError(error);
|
|
667
730
|
}
|
|
668
731
|
})),
|
|
669
|
-
delete: os.files.delete.handler(({ input, context: { ctx } }) => run(() => {
|
|
732
|
+
delete: os.files.delete.handler(({ input, context: { ctx } }) => run(async () => {
|
|
670
733
|
requireFields(input, 'session_id', 'path');
|
|
671
|
-
const s = fileOpsSession(ctx, input.session_id);
|
|
734
|
+
const s = (await fileOpsSession(ctx, input.session_id));
|
|
672
735
|
try {
|
|
673
736
|
const root = s.workspace;
|
|
674
737
|
assertWorkspaceFree(ctx, root);
|
|
@@ -690,9 +753,9 @@ export const sessionsRouter = os.router({
|
|
|
690
753
|
throw fileError(error);
|
|
691
754
|
}
|
|
692
755
|
})),
|
|
693
|
-
rename: os.files.rename.handler(({ input, context: { ctx } }) => run(() => {
|
|
756
|
+
rename: os.files.rename.handler(({ input, context: { ctx } }) => run(async () => {
|
|
694
757
|
requireFields(input, 'session_id', 'path', 'new_name');
|
|
695
|
-
const s = fileOpsSession(ctx, input.session_id);
|
|
758
|
+
const s = (await fileOpsSession(ctx, input.session_id));
|
|
696
759
|
try {
|
|
697
760
|
const root = s.workspace;
|
|
698
761
|
assertWorkspaceFree(ctx, root);
|
|
@@ -717,10 +780,10 @@ export const sessionsRouter = os.router({
|
|
|
717
780
|
throw fileError(error);
|
|
718
781
|
}
|
|
719
782
|
})),
|
|
720
|
-
move: os.files.move.handler(({ input, context: { ctx } }) => run(() => {
|
|
783
|
+
move: os.files.move.handler(({ input, context: { ctx } }) => run(async () => {
|
|
721
784
|
requireFields({ ...input, dest_dir: input.dest_dir ?? input.destination }, 'session_id', 'path', 'dest_dir');
|
|
722
785
|
const destDirRaw = (input.dest_dir ?? input.destination ?? '.').trim() || '.';
|
|
723
|
-
const s = fileOpsSession(ctx, input.session_id);
|
|
786
|
+
const s = (await fileOpsSession(ctx, input.session_id));
|
|
724
787
|
try {
|
|
725
788
|
const root = s.workspace;
|
|
726
789
|
assertWorkspaceFree(ctx, root);
|
|
@@ -753,7 +816,7 @@ export const sessionsRouter = os.router({
|
|
|
753
816
|
})),
|
|
754
817
|
reveal: os.files.reveal.handler(({ input, context: { ctx } }) => run(async () => {
|
|
755
818
|
requireFields(input, 'session_id', 'path');
|
|
756
|
-
const s = fileOpsSession(ctx, input.session_id);
|
|
819
|
+
const s = (await fileOpsSession(ctx, input.session_id));
|
|
757
820
|
try {
|
|
758
821
|
const target = safeResolve(s.workspace, input.path);
|
|
759
822
|
if (!existsSync(target))
|
|
@@ -772,9 +835,19 @@ export const sessionsRouter = os.router({
|
|
|
772
835
|
throw fileError(error);
|
|
773
836
|
}
|
|
774
837
|
})),
|
|
838
|
+
path: os.files.path.handler(({ input, context: { ctx } }) => run(async () => {
|
|
839
|
+
requireFields(input, 'session_id', 'path');
|
|
840
|
+
const s = (await fileOpsSession(ctx, input.session_id));
|
|
841
|
+
try {
|
|
842
|
+
return { ok: true, path: safeResolve(s.workspace, input.path) };
|
|
843
|
+
}
|
|
844
|
+
catch (error) {
|
|
845
|
+
throw fileError(error);
|
|
846
|
+
}
|
|
847
|
+
})),
|
|
775
848
|
openVsCode: os.files.openVsCode.handler(({ input, context: { ctx } }) => run(async () => {
|
|
776
849
|
requireFields(input, 'session_id', 'path');
|
|
777
|
-
const s = fileOpsSession(ctx, input.session_id);
|
|
850
|
+
const s = (await fileOpsSession(ctx, input.session_id));
|
|
778
851
|
try {
|
|
779
852
|
const target = safeResolve(s.workspace, input.path);
|
|
780
853
|
if (!existsSync(target))
|
|
@@ -790,8 +863,65 @@ export const sessionsRouter = os.router({
|
|
|
790
863
|
throw fileError(error);
|
|
791
864
|
}
|
|
792
865
|
})),
|
|
866
|
+
escapeAuthorize: os.files.escapeAuthorize.handler(({ input, context: { ctx } }) => run(async () => {
|
|
867
|
+
// A Referer alone is not a browser fetch: Python required `Origin`, which the global CSRF check has already matched.
|
|
868
|
+
if (!ctx.header('origin'))
|
|
869
|
+
throw new HttpError(403, 'browser origin required');
|
|
870
|
+
if (input.token?.trim())
|
|
871
|
+
throw new HttpError(400, 'token must not be provided');
|
|
872
|
+
const sid = (input.session_id ?? '').trim();
|
|
873
|
+
const rel = (input.path ?? '').trim();
|
|
874
|
+
if (!sid)
|
|
875
|
+
throw new HttpError(400, 'session_id is required');
|
|
876
|
+
if (!rel)
|
|
877
|
+
throw new HttpError(400, 'path is required');
|
|
878
|
+
const s = (await fileOpsSession(ctx, sid));
|
|
879
|
+
try {
|
|
880
|
+
return ctx.deps.escapeGrants.authorize(s.workspace, sid, s.profile, rel);
|
|
881
|
+
}
|
|
882
|
+
catch (error) {
|
|
883
|
+
throw fileError(error, 404);
|
|
884
|
+
}
|
|
885
|
+
})),
|
|
886
|
+
escapeList: os.files.escapeList.handler(({ input, context: { ctx } }) => run(async () => {
|
|
887
|
+
const req = (await escapeRequest(ctx, input.session_id, input.token, input.path ?? '.'));
|
|
888
|
+
try {
|
|
889
|
+
const listing = ctx.deps.escapeGrants.list(req);
|
|
890
|
+
return { ...listing, entries: serializeEntriesForBrowser(listing.entries) };
|
|
891
|
+
}
|
|
892
|
+
catch (error) {
|
|
893
|
+
throw fileError(error, 404);
|
|
894
|
+
}
|
|
895
|
+
})),
|
|
896
|
+
escapeRead: os.files.escapeRead.handler(({ input, context: { ctx } }) => run(async () => {
|
|
897
|
+
const req = (await escapeRequest(ctx, input.session_id, input.token, input.path ?? ''));
|
|
898
|
+
try {
|
|
899
|
+
const file = ctx.deps.escapeGrants.read(req);
|
|
900
|
+
// The frame loads the bytes through the same grant; the workspace preview grant would outlive and skip its re-checks.
|
|
901
|
+
return file.preview === 'html' ? { ...file, preview_url: `api/escape/file/raw?${new URLSearchParams({ session_id: String(input.session_id), token: String(input.token), path: req.requestPath, inline: '1' }).toString()}` } : file;
|
|
902
|
+
}
|
|
903
|
+
catch (error) {
|
|
904
|
+
throw fileError(error, 404);
|
|
905
|
+
}
|
|
906
|
+
})),
|
|
793
907
|
},
|
|
794
908
|
});
|
|
909
|
+
/** The escape routes' shared front half: required ids, the session, and the grant re-check (403 when it fails). */
|
|
910
|
+
export async function escapeRequest(ctx, sid, token, rel) {
|
|
911
|
+
if (!sid)
|
|
912
|
+
throw new HttpError(400, 'session_id is required');
|
|
913
|
+
if (!token)
|
|
914
|
+
throw new HttpError(400, 'token is required');
|
|
915
|
+
const s = (await fileOpsSession(ctx, sid));
|
|
916
|
+
try {
|
|
917
|
+
return ctx.deps.escapeGrants.resolve(s.workspace, sid, s.profile, token, rel);
|
|
918
|
+
}
|
|
919
|
+
catch (error) {
|
|
920
|
+
if (error instanceof EscapeGrantExpired)
|
|
921
|
+
throw new HttpError(403, error.message);
|
|
922
|
+
throw fileError(error, 404);
|
|
923
|
+
}
|
|
924
|
+
}
|
|
795
925
|
function isSymlinkAt(path) {
|
|
796
926
|
try {
|
|
797
927
|
return lstatSync(path).isSymbolicLink();
|
|
@@ -805,7 +935,7 @@ function assertWorkspaceFree(ctx, path) {
|
|
|
805
935
|
if (ctx.deps.git.workspaceBusy(path))
|
|
806
936
|
throw new HttpError(409, WORKSPACE_BUSY_MESSAGE);
|
|
807
937
|
}
|
|
808
|
-
function fileError(error, notFoundStatus = 400) {
|
|
938
|
+
export function fileError(error, notFoundStatus = 400) {
|
|
809
939
|
if (error instanceof HttpError)
|
|
810
940
|
return error;
|
|
811
941
|
if (error instanceof HttpFailure)
|
|
@@ -821,10 +951,10 @@ function fileError(error, notFoundStatus = 400) {
|
|
|
821
951
|
* `state.db` but that has no `sessions/<sid>.json` (CLI, messaging) is served as an external view bound to the active
|
|
822
952
|
* workspace, as the sidebar already lists it (issue #3280).
|
|
823
953
|
*/
|
|
824
|
-
export function fileOpsSession(ctx, sid, opts = {}) {
|
|
954
|
+
export async function fileOpsSession(ctx, sid, opts = {}) {
|
|
825
955
|
let session;
|
|
826
956
|
try {
|
|
827
|
-
session = ctx.deps.sessionStore.get(sid, { metadataOnly: true });
|
|
957
|
+
session = (await ctx.deps.sessionStore.get(sid, { metadataOnly: true }));
|
|
828
958
|
}
|
|
829
959
|
catch {
|
|
830
960
|
const profile = ctx.deps.activeProfile();
|
|
@@ -832,7 +962,7 @@ export function fileOpsSession(ctx, sid, opts = {}) {
|
|
|
832
962
|
throw new HttpError(404, 'Session not found');
|
|
833
963
|
if (!ctx.deps.workspaces.profileSupportsLocalIo(profile))
|
|
834
964
|
throw new HttpError(400, REMOTE_WORKSPACE_UNSUPPORTED_CODE, { message: REMOTE_WORKSPACE_UNSUPPORTED_MESSAGE });
|
|
835
|
-
return { workspace: ctx.deps.workspaces.lastWorkspace(profile), profile, recovered: false, session: null };
|
|
965
|
+
return { workspace: (await ctx.deps.workspaces.lastWorkspace(profile)), profile, recovered: false, session: null };
|
|
836
966
|
}
|
|
837
967
|
if (!ctx.deps.profilesMatch(session.profile, ctx.deps.activeProfile()))
|
|
838
968
|
throw new HttpError(404, 'Session not found');
|
|
@@ -842,7 +972,7 @@ export function fileOpsSession(ctx, sid, opts = {}) {
|
|
|
842
972
|
let recovered = false;
|
|
843
973
|
try {
|
|
844
974
|
;
|
|
845
|
-
[workspace, recovered] = ctx.deps.workspaces.resolveImplicitWithRecovery(session.workspace, (p) => ctx.deps.workspaces.lastWorkspace(p), session.profile);
|
|
975
|
+
[workspace, recovered] = (await ctx.deps.workspaces.resolveImplicitWithRecovery(session.workspace, async (p) => (await ctx.deps.workspaces.lastWorkspace(p)), session.profile));
|
|
846
976
|
}
|
|
847
977
|
catch (error) {
|
|
848
978
|
if (opts.strictWorkspace)
|
|
@@ -855,10 +985,10 @@ export function fileOpsSession(ctx, sid, opts = {}) {
|
|
|
855
985
|
if (cached)
|
|
856
986
|
cached.workspace = workspace;
|
|
857
987
|
try {
|
|
858
|
-
const full = ctx.deps.sessionStore.load(sid);
|
|
988
|
+
const full = (await ctx.deps.sessionStore.load(sid));
|
|
859
989
|
if (full) {
|
|
860
990
|
full.workspace = workspace;
|
|
861
|
-
ctx.deps.sessionStore.save(full, { touchUpdatedAt: false });
|
|
991
|
+
(await ctx.deps.sessionStore.save(full, { touchUpdatedAt: false }));
|
|
862
992
|
}
|
|
863
993
|
}
|
|
864
994
|
catch { /* recovery persistence is best effort */ }
|