@maudecode/talaria-web 1.18.0 → 1.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/_release.json +8 -8
- package/dist/api/auth-raw.js +16 -16
- package/dist/api/auth-raw.js.map +1 -1
- package/dist/api/automation-raw.d.ts +2 -2
- package/dist/api/automation-raw.js +93 -38
- package/dist/api/automation-raw.js.map +1 -1
- package/dist/api/automation-router.d.ts +99 -17
- package/dist/api/automation-router.js +22 -14
- package/dist/api/automation-router.js.map +1 -1
- package/dist/api/chat-router.d.ts +1433 -37
- package/dist/api/chat-router.js +205 -90
- package/dist/api/chat-router.js.map +1 -1
- package/dist/api/git-router.d.ts +6 -2
- package/dist/api/git-router.js +30 -30
- package/dist/api/git-router.js.map +1 -1
- package/dist/api/raw-routes.d.ts +3 -3
- package/dist/api/raw-routes.js +76 -62
- package/dist/api/raw-routes.js.map +1 -1
- package/dist/api/router.d.ts +5 -5
- package/dist/api/router.js +22 -22
- package/dist/api/router.js.map +1 -1
- package/dist/api/session-visibility.d.ts +4 -4
- package/dist/api/session-visibility.js +26 -16
- package/dist/api/session-visibility.js.map +1 -1
- package/dist/api/sessions-router.d.ts +2635 -151
- package/dist/api/sessions-router.js +193 -177
- package/dist/api/sessions-router.js.map +1 -1
- package/dist/api/settings-router.d.ts +450 -11
- package/dist/api/settings-router.js +102 -49
- package/dist/api/settings-router.js.map +1 -1
- package/dist/api/sse-routes.d.ts +2 -2
- package/dist/api/sse-routes.js +102 -80
- package/dist/api/sse-routes.js.map +1 -1
- package/dist/api/tools-raw.d.ts +5 -0
- package/dist/api/tools-raw.js +58 -33
- package/dist/api/tools-raw.js.map +1 -1
- package/dist/api/tools-router.d.ts +963 -109
- package/dist/api/tools-router.js +426 -72
- 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 +80 -57
- package/dist/app.js.map +1 -1
- package/dist/auth/crypto.d.ts +3 -0
- package/dist/auth/crypto.js +18 -0
- package/dist/auth/crypto.js.map +1 -1
- package/dist/auth/gate.js +14 -9
- package/dist/auth/gate.js.map +1 -1
- package/dist/auth/passkeys.d.ts +15 -14
- package/dist/auth/passkeys.js +89 -91
- package/dist/auth/passkeys.js.map +1 -1
- package/dist/auth/store.d.ts +17 -7
- package/dist/auth/store.js +93 -52
- package/dist/auth/store.js.map +1 -1
- package/dist/bin/talaria-web.js +12 -81
- package/dist/bin/talaria-web.js.map +1 -1
- package/dist/cli/ctl.js +8 -2
- package/dist/cli/ctl.js.map +1 -1
- package/dist/cli/dotenv.d.ts +5 -0
- package/dist/cli/dotenv.js +14 -2
- package/dist/cli/dotenv.js.map +1 -1
- package/dist/cli/launcher.js +5 -5
- package/dist/cli/launcher.js.map +1 -1
- package/dist/cli/main.d.ts +1 -0
- package/dist/cli/main.js +90 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/supervise.d.ts +24 -0
- package/dist/cli/supervise.js +147 -6
- package/dist/cli/supervise.js.map +1 -1
- package/dist/config/agent-config.d.ts +37 -11
- package/dist/config/agent-config.js +146 -64
- package/dist/config/agent-config.js.map +1 -1
- package/dist/config.d.ts +2 -0
- package/dist/config.js +14 -5
- package/dist/config.js.map +1 -1
- package/dist/fs/atomic.d.ts +4 -0
- package/dist/fs/atomic.js +19 -2
- package/dist/fs/atomic.js.map +1 -1
- package/dist/fs/stat.d.ts +7 -0
- package/dist/fs/stat.js +27 -0
- package/dist/fs/stat.js.map +1 -0
- package/dist/http/context.d.ts +28 -9
- package/dist/http/context.js +77 -25
- package/dist/http/context.js.map +1 -1
- package/dist/onboarding.d.ts +2 -2
- package/dist/onboarding.js +10 -8
- package/dist/onboarding.js.map +1 -1
- package/dist/profiles/profiles.d.ts +12 -4
- package/dist/profiles/profiles.js +78 -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 +85 -14
- package/dist/providers/catalog.js +502 -146
- package/dist/providers/catalog.js.map +1 -1
- package/dist/providers/env-file.d.ts +10 -3
- package/dist/providers/env-file.js +24 -75
- package/dist/providers/env-file.js.map +1 -1
- package/dist/providers/runtime-env.d.ts +4 -2
- package/dist/providers/runtime-env.js +9 -6
- package/dist/providers/runtime-env.js.map +1 -1
- package/dist/providers/tables.d.ts +3 -1
- package/dist/providers/tables.js +4 -2
- package/dist/providers/tables.js.map +1 -1
- package/dist/redact.js +56 -23
- package/dist/redact.js.map +1 -1
- package/dist/release.d.ts +7 -0
- package/dist/release.js +19 -3
- package/dist/release.js.map +1 -1
- package/dist/runtime.d.ts +5 -1
- package/dist/runtime.js +303 -96
- package/dist/runtime.js.map +1 -1
- package/dist/server.js +31 -18
- package/dist/server.js.map +1 -1
- package/dist/sessions/anchor.d.ts +11 -4
- package/dist/sessions/anchor.js +33 -37
- 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 +49 -23
- package/dist/sessions/background-tasks.js +161 -89
- 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 +23 -6
- package/dist/sessions/cli-sessions.js +84 -84
- package/dist/sessions/cli-sessions.js.map +1 -1
- package/dist/sessions/completions.d.ts +38 -2
- package/dist/sessions/completions.js +348 -77
- 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 +2 -0
- package/dist/sessions/export.js +6 -2
- package/dist/sessions/export.js.map +1 -1
- package/dist/sessions/gateway-sessions.d.ts +86 -0
- package/dist/sessions/gateway-sessions.js +914 -0
- package/dist/sessions/gateway-sessions.js.map +1 -0
- package/dist/sessions/gateway-watcher.d.ts +10 -11
- package/dist/sessions/gateway-watcher.js +25 -21
- package/dist/sessions/gateway-watcher.js.map +1 -1
- package/dist/sessions/goals.d.ts +31 -0
- package/dist/sessions/goals.js +75 -0
- package/dist/sessions/goals.js.map +1 -0
- package/dist/sessions/journal.d.ts +5 -79
- package/dist/sessions/journal.js +15 -606
- package/dist/sessions/journal.js.map +1 -1
- package/dist/sessions/list.d.ts +34 -18
- package/dist/sessions/list.js +161 -147
- package/dist/sessions/list.js.map +1 -1
- package/dist/sessions/merge.d.ts +77 -13
- package/dist/sessions/merge.js +315 -65
- 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 +85 -0
- package/dist/sessions/prefix-index.js +243 -0
- package/dist/sessions/prefix-index.js.map +1 -0
- package/dist/sessions/recovery.d.ts +4 -7
- package/dist/sessions/recovery.js +100 -283
- package/dist/sessions/recovery.js.map +1 -1
- package/dist/sessions/relay.d.ts +20 -20
- package/dist/sessions/relay.js +205 -127
- package/dist/sessions/relay.js.map +1 -1
- package/dist/sessions/service.d.ts +251 -78
- package/dist/sessions/service.js +1510 -564
- package/dist/sessions/service.js.map +1 -1
- package/dist/sessions/session.d.ts +20 -2
- package/dist/sessions/session.js +33 -5
- package/dist/sessions/session.js.map +1 -1
- package/dist/sessions/shares.d.ts +7 -6
- package/dist/sessions/shares.js +22 -45
- package/dist/sessions/shares.js.map +1 -1
- package/dist/sessions/source-kind.js +1 -0
- package/dist/sessions/source-kind.js.map +1 -1
- package/dist/sessions/state-db-identity.d.ts +18 -0
- package/dist/sessions/state-db-identity.js +67 -0
- package/dist/sessions/state-db-identity.js.map +1 -0
- package/dist/sessions/state-db-worker.js +24 -5
- package/dist/sessions/state-db-worker.js.map +1 -1
- package/dist/sessions/state-db.d.ts +157 -21
- package/dist/sessions/state-db.js +1145 -204
- package/dist/sessions/state-db.js.map +1 -1
- package/dist/sessions/state-saved.d.ts +1 -1
- package/dist/sessions/state-saved.js +35 -11
- package/dist/sessions/state-saved.js.map +1 -1
- package/dist/sessions/storage/backend.d.ts +171 -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 +25 -0
- package/dist/sessions/storage/json-documents.js +277 -0
- package/dist/sessions/storage/json-documents.js.map +1 -0
- package/dist/sessions/storage/json-files.d.ts +23 -0
- package/dist/sessions/storage/json-files.js +244 -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 +113 -0
- package/dist/sessions/storage/json-journal.js +756 -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 +82 -0
- package/dist/sessions/storage/json.js +350 -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 +67 -73
- package/dist/sessions/store.js +341 -607
- package/dist/sessions/store.js.map +1 -1
- package/dist/sessions/streams.d.ts +12 -7
- package/dist/sessions/streams.js +58 -15
- package/dist/sessions/streams.js.map +1 -1
- package/dist/sessions/titles.js +1 -1
- package/dist/sessions/titles.js.map +1 -1
- package/dist/sessions/todo.d.ts +5 -0
- package/dist/sessions/todo.js +28 -21
- package/dist/sessions/todo.js.map +1 -1
- package/dist/sessions/tool-display.d.ts +8 -5
- package/dist/sessions/tool-display.js +28 -16
- package/dist/sessions/tool-display.js.map +1 -1
- package/dist/sessions/turn-context.d.ts +10 -1
- package/dist/sessions/turn-context.js +13 -6
- package/dist/sessions/turn-context.js.map +1 -1
- package/dist/sessions/turn.d.ts +110 -22
- package/dist/sessions/turn.js +918 -380
- package/dist/sessions/turn.js.map +1 -1
- package/dist/sessions/wakeup-pause.d.ts +8 -13
- package/dist/sessions/wakeup-pause.js +31 -49
- package/dist/sessions/wakeup-pause.js.map +1 -1
- package/dist/sessions/window.js +13 -12
- package/dist/sessions/window.js.map +1 -1
- package/dist/settings.d.ts +19 -7
- package/dist/settings.js +179 -183
- package/dist/settings.js.map +1 -1
- package/dist/sidecar/client.d.ts +41 -4
- package/dist/sidecar/client.js +192 -42
- 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 +6 -2
- package/dist/sidecar/fake.js +34 -4
- package/dist/sidecar/fake.js.map +1 -1
- package/dist/spa.d.ts +9 -4
- package/dist/spa.js +36 -12
- package/dist/spa.js.map +1 -1
- package/dist/startup-timing.d.ts +66 -0
- package/dist/startup-timing.js +129 -0
- package/dist/startup-timing.js.map +1 -0
- package/dist/test/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/fs-handles.d.ts +11 -0
- package/dist/test/fs-handles.js +31 -0
- package/dist/test/fs-handles.js.map +1 -0
- package/dist/test/harness.d.ts +1 -0
- package/dist/test/harness.js +1 -1
- package/dist/test/harness.js.map +1 -1
- package/dist/test/passkeys.d.ts +22 -0
- package/dist/test/passkeys.js +62 -0
- package/dist/test/passkeys.js.map +1 -0
- package/dist/test/storage.d.ts +15 -0
- package/dist/test/storage.js +26 -0
- package/dist/test/storage.js.map +1 -0
- package/dist/tools/commands.d.ts +6 -1
- package/dist/tools/commands.js +8 -2
- package/dist/tools/commands.js.map +1 -1
- package/dist/tools/connectors.d.ts +33 -0
- package/dist/tools/connectors.js +121 -0
- package/dist/tools/connectors.js.map +1 -0
- package/dist/tools/crons.d.ts +46 -5
- package/dist/tools/crons.js +100 -26
- package/dist/tools/crons.js.map +1 -1
- package/dist/tools/dashboard-plugins.d.ts +34 -5
- package/dist/tools/dashboard-plugins.js +146 -14
- package/dist/tools/dashboard-plugins.js.map +1 -1
- package/dist/tools/extensions.d.ts +5 -4
- package/dist/tools/extensions.js +213 -207
- package/dist/tools/extensions.js.map +1 -1
- package/dist/tools/gateway-restart.d.ts +82 -0
- package/dist/tools/gateway-restart.js +222 -0
- package/dist/tools/gateway-restart.js.map +1 -0
- package/dist/tools/health.d.ts +28 -4
- package/dist/tools/health.js +171 -50
- 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/insights.d.ts +1 -1
- package/dist/tools/insights.js +2 -2
- package/dist/tools/insights.js.map +1 -1
- package/dist/tools/kanban.d.ts +4 -2
- package/dist/tools/kanban.js +28 -19
- package/dist/tools/kanban.js.map +1 -1
- package/dist/tools/mcp-health.js +74 -24
- package/dist/tools/mcp-health.js.map +1 -1
- package/dist/tools/mcp.js +19 -1
- 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-oauth.d.ts +14 -0
- package/dist/tools/plugin-oauth.js +53 -0
- package/dist/tools/plugin-oauth.js.map +1 -0
- package/dist/tools/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/prune-advice.d.ts +50 -0
- package/dist/tools/prune-advice.js +114 -0
- package/dist/tools/prune-advice.js.map +1 -0
- package/dist/tools/skills.d.ts +13 -5
- package/dist/tools/skills.js +53 -19
- package/dist/tools/skills.js.map +1 -1
- package/dist/tools/update-notifications.d.ts +102 -17
- package/dist/tools/update-notifications.js +400 -82
- 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 +100 -33
- package/dist/tools/updates.js +1085 -345
- package/dist/tools/updates.js.map +1 -1
- package/dist/util.d.ts +2 -0
- package/dist/util.js +5 -0
- package/dist/util.js.map +1 -1
- package/dist/workspace/git.d.ts +16 -1
- package/dist/workspace/git.js +291 -11
- package/dist/workspace/git.js.map +1 -1
- package/dist/workspace/media.d.ts +12 -9
- package/dist/workspace/media.js +98 -38
- package/dist/workspace/media.js.map +1 -1
- package/dist/workspace/preview.js +4 -14
- package/dist/workspace/preview.js.map +1 -1
- package/dist/workspace/rollback.d.ts +8 -4
- package/dist/workspace/rollback.js +22 -12
- package/dist/workspace/rollback.js.map +1 -1
- package/dist/workspace/workspaces.d.ts +15 -19
- package/dist/workspace/workspaces.js +55 -127
- package/dist/workspace/workspaces.js.map +1 -1
- package/dist/workspace/worktrees.js +170 -32
- package/dist/workspace/worktrees.js.map +1 -1
- package/package.json +6 -4
- package/sidecar/agent_dependency.json +4 -4
- package/sidecar/agent_support.json +29 -0
- package/sidecar/scripts/record-fixtures.py +12 -3
- package/sidecar/scripts/replay_sidecar.py +8 -0
- package/sidecar/scripts/suite_runner.py +458 -0
- package/sidecar/scripts/test.sh +11 -5
- package/sidecar/talaria_sidecar/__init__.py +6 -1
- package/sidecar/talaria_sidecar/__main__.py +13 -4
- package/sidecar/talaria_sidecar/agent_mutation.py +1111 -0
- package/sidecar/talaria_sidecar/agent_services.py +1116 -0
- package/sidecar/talaria_sidecar/context_detail.py +59 -0
- package/sidecar/talaria_sidecar/dependency_sync.py +85 -0
- package/sidecar/talaria_sidecar/home.py +133 -14
- package/sidecar/talaria_sidecar/methods/__init__.py +2 -2
- package/sidecar/talaria_sidecar/methods/aux.py +211 -41
- package/sidecar/talaria_sidecar/methods/chat.py +1378 -200
- package/sidecar/talaria_sidecar/methods/checkpoints.py +29 -4
- package/sidecar/talaria_sidecar/methods/commands.py +483 -13
- package/sidecar/talaria_sidecar/methods/config.py +195 -6
- package/sidecar/talaria_sidecar/methods/connectors.py +375 -0
- package/sidecar/talaria_sidecar/methods/cron.py +374 -36
- package/sidecar/talaria_sidecar/methods/cron_execution.py +284 -0
- package/sidecar/talaria_sidecar/methods/dashboard_plugins.py +301 -0
- package/sidecar/talaria_sidecar/methods/gateway.py +215 -55
- package/sidecar/talaria_sidecar/methods/gateway_sessions.py +418 -0
- package/sidecar/talaria_sidecar/methods/goals.py +81 -41
- package/sidecar/talaria_sidecar/methods/kanban.py +82 -30
- package/sidecar/talaria_sidecar/methods/memory.py +84 -0
- package/sidecar/talaria_sidecar/methods/oauth.py +144 -13
- package/sidecar/talaria_sidecar/methods/plugin_catalog.py +198 -0
- package/sidecar/talaria_sidecar/methods/plugin_oauth.py +234 -0
- package/sidecar/talaria_sidecar/methods/process.py +229 -16
- package/sidecar/talaria_sidecar/methods/profiles.py +48 -9
- package/sidecar/talaria_sidecar/methods/providers.py +196 -26
- package/sidecar/talaria_sidecar/methods/runtime.py +71 -1
- package/sidecar/talaria_sidecar/methods/skills.py +83 -5
- package/sidecar/talaria_sidecar/methods/state_db.py +405 -112
- 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 +51 -0
- package/sidecar/talaria_sidecar/methods/usage.py +113 -14
- package/sidecar/talaria_sidecar/methods/worktree.py +145 -19
- package/sidecar/talaria_sidecar/methods/write_approval.py +181 -0
- package/sidecar/talaria_sidecar/rpc.py +70 -7
- package/sidecar/talaria_sidecar/runtime.py +122 -14
- package/sidecar/talaria_sidecar/speed.py +47 -0
- package/sidecar/talaria_sidecar/startup_timing.py +119 -0
- package/static/dist/FILES.txt +242 -215
- package/static/dist/THIRD_PARTY_LICENSES.md +6 -22
- package/static/dist/assets/AppShell-3isgvoro.js +8 -0
- package/static/dist/assets/Button-f4n6dapf.js +1 -0
- package/static/dist/assets/ChatPage-k7b6xfax.js +4 -0
- package/static/dist/assets/ConnectTargets-juqvt5lm.js +1 -0
- package/static/dist/assets/Dialog-hta5utr3.js +1 -0
- package/static/dist/assets/ExtensionRoute-zrhjn0wm.js +1 -0
- package/static/dist/assets/Field-b6ez48oz.js +1 -0
- package/static/dist/assets/HubRoute-iwvso2tz.js +2 -0
- package/static/dist/assets/LinkCheckContext-ix6zqqkk.js +1 -0
- package/static/dist/assets/Markdown-jdeth7zq.js +2 -0
- package/static/dist/assets/MarkdownRenderer-fbswsgld.js +302 -0
- package/static/dist/assets/MarkdownRenderer-i9o6nr38.css +1 -0
- package/static/dist/assets/OAuthSignIn-bpd8hom3.js +1 -0
- package/static/dist/assets/ResourceSwitch-odi6dy2o.js +1 -0
- package/static/dist/assets/RightPanel-eu6enlo6.js +1 -0
- package/static/dist/assets/Select-kr07928w.js +1 -0
- package/static/dist/assets/SessionListPanel-etb2i54l.js +1 -0
- package/static/dist/assets/SettingsLayout-eu3xxp23.js +1 -0
- package/static/dist/assets/States-icab19yg.js +1 -0
- package/static/dist/assets/TerminalPanel-hngmsr8b.js +16 -0
- package/static/dist/assets/Toaster-nb2uzjw1.js +1 -0
- package/static/dist/assets/_app-ga1moszl.js +1 -0
- package/static/dist/assets/_app.ext._extensionId-na62087t.js +1 -0
- package/static/dist/assets/_app.index-jypgdqoi.js +1 -0
- package/static/dist/assets/_app.insights-kabejdtm.js +1 -0
- package/static/dist/assets/_app.kanban-m19kfcmx.js +1 -0
- package/static/dist/assets/_app.logs-iw4m96sz.js +1 -0
- package/static/dist/assets/_app.memory-jq5frwcg.js +1 -0
- package/static/dist/assets/_app.profiles-kwa3m7rp.js +1 -0
- package/static/dist/assets/_app.session._sessionId-o5lyeipj.js +1 -0
- package/static/dist/assets/_app.settings-ckl8hdll.js +1 -0
- package/static/dist/assets/_app.settings._section-dtdjk98a.js +3 -0
- package/static/dist/assets/_app.skills-n016rihd.js +1 -0
- package/static/dist/assets/_app.tasks-n8zuqsqe.js +1 -0
- package/static/dist/assets/_app.todos-btew5v2s.js +1 -0
- package/static/dist/assets/_app.workspaces-lnfk95ch.js +1 -0
- package/static/dist/assets/abnfDiagram-VCTEODGH-dttheegb.js +1 -0
- package/static/dist/assets/{angular-html-nu6l31w3.js → angular-html-l28bd5fo.js} +1 -1
- package/static/dist/assets/{angular-ts-fbx4f8mm.js → angular-ts-ffzx1vj0.js} +1 -1
- package/static/dist/assets/{apl-bx2xr7dh.js → apl-b7h7mmy4.js} +1 -1
- package/static/dist/assets/{arc-7popfhbk.js → arc-fk1b21lm.js} +1 -1
- package/static/dist/assets/architecture-7GRP2DOG-ic435919.js +1 -0
- package/static/dist/assets/architectureDiagram-5GKGNRK7-8r3glgiq.js +36 -0
- package/static/dist/assets/archive-il7c6053.js +1 -0
- package/static/dist/assets/{astro-g77i97cb.js → astro-k117fy0t.js} +1 -1
- package/static/dist/assets/back-gu3nu279.js +1 -0
- package/static/dist/assets/{blade-boo0u92y.js → blade-npefsmn8.js} +1 -1
- package/static/dist/assets/{blockDiagram-I7D4REHJ-jzthp1wa.js → blockDiagram-I7D4REHJ-jenyos6c.js} +4 -4
- package/static/dist/assets/{c-cat0w3sc.js → c-2umg6kbn.js} +1 -1
- package/static/dist/assets/{c4Diagram-7LVT6UL2-mwr67mt8.js → c4Diagram-7LVT6UL2-nzlx7yc4.js} +1 -1
- package/static/dist/assets/cancel-bsnfo36u.js +1 -0
- package/static/dist/assets/channel-dsbtk01y.js +1 -0
- package/static/dist/assets/{chunk-4HAMMTFA-gpq1y228.js → chunk-4HAMMTFA-g0cru63b.js} +20 -20
- package/static/dist/assets/{chunk-75Z2AOVW-ktje58c4.js → chunk-75Z2AOVW-7rkswkjw.js} +1 -1
- package/static/dist/assets/chunk-DU6HZSFF-fn73jzdo.js +128 -0
- package/static/dist/assets/{chunk-F27PBJKO-cmev85ti.js → chunk-F27PBJKO-oey8e72m.js} +1 -1
- package/static/dist/assets/{chunk-FOHPRMQF-opuflp73.js → chunk-FOHPRMQF-ipewusgj.js} +8 -8
- package/static/dist/assets/{chunk-GMAD6QVW-htjgt22y.js → chunk-GMAD6QVW-l2a32wiy.js} +6 -6
- package/static/dist/assets/{chunk-GVQU2GXP-qndvoxl7.js → chunk-GVQU2GXP-o9dwzh8h.js} +1 -1
- package/static/dist/assets/{chunk-IMKFNOWR-e5bkd5q6.js → chunk-IMKFNOWR-eblwj20b.js} +5 -5
- package/static/dist/assets/{chunk-L3NEJ4N5-mj1155r6.js → chunk-L3NEJ4N5-o2mufspb.js} +1 -1
- package/static/dist/assets/chunk-OSK3NFVY-ijp9pw29.js +10 -0
- package/static/dist/assets/{chunk-P2QGCYS3-f7t54xfm.js → chunk-P2QGCYS3-hs9hqwl4.js} +1 -1
- package/static/dist/assets/{chunk-POPQ4Y6H-i927v9oa.js → chunk-POPQ4Y6H-bp9rsqez.js} +1 -1
- package/static/dist/assets/{chunk-PWAF6VOD-m84lmnyt.js → chunk-PWAF6VOD-brkprov6.js} +1 -1
- package/static/dist/assets/{chunk-SHT3W25Y-mi0tlcu9.js → chunk-SHT3W25Y-gmpv0pxz.js} +13 -13
- package/static/dist/assets/{chunk-SVP7TREG-dnau702j.js → chunk-SVP7TREG-oldm08fu.js} +4 -4
- package/static/dist/assets/{chunk-TICWLB2K-edem1gkg.js → chunk-TICWLB2K-ooqilfv7.js} +6 -6
- package/static/dist/assets/{chunk-XXDRQBXY-n40pf9vy.js → chunk-XXDRQBXY-jkmnqu65.js} +1 -1
- package/static/dist/assets/classDiagram-ZZMXUADV-fvgcv24g.js +1 -0
- package/static/dist/assets/classDiagram-v2-VYDZK3BY-fvgcv24g.js +1 -0
- package/static/dist/assets/{cobol-go622aep.js → cobol-ssf9hkh7.js} +1 -1
- package/static/dist/assets/{coffee-jwo1xjhq.js → coffee-lsi9fwae.js} +1 -1
- package/static/dist/assets/copied-bz3gkazh.js +1 -0
- package/static/dist/assets/copy-jo006coq.js +1 -0
- package/static/dist/assets/cose-bilkent-JH36ORCC-layy2r27.js +1 -0
- package/static/dist/assets/{cpp-nre7j0kq.js → cpp-lfrh4y55.js} +1 -1
- package/static/dist/assets/{crystal-lviso2je.js → crystal-efh4pte7.js} +1 -1
- package/static/dist/assets/{css-ywz9j4hb.js → css-i82qdo89.js} +1 -1
- package/static/dist/assets/cynefin-OW5HDTMX-d47op7qs.js +1 -0
- package/static/dist/assets/cynefinDiagram-5FMLGOSQ-doa7594y.js +62 -0
- package/static/dist/assets/cytoscape.esm-fjn2algp.js +321 -0
- package/static/dist/assets/dagre-GXQ25YYZ-os768dp4.js +4 -0
- package/static/dist/assets/dagre-o5jmjz46.js +1 -0
- package/static/dist/assets/{diagram-S7CK7UJ4-l8abxaes.js → diagram-S7CK7UJ4-fyi81nxd.js} +4 -4
- package/static/dist/assets/diagram-UQ7AKVKN-j3exggaq.js +41 -0
- package/static/dist/assets/{diagram-VSXAHHWV-fnky6lvc.js → diagram-VSXAHHWV-omo1en2l.js} +1 -1
- package/static/dist/assets/diagram-VX7I27RA-oro2cyu0.js +24 -0
- package/static/dist/assets/diagram-Z3DM3KII-byt9vdb7.js +24 -0
- package/static/dist/assets/dist-crc46di9.js +7 -0
- package/static/dist/assets/dist-etpoyscq.js +44 -0
- package/static/dist/assets/{dist-c4c2m3kv.js → dist-nb670eu6.js} +1 -1
- package/static/dist/assets/ebnfDiagram-PWID7BFC-ee3haugh.js +1 -0
- package/static/dist/assets/{edge-dvv35byi.js → edge-lrob635n.js} +1 -1
- package/static/dist/assets/{elixir-i2f1ki1g.js → elixir-kdpxeq93.js} +1 -1
- package/static/dist/assets/{elm-cpepyjm4.js → elm-c8irj9uh.js} +1 -1
- package/static/dist/assets/erDiagram-RLTQ6QDP-d1e93yff.js +99 -0
- package/static/dist/assets/{erb-idlyfheg.js → erb-flwsv146.js} +1 -1
- package/static/dist/assets/eventmodeling-NTZA5JFV-i1ihb40c.js +1 -0
- package/static/dist/assets/flowDiagram-HODETNUW-jahfpiod.js +1 -0
- package/static/dist/assets/folder-plus-ivoglq98.js +1 -0
- package/static/dist/assets/{ganttDiagram-EL5Y4UJY-ngbsyp37.js → ganttDiagram-EL5Y4UJY-m7g0jud4.js} +1 -1
- package/static/dist/assets/{git-rebase-d9lpfpbn.js → git-rebase-bli19aoq.js} +1 -1
- package/static/dist/assets/gitGraph-4MIJSDKK-hzdj07yy.js +1 -0
- package/static/dist/assets/{gitGraphDiagram-WWUBYQGX-eravdti4.js → gitGraphDiagram-WWUBYQGX-dm9agbna.js} +1 -1
- package/static/dist/assets/{glimmer-js-39i0urfb.js → glimmer-js-d4icg38p.js} +1 -1
- package/static/dist/assets/{glimmer-ts-gdtd6n73.js → glimmer-ts-bk75772u.js} +1 -1
- package/static/dist/assets/{glsl-o1djm5pp.js → glsl-lqormp2b.js} +1 -1
- package/static/dist/assets/{graphql-kj6rz55t.js → graphql-hw6s5qzd.js} +1 -1
- package/static/dist/assets/{hack-pe1qqr2i.js → hack-ozrv6l4d.js} +1 -1
- package/static/dist/assets/{haml-cknnbcqs.js → haml-gytfosdt.js} +1 -1
- package/static/dist/assets/{handlebars-hwq64orh.js → handlebars-b6g7jffd.js} +1 -1
- package/static/dist/assets/highlighted-body-KPVGNVTW-mmgz2czu.js +1 -0
- package/static/dist/assets/host-fr6lni1p.js +1 -0
- package/static/dist/assets/{html-derivative-h2i2pyjc.js → html-derivative-f1tqcroo.js} +1 -1
- package/static/dist/assets/{html-ha05xtvt.js → html-on6oj6yj.js} +1 -1
- package/static/dist/assets/{http-cf94zu27.js → http-odhufsl7.js} +1 -1
- package/static/dist/assets/{hurl-lslax568.js → hurl-mu680336.js} +1 -1
- package/static/dist/assets/index-73649w7o.js +10 -0
- package/static/dist/assets/index-lhf1fsdf.css +2 -0
- package/static/dist/assets/info-A6RAGUB7-lll1dqmm.js +1 -0
- package/static/dist/assets/infoDiagram-27XIBGKW-k7esc639.js +2 -0
- package/static/dist/assets/{ishikawaDiagram-5VMMS53U-i6ypq351.js → ishikawaDiagram-5VMMS53U-lgr6k9wo.js} +6 -6
- package/static/dist/assets/{java-ndjf2o89.js → java-nxbe8uju.js} +1 -1
- package/static/dist/assets/{javascript-coftlwy3.js → javascript-lz3kxcyz.js} +1 -1
- package/static/dist/assets/{jinja-etei9wy7.js → jinja-l5pk84gt.js} +1 -1
- package/static/dist/assets/{jison-hyekgft1.js → jison-jdutdwyy.js} +1 -1
- package/static/dist/assets/{journeyDiagram-3NMN7TZE-lduf1z95.js → journeyDiagram-3NMN7TZE-ndmbxuqk.js} +1 -1
- package/static/dist/assets/{json-lok0yaho.js → json-dnge4ssf.js} +1 -1
- package/static/dist/assets/{jsx-b64w0nbx.js → jsx-c3lwhkep.js} +1 -1
- package/static/dist/assets/{jsx-runtime-eu92a5pu.js → jsx-runtime-o40ukmjl.js} +1 -1
- package/static/dist/assets/{julia-jxxzz2yn.js → julia-hwd4rrcb.js} +1 -1
- package/static/dist/assets/{just-mc29iw9t.js → just-nka3oxdx.js} +1 -1
- package/static/dist/assets/{kanban-definition-UXKFOSKX-e18bu4pg.js → kanban-definition-UXKFOSKX-mjxym0jp.js} +28 -28
- package/static/dist/assets/katex-cbdd1ohw.css +1 -0
- package/static/dist/assets/katex-pbij2oo6.js +257 -0
- package/static/dist/assets/{latex-pafa03ft.js → latex-iqmr7e40.js} +1 -1
- package/static/dist/assets/lazyRouteComponent-cwb6l7xh.js +1 -0
- package/static/dist/assets/{line-meizqsvn.js → line-mtr5k6il.js} +1 -1
- package/static/dist/assets/linear-jlwrvvy6.js +1 -0
- package/static/dist/assets/link-iadw4ghw.js +2 -0
- package/static/dist/assets/{liquid-hz5c2pov.js → liquid-okmk9tbp.js} +1 -1
- package/static/dist/assets/locale-cs-n41hptse.js +5 -0
- package/static/dist/assets/locale-de-k7ht47ew.js +5 -0
- package/static/dist/assets/locale-es-ih078lco.js +5 -0
- package/static/dist/assets/locale-fr-ojabnf41.js +5 -0
- package/static/dist/assets/locale-it-kb96jufy.js +5 -0
- package/static/dist/assets/locale-ja-jpsp3xs1.js +7 -0
- package/static/dist/assets/locale-ko-cpzuy0n7.js +5 -0
- package/static/dist/assets/locale-pl-dbap4leu.js +5 -0
- package/static/dist/assets/locale-pt-nci7w72x.js +5 -0
- package/static/dist/assets/locale-ru-soghe4cs.js +7 -0
- package/static/dist/assets/locale-tr-ks00mu68.js +5 -0
- package/static/dist/assets/locale-vi-ij7twfm6.js +5 -0
- package/static/dist/assets/locale-zh-Hant-feakwr7a.js +5 -0
- package/static/dist/assets/locale-zh-ren0vjyv.js +7 -0
- package/static/dist/assets/login-lkhtzfcl.js +1 -0
- package/static/dist/assets/{lua-leyf8mlb.js → lua-krx4xj5h.js} +1 -1
- package/static/dist/assets/{marko-cn1fzpdv.js → marko-gbvpfehz.js} +1 -1
- package/static/dist/assets/{mdc-huhy88df.js → mdc-c21zlyi5.js} +1 -1
- package/static/dist/assets/mermaid-HWGCJPDP-jx0q5dm2.js +1 -0
- package/static/dist/assets/mermaid-parser.core-k91vdnvi.js +7 -0
- package/static/dist/assets/micromark-factory-space-fnmnpi6s.js +1 -0
- package/static/dist/assets/{mindmap-definition-YA3MSWOX-27b26eok.js → mindmap-definition-YA3MSWOX-ehztfea4.js} +28 -28
- package/static/dist/assets/{nginx-e7lvhsmn.js → nginx-f3d68ed4.js} +1 -1
- package/static/dist/assets/{nim-dun5d8mk.js → nim-dw0jcy70.js} +1 -1
- package/static/dist/assets/onboarding-f67z0a2r.js +1 -0
- package/static/dist/assets/packet-AYTQ26CC-ok2xrblz.js +1 -0
- package/static/dist/assets/pcmTap.worklet-74EKjWAZ.js +1 -0
- package/static/dist/assets/pegDiagram-XKGWAZYB-ec3rpj0m.js +1 -0
- package/static/dist/assets/{perl-bj3oqtet.js → perl-3c0r45c8.js} +1 -1
- package/static/dist/assets/{php-buzp12r0.js → php-rznhidvp.js} +1 -1
- package/static/dist/assets/pie-WAS4IAKB-iwkir23u.js +1 -0
- package/static/dist/assets/pieDiagram-E7YTZNPT-fcpqpekh.js +39 -0
- package/static/dist/assets/{pug-mjad7he9.js → pug-f2le4f3y.js} +1 -1
- package/static/dist/assets/{qml-d1gdp10s.js → qml-e2wbq9cr.js} +1 -1
- package/static/dist/assets/{quadrantDiagram-AXDQQJYC-hhue7d8o.js → quadrantDiagram-AXDQQJYC-lqsync43.js} +1 -1
- package/static/dist/assets/queryKeys-ed4n2egc.js +9 -0
- package/static/dist/assets/{r-o3r9c7ao.js → r-epfzuw6q.js} +1 -1
- package/static/dist/assets/radar-RG4KPBEZ-hje4jbk6.js +1 -0
- package/static/dist/assets/railroad-74A4TZTK-gll9n6qi.js +1 -0
- package/static/dist/assets/railroad-abnf-HS5TGJTU-o6h6lpn4.js +1 -0
- package/static/dist/assets/railroad-ebnf-LZEXJU2U-juaefj6o.js +1 -0
- package/static/dist/assets/railroad-peg-WCYAUIDC-cgfhvpah.js +1 -0
- package/static/dist/assets/railroadDiagram-O6MQD6OU-lp3w7awf.js +1 -0
- package/static/dist/assets/{razor-ilc585yr.js → razor-pea1u1d0.js} +1 -1
- package/static/dist/assets/refresh-cw-iccm7a4e.js +1 -0
- package/static/dist/assets/refresh-i9ya9dvl.js +1 -0
- package/static/dist/assets/{regexp-mpjtcvwm.js → regexp-hzte0a5x.js} +1 -1
- package/static/dist/assets/registry-g7w3353u.js +1 -0
- package/static/dist/assets/requirementDiagram-BXWQKSXE-ha8eibcf.js +84 -0
- package/static/dist/assets/rolldown-runtime-bnnw9q4a.js +1 -0
- package/static/dist/assets/{rst-jrkwjdyi.js → rst-m6tugj5o.js} +1 -1
- package/static/dist/assets/{ruby-n4tjcbpz.js → ruby-l19vq3w1.js} +1 -1
- package/static/dist/assets/runtime-nlxpnegr.js +1 -0
- package/static/dist/assets/{sankeyDiagram-P5KCCOFB-fqb8xcjf.js → sankeyDiagram-P5KCCOFB-oxf31pr9.js} +1 -1
- package/static/dist/assets/{sas-hjo6y93k.js → sas-ktdxo397.js} +1 -1
- package/static/dist/assets/{scss-ncidjv48.js → scss-kn3oxfwf.js} +1 -1
- package/static/dist/assets/{sequenceDiagram-WJ2MYXX4-dlcz6qjz.js → sequenceDiagram-WJ2MYXX4-jiq8lhyo.js} +11 -11
- package/static/dist/assets/settings_section_extensions_title-fadc7o65.js +1 -0
- package/static/dist/assets/share._token-o76ki0ly.js +2 -0
- package/static/dist/assets/{shellscript-m8whjpqd.js → shellscript-l100jtrg.js} +1 -1
- package/static/dist/assets/{shellsession-i5bj6syz.js → shellsession-m5qukwow.js} +1 -1
- package/static/dist/assets/sizeCapture-INFHLROL-dk1io13w.js +1 -0
- package/static/dist/assets/sliders-horizontal-ddcs88av.js +1 -0
- package/static/dist/assets/{soy-hhh36ysq.js → soy-mexlscur.js} +1 -1
- package/static/dist/assets/{sql-j21bzcl6.js → sql-o0ho5suh.js} +1 -1
- package/static/dist/assets/src-h89s0hs4.js +1 -0
- package/static/dist/assets/{stata-bbu2onh1.js → stata-be9ck1q3.js} +1 -1
- package/static/dist/assets/stateDiagram-D77RDMKH-f3fslnon.js +1 -0
- package/static/dist/assets/stateDiagram-v2-MP3YSRHH-hlt6yphw.js +1 -0
- package/static/dist/assets/{surrealql-l5vczuco.js → surrealql-gk1xkkyy.js} +1 -1
- package/static/dist/assets/{svelte-idn422g6.js → svelte-k6ecjilf.js} +1 -1
- package/static/dist/assets/swimlanes-42K2YHIH-k1hmk7jf.js +1 -0
- package/static/dist/assets/swimlanesDiagram-VR7AAH4N-hd5t9tnt.js +8 -0
- package/static/dist/assets/{templ-e22qou3c.js → templ-gf3bftk6.js} +1 -1
- package/static/dist/assets/{tex-deqpc5ee.js → tex-d21fqv1z.js} +1 -1
- package/static/dist/assets/{timeline-definition-24CTP7MA-b1vl2zil.js → timeline-definition-24CTP7MA-n3ncfy9r.js} +8 -8
- package/static/dist/assets/toast-liparz2j.js +56 -0
- package/static/dist/assets/treeView-Q6P3EWNA-l3y2pejt.js +1 -0
- package/static/dist/assets/treemap-WGGIJYW6-jown9axh.js +1 -0
- package/static/dist/assets/{ts-tags-ctnibc27.js → ts-tags-n0g61gr6.js} +1 -1
- package/static/dist/assets/{tsx-i163n32g.js → tsx-cvv7wv6q.js} +1 -1
- package/static/dist/assets/{twig-x0fi7wm8.js → twig-n1f67204.js} +1 -1
- package/static/dist/assets/{typescript-g18c34xz.js → typescript-og7o55cx.js} +1 -1
- package/static/dist/assets/untitled-mj86r4gz.js +1 -0
- package/static/dist/assets/useDebounced-g8r0ggve.js +1 -0
- package/static/dist/assets/useForm-o4uu74mx.js +1 -0
- package/static/dist/assets/{useParams-b4dq6n4q.js → useParams-ftsveu84.js} +1 -1
- package/static/dist/assets/{useSearch-ipfmv3he.js → useSearch-crqueqga.js} +1 -1
- package/static/dist/assets/vennDiagram-4TSXK5OY-dh59uq1c.js +34 -0
- package/static/dist/assets/{vue-mwu5l1bb.js → vue-ej4xpwqw.js} +1 -1
- package/static/dist/assets/{vue-html-nskj3du0.js → vue-html-d48xsjuo.js} +1 -1
- package/static/dist/assets/{vue-vine-cqe77smq.js → vue-vine-pev88ip6.js} +1 -1
- package/static/dist/assets/wardley-WFR3VGLG-e6d74b0j.js +1 -0
- package/static/dist/assets/wardleyDiagram-VM6X3IG4-hnofh78f.js +78 -0
- package/static/dist/assets/with-selector-nu1b5z0v.js +1 -0
- package/static/dist/assets/{xml-gau7gvrv.js → xml-ifxp6gqb.js} +1 -1
- package/static/dist/assets/{xsl-ew09zq8b.js → xsl-fug2cckc.js} +1 -1
- package/static/dist/assets/{xychartDiagram-S5SC5T6Z-e49523ab.js → xychartDiagram-S5SC5T6Z-bpymjelb.js} +6 -6
- package/static/dist/assets/{yaml-ofnrxtvf.js → yaml-fjmafnlo.js} +1 -1
- package/static/dist/extension-sdk.js +1 -1
- package/static/dist/index.html +1 -1
- package/static/dist/sw.js +180 -136
- package/static/dist/assets/AppShell-g3bkgnvt.js +0 -1
- package/static/dist/assets/ChatPage-oo7bdan6.js +0 -25
- package/static/dist/assets/Dialog-g355qxhp.js +0 -1
- package/static/dist/assets/ExtensionRoute-i2y9fvjm.js +0 -1
- package/static/dist/assets/HubRoute-lmkrbw47.js +0 -2
- package/static/dist/assets/Markdown-j4kut4j2.js +0 -598
- package/static/dist/assets/Markdown-lwviulmg.css +0 -1
- package/static/dist/assets/RightPanel-ohlsdzfl.js +0 -1
- package/static/dist/assets/Select-kddq75qc.js +0 -1
- package/static/dist/assets/SessionListPanel-lu3oy0hw.js +0 -1
- package/static/dist/assets/SettingsLayout-o9bv4mgb.js +0 -1
- package/static/dist/assets/States-eq6fe29m.js +0 -1
- package/static/dist/assets/Toaster-pc247u9f.js +0 -1
- package/static/dist/assets/_app-f8n1i0m1.js +0 -1
- package/static/dist/assets/_app.ext._extensionId-gfbzpoou.js +0 -1
- package/static/dist/assets/_app.index-bzzv80hk.js +0 -1
- package/static/dist/assets/_app.insights-dzixbryi.js +0 -1
- package/static/dist/assets/_app.kanban-c6hep2us.js +0 -1
- package/static/dist/assets/_app.logs-i69qds98.js +0 -1
- package/static/dist/assets/_app.memory-kl4vf0gd.js +0 -1
- package/static/dist/assets/_app.profiles-b8zinmyp.js +0 -1
- package/static/dist/assets/_app.session._sessionId-fn1bhde6.js +0 -1
- package/static/dist/assets/_app.settings-cg8plwmf.js +0 -1
- package/static/dist/assets/_app.settings._section-bkwbi9zn.js +0 -3
- package/static/dist/assets/_app.skills-cs47sbvs.js +0 -1
- package/static/dist/assets/_app.tasks-dwvk64tc.js +0 -1
- package/static/dist/assets/_app.todos-c8xjm8p3.js +0 -1
- package/static/dist/assets/_app.workspaces-ehvd1gds.js +0 -1
- package/static/dist/assets/abnfDiagram-VCTEODGH-c8kdixke.js +0 -1
- package/static/dist/assets/architecture-7GRP2DOG-6crvnylg.js +0 -1
- package/static/dist/assets/architectureDiagram-5GKGNRK7-cku06x1p.js +0 -36
- package/static/dist/assets/back-h7aun7ew.js +0 -1
- package/static/dist/assets/cancel-fhi0vcnu.js +0 -1
- package/static/dist/assets/channel-b2zo73z1.js +0 -1
- package/static/dist/assets/chunk-DU6HZSFF-ofajdixh.js +0 -128
- package/static/dist/assets/chunk-OSK3NFVY-e7gkikcw.js +0 -10
- package/static/dist/assets/classDiagram-ZZMXUADV-oe99st8x.js +0 -1
- package/static/dist/assets/classDiagram-v2-VYDZK3BY-oe99st8x.js +0 -1
- package/static/dist/assets/copied-hcplv46p.js +0 -1
- package/static/dist/assets/copy-magtofyp.js +0 -1
- package/static/dist/assets/cose-bilkent-JH36ORCC-eclcy6ja.js +0 -1
- package/static/dist/assets/cynefin-OW5HDTMX-siqlulkl.js +0 -1
- package/static/dist/assets/cynefinDiagram-5FMLGOSQ-i648tah9.js +0 -62
- package/static/dist/assets/cytoscape.esm-bqu53u12.js +0 -321
- package/static/dist/assets/dagre-GXQ25YYZ-mwn6uc17.js +0 -4
- package/static/dist/assets/dagre-lkoknbjn.js +0 -1
- package/static/dist/assets/diagram-UQ7AKVKN-mekq7zgq.js +0 -41
- package/static/dist/assets/diagram-VX7I27RA-xe6r5qfw.js +0 -24
- package/static/dist/assets/diagram-Z3DM3KII-nq07dg7k.js +0 -24
- package/static/dist/assets/ebnfDiagram-PWID7BFC-c62ipm3g.js +0 -1
- package/static/dist/assets/endpoints-klbxod4t.js +0 -64
- package/static/dist/assets/erDiagram-RLTQ6QDP-h39kmnzy.js +0 -99
- package/static/dist/assets/eventmodeling-NTZA5JFV-obfede4u.js +0 -1
- package/static/dist/assets/flowDiagram-HODETNUW-kdpsp1je.js +0 -1
- package/static/dist/assets/gitGraph-4MIJSDKK-fr2i7caa.js +0 -1
- package/static/dist/assets/highlighted-body-KPVGNVTW-jwpop9p8.js +0 -1
- package/static/dist/assets/host-i828xuo7.js +0 -1
- package/static/dist/assets/index-eh8zilnv.css +0 -2
- package/static/dist/assets/index-r648f4o1.js +0 -11
- package/static/dist/assets/info-A6RAGUB7-h11x0dxo.js +0 -1
- package/static/dist/assets/infoDiagram-27XIBGKW-dfh47dw9.js +0 -2
- package/static/dist/assets/lazyRouteComponent-e1y4t2i9.js +0 -1
- package/static/dist/assets/linear-becwlnhk.js +0 -1
- package/static/dist/assets/link-oot2yn73.js +0 -1
- package/static/dist/assets/login-gu28l9ou.js +0 -1
- package/static/dist/assets/mermaid-HWGCJPDP-mtwrj8fn.js +0 -1
- package/static/dist/assets/mermaid-parser.core-ntne45i9.js +0 -7
- package/static/dist/assets/not-found-ccnnac39.js +0 -1
- package/static/dist/assets/onboarding-lkphzu1s.js +0 -1
- package/static/dist/assets/onboarding_model_label-ftpjdwqk.js +0 -1
- package/static/dist/assets/packet-AYTQ26CC-l6jdka8p.js +0 -1
- package/static/dist/assets/pegDiagram-XKGWAZYB-g1er3bxj.js +0 -1
- package/static/dist/assets/pie-WAS4IAKB-i0ylcrt9.js +0 -1
- package/static/dist/assets/pieDiagram-E7YTZNPT-fbz1e55z.js +0 -39
- package/static/dist/assets/radar-RG4KPBEZ-f9b70aa4.js +0 -1
- package/static/dist/assets/railroad-74A4TZTK-lgsuoeda.js +0 -1
- package/static/dist/assets/railroad-abnf-HS5TGJTU-nf9d6pdx.js +0 -1
- package/static/dist/assets/railroad-ebnf-LZEXJU2U-f7ummkt5.js +0 -1
- package/static/dist/assets/railroad-peg-WCYAUIDC-oczq5tqs.js +0 -1
- package/static/dist/assets/railroadDiagram-O6MQD6OU-eqpy9fnz.js +0 -1
- package/static/dist/assets/refresh-abtu93ke.js +0 -1
- package/static/dist/assets/refresh-cw-hlwb02qv.js +0 -1
- package/static/dist/assets/requirementDiagram-BXWQKSXE-ogf6puhi.js +0 -84
- package/static/dist/assets/rolldown-runtime-b9miacsj.js +0 -1
- package/static/dist/assets/root-mbklpuv4.js +0 -1
- package/static/dist/assets/saved-girnabkf.js +0 -1
- package/static/dist/assets/settings_section_extensions_title-h14cwk6f.js +0 -1
- package/static/dist/assets/share._token-kl0r7ido.js +0 -2
- package/static/dist/assets/sizeCapture-INFHLROL-g612l48j.js +0 -1
- package/static/dist/assets/sliders-horizontal-n1zm34qq.js +0 -1
- package/static/dist/assets/src-hjyib4mu.js +0 -1
- package/static/dist/assets/sse-iwku0sjo.js +0 -1
- package/static/dist/assets/stateDiagram-D77RDMKH-fyoznpcs.js +0 -1
- package/static/dist/assets/stateDiagram-v2-MP3YSRHH-ixhx8r46.js +0 -1
- package/static/dist/assets/swimlanes-42K2YHIH-oefldhfy.js +0 -1
- package/static/dist/assets/swimlanesDiagram-VR7AAH4N-h9ersk2e.js +0 -8
- package/static/dist/assets/todoStore-jjr5yr78.js +0 -1
- package/static/dist/assets/treeView-Q6P3EWNA-f7hcci5o.js +0 -1
- package/static/dist/assets/treemap-WGGIJYW6-nl85071a.js +0 -1
- package/static/dist/assets/units-kgxzxfhi.js +0 -1
- package/static/dist/assets/untitled-cikfjntn.js +0 -1
- package/static/dist/assets/useForm-kqoqg0k9.js +0 -1
- package/static/dist/assets/useLocale-o59tbiea.js +0 -1
- package/static/dist/assets/vennDiagram-4TSXK5OY-h5hzbk0n.js +0 -34
- package/static/dist/assets/wardley-WFR3VGLG-jftvpm3e.js +0 -1
- package/static/dist/assets/wardleyDiagram-VM6X3IG4-hedh85ge.js +0 -78
- /package/static/dist/assets/{ChatPage-gmu5c7lf.css → TerminalPanel-gmu5c7lf.css} +0 -0
package/dist/sessions/store.js
CHANGED
|
@@ -1,21 +1,10 @@
|
|
|
1
|
+
import { markedStateDbGeneration } from './state-db-identity.js';
|
|
1
2
|
import { str } from '../util.js';
|
|
2
|
-
/**
|
|
3
|
-
* The WebUI session store (Python `api/models.py`): `sessions/<sid>.json`
|
|
4
|
-
* sidecars written atomically with a `.bak` on shrink, the sorted
|
|
5
|
-
* `sessions/_index.json` sidebar index with incremental patching, a bounded
|
|
6
|
-
* LRU of resident sessions that never evicts active or unsaved work, the
|
|
7
|
-
* deleted-session tombstone, composer draft overlays, and per-session
|
|
8
|
-
* mutation locks.
|
|
9
|
-
*
|
|
10
|
-
* The state.db projection (CLI sessions, lineage metadata, transcript
|
|
11
|
-
* reconciliation) is not part of this store; it layers on in the sidebar
|
|
12
|
-
* builder once the read-only SQLite projection lands.
|
|
13
|
-
*/
|
|
14
|
-
import { closeSync, existsSync, fstatSync, fsyncSync, mkdirSync, openSync, readdirSync, readFileSync, renameSync, rmSync, statSync, unlinkSync } from 'node:fs';
|
|
15
|
-
import { writeFully } from '../fs/atomic.js';
|
|
16
|
-
import { basename, join } from 'node:path';
|
|
17
3
|
import { sanitizeSessionRow } from './list.js';
|
|
4
|
+
import { withBackgroundDisplayKinds } from './background-updates.js';
|
|
18
5
|
import { anchorSceneIndexFromRecords, collapseAdjacentDuplicatePartials, isSafeSessionId, Session } from './session.js';
|
|
6
|
+
import { RevisionConflict } from './storage/backend.js';
|
|
7
|
+
import { sessionSearchMatches, sessionSearchMessageText } from './storage/search-text.js';
|
|
19
8
|
export class SessionNotFound extends Error {
|
|
20
9
|
sid;
|
|
21
10
|
constructor(sid) {
|
|
@@ -24,175 +13,54 @@ export class SessionNotFound extends Error {
|
|
|
24
13
|
this.name = 'SessionNotFound';
|
|
25
14
|
}
|
|
26
15
|
}
|
|
27
|
-
const LOAD_STABLE_READ_ATTEMPTS = 3;
|
|
28
16
|
const UNSAVED_SHELL_GRACE_S = 1800;
|
|
29
|
-
const STALE_TMP_AGE_S = 3600;
|
|
30
|
-
const DELETED_TOMBSTONE_CAP = 1000;
|
|
31
|
-
const DELETED_TOMBSTONE_VERSION = 1;
|
|
32
|
-
let tmpCounter = 0;
|
|
33
|
-
function tmpName(path) {
|
|
34
|
-
return `${path}.tmp.${process.pid}.${++tmpCounter}`;
|
|
35
|
-
}
|
|
36
|
-
function writeAtomic(path, text) {
|
|
37
|
-
const tmp = tmpName(path);
|
|
38
|
-
const fd = openSync(tmp, 'w');
|
|
39
|
-
try {
|
|
40
|
-
writeFully(fd, text);
|
|
41
|
-
fsyncSync(fd);
|
|
42
|
-
closeSync(fd);
|
|
43
|
-
renameSync(tmp, path);
|
|
44
|
-
}
|
|
45
|
-
catch (error) {
|
|
46
|
-
try {
|
|
47
|
-
closeSync(fd);
|
|
48
|
-
}
|
|
49
|
-
catch { /* closed */ }
|
|
50
|
-
try {
|
|
51
|
-
unlinkSync(tmp);
|
|
52
|
-
}
|
|
53
|
-
catch { /* gone */ }
|
|
54
|
-
throw error;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
export function statSignature(path) {
|
|
58
|
-
try {
|
|
59
|
-
const st = statSync(path, { bigint: true });
|
|
60
|
-
return `${path}:${st.mtimeNs}:${st.size}:${st.ctimeNs}`;
|
|
61
|
-
}
|
|
62
|
-
catch {
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
/** Python `_read_metadata_json_prefix`: everything before the top-level `messages` (or `anchor_activity_scenes`) key. */
|
|
67
|
-
export function readMetadataJsonPrefix(path, maxBytes = 1024 * 1024) {
|
|
68
|
-
return readMetadataJsonPrefixWithSignature(path, maxBytes).prefix;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* The metadata prefix together with the signature of the inode it was read from (fstat of the open descriptor), so a
|
|
72
|
-
* file atomically replaced during the read is never cached under the replacement's identity.
|
|
73
|
-
*/
|
|
74
|
-
export function readMetadataJsonPrefixWithSignature(path, maxBytes = 1024 * 1024) {
|
|
75
|
-
const fd = openSync(path, 'r');
|
|
76
|
-
try {
|
|
77
|
-
const st = fstatSync(fd, { bigint: true });
|
|
78
|
-
const signature = `${path}:${st.mtimeNs}:${st.size}:${st.ctimeNs}`;
|
|
79
|
-
return { prefix: readPrefixFromFd(fd, maxBytes, Math.min(64 * 1024, maxBytes)), signature };
|
|
80
|
-
}
|
|
81
|
-
finally {
|
|
82
|
-
closeSync(fd);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
function readPrefixFromFd(fd, maxBytes, initialStage) {
|
|
86
|
-
let stage = initialStage;
|
|
87
|
-
{
|
|
88
|
-
let raw = Buffer.alloc(0);
|
|
89
|
-
let text = '';
|
|
90
|
-
let stopPos = null;
|
|
91
|
-
while (raw.length < maxBytes) {
|
|
92
|
-
const chunk = Buffer.alloc(Math.min(stage, maxBytes - raw.length));
|
|
93
|
-
const n = readSyncFully(fd, chunk);
|
|
94
|
-
if (n === 0)
|
|
95
|
-
return null;
|
|
96
|
-
raw = Buffer.concat([raw, chunk.subarray(0, n)]);
|
|
97
|
-
text = raw.toString('utf8');
|
|
98
|
-
const messagesPos = findTopLevelJsonKey(text, 'messages');
|
|
99
|
-
const scenesPos = findTopLevelJsonKey(text, 'anchor_activity_scenes');
|
|
100
|
-
stopPos = messagesPos;
|
|
101
|
-
if (scenesPos !== null && (stopPos === null || scenesPos < stopPos))
|
|
102
|
-
stopPos = scenesPos;
|
|
103
|
-
if (stopPos !== null)
|
|
104
|
-
break;
|
|
105
|
-
stage *= 2;
|
|
106
|
-
}
|
|
107
|
-
if (stopPos === null)
|
|
108
|
-
return null;
|
|
109
|
-
let prefix = text.slice(0, stopPos).trimEnd();
|
|
110
|
-
if (prefix.endsWith(','))
|
|
111
|
-
prefix = prefix.slice(0, -1).trimEnd();
|
|
112
|
-
return `${prefix}\n}`;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
import { readSync } from 'node:fs';
|
|
116
|
-
function readSyncFully(fd, buf) {
|
|
117
|
-
let total = 0;
|
|
118
|
-
while (total < buf.length) {
|
|
119
|
-
const n = readSync(fd, buf, total, buf.length - total, null);
|
|
120
|
-
if (n === 0)
|
|
121
|
-
break;
|
|
122
|
-
total += n;
|
|
123
|
-
}
|
|
124
|
-
return total;
|
|
125
|
-
}
|
|
126
|
-
/** Offset of `"key":` at JSON nesting depth 1, or null. */
|
|
127
|
-
export function findTopLevelJsonKey(text, key) {
|
|
128
|
-
let depth = 0;
|
|
129
|
-
let inString = false;
|
|
130
|
-
let escape = false;
|
|
131
|
-
let stringStart = -1;
|
|
132
|
-
for (let i = 0; i < text.length; i += 1) {
|
|
133
|
-
const ch = text[i];
|
|
134
|
-
if (inString) {
|
|
135
|
-
if (escape)
|
|
136
|
-
escape = false;
|
|
137
|
-
else if (ch === '\\')
|
|
138
|
-
escape = true;
|
|
139
|
-
else if (ch === '"') {
|
|
140
|
-
inString = false;
|
|
141
|
-
if (depth === 1 && text.slice(stringStart + 1, i) === key) {
|
|
142
|
-
let j = i + 1;
|
|
143
|
-
while (j < text.length && /\s/.test(text[j] ?? ''))
|
|
144
|
-
j += 1;
|
|
145
|
-
if (text[j] === ':')
|
|
146
|
-
return stringStart;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
continue;
|
|
150
|
-
}
|
|
151
|
-
if (ch === '"') {
|
|
152
|
-
inString = true;
|
|
153
|
-
stringStart = i;
|
|
154
|
-
continue;
|
|
155
|
-
}
|
|
156
|
-
if (ch === '{' || ch === '[')
|
|
157
|
-
depth += 1;
|
|
158
|
-
else if (ch === '}' || ch === ']')
|
|
159
|
-
depth -= 1;
|
|
160
|
-
}
|
|
161
|
-
return null;
|
|
162
|
-
}
|
|
163
|
-
export function readPersistedMessageCount(path) {
|
|
164
|
-
try {
|
|
165
|
-
const prefix = readMetadataJsonPrefix(path);
|
|
166
|
-
if (!prefix)
|
|
167
|
-
return null;
|
|
168
|
-
const value = JSON.parse(prefix).message_count;
|
|
169
|
-
if (typeof value === 'boolean')
|
|
170
|
-
return null;
|
|
171
|
-
const n = Number(value);
|
|
172
|
-
return Number.isInteger(n) && n >= 0 ? n : null;
|
|
173
|
-
}
|
|
174
|
-
catch {
|
|
175
|
-
return null;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
17
|
export class SessionStore {
|
|
179
18
|
deps;
|
|
180
|
-
sessionDir;
|
|
181
|
-
indexFile;
|
|
182
|
-
/** Resident sessions in LRU order (oldest first). */
|
|
183
19
|
sessions = new Map();
|
|
184
20
|
locks = new Map();
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
21
|
+
writes = new Map();
|
|
22
|
+
resolutions = new Map();
|
|
23
|
+
persistedMessages = new WeakMap();
|
|
24
|
+
indexWriter = Promise.resolve();
|
|
188
25
|
indexPending = new Map();
|
|
26
|
+
indexFlush = null;
|
|
27
|
+
indexFailure = null;
|
|
189
28
|
constructor(deps) {
|
|
190
29
|
this.deps = deps;
|
|
191
|
-
this.sessionDir = deps.sessionDir;
|
|
192
|
-
this.indexFile = join(deps.sessionDir, '_index.json');
|
|
193
30
|
}
|
|
194
|
-
|
|
195
|
-
|
|
31
|
+
get backend() { return this.deps.storage.sessions; }
|
|
32
|
+
async exists(sid) { return this.backend.exists(sid); }
|
|
33
|
+
async revision(sid) { return this.backend.revision(sid); }
|
|
34
|
+
readMessages(sid, range) { return this.backend.readMessages(sid, range); }
|
|
35
|
+
/** Readers retry rows a failed batch left queued; a still-failing index reads as unreadable, never as current. */
|
|
36
|
+
async index() {
|
|
37
|
+
await this.queueIndexUpdate([]);
|
|
38
|
+
// The joined flush may itself have failed; retry what it left queued once.
|
|
39
|
+
if (this.indexPending.size)
|
|
40
|
+
await this.queueIndexUpdate([]);
|
|
41
|
+
if (this.indexFailure && this.indexPending.size)
|
|
42
|
+
throw this.indexFailure;
|
|
43
|
+
return this.backend.index();
|
|
44
|
+
}
|
|
45
|
+
async hasIndex() { return this.backend.hasIndex(); }
|
|
46
|
+
get shrinkBackup() { return this.backend.shrinkBackup; }
|
|
47
|
+
async diagnose() { return this.backend.diagnose(); }
|
|
48
|
+
async repair(issue) {
|
|
49
|
+
const repaired = await this.backend.repair(issue);
|
|
50
|
+
if (repaired)
|
|
51
|
+
this.sessions.delete(issue.session_id);
|
|
52
|
+
return repaired;
|
|
53
|
+
}
|
|
54
|
+
async close() {
|
|
55
|
+
try {
|
|
56
|
+
await Promise.allSettled(this.resolutions.values());
|
|
57
|
+
await Promise.allSettled(this.writes.values());
|
|
58
|
+
await this.indexFlush;
|
|
59
|
+
await this.indexWriter;
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
await this.deps.storage.close();
|
|
63
|
+
}
|
|
196
64
|
}
|
|
197
65
|
// ── locks ────────────────────────────────────────────────────────────────
|
|
198
66
|
/** Serialize one session's read-modify-write sequences (Python `_get_session_agent_lock`). */
|
|
@@ -222,17 +90,17 @@ export class SessionStore {
|
|
|
222
90
|
}
|
|
223
91
|
}
|
|
224
92
|
// ── creation / resolution ────────────────────────────────────────────────
|
|
225
|
-
construct(init, profile) {
|
|
226
|
-
const session = new Session(init, this.deps.defaults(profile));
|
|
93
|
+
async construct(init, profile) {
|
|
94
|
+
const session = new Session(init, (await this.deps.defaults(profile)));
|
|
227
95
|
// New-session defaults must not replace the title supplied by the read projection.
|
|
228
96
|
if (typeof init.title === 'string')
|
|
229
97
|
session.title = init.title;
|
|
230
98
|
return session;
|
|
231
99
|
}
|
|
232
100
|
/** In-memory only until the first message is persisted (Python `new_session`). */
|
|
233
|
-
newSession(opts = {}) {
|
|
101
|
+
async newSession(opts = {}) {
|
|
234
102
|
const profile = opts.profile ?? null;
|
|
235
|
-
const defaults = this.deps.defaults(profile);
|
|
103
|
+
const defaults = (await this.deps.defaults(profile));
|
|
236
104
|
const wt = opts.worktree ?? null;
|
|
237
105
|
const s = new Session({
|
|
238
106
|
workspace: (wt ? wt.path : opts.workspace) || defaults.workspace,
|
|
@@ -247,97 +115,82 @@ export class SessionStore {
|
|
|
247
115
|
worktree_created_at: wt?.created_at ?? null,
|
|
248
116
|
enabled_toolsets: opts.enabledToolsets ?? null,
|
|
249
117
|
}, defaults);
|
|
250
|
-
this.clearDeletedTombstone(s.session_id);
|
|
251
|
-
this.touch(s);
|
|
118
|
+
await this.clearDeletedTombstone(s.session_id);
|
|
119
|
+
await this.touch(s);
|
|
252
120
|
if (wt)
|
|
253
|
-
this.save(s);
|
|
121
|
+
(await this.save(s));
|
|
254
122
|
return s;
|
|
255
123
|
}
|
|
256
124
|
/** Insert or refresh a session in the LRU and evict over the cap. */
|
|
257
|
-
touch(session) {
|
|
125
|
+
async touch(session) {
|
|
258
126
|
this.sessions.delete(session.session_id);
|
|
259
127
|
this.sessions.set(session.session_id, session);
|
|
260
|
-
this.evictOverCap();
|
|
128
|
+
await this.evictOverCap();
|
|
261
129
|
}
|
|
262
|
-
load(sid) {
|
|
130
|
+
async load(sid, opts = {}) {
|
|
263
131
|
if (!isSafeSessionId(sid))
|
|
264
132
|
return null;
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
const
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
133
|
+
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
134
|
+
const stored = await this.backend.readDocument(sid);
|
|
135
|
+
if (!stored)
|
|
136
|
+
return null;
|
|
137
|
+
const data = sanitizeSessionRow(stored.doc, this, sid);
|
|
138
|
+
if (data?.session_id !== sid)
|
|
139
|
+
return null;
|
|
140
|
+
const messages = stored.messages;
|
|
141
|
+
if (stored.revision === null || stored.revision !== await this.revision(sid))
|
|
142
|
+
continue;
|
|
143
|
+
const [rows, collapsed] = collapseAdjacentDuplicatePartials(messages);
|
|
144
|
+
// Keep the parsed baseline independent of in-place edits to the resident session.
|
|
145
|
+
data.messages = structuredClone(rows);
|
|
146
|
+
const session = (await this.construct(data, data.profile ?? null));
|
|
147
|
+
session.sidecarLoadedSignature = stored.revision;
|
|
148
|
+
this.persistedMessages.set(session, { rows: messages });
|
|
149
|
+
if (collapsed && (opts.repairDuplicates ?? true)) {
|
|
150
|
+
try {
|
|
151
|
+
await this.save(session, { touchUpdatedAt: false, skipIndex: true });
|
|
152
|
+
}
|
|
153
|
+
catch { /* best effort */ }
|
|
279
154
|
}
|
|
280
|
-
}
|
|
281
|
-
const clean = sanitizeSessionRow(data, this, basename(path));
|
|
282
|
-
if (!clean)
|
|
283
|
-
return null;
|
|
284
|
-
data = clean;
|
|
285
|
-
const [messages, collapsed] = collapseAdjacentDuplicatePartials(data.messages);
|
|
286
|
-
data.messages = messages;
|
|
287
|
-
const session = this.construct(data, data.profile ?? null);
|
|
288
|
-
if (collapsed) {
|
|
289
155
|
try {
|
|
290
|
-
|
|
156
|
+
if (opts.drafts ?? true)
|
|
157
|
+
session.composer_draft = (await this.deps.drafts.read(sid, session.composer_draft));
|
|
291
158
|
}
|
|
292
|
-
catch { /*
|
|
293
|
-
|
|
294
|
-
else {
|
|
295
|
-
session.sidecarLoadedSignature = signature;
|
|
296
|
-
}
|
|
297
|
-
try {
|
|
298
|
-
session.composer_draft = this.deps.drafts.read(sid, session.composer_draft);
|
|
159
|
+
catch { /* ignore */ }
|
|
160
|
+
return session;
|
|
299
161
|
}
|
|
300
|
-
|
|
301
|
-
return session;
|
|
162
|
+
throw new RevisionConflict(sid);
|
|
302
163
|
}
|
|
303
|
-
loadMetadataOnly(sid, opts = {}) {
|
|
164
|
+
async loadMetadataOnly(sid, opts = {}) {
|
|
304
165
|
if (!isSafeSessionId(sid))
|
|
305
166
|
return null;
|
|
306
|
-
const path = this.pathFor(sid);
|
|
307
|
-
if (!existsSync(path))
|
|
308
|
-
return null;
|
|
309
167
|
try {
|
|
310
|
-
const
|
|
311
|
-
if (!
|
|
312
|
-
return
|
|
313
|
-
|
|
314
|
-
|
|
168
|
+
const stored = await this.backend.readDocument(sid, { metadataOnly: true });
|
|
169
|
+
if (!stored)
|
|
170
|
+
return null;
|
|
171
|
+
if (!stored.metadataOnly)
|
|
172
|
+
return (await this.load(sid));
|
|
173
|
+
const parsed = sanitizeSessionRow(stored.doc, this, sid);
|
|
174
|
+
if (parsed?.session_id !== sid)
|
|
315
175
|
return null;
|
|
316
|
-
for (const key of ['session_id', 'title', 'created_at', 'updated_at'])
|
|
317
|
-
if (!(key in parsed))
|
|
318
|
-
return this.load(sid);
|
|
319
|
-
const sidecarCount = parsed.message_count;
|
|
320
|
-
const modernCount = typeof sidecarCount === 'number' && Number.isInteger(sidecarCount) && sidecarCount >= 0 ? sidecarCount : null;
|
|
321
|
-
if (modernCount === null && !('anchor_scene_index' in parsed))
|
|
322
|
-
return this.load(sid);
|
|
323
176
|
parsed.messages = [];
|
|
324
177
|
parsed.tool_calls = [];
|
|
325
|
-
const session = this.construct(parsed, parsed.profile ?? null);
|
|
326
|
-
|
|
327
|
-
if (modernCount === null)
|
|
328
|
-
indexCount = (opts.indexMessageCounts ?? this.indexMessageCounts()).get(sid) ?? null;
|
|
329
|
-
const known = [indexCount, modernCount].filter((c) => c !== null);
|
|
330
|
-
session.metadataMessageCount = known.length ? Math.max(...known) : null;
|
|
178
|
+
const session = (await this.construct(parsed, parsed.profile ?? null));
|
|
179
|
+
session.metadataMessageCount = stored.messageCount ?? (opts.indexMessageCounts ?? await this.indexMessageCounts()).get(sid) ?? null;
|
|
331
180
|
session.loadedMetadataOnly = true;
|
|
332
|
-
session.sidecarLoadedSignature =
|
|
181
|
+
session.sidecarLoadedSignature = stored.revision;
|
|
333
182
|
return session;
|
|
334
183
|
}
|
|
335
184
|
catch {
|
|
336
|
-
return this.load(sid);
|
|
185
|
+
return (await this.load(sid));
|
|
337
186
|
}
|
|
338
187
|
}
|
|
339
|
-
/** Resolve a session through the cache with disk-freshness checks (Python `get_session`). Throws `SessionNotFound`. */
|
|
340
188
|
get(sid, opts = {}) {
|
|
189
|
+
return this.serializeSession(sid, () => this.getNow(sid, opts), this.resolutions);
|
|
190
|
+
}
|
|
191
|
+
async getNow(sid, opts) {
|
|
192
|
+
// A local commit updates the resident revision before a reader can mistake it for an external edit.
|
|
193
|
+
await this.writes.get(sid)?.catch(() => { });
|
|
341
194
|
const cached = this.sessions.get(sid);
|
|
342
195
|
if (cached) {
|
|
343
196
|
if (cached.session_id !== sid) {
|
|
@@ -349,15 +202,13 @@ export class SessionStore {
|
|
|
349
202
|
this.sessions.delete(sid);
|
|
350
203
|
this.sessions.set(sid, cached);
|
|
351
204
|
}
|
|
352
|
-
const lags = this.
|
|
353
|
-
|
|
354
|
-
if (lags && !existsSync(this.pathFor(sid))) {
|
|
205
|
+
const lags = await this.cachedLagsStorage(cached);
|
|
206
|
+
if (lags && !await this.exists(sid)) {
|
|
355
207
|
this.sessions.delete(sid);
|
|
356
208
|
throw new SessionNotFound(sid);
|
|
357
209
|
}
|
|
358
|
-
// A sidebar-only stub (metadata load) must be upgraded to the full transcript when messages are requested.
|
|
359
210
|
if (!opts.metadataOnly && (cached.loadedMetadataOnly || lags)) {
|
|
360
|
-
const fresh = this.load(sid);
|
|
211
|
+
const fresh = await this.load(sid);
|
|
361
212
|
if (fresh) {
|
|
362
213
|
this.sessions.set(sid, fresh);
|
|
363
214
|
return fresh;
|
|
@@ -366,381 +217,292 @@ export class SessionStore {
|
|
|
366
217
|
return cached;
|
|
367
218
|
}
|
|
368
219
|
}
|
|
369
|
-
const loaded = opts.metadataOnly ? this.loadMetadataOnly(sid) : this.load(sid);
|
|
220
|
+
const loaded = opts.metadataOnly ? await this.loadMetadataOnly(sid) : await this.load(sid);
|
|
370
221
|
if (!loaded)
|
|
371
222
|
throw new SessionNotFound(sid);
|
|
372
223
|
if (opts.cacheOnMiss ?? true)
|
|
373
|
-
this.touch(loaded);
|
|
224
|
+
await this.touch(loaded);
|
|
374
225
|
return loaded;
|
|
375
226
|
}
|
|
376
|
-
|
|
377
|
-
ensureFull(sid, session) {
|
|
227
|
+
async ensureFull(sid, session) {
|
|
378
228
|
if (!session.loadedMetadataOnly)
|
|
379
229
|
return session;
|
|
380
|
-
const full = this.load(sid);
|
|
230
|
+
const full = await this.load(sid);
|
|
381
231
|
if (!full)
|
|
382
232
|
throw new SessionNotFound(sid);
|
|
383
|
-
this.touch(full);
|
|
233
|
+
await this.touch(full);
|
|
384
234
|
return full;
|
|
385
235
|
}
|
|
386
|
-
|
|
387
|
-
cachedLagsDisk(cached) {
|
|
236
|
+
async cachedLagsStorage(cached) {
|
|
388
237
|
if (cached.active_stream_id || cached.pending_user_message || cached.pending_started_at)
|
|
389
238
|
return false;
|
|
390
|
-
|
|
391
|
-
// A session that was persisted and whose file has since vanished was deleted underneath us: it is stale, and the
|
|
392
|
-
// reload's miss evicts it rather than letting a later mutation recreate the deleted sidecar.
|
|
393
|
-
if (current === null)
|
|
394
|
-
return cached.sidecarLoadedSignature !== null;
|
|
395
|
-
// An unknown read identity (the file changed underneath the load) must not be trusted: reload it.
|
|
396
|
-
if (cached.sidecarLoadedSignature === null)
|
|
397
|
-
return true;
|
|
398
|
-
return current !== cached.sidecarLoadedSignature;
|
|
239
|
+
return await this.revision(cached.session_id) !== cached.sidecarLoadedSignature;
|
|
399
240
|
}
|
|
400
|
-
// ── persistence ──────────────────────────────────────────────────────────
|
|
401
241
|
save(session, opts = {}) {
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
|
|
242
|
+
return this.serializeSession(session.session_id, () => this.saveNow(session, opts));
|
|
243
|
+
}
|
|
244
|
+
serializeSession(sid, fn, queue = this.writes) {
|
|
245
|
+
const result = (queue.get(sid) ?? Promise.resolve()).then(fn);
|
|
246
|
+
const settled = result.then(() => { }, () => { });
|
|
247
|
+
queue.set(sid, settled);
|
|
248
|
+
return result.finally(() => { if (queue.get(sid) === settled)
|
|
249
|
+
queue.delete(sid); });
|
|
250
|
+
}
|
|
251
|
+
async saveNow(session, opts) {
|
|
252
|
+
const sid = session.session_id;
|
|
253
|
+
if (!isSafeSessionId(sid))
|
|
254
|
+
throw new Error(`Unsafe session_id ${JSON.stringify(sid)}; refusing to write outside session store`);
|
|
255
|
+
if (session.loadedMetadataOnly)
|
|
256
|
+
throw new Error(`Refusing to save metadata-only session ${JSON.stringify(sid)}: would overwrite messages with []. Reload before mutating state.`);
|
|
409
257
|
const markerCurrent = session.state_db_seen_stamp === session.updated_at;
|
|
410
258
|
if (opts.touchUpdatedAt ?? true)
|
|
411
259
|
session.updated_at = this.deps.now();
|
|
412
260
|
if (markerCurrent)
|
|
413
261
|
session.state_db_seen_stamp = session.updated_at;
|
|
414
|
-
|
|
415
|
-
const
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
catch {
|
|
429
|
-
existingCount = -1;
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
if (existingCount > 0 && incoming === 0 && (session.active_stream_id || session.pending_user_message)) {
|
|
433
|
-
this.deps.log(`[webui] WARNING: refusing to overwrite session ${session.session_id} messages with empty active/pending snapshot (existing=${existingCount}, incoming=${incoming}, stream=${session.active_stream_id ?? ''})`);
|
|
434
|
-
return;
|
|
435
|
-
}
|
|
436
|
-
if (existingCount > incoming) {
|
|
437
|
-
existingText ??= readFileSync(path, 'utf8');
|
|
438
|
-
try {
|
|
439
|
-
writeAtomic(`${path}.bak`, existingText);
|
|
440
|
-
}
|
|
441
|
-
catch { /* backup is best effort */ }
|
|
262
|
+
session.messages = withBackgroundDisplayKinds(session.messages, session);
|
|
263
|
+
const liveRows = session.messages, liveCalls = session.tool_calls, callCount = liveCalls.length;
|
|
264
|
+
const prefix = session.prefixIndex;
|
|
265
|
+
let appendOnly = Boolean(prefix && session.messages.length >= prefix.length && prefix.generation === markedStateDbGeneration(session) && prefix.matchesToolCalls(session.tool_calls));
|
|
266
|
+
const doc = structuredClone(session.toDocument());
|
|
267
|
+
const rows = doc.messages;
|
|
268
|
+
delete doc.messages;
|
|
269
|
+
// One serialization per row serves both the prefix check and the diff; the backend serializes the document once.
|
|
270
|
+
const snapshot = rows.map((row) => JSON.stringify(row));
|
|
271
|
+
if (appendOnly)
|
|
272
|
+
for (let i = 0; i < prefix.length; i += 1)
|
|
273
|
+
if (!prefix.matchesRow(i, snapshot[i])) {
|
|
274
|
+
appendOnly = false;
|
|
275
|
+
break;
|
|
442
276
|
}
|
|
277
|
+
const indexEntry = session.compact();
|
|
278
|
+
const persisted = this.persistedMessages.get(session);
|
|
279
|
+
const previous = persisted && ('rows' in persisted ? persisted.rows.map((row) => JSON.stringify(row)) : persisted.serialized);
|
|
280
|
+
if (previous)
|
|
281
|
+
this.persistedMessages.set(session, { serialized: previous });
|
|
282
|
+
let messages = { kind: 'replace', rows };
|
|
283
|
+
if (previous) {
|
|
284
|
+
let from = 0;
|
|
285
|
+
while (from < previous.length && from < snapshot.length && previous[from] === snapshot[from])
|
|
286
|
+
from += 1;
|
|
287
|
+
if (from === previous.length)
|
|
288
|
+
messages = from === snapshot.length ? { kind: 'unchanged' } : { kind: 'append', rows: rows.slice(from) };
|
|
289
|
+
else if (snapshot.length >= previous.length) {
|
|
290
|
+
let tail = 0;
|
|
291
|
+
while (tail < previous.length - from && tail < snapshot.length - from && previous[previous.length - 1 - tail] === snapshot[snapshot.length - 1 - tail])
|
|
292
|
+
tail += 1;
|
|
293
|
+
messages = { kind: 'splice', from, deleteCount: previous.length - from - tail, rows: rows.slice(from, rows.length - tail) };
|
|
443
294
|
}
|
|
444
295
|
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
if (session.messages.length)
|
|
452
|
-
this.clearDeletedTombstone(session.session_id);
|
|
453
|
-
}
|
|
454
|
-
// ── index ────────────────────────────────────────────────────────────────
|
|
455
|
-
cleanupStaleTmpFiles() {
|
|
456
|
-
const cutoff = this.deps.now() - STALE_TMP_AGE_S;
|
|
457
|
-
try {
|
|
458
|
-
for (const name of readdirSync(this.sessionDir)) {
|
|
459
|
-
if (!name.includes('.tmp.'))
|
|
460
|
-
continue;
|
|
461
|
-
const p = join(this.sessionDir, name);
|
|
462
|
-
try {
|
|
463
|
-
if (statSync(p).mtimeMs / 1000 < cutoff)
|
|
464
|
-
unlinkSync(p);
|
|
465
|
-
}
|
|
466
|
-
catch { /* best effort */ }
|
|
296
|
+
const expected = session.sidecarLoadedSignature;
|
|
297
|
+
if (!rows.length && (session.active_stream_id || session.pending_user_message)) {
|
|
298
|
+
const stored = await this.backend.readDocument(sid, { metadataOnly: true });
|
|
299
|
+
if ((stored?.messageCount ?? 0) > 0) {
|
|
300
|
+
this.deps.log(`[webui] WARNING: refusing to overwrite session ${sid} messages with empty active/pending snapshot`);
|
|
301
|
+
return;
|
|
467
302
|
}
|
|
468
303
|
}
|
|
469
|
-
catch { /* dir may not exist */ }
|
|
470
|
-
}
|
|
471
|
-
invalidatePersistedIds() {
|
|
472
|
-
this.persistedIdsCache = null;
|
|
473
|
-
}
|
|
474
|
-
persistedIds() {
|
|
475
|
-
let mtimeNs = null;
|
|
476
304
|
try {
|
|
477
|
-
|
|
305
|
+
session.sidecarLoadedSignature = await this.backend.write(sid, { doc, messages, all: rows }, expected);
|
|
478
306
|
}
|
|
479
|
-
catch {
|
|
480
|
-
|
|
307
|
+
catch (error) {
|
|
308
|
+
if (error instanceof RevisionConflict) {
|
|
309
|
+
this.sessions.delete(sid);
|
|
310
|
+
const fresh = await this.load(sid, { repairDuplicates: false });
|
|
311
|
+
if (fresh)
|
|
312
|
+
this.sessions.set(sid, fresh);
|
|
313
|
+
}
|
|
314
|
+
throw error;
|
|
481
315
|
}
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
try {
|
|
486
|
-
for (const name of readdirSync(this.sessionDir))
|
|
487
|
-
if (name.endsWith('.json') && !name.startsWith('_'))
|
|
488
|
-
ids.add(name.slice(0, -5));
|
|
316
|
+
this.persistedMessages.set(session, { serialized: snapshot });
|
|
317
|
+
if (appendOnly && session.messages === liveRows && liveRows.length === rows.length && session.tool_calls === liveCalls && liveCalls.length === callCount) {
|
|
318
|
+
prefix.savedAppend(liveRows, session.sidecarLoadedSignature, liveCalls);
|
|
489
319
|
}
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
320
|
+
else
|
|
321
|
+
delete session.prefixIndex;
|
|
322
|
+
// The document is committed; the batched index flush must not delay the caller (the turn's `done`).
|
|
323
|
+
if (!(opts.skipIndex ?? false))
|
|
324
|
+
void this.queueIndexUpdate([indexEntry]);
|
|
325
|
+
if (rows.length)
|
|
326
|
+
await this.clearDeletedTombstone(sid);
|
|
327
|
+
}
|
|
328
|
+
async searchMessages(sids, terms, depth) {
|
|
329
|
+
const matches = new Map();
|
|
330
|
+
const remaining = [];
|
|
331
|
+
for (const sid of sids) {
|
|
332
|
+
const cached = this.sessions.get(sid);
|
|
333
|
+
if (!cached || cached.loadedMetadataOnly || await this.cachedLagsStorage(cached)) {
|
|
334
|
+
remaining.push(sid);
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
const rows = depth ? cached.messages.slice(0, depth) : cached.messages;
|
|
338
|
+
const idx = rows.findIndex((row) => sessionSearchMatches(sessionSearchMessageText(row), terms));
|
|
339
|
+
if (idx >= 0)
|
|
340
|
+
matches.set(sid, { idx, text: sessionSearchMessageText(rows[idx]) });
|
|
341
|
+
}
|
|
342
|
+
for (const [sid, match] of await this.backend.searchMessages(remaining, terms, depth))
|
|
343
|
+
matches.set(sid, match);
|
|
344
|
+
return matches;
|
|
345
|
+
}
|
|
346
|
+
async persistedIds(opts = {}) { return this.backend.ids(opts); }
|
|
347
|
+
async hasPersistedSessionFiles() { return (await this.persistedIds()).size > 0; }
|
|
348
|
+
async readIndexEntries() { return (await this.index()).entries; }
|
|
349
|
+
async indexMessageCounts(entries) {
|
|
514
350
|
let rows = entries;
|
|
515
351
|
if (!rows) {
|
|
516
352
|
try {
|
|
517
|
-
rows =
|
|
353
|
+
rows = await this.readIndexEntries();
|
|
518
354
|
}
|
|
519
355
|
catch {
|
|
520
356
|
rows = [];
|
|
521
357
|
}
|
|
522
358
|
}
|
|
359
|
+
const out = new Map();
|
|
523
360
|
for (const row of rows) {
|
|
524
|
-
const sid = str(row.session_id);
|
|
525
|
-
const n = Number(row.message_count);
|
|
361
|
+
const sid = str(row.session_id), n = Number(row.message_count);
|
|
526
362
|
if (sid && Number.isInteger(n) && n >= 0)
|
|
527
363
|
out.set(sid, n);
|
|
528
364
|
}
|
|
529
365
|
return out;
|
|
530
366
|
}
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
this.parsedIndexCache = { signature, entries };
|
|
536
|
-
}
|
|
537
|
-
loadSessionFromPath(path) {
|
|
538
|
-
try {
|
|
539
|
-
const data = sanitizeSessionRow(JSON.parse(readFileSync(path, 'utf8')), this, basename(path));
|
|
540
|
-
if (!data)
|
|
541
|
-
return null;
|
|
542
|
-
const [messages] = collapseAdjacentDuplicatePartials(data.messages);
|
|
543
|
-
data.messages = messages;
|
|
544
|
-
return this.construct(data, data.profile ?? null);
|
|
545
|
-
}
|
|
546
|
-
catch {
|
|
547
|
-
return null;
|
|
548
|
-
}
|
|
367
|
+
async serializeIndex(fn) {
|
|
368
|
+
const pending = this.indexWriter.then(fn, fn);
|
|
369
|
+
this.indexWriter = pending.catch(() => { });
|
|
370
|
+
return pending;
|
|
549
371
|
}
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
if (!name.endsWith('.json') || name.startsWith('_'))
|
|
560
|
-
continue;
|
|
561
|
-
const s = this.loadSessionFromPath(join(this.sessionDir, name));
|
|
562
|
-
if (!s)
|
|
563
|
-
continue;
|
|
564
|
-
const c = s.compact();
|
|
565
|
-
const sid = str(c.session_id);
|
|
566
|
-
if (!sid)
|
|
567
|
-
continue;
|
|
568
|
-
const existing = entryMap.get(sid);
|
|
569
|
-
if (!existing || Number(c.message_count ?? 0) > Number(existing.message_count ?? 0))
|
|
570
|
-
entryMap.set(sid, c);
|
|
372
|
+
async rebuildIndexNow(opts = {}) {
|
|
373
|
+
const map = new Map();
|
|
374
|
+
for (const sid of await this.persistedIds()) {
|
|
375
|
+
try {
|
|
376
|
+
const session = await this.load(sid, { drafts: false, repairDuplicates: false });
|
|
377
|
+
if (session)
|
|
378
|
+
map.set(session.session_id, session.compact());
|
|
379
|
+
}
|
|
380
|
+
catch { /* corrupt sessions are omitted */ }
|
|
571
381
|
}
|
|
572
|
-
const entries = [...entryMap.values()];
|
|
573
382
|
if (!opts.diskOnly)
|
|
574
383
|
for (const s of this.sessions.values())
|
|
575
|
-
if (!
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
updatedMap.set(update.session_id, update.compact());
|
|
595
|
-
else if (typeof update.session_id === 'string' && update.session_id)
|
|
596
|
-
updatedMap.set(update.session_id, update);
|
|
384
|
+
if (!map.has(s.session_id))
|
|
385
|
+
map.set(s.session_id, s.compact());
|
|
386
|
+
await this.backend.writeIndex([...map.values()].sort((a, b) => Number(b.updated_at ?? 0) - Number(a.updated_at ?? 0)));
|
|
387
|
+
}
|
|
388
|
+
async rebuildIndex(opts = {}) { await this.serializeIndex(async () => { await this.rebuildIndexNow(opts); }); }
|
|
389
|
+
async writeIndex(updates) {
|
|
390
|
+
const snapshots = updates?.map((s) => s instanceof Session ? s.compact() : s);
|
|
391
|
+
await this.serializeIndex(async () => {
|
|
392
|
+
if (!snapshots || !await this.backend.hasIndex()) {
|
|
393
|
+
await this.rebuildIndexNow();
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
let rows;
|
|
397
|
+
try {
|
|
398
|
+
rows = (await this.backend.index()).entries;
|
|
399
|
+
}
|
|
400
|
+
catch {
|
|
401
|
+
await this.rebuildIndexNow();
|
|
402
|
+
return;
|
|
597
403
|
}
|
|
598
|
-
const
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
404
|
+
const ids = await this.persistedIds();
|
|
405
|
+
const live = (sid) => ids.has(sid) || this.sessions.has(sid);
|
|
406
|
+
const kept = rows.filter((r) => live(str(r.session_id)));
|
|
407
|
+
// Only the pruned and upserted entries can differ, so compare those instead of serializing the whole index.
|
|
408
|
+
let changed = kept.length !== rows.length;
|
|
409
|
+
rows = kept;
|
|
410
|
+
const order = rows.map((r) => str(r.session_id));
|
|
411
|
+
const positions = new Map(rows.map((r, i) => [str(r.session_id), i]));
|
|
412
|
+
for (const row of snapshots) {
|
|
413
|
+
const sid = str(row.session_id);
|
|
414
|
+
// A queued row can outlive its session (deleted while a failed batch waited for a retry).
|
|
415
|
+
if (!sid || !live(sid))
|
|
416
|
+
continue;
|
|
417
|
+
const i = positions.get(sid);
|
|
418
|
+
if (i === undefined) {
|
|
419
|
+
positions.set(sid, rows.length);
|
|
420
|
+
rows.push(row);
|
|
607
421
|
changed = true;
|
|
608
422
|
}
|
|
609
|
-
else
|
|
610
|
-
|
|
611
|
-
|
|
423
|
+
else {
|
|
424
|
+
changed ||= JSON.stringify(rows[i]) !== JSON.stringify(row);
|
|
425
|
+
rows[i] = row;
|
|
612
426
|
}
|
|
613
427
|
}
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
if (
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
428
|
+
rows.sort((a, b) => Number(b.updated_at ?? 0) - Number(a.updated_at ?? 0));
|
|
429
|
+
changed ||= rows.some((r, i) => str(r.session_id) !== order[i]);
|
|
430
|
+
if (changed)
|
|
431
|
+
await this.backend.writeIndex(rows);
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
queueIndexUpdate(updates) {
|
|
435
|
+
for (const update of updates) {
|
|
436
|
+
const row = update instanceof Session ? update.compact() : update;
|
|
437
|
+
const sid = str(row.session_id);
|
|
438
|
+
if (sid)
|
|
439
|
+
this.indexPending.set(sid, row);
|
|
624
440
|
}
|
|
441
|
+
this.indexFlush ??= Promise.resolve().then(async () => {
|
|
442
|
+
try {
|
|
443
|
+
while (this.indexPending.size) {
|
|
444
|
+
const batch = new Map(this.indexPending);
|
|
445
|
+
this.indexPending.clear();
|
|
446
|
+
try {
|
|
447
|
+
await this.writeIndex([...batch.values()]);
|
|
448
|
+
this.indexFailure = null;
|
|
449
|
+
}
|
|
450
|
+
catch (error) {
|
|
451
|
+
// Nobody awaits the flush, so a failed batch stays queued for the next save or index read instead of being lost.
|
|
452
|
+
for (const [sid, row] of batch)
|
|
453
|
+
if (!this.indexPending.has(sid))
|
|
454
|
+
this.indexPending.set(sid, row);
|
|
455
|
+
this.indexFailure = error instanceof Error ? error : new Error(String(error));
|
|
456
|
+
this.deps.log(`[webui] WARNING: session index update failed: ${this.indexFailure.message}`);
|
|
457
|
+
break;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
finally {
|
|
462
|
+
this.indexFlush = null;
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
return this.indexFlush;
|
|
625
466
|
}
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
this.indexPending.set(s.session_id, s.compact());
|
|
630
|
-
this.flushIndexNow();
|
|
631
|
-
}
|
|
632
|
-
flushIndexNow() {
|
|
633
|
-
const pending = [...this.indexPending.values()];
|
|
634
|
-
this.indexPending.clear();
|
|
635
|
-
if (pending.length)
|
|
636
|
-
this.writeIndex(pending);
|
|
637
|
-
}
|
|
638
|
-
pruneFromIndex(sid) {
|
|
639
|
-
if (!sid || !existsSync(this.indexFile))
|
|
640
|
-
return;
|
|
641
|
-
try {
|
|
642
|
-
const existing = JSON.parse(readFileSync(this.indexFile, 'utf8'));
|
|
643
|
-
if (!Array.isArray(existing))
|
|
644
|
-
throw new Error('session index must be a list');
|
|
645
|
-
const pruned = existing.filter((e) => e.session_id !== sid);
|
|
646
|
-
if (pruned.length === existing.length)
|
|
467
|
+
async pruneFromIndex(sid) {
|
|
468
|
+
await this.serializeIndex(async () => {
|
|
469
|
+
if (!sid || !await this.backend.hasIndex())
|
|
647
470
|
return;
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
loadDeletedTombstone() {
|
|
659
|
-
try {
|
|
660
|
-
if (!existsSync(this.deletedTombstoneFile))
|
|
661
|
-
return new Set();
|
|
662
|
-
const raw = JSON.parse(readFileSync(this.deletedTombstoneFile, 'utf8'));
|
|
663
|
-
if (!raw || typeof raw !== 'object' || Number(raw.version) !== DELETED_TOMBSTONE_VERSION || !Array.isArray(raw.ids))
|
|
664
|
-
return new Set();
|
|
665
|
-
return new Set(raw.ids.map((v) => String(v ?? '').trim()).filter(Boolean));
|
|
666
|
-
}
|
|
667
|
-
catch {
|
|
668
|
-
return new Set();
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
saveDeletedTombstone(ids) {
|
|
672
|
-
let sorted = [...ids].sort();
|
|
673
|
-
if (sorted.length > DELETED_TOMBSTONE_CAP)
|
|
674
|
-
sorted = sorted.slice(-DELETED_TOMBSTONE_CAP);
|
|
675
|
-
try {
|
|
676
|
-
mkdirSync(this.sessionDir, { recursive: true });
|
|
677
|
-
writeAtomic(this.deletedTombstoneFile, JSON.stringify({ version: DELETED_TOMBSTONE_VERSION, ids: sorted }, null, 2));
|
|
678
|
-
}
|
|
679
|
-
catch { /* best effort */ }
|
|
680
|
-
}
|
|
681
|
-
recordDeletedTombstone(sid) {
|
|
682
|
-
const ids = this.loadDeletedTombstone();
|
|
683
|
-
if (ids.has(sid))
|
|
684
|
-
return;
|
|
685
|
-
ids.add(sid);
|
|
686
|
-
this.saveDeletedTombstone(ids);
|
|
687
|
-
}
|
|
688
|
-
clearDeletedTombstone(sid) {
|
|
689
|
-
const ids = this.loadDeletedTombstone();
|
|
690
|
-
if (!ids.has(sid))
|
|
691
|
-
return;
|
|
692
|
-
ids.delete(sid);
|
|
693
|
-
if (ids.size)
|
|
694
|
-
this.saveDeletedTombstone(ids);
|
|
695
|
-
else
|
|
696
|
-
rmSync(this.deletedTombstoneFile, { force: true });
|
|
697
|
-
}
|
|
698
|
-
/** The index marked this id as a deleted WebUI session (Python `_marks_deleted_webui_session`, tombstone half). */
|
|
699
|
-
wasDeleted(sid) {
|
|
700
|
-
return this.loadDeletedTombstone().has(sid);
|
|
701
|
-
}
|
|
702
|
-
// ── eviction ─────────────────────────────────────────────────────────────
|
|
703
|
-
persistedMessageCount(sid) {
|
|
704
|
-
const path = this.pathFor(sid);
|
|
705
|
-
if (!existsSync(path))
|
|
706
|
-
return null;
|
|
707
|
-
const count = readPersistedMessageCount(path);
|
|
708
|
-
if (count !== null)
|
|
709
|
-
return count;
|
|
710
|
-
try {
|
|
711
|
-
const data = JSON.parse(readFileSync(path, 'utf8'));
|
|
712
|
-
return Array.isArray(data.messages) ? data.messages.length : 0;
|
|
713
|
-
}
|
|
714
|
-
catch {
|
|
715
|
-
return null;
|
|
716
|
-
}
|
|
471
|
+
try {
|
|
472
|
+
const rows = (await this.backend.index()).entries;
|
|
473
|
+
const pruned = rows.filter((r) => r.session_id !== sid);
|
|
474
|
+
if (pruned.length !== rows.length)
|
|
475
|
+
await this.backend.writeIndex(pruned);
|
|
476
|
+
}
|
|
477
|
+
catch {
|
|
478
|
+
await this.rebuildIndexNow();
|
|
479
|
+
}
|
|
480
|
+
});
|
|
717
481
|
}
|
|
718
|
-
|
|
719
|
-
|
|
482
|
+
async loadDeletedTombstone() { return this.backend.tombstones.all(); }
|
|
483
|
+
async recordDeletedTombstone(sid) { return this.backend.tombstones.add(sid); }
|
|
484
|
+
async clearDeletedTombstone(sid) { return this.backend.tombstones.remove(sid); }
|
|
485
|
+
async wasDeleted(sid) { return this.backend.tombstones.has(sid); }
|
|
486
|
+
async isEvictable(s) {
|
|
720
487
|
if (!s)
|
|
721
488
|
return true;
|
|
722
|
-
if (s.active_stream_id || s.pending_user_message || s.pending_started_at)
|
|
723
|
-
return false;
|
|
724
|
-
if (!s.session_id)
|
|
489
|
+
if (s.active_stream_id || s.pending_user_message || s.pending_started_at || !s.session_id)
|
|
725
490
|
return false;
|
|
726
491
|
if (s.loadedMetadataOnly)
|
|
727
492
|
return true;
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
if (existsSync(this.pathFor(s.session_id)))
|
|
493
|
+
let count = null;
|
|
494
|
+
try {
|
|
495
|
+
count = (await this.backend.readDocument(s.session_id, { metadataOnly: true }))?.messageCount ?? null;
|
|
496
|
+
}
|
|
497
|
+
catch { /* corrupt */ }
|
|
498
|
+
if (count === null) {
|
|
499
|
+
if (s.messages.length || Object.keys(s.composer_draft).length || await this.exists(s.session_id))
|
|
736
500
|
return false;
|
|
737
501
|
return this.deps.now() - s.created_at > UNSAVED_SHELL_GRACE_S;
|
|
738
502
|
}
|
|
739
|
-
|
|
740
|
-
return true;
|
|
741
|
-
return diskCount >= inMemory;
|
|
503
|
+
return count >= s.messages.length;
|
|
742
504
|
}
|
|
743
|
-
evictOverCap(cap) {
|
|
505
|
+
async evictOverCap(cap) {
|
|
744
506
|
let limit = cap ?? this.deps.cacheMax();
|
|
745
507
|
if (!Number.isInteger(limit) || limit < 1)
|
|
746
508
|
limit = 100;
|
|
@@ -748,63 +510,35 @@ export class SessionStore {
|
|
|
748
510
|
for (const sid of [...this.sessions.keys()]) {
|
|
749
511
|
if (this.sessions.size <= limit)
|
|
750
512
|
break;
|
|
751
|
-
|
|
513
|
+
const session = this.sessions.get(sid);
|
|
514
|
+
if (await this.isEvictable(session) && this.sessions.get(sid) === session && !session?.active_stream_id && !session?.pending_user_message && !session?.pending_started_at) {
|
|
752
515
|
this.sessions.delete(sid);
|
|
753
516
|
evicted += 1;
|
|
754
517
|
}
|
|
755
518
|
}
|
|
756
519
|
return evicted;
|
|
757
520
|
}
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
}
|
|
775
|
-
catch { /* ignore */ }
|
|
776
|
-
try {
|
|
777
|
-
rmSync(`${path}.bak`, { force: true });
|
|
778
|
-
}
|
|
779
|
-
catch { /* ignore */ }
|
|
780
|
-
try {
|
|
781
|
-
this.deps.drafts.delete(sid);
|
|
782
|
-
}
|
|
783
|
-
catch { /* ignore */ }
|
|
784
|
-
// TAL-372: the session's background work records (`BackgroundTaskStore`) go with it.
|
|
785
|
-
try {
|
|
786
|
-
rmSync(join(this.sessionDir, '_background', `${sid}.json`), { force: true });
|
|
787
|
-
}
|
|
788
|
-
catch { /* ignore */ }
|
|
789
|
-
this.deps.onDeleted?.(sid);
|
|
790
|
-
if (opts.tombstone ?? true)
|
|
791
|
-
this.recordDeletedTombstone(sid);
|
|
792
|
-
return true;
|
|
521
|
+
delete(sid, opts = {}) {
|
|
522
|
+
return this.serializeSession(sid, async () => {
|
|
523
|
+
if (!await this.backend.delete(sid, { tombstone: opts.tombstone ?? true }))
|
|
524
|
+
return false;
|
|
525
|
+
this.sessions.delete(sid);
|
|
526
|
+
try {
|
|
527
|
+
await this.pruneFromIndex(sid);
|
|
528
|
+
}
|
|
529
|
+
catch { /* ignore */ }
|
|
530
|
+
try {
|
|
531
|
+
(await this.deps.drafts.delete(sid));
|
|
532
|
+
}
|
|
533
|
+
catch { /* ignore */ }
|
|
534
|
+
await this.deps.onDeleted?.(sid);
|
|
535
|
+
return true;
|
|
536
|
+
});
|
|
793
537
|
}
|
|
794
|
-
|
|
795
|
-
scanAll() {
|
|
538
|
+
async scanAll() {
|
|
796
539
|
const out = [];
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
names = readdirSync(this.sessionDir);
|
|
800
|
-
}
|
|
801
|
-
catch {
|
|
802
|
-
return out;
|
|
803
|
-
}
|
|
804
|
-
for (const name of names) {
|
|
805
|
-
if (!name.endsWith('.json') || name.startsWith('_'))
|
|
806
|
-
continue;
|
|
807
|
-
const s = this.load(name.slice(0, -5));
|
|
540
|
+
for (const sid of await this.persistedIds()) {
|
|
541
|
+
const s = await this.load(sid);
|
|
808
542
|
if (s)
|
|
809
543
|
out.push(s);
|
|
810
544
|
}
|