@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/list.js
CHANGED
|
@@ -10,54 +10,12 @@ import { createHash } from 'node:crypto';
|
|
|
10
10
|
import { redactText } from '../redact.js';
|
|
11
11
|
import { CONTEXT_USAGE_FIELDS, Session, contextUsage, sharePath, stripSidebarHeavyMetadata } from './session.js';
|
|
12
12
|
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
13
|
-
import { isCliSessionRow as isStateDbCliRow, isCliSessionRowVisible, normalizeAgentSessionSource } from './state-db.js';
|
|
13
|
+
import { AGENT_STORAGE_OK, CANONICAL_READ_ONLY_REASON, OWNERSHIP_UNAVAILABLE_REASON, isCliSessionRow as isStateDbCliRow, isCliSessionRowVisible, normalizeAgentSessionSource } from './state-db.js';
|
|
14
14
|
import { MESSAGING_SOURCES, sourceKind } from './source-kind.js';
|
|
15
|
-
import {
|
|
15
|
+
import {} from '@maudecode/talaria-web-contracts';
|
|
16
16
|
const num = (v) => { const n = Number(v ?? 0); return Number.isFinite(n) && n > 0 ? n : 0; };
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
export function sanitizeSessionRow(value, store, file) {
|
|
20
|
-
const row = value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
21
|
-
file ??= `${str(row.session_id)}.json`;
|
|
22
|
-
const mismatchedFile = file.endsWith('.json') && file !== '_index.json' && row.session_id !== file.slice(0, -5);
|
|
23
|
-
if (!SessionRowSchema.shape.session_id.safeParse(row.session_id).success || mismatchedFile) {
|
|
24
|
-
const logged = malformedFiles.get(store) ?? new Set();
|
|
25
|
-
if (!logged.has(file)) {
|
|
26
|
-
store.deps.log(`[webui] WARNING: skipping session row with invalid session_id in ${JSON.stringify(file)}`);
|
|
27
|
-
logged.add(file);
|
|
28
|
-
malformedFiles.set(store, logged);
|
|
29
|
-
}
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
const result = { ...row, title: row.title ?? '' };
|
|
33
|
-
for (const [key, schema] of Object.entries(SessionRowSchema.shape)) {
|
|
34
|
-
const value = result[key];
|
|
35
|
-
if (value === undefined || schema.safeParse(value).success)
|
|
36
|
-
continue;
|
|
37
|
-
const coerced = typeof value === 'string' && value.trim() !== ''
|
|
38
|
-
? value.trim() === 'true' ? true : value.trim() === 'false' ? false : Number(value)
|
|
39
|
-
: typeof value === 'number' || typeof value === 'boolean' ? String(value) : undefined;
|
|
40
|
-
const boolean = value === 0 || value === 1 ? value === 1 : coerced === 0 || coerced === 1 ? coerced === 1 : undefined;
|
|
41
|
-
if (coerced !== undefined && schema.safeParse(coerced).success)
|
|
42
|
-
result[key] = coerced;
|
|
43
|
-
else if (boolean !== undefined && schema.safeParse(boolean).success)
|
|
44
|
-
result[key] = boolean;
|
|
45
|
-
else if (key === 'title')
|
|
46
|
-
result[key] = '';
|
|
47
|
-
// Invalid persisted permissions must not turn a locked session into an editable one.
|
|
48
|
-
else if (key === 'read_only')
|
|
49
|
-
result[key] = true;
|
|
50
|
-
else
|
|
51
|
-
Reflect.deleteProperty(result, key);
|
|
52
|
-
}
|
|
53
|
-
// These persisted flags affect list filtering before the wire flags are computed.
|
|
54
|
-
for (const key of ['pre_compression_snapshot', 'default_hidden', 'has_pending_user_message']) {
|
|
55
|
-
if (result[key] === 'true' || result[key] === 'false')
|
|
56
|
-
result[key] = result[key] === 'true';
|
|
57
|
-
}
|
|
58
|
-
return result;
|
|
59
|
-
}
|
|
60
|
-
/** TAL-306: the row's `sort_ts`, the time it sorts and date-buckets by on every client. */
|
|
17
|
+
import { sanitizeSessionRow } from './storage/row.js';
|
|
18
|
+
export { sanitizeSessionRow } from './storage/row.js';
|
|
61
19
|
export function sessionSortTimestamp(row) {
|
|
62
20
|
return num(row.last_message_at) || num(row.updated_at) || num(row.created_at);
|
|
63
21
|
}
|
|
@@ -205,10 +163,12 @@ function isEmptyUntitledDraft(row) {
|
|
|
205
163
|
return str(row.title || 'Untitled') === 'Untitled' && Math.trunc(Number(row.message_count ?? 0)) === 0 && !row.active_stream_id && !row.has_pending_user_message && !row.worktree_path;
|
|
206
164
|
}
|
|
207
165
|
/** Python `all_sessions` without the state.db lineage overlay. */
|
|
208
|
-
export function allSessions(store, opts = {}) {
|
|
166
|
+
export async function allSessions(store, opts = {}) {
|
|
209
167
|
const activeStreamIds = store.deps.activeStreamIds();
|
|
168
|
+
// Only reuse this read's validated objects; replacements still need validation.
|
|
169
|
+
const sanitizedRows = new WeakSet();
|
|
210
170
|
const finish = (result) => {
|
|
211
|
-
result = result.flatMap((row) => { const clean = sanitizeSessionRow(row, store); return clean ? [clean] : []; });
|
|
171
|
+
result = result.flatMap((row) => { const clean = sanitizedRows.has(row) ? row : sanitizeSessionRow(row, store); return clean ? [clean] : []; });
|
|
212
172
|
result = preferFullerSnapshots(result);
|
|
213
173
|
const candidates = result;
|
|
214
174
|
const visible = candidates.filter((r) => !hideFromDefaultSidebar(r));
|
|
@@ -228,43 +188,44 @@ export function allSessions(store, opts = {}) {
|
|
|
228
188
|
}
|
|
229
189
|
return rows.sort(compareSessionRows);
|
|
230
190
|
};
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
}
|
|
234
|
-
catch {
|
|
235
|
-
return false;
|
|
236
|
-
} })();
|
|
237
|
-
if (!indexExists) {
|
|
191
|
+
try {
|
|
192
|
+
let entries;
|
|
238
193
|
try {
|
|
239
|
-
store.
|
|
194
|
+
entries = await store.readIndexEntries();
|
|
240
195
|
}
|
|
241
|
-
catch {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
196
|
+
catch {
|
|
197
|
+
try {
|
|
198
|
+
await store.writeIndex();
|
|
199
|
+
}
|
|
200
|
+
catch { /* retry the index before falling back to the scan */ }
|
|
201
|
+
entries = await store.readIndexEntries();
|
|
202
|
+
}
|
|
203
|
+
let index = entries.flatMap((row) => {
|
|
204
|
+
const clean = sanitizeSessionRow(row, store, 'index');
|
|
205
|
+
if (clean)
|
|
206
|
+
sanitizedRows.add(clean);
|
|
246
207
|
return clean ? [clean] : [];
|
|
247
208
|
});
|
|
248
209
|
const inMemory = new Set(store.sessions.keys());
|
|
249
|
-
const persisted = store.persistedIds();
|
|
250
|
-
if (!index.length && store.hasPersistedSessionFiles())
|
|
210
|
+
const persisted = (await store.persistedIds());
|
|
211
|
+
if (!index.length && (await store.hasPersistedSessionFiles()))
|
|
251
212
|
throw new Error('empty session index while session files exist');
|
|
252
213
|
index = index.filter((r) => inMemory.has(str(r.session_id)) || persisted.has(str(r.session_id)));
|
|
253
|
-
if (!index.length && store.hasPersistedSessionFiles())
|
|
214
|
+
if (!index.length && (await store.hasPersistedSessionFiles()))
|
|
254
215
|
throw new Error('session index has no live rows while session files exist');
|
|
255
216
|
const backfilled = [];
|
|
256
|
-
index = index.map((r) => {
|
|
217
|
+
index = await Promise.all(index.map(async (r) => {
|
|
257
218
|
if ('last_message_at' in r)
|
|
258
219
|
return r;
|
|
259
|
-
const full = store.load(str(r.session_id));
|
|
220
|
+
const full = (await store.load(str(r.session_id)));
|
|
260
221
|
if (!full)
|
|
261
222
|
return r;
|
|
262
223
|
backfilled.push(full);
|
|
263
224
|
return full.compact({ sidebarMetadataOnly: opts.sidebarMetadataOnly ?? false });
|
|
264
|
-
});
|
|
225
|
+
}));
|
|
265
226
|
if (backfilled.length) {
|
|
266
227
|
try {
|
|
267
|
-
store.writeIndex(backfilled);
|
|
228
|
+
(await store.writeIndex(backfilled));
|
|
268
229
|
}
|
|
269
230
|
catch { /* ignore */ }
|
|
270
231
|
}
|
|
@@ -276,7 +237,7 @@ export function allSessions(store, opts = {}) {
|
|
|
276
237
|
const missing = [...persisted].filter((sid) => !indexMap.has(sid)).sort();
|
|
277
238
|
const recovered = [];
|
|
278
239
|
for (const sid of missing) {
|
|
279
|
-
const sidecar = store.loadMetadataOnly(sid);
|
|
240
|
+
const sidecar = (await store.loadMetadataOnly(sid));
|
|
280
241
|
if (!sidecar)
|
|
281
242
|
continue;
|
|
282
243
|
indexMap.set(sidecar.session_id, sidecar.compact({ includeRuntime: true, activeStreamIds, sidebarMetadataOnly: opts.sidebarMetadataOnly ?? false }));
|
|
@@ -284,12 +245,12 @@ export function allSessions(store, opts = {}) {
|
|
|
284
245
|
}
|
|
285
246
|
if (recovered.length) {
|
|
286
247
|
try {
|
|
287
|
-
store.writeIndex(recovered);
|
|
248
|
+
(await store.writeIndex(recovered));
|
|
288
249
|
}
|
|
289
250
|
catch { /* ignore */ }
|
|
290
251
|
}
|
|
291
|
-
const indexCounts = store.indexMessageCounts(index);
|
|
292
|
-
const refreshed = refreshIndexRowsFromSidecarMetadata(store, [...indexMap.values()], indexCounts, activeStreamIds);
|
|
252
|
+
const indexCounts = (await store.indexMessageCounts(index));
|
|
253
|
+
const refreshed = (await refreshIndexRowsFromSidecarMetadata(store, [...indexMap.values()], indexCounts, activeStreamIds));
|
|
293
254
|
let result = refreshed.filter((r) => r.session_id);
|
|
294
255
|
result = result.filter((r) => !isEmptyUntitledDraft(r));
|
|
295
256
|
return finish(result);
|
|
@@ -297,7 +258,7 @@ export function allSessions(store, opts = {}) {
|
|
|
297
258
|
catch {
|
|
298
259
|
/* fall back to the full scan */
|
|
299
260
|
}
|
|
300
|
-
const out = store.scanAll();
|
|
261
|
+
const out = (await store.scanAll());
|
|
301
262
|
for (const s of store.sessions.values())
|
|
302
263
|
if (!out.some((x) => x.session_id === s.session_id))
|
|
303
264
|
out.push(s);
|
|
@@ -306,22 +267,14 @@ export function allSessions(store, opts = {}) {
|
|
|
306
267
|
.map((s) => s.compact({ includeRuntime: true, activeStreamIds, sidebarMetadataOnly: opts.sidebarMetadataOnly ?? false }));
|
|
307
268
|
return finish(rows);
|
|
308
269
|
}
|
|
309
|
-
function sidecarMtimeAfterIndexTimestamp(store, row) {
|
|
270
|
+
async function sidecarMtimeAfterIndexTimestamp(store, row) {
|
|
310
271
|
const sid = str(row.session_id);
|
|
311
272
|
if (!sid)
|
|
312
273
|
return false;
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
return mtime > sessionSortTimestamp(row) + 0.001;
|
|
316
|
-
}
|
|
317
|
-
catch {
|
|
318
|
-
return false;
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
function statSyncMtime(path) {
|
|
322
|
-
return statSync(path).mtimeMs / 1000;
|
|
274
|
+
// A backend revision is opaque; refresh legacy rows whenever persisted data exists.
|
|
275
|
+
return await store.revision(sid) !== null;
|
|
323
276
|
}
|
|
324
|
-
function rowMayNeedSidecarRefresh(store, row, staleSnapshotIds) {
|
|
277
|
+
async function rowMayNeedSidecarRefresh(store, row, staleSnapshotIds) {
|
|
325
278
|
if (hasLiveState(row))
|
|
326
279
|
return true;
|
|
327
280
|
const sid = str(row.session_id);
|
|
@@ -332,15 +285,15 @@ function rowMayNeedSidecarRefresh(store, row, staleSnapshotIds) {
|
|
|
332
285
|
return true;
|
|
333
286
|
const lineageShaped = Boolean(row.parent_session_id || row._lineage_root_id || row._compression_segment_count);
|
|
334
287
|
const needsMtime = Boolean(sid) && (looksLikeStaleZeroMessageRow(row) || (lineageShaped && (row.user_message_count === null || row.user_message_count === undefined)));
|
|
335
|
-
return needsMtime && sidecarMtimeAfterIndexTimestamp(store, row);
|
|
288
|
+
return needsMtime && await sidecarMtimeAfterIndexTimestamp(store, row);
|
|
336
289
|
}
|
|
337
|
-
if (sid && looksLikeStaleZeroMessageRow(row) && str(row.session_source).trim().toLowerCase() !== 'fork' && sidecarMtimeAfterIndexTimestamp(store, row))
|
|
290
|
+
if (sid && looksLikeStaleZeroMessageRow(row) && str(row.session_source).trim().toLowerCase() !== 'fork' && await sidecarMtimeAfterIndexTimestamp(store, row))
|
|
338
291
|
return true;
|
|
339
292
|
if (row.message_count === null || row.message_count === undefined || row.last_message_at === null || row.last_message_at === undefined)
|
|
340
293
|
return true;
|
|
341
294
|
return Boolean(sid) && staleSnapshotIds.has(sid);
|
|
342
295
|
}
|
|
343
|
-
function staleSnapshotRefreshIds(store, rows) {
|
|
296
|
+
async function staleSnapshotRefreshIds(store, rows) {
|
|
344
297
|
const byId = new Map(rows.filter((r) => r.session_id).map((r) => [str(r.session_id), r]));
|
|
345
298
|
const groups = new Map();
|
|
346
299
|
for (const row of rows) {
|
|
@@ -364,23 +317,23 @@ function staleSnapshotRefreshIds(store, rows) {
|
|
|
364
317
|
continue;
|
|
365
318
|
if (snapshot.user_message_count !== null && snapshot.user_message_count !== undefined && Math.trunc(Number(snapshot.message_count ?? 0)) > 0 && snapshot.last_message_at !== null && snapshot.last_message_at !== undefined)
|
|
366
319
|
continue;
|
|
367
|
-
if (sidecarMtimeAfterIndexTimestamp(store, snapshot))
|
|
320
|
+
if (await sidecarMtimeAfterIndexTimestamp(store, snapshot))
|
|
368
321
|
ids.add(sid);
|
|
369
322
|
}
|
|
370
323
|
}
|
|
371
324
|
return ids;
|
|
372
325
|
}
|
|
373
326
|
const REFRESH_KEYS = ['message_count', 'updated_at', 'last_message_at', 'title', 'workspace', 'model', 'model_provider', 'created_at', 'pinned', 'archived', 'project_id', 'profile', 'pre_compression_snapshot', 'parent_session_id', 'source_tag', 'raw_source', 'session_source', 'source_label', 'active_stream_id', 'has_pending_user_message', 'pending_user_message', 'pending_started_at'];
|
|
374
|
-
function refreshIndexRowsFromSidecarMetadata(store, rows, indexCounts, activeStreamIds) {
|
|
375
|
-
const stale = staleSnapshotRefreshIds(store, rows);
|
|
327
|
+
async function refreshIndexRowsFromSidecarMetadata(store, rows, indexCounts, activeStreamIds) {
|
|
328
|
+
const stale = await staleSnapshotRefreshIds(store, rows);
|
|
376
329
|
const out = [];
|
|
377
330
|
for (const row of rows) {
|
|
378
331
|
const sid = str(row.session_id);
|
|
379
|
-
if (!rowMayNeedSidecarRefresh(store, row, stale) || !sid) {
|
|
332
|
+
if (!await rowMayNeedSidecarRefresh(store, row, stale) || !sid) {
|
|
380
333
|
out.push(row);
|
|
381
334
|
continue;
|
|
382
335
|
}
|
|
383
|
-
const sidecar = store.loadMetadataOnly(sid, { indexMessageCounts: indexCounts });
|
|
336
|
+
const sidecar = (await store.loadMetadataOnly(sid, { indexMessageCounts: indexCounts }));
|
|
384
337
|
if (!sidecar) {
|
|
385
338
|
out.push(row);
|
|
386
339
|
continue;
|
|
@@ -407,7 +360,8 @@ export const SIDEBAR_SESSION_RESPONSE_FIELDS = new Set([
|
|
|
407
360
|
'is_cli_session', 'is_messaging_session', 'is_streaming', 'cron_running', 'active_stream_id', 'has_pending_user_message', 'pending_started_at', 'default_hidden',
|
|
408
361
|
'worktree_path', 'worktree_branch', 'parent_session_id', 'parent_title', 'parent_source', 'relationship_type', 'pre_compression_snapshot', '_lineage_root_id',
|
|
409
362
|
'_lineage_tip_id', '_compression_segment_count', '_lineage_collapsed_count', '_parent_lineage_root_id', '_parent_lineage_tip_id', '_cross_surface_child_session',
|
|
410
|
-
'match_type', 'match_preview', 'read_only', 'can_branch', 'can_pin', 'can_archive', 'can_delete', 'can_duplicate', 'gateway_routing', 'share_url',
|
|
363
|
+
'match_type', 'match_preview', 'read_only', 'read_only_reason', 'can_branch', 'can_pin', 'can_archive', 'can_delete', 'can_duplicate', 'gateway_routing', 'share_url',
|
|
364
|
+
'execution_mode',
|
|
411
365
|
]);
|
|
412
366
|
export function isCliSessionRow(row) {
|
|
413
367
|
const lower = (v) => str(v).trim().toLowerCase();
|
|
@@ -503,15 +457,20 @@ export function isMessagingSessionRecord(row) {
|
|
|
503
457
|
return true;
|
|
504
458
|
return isKnownMessagingSource(first(row.raw_source, row.source_tag, row.source, row.source_label));
|
|
505
459
|
}
|
|
506
|
-
/**
|
|
460
|
+
/**
|
|
461
|
+
* Python `_is_claimable_cli_source`: a denylist of foreign families that own their sessions. A `kanban` state.db owner
|
|
462
|
+
* (`stateDbSessionSources` folds in the lineage's `created_source`) refuses whatever the row's tag says (TAL-793).
|
|
463
|
+
*/
|
|
507
464
|
export function isClaimableCliSource(meta, stateDbSource) {
|
|
508
|
-
if (meta.read_only)
|
|
465
|
+
if (typeof stateDbSource === 'object' || meta.read_only)
|
|
466
|
+
return false;
|
|
467
|
+
if (stateDbSource.trim().toLowerCase() === 'kanban')
|
|
509
468
|
return false;
|
|
510
469
|
const sessionSource = str(meta.session_source).trim().toLowerCase();
|
|
511
470
|
if (['messaging', 'external_agent'].includes(sessionSource))
|
|
512
471
|
return false;
|
|
513
472
|
const tag = str(meta.source_tag || meta.raw_source).trim().toLowerCase();
|
|
514
|
-
const refused = new Set(['claude_code', 'cron', 'external_agent', 'gateway', 'messaging', 'subagent', 'unknown']);
|
|
473
|
+
const refused = new Set(['claude_code', 'cron', 'external_agent', 'gateway', 'kanban', 'messaging', 'subagent', 'unknown']);
|
|
515
474
|
if (tag && refused.has(tag))
|
|
516
475
|
return false;
|
|
517
476
|
if (isMessagingSessionRecord(meta))
|
|
@@ -520,29 +479,30 @@ export function isClaimableCliSource(meta, stateDbSource) {
|
|
|
520
479
|
return false;
|
|
521
480
|
return true;
|
|
522
481
|
}
|
|
523
|
-
/**
|
|
524
|
-
* TAL-358: marks read-only each WebUI sidecar row whose active-profile state.db owner (`sessions.source`) refuses
|
|
525
|
-
* claiming, as a sidecar-less row from that owner is. A sidecar persisted as WebUI- or fork-born stays WebUI-owned
|
|
526
|
-
* whatever state.db mirrors for its id. `stateDbSources` reads every candidate's owner in one batch, not per row; an
|
|
527
|
-
* unreadable state.db (null) locks every candidate, since an unknown owner is not a released one.
|
|
528
|
-
*/
|
|
529
482
|
export function withOwnerLocks(rows, stateDbSources) {
|
|
530
|
-
const
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
if (
|
|
536
|
-
return true;
|
|
537
|
-
const
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
483
|
+
const byProfile = ownerLockCandidates(rows);
|
|
484
|
+
const ownersByProfile = new Map([...byProfile].map(([profile, ids]) => [profile, stateDbSources([...ids], profile)]));
|
|
485
|
+
return rows.map((r) => {
|
|
486
|
+
const owners = ownersByProfile.get(str(r.profile) || 'default');
|
|
487
|
+
const owner = owners?.get(str(r.session_id).trim());
|
|
488
|
+
if (typeof owner === 'object')
|
|
489
|
+
return { ...r, ...(owner.source ? { ...normalizeAgentSessionSource(owner.source), source_tag: owner.source } : {}), ...(owner.execution_mode ? { execution_mode: owner.execution_mode } : {}), read_only: true, read_only_reason: owner.reason ?? CANONICAL_READ_ONLY_REASON };
|
|
490
|
+
const webui = ['source_tag', 'raw_source', 'session_source'].some((k) => ['webui', 'fork'].includes(str(r[k]).trim().toLowerCase()));
|
|
491
|
+
if (!owners || (!webui && owner && !isClaimableCliSource({ source_tag: owner, ...normalizeAgentSessionSource(owner) }, owner)))
|
|
492
|
+
return { ...r, read_only: true, ...(!owners ? { read_only_reason: OWNERSHIP_UNAVAILABLE_REASON } : {}) };
|
|
493
|
+
return r;
|
|
494
|
+
});
|
|
541
495
|
}
|
|
542
|
-
/**
|
|
496
|
+
/** Every sidecar is checked in its own profile, including cached WebUI/fork tags. */
|
|
543
497
|
export function ownerLockCandidates(rows) {
|
|
544
|
-
const
|
|
545
|
-
|
|
498
|
+
const byProfile = new Map();
|
|
499
|
+
for (const row of rows) {
|
|
500
|
+
const profile = str(row.profile) || 'default';
|
|
501
|
+
const ids = byProfile.get(profile) ?? new Set();
|
|
502
|
+
ids.add(str(row.session_id).trim());
|
|
503
|
+
byProfile.set(profile, ids);
|
|
504
|
+
}
|
|
505
|
+
return byProfile;
|
|
546
506
|
}
|
|
547
507
|
/** Python `_session_is_subagent_view_only` on a row: a delegated child by any source marker. */
|
|
548
508
|
export function isSubagentRow(row) {
|
|
@@ -577,15 +537,16 @@ export function withSessionWireFlags(row, activeStreamIds) {
|
|
|
577
537
|
else
|
|
578
538
|
r.read_only = Boolean(r.read_only);
|
|
579
539
|
// The branch gate (`SessionService.branch`): never a subagent child, and a read-only source only when it is a cron run.
|
|
580
|
-
|
|
540
|
+
const ownerReadOnly = r.read_only && Boolean(r.read_only_reason);
|
|
541
|
+
r.can_branch = !ownerReadOnly && !subagent && (!r.read_only || str(r.source_tag || r.raw_source).trim().toLowerCase() === 'cron');
|
|
581
542
|
// Pin and archive refuse only subagent children; duplicate also needs the WebUI sidecar it copies, so a sidecar-less
|
|
582
543
|
// foreign row arrives with `can_duplicate: false`. Rename, move and delete follow `read_only` (the mutation gate).
|
|
583
544
|
// A Claude Code import is a live view Web never stores (TAL-551), so it cannot be pinned or archived either.
|
|
584
|
-
const stored = !subagent && kind !== 'claude_code';
|
|
545
|
+
const stored = !ownerReadOnly && !subagent && kind !== 'claude_code';
|
|
585
546
|
r.can_pin = stored;
|
|
586
547
|
r.can_archive = stored;
|
|
587
548
|
r.can_delete = !r.read_only;
|
|
588
|
-
r.can_duplicate = !subagent && r.can_duplicate !== false;
|
|
549
|
+
r.can_duplicate = !ownerReadOnly && !subagent && r.can_duplicate !== false;
|
|
589
550
|
r.sort_ts = sessionSortTimestamp(r);
|
|
590
551
|
return row;
|
|
591
552
|
}
|
|
@@ -618,21 +579,66 @@ export function mergeCliSidebarMetadata(ui, meta) {
|
|
|
618
579
|
function sessionSourceIsWebui(row) {
|
|
619
580
|
return ['source_tag', 'raw_source', 'session_source', 'source'].some((k) => str(row[k]).trim().toLowerCase() === 'webui');
|
|
620
581
|
}
|
|
621
|
-
|
|
582
|
+
/** TAL-1040: a chat Web created through the owner, by its receipt identity anywhere in the row's lineage (compression moves the tip). */
|
|
583
|
+
export function isWebDiagnosticRow(row, ids) {
|
|
584
|
+
return ids !== undefined && ids.size > 0 && [...sessionLineageIds(row)].some((id) => ids.has(id));
|
|
585
|
+
}
|
|
586
|
+
export function sessionLineageIds(row) {
|
|
622
587
|
const ids = new Set();
|
|
623
588
|
for (const key of ['session_id', '_lineage_root_id', '_lineage_tip_id'])
|
|
624
589
|
if (row[key])
|
|
625
590
|
ids.add(str(row[key]));
|
|
591
|
+
if (Array.isArray(row._lineage_ids))
|
|
592
|
+
for (const id of row._lineage_ids)
|
|
593
|
+
if (typeof id === 'string')
|
|
594
|
+
ids.add(id);
|
|
626
595
|
return ids;
|
|
627
596
|
}
|
|
597
|
+
/** The newest saved physical member owns UI metadata; listing and materialization use this same selection. */
|
|
598
|
+
export function latestLineageSidecar(ids, profile, lookup, profilesMatch) {
|
|
599
|
+
for (let i = ids.length - 1; i >= 0; i -= 1) {
|
|
600
|
+
const row = lookup(ids[i]);
|
|
601
|
+
if (row && profilesMatch(str(row.profile) || null, profile))
|
|
602
|
+
return row;
|
|
603
|
+
}
|
|
604
|
+
return undefined;
|
|
605
|
+
}
|
|
606
|
+
/** Receipt members are aliases of the current target. Keep UI metadata, never an old member's transcript counts. */
|
|
607
|
+
export function reconcileLocalSessionRows(rows, cli, profilesMatch) {
|
|
608
|
+
const byId = new Map(rows.map((row) => [str(row.session_id), row]));
|
|
609
|
+
const members = new Map();
|
|
610
|
+
const chosen = new Map();
|
|
611
|
+
for (const meta of cli) {
|
|
612
|
+
if (!Array.isArray(meta._lineage_ids))
|
|
613
|
+
continue;
|
|
614
|
+
const ids = meta._lineage_ids.filter((id) => typeof id === 'string');
|
|
615
|
+
for (const id of ids)
|
|
616
|
+
members.set(id, meta);
|
|
617
|
+
const row = latestLineageSidecar(ids, str(meta.profile) || null, (id) => byId.get(id), profilesMatch);
|
|
618
|
+
if (row)
|
|
619
|
+
chosen.set(str(meta.session_id), { row, meta });
|
|
620
|
+
}
|
|
621
|
+
const other = rows.filter((row) => { const meta = members.get(str(row.session_id)); return !meta || !profilesMatch(str(row.profile) || null, str(meta.profile) || null); });
|
|
622
|
+
for (const [target, { row, meta }] of chosen) {
|
|
623
|
+
const merged = mergeCliSidebarMetadata(row, meta);
|
|
624
|
+
if (str(row.session_id) !== target) {
|
|
625
|
+
merged.message_count = meta.message_count ?? 0;
|
|
626
|
+
merged.user_message_count = meta.user_message_count ?? 0;
|
|
627
|
+
merged.last_message_at = meta.last_message_at ?? meta.updated_at;
|
|
628
|
+
}
|
|
629
|
+
other.push({ ...merged, session_id: target });
|
|
630
|
+
}
|
|
631
|
+
return other;
|
|
632
|
+
}
|
|
628
633
|
/** Python `_dedupe_cli_sidebar_sessions_for_api`: additive state rows, keeping project-hidden background rows addressable. */
|
|
629
634
|
export function dedupeCliSidebarSessions(cli, represented, opts) {
|
|
635
|
+
const webCreated = (r) => isWebDiagnosticRow(r, opts.webCreated);
|
|
630
636
|
const sf = str(opts.sourceFilter).trim().toLowerCase();
|
|
631
637
|
const showCron = opts.showCron || sf === 'cron';
|
|
632
638
|
const showWebhook = opts.showWebhook || sf === 'webhook';
|
|
633
639
|
const showKanban = opts.showKanban || sf === 'kanban';
|
|
634
|
-
const candidates = cli.filter((r) => !represented.has(str(r.session_id)) && !(sessionSourceIsWebui(r) && [...sessionLineageIds(r)].some((id) => represented.has(id))) && isCliSessionRowVisible(r));
|
|
635
|
-
const visible = candidates.filter((r) => (!isIntentionallyBackground(r) && opts.showCli) || (isIntentionallyBackground(r) && !hideFromDefaultSidebar(r, { showCron, showWebhook, showKanban })));
|
|
640
|
+
const candidates = cli.filter((r) => !represented.has(str(r.session_id)) && !(sessionSourceIsWebui(r) && [...sessionLineageIds(r)].some((id) => represented.has(id))) && (isCliSessionRowVisible(r) || webCreated(r)));
|
|
641
|
+
const visible = candidates.filter((r) => (!isIntentionallyBackground(r) && (opts.showCli || webCreated(r))) || (isIntentionallyBackground(r) && !hideFromDefaultSidebar(r, { showCron, showWebhook, showKanban })));
|
|
636
642
|
if (opts.requestVisibilityOverrides)
|
|
637
643
|
return visible;
|
|
638
644
|
return includeProjectHiddenBackground(candidates, visible);
|
|
@@ -715,6 +721,9 @@ export function capRecentCliSessions(rows, cap = CLI_VISIBLE_SESSION_CAP) {
|
|
|
715
721
|
return true; seen += 1; return seen <= cap; });
|
|
716
722
|
}
|
|
717
723
|
function sessionHasServerVisibleMessages(row) {
|
|
724
|
+
// A validated local reset keeps its empty current target discoverable under the existing lineage identity.
|
|
725
|
+
if (row._lineage_root_id && row._lineage_tip_id)
|
|
726
|
+
return true;
|
|
718
727
|
// A worktree chat owns a directory on disk from creation; its row is where the user removes it (TAL-605).
|
|
719
728
|
if (sidebarMessageCount(row) > 0 || row.worktree_path)
|
|
720
729
|
return true;
|
|
@@ -750,9 +759,9 @@ function hiddenArchivedReferences(visible, archived) {
|
|
|
750
759
|
return references;
|
|
751
760
|
}
|
|
752
761
|
/** Python `_build_session_list_cache_payload`; of its orphaned-sidecar prunes only the imported one (#3238) applies. */
|
|
753
|
-
export function buildSessionListPayload(store, params) {
|
|
754
|
-
let webuiSessions = (params.webuiRows ?? allSessions(store, { sidebarMetadataOnly: true })).map((r) => ({ ...r, is_cli_session: isCliSessionRow(r) }));
|
|
755
|
-
const orphans = params.pruneOrphanedImports?.(webuiSessions);
|
|
762
|
+
export async function buildSessionListPayload(store, params) {
|
|
763
|
+
let webuiSessions = (params.webuiRows ?? (await allSessions(store, { sidebarMetadataOnly: true }))).map((r) => ({ ...r, is_cli_session: isCliSessionRow(r) }));
|
|
764
|
+
const orphans = await params.pruneOrphanedImports?.(webuiSessions);
|
|
756
765
|
if (orphans?.size)
|
|
757
766
|
webuiSessions = webuiSessions.filter((r) => !orphans.has(str(r.session_id)));
|
|
758
767
|
// Before the state.db overlay below replaces the sidecar's own source fields, which the WebUI-born exception reads.
|
|
@@ -761,6 +770,7 @@ export function buildSessionListPayload(store, params) {
|
|
|
761
770
|
let dedupedCli = [];
|
|
762
771
|
if (params.cliRows) {
|
|
763
772
|
const cliRows = params.cliRows.flatMap((r) => { const clean = sanitizeSessionRow(r, store, 'state.db'); return clean ? [clean] : []; });
|
|
773
|
+
webuiSessions = reconcileLocalSessionRows(webuiSessions, cliRows, params.profilesMatch);
|
|
764
774
|
const cliById = new Map(cliRows.map((r) => [str(r.session_id), r]));
|
|
765
775
|
webuiSessions = webuiSessions.map((s) => {
|
|
766
776
|
const meta = cliById.get(str(s.session_id));
|
|
@@ -786,9 +796,11 @@ export function buildSessionListPayload(store, params) {
|
|
|
786
796
|
for (const s of webuiSessions)
|
|
787
797
|
for (const id of sessionLineageIds(s))
|
|
788
798
|
represented.add(id);
|
|
789
|
-
dedupedCli = dedupeCliSidebarSessions(cliRows, represented, { showCli: params.showCliSessions, showCron: params.showCronSessions, showWebhook: params.showWebhookSessions, showKanban: params.showKanbanSessions, sourceFilter: params.sourceFilter ?? null, requestVisibilityOverrides: params.requestVisibilityOverrides })
|
|
790
|
-
|
|
791
|
-
|
|
799
|
+
dedupedCli = dedupeCliSidebarSessions(cliRows, represented, { showCli: params.showCliSessions, showCron: params.showCronSessions, showWebhook: params.showWebhookSessions, showKanban: params.showKanbanSessions, sourceFilter: params.sourceFilter ?? null, requestVisibilityOverrides: params.requestVisibilityOverrides, webCreated: params.webDiagnosticIds });
|
|
800
|
+
const owners = params.stateDbSources ? params.stateDbSources(dedupedCli.map((r) => str(r.session_id))) : new Map();
|
|
801
|
+
// A sidecar-less foreign row whose owner refuses claiming is read-only, as its detail and mutations are; an
|
|
802
|
+
// unreadable owner read (null) locks every row, as it locks sidecars.
|
|
803
|
+
dedupedCli = withOwnerLocks(dedupedCli.map((r) => ({ ...r, read_only: !owners || !isClaimableCliSource(r, owners.get(str(r.session_id)) || str(r.source)), can_duplicate: false })), () => owners);
|
|
792
804
|
}
|
|
793
805
|
else {
|
|
794
806
|
webuiSessions = webuiSessions.filter((r) => !isCliSessionForSettings(r));
|
|
@@ -807,8 +819,19 @@ export function buildSessionListPayload(store, params) {
|
|
|
807
819
|
otherProfileCount = params.isolatedProfileMode ? 0 : merged.length - scoped.length;
|
|
808
820
|
}
|
|
809
821
|
const identity = params.gatewayIdentity ?? new Map();
|
|
810
|
-
const
|
|
811
|
-
|
|
822
|
+
const indexedParents = new Map((await store.readIndexEntries().catch(() => [])).flatMap((row) => {
|
|
823
|
+
// Older indexes omit the flag; only an explicit boolean can replace the document read.
|
|
824
|
+
return typeof row?.session_id === 'string' && typeof row.pre_compression_snapshot === 'boolean' ? [[row.session_id, row]] : [];
|
|
825
|
+
}));
|
|
826
|
+
const snapshots = new Set();
|
|
827
|
+
for (const parent of new Set(scoped.map((row) => str(row.parent_session_id)))) {
|
|
828
|
+
if (!/^[a-z0-9_]+$/.test(parent))
|
|
829
|
+
continue;
|
|
830
|
+
const row = indexedParents.get(parent) ?? await store.loadMetadataOnly(parent);
|
|
831
|
+
if (row?.pre_compression_snapshot)
|
|
832
|
+
snapshots.add(parent);
|
|
833
|
+
}
|
|
834
|
+
const isPreCompressionSnapshotId = (sid) => snapshots.has(sid);
|
|
812
835
|
const dedupeOpts = { showPrevious: params.showPreviousMessagingSessions, identity, isPreCompressionSnapshotId };
|
|
813
836
|
let archivedScoped = keepLatestMessagingSessionPerSource([...scoped], dedupeOpts);
|
|
814
837
|
let visibleScoped = keepLatestMessagingSessionPerSource(scoped.filter((r) => !r.archived), dedupeOpts);
|
|
@@ -817,8 +840,10 @@ export function buildSessionListPayload(store, params) {
|
|
|
817
840
|
visibleScoped = capRecentCliSessions(visibleScoped);
|
|
818
841
|
}
|
|
819
842
|
if (params.visibleOnly) {
|
|
820
|
-
|
|
821
|
-
|
|
843
|
+
// A Web-created diagnostic chat exists from creation, like a worktree chat, even before its first turn ran.
|
|
844
|
+
const visible = (r) => sessionHasServerVisibleMessages(r) || isWebDiagnosticRow(r, params.webDiagnosticIds);
|
|
845
|
+
archivedScoped = archivedScoped.filter(visible);
|
|
846
|
+
visibleScoped = visibleScoped.filter(visible);
|
|
822
847
|
}
|
|
823
848
|
if (params.excludeHidden) {
|
|
824
849
|
archivedScoped = archivedScoped.filter((r) => !r.default_hidden);
|
|
@@ -853,6 +878,7 @@ export function buildSessionListPayload(store, params) {
|
|
|
853
878
|
scheduled_sessions_truncated: params.showCronSessions && truncated.has('cron'),
|
|
854
879
|
webhook_session_count: visibleFiltered.filter((r) => sourceKind(r) === 'webhook').length,
|
|
855
880
|
webhook_sessions_truncated: params.showWebhookSessions && truncated.has('webhook'),
|
|
881
|
+
agent_storage: params.agentStorage ?? AGENT_STORAGE_OK,
|
|
856
882
|
include_archived: params.includeArchived,
|
|
857
883
|
archived_limit: params.archivedLimit,
|
|
858
884
|
archived_offset: params.archivedOffset,
|
|
@@ -952,6 +978,7 @@ export function sessionListResponse(payload, overlay, redactEnabled, now, worksp
|
|
|
952
978
|
scheduled_sessions_truncated: payload.scheduled_sessions_truncated,
|
|
953
979
|
webhook_session_count: payload.webhook_session_count,
|
|
954
980
|
webhook_sessions_truncated: payload.webhook_sessions_truncated,
|
|
981
|
+
agent_storage: payload.agent_storage,
|
|
955
982
|
};
|
|
956
983
|
if (payload.archived_limit !== null) {
|
|
957
984
|
body.archived_limit = Math.trunc(payload.archived_limit) || 0;
|
|
@@ -962,20 +989,7 @@ export function sessionListResponse(payload, overlay, redactEnabled, now, worksp
|
|
|
962
989
|
return { body, etag };
|
|
963
990
|
}
|
|
964
991
|
// ── search ────────────────────────────────────────────────────────────────
|
|
965
|
-
export
|
|
966
|
-
const content = message && typeof message === 'object' ? message.content : '';
|
|
967
|
-
if (Array.isArray(content))
|
|
968
|
-
return content.filter((p) => Boolean(p) && typeof p === 'object' && p.type === 'text').map((p) => str(p.text)).join(' ');
|
|
969
|
-
return str(content);
|
|
970
|
-
}
|
|
971
|
-
/** TAL-453: a query's distinct whitespace-separated terms, lowercased; a row matches when one field holds them all. */
|
|
972
|
-
export function sessionSearchTerms(query) {
|
|
973
|
-
return [...new Set(query.toLowerCase().split(/\s+/).filter(Boolean))];
|
|
974
|
-
}
|
|
975
|
-
export function sessionSearchMatches(text, terms) {
|
|
976
|
-
const lower = text.toLowerCase();
|
|
977
|
-
return terms.length > 0 && terms.every((term) => lower.includes(term));
|
|
978
|
-
}
|
|
992
|
+
export { sessionSearchMessageText, sessionSearchTerms, sessionSearchMatches } from './storage/search-text.js';
|
|
979
993
|
/** An excerpt of `text` centred on the earliest occurrence of any of `terms`. */
|
|
980
994
|
export function sessionSearchPreview(text, terms, maxLen = 124) {
|
|
981
995
|
const normalized = text.replace(/\s+/g, ' ').trim();
|