@sudocode-ai/local-server 0.1.7 → 0.1.8
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 +6 -0
- package/dist/errors/agent-errors.d.ts +43 -0
- package/dist/errors/agent-errors.d.ts.map +1 -0
- package/dist/errors/agent-errors.js +69 -0
- package/dist/errors/agent-errors.js.map +1 -0
- package/dist/execution/adapters/claude-adapter.d.ts +63 -0
- package/dist/execution/adapters/claude-adapter.d.ts.map +1 -0
- package/dist/execution/adapters/claude-adapter.js +82 -0
- package/dist/execution/adapters/claude-adapter.js.map +1 -0
- package/dist/execution/adapters/codex-adapter.d.ts +67 -0
- package/dist/execution/adapters/codex-adapter.d.ts.map +1 -0
- package/dist/execution/adapters/codex-adapter.js +183 -0
- package/dist/execution/adapters/codex-adapter.js.map +1 -0
- package/dist/execution/adapters/codex-config-builder.d.ts +30 -0
- package/dist/execution/adapters/codex-config-builder.d.ts.map +1 -0
- package/dist/execution/adapters/codex-config-builder.js +110 -0
- package/dist/execution/adapters/codex-config-builder.js.map +1 -0
- package/dist/execution/adapters/copilot-adapter.d.ts +94 -0
- package/dist/execution/adapters/copilot-adapter.d.ts.map +1 -0
- package/dist/execution/adapters/copilot-adapter.js +163 -0
- package/dist/execution/adapters/copilot-adapter.js.map +1 -0
- package/dist/execution/adapters/copilot-config-builder.d.ts +48 -0
- package/dist/execution/adapters/copilot-config-builder.d.ts.map +1 -0
- package/dist/execution/adapters/copilot-config-builder.js +125 -0
- package/dist/execution/adapters/copilot-config-builder.js.map +1 -0
- package/dist/execution/adapters/cursor-adapter.d.ts +66 -0
- package/dist/execution/adapters/cursor-adapter.d.ts.map +1 -0
- package/dist/execution/adapters/cursor-adapter.js +121 -0
- package/dist/execution/adapters/cursor-adapter.js.map +1 -0
- package/dist/execution/adapters/cursor-config-builder.d.ts +29 -0
- package/dist/execution/adapters/cursor-config-builder.d.ts.map +1 -0
- package/dist/execution/adapters/cursor-config-builder.js +49 -0
- package/dist/execution/adapters/cursor-config-builder.js.map +1 -0
- package/dist/execution/adapters/shared/config-presets.d.ts +102 -0
- package/dist/execution/adapters/shared/config-presets.d.ts.map +1 -0
- package/dist/execution/adapters/shared/config-presets.js +205 -0
- package/dist/execution/adapters/shared/config-presets.js.map +1 -0
- package/dist/execution/adapters/shared/config-utils.d.ts +95 -0
- package/dist/execution/adapters/shared/config-utils.d.ts.map +1 -0
- package/dist/execution/adapters/shared/config-utils.js +163 -0
- package/dist/execution/adapters/shared/config-utils.js.map +1 -0
- package/dist/execution/adapters/shared/index.d.ts +8 -0
- package/dist/execution/adapters/shared/index.d.ts.map +1 -0
- package/dist/execution/adapters/shared/index.js +8 -0
- package/dist/execution/adapters/shared/index.js.map +1 -0
- package/dist/execution/executors/agent-executor-wrapper.d.ts +153 -0
- package/dist/execution/executors/agent-executor-wrapper.d.ts.map +1 -0
- package/dist/execution/executors/agent-executor-wrapper.js +652 -0
- package/dist/execution/executors/agent-executor-wrapper.js.map +1 -0
- package/dist/execution/executors/executor-factory.d.ts +95 -0
- package/dist/execution/executors/executor-factory.d.ts.map +1 -0
- package/dist/execution/executors/executor-factory.js +120 -0
- package/dist/execution/executors/executor-factory.js.map +1 -0
- package/dist/execution/output/ag-ui-adapter.d.ts +0 -2
- package/dist/execution/output/ag-ui-adapter.d.ts.map +1 -1
- package/dist/execution/output/ag-ui-adapter.js +0 -2
- package/dist/execution/output/ag-ui-adapter.js.map +1 -1
- package/dist/execution/output/index.d.ts +0 -3
- package/dist/execution/output/index.d.ts.map +1 -1
- package/dist/execution/output/index.js +0 -2
- package/dist/execution/output/index.js.map +1 -1
- package/dist/execution/output/normalized-to-ag-ui-adapter.d.ts +108 -0
- package/dist/execution/output/normalized-to-ag-ui-adapter.d.ts.map +1 -0
- package/dist/execution/output/normalized-to-ag-ui-adapter.js +321 -0
- package/dist/execution/output/normalized-to-ag-ui-adapter.js.map +1 -0
- package/dist/execution/process/builders/claude.d.ts +24 -57
- package/dist/execution/process/builders/claude.d.ts.map +1 -1
- package/dist/execution/process/builders/claude.js +153 -19
- package/dist/execution/process/builders/claude.js.map +1 -1
- package/dist/execution/transport/ipc-transport-manager.d.ts +74 -0
- package/dist/execution/transport/ipc-transport-manager.d.ts.map +1 -0
- package/dist/execution/transport/ipc-transport-manager.js +104 -0
- package/dist/execution/transport/ipc-transport-manager.js.map +1 -0
- package/dist/execution/transport/transport-manager.d.ts.map +1 -1
- package/dist/execution/transport/transport-manager.js +3 -0
- package/dist/execution/transport/transport-manager.js.map +1 -1
- package/dist/execution/worktree/conflict-detector.d.ts +85 -0
- package/dist/execution/worktree/conflict-detector.d.ts.map +1 -0
- package/dist/execution/worktree/conflict-detector.js +129 -0
- package/dist/execution/worktree/conflict-detector.js.map +1 -0
- package/dist/execution/worktree/git-cli.d.ts +9 -0
- package/dist/execution/worktree/git-cli.d.ts.map +1 -1
- package/dist/execution/worktree/git-cli.js +10 -0
- package/dist/execution/worktree/git-cli.js.map +1 -1
- package/dist/execution/worktree/git-sync-cli.d.ts +187 -0
- package/dist/execution/worktree/git-sync-cli.d.ts.map +1 -0
- package/dist/execution/worktree/git-sync-cli.js +350 -0
- package/dist/execution/worktree/git-sync-cli.js.map +1 -0
- package/dist/execution/worktree/manager.d.ts +18 -0
- package/dist/execution/worktree/manager.d.ts.map +1 -1
- package/dist/execution/worktree/manager.js +9 -3
- package/dist/execution/worktree/manager.js.map +1 -1
- package/dist/index.d.ts +1 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +132 -211
- package/dist/index.js.map +1 -1
- package/dist/middleware/project-context.d.ts +37 -0
- package/dist/middleware/project-context.d.ts.map +1 -0
- package/dist/middleware/project-context.js +91 -0
- package/dist/middleware/project-context.js.map +1 -0
- package/dist/public/assets/index-Bb_W5bUr.css +1 -0
- package/dist/public/assets/index-CFKL113G.js +710 -0
- package/dist/public/assets/index-CFKL113G.js.map +1 -0
- package/dist/public/assets/{react-vendor-ByUx1V_q.js → react-vendor-DiL5hC7l.js} +2 -2
- package/dist/public/assets/{react-vendor-ByUx1V_q.js.map → react-vendor-DiL5hC7l.js.map} +1 -1
- package/dist/public/assets/ui-vendor-B4WMPEfa.js +54 -0
- package/dist/public/assets/ui-vendor-B4WMPEfa.js.map +1 -0
- package/dist/public/index.html +4 -4
- package/dist/routes/agents.d.ts +3 -0
- package/dist/routes/agents.d.ts.map +1 -0
- package/dist/routes/agents.js +62 -0
- package/dist/routes/agents.js.map +1 -0
- package/dist/routes/config.d.ts +3 -0
- package/dist/routes/config.d.ts.map +1 -0
- package/dist/routes/config.js +25 -0
- package/dist/routes/config.js.map +1 -0
- package/dist/routes/editors.d.ts +15 -0
- package/dist/routes/editors.d.ts.map +1 -0
- package/dist/routes/editors.js +98 -0
- package/dist/routes/editors.js.map +1 -0
- package/dist/routes/executions-stream.d.ts +8 -5
- package/dist/routes/executions-stream.d.ts.map +1 -1
- package/dist/routes/executions-stream.js +10 -6
- package/dist/routes/executions-stream.js.map +1 -1
- package/dist/routes/executions.d.ts +6 -10
- package/dist/routes/executions.d.ts.map +1 -1
- package/dist/routes/executions.js +506 -54
- package/dist/routes/executions.js.map +1 -1
- package/dist/routes/feedback.d.ts +3 -2
- package/dist/routes/feedback.d.ts.map +1 -1
- package/dist/routes/feedback.js +12 -10
- package/dist/routes/feedback.js.map +1 -1
- package/dist/routes/files.d.ts +18 -0
- package/dist/routes/files.d.ts.map +1 -0
- package/dist/routes/files.js +89 -0
- package/dist/routes/files.js.map +1 -0
- package/dist/routes/issues.d.ts +3 -2
- package/dist/routes/issues.d.ts.map +1 -1
- package/dist/routes/issues.js +19 -18
- package/dist/routes/issues.js.map +1 -1
- package/dist/routes/projects.d.ts +11 -0
- package/dist/routes/projects.d.ts.map +1 -0
- package/dist/routes/projects.js +447 -0
- package/dist/routes/projects.js.map +1 -0
- package/dist/routes/relationships.d.ts +3 -2
- package/dist/routes/relationships.d.ts.map +1 -1
- package/dist/routes/relationships.js +12 -10
- package/dist/routes/relationships.js.map +1 -1
- package/dist/routes/repo-info.d.ts +3 -0
- package/dist/routes/repo-info.d.ts.map +1 -0
- package/dist/routes/repo-info.js +126 -0
- package/dist/routes/repo-info.js.map +1 -0
- package/dist/routes/specs.d.ts +3 -2
- package/dist/routes/specs.d.ts.map +1 -1
- package/dist/routes/specs.js +19 -18
- package/dist/routes/specs.js.map +1 -1
- package/dist/services/agent-registry.d.ts +140 -0
- package/dist/services/agent-registry.d.ts.map +1 -0
- package/dist/services/agent-registry.js +272 -0
- package/dist/services/agent-registry.js.map +1 -0
- package/dist/services/editor-service.d.ts +57 -0
- package/dist/services/editor-service.d.ts.map +1 -0
- package/dist/services/editor-service.js +204 -0
- package/dist/services/editor-service.js.map +1 -0
- package/dist/services/execution-changes-service.d.ts +92 -0
- package/dist/services/execution-changes-service.d.ts.map +1 -0
- package/dist/services/execution-changes-service.js +546 -0
- package/dist/services/execution-changes-service.js.map +1 -0
- package/dist/services/execution-lifecycle.d.ts +1 -0
- package/dist/services/execution-lifecycle.d.ts.map +1 -1
- package/dist/services/execution-lifecycle.js +37 -7
- package/dist/services/execution-lifecycle.js.map +1 -1
- package/dist/services/execution-logs-store.d.ts +75 -0
- package/dist/services/execution-logs-store.d.ts.map +1 -1
- package/dist/services/execution-logs-store.js +142 -2
- package/dist/services/execution-logs-store.js.map +1 -1
- package/dist/services/execution-service.d.ts +50 -58
- package/dist/services/execution-service.d.ts.map +1 -1
- package/dist/services/execution-service.js +433 -469
- package/dist/services/execution-service.js.map +1 -1
- package/dist/services/execution-worker-pool.d.ts +116 -0
- package/dist/services/execution-worker-pool.d.ts.map +1 -0
- package/dist/services/execution-worker-pool.js +326 -0
- package/dist/services/execution-worker-pool.js.map +1 -0
- package/dist/services/executions.d.ts +3 -0
- package/dist/services/executions.d.ts.map +1 -1
- package/dist/services/executions.js +11 -17
- package/dist/services/executions.js.map +1 -1
- package/dist/services/export.d.ts +8 -2
- package/dist/services/export.d.ts.map +1 -1
- package/dist/services/export.js +29 -23
- package/dist/services/export.js.map +1 -1
- package/dist/services/file-search/git-ls-files-strategy.d.ts +72 -0
- package/dist/services/file-search/git-ls-files-strategy.d.ts.map +1 -0
- package/dist/services/file-search/git-ls-files-strategy.js +176 -0
- package/dist/services/file-search/git-ls-files-strategy.js.map +1 -0
- package/dist/services/file-search/index.d.ts +9 -0
- package/dist/services/file-search/index.d.ts.map +1 -0
- package/dist/services/file-search/index.js +10 -0
- package/dist/services/file-search/index.js.map +1 -0
- package/dist/services/file-search/registry.d.ts +97 -0
- package/dist/services/file-search/registry.d.ts.map +1 -0
- package/dist/services/file-search/registry.js +140 -0
- package/dist/services/file-search/registry.js.map +1 -0
- package/dist/services/file-search/strategy.d.ts +58 -0
- package/dist/services/file-search/strategy.d.ts.map +1 -0
- package/dist/services/file-search/strategy.js +8 -0
- package/dist/services/file-search/strategy.js.map +1 -0
- package/dist/services/project-context.d.ts +69 -0
- package/dist/services/project-context.d.ts.map +1 -0
- package/dist/services/project-context.js +113 -0
- package/dist/services/project-context.js.map +1 -0
- package/dist/services/project-manager.d.ts +95 -0
- package/dist/services/project-manager.d.ts.map +1 -0
- package/dist/services/project-manager.js +388 -0
- package/dist/services/project-manager.js.map +1 -0
- package/dist/services/project-registry.d.ts +98 -0
- package/dist/services/project-registry.d.ts.map +1 -0
- package/dist/services/project-registry.js +289 -0
- package/dist/services/project-registry.js.map +1 -0
- package/dist/services/prompt-resolver.d.ts +97 -0
- package/dist/services/prompt-resolver.d.ts.map +1 -0
- package/dist/services/prompt-resolver.js +377 -0
- package/dist/services/prompt-resolver.js.map +1 -0
- package/dist/services/repo-info.d.ts +12 -0
- package/dist/services/repo-info.d.ts.map +1 -1
- package/dist/services/repo-info.js +46 -0
- package/dist/services/repo-info.js.map +1 -1
- package/dist/services/watcher.d.ts +3 -4
- package/dist/services/watcher.d.ts.map +1 -1
- package/dist/services/watcher.js +18 -35
- package/dist/services/watcher.js.map +1 -1
- package/dist/services/websocket.d.ts +30 -16
- package/dist/services/websocket.d.ts.map +1 -1
- package/dist/services/websocket.js +102 -37
- package/dist/services/websocket.js.map +1 -1
- package/dist/services/worktree-sync-service.d.ts +228 -0
- package/dist/services/worktree-sync-service.d.ts.map +1 -0
- package/dist/services/worktree-sync-service.js +563 -0
- package/dist/services/worktree-sync-service.js.map +1 -0
- package/dist/types/editor.d.ts +49 -0
- package/dist/types/editor.d.ts.map +1 -0
- package/dist/types/editor.js +50 -0
- package/dist/types/editor.js.map +1 -0
- package/dist/types/project.d.ts +58 -0
- package/dist/types/project.d.ts.map +1 -0
- package/dist/types/project.js +10 -0
- package/dist/types/project.js.map +1 -0
- package/dist/utils/executable-check.d.ts +36 -0
- package/dist/utils/executable-check.d.ts.map +1 -0
- package/dist/utils/executable-check.js +79 -0
- package/dist/utils/executable-check.js.map +1 -0
- package/dist/workers/execution-worker.d.ts +18 -0
- package/dist/workers/execution-worker.d.ts.map +1 -0
- package/dist/workers/execution-worker.js +340 -0
- package/dist/workers/execution-worker.js.map +1 -0
- package/dist/workers/worker-ipc.d.ts +84 -0
- package/dist/workers/worker-ipc.d.ts.map +1 -0
- package/dist/workers/worker-ipc.js +29 -0
- package/dist/workers/worker-ipc.js.map +1 -0
- package/package.json +6 -5
- package/dist/execution/output/ag-ui-integration.d.ts +0 -96
- package/dist/execution/output/ag-ui-integration.d.ts.map +0 -1
- package/dist/execution/output/ag-ui-integration.js +0 -96
- package/dist/execution/output/ag-ui-integration.js.map +0 -1
- package/dist/execution/output/claude-code-output-processor.d.ts +0 -321
- package/dist/execution/output/claude-code-output-processor.d.ts.map +0 -1
- package/dist/execution/output/claude-code-output-processor.js +0 -769
- package/dist/execution/output/claude-code-output-processor.js.map +0 -1
- package/dist/public/assets/index-B3SEMufD.js +0 -580
- package/dist/public/assets/index-B3SEMufD.js.map +0 -1
- package/dist/public/assets/index-D2YGL3gX.css +0 -1
- package/dist/public/assets/ui-vendor-CotR6bx9.js +0 -54
- package/dist/public/assets/ui-vendor-CotR6bx9.js.map +0 -1
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import { ProjectContext } from "./project-context.js";
|
|
4
|
+
import { initDatabase } from "./db.js";
|
|
5
|
+
import { TransportManager } from "../execution/transport/transport-manager.js";
|
|
6
|
+
import { ExecutionService } from "./execution-service.js";
|
|
7
|
+
import { ExecutionLogsStore } from "./execution-logs-store.js";
|
|
8
|
+
import { WorktreeManager } from "../execution/worktree/manager.js";
|
|
9
|
+
import { getWorktreeConfig } from "../execution/worktree/config.js";
|
|
10
|
+
import { ExecutionLifecycleService } from "./execution-lifecycle.js";
|
|
11
|
+
import { startServerWatcher } from "./watcher.js";
|
|
12
|
+
import { Ok, Err } from "../types/project.js";
|
|
13
|
+
import { broadcastIssueUpdate, broadcastSpecUpdate } from "./websocket.js";
|
|
14
|
+
import { getIssueById } from "./issues.js";
|
|
15
|
+
import { getSpecById } from "./specs.js";
|
|
16
|
+
import { performInitialization, isInitialized, } from "@sudocode-ai/cli/dist/cli/init-commands.js";
|
|
17
|
+
/**
|
|
18
|
+
* ProjectManager manages the lifecycle of multiple open projects.
|
|
19
|
+
*
|
|
20
|
+
* Responsibilities:
|
|
21
|
+
* - Open and close projects
|
|
22
|
+
* - Validate project directories
|
|
23
|
+
* - Cache database connections with TTL eviction
|
|
24
|
+
* - Track all open projects
|
|
25
|
+
* - Coordinate with ProjectRegistry for persistence
|
|
26
|
+
*
|
|
27
|
+
* Architecture:
|
|
28
|
+
* - Each open project gets a ProjectContext with isolated services
|
|
29
|
+
* - Database connections are cached for 30 minutes after project close
|
|
30
|
+
* - All services (file watcher, executions, etc.) are per-project
|
|
31
|
+
*/
|
|
32
|
+
export class ProjectManager {
|
|
33
|
+
registry;
|
|
34
|
+
openProjects = new Map();
|
|
35
|
+
dbCache = new Map();
|
|
36
|
+
/** Database connection TTL: 30 minutes */
|
|
37
|
+
DB_CACHE_TTL = 30 * 60 * 1000;
|
|
38
|
+
/** Whether file watching is enabled */
|
|
39
|
+
watchEnabled;
|
|
40
|
+
constructor(registry, options) {
|
|
41
|
+
this.registry = registry;
|
|
42
|
+
this.watchEnabled = options?.watchEnabled ?? true;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Open a project and initialize all its services
|
|
46
|
+
* @param projectPath - Absolute path to project root directory
|
|
47
|
+
* @returns ProjectContext for the opened project
|
|
48
|
+
*/
|
|
49
|
+
async openProject(projectPath) {
|
|
50
|
+
try {
|
|
51
|
+
// 1. Validate project structure
|
|
52
|
+
const validation = this.validateProject(projectPath);
|
|
53
|
+
if (!validation.ok) {
|
|
54
|
+
return validation;
|
|
55
|
+
}
|
|
56
|
+
// 2. Generate or lookup project ID
|
|
57
|
+
const projectId = this.registry.generateProjectId(projectPath);
|
|
58
|
+
// 3. Check if already open
|
|
59
|
+
const existing = this.openProjects.get(projectId);
|
|
60
|
+
if (existing) {
|
|
61
|
+
console.log(`Project already open: ${projectId}`);
|
|
62
|
+
this.registry.updateLastOpened(projectId);
|
|
63
|
+
await this.registry.save();
|
|
64
|
+
return Ok(existing);
|
|
65
|
+
}
|
|
66
|
+
// 4. Initialize database (check cache first)
|
|
67
|
+
const db = await this.getOrCreateDatabase(projectId, projectPath);
|
|
68
|
+
// 5. Initialize all services for this project
|
|
69
|
+
const sudocodeDir = path.join(projectPath, ".sudocode");
|
|
70
|
+
const transportManager = new TransportManager();
|
|
71
|
+
const logsStore = new ExecutionLogsStore(db);
|
|
72
|
+
const worktreeConfig = getWorktreeConfig(projectPath);
|
|
73
|
+
const worktreeManager = new WorktreeManager(worktreeConfig);
|
|
74
|
+
// NOTE: Worker pool execution is disabled - using in-process execution
|
|
75
|
+
// Worker pool can be re-enabled by uncommenting the ExecutionWorkerPool creation
|
|
76
|
+
// and passing it to ExecutionService and ProjectContext
|
|
77
|
+
// Create execution service without worker pool (will use in-process execution)
|
|
78
|
+
const executionService = new ExecutionService(db, projectId, projectPath, undefined, transportManager, logsStore, undefined // No worker pool - use in-process execution
|
|
79
|
+
);
|
|
80
|
+
// 6. Create project context
|
|
81
|
+
const context = new ProjectContext(projectId, projectPath, sudocodeDir, db, transportManager, executionService, logsStore, worktreeManager, undefined // No worker pool
|
|
82
|
+
);
|
|
83
|
+
await context.initialize();
|
|
84
|
+
// 7. Start file watcher if enabled
|
|
85
|
+
if (this.watchEnabled) {
|
|
86
|
+
context.watcher = startServerWatcher({
|
|
87
|
+
db,
|
|
88
|
+
baseDir: sudocodeDir,
|
|
89
|
+
onFileChange: (info) => {
|
|
90
|
+
console.log(`[project-manager] File change in ${projectId}`);
|
|
91
|
+
// Broadcast WebSocket updates based on entity type
|
|
92
|
+
if (info.entityType && info.entityId) {
|
|
93
|
+
if (info.entityType === "issue") {
|
|
94
|
+
// Use entity from event if available (optimization)
|
|
95
|
+
if (info.entity) {
|
|
96
|
+
broadcastIssueUpdate(projectId, info.entityId, "updated", info.entity);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
// Fallback to DB query (for backward compatibility)
|
|
100
|
+
const issue = getIssueById(db, info.entityId);
|
|
101
|
+
if (issue) {
|
|
102
|
+
broadcastIssueUpdate(projectId, info.entityId, "updated", issue);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else if (info.entityType === "spec") {
|
|
107
|
+
// Use entity from event if available (optimization)
|
|
108
|
+
if (info.entity) {
|
|
109
|
+
broadcastSpecUpdate(projectId, info.entityId, "updated", info.entity);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
// Fallback to DB query (for backward compatibility)
|
|
113
|
+
const spec = getSpecById(db, info.entityId);
|
|
114
|
+
if (spec) {
|
|
115
|
+
broadcastSpecUpdate(projectId, info.entityId, "updated", spec);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
// 8. Cleanup orphaned worktrees on first open
|
|
124
|
+
if (worktreeConfig.cleanupOrphanedWorktreesOnStartup) {
|
|
125
|
+
try {
|
|
126
|
+
const lifecycleService = new ExecutionLifecycleService(db, projectPath, worktreeManager);
|
|
127
|
+
await lifecycleService.cleanupOrphanedWorktrees();
|
|
128
|
+
console.log(`Cleaned up orphaned worktrees for ${projectId}`);
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
console.warn(`Failed to cleanup orphaned worktrees for ${projectId}:`, error);
|
|
132
|
+
// Don't fail the open operation
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// 9. Register and track
|
|
136
|
+
this.registry.registerProject(projectPath);
|
|
137
|
+
this.registry.updateLastOpened(projectId);
|
|
138
|
+
await this.registry.save();
|
|
139
|
+
this.openProjects.set(projectId, context);
|
|
140
|
+
console.log(`Project opened successfully: ${projectId} at ${projectPath}`);
|
|
141
|
+
return Ok(context);
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
console.error(`Failed to open project at ${projectPath}:`, error);
|
|
145
|
+
return Err({
|
|
146
|
+
type: "UNKNOWN",
|
|
147
|
+
message: error.message || String(error),
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Initialize a new sudocode project in an existing directory
|
|
153
|
+
* @param projectPath - Absolute path to project root directory
|
|
154
|
+
* @param name - Optional custom project name
|
|
155
|
+
* @returns ProjectContext for the initialized and opened project
|
|
156
|
+
*/
|
|
157
|
+
async initializeProject(projectPath, name) {
|
|
158
|
+
try {
|
|
159
|
+
// 1. Check that path exists
|
|
160
|
+
if (!fs.existsSync(projectPath)) {
|
|
161
|
+
return Err({
|
|
162
|
+
type: "PATH_NOT_FOUND",
|
|
163
|
+
path: projectPath,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
// 2. Check that it's a directory
|
|
167
|
+
const stats = fs.statSync(projectPath);
|
|
168
|
+
if (!stats.isDirectory()) {
|
|
169
|
+
return Err({
|
|
170
|
+
type: "INVALID_PROJECT",
|
|
171
|
+
message: `Path is not a directory: ${projectPath}`,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
// 3. Check if already initialized
|
|
175
|
+
const sudocodeDir = path.join(projectPath, ".sudocode");
|
|
176
|
+
if (isInitialized(sudocodeDir)) {
|
|
177
|
+
// Already initialized, just open it
|
|
178
|
+
console.log(`Project already initialized at ${projectPath}, opening...`);
|
|
179
|
+
return this.openProject(projectPath);
|
|
180
|
+
}
|
|
181
|
+
// 4. Perform initialization using CLI's performInitialization
|
|
182
|
+
console.log(`Initializing new project at ${projectPath}`);
|
|
183
|
+
await performInitialization({
|
|
184
|
+
dir: sudocodeDir,
|
|
185
|
+
jsonOutput: true, // Suppress CLI console output
|
|
186
|
+
});
|
|
187
|
+
// 5. Update project name in registry if provided
|
|
188
|
+
const projectId = this.registry.generateProjectId(projectPath);
|
|
189
|
+
if (name) {
|
|
190
|
+
this.registry.registerProject(projectPath);
|
|
191
|
+
this.registry.updateProject(projectId, { name });
|
|
192
|
+
await this.registry.save();
|
|
193
|
+
}
|
|
194
|
+
// 6. Open the newly initialized project
|
|
195
|
+
return this.openProject(projectPath);
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
console.error(`Failed to initialize project at ${projectPath}:`, error);
|
|
199
|
+
return Err({
|
|
200
|
+
type: "UNKNOWN",
|
|
201
|
+
message: error.message || String(error),
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Close a project and cleanup its resources
|
|
207
|
+
* @param projectId - Project ID to close
|
|
208
|
+
* @param keepDbInCache - Whether to keep database in cache (default: true)
|
|
209
|
+
*/
|
|
210
|
+
async closeProject(projectId, keepDbInCache = true) {
|
|
211
|
+
const context = this.openProjects.get(projectId);
|
|
212
|
+
if (!context) {
|
|
213
|
+
console.warn(`Cannot close project ${projectId}: not open`);
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
console.log(`Closing project: ${projectId}`);
|
|
217
|
+
try {
|
|
218
|
+
// Shutdown project context (stops watcher, cancels executions, etc.)
|
|
219
|
+
await context.shutdown();
|
|
220
|
+
// Keep DB in cache for fast reopening (unless explicitly disabled)
|
|
221
|
+
if (keepDbInCache) {
|
|
222
|
+
this.addToDbCache(projectId, context.db);
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
context.db.close();
|
|
226
|
+
}
|
|
227
|
+
// Remove from active projects
|
|
228
|
+
this.openProjects.delete(projectId);
|
|
229
|
+
// TODO: Broadcast project_closed WebSocket message
|
|
230
|
+
console.log(`Project closed: ${projectId}`);
|
|
231
|
+
}
|
|
232
|
+
catch (error) {
|
|
233
|
+
console.error(`Error closing project ${projectId}:`, error);
|
|
234
|
+
throw error;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Get an open project by ID
|
|
239
|
+
*/
|
|
240
|
+
getProject(projectId) {
|
|
241
|
+
return this.openProjects.get(projectId) || null;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Get all currently open projects
|
|
245
|
+
*/
|
|
246
|
+
getAllOpenProjects() {
|
|
247
|
+
return Array.from(this.openProjects.values());
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Check if a project is currently open
|
|
251
|
+
*/
|
|
252
|
+
isProjectOpen(projectId) {
|
|
253
|
+
return this.openProjects.has(projectId);
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Validate that a project directory is valid for opening
|
|
257
|
+
*/
|
|
258
|
+
validateProject(projectPath) {
|
|
259
|
+
// Check that path exists
|
|
260
|
+
if (!fs.existsSync(projectPath)) {
|
|
261
|
+
return Err({
|
|
262
|
+
type: "PATH_NOT_FOUND",
|
|
263
|
+
path: projectPath,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
// Check that it's a directory
|
|
267
|
+
const stats = fs.statSync(projectPath);
|
|
268
|
+
if (!stats.isDirectory()) {
|
|
269
|
+
return Err({
|
|
270
|
+
type: "INVALID_PROJECT",
|
|
271
|
+
message: `Path is not a directory: ${projectPath}`,
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
// Check that .sudocode directory exists
|
|
275
|
+
const sudocodeDir = path.join(projectPath, ".sudocode");
|
|
276
|
+
if (!fs.existsSync(sudocodeDir)) {
|
|
277
|
+
return Err({
|
|
278
|
+
type: "INVALID_PROJECT",
|
|
279
|
+
message: `Missing .sudocode directory: ${sudocodeDir}`,
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
// Check that cache.db exists
|
|
283
|
+
const dbPath = path.join(sudocodeDir, "cache.db");
|
|
284
|
+
if (!fs.existsSync(dbPath)) {
|
|
285
|
+
return Err({
|
|
286
|
+
type: "INVALID_PROJECT",
|
|
287
|
+
message: `Missing cache.db file: ${dbPath}`,
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
return Ok(undefined);
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Get or create a database connection for a project
|
|
294
|
+
* Checks cache first, then initializes new connection
|
|
295
|
+
*/
|
|
296
|
+
async getOrCreateDatabase(projectId, projectPath) {
|
|
297
|
+
// Check cache
|
|
298
|
+
const cached = this.dbCache.get(projectId);
|
|
299
|
+
if (cached) {
|
|
300
|
+
console.log(`Using cached database for ${projectId}`);
|
|
301
|
+
cached.lastAccessed = new Date();
|
|
302
|
+
// Clear eviction timer since we're using it again
|
|
303
|
+
if (cached.evictionTimer) {
|
|
304
|
+
clearTimeout(cached.evictionTimer);
|
|
305
|
+
cached.evictionTimer = undefined;
|
|
306
|
+
}
|
|
307
|
+
// Remove from cache (will be managed by project context)
|
|
308
|
+
this.dbCache.delete(projectId);
|
|
309
|
+
return cached.db;
|
|
310
|
+
}
|
|
311
|
+
// Initialize new database
|
|
312
|
+
const dbPath = path.join(projectPath, ".sudocode", "cache.db");
|
|
313
|
+
console.log(`Initializing new database for ${projectId} at ${dbPath}`);
|
|
314
|
+
const db = initDatabase({ path: dbPath });
|
|
315
|
+
return db;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Add a database to the cache with TTL eviction
|
|
319
|
+
*/
|
|
320
|
+
addToDbCache(projectId, db) {
|
|
321
|
+
// Clear any existing cache entry
|
|
322
|
+
const existing = this.dbCache.get(projectId);
|
|
323
|
+
if (existing?.evictionTimer) {
|
|
324
|
+
clearTimeout(existing.evictionTimer);
|
|
325
|
+
}
|
|
326
|
+
// Add to cache
|
|
327
|
+
const cached = {
|
|
328
|
+
db,
|
|
329
|
+
lastAccessed: new Date(),
|
|
330
|
+
};
|
|
331
|
+
// Schedule eviction
|
|
332
|
+
cached.evictionTimer = setTimeout(() => {
|
|
333
|
+
const entry = this.dbCache.get(projectId);
|
|
334
|
+
if (entry) {
|
|
335
|
+
const age = Date.now() - entry.lastAccessed.getTime();
|
|
336
|
+
if (age >= this.DB_CACHE_TTL) {
|
|
337
|
+
console.log(`Evicting cached database for ${projectId} (age: ${age}ms)`);
|
|
338
|
+
try {
|
|
339
|
+
entry.db.close();
|
|
340
|
+
}
|
|
341
|
+
catch (error) {
|
|
342
|
+
console.error(`Error closing cached database for ${projectId}:`, error);
|
|
343
|
+
}
|
|
344
|
+
this.dbCache.delete(projectId);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}, this.DB_CACHE_TTL);
|
|
348
|
+
this.dbCache.set(projectId, cached);
|
|
349
|
+
console.log(`Database cached for ${projectId} (TTL: ${this.DB_CACHE_TTL}ms)`);
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Get summary of all projects (open and cached)
|
|
353
|
+
*/
|
|
354
|
+
getSummary() {
|
|
355
|
+
return {
|
|
356
|
+
openProjects: this.getAllOpenProjects().map((p) => p.getSummary()),
|
|
357
|
+
cachedDatabases: Array.from(this.dbCache.keys()),
|
|
358
|
+
totalOpen: this.openProjects.size,
|
|
359
|
+
totalCached: this.dbCache.size,
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Shutdown the project manager and cleanup all resources
|
|
364
|
+
*/
|
|
365
|
+
async shutdown() {
|
|
366
|
+
console.log("Shutting down ProjectManager...");
|
|
367
|
+
// Close all open projects
|
|
368
|
+
const projectIds = Array.from(this.openProjects.keys());
|
|
369
|
+
for (const projectId of projectIds) {
|
|
370
|
+
await this.closeProject(projectId, false); // Don't cache on shutdown
|
|
371
|
+
}
|
|
372
|
+
// Close all cached databases
|
|
373
|
+
for (const [projectId, cached] of this.dbCache.entries()) {
|
|
374
|
+
if (cached.evictionTimer) {
|
|
375
|
+
clearTimeout(cached.evictionTimer);
|
|
376
|
+
}
|
|
377
|
+
try {
|
|
378
|
+
cached.db.close();
|
|
379
|
+
}
|
|
380
|
+
catch (error) {
|
|
381
|
+
console.error(`Error closing cached database for ${projectId}:`, error);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
this.dbCache.clear();
|
|
385
|
+
console.log("ProjectManager shutdown complete");
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
//# sourceMappingURL=project-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-manager.js","sourceRoot":"","sources":["../../src/services/project-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { ProjectInfo, ProjectsConfig, ProjectError, Result } from '../types/project.js';
|
|
2
|
+
/**
|
|
3
|
+
* ProjectRegistry manages the persistent storage of registered projects.
|
|
4
|
+
*
|
|
5
|
+
* Configuration is stored at ~/.config/sudocode/projects.json and includes:
|
|
6
|
+
* - Registered projects with metadata
|
|
7
|
+
* - Recent projects list
|
|
8
|
+
* - User settings
|
|
9
|
+
*/
|
|
10
|
+
export declare class ProjectRegistry {
|
|
11
|
+
private configPath;
|
|
12
|
+
private config;
|
|
13
|
+
/**
|
|
14
|
+
* Create a new ProjectRegistry instance
|
|
15
|
+
* @param configPath - Optional custom config file path (defaults to ~/.config/sudocode/projects.json)
|
|
16
|
+
*/
|
|
17
|
+
constructor(configPath?: string);
|
|
18
|
+
/**
|
|
19
|
+
* Get the default config file path following XDG Base Directory specification
|
|
20
|
+
*/
|
|
21
|
+
private getDefaultConfigPath;
|
|
22
|
+
/**
|
|
23
|
+
* Load configuration from disk. Creates default config if file doesn't exist.
|
|
24
|
+
* @throws {Error} If config file is corrupted or unreadable
|
|
25
|
+
*/
|
|
26
|
+
load(): Promise<Result<void, ProjectError>>;
|
|
27
|
+
/**
|
|
28
|
+
* Save configuration to disk atomically (write to temp file, then rename)
|
|
29
|
+
*/
|
|
30
|
+
save(): Promise<Result<void, ProjectError>>;
|
|
31
|
+
/**
|
|
32
|
+
* Generate a deterministic, human-readable project ID from path
|
|
33
|
+
* Format: <repo-name>-<8-char-hash>
|
|
34
|
+
* Example: sudocode-a1b2c3d4
|
|
35
|
+
*/
|
|
36
|
+
generateProjectId(projectPath: string): string;
|
|
37
|
+
/**
|
|
38
|
+
* Register a new project or update existing one
|
|
39
|
+
* @param projectPath - Absolute path to project root directory
|
|
40
|
+
* @returns ProjectInfo for the registered project
|
|
41
|
+
*/
|
|
42
|
+
registerProject(projectPath: string): ProjectInfo;
|
|
43
|
+
/**
|
|
44
|
+
* Unregister a project (remove from registry)
|
|
45
|
+
* @param projectId - Project ID to remove
|
|
46
|
+
* @returns true if project was removed, false if not found
|
|
47
|
+
*/
|
|
48
|
+
unregisterProject(projectId: string): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Get project info by ID
|
|
51
|
+
*/
|
|
52
|
+
getProject(projectId: string): ProjectInfo | null;
|
|
53
|
+
/**
|
|
54
|
+
* Get all registered projects
|
|
55
|
+
*/
|
|
56
|
+
getAllProjects(): ProjectInfo[];
|
|
57
|
+
/**
|
|
58
|
+
* Update the lastOpenedAt timestamp for a project
|
|
59
|
+
*/
|
|
60
|
+
updateLastOpened(projectId: string): void;
|
|
61
|
+
/**
|
|
62
|
+
* Add a project to the recent projects list
|
|
63
|
+
* Maintains the list at maxRecentProjects size with most recent first
|
|
64
|
+
*/
|
|
65
|
+
addToRecent(projectId: string): void;
|
|
66
|
+
/**
|
|
67
|
+
* Get recent projects (ordered by most recent first)
|
|
68
|
+
*/
|
|
69
|
+
getRecentProjects(): ProjectInfo[];
|
|
70
|
+
/**
|
|
71
|
+
* Update project metadata
|
|
72
|
+
* @param projectId - Project ID to update
|
|
73
|
+
* @param updates - Partial project info to update
|
|
74
|
+
* @returns true if project was updated, false if not found
|
|
75
|
+
*/
|
|
76
|
+
updateProject(projectId: string, updates: Partial<Pick<ProjectInfo, 'name' | 'favorite'>>): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Toggle favorite status for a project
|
|
79
|
+
*/
|
|
80
|
+
toggleFavorite(projectId: string): boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Get all favorite projects
|
|
83
|
+
*/
|
|
84
|
+
getFavoriteProjects(): ProjectInfo[];
|
|
85
|
+
/**
|
|
86
|
+
* Update user settings
|
|
87
|
+
*/
|
|
88
|
+
updateSettings(settings: Partial<ProjectsConfig['settings']>): void;
|
|
89
|
+
/**
|
|
90
|
+
* Get current settings
|
|
91
|
+
*/
|
|
92
|
+
getSettings(): ProjectsConfig['settings'];
|
|
93
|
+
/**
|
|
94
|
+
* Get the config file path
|
|
95
|
+
*/
|
|
96
|
+
getConfigPath(): string;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=project-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-registry.d.ts","sourceRoot":"","sources":["../../src/services/project-registry.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAe5F;;;;;;;GAOG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,MAAM,CAAgB;IAE9B;;;OAGG;gBACS,UAAU,CAAC,EAAE,MAAM;IAK/B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAM5B;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IA+CjD;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IA0BjD;;;;OAIG;IACH,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;IAsB9C;;;;OAIG;IACH,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,WAAW;IA+BjD;;;;OAIG;IACH,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAe7C;;OAEG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAIjD;;OAEG;IACH,cAAc,IAAI,WAAW,EAAE;IAI/B;;OAEG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAOzC;;;OAGG;IACH,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAgBpC;;OAEG;IACH,iBAAiB,IAAI,WAAW,EAAE;IAMlC;;;;;OAKG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,UAAU,CAAC,CAAC,GAAG,OAAO;IAiBnG;;OAEG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAU1C;;OAEG;IACH,mBAAmB,IAAI,WAAW,EAAE;IAIpC;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,GAAG,IAAI;IAOnE;;OAEG;IACH,WAAW,IAAI,cAAc,CAAC,UAAU,CAAC;IAIzC;;OAEG;IACH,aAAa,IAAI,MAAM;CAGxB"}
|