@jingyi0605/codingns 0.3.6 → 0.5.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/README.md +3 -0
- package/bin/codingns.mjs +913 -1
- package/dist/public/assets/AdaptiveButlerPage-B153lk5H.css +1 -0
- package/dist/public/assets/AdaptiveButlerPage-R-XZw7pd.js +3 -0
- package/dist/public/assets/App-DUAg5urj.css +1 -0
- package/dist/public/assets/App-DkvE5EyM.js +30 -0
- package/dist/public/assets/BootstrapPage-Vu5oEJ8z.js +1 -0
- package/dist/public/assets/ConversationPage-Cjpg6g0J.js +2 -0
- package/dist/public/assets/DesktopDetachPreviewPage-BgeEqbc5.js +1 -0
- package/dist/public/assets/DesktopWindowPage-1WelvxdH.js +2 -0
- package/dist/public/assets/FileContextPanel-D_ghXJuW.js +1 -0
- package/dist/public/assets/GitSidebar-D9f9Jxwr.js +6 -0
- package/dist/public/assets/MobileCreateSessionSheet-DLq5qPkx.js +1 -0
- package/dist/public/assets/MobileSheet-DLg-gX1t.js +1 -0
- package/dist/public/assets/MobileTopHeaderFrame-DArgZI7L.js +1 -0
- package/dist/public/assets/MobileWorkspaceSwitcherHeader-0ywJKfBQ.js +1 -0
- package/dist/public/assets/ServerSettingsModal-izoYMx9U.js +1 -0
- package/dist/public/assets/SessionIndexPage-C5aG8FIv.js +1 -0
- package/dist/public/assets/SettingsPage-HJIC-P-4.js +1 -0
- package/dist/public/assets/TerminalManagerPanel-DpyUTo9k.js +1 -0
- package/dist/public/assets/{TerminalPage-D00S4KM6.js → TerminalPage-CtKXIU0h.js} +19 -19
- package/dist/public/assets/TerminalRuntimeFallbackModal-CRhOQOsT.js +1 -0
- package/dist/public/assets/ToolFilesPage-DcYPsS-e.js +1 -0
- package/dist/public/assets/ToolGitPage-CsPl89ty.js +1 -0
- package/dist/public/assets/ToolProcessesPage-D0dvR8xK.js +1 -0
- package/dist/public/assets/ToolsHomePage-4fP-KRiv.js +1 -0
- package/dist/public/assets/WorkbenchLandingPage-kvlfyxRo.js +1 -0
- package/dist/public/assets/WorkbenchLayout-ByFw4eeu.js +3 -0
- package/dist/public/assets/WorkbenchModal-Ctob14VR.js +1 -0
- package/dist/public/assets/WorkbenchShellRoute-BUITtdAg.css +1 -0
- package/dist/public/assets/WorkbenchShellRoute-Kw7JEZI3.js +1 -0
- package/dist/public/assets/WorkspaceDebugDetailPage-Com5kEXJ.js +1 -0
- package/dist/public/assets/WorkspaceDetailPage-D0Lrx4Uz.js +1 -0
- package/dist/public/assets/WorkspaceHomePage-wR8d3aP9.js +1 -0
- package/dist/public/assets/butler-records-events-DgWCG364.js +1 -0
- package/dist/public/assets/default-session-permission-mode-CcGwR4Kk.js +1 -0
- package/dist/public/assets/event-DvH9tcej.js +1 -0
- package/dist/public/assets/file-tree-icon-UFVoVzhM.js +31 -0
- package/dist/public/assets/index-Byp9hJ0c.js +42 -0
- package/dist/public/assets/index-_52jxu4a.css +1 -0
- package/dist/public/assets/preferences-service-KIYeE2gk.js +1 -0
- package/dist/public/assets/session-runtime-machine-0KNSSPp5.js +17 -0
- package/dist/public/assets/styles-BWPBZvze.css +1 -0
- package/dist/public/assets/styles-CSUx5LGe.js +1 -0
- package/dist/public/assets/terminal-runtime-meta-AWXJpN4r.js +1 -0
- package/dist/public/assets/useRegisteredDebugTemplates-DBDRdptr.js +1 -0
- package/dist/public/assets/window-BWqRixxq.js +1 -0
- package/dist/public/index.html +2 -2
- package/dist/server/middlewares/auth-guard.d.ts +4 -0
- package/dist/server/middlewares/auth-guard.js +42 -4
- package/dist/server/middlewares/auth-guard.js.map +1 -1
- package/dist/server/modules/assistant-capability/assistant-capability-controller.d.ts +234 -0
- package/dist/server/modules/assistant-capability/assistant-capability-controller.js +365 -0
- package/dist/server/modules/assistant-capability/assistant-capability-controller.js.map +1 -1
- package/dist/server/modules/assistant-capability/assistant-capability-service.d.ts +262 -2
- package/dist/server/modules/assistant-capability/assistant-capability-service.js +737 -3
- package/dist/server/modules/assistant-capability/assistant-capability-service.js.map +1 -1
- package/dist/server/modules/auth/auth-controller.d.ts +11 -1
- package/dist/server/modules/auth/auth-controller.js +61 -2
- package/dist/server/modules/auth/auth-controller.js.map +1 -1
- package/dist/server/modules/auth/auth-device-display-name.d.ts +10 -0
- package/dist/server/modules/auth/auth-device-display-name.js +190 -0
- package/dist/server/modules/auth/auth-device-display-name.js.map +1 -0
- package/dist/server/modules/auth/auth-service.d.ts +80 -5
- package/dist/server/modules/auth/auth-service.js +333 -23
- package/dist/server/modules/auth/auth-service.js.map +1 -1
- package/dist/server/modules/butler/assistant-automation-service.d.ts +112 -0
- package/dist/server/modules/butler/assistant-automation-service.js +832 -0
- package/dist/server/modules/butler/assistant-automation-service.js.map +1 -0
- package/dist/server/modules/butler/assistant-automation-trigger.d.ts +94 -0
- package/dist/server/modules/butler/assistant-automation-trigger.js +400 -0
- package/dist/server/modules/butler/assistant-automation-trigger.js.map +1 -0
- package/dist/server/modules/butler/assistant-sandbox-cleanup-scheduler.d.ts +32 -0
- package/dist/server/modules/butler/assistant-sandbox-cleanup-scheduler.js +93 -0
- package/dist/server/modules/butler/assistant-sandbox-cleanup-scheduler.js.map +1 -0
- package/dist/server/modules/butler/assistant-sandbox-service.d.ts +69 -0
- package/dist/server/modules/butler/assistant-sandbox-service.js +399 -0
- package/dist/server/modules/butler/assistant-sandbox-service.js.map +1 -0
- package/dist/server/modules/butler/butler-action-context-service.d.ts +4 -1
- package/dist/server/modules/butler/butler-action-context-service.js +8 -2
- package/dist/server/modules/butler/butler-action-context-service.js.map +1 -1
- package/dist/server/modules/butler/butler-auth-service.js +7 -2
- package/dist/server/modules/butler/butler-auth-service.js.map +1 -1
- package/dist/server/modules/butler/butler-control-session-service.d.ts +11 -1
- package/dist/server/modules/butler/butler-control-session-service.js +173 -40
- package/dist/server/modules/butler/butler-control-session-service.js.map +1 -1
- package/dist/server/modules/butler/butler-control-timer-scheduler.d.ts +32 -0
- package/dist/server/modules/butler/butler-control-timer-scheduler.js +93 -0
- package/dist/server/modules/butler/butler-control-timer-scheduler.js.map +1 -0
- package/dist/server/modules/butler/butler-control-timer-service.d.ts +42 -0
- package/dist/server/modules/butler/butler-control-timer-service.js +132 -0
- package/dist/server/modules/butler/butler-control-timer-service.js.map +1 -0
- package/dist/server/modules/butler/butler-controller.d.ts +42 -2
- package/dist/server/modules/butler/butler-controller.js +79 -12
- package/dist/server/modules/butler/butler-controller.js.map +1 -1
- package/dist/server/modules/butler/butler-follow-up-evaluation-instruction-adapter.d.ts +2 -1
- package/dist/server/modules/butler/butler-follow-up-evaluation-instruction-adapter.js +27 -25
- package/dist/server/modules/butler/butler-follow-up-evaluation-instruction-adapter.js.map +1 -1
- package/dist/server/modules/butler/butler-follow-up-service.d.ts +41 -5
- package/dist/server/modules/butler/butler-follow-up-service.js +568 -371
- package/dist/server/modules/butler/butler-follow-up-service.js.map +1 -1
- package/dist/server/modules/butler/butler-inbox-analysis-service.d.ts +4 -1
- package/dist/server/modules/butler/butler-inbox-analysis-service.js +18 -4
- package/dist/server/modules/butler/butler-inbox-analysis-service.js.map +1 -1
- package/dist/server/modules/butler/butler-inbox-service.js +1 -0
- package/dist/server/modules/butler/butler-inbox-service.js.map +1 -1
- package/dist/server/modules/butler/butler-profile-service.js +2 -5
- package/dist/server/modules/butler/butler-profile-service.js.map +1 -1
- package/dist/server/modules/butler/butler-project-service.d.ts +3 -1
- package/dist/server/modules/butler/butler-project-service.js +7 -1
- package/dist/server/modules/butler/butler-project-service.js.map +1 -1
- package/dist/server/modules/butler/butler-session-service.d.ts +5 -1
- package/dist/server/modules/butler/butler-session-service.js +26 -1
- package/dist/server/modules/butler/butler-session-service.js.map +1 -1
- package/dist/server/modules/butler/butler-session-summary-service.js +2 -1
- package/dist/server/modules/butler/butler-session-summary-service.js.map +1 -1
- package/dist/server/modules/butler/butler-workspace-context.d.ts +4 -1
- package/dist/server/modules/butler/butler-workspace-context.js +204 -58
- package/dist/server/modules/butler/butler-workspace-context.js.map +1 -1
- package/dist/server/modules/butler/patrol-execution-service.js +2 -1
- package/dist/server/modules/butler/patrol-execution-service.js.map +1 -1
- package/dist/server/modules/butler/provider-adapter-registry.d.ts +3 -0
- package/dist/server/modules/butler/provider-adapter-registry.js +18 -1
- package/dist/server/modules/butler/provider-adapter-registry.js.map +1 -1
- package/dist/server/modules/butler/verification-run-service.d.ts +9 -2
- package/dist/server/modules/butler/verification-run-service.js +188 -34
- package/dist/server/modules/butler/verification-run-service.js.map +1 -1
- package/dist/server/modules/debug-target/debug-target-controller.js +1 -1
- package/dist/server/modules/debug-target/debug-target-controller.js.map +1 -1
- package/dist/server/modules/debug-target/debug-target-service.d.ts +7 -2
- package/dist/server/modules/debug-target/debug-target-service.js +563 -100
- package/dist/server/modules/debug-target/debug-target-service.js.map +1 -1
- package/dist/server/modules/git/git-command-helper-client.d.ts +1 -0
- package/dist/server/modules/git/git-command-helper-client.js +19 -26
- package/dist/server/modules/git/git-command-helper-client.js.map +1 -1
- package/dist/server/modules/git/git-command-runner.js +19 -1
- package/dist/server/modules/git/git-command-runner.js.map +1 -1
- package/dist/server/modules/preferences/profile-service.d.ts +3 -1
- package/dist/server/modules/preferences/profile-service.js +74 -3
- package/dist/server/modules/preferences/profile-service.js.map +1 -1
- package/dist/server/modules/provider/provider-controller.d.ts +1 -1
- package/dist/server/modules/provider/provider-controller.js.map +1 -1
- package/dist/server/modules/provider/provider-discovery-helper-client.d.ts +5 -3
- package/dist/server/modules/provider/provider-discovery-helper-client.js +129 -43
- package/dist/server/modules/provider/provider-discovery-helper-client.js.map +1 -1
- package/dist/server/modules/provider/provider-discovery-helper-process.js +44 -0
- package/dist/server/modules/provider/provider-discovery-helper-process.js.map +1 -1
- package/dist/server/modules/provider/provider-discovery-runtime.js +83 -3
- package/dist/server/modules/provider/provider-discovery-runtime.js.map +1 -1
- package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-identity-service.d.ts +10 -0
- package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-identity-service.js +48 -0
- package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-identity-service.js.map +1 -0
- package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-packets.d.ts +48 -0
- package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-packets.js +11 -0
- package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-packets.js.map +1 -0
- package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-protocol.d.ts +74 -0
- package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-protocol.js +302 -0
- package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-protocol.js.map +1 -0
- package/dist/server/modules/relay-tunnel/relay-tunnel-controller.d.ts +33 -0
- package/dist/server/modules/relay-tunnel/relay-tunnel-controller.js +57 -0
- package/dist/server/modules/relay-tunnel/relay-tunnel-controller.js.map +1 -0
- package/dist/server/modules/relay-tunnel/relay-tunnel-edge-proof.d.ts +9 -0
- package/dist/server/modules/relay-tunnel/relay-tunnel-edge-proof.js +25 -0
- package/dist/server/modules/relay-tunnel/relay-tunnel-edge-proof.js.map +1 -0
- package/dist/server/modules/relay-tunnel/relay-tunnel-gateway-service.d.ts +18 -0
- package/dist/server/modules/relay-tunnel/relay-tunnel-gateway-service.js +230 -0
- package/dist/server/modules/relay-tunnel/relay-tunnel-gateway-service.js.map +1 -0
- package/dist/server/modules/relay-tunnel/relay-tunnel-runtime-adapter.d.ts +41 -0
- package/dist/server/modules/relay-tunnel/relay-tunnel-runtime-adapter.js +443 -0
- package/dist/server/modules/relay-tunnel/relay-tunnel-runtime-adapter.js.map +1 -0
- package/dist/server/modules/relay-tunnel/relay-tunnel-service.d.ts +111 -0
- package/dist/server/modules/relay-tunnel/relay-tunnel-service.js +771 -0
- package/dist/server/modules/relay-tunnel/relay-tunnel-service.js.map +1 -0
- package/dist/server/modules/sessions/claude-runtime-helper-client.js +23 -1
- package/dist/server/modules/sessions/claude-runtime-helper-client.js.map +1 -1
- package/dist/server/modules/sessions/codex-app-server-helper-client.d.ts +2 -1
- package/dist/server/modules/sessions/codex-app-server-helper-client.js +78 -0
- package/dist/server/modules/sessions/codex-app-server-helper-client.js.map +1 -1
- package/dist/server/modules/sessions/codex-app-server-helper-process.js +84 -2
- package/dist/server/modules/sessions/codex-app-server-helper-process.js.map +1 -1
- package/dist/server/modules/sessions/provider-session-delete-cli.d.ts +15 -0
- package/dist/server/modules/sessions/provider-session-delete-cli.js +148 -0
- package/dist/server/modules/sessions/provider-session-delete-cli.js.map +1 -0
- package/dist/server/modules/sessions/session-controller.d.ts +4 -1
- package/dist/server/modules/sessions/session-controller.js +4 -0
- package/dist/server/modules/sessions/session-controller.js.map +1 -1
- package/dist/server/modules/sessions/session-history-service.d.ts +24 -1
- package/dist/server/modules/sessions/session-history-service.js +401 -42
- package/dist/server/modules/sessions/session-history-service.js.map +1 -1
- package/dist/server/modules/sessions/session-live-runtime-router-service.d.ts +25 -0
- package/dist/server/modules/sessions/session-live-runtime-router-service.js +42 -0
- package/dist/server/modules/sessions/session-live-runtime-router-service.js.map +1 -0
- package/dist/server/modules/sessions/session-live-runtime-service.d.ts +6 -0
- package/dist/server/modules/sessions/session-live-runtime-service.js +130 -28
- package/dist/server/modules/sessions/session-live-runtime-service.js.map +1 -1
- package/dist/server/modules/sessions/session-message-attachment-service.d.ts +1 -0
- package/dist/server/modules/sessions/session-message-attachment-service.js +22 -0
- package/dist/server/modules/sessions/session-message-attachment-service.js.map +1 -1
- package/dist/server/modules/sessions/session-message-origin-utils.d.ts +12 -0
- package/dist/server/modules/sessions/session-message-origin-utils.js +45 -0
- package/dist/server/modules/sessions/session-message-origin-utils.js.map +1 -0
- package/dist/server/modules/sessions/session-permission-request-service.d.ts +1 -0
- package/dist/server/modules/sessions/session-permission-request-service.js +367 -5
- package/dist/server/modules/sessions/session-permission-request-service.js.map +1 -1
- package/dist/server/modules/sessions/session-provider-error-mapper.js +32 -0
- package/dist/server/modules/sessions/session-provider-error-mapper.js.map +1 -1
- package/dist/server/modules/sessions/session-provider-usage-guard-service.d.ts +37 -0
- package/dist/server/modules/sessions/session-provider-usage-guard-service.js +179 -0
- package/dist/server/modules/sessions/session-provider-usage-guard-service.js.map +1 -0
- package/dist/server/modules/sessions/session-provider-usage-limit.d.ts +17 -0
- package/dist/server/modules/sessions/session-provider-usage-limit.js +465 -0
- package/dist/server/modules/sessions/session-provider-usage-limit.js.map +1 -0
- package/dist/server/modules/skills/assistant-runtime-skill-catalog.d.ts +8 -0
- package/dist/server/modules/skills/assistant-runtime-skill-catalog.js +26 -0
- package/dist/server/modules/skills/assistant-runtime-skill-catalog.js.map +1 -0
- package/dist/server/modules/skills/assistant-runtime-skill-cleanup.d.ts +9 -0
- package/dist/server/modules/skills/assistant-runtime-skill-cleanup.js +55 -0
- package/dist/server/modules/skills/assistant-runtime-skill-cleanup.js.map +1 -0
- package/dist/server/modules/skills/builtin-skill-service.js +1 -6
- package/dist/server/modules/skills/builtin-skill-service.js.map +1 -1
- package/dist/server/modules/skills/builtin-skills/codingns-assistant/SKILL.md +19 -12
- package/dist/server/modules/skills/builtin-skills/codingns-assistant/references/cli-workflow.md +9 -3
- package/dist/server/modules/skills/skill-controller.d.ts +2 -2
- package/dist/server/modules/skills/skill-controller.js +9 -1
- package/dist/server/modules/skills/skill-controller.js.map +1 -1
- package/dist/server/modules/skills/skill-manager-service.d.ts +26 -1
- package/dist/server/modules/skills/skill-manager-service.js +346 -90
- package/dist/server/modules/skills/skill-manager-service.js.map +1 -1
- package/dist/server/modules/skills/skill-name-policy.d.ts +2 -0
- package/dist/server/modules/skills/skill-name-policy.js +10 -0
- package/dist/server/modules/skills/skill-name-policy.js.map +1 -0
- package/dist/server/modules/tailscale/tailscale-service.d.ts +2 -0
- package/dist/server/modules/tailscale/tailscale-service.js +21 -8
- package/dist/server/modules/tailscale/tailscale-service.js.map +1 -1
- package/dist/server/modules/tasks/task-helper-client.d.ts +5 -2
- package/dist/server/modules/tasks/task-helper-client.js +118 -38
- package/dist/server/modules/tasks/task-helper-client.js.map +1 -1
- package/dist/server/modules/tasks/task-helper-process.js +94 -3
- package/dist/server/modules/tasks/task-helper-process.js.map +1 -1
- package/dist/server/modules/tasks/task-types.d.ts +6 -0
- package/dist/server/modules/tasks/task-types.js +7 -1
- package/dist/server/modules/tasks/task-types.js.map +1 -1
- package/dist/server/modules/terminal/command-template-service.d.ts +9 -0
- package/dist/server/modules/terminal/command-template-service.js +87 -5
- package/dist/server/modules/terminal/command-template-service.js.map +1 -1
- package/dist/server/modules/terminal/template-reverse-proxy-service.js +71 -3
- package/dist/server/modules/terminal/template-reverse-proxy-service.js.map +1 -1
- package/dist/server/modules/terminal/terminal-controller.d.ts +3 -0
- package/dist/server/modules/terminal/terminal-controller.js +41 -0
- package/dist/server/modules/terminal/terminal-controller.js.map +1 -1
- package/dist/server/modules/workbench/workbench-service.d.ts +3 -0
- package/dist/server/modules/workbench/workbench-service.js +4 -3
- package/dist/server/modules/workbench/workbench-service.js.map +1 -1
- package/dist/server/modules/workbench/workspace-file-watcher.d.ts +14 -6
- package/dist/server/modules/workbench/workspace-file-watcher.js +267 -57
- package/dist/server/modules/workbench/workspace-file-watcher.js.map +1 -1
- package/dist/server/modules/workbench/workspace-panel-snapshot-service.d.ts +2 -0
- package/dist/server/modules/workbench/workspace-panel-snapshot-service.js +32 -3
- package/dist/server/modules/workbench/workspace-panel-snapshot-service.js.map +1 -1
- package/dist/server/modules/worktree/worktree-manager.d.ts +9 -1
- package/dist/server/modules/worktree/worktree-manager.js +9 -1
- package/dist/server/modules/worktree/worktree-manager.js.map +1 -1
- package/dist/server/routes/assistant.js +49 -0
- package/dist/server/routes/assistant.js.map +1 -1
- package/dist/server/routes/auth.js +4 -0
- package/dist/server/routes/auth.js.map +1 -1
- package/dist/server/routes/butler.js +5 -0
- package/dist/server/routes/butler.js.map +1 -1
- package/dist/server/routes/sessions.js +1 -0
- package/dist/server/routes/sessions.js.map +1 -1
- package/dist/server/routes/system.d.ts +2 -1
- package/dist/server/routes/system.js +13 -1
- package/dist/server/routes/system.js.map +1 -1
- package/dist/server/server/create-server.d.ts +18 -0
- package/dist/server/server/create-server.js +113 -20
- package/dist/server/server/create-server.js.map +1 -1
- package/dist/server/shared/utils/tokens.d.ts +3 -1
- package/dist/server/shared/utils/tokens.js +9 -2
- package/dist/server/shared/utils/tokens.js.map +1 -1
- package/dist/server/storage/repositories/assistant-automation-run-repository.d.ts +12 -0
- package/dist/server/storage/repositories/assistant-automation-run-repository.js +139 -0
- package/dist/server/storage/repositories/assistant-automation-run-repository.js.map +1 -0
- package/dist/server/storage/repositories/assistant-automation-task-repository.d.ts +17 -0
- package/dist/server/storage/repositories/assistant-automation-task-repository.js +179 -0
- package/dist/server/storage/repositories/assistant-automation-task-repository.js.map +1 -0
- package/dist/server/storage/repositories/assistant-sandbox-workspace-repository.d.ts +18 -0
- package/dist/server/storage/repositories/assistant-sandbox-workspace-repository.js +191 -0
- package/dist/server/storage/repositories/assistant-sandbox-workspace-repository.js.map +1 -0
- package/dist/server/storage/repositories/auth-device-repository.d.ts +22 -0
- package/dist/server/storage/repositories/auth-device-repository.js +97 -0
- package/dist/server/storage/repositories/auth-device-repository.js.map +1 -0
- package/dist/server/storage/repositories/auth-device-session-repository.d.ts +17 -0
- package/dist/server/storage/repositories/auth-device-session-repository.js +82 -0
- package/dist/server/storage/repositories/auth-device-session-repository.js.map +1 -0
- package/dist/server/storage/repositories/auth-login-event-repository.d.ts +9 -0
- package/dist/server/storage/repositories/auth-login-event-repository.js +53 -0
- package/dist/server/storage/repositories/auth-login-event-repository.js.map +1 -0
- package/dist/server/storage/repositories/auth-token-repository.d.ts +4 -0
- package/dist/server/storage/repositories/auth-token-repository.js +58 -5
- package/dist/server/storage/repositories/auth-token-repository.js.map +1 -1
- package/dist/server/storage/repositories/butler-control-session-repository.js +27 -3
- package/dist/server/storage/repositories/butler-control-session-repository.js.map +1 -1
- package/dist/server/storage/repositories/butler-control-timer-repository.d.ts +15 -0
- package/dist/server/storage/repositories/butler-control-timer-repository.js +157 -0
- package/dist/server/storage/repositories/butler-control-timer-repository.js.map +1 -0
- package/dist/server/storage/repositories/butler-follow-up-task-repository.js +21 -3
- package/dist/server/storage/repositories/butler-follow-up-task-repository.js.map +1 -1
- package/dist/server/storage/repositories/instance-relay-tunnel-identity-repository.d.ts +8 -0
- package/dist/server/storage/repositories/instance-relay-tunnel-identity-repository.js +52 -0
- package/dist/server/storage/repositories/instance-relay-tunnel-identity-repository.js.map +1 -0
- package/dist/server/storage/repositories/instance-relay-tunnel-repository.d.ts +10 -0
- package/dist/server/storage/repositories/instance-relay-tunnel-repository.js +153 -0
- package/dist/server/storage/repositories/instance-relay-tunnel-repository.js.map +1 -0
- package/dist/server/storage/repositories/instance-tailscale-repository.js +6 -3
- package/dist/server/storage/repositories/instance-tailscale-repository.js.map +1 -1
- package/dist/server/storage/repositories/managed-skill-repository.d.ts +2 -1
- package/dist/server/storage/repositories/managed-skill-repository.js +14 -4
- package/dist/server/storage/repositories/managed-skill-repository.js.map +1 -1
- package/dist/server/storage/repositories/session-message-attachment-repository.d.ts +2 -0
- package/dist/server/storage/repositories/session-message-attachment-repository.js +24 -0
- package/dist/server/storage/repositories/session-message-attachment-repository.js.map +1 -1
- package/dist/server/storage/repositories/user-preference-profile-repository.js +6 -3
- package/dist/server/storage/repositories/user-preference-profile-repository.js.map +1 -1
- package/dist/server/storage/sqlite/client.js +534 -2
- package/dist/server/storage/sqlite/client.js.map +1 -1
- package/dist/server/storage/sqlite/schema.sql +228 -4
- package/dist/server/types/domain.d.ts +170 -2
- package/dist/server/ws/workbench-ws-hub.d.ts +14 -8
- package/dist/server/ws/workbench-ws-hub.js +369 -209
- package/dist/server/ws/workbench-ws-hub.js.map +1 -1
- package/dist/server/ws/ws-auth-guard.js +1 -4
- package/dist/server/ws/ws-auth-guard.js.map +1 -1
- package/dist/server/ws/ws-server.d.ts +1 -1
- package/dist/server/ws/ws-server.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/codex-resume-history.d.ts +1 -0
- package/node_modules/@codingns/session-sync-core/dist/codex-resume-history.js +80 -0
- package/node_modules/@codingns/session-sync-core/dist/codex-resume-history.js.map +1 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.d.ts +5 -1
- package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.js +122 -4
- package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/providers/codex.d.ts +17 -1
- package/node_modules/@codingns/session-sync-core/dist/providers/codex.js +437 -51
- package/node_modules/@codingns/session-sync-core/dist/providers/codex.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/providers/gemini.d.ts +7 -1
- package/node_modules/@codingns/session-sync-core/dist/providers/gemini.js +240 -27
- package/node_modules/@codingns/session-sync-core/dist/providers/gemini.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/providers/kimi.d.ts +5 -1
- package/node_modules/@codingns/session-sync-core/dist/providers/kimi.js +108 -2
- package/node_modules/@codingns/session-sync-core/dist/providers/kimi.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/providers/opencode.d.ts +3 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js +101 -8
- package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/providers/utils.d.ts +1 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/utils.js +4 -1
- package/node_modules/@codingns/session-sync-core/dist/providers/utils.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.js +44 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.d.ts +5 -1
- package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js +153 -60
- package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/runtime/types.d.ts +1 -0
- package/node_modules/@codingns/session-sync-core/dist/services.d.ts +1 -0
- package/node_modules/@codingns/session-sync-core/dist/services.js +24 -8
- package/node_modules/@codingns/session-sync-core/dist/services.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/types.d.ts +6 -0
- package/package.json +1 -1
- package/scripts/postinstall.mjs +0 -33
- package/dist/public/assets/index-BlOinYqR.js +0 -122
- package/dist/public/assets/index-Dg_7g6lA.css +0 -1
|
@@ -19,6 +19,7 @@ import { discoverWorkspaceSessionsInRuntime } from "../provider/provider-discove
|
|
|
19
19
|
import { createTaskManager } from "../tasks/task-manager.js";
|
|
20
20
|
import { HOST_TASK_TYPES } from "../tasks/task-types.js";
|
|
21
21
|
import { CodexAppServerHelperClient } from "./codex-app-server-helper-client.js";
|
|
22
|
+
import { CodingnsProviderSessionDeleteCli } from "./provider-session-delete-cli.js";
|
|
22
23
|
const RECONSTRUCTED_FORK_TARGET_PROVIDERS = new Set(["codex", "claude-code", "opencode"]);
|
|
23
24
|
const FORK_RECONSTRUCTION_PAGE_SIZE = 200;
|
|
24
25
|
const MAX_FORK_DEPTH = 4;
|
|
@@ -32,9 +33,13 @@ const SESSION_START_DEFERRED_PROVIDERS = new Set([
|
|
|
32
33
|
]);
|
|
33
34
|
const MUTABLE_HISTORY_TAIL_REFRESH_INTERVAL_MS = 1_200;
|
|
34
35
|
const WORKSPACE_DISCOVERY_BACKGROUND_MAX_AGE_MS = 15_000;
|
|
36
|
+
const WORKSPACE_DISCOVERY_SCAN_CONCURRENCY = 2;
|
|
35
37
|
const PROVIDER_CAPABILITY_CACHE_MAX_AGE_MS = 5_000;
|
|
36
38
|
const WORKSPACE_DISCOVERY_PERSIST_BATCH_SIZE = 25;
|
|
37
39
|
const SESSION_TRANSACTION_HOTSPOT_THRESHOLD_MS = 150;
|
|
40
|
+
const WORKSPACE_STATE_REFRESH_COOLDOWN_MS = 1_500;
|
|
41
|
+
const SQLITE_BUSY_RETRY_LIMIT = 3;
|
|
42
|
+
const SQLITE_BUSY_RETRY_DELAY_MS = 100;
|
|
38
43
|
export class SessionHistoryService {
|
|
39
44
|
db;
|
|
40
45
|
workspaceRepository;
|
|
@@ -50,6 +55,7 @@ export class SessionHistoryService {
|
|
|
50
55
|
capabilityService;
|
|
51
56
|
sessionActivityAuthorityService;
|
|
52
57
|
sessionForkRepository;
|
|
58
|
+
providerSessionDeleteCli;
|
|
53
59
|
claudeCodeHomeDir;
|
|
54
60
|
codexModelOptionsService;
|
|
55
61
|
openCodeModelOptionsService;
|
|
@@ -59,10 +65,12 @@ export class SessionHistoryService {
|
|
|
59
65
|
providerSessionDiscoveryConfig;
|
|
60
66
|
taskManager;
|
|
61
67
|
workspaceDiscoveryStatuses = new Map();
|
|
62
|
-
|
|
68
|
+
workspaceStateRefreshStatuses = new Map();
|
|
63
69
|
providerCapabilityCache = new Map();
|
|
64
70
|
liveActivityObservationResolvers = new Set();
|
|
71
|
+
sessionDeletedObservers = new Set();
|
|
65
72
|
workspaceSessionRelations = new Map();
|
|
73
|
+
workspaceStateRefreshTaskSequence = 0;
|
|
66
74
|
constructor(db, workspaceRepository, sessionBindingRepository, sessionChangedFileService, sessionIndexRepository, sessionMessageAttachmentService, sessionStateRepository, sessionStatusSnapshotRepository, config, sessionActivityAuthorityService = new SessionActivityAuthorityService(), sessionMessageOriginRepository = null, sessionForkRepository = null, adapterOverrides = {}, taskManager = createTaskManager()) {
|
|
67
75
|
this.db = db;
|
|
68
76
|
this.workspaceRepository = workspaceRepository;
|
|
@@ -75,6 +83,8 @@ export class SessionHistoryService {
|
|
|
75
83
|
this.sessionMessageOriginRepository = sessionMessageOriginRepository;
|
|
76
84
|
this.sessionActivityAuthorityService = sessionActivityAuthorityService;
|
|
77
85
|
this.sessionForkRepository = sessionForkRepository ?? new SessionForkRepository(db);
|
|
86
|
+
this.providerSessionDeleteCli =
|
|
87
|
+
adapterOverrides.providerSessionDeleteCli ?? new CodingnsProviderSessionDeleteCli(config);
|
|
78
88
|
this.taskManager = taskManager;
|
|
79
89
|
this.claudeCodeHomeDir = config.claudeCodeHomeDir;
|
|
80
90
|
this.providerCliCommandPaths = {
|
|
@@ -102,7 +112,8 @@ export class SessionHistoryService {
|
|
|
102
112
|
new CodexAdapter({
|
|
103
113
|
homeDir: config.codexHomeDir,
|
|
104
114
|
forkTransportFactory: adapterOverrides.codexForkTransportFactory
|
|
105
|
-
?? createCodexForkTransportFactory(config.codexCliPath, config.codexHomeDir)
|
|
115
|
+
?? createCodexForkTransportFactory(config.codexCliPath, config.codexHomeDir),
|
|
116
|
+
threadControlTransportFactory: createCodexThreadControlTransportFactory(config.codexCliPath, config.codexHomeDir)
|
|
106
117
|
}),
|
|
107
118
|
new GeminiAdapter({
|
|
108
119
|
homeDir: config.geminiHomeDir,
|
|
@@ -147,6 +158,14 @@ export class SessionHistoryService {
|
|
|
147
158
|
}
|
|
148
159
|
};
|
|
149
160
|
}
|
|
161
|
+
registerSessionDeletedObserver(observer) {
|
|
162
|
+
this.sessionDeletedObservers.add(observer);
|
|
163
|
+
return {
|
|
164
|
+
close: () => {
|
|
165
|
+
this.sessionDeletedObservers.delete(observer);
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
}
|
|
150
169
|
registerBackgroundTasks() {
|
|
151
170
|
if (!this.taskManager.has(HOST_TASK_TYPES.workspaceDiscovery)) {
|
|
152
171
|
this.taskManager.register({
|
|
@@ -159,6 +178,7 @@ export class SessionHistoryService {
|
|
|
159
178
|
this.taskManager.register({
|
|
160
179
|
taskType: HOST_TASK_TYPES.workspaceDiscoveryScan,
|
|
161
180
|
executionLane: "helper_process",
|
|
181
|
+
concurrency: WORKSPACE_DISCOVERY_SCAN_CONCURRENCY,
|
|
162
182
|
helperProcessHandler: "session.workspace_discovery",
|
|
163
183
|
run: async ({ config, workspacePath, knownSessions }, context) => await discoverWorkspaceSessionsInRuntime(config, workspacePath, knownSessions, context.signal)
|
|
164
184
|
});
|
|
@@ -319,6 +339,12 @@ export class SessionHistoryService {
|
|
|
319
339
|
originRef: null
|
|
320
340
|
};
|
|
321
341
|
}
|
|
342
|
+
resolveMessageOriginByClientRequestId(sessionId, clientRequestId, messageId, updatedAt) {
|
|
343
|
+
if (!this.sessionMessageOriginRepository || !clientRequestId || !messageId) {
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
this.sessionMessageOriginRepository.resolveMessageId(sessionId, clientRequestId, messageId, updatedAt);
|
|
347
|
+
}
|
|
322
348
|
async findLatestUserMessage(sessionId, content, maxAttempts = 12, minTimestamp = null) {
|
|
323
349
|
const binding = this.getBindingOrThrow(sessionId);
|
|
324
350
|
const acceptedContents = new Set((Array.isArray(content) ? content : [content]).filter((value) => value.trim().length > 0));
|
|
@@ -1066,6 +1092,44 @@ export class SessionHistoryService {
|
|
|
1066
1092
|
isArchived: nextArchivedState
|
|
1067
1093
|
});
|
|
1068
1094
|
}
|
|
1095
|
+
async deleteSession(sessionId, userId) {
|
|
1096
|
+
const binding = this.getBindingOrThrow(sessionId);
|
|
1097
|
+
const existing = this.getSessionListItemOrThrow(sessionId, userId);
|
|
1098
|
+
if (existing.runningState === "starting" || existing.runningState === "running") {
|
|
1099
|
+
throw new AppError({
|
|
1100
|
+
statusCode: 409,
|
|
1101
|
+
errorCode: "SESSION_DELETE_RUNNING",
|
|
1102
|
+
detail: "运行中的会话不能直接删除,请先等当前执行结束",
|
|
1103
|
+
field: "sessionId"
|
|
1104
|
+
});
|
|
1105
|
+
}
|
|
1106
|
+
try {
|
|
1107
|
+
await this.providerSessionDeleteCli.deleteSession({
|
|
1108
|
+
provider: binding.provider,
|
|
1109
|
+
providerSessionId: binding.providerSessionId,
|
|
1110
|
+
rawStoreRef: binding.rawStoreRef
|
|
1111
|
+
});
|
|
1112
|
+
}
|
|
1113
|
+
catch (error) {
|
|
1114
|
+
if (!isProviderSessionMissing(error)) {
|
|
1115
|
+
throw mapSessionProviderError(error);
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
for (const observer of this.sessionDeletedObservers) {
|
|
1119
|
+
await observer({
|
|
1120
|
+
sessionId,
|
|
1121
|
+
userId,
|
|
1122
|
+
workspaceId: binding.workspaceId,
|
|
1123
|
+
remainingWorkspaceSessionCount: this.countOtherWorkspaceSessions(binding.workspaceId, sessionId)
|
|
1124
|
+
});
|
|
1125
|
+
}
|
|
1126
|
+
const deleteTransaction = this.db.transaction((targetSessionId) => {
|
|
1127
|
+
this.detachSessionRelationsBeforeDelete(targetSessionId);
|
|
1128
|
+
this.deleteSessionById(targetSessionId);
|
|
1129
|
+
});
|
|
1130
|
+
deleteTransaction(sessionId);
|
|
1131
|
+
this.removeWorkspaceSessionRelation(sessionId);
|
|
1132
|
+
}
|
|
1069
1133
|
async renameSessionTitle(sessionId, userId, title) {
|
|
1070
1134
|
const binding = this.getBindingOrThrow(sessionId);
|
|
1071
1135
|
const existing = this.getSessionListItemOrThrow(sessionId, userId);
|
|
@@ -1215,7 +1279,7 @@ export class SessionHistoryService {
|
|
|
1215
1279
|
const existingIndex = existing
|
|
1216
1280
|
? this.sessionIndexRepository.findIndexRecordBySessionId(existing.sessionId)
|
|
1217
1281
|
: null;
|
|
1218
|
-
|
|
1282
|
+
const nextBinding = {
|
|
1219
1283
|
sessionId,
|
|
1220
1284
|
workspaceId: workspace.id,
|
|
1221
1285
|
provider: session.provider,
|
|
@@ -1223,7 +1287,10 @@ export class SessionHistoryService {
|
|
|
1223
1287
|
rawStoreRef: session.rawStoreRef,
|
|
1224
1288
|
createdAt,
|
|
1225
1289
|
updatedAt: timestamp
|
|
1226
|
-
}
|
|
1290
|
+
};
|
|
1291
|
+
if (!areEquivalentSessionBindings(existing, nextBinding)) {
|
|
1292
|
+
this.sessionBindingRepository.upsert(nextBinding);
|
|
1293
|
+
}
|
|
1227
1294
|
const preservedParentSessionId = existingIndex?.parentSessionId
|
|
1228
1295
|
?? this.sessionForkRepository.findBySessionId(sessionId)?.parentSessionId
|
|
1229
1296
|
?? null;
|
|
@@ -1231,7 +1298,7 @@ export class SessionHistoryService {
|
|
|
1231
1298
|
? this.sessionIndexRepository.findIndexRecordBySessionId(preservedParentSessionId)?.title ?? null
|
|
1232
1299
|
: null;
|
|
1233
1300
|
const preservedTitle = resolvePersistedSessionTitle(session.provider, session.title, existingIndex?.title ?? null, preservedParentTitle);
|
|
1234
|
-
|
|
1301
|
+
const nextIndex = {
|
|
1235
1302
|
sessionId,
|
|
1236
1303
|
workspaceId: workspace.id,
|
|
1237
1304
|
provider: session.provider,
|
|
@@ -1243,12 +1310,15 @@ export class SessionHistoryService {
|
|
|
1243
1310
|
subagentLabel: existingIndex?.subagentLabel ?? null,
|
|
1244
1311
|
title: preservedTitle,
|
|
1245
1312
|
messageCount: session.messageCount,
|
|
1246
|
-
isArchived: resolveDiscoveredArchiveState(existingIndex?.isArchived ?? false, session.isArchived),
|
|
1313
|
+
isArchived: resolveDiscoveredArchiveState(session.provider, existingIndex?.isArchived ?? false, session.isArchived),
|
|
1247
1314
|
lastMessageAt: session.lastMessageAt,
|
|
1248
1315
|
createdAt,
|
|
1249
1316
|
updatedAt: timestamp
|
|
1250
|
-
}
|
|
1251
|
-
|
|
1317
|
+
};
|
|
1318
|
+
if (!areEquivalentSessionIndexRecords(existingIndex, nextIndex)) {
|
|
1319
|
+
this.sessionIndexRepository.upsert(nextIndex);
|
|
1320
|
+
}
|
|
1321
|
+
const nextSnapshot = {
|
|
1252
1322
|
sessionId,
|
|
1253
1323
|
syncStatus: currentSnapshot?.syncStatus ?? "idle",
|
|
1254
1324
|
syncCursor: currentSnapshot?.syncCursor ?? null,
|
|
@@ -1257,13 +1327,17 @@ export class SessionHistoryService {
|
|
|
1257
1327
|
lastErrorDetail: currentSnapshot?.lastErrorDetail ?? null,
|
|
1258
1328
|
resumedAt: currentSnapshot?.resumedAt ?? null,
|
|
1259
1329
|
updatedAt: timestamp
|
|
1260
|
-
}
|
|
1330
|
+
};
|
|
1331
|
+
if (!areEquivalentSessionStatusSnapshots(currentSnapshot, nextSnapshot)) {
|
|
1332
|
+
this.sessionStatusSnapshotRepository.upsert(nextSnapshot);
|
|
1333
|
+
}
|
|
1261
1334
|
discoveredSessionIds.set(buildProviderSessionKey(session.provider, session.providerSessionId), sessionId);
|
|
1262
1335
|
persistedSessions.push({
|
|
1263
1336
|
session,
|
|
1264
1337
|
sessionId,
|
|
1265
1338
|
createdAt,
|
|
1266
|
-
existingIndex
|
|
1339
|
+
existingIndex,
|
|
1340
|
+
pass1Index: nextIndex
|
|
1267
1341
|
});
|
|
1268
1342
|
}
|
|
1269
1343
|
});
|
|
@@ -1293,7 +1367,7 @@ export class SessionHistoryService {
|
|
|
1293
1367
|
const resolvedParentTitle = resolvedParentSessionId
|
|
1294
1368
|
? this.sessionIndexRepository.findIndexRecordBySessionId(resolvedParentSessionId)?.title ?? null
|
|
1295
1369
|
: null;
|
|
1296
|
-
|
|
1370
|
+
const nextIndex = {
|
|
1297
1371
|
sessionId: persistedSession.sessionId,
|
|
1298
1372
|
workspaceId: workspace.id,
|
|
1299
1373
|
provider: persistedSession.session.provider,
|
|
@@ -1315,11 +1389,14 @@ export class SessionHistoryService {
|
|
|
1315
1389
|
?? null,
|
|
1316
1390
|
title: resolvePersistedSessionTitle(persistedSession.session.provider, persistedSession.session.title, persistedSession.existingIndex?.title ?? null, resolvedParentTitle),
|
|
1317
1391
|
messageCount: persistedSession.session.messageCount,
|
|
1318
|
-
isArchived: resolveDiscoveredArchiveState(persistedSession.existingIndex?.isArchived ?? false, persistedSession.session.isArchived),
|
|
1392
|
+
isArchived: resolveDiscoveredArchiveState(persistedSession.session.provider, persistedSession.existingIndex?.isArchived ?? false, persistedSession.session.isArchived),
|
|
1319
1393
|
lastMessageAt: persistedSession.session.lastMessageAt,
|
|
1320
1394
|
createdAt: persistedSession.createdAt,
|
|
1321
1395
|
updatedAt: timestamp
|
|
1322
|
-
}
|
|
1396
|
+
};
|
|
1397
|
+
if (!areEquivalentSessionIndexRecords(persistedSession.pass1Index, nextIndex)) {
|
|
1398
|
+
this.sessionIndexRepository.upsert(nextIndex);
|
|
1399
|
+
}
|
|
1323
1400
|
}
|
|
1324
1401
|
});
|
|
1325
1402
|
const persistPass2StartedAt = Date.now();
|
|
@@ -1387,7 +1464,22 @@ export class SessionHistoryService {
|
|
|
1387
1464
|
discoveredSessions: sessions.length,
|
|
1388
1465
|
returnedSessions: nextItems.length,
|
|
1389
1466
|
discoveryComplete: discovery.isComplete,
|
|
1390
|
-
providerDiagnostics: (discovery.providerDiagnostics ?? []).map((entry) =>
|
|
1467
|
+
providerDiagnostics: (discovery.providerDiagnostics ?? []).map((entry) => {
|
|
1468
|
+
const scannedFiles = entry.scannedFiles ?? 0;
|
|
1469
|
+
const skippedByMtimeSize = entry.skippedByMtimeSize ?? 0;
|
|
1470
|
+
const parsedFiles = entry.parsedFiles ?? 0;
|
|
1471
|
+
const bytesRead = entry.bytesRead ?? 0;
|
|
1472
|
+
return [
|
|
1473
|
+
entry.provider,
|
|
1474
|
+
entry.status,
|
|
1475
|
+
`${Math.round(entry.durationMs)}ms`,
|
|
1476
|
+
`sessions=${entry.sessionCount}`,
|
|
1477
|
+
`scanned=${scannedFiles}`,
|
|
1478
|
+
`skipped=${skippedByMtimeSize}`,
|
|
1479
|
+
`parsed=${parsedFiles}`,
|
|
1480
|
+
`bytes=${bytesRead}`
|
|
1481
|
+
].join(":");
|
|
1482
|
+
}),
|
|
1391
1483
|
refreshedStates: refreshCandidates.length,
|
|
1392
1484
|
discoverMs: discoverDurationMs,
|
|
1393
1485
|
persistMs: persistDurationMs,
|
|
@@ -1542,13 +1634,6 @@ export class SessionHistoryService {
|
|
|
1542
1634
|
const originByMessageId = new Map(originRows
|
|
1543
1635
|
.filter((row) => row.messageId)
|
|
1544
1636
|
.map((row) => [row.messageId, row]));
|
|
1545
|
-
const unresolvedRows = originRepository.listUnresolvedBySessionAndContents(sessionId, [...new Set(messages.map((message) => message.content).filter((content) => content.trim().length > 0))]);
|
|
1546
|
-
const unresolvedByContent = new Map();
|
|
1547
|
-
for (const row of unresolvedRows) {
|
|
1548
|
-
const current = unresolvedByContent.get(row.content) ?? [];
|
|
1549
|
-
current.push(row);
|
|
1550
|
-
unresolvedByContent.set(row.content, current);
|
|
1551
|
-
}
|
|
1552
1637
|
return messages.map((message) => {
|
|
1553
1638
|
const resolved = originByMessageId.get(message.messageId) ?? null;
|
|
1554
1639
|
if (resolved) {
|
|
@@ -1565,21 +1650,10 @@ export class SessionHistoryService {
|
|
|
1565
1650
|
originRef: null
|
|
1566
1651
|
};
|
|
1567
1652
|
}
|
|
1568
|
-
const candidates = unresolvedByContent.get(message.content) ?? [];
|
|
1569
|
-
const matched = candidates.find((row) => isMessageAtOrAfter(message.timestamp, row.createdAt)) ?? null;
|
|
1570
|
-
if (!matched) {
|
|
1571
|
-
return {
|
|
1572
|
-
...message,
|
|
1573
|
-
origin: null,
|
|
1574
|
-
originRef: null
|
|
1575
|
-
};
|
|
1576
|
-
}
|
|
1577
|
-
originRepository.resolveMessageId(sessionId, matched.clientRequestId, message.messageId, message.timestamp);
|
|
1578
|
-
unresolvedByContent.set(message.content, candidates.filter((candidate) => candidate.clientRequestId !== matched.clientRequestId));
|
|
1579
1653
|
return {
|
|
1580
1654
|
...message,
|
|
1581
|
-
origin:
|
|
1582
|
-
originRef:
|
|
1655
|
+
origin: null,
|
|
1656
|
+
originRef: null
|
|
1583
1657
|
};
|
|
1584
1658
|
});
|
|
1585
1659
|
}
|
|
@@ -1718,6 +1792,9 @@ export class SessionHistoryService {
|
|
|
1718
1792
|
if (shouldSkipClaudePendingBinding(binding)) {
|
|
1719
1793
|
return;
|
|
1720
1794
|
}
|
|
1795
|
+
if (!shouldSyncSessionTitleFromProvider(binding.provider, currentIndex.title)) {
|
|
1796
|
+
return;
|
|
1797
|
+
}
|
|
1721
1798
|
const nextTitle = (await this.providerDiscoveryHelperClient.readSessionTitle({
|
|
1722
1799
|
config: this.providerSessionDiscoveryConfig,
|
|
1723
1800
|
provider: binding.provider,
|
|
@@ -1926,13 +2003,71 @@ export class SessionHistoryService {
|
|
|
1926
2003
|
return;
|
|
1927
2004
|
}
|
|
1928
2005
|
const inflightKey = `${workspaceId}:${userId}`;
|
|
1929
|
-
|
|
2006
|
+
const refreshState = this.getOrCreateWorkspaceStateRefreshStatus(inflightKey);
|
|
2007
|
+
const now = Date.now();
|
|
2008
|
+
refreshState.lastRequestedAt = now;
|
|
2009
|
+
refreshState.phase = refreshState.phase === "fresh" ? "stale" : refreshState.phase;
|
|
2010
|
+
refreshState.dirtyReasons.add("workspace.discovery.deferred_state_refresh");
|
|
2011
|
+
mergeWorkspaceStateRefreshSessions(refreshState.pendingSessions, sessions);
|
|
2012
|
+
if (refreshState.phase === "running" && refreshState.runningPromise) {
|
|
1930
2013
|
return;
|
|
1931
2014
|
}
|
|
2015
|
+
if (this.isWorkspaceStateRefreshCoolingDown(refreshState, now)) {
|
|
2016
|
+
refreshState.phase = "stale";
|
|
2017
|
+
this.ensureWorkspaceStateRefreshCooldownTimer(inflightKey, workspaceId, userId, refreshState);
|
|
2018
|
+
return;
|
|
2019
|
+
}
|
|
2020
|
+
this.startWorkspaceStateRefreshTask(inflightKey, workspaceId, userId, refreshState);
|
|
2021
|
+
}
|
|
2022
|
+
getOrCreateWorkspaceStateRefreshStatus(key) {
|
|
2023
|
+
const existing = this.workspaceStateRefreshStatuses.get(key);
|
|
2024
|
+
if (existing) {
|
|
2025
|
+
return existing;
|
|
2026
|
+
}
|
|
2027
|
+
const created = {
|
|
2028
|
+
phase: "fresh",
|
|
2029
|
+
dirtyReasons: new Set(),
|
|
2030
|
+
pendingSessions: new Map(),
|
|
2031
|
+
runningPromise: null,
|
|
2032
|
+
cooldownTimer: null,
|
|
2033
|
+
lastRequestedAt: null,
|
|
2034
|
+
lastStartedAt: null,
|
|
2035
|
+
lastCompletedAt: null,
|
|
2036
|
+
lastFailedAt: null,
|
|
2037
|
+
nextAllowedAt: null,
|
|
2038
|
+
runningTaskId: null
|
|
2039
|
+
};
|
|
2040
|
+
this.workspaceStateRefreshStatuses.set(key, created);
|
|
2041
|
+
return created;
|
|
2042
|
+
}
|
|
2043
|
+
isWorkspaceStateRefreshCoolingDown(state, now) {
|
|
2044
|
+
if (state.nextAllowedAt === null || now >= state.nextAllowedAt) {
|
|
2045
|
+
return false;
|
|
2046
|
+
}
|
|
2047
|
+
return state.phase === "cooldown" || state.phase === "failed";
|
|
2048
|
+
}
|
|
2049
|
+
startWorkspaceStateRefreshTask(key, workspaceId, userId, state) {
|
|
2050
|
+
if (state.runningPromise) {
|
|
2051
|
+
return;
|
|
2052
|
+
}
|
|
2053
|
+
const sessions = [...state.pendingSessions.values()];
|
|
2054
|
+
if (sessions.length === 0) {
|
|
2055
|
+
state.phase = "fresh";
|
|
2056
|
+
state.dirtyReasons.clear();
|
|
2057
|
+
return;
|
|
2058
|
+
}
|
|
2059
|
+
state.pendingSessions.clear();
|
|
2060
|
+
state.phase = "running";
|
|
2061
|
+
state.lastStartedAt = Date.now();
|
|
2062
|
+
state.runningTaskId = `${key}:${++this.workspaceStateRefreshTaskSequence}`;
|
|
1932
2063
|
const startedAt = Date.now();
|
|
1933
2064
|
const task = delay(0)
|
|
1934
2065
|
.then(() => this.refreshRecentSessionStates(sessions, userId))
|
|
1935
2066
|
.then(() => {
|
|
2067
|
+
state.lastCompletedAt = Date.now();
|
|
2068
|
+
state.phase = "cooldown";
|
|
2069
|
+
state.nextAllowedAt = state.lastCompletedAt + WORKSPACE_STATE_REFRESH_COOLDOWN_MS;
|
|
2070
|
+
state.dirtyReasons.clear();
|
|
1936
2071
|
logPerformance("workspace.refresh_recent_session_states", Date.now() - startedAt, {
|
|
1937
2072
|
workspaceId,
|
|
1938
2073
|
refreshedStates: sessions.length
|
|
@@ -1941,6 +2076,9 @@ export class SessionHistoryService {
|
|
|
1941
2076
|
});
|
|
1942
2077
|
})
|
|
1943
2078
|
.catch((error) => {
|
|
2079
|
+
state.lastFailedAt = Date.now();
|
|
2080
|
+
state.phase = "failed";
|
|
2081
|
+
state.nextAllowedAt = state.lastFailedAt + WORKSPACE_STATE_REFRESH_COOLDOWN_MS;
|
|
1944
2082
|
logPerformance("workspace.refresh_recent_session_states.failed", Date.now() - startedAt, {
|
|
1945
2083
|
workspaceId,
|
|
1946
2084
|
refreshedStates: sessions.length,
|
|
@@ -1951,9 +2089,42 @@ export class SessionHistoryService {
|
|
|
1951
2089
|
});
|
|
1952
2090
|
})
|
|
1953
2091
|
.finally(() => {
|
|
1954
|
-
|
|
2092
|
+
state.runningPromise = null;
|
|
2093
|
+
state.runningTaskId = null;
|
|
2094
|
+
if (state.pendingSessions.size === 0) {
|
|
2095
|
+
if (state.phase === "cooldown") {
|
|
2096
|
+
this.ensureWorkspaceStateRefreshCooldownTimer(key, workspaceId, userId, state);
|
|
2097
|
+
return;
|
|
2098
|
+
}
|
|
2099
|
+
if (state.phase === "failed") {
|
|
2100
|
+
this.ensureWorkspaceStateRefreshCooldownTimer(key, workspaceId, userId, state);
|
|
2101
|
+
return;
|
|
2102
|
+
}
|
|
2103
|
+
state.phase = "fresh";
|
|
2104
|
+
return;
|
|
2105
|
+
}
|
|
2106
|
+
state.phase = "stale";
|
|
2107
|
+
this.ensureWorkspaceStateRefreshCooldownTimer(key, workspaceId, userId, state);
|
|
1955
2108
|
});
|
|
1956
|
-
|
|
2109
|
+
state.runningPromise = task;
|
|
2110
|
+
}
|
|
2111
|
+
ensureWorkspaceStateRefreshCooldownTimer(key, workspaceId, userId, state) {
|
|
2112
|
+
if (state.cooldownTimer) {
|
|
2113
|
+
return;
|
|
2114
|
+
}
|
|
2115
|
+
const now = Date.now();
|
|
2116
|
+
const delayMs = Math.max(0, (state.nextAllowedAt ?? now) - now);
|
|
2117
|
+
state.cooldownTimer = setTimeout(() => {
|
|
2118
|
+
state.cooldownTimer = null;
|
|
2119
|
+
if (state.pendingSessions.size === 0) {
|
|
2120
|
+
state.phase = "fresh";
|
|
2121
|
+
state.dirtyReasons.clear();
|
|
2122
|
+
state.nextAllowedAt = null;
|
|
2123
|
+
return;
|
|
2124
|
+
}
|
|
2125
|
+
state.phase = "stale";
|
|
2126
|
+
this.startWorkspaceStateRefreshTask(key, workspaceId, userId, state);
|
|
2127
|
+
}, delayMs);
|
|
1957
2128
|
}
|
|
1958
2129
|
async cleanupStaleHiddenSessions(workspaceId, userId, sessions) {
|
|
1959
2130
|
const discoveredProviderSessionIds = new Set(sessions.map((session) => buildProviderSessionKey(session.provider, session.providerSessionId)));
|
|
@@ -1981,6 +2152,7 @@ export class SessionHistoryService {
|
|
|
1981
2152
|
}
|
|
1982
2153
|
const deleteTransaction = this.db.transaction((ids) => {
|
|
1983
2154
|
for (const sessionId of ids) {
|
|
2155
|
+
this.detachSessionRelationsBeforeDelete(sessionId);
|
|
1984
2156
|
this.deleteSessionById(sessionId);
|
|
1985
2157
|
}
|
|
1986
2158
|
});
|
|
@@ -2250,10 +2422,14 @@ export class SessionHistoryService {
|
|
|
2250
2422
|
}
|
|
2251
2423
|
}
|
|
2252
2424
|
deleteSessionById(sessionId) {
|
|
2425
|
+
this.sessionMessageAttachmentService.deleteSessionAttachments(sessionId);
|
|
2253
2426
|
this.sessionChangedFileService.deleteBySessionId(sessionId);
|
|
2254
2427
|
this.db
|
|
2255
2428
|
.prepare("DELETE FROM session_message_attachments WHERE session_id = ?")
|
|
2256
2429
|
.run(sessionId);
|
|
2430
|
+
this.db
|
|
2431
|
+
.prepare("DELETE FROM session_message_origins WHERE session_id = ?")
|
|
2432
|
+
.run(sessionId);
|
|
2257
2433
|
this.db
|
|
2258
2434
|
.prepare("DELETE FROM session_send_queue WHERE session_id = ?")
|
|
2259
2435
|
.run(sessionId);
|
|
@@ -2276,6 +2452,82 @@ export class SessionHistoryService {
|
|
|
2276
2452
|
.prepare("DELETE FROM session_bindings WHERE session_id = ?")
|
|
2277
2453
|
.run(sessionId);
|
|
2278
2454
|
}
|
|
2455
|
+
countOtherWorkspaceSessions(workspaceId, sessionId) {
|
|
2456
|
+
const row = this.db
|
|
2457
|
+
.prepare(`SELECT COUNT(*) AS count
|
|
2458
|
+
FROM session_bindings
|
|
2459
|
+
WHERE workspace_id = ?
|
|
2460
|
+
AND session_id != ?`)
|
|
2461
|
+
.get(workspaceId, sessionId);
|
|
2462
|
+
return Number(row?.count ?? 0);
|
|
2463
|
+
}
|
|
2464
|
+
detachSessionRelationsBeforeDelete(sessionId) {
|
|
2465
|
+
this.db
|
|
2466
|
+
.prepare(`UPDATE session_indices
|
|
2467
|
+
SET parent_session_id = NULL
|
|
2468
|
+
WHERE parent_session_id = ?`)
|
|
2469
|
+
.run(sessionId);
|
|
2470
|
+
this.db
|
|
2471
|
+
.prepare(`DELETE FROM session_forks
|
|
2472
|
+
WHERE parent_session_id = ?
|
|
2473
|
+
OR fork_source_session_id = ?`)
|
|
2474
|
+
.run(sessionId, sessionId);
|
|
2475
|
+
this.db
|
|
2476
|
+
.prepare("DELETE FROM butler_control_sessions WHERE session_id = ?")
|
|
2477
|
+
.run(sessionId);
|
|
2478
|
+
const butlerSessionIds = this.db
|
|
2479
|
+
.prepare(`SELECT id
|
|
2480
|
+
FROM butler_sessions
|
|
2481
|
+
WHERE session_id = ?`)
|
|
2482
|
+
.all(sessionId)
|
|
2483
|
+
.map((row) => String(row.id));
|
|
2484
|
+
if (butlerSessionIds.length === 0) {
|
|
2485
|
+
return;
|
|
2486
|
+
}
|
|
2487
|
+
const butlerPlaceholders = butlerSessionIds.map(() => "?").join(", ");
|
|
2488
|
+
const checkpointIds = this.db
|
|
2489
|
+
.prepare(`SELECT id
|
|
2490
|
+
FROM session_checkpoints
|
|
2491
|
+
WHERE butler_session_id IN (${butlerPlaceholders})`)
|
|
2492
|
+
.all(...butlerSessionIds)
|
|
2493
|
+
.map((row) => String(row.id));
|
|
2494
|
+
if (checkpointIds.length > 0) {
|
|
2495
|
+
const checkpointPlaceholders = checkpointIds.map(() => "?").join(", ");
|
|
2496
|
+
this.db
|
|
2497
|
+
.prepare(`UPDATE project_memories
|
|
2498
|
+
SET source_checkpoint_id = NULL
|
|
2499
|
+
WHERE source_checkpoint_id IN (${checkpointPlaceholders})`)
|
|
2500
|
+
.run(...checkpointIds);
|
|
2501
|
+
}
|
|
2502
|
+
this.db
|
|
2503
|
+
.prepare(`UPDATE project_memories
|
|
2504
|
+
SET source_butler_session_id = NULL
|
|
2505
|
+
WHERE source_butler_session_id IN (${butlerPlaceholders})`)
|
|
2506
|
+
.run(...butlerSessionIds);
|
|
2507
|
+
this.db
|
|
2508
|
+
.prepare(`UPDATE patrol_runs
|
|
2509
|
+
SET butler_session_id = NULL
|
|
2510
|
+
WHERE butler_session_id IN (${butlerPlaceholders})`)
|
|
2511
|
+
.run(...butlerSessionIds);
|
|
2512
|
+
this.db
|
|
2513
|
+
.prepare(`UPDATE verification_runs
|
|
2514
|
+
SET butler_session_id = NULL
|
|
2515
|
+
WHERE butler_session_id IN (${butlerPlaceholders})`)
|
|
2516
|
+
.run(...butlerSessionIds);
|
|
2517
|
+
this.db
|
|
2518
|
+
.prepare("DELETE FROM butler_sessions WHERE session_id = ?")
|
|
2519
|
+
.run(sessionId);
|
|
2520
|
+
}
|
|
2521
|
+
removeWorkspaceSessionRelation(sessionId) {
|
|
2522
|
+
for (const relationMap of this.workspaceSessionRelations.values()) {
|
|
2523
|
+
relationMap.delete(sessionId);
|
|
2524
|
+
for (const relation of relationMap.values()) {
|
|
2525
|
+
if (relation.parentSessionId === sessionId) {
|
|
2526
|
+
relation.parentSessionId = null;
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2279
2531
|
buildKnownSessionSummaries(sessions, workspacePath) {
|
|
2280
2532
|
return sessions
|
|
2281
2533
|
.filter((session) => !this.isPendingSessionAlias(session))
|
|
@@ -2451,6 +2703,19 @@ function createCodexForkTransportFactory(commandPath, homeDir) {
|
|
|
2451
2703
|
};
|
|
2452
2704
|
};
|
|
2453
2705
|
}
|
|
2706
|
+
function createCodexThreadControlTransportFactory(commandPath, homeDir) {
|
|
2707
|
+
return () => {
|
|
2708
|
+
const client = new CodexAppServerHelperClient(commandPath, { homeDir });
|
|
2709
|
+
const transport = client.createThreadControlTransport();
|
|
2710
|
+
return {
|
|
2711
|
+
...transport,
|
|
2712
|
+
close() {
|
|
2713
|
+
transport.close();
|
|
2714
|
+
client.dispose();
|
|
2715
|
+
}
|
|
2716
|
+
};
|
|
2717
|
+
};
|
|
2718
|
+
}
|
|
2454
2719
|
function buildInspectionActivityObservation(sessionId, inspection, observedAt) {
|
|
2455
2720
|
const resolvedRunningState = inspection.runningState === "failed"
|
|
2456
2721
|
? "failed"
|
|
@@ -2532,6 +2797,11 @@ function buildSessionStateRefreshCandidates(items, recentCount) {
|
|
|
2532
2797
|
}
|
|
2533
2798
|
return Array.from(deduped.values());
|
|
2534
2799
|
}
|
|
2800
|
+
function mergeWorkspaceStateRefreshSessions(target, sessions) {
|
|
2801
|
+
for (const session of sessions) {
|
|
2802
|
+
target.set(session.sessionId, session);
|
|
2803
|
+
}
|
|
2804
|
+
}
|
|
2535
2805
|
function isSessionStateRefreshCandidate(item) {
|
|
2536
2806
|
return item.activityState === "running"
|
|
2537
2807
|
|| item.runningState === "starting"
|
|
@@ -2609,12 +2879,20 @@ function mergeSessionIndexRecord(input) {
|
|
|
2609
2879
|
subagentLabel: input.target?.subagentLabel ?? input.source?.subagentLabel ?? null,
|
|
2610
2880
|
title: pickPreferredSessionTitle(input.target?.title ?? null, input.source?.title ?? null),
|
|
2611
2881
|
messageCount: Math.max(input.target?.messageCount ?? 0, input.source?.messageCount ?? 0),
|
|
2612
|
-
isArchived:
|
|
2882
|
+
isArchived: mergePersistedArchiveState(input.provider, input.target?.isArchived, input.source?.isArchived),
|
|
2613
2883
|
lastMessageAt: pickLaterIso(input.target?.lastMessageAt ?? null, input.source?.lastMessageAt ?? null),
|
|
2614
2884
|
createdAt: pickEarlierIso(input.target?.createdAt ?? null, input.source?.createdAt ?? null) ?? input.timestamp,
|
|
2615
2885
|
updatedAt: input.timestamp
|
|
2616
2886
|
};
|
|
2617
2887
|
}
|
|
2888
|
+
function mergePersistedArchiveState(provider, targetArchived, sourceArchived) {
|
|
2889
|
+
// 只有 Codex 这类真实支持归档的 provider 才认底层归档真相;
|
|
2890
|
+
// 其他 provider 的归档完全由 Host 本地索引维护,不能让旧副本把恢复状态再刷回去。
|
|
2891
|
+
if (shouldUseProviderDiscoveredArchiveState(provider)) {
|
|
2892
|
+
return Boolean(targetArchived || sourceArchived);
|
|
2893
|
+
}
|
|
2894
|
+
return targetArchived ?? sourceArchived ?? false;
|
|
2895
|
+
}
|
|
2618
2896
|
function mergeSessionStatusSnapshot(input) {
|
|
2619
2897
|
if (!input.target && !input.source) {
|
|
2620
2898
|
return null;
|
|
@@ -2915,12 +3193,16 @@ function isCloseClaudeSessionTimestamp(left, right, maxGapMs = 2 * 60 * 1000) {
|
|
|
2915
3193
|
}
|
|
2916
3194
|
return Math.abs(leftAt - rightAt) <= maxGapMs;
|
|
2917
3195
|
}
|
|
2918
|
-
function resolveDiscoveredArchiveState(existingArchived, discoveredArchived) {
|
|
2919
|
-
if (
|
|
2920
|
-
return
|
|
3196
|
+
function resolveDiscoveredArchiveState(provider, existingArchived, discoveredArchived) {
|
|
3197
|
+
if (!shouldUseProviderDiscoveredArchiveState(provider)) {
|
|
3198
|
+
return existingArchived;
|
|
2921
3199
|
}
|
|
2922
3200
|
return discoveredArchived === true;
|
|
2923
3201
|
}
|
|
3202
|
+
function shouldUseProviderDiscoveredArchiveState(provider) {
|
|
3203
|
+
// 当前只有 Codex 的归档能稳定映射到底层文件位置;其余 provider 一律信本地 session_indices。
|
|
3204
|
+
return provider === "codex";
|
|
3205
|
+
}
|
|
2924
3206
|
function isMessageAtOrAfter(timestamp, minTimestamp) {
|
|
2925
3207
|
if (!minTimestamp) {
|
|
2926
3208
|
return true;
|
|
@@ -2942,6 +3224,9 @@ function isAcceptedUserMessageTimestamp(provider, timestamp, minTimestamp) {
|
|
|
2942
3224
|
function isSyntheticKimiHistoryTimestamp(timestamp) {
|
|
2943
3225
|
return timestamp.startsWith("2020-01-01T00:");
|
|
2944
3226
|
}
|
|
3227
|
+
function isProviderSessionMissing(error) {
|
|
3228
|
+
return error instanceof Error && error.message === "PROVIDER_SESSION_NOT_FOUND";
|
|
3229
|
+
}
|
|
2945
3230
|
function createDeliveredHistoryMessageState() {
|
|
2946
3231
|
return {
|
|
2947
3232
|
signaturesByMessageId: new Map(),
|
|
@@ -3153,6 +3438,16 @@ function isSyntheticCodexSessionTitle(title) {
|
|
|
3153
3438
|
return (/^rollout-\d{4}-\d{2}-\d{2}t/i.test(title) ||
|
|
3154
3439
|
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(title));
|
|
3155
3440
|
}
|
|
3441
|
+
function shouldSyncSessionTitleFromProvider(provider, currentTitle) {
|
|
3442
|
+
const normalizedTitle = currentTitle?.trim() ?? "";
|
|
3443
|
+
if (normalizedTitle.length === 0) {
|
|
3444
|
+
return true;
|
|
3445
|
+
}
|
|
3446
|
+
if (provider === "codex" && isSyntheticCodexSessionTitle(normalizedTitle)) {
|
|
3447
|
+
return true;
|
|
3448
|
+
}
|
|
3449
|
+
return false;
|
|
3450
|
+
}
|
|
3156
3451
|
function shouldRemoveHiddenClaudeDebugSession(session) {
|
|
3157
3452
|
const normalizedRawStoreRef = session.rawStoreRef.replaceAll("\\", "/");
|
|
3158
3453
|
if (normalizedRawStoreRef.includes("/subagents/")) {
|
|
@@ -3325,6 +3620,56 @@ function getAbortMessage(reason) {
|
|
|
3325
3620
|
}
|
|
3326
3621
|
return "任务已取消";
|
|
3327
3622
|
}
|
|
3623
|
+
function areEquivalentSessionBindings(current, next) {
|
|
3624
|
+
if (!current) {
|
|
3625
|
+
return false;
|
|
3626
|
+
}
|
|
3627
|
+
return (current.sessionId === next.sessionId &&
|
|
3628
|
+
current.workspaceId === next.workspaceId &&
|
|
3629
|
+
current.provider === next.provider &&
|
|
3630
|
+
current.providerSessionId === next.providerSessionId &&
|
|
3631
|
+
current.rawStoreRef === next.rawStoreRef &&
|
|
3632
|
+
current.createdAt === next.createdAt);
|
|
3633
|
+
}
|
|
3634
|
+
function areEquivalentSessionIndexRecords(current, next) {
|
|
3635
|
+
if (!current) {
|
|
3636
|
+
return false;
|
|
3637
|
+
}
|
|
3638
|
+
return (current.sessionId === next.sessionId &&
|
|
3639
|
+
current.workspaceId === next.workspaceId &&
|
|
3640
|
+
current.provider === next.provider &&
|
|
3641
|
+
(current.parentSessionId ?? null) === (next.parentSessionId ?? null) &&
|
|
3642
|
+
(current.sessionKind ?? "default") === (next.sessionKind ?? "default") &&
|
|
3643
|
+
(current.annotationSourceMessageId ?? null) === (next.annotationSourceMessageId ?? null) &&
|
|
3644
|
+
(current.annotationSourceText ?? null) === (next.annotationSourceText ?? null) &&
|
|
3645
|
+
(current.isSubagent ?? false) === (next.isSubagent ?? false) &&
|
|
3646
|
+
(current.subagentLabel ?? null) === (next.subagentLabel ?? null) &&
|
|
3647
|
+
current.title === next.title &&
|
|
3648
|
+
current.messageCount === next.messageCount &&
|
|
3649
|
+
current.isArchived === next.isArchived &&
|
|
3650
|
+
(current.lastMessageAt ?? null) === (next.lastMessageAt ?? null) &&
|
|
3651
|
+
current.createdAt === next.createdAt);
|
|
3652
|
+
}
|
|
3653
|
+
function areEquivalentSessionStatusSnapshots(current, next) {
|
|
3654
|
+
if (!current) {
|
|
3655
|
+
return false;
|
|
3656
|
+
}
|
|
3657
|
+
return (current.sessionId === next.sessionId &&
|
|
3658
|
+
current.syncStatus === next.syncStatus &&
|
|
3659
|
+
(current.syncCursor ?? null) === (next.syncCursor ?? null) &&
|
|
3660
|
+
(current.lastSyncAt ?? null) === (next.lastSyncAt ?? null) &&
|
|
3661
|
+
(current.lastErrorCode ?? null) === (next.lastErrorCode ?? null) &&
|
|
3662
|
+
(current.lastErrorDetail ?? null) === (next.lastErrorDetail ?? null) &&
|
|
3663
|
+
(current.resumedAt ?? null) === (next.resumedAt ?? null));
|
|
3664
|
+
}
|
|
3665
|
+
function isSqliteBusyError(error) {
|
|
3666
|
+
if (!error || typeof error !== "object") {
|
|
3667
|
+
return false;
|
|
3668
|
+
}
|
|
3669
|
+
const sqliteCode = "code" in error ? error.code : null;
|
|
3670
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3671
|
+
return sqliteCode === "SQLITE_BUSY" || message.includes("database is locked");
|
|
3672
|
+
}
|
|
3328
3673
|
async function runBatchedTransactions(items, batchSize, transaction, logOptions) {
|
|
3329
3674
|
const normalizedBatchSize = Math.max(1, Math.floor(batchSize) || 1);
|
|
3330
3675
|
let batchCount = 0;
|
|
@@ -3332,7 +3677,20 @@ async function runBatchedTransactions(items, batchSize, transaction, logOptions)
|
|
|
3332
3677
|
for (let index = 0; index < items.length; index += normalizedBatchSize) {
|
|
3333
3678
|
const batch = items.slice(index, index + normalizedBatchSize);
|
|
3334
3679
|
const batchStartedAt = Date.now();
|
|
3335
|
-
|
|
3680
|
+
let retryCount = 0;
|
|
3681
|
+
while (true) {
|
|
3682
|
+
try {
|
|
3683
|
+
transaction(batch);
|
|
3684
|
+
break;
|
|
3685
|
+
}
|
|
3686
|
+
catch (error) {
|
|
3687
|
+
if (!isSqliteBusyError(error) || retryCount >= SQLITE_BUSY_RETRY_LIMIT) {
|
|
3688
|
+
throw error;
|
|
3689
|
+
}
|
|
3690
|
+
retryCount += 1;
|
|
3691
|
+
await delay(SQLITE_BUSY_RETRY_DELAY_MS * retryCount);
|
|
3692
|
+
}
|
|
3693
|
+
}
|
|
3336
3694
|
const batchDurationMs = Date.now() - batchStartedAt;
|
|
3337
3695
|
const nextBatchIndex = batchCount + 1;
|
|
3338
3696
|
if (logOptions) {
|
|
@@ -3341,6 +3699,7 @@ async function runBatchedTransactions(items, batchSize, transaction, logOptions)
|
|
|
3341
3699
|
batchIndex: nextBatchIndex,
|
|
3342
3700
|
batchSize: batch.length,
|
|
3343
3701
|
batchStartIndex: index,
|
|
3702
|
+
retryCount,
|
|
3344
3703
|
totalItems: items.length,
|
|
3345
3704
|
configuredBatchSize: normalizedBatchSize
|
|
3346
3705
|
}, {
|