@jingyi0605/codingns 0.2.0 → 0.3.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 +44 -0
- package/bin/codingns.mjs +918 -55
- package/dist/public/assets/{TerminalPage-BlbQuWi1.js → TerminalPage-Dfw1QUqW.js} +19 -19
- package/dist/public/assets/index-DR2rPNi7.css +1 -0
- package/dist/public/assets/index-DTOruahn.js +114 -0
- package/dist/public/index.html +2 -2
- package/dist/server/config/env.d.ts +3 -0
- package/dist/server/config/env.js +35 -3
- package/dist/server/config/env.js.map +1 -1
- package/dist/server/modules/assistant-capability/assistant-capability-controller.d.ts +89 -0
- package/dist/server/modules/assistant-capability/assistant-capability-controller.js +138 -0
- package/dist/server/modules/assistant-capability/assistant-capability-controller.js.map +1 -0
- package/dist/server/modules/assistant-capability/assistant-capability-service.d.ts +115 -0
- package/dist/server/modules/assistant-capability/assistant-capability-service.js +241 -0
- package/dist/server/modules/assistant-capability/assistant-capability-service.js.map +1 -0
- package/dist/server/modules/butler/butler-control-session-service.d.ts +3 -1
- package/dist/server/modules/butler/butler-control-session-service.js +96 -33
- package/dist/server/modules/butler/butler-control-session-service.js.map +1 -1
- package/dist/server/modules/butler/butler-follow-up-scheduler.d.ts +9 -0
- package/dist/server/modules/butler/butler-follow-up-scheduler.js +47 -11
- package/dist/server/modules/butler/butler-follow-up-scheduler.js.map +1 -1
- package/dist/server/modules/butler/butler-follow-up-service.d.ts +7 -1
- package/dist/server/modules/butler/butler-follow-up-service.js +10 -0
- package/dist/server/modules/butler/butler-follow-up-service.js.map +1 -1
- package/dist/server/modules/butler/butler-session-service.d.ts +3 -1
- package/dist/server/modules/butler/butler-session-service.js +82 -16
- package/dist/server/modules/butler/butler-session-service.js.map +1 -1
- package/dist/server/modules/butler/butler-session-summary-service.d.ts +8 -1
- package/dist/server/modules/butler/butler-session-summary-service.js +34 -7
- package/dist/server/modules/butler/butler-session-summary-service.js.map +1 -1
- package/dist/server/modules/butler/context-aggregator.js +44 -13
- package/dist/server/modules/butler/context-aggregator.js.map +1 -1
- package/dist/server/modules/butler/patrol-scheduler.d.ts +9 -0
- package/dist/server/modules/butler/patrol-scheduler.js +63 -9
- package/dist/server/modules/butler/patrol-scheduler.js.map +1 -1
- package/dist/server/modules/butler/session-summary-scheduler.d.ts +9 -0
- package/dist/server/modules/butler/session-summary-scheduler.js +47 -11
- package/dist/server/modules/butler/session-summary-scheduler.js.map +1 -1
- package/dist/server/modules/debug-target/debug-runtime-reconciliation-scheduler.d.ts +38 -0
- package/dist/server/modules/debug-target/debug-runtime-reconciliation-scheduler.js +99 -0
- package/dist/server/modules/debug-target/debug-runtime-reconciliation-scheduler.js.map +1 -0
- package/dist/server/modules/debug-target/debug-target-controller.d.ts +70 -0
- package/dist/server/modules/debug-target/debug-target-controller.js +113 -0
- package/dist/server/modules/debug-target/debug-target-controller.js.map +1 -0
- package/dist/server/modules/debug-target/debug-target-service.d.ts +105 -0
- package/dist/server/modules/debug-target/debug-target-service.js +1644 -0
- package/dist/server/modules/debug-target/debug-target-service.js.map +1 -0
- package/dist/server/modules/debug-target/framework-compatibility-matrix.d.ts +4 -0
- package/dist/server/modules/debug-target/framework-compatibility-matrix.js +45 -0
- package/dist/server/modules/debug-target/framework-compatibility-matrix.js.map +1 -0
- package/dist/server/modules/debug-target/launch-adapter-registry.d.ts +25 -0
- package/dist/server/modules/debug-target/launch-adapter-registry.js +445 -0
- package/dist/server/modules/debug-target/launch-adapter-registry.js.map +1 -0
- package/dist/server/modules/file/file-constants.d.ts +1 -0
- package/dist/server/modules/file/file-constants.js +1 -0
- package/dist/server/modules/file/file-constants.js.map +1 -1
- package/dist/server/modules/file/file-content-service.d.ts +2 -1
- package/dist/server/modules/file/file-content-service.js +53 -0
- package/dist/server/modules/file/file-content-service.js.map +1 -1
- package/dist/server/modules/file/file-controller.js +12 -3
- package/dist/server/modules/file/file-controller.js.map +1 -1
- package/dist/server/modules/file/file-preview-link-service.js +6 -37
- package/dist/server/modules/file/file-preview-link-service.js.map +1 -1
- package/dist/server/modules/file/file-preview-service.d.ts +6 -12
- package/dist/server/modules/file/file-preview-service.js +114 -28
- package/dist/server/modules/file/file-preview-service.js.map +1 -1
- package/dist/server/modules/file/file-preview-types.d.ts +37 -0
- package/dist/server/modules/file/file-preview-types.js +84 -0
- package/dist/server/modules/file/file-preview-types.js.map +1 -0
- package/dist/server/modules/git/commit-orchestrator.d.ts +4 -1
- package/dist/server/modules/git/commit-orchestrator.js +18 -1
- package/dist/server/modules/git/commit-orchestrator.js.map +1 -1
- package/dist/server/modules/git/git-auth.d.ts +25 -0
- package/dist/server/modules/git/git-auth.js +88 -0
- package/dist/server/modules/git/git-auth.js.map +1 -0
- package/dist/server/modules/git/git-controller.d.ts +12 -0
- package/dist/server/modules/git/git-controller.js +18 -1
- package/dist/server/modules/git/git-controller.js.map +1 -1
- package/dist/server/modules/git/git-read-service.d.ts +3 -1
- package/dist/server/modules/git/git-read-service.js +119 -2
- package/dist/server/modules/git/git-read-service.js.map +1 -1
- package/dist/server/modules/git/git-remote-credential-service.d.ts +9 -0
- package/dist/server/modules/git/git-remote-credential-service.js +76 -0
- package/dist/server/modules/git/git-remote-credential-service.js.map +1 -0
- package/dist/server/modules/git/git-write-service.d.ts +5 -2
- package/dist/server/modules/git/git-write-service.js +33 -17
- package/dist/server/modules/git/git-write-service.js.map +1 -1
- package/dist/server/modules/git/types.d.ts +26 -0
- package/dist/server/modules/git/workspace-repo-guard.js +3 -2
- package/dist/server/modules/git/workspace-repo-guard.js.map +1 -1
- package/dist/server/modules/provider/codex-model-options.d.ts +3 -1
- package/dist/server/modules/provider/codex-model-options.js +4 -1
- package/dist/server/modules/provider/codex-model-options.js.map +1 -1
- package/dist/server/modules/provider/opencode-model-options.d.ts +3 -1
- package/dist/server/modules/provider/opencode-model-options.js +5 -1
- package/dist/server/modules/provider/opencode-model-options.js.map +1 -1
- package/dist/server/modules/provider/provider-discovery-helper-client.d.ts +24 -0
- package/dist/server/modules/provider/provider-discovery-helper-client.js +14 -0
- package/dist/server/modules/provider/provider-discovery-helper-client.js.map +1 -1
- package/dist/server/modules/provider/provider-discovery-helper-process.js +54 -0
- package/dist/server/modules/provider/provider-discovery-helper-process.js.map +1 -1
- package/dist/server/modules/sessions/session-activity-authority-service.js +13 -1
- package/dist/server/modules/sessions/session-activity-authority-service.js.map +1 -1
- package/dist/server/modules/sessions/session-activity-inspector.js +21 -5
- package/dist/server/modules/sessions/session-activity-inspector.js.map +1 -1
- package/dist/server/modules/sessions/session-controller.d.ts +5 -0
- package/dist/server/modules/sessions/session-controller.js +16 -0
- package/dist/server/modules/sessions/session-controller.js.map +1 -1
- package/dist/server/modules/sessions/session-history-service.d.ts +27 -7
- package/dist/server/modules/sessions/session-history-service.js +439 -81
- package/dist/server/modules/sessions/session-history-service.js.map +1 -1
- package/dist/server/modules/sessions/session-live-runtime-service.d.ts +2 -1
- package/dist/server/modules/sessions/session-live-runtime-service.js +12 -0
- package/dist/server/modules/sessions/session-live-runtime-service.js.map +1 -1
- package/dist/server/modules/skills/skill-controller.d.ts +23 -0
- package/dist/server/modules/skills/skill-controller.js +35 -0
- package/dist/server/modules/skills/skill-controller.js.map +1 -0
- package/dist/server/modules/skills/skill-manager-service.d.ts +86 -0
- package/dist/server/modules/skills/skill-manager-service.js +557 -0
- package/dist/server/modules/skills/skill-manager-service.js.map +1 -0
- package/dist/server/modules/skills/skill-reconciler.d.ts +21 -0
- package/dist/server/modules/skills/skill-reconciler.js +99 -0
- package/dist/server/modules/skills/skill-reconciler.js.map +1 -0
- package/dist/server/modules/skills/skill-sync-planner.d.ts +8 -0
- package/dist/server/modules/skills/skill-sync-planner.js +20 -0
- package/dist/server/modules/skills/skill-sync-planner.js.map +1 -0
- package/dist/server/modules/skills/skill-target-adapter.d.ts +34 -0
- package/dist/server/modules/skills/skill-target-adapter.js +65 -0
- package/dist/server/modules/skills/skill-target-adapter.js.map +1 -0
- package/dist/server/modules/tailscale/tailscale-controller.d.ts +15 -0
- package/dist/server/modules/tailscale/tailscale-controller.js +33 -0
- package/dist/server/modules/tailscale/tailscale-controller.js.map +1 -0
- package/dist/server/modules/tailscale/tailscale-helper-client.d.ts +41 -0
- package/dist/server/modules/tailscale/tailscale-helper-client.js +135 -0
- package/dist/server/modules/tailscale/tailscale-helper-client.js.map +1 -0
- package/dist/server/modules/tailscale/tailscale-helper-process.d.ts +1 -0
- package/dist/server/modules/tailscale/tailscale-helper-process.js +327 -0
- package/dist/server/modules/tailscale/tailscale-helper-process.js.map +1 -0
- package/dist/server/modules/tailscale/tailscale-manager.d.ts +41 -0
- package/dist/server/modules/tailscale/tailscale-manager.js +259 -0
- package/dist/server/modules/tailscale/tailscale-manager.js.map +1 -0
- package/dist/server/modules/tailscale/tailscale-service.d.ts +43 -0
- package/dist/server/modules/tailscale/tailscale-service.js +201 -0
- package/dist/server/modules/tailscale/tailscale-service.js.map +1 -0
- package/dist/server/modules/tasks/event-loop-monitor.d.ts +21 -0
- package/dist/server/modules/tasks/event-loop-monitor.js +64 -0
- package/dist/server/modules/tasks/event-loop-monitor.js.map +1 -0
- package/dist/server/modules/tasks/observability-controller.d.ts +30 -0
- package/dist/server/modules/tasks/observability-controller.js +44 -0
- package/dist/server/modules/tasks/observability-controller.js.map +1 -0
- package/dist/server/modules/tasks/observability-service.d.ts +32 -0
- package/dist/server/modules/tasks/observability-service.js +104 -0
- package/dist/server/modules/tasks/observability-service.js.map +1 -0
- package/dist/server/modules/tasks/scheduler-metrics.d.ts +41 -0
- package/dist/server/modules/tasks/scheduler-metrics.js +92 -0
- package/dist/server/modules/tasks/scheduler-metrics.js.map +1 -0
- package/dist/server/modules/tasks/task-activity-log.d.ts +39 -0
- package/dist/server/modules/tasks/task-activity-log.js +43 -0
- package/dist/server/modules/tasks/task-activity-log.js.map +1 -0
- package/dist/server/modules/tasks/task-helper-client.d.ts +11 -0
- package/dist/server/modules/tasks/task-helper-client.js +132 -0
- package/dist/server/modules/tasks/task-helper-client.js.map +1 -0
- package/dist/server/modules/tasks/task-helper-process-handlers.d.ts +16 -0
- package/dist/server/modules/tasks/task-helper-process-handlers.js +14 -0
- package/dist/server/modules/tasks/task-helper-process-handlers.js.map +1 -0
- package/dist/server/modules/tasks/task-helper-process.d.ts +1 -0
- package/dist/server/modules/tasks/task-helper-process.js +49 -0
- package/dist/server/modules/tasks/task-helper-process.js.map +1 -0
- package/dist/server/modules/tasks/task-lane-executors.d.ts +2 -0
- package/dist/server/modules/tasks/task-lane-executors.js +15 -0
- package/dist/server/modules/tasks/task-lane-executors.js.map +1 -0
- package/dist/server/modules/tasks/task-manager.d.ts +15 -0
- package/dist/server/modules/tasks/task-manager.js +36 -0
- package/dist/server/modules/tasks/task-manager.js.map +1 -0
- package/dist/server/modules/tasks/task-metrics.d.ts +9 -0
- package/dist/server/modules/tasks/task-metrics.js +81 -0
- package/dist/server/modules/tasks/task-metrics.js.map +1 -0
- package/dist/server/modules/tasks/task-registry.d.ts +7 -0
- package/dist/server/modules/tasks/task-registry.js +21 -0
- package/dist/server/modules/tasks/task-registry.js.map +1 -0
- package/dist/server/modules/tasks/task-scheduler.d.ts +31 -0
- package/dist/server/modules/tasks/task-scheduler.js +473 -0
- package/dist/server/modules/tasks/task-scheduler.js.map +1 -0
- package/dist/server/modules/tasks/task-types.d.ts +106 -0
- package/dist/server/modules/tasks/task-types.js +23 -0
- package/dist/server/modules/tasks/task-types.js.map +1 -0
- package/dist/server/modules/terminal/command-template-service.d.ts +4 -0
- package/dist/server/modules/terminal/command-template-service.js +5 -3
- package/dist/server/modules/terminal/command-template-service.js.map +1 -1
- package/dist/server/modules/terminal/runtime/terminal-log-spooler.d.ts +7 -3
- package/dist/server/modules/terminal/runtime/terminal-log-spooler.js +95 -15
- package/dist/server/modules/terminal/runtime/terminal-log-spooler.js.map +1 -1
- package/dist/server/modules/terminal/runtime/terminal-log-writer-client.d.ts +21 -0
- package/dist/server/modules/terminal/runtime/terminal-log-writer-client.js +144 -0
- package/dist/server/modules/terminal/runtime/terminal-log-writer-client.js.map +1 -0
- package/dist/server/modules/terminal/runtime/terminal-log-writer-process.d.ts +1 -0
- package/dist/server/modules/terminal/runtime/terminal-log-writer-process.js +187 -0
- package/dist/server/modules/terminal/runtime/terminal-log-writer-process.js.map +1 -0
- package/dist/server/modules/terminal/terminal-service.d.ts +12 -0
- package/dist/server/modules/terminal/terminal-service.js +34 -17
- package/dist/server/modules/terminal/terminal-service.js.map +1 -1
- package/dist/server/modules/workbench/workbench-service.d.ts +23 -2
- package/dist/server/modules/workbench/workbench-service.js +126 -15
- package/dist/server/modules/workbench/workbench-service.js.map +1 -1
- package/dist/server/modules/workbench/workspace-panel-snapshot-service.d.ts +5 -1
- package/dist/server/modules/workbench/workspace-panel-snapshot-service.js +88 -19
- package/dist/server/modules/workbench/workspace-panel-snapshot-service.js.map +1 -1
- package/dist/server/modules/workspace/workspace-code-composition.d.ts +2 -0
- package/dist/server/modules/workspace/workspace-code-composition.js +154 -0
- package/dist/server/modules/workspace/workspace-code-composition.js.map +1 -0
- package/dist/server/modules/workspace/workspace-controller.d.ts +14 -0
- package/dist/server/modules/workspace/workspace-controller.js +19 -0
- package/dist/server/modules/workspace/workspace-controller.js.map +1 -1
- package/dist/server/modules/workspace/workspace-service.d.ts +21 -14
- package/dist/server/modules/workspace/workspace-service.js +183 -234
- package/dist/server/modules/workspace/workspace-service.js.map +1 -1
- package/dist/server/modules/worktree/worktree-cleanup-service.d.ts +35 -0
- package/dist/server/modules/worktree/worktree-cleanup-service.js +210 -0
- package/dist/server/modules/worktree/worktree-cleanup-service.js.map +1 -0
- package/dist/server/modules/worktree/worktree-controller.d.ts +44 -0
- package/dist/server/modules/worktree/worktree-controller.js +40 -0
- package/dist/server/modules/worktree/worktree-controller.js.map +1 -0
- package/dist/server/modules/worktree/worktree-manager.d.ts +34 -0
- package/dist/server/modules/worktree/worktree-manager.js +292 -0
- package/dist/server/modules/worktree/worktree-manager.js.map +1 -0
- package/dist/server/modules/worktree/worktree-merge-service.d.ts +52 -0
- package/dist/server/modules/worktree/worktree-merge-service.js +293 -0
- package/dist/server/modules/worktree/worktree-merge-service.js.map +1 -0
- package/dist/server/modules/worktree/worktree-sync-service.d.ts +23 -0
- package/dist/server/modules/worktree/worktree-sync-service.js +166 -0
- package/dist/server/modules/worktree/worktree-sync-service.js.map +1 -0
- package/dist/server/routes/assistant.d.ts +3 -0
- package/dist/server/routes/assistant.js +15 -0
- package/dist/server/routes/assistant.js.map +1 -0
- package/dist/server/routes/debug-targets.d.ts +3 -0
- package/dist/server/routes/debug-targets.js +15 -0
- package/dist/server/routes/debug-targets.js.map +1 -0
- package/dist/server/routes/git.js +2 -0
- package/dist/server/routes/git.js.map +1 -1
- package/dist/server/routes/observability.d.ts +3 -0
- package/dist/server/routes/observability.js +7 -0
- package/dist/server/routes/observability.js.map +1 -0
- package/dist/server/routes/skills.d.ts +3 -0
- package/dist/server/routes/skills.js +7 -0
- package/dist/server/routes/skills.js.map +1 -0
- package/dist/server/routes/system.d.ts +3 -0
- package/dist/server/routes/system.js +9 -0
- package/dist/server/routes/system.js.map +1 -0
- package/dist/server/routes/workspaces.js +2 -0
- package/dist/server/routes/workspaces.js.map +1 -1
- package/dist/server/routes/worktrees.d.ts +3 -0
- package/dist/server/routes/worktrees.js +8 -0
- package/dist/server/routes/worktrees.js.map +1 -0
- package/dist/server/server/create-server.d.ts +46 -0
- package/dist/server/server/create-server.js +141 -12
- package/dist/server/server/create-server.js.map +1 -1
- package/dist/server/shared/utils/command-availability.d.ts +1 -0
- package/dist/server/shared/utils/command-availability.js +26 -3
- package/dist/server/shared/utils/command-availability.js.map +1 -1
- package/dist/server/shared/utils/secret-box.d.ts +2 -0
- package/dist/server/shared/utils/secret-box.js +29 -0
- package/dist/server/shared/utils/secret-box.js.map +1 -0
- package/dist/server/shared/utils/terminal-debug-log.js +5 -3
- package/dist/server/shared/utils/terminal-debug-log.js.map +1 -1
- package/dist/server/storage/repositories/ai-fallback-edit-repository.d.ts +11 -0
- package/dist/server/storage/repositories/ai-fallback-edit-repository.js +118 -0
- package/dist/server/storage/repositories/ai-fallback-edit-repository.js.map +1 -0
- package/dist/server/storage/repositories/debug-runtime-session-repository.d.ts +11 -0
- package/dist/server/storage/repositories/debug-runtime-session-repository.js +100 -0
- package/dist/server/storage/repositories/debug-runtime-session-repository.js.map +1 -0
- package/dist/server/storage/repositories/debug-service-repository.d.ts +9 -0
- package/dist/server/storage/repositories/debug-service-repository.js +99 -0
- package/dist/server/storage/repositories/debug-service-repository.js.map +1 -0
- package/dist/server/storage/repositories/debug-target-repository.d.ts +11 -0
- package/dist/server/storage/repositories/debug-target-repository.js +100 -0
- package/dist/server/storage/repositories/debug-target-repository.js.map +1 -0
- package/dist/server/storage/repositories/framework-analysis-result-repository.d.ts +9 -0
- package/dist/server/storage/repositories/framework-analysis-result-repository.js +98 -0
- package/dist/server/storage/repositories/framework-analysis-result-repository.js.map +1 -0
- package/dist/server/storage/repositories/git-remote-credential-repository.d.ts +9 -0
- package/dist/server/storage/repositories/git-remote-credential-repository.js +51 -0
- package/dist/server/storage/repositories/git-remote-credential-repository.js.map +1 -0
- package/dist/server/storage/repositories/instance-tailscale-repository.d.ts +10 -0
- package/dist/server/storage/repositories/instance-tailscale-repository.js +112 -0
- package/dist/server/storage/repositories/instance-tailscale-repository.js.map +1 -0
- package/dist/server/storage/repositories/managed-skill-repository.d.ts +11 -0
- package/dist/server/storage/repositories/managed-skill-repository.js +102 -0
- package/dist/server/storage/repositories/managed-skill-repository.js.map +1 -0
- package/dist/server/storage/repositories/port-lease-repository.d.ts +12 -0
- package/dist/server/storage/repositories/port-lease-repository.js +124 -0
- package/dist/server/storage/repositories/port-lease-repository.js.map +1 -0
- package/dist/server/storage/repositories/runtime-binding-repository.d.ts +10 -0
- package/dist/server/storage/repositories/runtime-binding-repository.js +89 -0
- package/dist/server/storage/repositories/runtime-binding-repository.js.map +1 -0
- package/dist/server/storage/repositories/skill-target-binding-repository.d.ts +10 -0
- package/dist/server/storage/repositories/skill-target-binding-repository.js +77 -0
- package/dist/server/storage/repositories/skill-target-binding-repository.js.map +1 -0
- package/dist/server/storage/repositories/terminal-command-template-repository.js +77 -4
- package/dist/server/storage/repositories/terminal-command-template-repository.js.map +1 -1
- package/dist/server/storage/repositories/terminal-instance-repository.js +89 -7
- package/dist/server/storage/repositories/terminal-instance-repository.js.map +1 -1
- package/dist/server/storage/repositories/workspace-navigation-state-repository.d.ts +9 -0
- package/dist/server/storage/repositories/workspace-navigation-state-repository.js +49 -0
- package/dist/server/storage/repositories/workspace-navigation-state-repository.js.map +1 -0
- package/dist/server/storage/repositories/workspace-repository.d.ts +7 -1
- package/dist/server/storage/repositories/workspace-repository.js +32 -8
- package/dist/server/storage/repositories/workspace-repository.js.map +1 -1
- package/dist/server/storage/repositories/workspace-worktree-repository.d.ts +13 -0
- package/dist/server/storage/repositories/workspace-worktree-repository.js +158 -0
- package/dist/server/storage/repositories/workspace-worktree-repository.js.map +1 -0
- package/dist/server/storage/sqlite/client.js +311 -0
- package/dist/server/storage/sqlite/client.js.map +1 -1
- package/dist/server/storage/sqlite/schema.sql +303 -0
- package/dist/server/types/domain.d.ts +303 -0
- package/dist/server/ws/workbench-ws-hub.js +33 -9
- package/dist/server/ws/workbench-ws-hub.js.map +1 -1
- package/dist/server/ws/ws-server.js +4 -4
- package/dist/server/ws/ws-server.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.js +18 -6
- 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.js +14 -2
- package/node_modules/@codingns/session-sync-core/dist/providers/codex.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js +25 -1
- package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/types.d.ts +6 -0
- package/package.json +1 -1
- package/dist/public/assets/index-1VIm8lVL.css +0 -1
- package/dist/public/assets/index-Dti93O2S.js +0 -109
|
@@ -4,6 +4,7 @@ import { AppError } from "../../shared/errors/app-error.js";
|
|
|
4
4
|
import { hashContent } from "../../shared/utils/hash.js";
|
|
5
5
|
import { createId } from "../../shared/utils/id.js";
|
|
6
6
|
import { logPerformance } from "../../shared/utils/perf-log.js";
|
|
7
|
+
import { isTerminalDebugEnabled, logTerminalDebug, terminalDebugNowMs } from "../../shared/utils/terminal-debug-log.js";
|
|
7
8
|
import { nowIso } from "../../shared/utils/time.js";
|
|
8
9
|
import { isCommandAvailable } from "../../shared/utils/command-availability.js";
|
|
9
10
|
import { inspectSessionActivity } from "./session-activity-inspector.js";
|
|
@@ -11,8 +12,11 @@ import { SessionActivityAuthorityService } from "./session-activity-authority-se
|
|
|
11
12
|
import { mapSessionProviderError } from "./session-provider-error-mapper.js";
|
|
12
13
|
import { SessionForkRepository } from "../../storage/repositories/session-fork-repository.js";
|
|
13
14
|
import { enrichClaudeCapabilities } from "../provider/claude-model-options.js";
|
|
14
|
-
import { CodexModelOptionsService, enrichCodexCapabilities } from "../provider/codex-model-options.js";
|
|
15
|
-
import { OpenCodeModelOptionsService, enrichOpenCodeCapabilities } from "../provider/opencode-model-options.js";
|
|
15
|
+
import { CodexModelOptionsService, createFallbackCodexModelOptions, enrichCodexCapabilities } from "../provider/codex-model-options.js";
|
|
16
|
+
import { OpenCodeModelOptionsService, createFallbackOpenCodeModelOptions, enrichOpenCodeCapabilities } from "../provider/opencode-model-options.js";
|
|
17
|
+
import { ProviderDiscoveryHelperClient } from "../provider/provider-discovery-helper-client.js";
|
|
18
|
+
import { createTaskManager } from "../tasks/task-manager.js";
|
|
19
|
+
import { HOST_TASK_TYPES } from "../tasks/task-types.js";
|
|
16
20
|
import { CodexAppServerHelperClient } from "./codex-app-server-helper-client.js";
|
|
17
21
|
const RECONSTRUCTED_FORK_TARGET_PROVIDERS = new Set(["codex", "claude-code", "opencode"]);
|
|
18
22
|
const FORK_RECONSTRUCTION_PAGE_SIZE = 200;
|
|
@@ -25,6 +29,9 @@ const SESSION_START_DEFERRED_PROVIDERS = new Set([
|
|
|
25
29
|
"kimi"
|
|
26
30
|
]);
|
|
27
31
|
const MUTABLE_HISTORY_TAIL_REFRESH_INTERVAL_MS = 1_200;
|
|
32
|
+
const WORKSPACE_DISCOVERY_BACKGROUND_MAX_AGE_MS = 15_000;
|
|
33
|
+
const PROVIDER_CAPABILITY_CACHE_MAX_AGE_MS = 5_000;
|
|
34
|
+
const WORKSPACE_DISCOVERY_PERSIST_BATCH_SIZE = 25;
|
|
28
35
|
export class SessionHistoryService {
|
|
29
36
|
db;
|
|
30
37
|
workspaceRepository;
|
|
@@ -45,11 +52,15 @@ export class SessionHistoryService {
|
|
|
45
52
|
openCodeModelOptionsService;
|
|
46
53
|
providerCliCommandPaths;
|
|
47
54
|
providerCliAvailability;
|
|
55
|
+
providerDiscoveryHelperClient = new ProviderDiscoveryHelperClient();
|
|
56
|
+
providerSessionDiscoveryConfig;
|
|
57
|
+
taskManager;
|
|
48
58
|
workspaceDiscoveryStatuses = new Map();
|
|
49
|
-
workspaceDiscoveryInflight = new Map();
|
|
50
59
|
workspaceStateRefreshInflight = new Map();
|
|
60
|
+
providerCapabilityCache = new Map();
|
|
61
|
+
liveActivityObservationResolvers = new Set();
|
|
51
62
|
workspaceSessionRelations = new Map();
|
|
52
|
-
constructor(db, workspaceRepository, sessionBindingRepository, sessionChangedFileService, sessionIndexRepository, sessionMessageAttachmentService, sessionStateRepository, sessionStatusSnapshotRepository, config, sessionActivityAuthorityService = new SessionActivityAuthorityService(), sessionMessageOriginRepository = null, sessionForkRepository = null, adapterOverrides = {}) {
|
|
63
|
+
constructor(db, workspaceRepository, sessionBindingRepository, sessionChangedFileService, sessionIndexRepository, sessionMessageAttachmentService, sessionStateRepository, sessionStatusSnapshotRepository, config, sessionActivityAuthorityService = new SessionActivityAuthorityService(), sessionMessageOriginRepository = null, sessionForkRepository = null, adapterOverrides = {}, taskManager = createTaskManager()) {
|
|
53
64
|
this.db = db;
|
|
54
65
|
this.workspaceRepository = workspaceRepository;
|
|
55
66
|
this.sessionBindingRepository = sessionBindingRepository;
|
|
@@ -61,6 +72,7 @@ export class SessionHistoryService {
|
|
|
61
72
|
this.sessionMessageOriginRepository = sessionMessageOriginRepository;
|
|
62
73
|
this.sessionActivityAuthorityService = sessionActivityAuthorityService;
|
|
63
74
|
this.sessionForkRepository = sessionForkRepository ?? new SessionForkRepository(db);
|
|
75
|
+
this.taskManager = taskManager;
|
|
64
76
|
this.claudeCodeHomeDir = config.claudeCodeHomeDir;
|
|
65
77
|
this.providerCliCommandPaths = {
|
|
66
78
|
"claude-code": process.platform === "win32" ? "claude.cmd" : "claude",
|
|
@@ -70,6 +82,18 @@ export class SessionHistoryService {
|
|
|
70
82
|
};
|
|
71
83
|
// CLI 是否可用只在 Host 启动时探测一次;后续统一读缓存,更新 CLI 后重启 Host 生效。
|
|
72
84
|
this.providerCliAvailability = buildProviderCliAvailabilitySnapshot(this.providerCliCommandPaths);
|
|
85
|
+
this.providerSessionDiscoveryConfig = {
|
|
86
|
+
claudeCodeHomeDir: config.claudeCodeHomeDir,
|
|
87
|
+
codexCliPath: config.codexCliPath,
|
|
88
|
+
codexHomeDir: config.codexHomeDir,
|
|
89
|
+
geminiCliPath: config.geminiCliPath,
|
|
90
|
+
geminiHomeDir: config.geminiHomeDir,
|
|
91
|
+
kimiDefaultModel: config.kimiDefaultModel,
|
|
92
|
+
kimiHomeDir: config.kimiHomeDir,
|
|
93
|
+
opencodeBaseUrl: config.opencodeBaseUrl,
|
|
94
|
+
opencodeDataDir: config.opencodeDataDir,
|
|
95
|
+
opencodeDbPath: config.opencodeDbPath
|
|
96
|
+
};
|
|
73
97
|
this.providerRegistry = new ProviderRegistry([
|
|
74
98
|
new ClaudeCodeAdapter({ homeDir: config.claudeCodeHomeDir }),
|
|
75
99
|
new CodexAdapter({
|
|
@@ -102,6 +126,45 @@ export class SessionHistoryService {
|
|
|
102
126
|
baseUrlResolver: config.opencodeBaseUrlResolver?.resolve.bind(config.opencodeBaseUrlResolver),
|
|
103
127
|
commandPath: config.opencodeCliPath
|
|
104
128
|
});
|
|
129
|
+
this.registerBackgroundTasks();
|
|
130
|
+
}
|
|
131
|
+
observeBackgroundTaskMetrics() {
|
|
132
|
+
return this.taskManager.observe();
|
|
133
|
+
}
|
|
134
|
+
registerLiveActivityObservationResolver(resolver) {
|
|
135
|
+
this.liveActivityObservationResolvers.add(resolver);
|
|
136
|
+
let closed = false;
|
|
137
|
+
return {
|
|
138
|
+
close: () => {
|
|
139
|
+
if (closed) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
closed = true;
|
|
143
|
+
this.liveActivityObservationResolvers.delete(resolver);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
registerBackgroundTasks() {
|
|
148
|
+
if (!this.taskManager.has(HOST_TASK_TYPES.workspaceDiscovery)) {
|
|
149
|
+
this.taskManager.register({
|
|
150
|
+
taskType: HOST_TASK_TYPES.workspaceDiscovery,
|
|
151
|
+
executionLane: "helper_process",
|
|
152
|
+
run: async ({ workspaceId, userId, refreshStateMode }) => this.runDiscoverWorkspaceSessions(workspaceId, userId, refreshStateMode)
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
if (!this.taskManager.has(HOST_TASK_TYPES.providerCapabilityRefresh)) {
|
|
156
|
+
this.taskManager.register({
|
|
157
|
+
taskType: HOST_TASK_TYPES.providerCapabilityRefresh,
|
|
158
|
+
executionLane: "external_process",
|
|
159
|
+
run: async ({ capabilities, workspacePath }) => {
|
|
160
|
+
const value = await this.enrichProviderCapabilities(capabilities, workspacePath);
|
|
161
|
+
this.providerCapabilityCache.set(buildProviderCapabilityCacheKey(capabilities.provider, workspacePath), {
|
|
162
|
+
refreshedAt: Date.now(),
|
|
163
|
+
value
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
}
|
|
105
168
|
}
|
|
106
169
|
async discoverWorkspaceSessions(workspaceId, userId, options) {
|
|
107
170
|
const maxAgeMs = options?.maxAgeMs ?? 0;
|
|
@@ -112,17 +175,47 @@ export class SessionHistoryService {
|
|
|
112
175
|
discoveryStatus?.isComplete === true &&
|
|
113
176
|
maxAgeMs > 0 &&
|
|
114
177
|
Date.now() - lastRefreshedAt <= maxAgeMs) {
|
|
178
|
+
this.taskManager.recordCacheHit(HOST_TASK_TYPES.workspaceDiscovery, workspaceId);
|
|
115
179
|
return this.listWorkspaceSessions(workspaceId, userId);
|
|
116
180
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
181
|
+
return this.taskManager.enqueue(HOST_TASK_TYPES.workspaceDiscovery, {
|
|
182
|
+
key: workspaceId,
|
|
183
|
+
source: "session_history.discover_workspace_sessions",
|
|
184
|
+
input: {
|
|
185
|
+
workspaceId,
|
|
186
|
+
userId,
|
|
187
|
+
refreshStateMode: options?.refreshStateMode ?? "inline"
|
|
188
|
+
}
|
|
189
|
+
}).promise;
|
|
190
|
+
}
|
|
191
|
+
requestWorkspaceDiscovery(workspaceId, userId, options) {
|
|
192
|
+
const maxAgeMs = options?.maxAgeMs ?? WORKSPACE_DISCOVERY_BACKGROUND_MAX_AGE_MS;
|
|
193
|
+
const force = options?.force ?? false;
|
|
194
|
+
if (!force && !this.needsWorkspaceDiscovery(workspaceId, maxAgeMs)) {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
const task = this.taskManager.enqueue(HOST_TASK_TYPES.workspaceDiscovery, {
|
|
198
|
+
key: workspaceId,
|
|
199
|
+
source: "session_history.request_workspace_discovery",
|
|
200
|
+
input: {
|
|
201
|
+
workspaceId,
|
|
202
|
+
userId,
|
|
203
|
+
refreshStateMode: options?.refreshStateMode ?? "deferred"
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
if (task.deduped) {
|
|
207
|
+
return;
|
|
120
208
|
}
|
|
121
|
-
|
|
122
|
-
|
|
209
|
+
void task.promise.catch((error) => {
|
|
210
|
+
logPerformance("workspace.discover_sessions.background_failed", 0, {
|
|
211
|
+
workspaceId,
|
|
212
|
+
error: error instanceof Error ? error.message : "unknown"
|
|
213
|
+
}, {
|
|
214
|
+
thresholdMs: 0,
|
|
215
|
+
force: true
|
|
216
|
+
});
|
|
217
|
+
return this.listWorkspaceSessions(workspaceId, userId);
|
|
123
218
|
});
|
|
124
|
-
this.workspaceDiscoveryInflight.set(workspaceId, task);
|
|
125
|
-
return task;
|
|
126
219
|
}
|
|
127
220
|
needsWorkspaceDiscovery(workspaceId, maxAgeMs) {
|
|
128
221
|
if (maxAgeMs <= 0) {
|
|
@@ -246,13 +339,13 @@ export class SessionHistoryService {
|
|
|
246
339
|
const binding = this.getBindingOrThrow(sessionId);
|
|
247
340
|
await this.syncSessionTitleFromProvider(sessionId, binding);
|
|
248
341
|
}
|
|
249
|
-
async syncWorkspaceSessionTitles(workspaceId, userId) {
|
|
342
|
+
async syncWorkspaceSessionTitles(workspaceId, userId, concurrency = 1) {
|
|
250
343
|
const sessions = this.sessionIndexRepository.listByWorkspace(workspaceId, userId);
|
|
251
|
-
|
|
344
|
+
await runWithConcurrency(sessions, concurrency, async (session) => {
|
|
252
345
|
await this.syncSessionTitle(session.sessionId).catch(() => {
|
|
253
346
|
return;
|
|
254
347
|
});
|
|
255
|
-
}
|
|
348
|
+
});
|
|
256
349
|
}
|
|
257
350
|
async listSessionChangedFiles(sessionId, userId) {
|
|
258
351
|
this.getSession(sessionId, userId);
|
|
@@ -266,7 +359,7 @@ export class SessionHistoryService {
|
|
|
266
359
|
}
|
|
267
360
|
getProviderCapabilitiesSnapshot(provider) {
|
|
268
361
|
try {
|
|
269
|
-
return this.applyProviderCliAvailability(this.capabilityService.getProviderCapabilities(provider));
|
|
362
|
+
return this.resolveProviderCapabilitiesImmediate(this.applyProviderCliAvailability(this.capabilityService.getProviderCapabilities(provider)), null);
|
|
270
363
|
}
|
|
271
364
|
catch (error) {
|
|
272
365
|
throw mapSessionProviderError(error);
|
|
@@ -275,7 +368,9 @@ export class SessionHistoryService {
|
|
|
275
368
|
async getProviderCapabilities(provider, workspaceId) {
|
|
276
369
|
try {
|
|
277
370
|
const workspacePath = workspaceId ? this.getWorkspaceOrThrow(workspaceId).path : null;
|
|
278
|
-
|
|
371
|
+
const baseCapabilities = this.applyProviderCliAvailability(this.capabilityService.getProviderCapabilities(provider));
|
|
372
|
+
this.scheduleProviderCapabilityRefresh(baseCapabilities, workspacePath);
|
|
373
|
+
return this.resolveProviderCapabilitiesImmediate(baseCapabilities, workspacePath);
|
|
279
374
|
}
|
|
280
375
|
catch (error) {
|
|
281
376
|
throw mapSessionProviderError(error);
|
|
@@ -284,9 +379,14 @@ export class SessionHistoryService {
|
|
|
284
379
|
async getSessionCapabilities(sessionId) {
|
|
285
380
|
const binding = this.getBindingOrThrow(sessionId);
|
|
286
381
|
const workspace = this.getWorkspaceOrThrow(binding.workspaceId);
|
|
382
|
+
const workspacePath = workspace.path;
|
|
287
383
|
return this.capabilityService
|
|
288
384
|
.getSessionCapabilities(binding.provider, binding.providerSessionId)
|
|
289
|
-
.then((capabilities) =>
|
|
385
|
+
.then((capabilities) => {
|
|
386
|
+
const normalizedCapabilities = this.applyProviderCliAvailability(capabilities);
|
|
387
|
+
this.scheduleProviderCapabilityRefresh(normalizedCapabilities, workspacePath);
|
|
388
|
+
return this.resolveProviderCapabilitiesImmediate(normalizedCapabilities, workspacePath);
|
|
389
|
+
})
|
|
290
390
|
.catch((error) => {
|
|
291
391
|
throw mapSessionProviderError(error);
|
|
292
392
|
});
|
|
@@ -299,6 +399,48 @@ export class SessionHistoryService {
|
|
|
299
399
|
const codexEnriched = await enrichCodexCapabilities(claudeEnriched, this.codexModelOptionsService);
|
|
300
400
|
return enrichOpenCodeCapabilities(codexEnriched, this.openCodeModelOptionsService, workspacePath);
|
|
301
401
|
}
|
|
402
|
+
resolveProviderCapabilitiesImmediate(capabilities, workspacePath) {
|
|
403
|
+
const cacheKey = buildProviderCapabilityCacheKey(capabilities.provider, workspacePath);
|
|
404
|
+
const cached = this.providerCapabilityCache.get(cacheKey);
|
|
405
|
+
if (cached) {
|
|
406
|
+
this.taskManager.recordCacheHit(HOST_TASK_TYPES.providerCapabilityRefresh, cacheKey);
|
|
407
|
+
return cached.value;
|
|
408
|
+
}
|
|
409
|
+
const claudeEnriched = enrichClaudeCapabilities(capabilities, {
|
|
410
|
+
claudeHomeDir: this.claudeCodeHomeDir,
|
|
411
|
+
workspacePath
|
|
412
|
+
});
|
|
413
|
+
return applyImmediateModelOptionFallbacks(claudeEnriched, this.codexModelOptionsService.peekSnapshot(), this.openCodeModelOptionsService.peekSnapshot(workspacePath));
|
|
414
|
+
}
|
|
415
|
+
scheduleProviderCapabilityRefresh(capabilities, workspacePath) {
|
|
416
|
+
const cacheKey = buildProviderCapabilityCacheKey(capabilities.provider, workspacePath);
|
|
417
|
+
const cached = this.providerCapabilityCache.get(cacheKey);
|
|
418
|
+
if (cached &&
|
|
419
|
+
Date.now() - cached.refreshedAt <= PROVIDER_CAPABILITY_CACHE_MAX_AGE_MS) {
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
const task = this.taskManager.enqueue(HOST_TASK_TYPES.providerCapabilityRefresh, {
|
|
423
|
+
key: cacheKey,
|
|
424
|
+
source: "session_history.provider_capability_refresh",
|
|
425
|
+
input: {
|
|
426
|
+
capabilities,
|
|
427
|
+
workspacePath
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
if (task.deduped) {
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
void task.promise.catch((error) => {
|
|
434
|
+
logPerformance("provider.capabilities.background_failed", 0, {
|
|
435
|
+
provider: capabilities.provider,
|
|
436
|
+
workspacePath,
|
|
437
|
+
error: error instanceof Error ? error.message : "unknown"
|
|
438
|
+
}, {
|
|
439
|
+
thresholdMs: 0,
|
|
440
|
+
force: true
|
|
441
|
+
});
|
|
442
|
+
});
|
|
443
|
+
}
|
|
302
444
|
applyProviderCliAvailability(capabilities) {
|
|
303
445
|
if (!isProviderCliBacked(capabilities.provider)) {
|
|
304
446
|
return capabilities;
|
|
@@ -472,6 +614,7 @@ export class SessionHistoryService {
|
|
|
472
614
|
rawStoreRef: binding.rawStoreRef,
|
|
473
615
|
sourceType: input.sourceType,
|
|
474
616
|
sourceMessageId,
|
|
617
|
+
sourceMessageSnapshot: input.sourceMessageSnapshot ?? null,
|
|
475
618
|
strategy: input.strategy ?? "auto"
|
|
476
619
|
});
|
|
477
620
|
const sessionId = createId();
|
|
@@ -561,7 +704,7 @@ export class SessionHistoryService {
|
|
|
561
704
|
throw mapSessionProviderError(new Error("FORK_TARGET_PROVIDER_NOT_SUPPORTED"));
|
|
562
705
|
}
|
|
563
706
|
const sourceIndex = this.sessionIndexRepository.findIndexRecordBySessionId(input.sessionId);
|
|
564
|
-
const inheritedMessages = await this.readForkSourceMessages(input.sessionId, sourceBinding, input.sourceType, sourceMessageId);
|
|
707
|
+
const inheritedMessages = await this.readForkSourceMessages(input.sessionId, sourceBinding, input.sourceType, sourceMessageId, input.sourceMessageSnapshot ?? null);
|
|
565
708
|
const reconstructedMessages = inheritedMessages.filter((message) => (message.role === "user" || message.role === "assistant")
|
|
566
709
|
&& message.kind === "text"
|
|
567
710
|
&& message.content.trim().length > 0);
|
|
@@ -624,7 +767,7 @@ export class SessionHistoryService {
|
|
|
624
767
|
this.workspaceSessionRelations.set(sourceBinding.workspaceId, relationMap);
|
|
625
768
|
return this.getSessionListItemOrThrow(startedSession.sessionId, input.userId);
|
|
626
769
|
}
|
|
627
|
-
async readForkSourceMessages(sessionId, binding, sourceType, sourceMessageId) {
|
|
770
|
+
async readForkSourceMessages(sessionId, binding, sourceType, sourceMessageId, sourceMessageSnapshot = null) {
|
|
628
771
|
const messages = [];
|
|
629
772
|
let cursor = null;
|
|
630
773
|
while (true) {
|
|
@@ -642,7 +785,21 @@ export class SessionHistoryService {
|
|
|
642
785
|
if (targetIndex < 0) {
|
|
643
786
|
throw mapSessionProviderError(new Error("FORK_SOURCE_MESSAGE_NOT_FOUND"));
|
|
644
787
|
}
|
|
645
|
-
|
|
788
|
+
const inheritedMessages = messages.slice(0, targetIndex + 1);
|
|
789
|
+
if (!sourceMessageSnapshot) {
|
|
790
|
+
return inheritedMessages;
|
|
791
|
+
}
|
|
792
|
+
const targetMessage = inheritedMessages[targetIndex];
|
|
793
|
+
if (!targetMessage) {
|
|
794
|
+
return inheritedMessages;
|
|
795
|
+
}
|
|
796
|
+
inheritedMessages[targetIndex] = {
|
|
797
|
+
...targetMessage,
|
|
798
|
+
role: sourceMessageSnapshot.role,
|
|
799
|
+
kind: sourceMessageSnapshot.kind,
|
|
800
|
+
content: sourceMessageSnapshot.content
|
|
801
|
+
};
|
|
802
|
+
return inheritedMessages;
|
|
646
803
|
}
|
|
647
804
|
assertForkDepthWithinLimit(parentSessionId) {
|
|
648
805
|
const nextDepth = this.getSessionForkDepth(parentSessionId) + 1;
|
|
@@ -935,11 +1092,11 @@ export class SessionHistoryService {
|
|
|
935
1092
|
});
|
|
936
1093
|
const currentBinding = this.sessionBindingRepository.findBySessionId(sessionId);
|
|
937
1094
|
const timestamp = nowIso();
|
|
938
|
-
const duplicateBinding = this.
|
|
1095
|
+
const duplicateBinding = this.findSameWorkspaceBindingDuplicate(sessionId, workspaceId, resolvedSnapshot);
|
|
939
1096
|
this.db.transaction(() => {
|
|
940
1097
|
if (duplicateBinding) {
|
|
941
|
-
//
|
|
942
|
-
//
|
|
1098
|
+
// 运行时链路显式指定了当前 sessionId,就应该由当前会话接管同工作区里的重复底层会话。
|
|
1099
|
+
// 否则后续事件重放或后台发现补录都会持续撞 UNIQUE(provider, provider_session_id)。
|
|
943
1100
|
this.mergeSessionIntoTarget({
|
|
944
1101
|
workspaceId,
|
|
945
1102
|
targetSessionId: sessionId,
|
|
@@ -969,16 +1126,29 @@ export class SessionHistoryService {
|
|
|
969
1126
|
}
|
|
970
1127
|
async runDiscoverWorkspaceSessions(workspaceId, userId, refreshStateMode = "inline") {
|
|
971
1128
|
const startedAt = Date.now();
|
|
1129
|
+
const debugStartedAtMs = terminalDebugNowMs();
|
|
972
1130
|
const workspace = this.getWorkspaceOrThrow(workspaceId);
|
|
973
1131
|
let discoverDurationMs = 0;
|
|
974
1132
|
let persistDurationMs = 0;
|
|
1133
|
+
let persistPass1DurationMs = 0;
|
|
1134
|
+
let persistPass1BatchCount = 0;
|
|
1135
|
+
let persistPass1MaxBatchMs = 0;
|
|
1136
|
+
let relationMapDurationMs = 0;
|
|
1137
|
+
let persistPass2DurationMs = 0;
|
|
1138
|
+
let persistPass2BatchCount = 0;
|
|
1139
|
+
let persistPass2MaxBatchMs = 0;
|
|
1140
|
+
let cleanupDurationMs = 0;
|
|
1141
|
+
let listItemsDurationMs = 0;
|
|
1142
|
+
let refreshStateDurationMs = 0;
|
|
975
1143
|
const refreshStateCount = 10;
|
|
976
1144
|
try {
|
|
977
1145
|
const discoverStartedAt = Date.now();
|
|
978
1146
|
const existingWorkspaceSessions = this.sessionIndexRepository.listByWorkspace(workspaceId, userId);
|
|
979
1147
|
const knownSessions = this.buildKnownSessionSummaries(existingWorkspaceSessions, workspace.path);
|
|
980
|
-
const discovery = await this.
|
|
981
|
-
.discoverWorkspaceSessions(
|
|
1148
|
+
const discovery = await this.providerDiscoveryHelperClient
|
|
1149
|
+
.discoverWorkspaceSessions({
|
|
1150
|
+
config: this.providerSessionDiscoveryConfig,
|
|
1151
|
+
workspacePath: workspace.path,
|
|
982
1152
|
knownSessions
|
|
983
1153
|
})
|
|
984
1154
|
.catch((error) => {
|
|
@@ -990,10 +1160,9 @@ export class SessionHistoryService {
|
|
|
990
1160
|
const discoveredSessionIds = new Map();
|
|
991
1161
|
const persistedSessions = [];
|
|
992
1162
|
const claimedPendingSessionIds = new Set();
|
|
993
|
-
const
|
|
994
|
-
for (const session of
|
|
1163
|
+
const persistPass1Transaction = this.db.transaction((batch) => {
|
|
1164
|
+
for (const session of batch) {
|
|
995
1165
|
const exactExisting = this.sessionBindingRepository.findByProviderSession(session.provider, session.providerSessionId) ?? this.sessionBindingRepository.findByRawStoreRef(session.provider, session.rawStoreRef);
|
|
996
|
-
// discover 只能补全当前工作区,不能把别的工作区已有会话偷过来重绑。
|
|
997
1166
|
if (exactExisting && exactExisting.workspaceId !== workspaceId) {
|
|
998
1167
|
continue;
|
|
999
1168
|
}
|
|
@@ -1065,8 +1234,17 @@ export class SessionHistoryService {
|
|
|
1065
1234
|
existingIndex
|
|
1066
1235
|
});
|
|
1067
1236
|
}
|
|
1068
|
-
|
|
1069
|
-
|
|
1237
|
+
});
|
|
1238
|
+
const persistPass1StartedAt = Date.now();
|
|
1239
|
+
const persistPass1Stats = await runBatchedTransactions(sessions, WORKSPACE_DISCOVERY_PERSIST_BATCH_SIZE, persistPass1Transaction);
|
|
1240
|
+
persistPass1DurationMs = Date.now() - persistPass1StartedAt;
|
|
1241
|
+
persistPass1BatchCount = persistPass1Stats.batchCount;
|
|
1242
|
+
persistPass1MaxBatchMs = persistPass1Stats.maxBatchMs;
|
|
1243
|
+
const relationMapStartedAt = Date.now();
|
|
1244
|
+
const relationMap = this.buildWorkspaceSessionRelationMap(sessions, discoveredSessionIds);
|
|
1245
|
+
relationMapDurationMs = Date.now() - relationMapStartedAt;
|
|
1246
|
+
const persistPass2Transaction = this.db.transaction((batch) => {
|
|
1247
|
+
for (const persistedSession of batch) {
|
|
1070
1248
|
const relation = relationMap.get(persistedSession.sessionId);
|
|
1071
1249
|
const resolvedParentSessionId = relation?.parentSessionId
|
|
1072
1250
|
?? persistedSession.existingIndex?.parentSessionId
|
|
@@ -1104,26 +1282,56 @@ export class SessionHistoryService {
|
|
|
1104
1282
|
});
|
|
1105
1283
|
}
|
|
1106
1284
|
});
|
|
1107
|
-
const
|
|
1108
|
-
|
|
1109
|
-
|
|
1285
|
+
const persistPass2StartedAt = Date.now();
|
|
1286
|
+
const persistPass2Stats = await runBatchedTransactions(persistedSessions, WORKSPACE_DISCOVERY_PERSIST_BATCH_SIZE, persistPass2Transaction);
|
|
1287
|
+
persistPass2DurationMs = Date.now() - persistPass2StartedAt;
|
|
1288
|
+
persistPass2BatchCount = persistPass2Stats.batchCount;
|
|
1289
|
+
persistPass2MaxBatchMs = persistPass2Stats.maxBatchMs;
|
|
1290
|
+
persistDurationMs = persistPass1DurationMs + relationMapDurationMs + persistPass2DurationMs;
|
|
1110
1291
|
if (discovery.isComplete) {
|
|
1111
|
-
|
|
1292
|
+
const cleanupStartedAt = Date.now();
|
|
1293
|
+
await this.cleanupStaleHiddenSessions(workspaceId, userId, sessions);
|
|
1294
|
+
cleanupDurationMs = Date.now() - cleanupStartedAt;
|
|
1112
1295
|
}
|
|
1113
|
-
this.workspaceSessionRelations.set(workspaceId,
|
|
1296
|
+
this.workspaceSessionRelations.set(workspaceId, relationMap);
|
|
1297
|
+
const listItemsStartedAt = Date.now();
|
|
1114
1298
|
const items = this.sessionIndexRepository.listByWorkspace(workspaceId, userId);
|
|
1299
|
+
listItemsDurationMs = Date.now() - listItemsStartedAt;
|
|
1115
1300
|
const refreshCandidates = buildSessionStateRefreshCandidates(items, refreshStateCount);
|
|
1116
1301
|
this.workspaceDiscoveryStatuses.set(workspaceId, {
|
|
1117
1302
|
refreshedAt: Date.now(),
|
|
1118
1303
|
isComplete: discovery.isComplete
|
|
1119
1304
|
});
|
|
1305
|
+
const refreshStateStartedAt = Date.now();
|
|
1120
1306
|
if (refreshStateMode === "inline") {
|
|
1121
1307
|
await this.refreshRecentSessionStates(refreshCandidates, userId);
|
|
1122
1308
|
}
|
|
1123
1309
|
else {
|
|
1124
1310
|
this.scheduleWorkspaceStateRefresh(workspaceId, userId, refreshCandidates);
|
|
1125
1311
|
}
|
|
1312
|
+
refreshStateDurationMs = Date.now() - refreshStateStartedAt;
|
|
1126
1313
|
const nextItems = this.listWorkspaceSessions(workspaceId, userId);
|
|
1314
|
+
if (isTerminalDebugEnabled()) {
|
|
1315
|
+
logTerminalDebug("workspace.discovery.completed", {
|
|
1316
|
+
workspaceId,
|
|
1317
|
+
sessionCount: sessions.length,
|
|
1318
|
+
returnedSessionCount: nextItems.length,
|
|
1319
|
+
discoverMs: discoverDurationMs,
|
|
1320
|
+
persistMs: persistDurationMs,
|
|
1321
|
+
persistPass1Ms: persistPass1DurationMs,
|
|
1322
|
+
persistPass1BatchCount,
|
|
1323
|
+
persistPass1MaxBatchMs,
|
|
1324
|
+
relationMapMs: relationMapDurationMs,
|
|
1325
|
+
persistPass2Ms: persistPass2DurationMs,
|
|
1326
|
+
persistPass2BatchCount,
|
|
1327
|
+
persistPass2MaxBatchMs,
|
|
1328
|
+
cleanupMs: cleanupDurationMs,
|
|
1329
|
+
listItemsMs: listItemsDurationMs,
|
|
1330
|
+
refreshStateMs: refreshStateDurationMs,
|
|
1331
|
+
refreshStateDeferred: refreshStateMode !== "inline",
|
|
1332
|
+
durationMs: terminalDebugNowMs() - debugStartedAtMs
|
|
1333
|
+
});
|
|
1334
|
+
}
|
|
1127
1335
|
logPerformance("workspace.discover_sessions", Date.now() - startedAt, {
|
|
1128
1336
|
workspaceId,
|
|
1129
1337
|
workspacePath: workspace.path,
|
|
@@ -1135,6 +1343,16 @@ export class SessionHistoryService {
|
|
|
1135
1343
|
refreshedStates: refreshCandidates.length,
|
|
1136
1344
|
discoverMs: discoverDurationMs,
|
|
1137
1345
|
persistMs: persistDurationMs,
|
|
1346
|
+
persistPass1Ms: persistPass1DurationMs,
|
|
1347
|
+
persistPass1BatchCount,
|
|
1348
|
+
persistPass1MaxBatchMs,
|
|
1349
|
+
relationMapMs: relationMapDurationMs,
|
|
1350
|
+
persistPass2Ms: persistPass2DurationMs,
|
|
1351
|
+
persistPass2BatchCount,
|
|
1352
|
+
persistPass2MaxBatchMs,
|
|
1353
|
+
cleanupMs: cleanupDurationMs,
|
|
1354
|
+
listItemsMs: listItemsDurationMs,
|
|
1355
|
+
refreshStateMs: refreshStateDurationMs,
|
|
1138
1356
|
refreshStateDeferred: refreshStateMode !== "inline"
|
|
1139
1357
|
}, {
|
|
1140
1358
|
thresholdMs: 500
|
|
@@ -1147,6 +1365,16 @@ export class SessionHistoryService {
|
|
|
1147
1365
|
workspacePath: workspace.path,
|
|
1148
1366
|
discoverMs: discoverDurationMs,
|
|
1149
1367
|
persistMs: persistDurationMs,
|
|
1368
|
+
persistPass1Ms: persistPass1DurationMs,
|
|
1369
|
+
persistPass1BatchCount,
|
|
1370
|
+
persistPass1MaxBatchMs,
|
|
1371
|
+
relationMapMs: relationMapDurationMs,
|
|
1372
|
+
persistPass2Ms: persistPass2DurationMs,
|
|
1373
|
+
persistPass2BatchCount,
|
|
1374
|
+
persistPass2MaxBatchMs,
|
|
1375
|
+
cleanupMs: cleanupDurationMs,
|
|
1376
|
+
listItemsMs: listItemsDurationMs,
|
|
1377
|
+
refreshStateMs: refreshStateDurationMs,
|
|
1150
1378
|
refreshStateDeferred: refreshStateMode !== "inline",
|
|
1151
1379
|
error: error instanceof Error ? error.message : "unknown"
|
|
1152
1380
|
}, {
|
|
@@ -1391,7 +1619,12 @@ export class SessionHistoryService {
|
|
|
1391
1619
|
if (shouldSkipClaudePendingBinding(binding)) {
|
|
1392
1620
|
return;
|
|
1393
1621
|
}
|
|
1394
|
-
const nextTitle = (await this.
|
|
1622
|
+
const nextTitle = (await this.providerDiscoveryHelperClient.readSessionTitle({
|
|
1623
|
+
config: this.providerSessionDiscoveryConfig,
|
|
1624
|
+
provider: binding.provider,
|
|
1625
|
+
providerSessionId: binding.providerSessionId,
|
|
1626
|
+
rawStoreRef: binding.rawStoreRef
|
|
1627
|
+
})).trim();
|
|
1395
1628
|
const resolvedTitle = resolvePersistedSessionTitle(binding.provider, nextTitle, currentIndex.title);
|
|
1396
1629
|
if (resolvedTitle.length === 0 || resolvedTitle === currentIndex.title) {
|
|
1397
1630
|
return;
|
|
@@ -1486,11 +1719,11 @@ export class SessionHistoryService {
|
|
|
1486
1719
|
return this.sessionBindingRepository.findBySessionId(aliasTargetSessionId);
|
|
1487
1720
|
}
|
|
1488
1721
|
findPendingSessionAliasTargetSessionId(descriptor) {
|
|
1489
|
-
if (!descriptor
|
|
1722
|
+
if (!descriptor) {
|
|
1490
1723
|
return null;
|
|
1491
1724
|
}
|
|
1492
|
-
const aliasTargetSessionId =
|
|
1493
|
-
??
|
|
1725
|
+
const aliasTargetSessionId = extractSessionAliasTargetSessionId(descriptor.providerSessionId)
|
|
1726
|
+
?? extractSessionAliasTargetSessionId(descriptor.rawStoreRef);
|
|
1494
1727
|
if (!aliasTargetSessionId || aliasTargetSessionId === descriptor.sessionId) {
|
|
1495
1728
|
return null;
|
|
1496
1729
|
}
|
|
@@ -1548,7 +1781,7 @@ export class SessionHistoryService {
|
|
|
1548
1781
|
});
|
|
1549
1782
|
this.workspaceStateRefreshInflight.set(inflightKey, task);
|
|
1550
1783
|
}
|
|
1551
|
-
cleanupStaleHiddenSessions(workspaceId, userId, sessions) {
|
|
1784
|
+
async cleanupStaleHiddenSessions(workspaceId, userId, sessions) {
|
|
1552
1785
|
const discoveredProviderSessionIds = new Set(sessions.map((session) => buildProviderSessionKey(session.provider, session.providerSessionId)));
|
|
1553
1786
|
const discoveredRawStoreRefs = new Set(sessions.map((session) => session.rawStoreRef));
|
|
1554
1787
|
const staleHiddenSessions = this.sessionIndexRepository
|
|
@@ -1568,20 +1801,14 @@ export class SessionHistoryService {
|
|
|
1568
1801
|
if (staleHiddenSessions.length === 0) {
|
|
1569
1802
|
return;
|
|
1570
1803
|
}
|
|
1571
|
-
this.
|
|
1572
|
-
}
|
|
1573
|
-
deleteSessionsByIds(sessionIds) {
|
|
1574
|
-
const remove = this.db.transaction((ids) => {
|
|
1804
|
+
const deleteTransaction = this.db.transaction((ids) => {
|
|
1575
1805
|
for (const sessionId of ids) {
|
|
1576
1806
|
this.deleteSessionById(sessionId);
|
|
1577
1807
|
}
|
|
1578
1808
|
});
|
|
1579
|
-
|
|
1809
|
+
await runBatchedTransactions(staleHiddenSessions.map((session) => session.sessionId), WORKSPACE_DISCOVERY_PERSIST_BATCH_SIZE, deleteTransaction);
|
|
1580
1810
|
}
|
|
1581
|
-
|
|
1582
|
-
if (!currentBinding || !isPendingBindingValue(currentBinding.providerSessionId)) {
|
|
1583
|
-
return null;
|
|
1584
|
-
}
|
|
1811
|
+
findSameWorkspaceBindingDuplicate(sessionId, workspaceId, snapshot) {
|
|
1585
1812
|
if (isPendingBindingValue(snapshot.providerSessionId)) {
|
|
1586
1813
|
return null;
|
|
1587
1814
|
}
|
|
@@ -1673,12 +1900,22 @@ export class SessionHistoryService {
|
|
|
1673
1900
|
this.db
|
|
1674
1901
|
.prepare("DELETE FROM session_forks WHERE session_id = ?")
|
|
1675
1902
|
.run(input.sourceSessionId);
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
.
|
|
1681
|
-
|
|
1903
|
+
// 保留旧 session_id 作为 alias,避免前端或 Butler 还拿着旧 id 时直接炸成 SESSION_NOT_FOUND。
|
|
1904
|
+
this.sessionBindingRepository.upsert({
|
|
1905
|
+
sessionId: input.sourceSessionId,
|
|
1906
|
+
workspaceId: sourceBinding.workspaceId,
|
|
1907
|
+
provider: sourceBinding.provider,
|
|
1908
|
+
providerSessionId: buildAliasBindingValue(input.provider, input.targetSessionId, input.sourceSessionId),
|
|
1909
|
+
rawStoreRef: buildAliasBindingValue(input.provider, input.targetSessionId, input.sourceSessionId),
|
|
1910
|
+
createdAt: sourceBinding.createdAt,
|
|
1911
|
+
updatedAt: input.timestamp
|
|
1912
|
+
});
|
|
1913
|
+
if (sourceIndex) {
|
|
1914
|
+
this.sessionIndexRepository.upsert({
|
|
1915
|
+
...sourceIndex,
|
|
1916
|
+
updatedAt: input.timestamp
|
|
1917
|
+
});
|
|
1918
|
+
}
|
|
1682
1919
|
this.rewriteWorkspaceSessionRelations(input.workspaceId, input.targetSessionId, input.sourceSessionId, targetIndex, sourceIndex);
|
|
1683
1920
|
}
|
|
1684
1921
|
listSessionStatesBySessionId(sessionId) {
|
|
@@ -1804,6 +2041,7 @@ export class SessionHistoryService {
|
|
|
1804
2041
|
}
|
|
1805
2042
|
buildKnownSessionSummaries(sessions, workspacePath) {
|
|
1806
2043
|
return sessions
|
|
2044
|
+
.filter((session) => !this.isPendingSessionAlias(session))
|
|
1807
2045
|
.filter((session) => !shouldSkipClaudePendingBinding(session))
|
|
1808
2046
|
.map((session) => {
|
|
1809
2047
|
const stats = safeStat(session.rawStoreRef);
|
|
@@ -1823,19 +2061,28 @@ export class SessionHistoryService {
|
|
|
1823
2061
|
async refreshSessionState(sessionId, userId) {
|
|
1824
2062
|
const binding = this.getBindingOrThrow(sessionId);
|
|
1825
2063
|
const current = this.sessionStateRepository.findBySessionAndUser(sessionId, userId);
|
|
1826
|
-
const inspection = inspectSessionActivity(binding.provider, binding.rawStoreRef);
|
|
1827
2064
|
const timestamp = nowIso();
|
|
1828
|
-
const
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
if (
|
|
1833
|
-
|
|
2065
|
+
const liveObservation = this.resolveLiveActivityObservation(sessionId);
|
|
2066
|
+
const inspection = liveObservation
|
|
2067
|
+
? null
|
|
2068
|
+
: inspectSessionActivity(binding.provider, binding.rawStoreRef);
|
|
2069
|
+
if (inspection) {
|
|
2070
|
+
const nowMs = Date.parse(timestamp);
|
|
2071
|
+
if (shouldClearStaleRuntimeWithoutInspection(current, inspection, nowMs)) {
|
|
2072
|
+
this.sessionActivityAuthorityService.clearSession(sessionId);
|
|
2073
|
+
}
|
|
2074
|
+
if (shouldPreserveRuntimeTerminalState(current, inspection)) {
|
|
2075
|
+
return current;
|
|
2076
|
+
}
|
|
1834
2077
|
}
|
|
1835
|
-
const resolution =
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
2078
|
+
const resolution = liveObservation
|
|
2079
|
+
? this.sessionActivityAuthorityService.observe(liveObservation)
|
|
2080
|
+
: this.sessionActivityAuthorityService.observe(buildInspectionActivityObservation(sessionId, inspection, timestamp));
|
|
2081
|
+
const resolvedLastEventAt = liveObservation
|
|
2082
|
+
? resolution.lastObservedAt ?? current?.lastEventAt ?? null
|
|
2083
|
+
: inspection && hasInspectionEvidence(inspection)
|
|
2084
|
+
? resolution.lastObservedAt ?? inspection.lastEventAt ?? current?.lastEventAt ?? null
|
|
2085
|
+
: current?.lastEventAt ?? null;
|
|
1839
2086
|
const nextRecord = {
|
|
1840
2087
|
sessionId,
|
|
1841
2088
|
userId,
|
|
@@ -1844,7 +2091,7 @@ export class SessionHistoryService {
|
|
|
1844
2091
|
favorite: current?.favorite ?? false,
|
|
1845
2092
|
lastEventAt: resolvedLastEventAt,
|
|
1846
2093
|
completedAt: isTerminalResolvedRunningState(resolution.runningState)
|
|
1847
|
-
? resolution.terminalAt ?? inspection
|
|
2094
|
+
? resolution.terminalAt ?? inspection?.completedAtCandidate ?? current?.completedAt ?? null
|
|
1848
2095
|
: null,
|
|
1849
2096
|
lastSeenAt: current?.lastSeenAt ?? null,
|
|
1850
2097
|
updatedAt: timestamp
|
|
@@ -1862,8 +2109,8 @@ export class SessionHistoryService {
|
|
|
1862
2109
|
syncCursor: currentSnapshot?.syncCursor ?? null,
|
|
1863
2110
|
lastSyncAt: resolution.lastObservedAt
|
|
1864
2111
|
?? resolution.terminalAt
|
|
1865
|
-
?? inspection
|
|
1866
|
-
?? inspection
|
|
2112
|
+
?? inspection?.lastEventAt
|
|
2113
|
+
?? inspection?.completedAtCandidate
|
|
1867
2114
|
?? currentSnapshot?.lastSyncAt
|
|
1868
2115
|
?? null,
|
|
1869
2116
|
lastErrorCode: resolution.runningState === "failed"
|
|
@@ -1881,17 +2128,34 @@ export class SessionHistoryService {
|
|
|
1881
2128
|
});
|
|
1882
2129
|
return nextRecord;
|
|
1883
2130
|
}
|
|
2131
|
+
resolveLiveActivityObservation(sessionId) {
|
|
2132
|
+
for (const resolver of this.liveActivityObservationResolvers) {
|
|
2133
|
+
const observation = resolver(sessionId);
|
|
2134
|
+
if (observation) {
|
|
2135
|
+
return observation;
|
|
2136
|
+
}
|
|
2137
|
+
}
|
|
2138
|
+
return null;
|
|
2139
|
+
}
|
|
1884
2140
|
upsertSnapshot(sessionId, input) {
|
|
2141
|
+
const resolvedSessionId = this.resolveCanonicalSessionId(sessionId);
|
|
2142
|
+
if (!this.sessionBindingRepository.findBySessionId(resolvedSessionId)) {
|
|
2143
|
+
return;
|
|
2144
|
+
}
|
|
1885
2145
|
this.sessionStatusSnapshotRepository.upsert({
|
|
1886
|
-
sessionId,
|
|
2146
|
+
sessionId: resolvedSessionId,
|
|
1887
2147
|
...input,
|
|
1888
2148
|
updatedAt: nowIso()
|
|
1889
2149
|
});
|
|
1890
2150
|
}
|
|
1891
2151
|
markSessionError(sessionId, errorCode, error) {
|
|
1892
|
-
const
|
|
2152
|
+
const resolvedSessionId = this.resolveCanonicalSessionId(sessionId);
|
|
2153
|
+
if (!this.sessionBindingRepository.findBySessionId(resolvedSessionId)) {
|
|
2154
|
+
return;
|
|
2155
|
+
}
|
|
2156
|
+
const current = this.sessionStatusSnapshotRepository.findBySessionId(resolvedSessionId);
|
|
1893
2157
|
this.sessionStatusSnapshotRepository.upsert({
|
|
1894
|
-
sessionId,
|
|
2158
|
+
sessionId: resolvedSessionId,
|
|
1895
2159
|
syncStatus: "error",
|
|
1896
2160
|
syncCursor: current?.syncCursor ?? null,
|
|
1897
2161
|
lastSyncAt: current?.lastSyncAt ?? null,
|
|
@@ -1961,23 +2225,28 @@ function hasInspectionEvidence(inspection) {
|
|
|
1961
2225
|
|| !!inspection.completedAtCandidate;
|
|
1962
2226
|
}
|
|
1963
2227
|
function applySessionActivityResolution(item, resolution) {
|
|
1964
|
-
const
|
|
1965
|
-
|
|
2228
|
+
const rawResolvedRunningState = resolution.runningState === "unknown" && item.runningState === null
|
|
2229
|
+
? null
|
|
2230
|
+
: resolution.runningState;
|
|
2231
|
+
const resolvedRunningState = resolution.activityResolutionSource === "inferred_log" && rawResolvedRunningState === "completed"
|
|
2232
|
+
? "idle"
|
|
2233
|
+
: rawResolvedRunningState;
|
|
2234
|
+
const shouldClearResolvedFailure = resolvedRunningState !== "failed" && item.runningState === "failed";
|
|
1966
2235
|
const lastEventAt = resolution.lastObservedAt ?? item.lastEventAt;
|
|
1967
|
-
const completedAt = isTerminalResolvedRunningState(
|
|
2236
|
+
const completedAt = rawResolvedRunningState && isTerminalResolvedRunningState(rawResolvedRunningState)
|
|
1968
2237
|
? resolution.terminalAt ?? item.completedAt
|
|
1969
2238
|
: null;
|
|
1970
|
-
const lastErrorCode =
|
|
2239
|
+
const lastErrorCode = resolvedRunningState === "failed"
|
|
1971
2240
|
? resolution.errorCode ?? item.lastErrorCode
|
|
1972
2241
|
: shouldClearResolvedFailure
|
|
1973
2242
|
? null
|
|
1974
2243
|
: item.lastErrorCode;
|
|
1975
|
-
const lastErrorDetail =
|
|
2244
|
+
const lastErrorDetail = resolvedRunningState === "failed"
|
|
1976
2245
|
? resolution.detail ?? item.lastErrorDetail
|
|
1977
2246
|
: shouldClearResolvedFailure
|
|
1978
2247
|
? null
|
|
1979
2248
|
: item.lastErrorDetail;
|
|
1980
|
-
const syncStatus =
|
|
2249
|
+
const syncStatus = resolvedRunningState === "failed"
|
|
1981
2250
|
? "error"
|
|
1982
2251
|
: shouldClearResolvedFailure && item.syncStatus === "error"
|
|
1983
2252
|
? "idle"
|
|
@@ -1985,7 +2254,7 @@ function applySessionActivityResolution(item, resolution) {
|
|
|
1985
2254
|
return {
|
|
1986
2255
|
...item,
|
|
1987
2256
|
syncStatus,
|
|
1988
|
-
runningState,
|
|
2257
|
+
runningState: resolvedRunningState,
|
|
1989
2258
|
activitySource: mapResolutionSourceToCompatibilitySource(resolution.activityResolutionSource),
|
|
1990
2259
|
activityResolutionSource: resolution.activityResolutionSource,
|
|
1991
2260
|
activityConfidence: resolution.activityConfidence,
|
|
@@ -1995,7 +2264,7 @@ function applySessionActivityResolution(item, resolution) {
|
|
|
1995
2264
|
lastErrorCode,
|
|
1996
2265
|
lastErrorDetail,
|
|
1997
2266
|
watchdogTriggeredAt: resolution.watchdogTriggeredAt,
|
|
1998
|
-
activityState: resolveActivityState(
|
|
2267
|
+
activityState: resolveActivityState(resolvedRunningState, completedAt, item.lastSeenAt)
|
|
1999
2268
|
};
|
|
2000
2269
|
}
|
|
2001
2270
|
function clampLimit(limit) {
|
|
@@ -2194,6 +2463,9 @@ function isPendingBindingValue(value) {
|
|
|
2194
2463
|
function buildPendingBindingValue(provider, sessionId) {
|
|
2195
2464
|
return `pending://${provider}/${sessionId}`;
|
|
2196
2465
|
}
|
|
2466
|
+
function buildAliasBindingValue(provider, targetSessionId, sourceSessionId) {
|
|
2467
|
+
return `alias://${provider}/${targetSessionId}/${sourceSessionId}`;
|
|
2468
|
+
}
|
|
2197
2469
|
function extractPendingBindingTargetSessionId(value) {
|
|
2198
2470
|
if (!isPendingBindingValue(value)) {
|
|
2199
2471
|
return null;
|
|
@@ -2202,6 +2474,25 @@ function extractPendingBindingTargetSessionId(value) {
|
|
|
2202
2474
|
const targetSessionId = normalizedValue.slice(normalizedValue.indexOf("/", "pending://".length) + 1).trim();
|
|
2203
2475
|
return targetSessionId || null;
|
|
2204
2476
|
}
|
|
2477
|
+
function extractAliasBindingTargetSessionId(value) {
|
|
2478
|
+
const normalizedValue = value.trim();
|
|
2479
|
+
if (!normalizedValue.toLowerCase().startsWith("alias://")) {
|
|
2480
|
+
return null;
|
|
2481
|
+
}
|
|
2482
|
+
const pathStart = normalizedValue.indexOf("/", "alias://".length);
|
|
2483
|
+
if (pathStart < 0) {
|
|
2484
|
+
return null;
|
|
2485
|
+
}
|
|
2486
|
+
const targetAndSource = normalizedValue.slice(pathStart + 1).trim();
|
|
2487
|
+
if (targetAndSource.length === 0) {
|
|
2488
|
+
return null;
|
|
2489
|
+
}
|
|
2490
|
+
const [targetSessionId] = targetAndSource.split("/", 1);
|
|
2491
|
+
return targetSessionId?.trim() || null;
|
|
2492
|
+
}
|
|
2493
|
+
function extractSessionAliasTargetSessionId(value) {
|
|
2494
|
+
return extractAliasBindingTargetSessionId(value) ?? extractPendingBindingTargetSessionId(value);
|
|
2495
|
+
}
|
|
2205
2496
|
function isClaudePendingRuntimeRawStoreRef(rawStoreRef) {
|
|
2206
2497
|
const normalizedRawStoreRef = rawStoreRef.replaceAll("\\", "/").toLowerCase();
|
|
2207
2498
|
return normalizedRawStoreRef.includes("/.pending-");
|
|
@@ -2570,7 +2861,7 @@ function mapResolutionSourceToLegacyActivitySource(source, inspection) {
|
|
|
2570
2861
|
if (source === "authoritative_runtime" || source === "authoritative_provider_event") {
|
|
2571
2862
|
return "runtime";
|
|
2572
2863
|
}
|
|
2573
|
-
if (inspection.lastEventAt || inspection.completedAtCandidate) {
|
|
2864
|
+
if (inspection && (inspection.lastEventAt || inspection.completedAtCandidate)) {
|
|
2574
2865
|
return "inferred";
|
|
2575
2866
|
}
|
|
2576
2867
|
return "none";
|
|
@@ -2620,4 +2911,71 @@ function buildReconstructedForkPrompt(input) {
|
|
|
2620
2911
|
}
|
|
2621
2912
|
return lines.join("\n").trim();
|
|
2622
2913
|
}
|
|
2914
|
+
function buildProviderCapabilityCacheKey(provider, workspacePath) {
|
|
2915
|
+
return `${provider}::${workspacePath ?? ""}`;
|
|
2916
|
+
}
|
|
2917
|
+
async function runWithConcurrency(items, concurrency, worker) {
|
|
2918
|
+
const normalizedConcurrency = Math.max(1, Math.floor(concurrency) || 1);
|
|
2919
|
+
const queue = [...items];
|
|
2920
|
+
const runners = Array.from({
|
|
2921
|
+
length: Math.min(normalizedConcurrency, queue.length || 1)
|
|
2922
|
+
}, async () => {
|
|
2923
|
+
while (queue.length > 0) {
|
|
2924
|
+
const current = queue.shift();
|
|
2925
|
+
if (current === undefined) {
|
|
2926
|
+
return;
|
|
2927
|
+
}
|
|
2928
|
+
await worker(current);
|
|
2929
|
+
}
|
|
2930
|
+
});
|
|
2931
|
+
await Promise.all(runners);
|
|
2932
|
+
}
|
|
2933
|
+
async function runBatchedTransactions(items, batchSize, transaction) {
|
|
2934
|
+
const normalizedBatchSize = Math.max(1, Math.floor(batchSize) || 1);
|
|
2935
|
+
let batchCount = 0;
|
|
2936
|
+
let maxBatchMs = 0;
|
|
2937
|
+
for (let index = 0; index < items.length; index += normalizedBatchSize) {
|
|
2938
|
+
const batch = items.slice(index, index + normalizedBatchSize);
|
|
2939
|
+
const batchStartedAt = Date.now();
|
|
2940
|
+
transaction(batch);
|
|
2941
|
+
const batchDurationMs = Date.now() - batchStartedAt;
|
|
2942
|
+
batchCount += 1;
|
|
2943
|
+
maxBatchMs = Math.max(maxBatchMs, batchDurationMs);
|
|
2944
|
+
if (index + normalizedBatchSize < items.length) {
|
|
2945
|
+
await delay(0);
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2948
|
+
return {
|
|
2949
|
+
batchCount,
|
|
2950
|
+
maxBatchMs
|
|
2951
|
+
};
|
|
2952
|
+
}
|
|
2953
|
+
function applyImmediateModelOptionFallbacks(capabilities, codexSnapshot, openCodeSnapshot) {
|
|
2954
|
+
if (capabilities.provider === "codex") {
|
|
2955
|
+
return {
|
|
2956
|
+
...capabilities,
|
|
2957
|
+
modelOptions: codexSnapshot?.modelOptions ?? createFallbackCodexModelOptions(null),
|
|
2958
|
+
defaultReasoningLevel: codexSnapshot?.defaultReasoningLevel ?? null,
|
|
2959
|
+
limitations: codexSnapshot
|
|
2960
|
+
? capabilities.limitations
|
|
2961
|
+
: Array.from(new Set([
|
|
2962
|
+
...capabilities.limitations,
|
|
2963
|
+
"当前暂时使用缓存或兜底模型列表,后台会继续刷新 Codex 能力。"
|
|
2964
|
+
]))
|
|
2965
|
+
};
|
|
2966
|
+
}
|
|
2967
|
+
if (capabilities.provider === "opencode") {
|
|
2968
|
+
return {
|
|
2969
|
+
...capabilities,
|
|
2970
|
+
modelOptions: openCodeSnapshot?.modelOptions ?? createFallbackOpenCodeModelOptions(null),
|
|
2971
|
+
limitations: openCodeSnapshot
|
|
2972
|
+
? capabilities.limitations
|
|
2973
|
+
: Array.from(new Set([
|
|
2974
|
+
...capabilities.limitations,
|
|
2975
|
+
"当前暂时使用缓存或兜底模型列表,后台会继续刷新 OpenCode 能力。"
|
|
2976
|
+
]))
|
|
2977
|
+
};
|
|
2978
|
+
}
|
|
2979
|
+
return capabilities;
|
|
2980
|
+
}
|
|
2623
2981
|
//# sourceMappingURL=session-history-service.js.map
|