@sudocode-ai/local-server 0.1.7 → 0.1.9
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 +198 -0
- package/dist/execution/worktree/git-sync-cli.d.ts.map +1 -0
- package/dist/execution/worktree/git-sync-cli.js +401 -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 +124 -229
- 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-DV9Tbujb.css +1 -0
- package/dist/public/assets/index-DcDX9-Ad.js +740 -0
- package/dist/public/assets/index-DcDX9-Ad.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 +792 -37
- 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 +203 -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/routes/version.d.ts +3 -0
- package/dist/routes/version.d.ts.map +1 -0
- package/dist/routes/version.js +25 -0
- package/dist/routes/version.js.map +1 -0
- 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 +110 -0
- package/dist/services/execution-changes-service.d.ts.map +1 -0
- package/dist/services/execution-changes-service.js +700 -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 +82 -59
- package/dist/services/execution-service.d.ts.map +1 -1
- package/dist/services/execution-service.js +514 -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/version-service.d.ts +14 -0
- package/dist/services/version-service.d.ts.map +1 -0
- package/dist/services/version-service.js +57 -0
- package/dist/services/version-service.js.map +1 -0
- 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 +326 -0
- package/dist/services/worktree-sync-service.d.ts.map +1 -0
- package/dist/services/worktree-sync-service.js +1091 -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,700 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Execution Changes Service
|
|
3
|
+
*
|
|
4
|
+
* Calculates code changes (file list + diff statistics) from execution commits.
|
|
5
|
+
* Supports 3 scenarios:
|
|
6
|
+
* - Committed changes (commit-to-commit diff)
|
|
7
|
+
* - Uncommitted changes (working tree diff)
|
|
8
|
+
* - No changes
|
|
9
|
+
*
|
|
10
|
+
* @module services/execution-changes-service
|
|
11
|
+
*/
|
|
12
|
+
import { execSync } from "child_process";
|
|
13
|
+
import { getExecution } from "./executions.js";
|
|
14
|
+
import { existsSync } from "fs";
|
|
15
|
+
/**
|
|
16
|
+
* Service for calculating code changes from execution commits
|
|
17
|
+
*/
|
|
18
|
+
export class ExecutionChangesService {
|
|
19
|
+
db;
|
|
20
|
+
repoPath;
|
|
21
|
+
constructor(db, repoPath) {
|
|
22
|
+
this.db = db;
|
|
23
|
+
this.repoPath = repoPath;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Get code changes for an execution
|
|
27
|
+
*
|
|
28
|
+
* For execution chains (follow-ups), automatically calculates accumulated changes
|
|
29
|
+
* from the root execution to the current execution.
|
|
30
|
+
*
|
|
31
|
+
* @param executionId - Execution ID
|
|
32
|
+
* @returns ExecutionChangesResult with both captured and current states
|
|
33
|
+
*/
|
|
34
|
+
async getChanges(executionId) {
|
|
35
|
+
// 1. Load execution from database
|
|
36
|
+
const execution = getExecution(this.db, executionId);
|
|
37
|
+
if (!execution) {
|
|
38
|
+
console.log(`[ExecutionChangesService] Execution not found: ${executionId}`);
|
|
39
|
+
return {
|
|
40
|
+
available: false,
|
|
41
|
+
reason: "incomplete_execution",
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
console.log(`[ExecutionChangesService] Execution ${executionId}:`, {
|
|
45
|
+
status: execution.status,
|
|
46
|
+
before_commit: execution.before_commit,
|
|
47
|
+
after_commit: execution.after_commit,
|
|
48
|
+
parent_execution_id: execution.parent_execution_id,
|
|
49
|
+
});
|
|
50
|
+
// 2. Validate status (must have started executing)
|
|
51
|
+
// Allow running, completed, stopped, failed, cancelled - reject pending, preparing, paused
|
|
52
|
+
const validStatuses = ["running", "completed", "stopped", "failed", "cancelled"];
|
|
53
|
+
if (!validStatuses.includes(execution.status)) {
|
|
54
|
+
console.log(`[ExecutionChangesService] Execution not started: ${execution.status}`);
|
|
55
|
+
return {
|
|
56
|
+
available: false,
|
|
57
|
+
reason: "incomplete_execution",
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
// 3. Find root execution (for execution chains)
|
|
61
|
+
const rootExecution = this.getRootExecution(execution);
|
|
62
|
+
const beforeCommit = rootExecution.before_commit || execution.before_commit;
|
|
63
|
+
console.log(`[ExecutionChangesService] Root execution ${rootExecution.id}:`, {
|
|
64
|
+
before_commit: rootExecution.before_commit,
|
|
65
|
+
after_commit: rootExecution.after_commit,
|
|
66
|
+
});
|
|
67
|
+
console.log(`[ExecutionChangesService] Computed beforeCommit: ${beforeCommit}`);
|
|
68
|
+
// 4. Validate before_commit exists (required for calculating any changes)
|
|
69
|
+
if (!beforeCommit) {
|
|
70
|
+
console.log(`[ExecutionChangesService] Missing before_commit - cannot calculate changes`);
|
|
71
|
+
return {
|
|
72
|
+
available: false,
|
|
73
|
+
reason: "missing_commits",
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
// 5. Get branch and worktree information
|
|
77
|
+
const branchName = execution.branch_name;
|
|
78
|
+
const executionMode = execution.mode;
|
|
79
|
+
const worktreeExists = execution.worktree_path
|
|
80
|
+
? existsSync(execution.worktree_path)
|
|
81
|
+
: false;
|
|
82
|
+
// 6. Check if branch exists and get current HEAD
|
|
83
|
+
// Always check the main repo for branch info (branches exist in main repo, not just worktrees)
|
|
84
|
+
let branchExists = false;
|
|
85
|
+
let currentBranchHead = null;
|
|
86
|
+
if (branchName) {
|
|
87
|
+
const branchInfo = this.getBranchInfo(branchName, this.repoPath);
|
|
88
|
+
branchExists = branchInfo.exists;
|
|
89
|
+
currentBranchHead = branchInfo.head;
|
|
90
|
+
}
|
|
91
|
+
// 7. Compute captured state (from root to current execution)
|
|
92
|
+
let captured;
|
|
93
|
+
let uncommittedSnapshot;
|
|
94
|
+
const hasCommittedChanges = beforeCommit &&
|
|
95
|
+
execution.after_commit &&
|
|
96
|
+
execution.after_commit !== beforeCommit;
|
|
97
|
+
if (hasCommittedChanges) {
|
|
98
|
+
// Captured: committed changes (requires beforeCommit from root)
|
|
99
|
+
const capturedResult = await this.getCommittedChanges(beforeCommit, execution.after_commit);
|
|
100
|
+
if (!capturedResult.available) {
|
|
101
|
+
// Preserve specific error reason (commits_not_found, etc.)
|
|
102
|
+
return capturedResult;
|
|
103
|
+
}
|
|
104
|
+
if (capturedResult.changes) {
|
|
105
|
+
captured = {
|
|
106
|
+
files: capturedResult.changes.files,
|
|
107
|
+
summary: capturedResult.changes.summary,
|
|
108
|
+
commitRange: capturedResult.commitRange,
|
|
109
|
+
uncommitted: false,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
// Additionally check for uncommitted changes on top of committed changes
|
|
113
|
+
const uncommittedResult = await this.getUncommittedChanges(execution.worktree_path);
|
|
114
|
+
if (uncommittedResult.available && uncommittedResult.changes && uncommittedResult.changes.files.length > 0) {
|
|
115
|
+
uncommittedSnapshot = {
|
|
116
|
+
files: uncommittedResult.changes.files,
|
|
117
|
+
summary: uncommittedResult.changes.summary,
|
|
118
|
+
commitRange: null,
|
|
119
|
+
uncommitted: true,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
// Captured: uncommitted changes only (or no changes at completion)
|
|
125
|
+
const capturedResult = await this.getUncommittedChanges(execution.worktree_path);
|
|
126
|
+
if (!capturedResult.available) {
|
|
127
|
+
// Preserve specific error reason (worktree_deleted_with_uncommitted_changes, etc.)
|
|
128
|
+
return capturedResult;
|
|
129
|
+
}
|
|
130
|
+
if (capturedResult.changes) {
|
|
131
|
+
captured = {
|
|
132
|
+
files: capturedResult.changes.files,
|
|
133
|
+
summary: capturedResult.changes.summary,
|
|
134
|
+
commitRange: null,
|
|
135
|
+
uncommitted: true,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// 8. Compute current state (if branch exists and differs from captured)
|
|
140
|
+
// Requires beforeCommit to calculate diff
|
|
141
|
+
// Note: Use main repo for git operations (worktree may be deleted)
|
|
142
|
+
let current;
|
|
143
|
+
let additionalCommits = 0;
|
|
144
|
+
if (branchExists && currentBranchHead && beforeCommit) {
|
|
145
|
+
// Check if current HEAD is different from captured after_commit
|
|
146
|
+
const isDifferent = currentBranchHead !== execution.after_commit;
|
|
147
|
+
if (isDifferent && execution.after_commit) {
|
|
148
|
+
// Count commits between captured and current
|
|
149
|
+
// Always use main repo path (worktree may be deleted)
|
|
150
|
+
additionalCommits = this.countCommitsBetween(execution.after_commit, currentBranchHead, this.repoPath);
|
|
151
|
+
// Compute current changes (from root to current HEAD)
|
|
152
|
+
const currentResult = await this.getCommittedChanges(beforeCommit, currentBranchHead);
|
|
153
|
+
if (currentResult.available && currentResult.changes) {
|
|
154
|
+
current = {
|
|
155
|
+
files: currentResult.changes.files,
|
|
156
|
+
summary: currentResult.changes.summary,
|
|
157
|
+
commitRange: {
|
|
158
|
+
before: beforeCommit,
|
|
159
|
+
after: currentBranchHead,
|
|
160
|
+
},
|
|
161
|
+
uncommitted: false,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// 9. Calculate commits ahead of target branch (for merge action visibility)
|
|
167
|
+
let commitsAhead = 0;
|
|
168
|
+
if (branchExists && currentBranchHead && execution.target_branch) {
|
|
169
|
+
commitsAhead = this.countCommitsAhead(execution.target_branch, currentBranchHead, this.repoPath);
|
|
170
|
+
}
|
|
171
|
+
// 10. Return result with both states
|
|
172
|
+
if (!captured) {
|
|
173
|
+
return {
|
|
174
|
+
available: false,
|
|
175
|
+
reason: "git_error",
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
available: true,
|
|
180
|
+
captured,
|
|
181
|
+
uncommittedSnapshot,
|
|
182
|
+
current,
|
|
183
|
+
branchName,
|
|
184
|
+
branchExists,
|
|
185
|
+
worktreeExists,
|
|
186
|
+
executionMode,
|
|
187
|
+
additionalCommits,
|
|
188
|
+
commitsAhead,
|
|
189
|
+
// Legacy compatibility
|
|
190
|
+
changes: captured,
|
|
191
|
+
commitRange: captured.commitRange,
|
|
192
|
+
uncommitted: captured.uncommitted,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Get root execution by traversing parent_execution_id chain
|
|
197
|
+
*
|
|
198
|
+
* For execution chains (follow-ups), this finds the original root execution.
|
|
199
|
+
* This allows us to calculate accumulated changes from the start of the chain.
|
|
200
|
+
*/
|
|
201
|
+
getRootExecution(execution) {
|
|
202
|
+
let current = execution;
|
|
203
|
+
let maxDepth = 100; // Safety limit to prevent infinite loops
|
|
204
|
+
let depth = 0;
|
|
205
|
+
while (current.parent_execution_id && depth < maxDepth) {
|
|
206
|
+
const parent = getExecution(this.db, current.parent_execution_id);
|
|
207
|
+
if (!parent) {
|
|
208
|
+
// Parent not found, return current as root
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
current = parent;
|
|
212
|
+
depth++;
|
|
213
|
+
}
|
|
214
|
+
return current;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Get committed changes (commit-to-commit diff)
|
|
218
|
+
* Scenario A: after_commit exists and differs from before_commit
|
|
219
|
+
*/
|
|
220
|
+
async getCommittedChanges(beforeCommit, afterCommit) {
|
|
221
|
+
try {
|
|
222
|
+
// Verify commits exist in repo
|
|
223
|
+
try {
|
|
224
|
+
execSync(`git cat-file -t ${beforeCommit}`, {
|
|
225
|
+
cwd: this.repoPath,
|
|
226
|
+
encoding: "utf-8",
|
|
227
|
+
stdio: "pipe",
|
|
228
|
+
});
|
|
229
|
+
execSync(`git cat-file -t ${afterCommit}`, {
|
|
230
|
+
cwd: this.repoPath,
|
|
231
|
+
encoding: "utf-8",
|
|
232
|
+
stdio: "pipe",
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
catch (error) {
|
|
236
|
+
return {
|
|
237
|
+
available: false,
|
|
238
|
+
reason: "commits_not_found",
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
// Get diff statistics
|
|
242
|
+
const files = await this.calculateDiff(beforeCommit, afterCommit, this.repoPath);
|
|
243
|
+
return {
|
|
244
|
+
available: true,
|
|
245
|
+
uncommitted: false,
|
|
246
|
+
commitRange: {
|
|
247
|
+
before: beforeCommit,
|
|
248
|
+
after: afterCommit,
|
|
249
|
+
},
|
|
250
|
+
changes: {
|
|
251
|
+
files,
|
|
252
|
+
summary: this.calculateSummary(files),
|
|
253
|
+
commitRange: {
|
|
254
|
+
before: beforeCommit,
|
|
255
|
+
after: afterCommit,
|
|
256
|
+
},
|
|
257
|
+
uncommitted: false,
|
|
258
|
+
},
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
catch (error) {
|
|
262
|
+
console.error("[ExecutionChangesService] Error getting committed changes:", error);
|
|
263
|
+
return {
|
|
264
|
+
available: false,
|
|
265
|
+
reason: "git_error",
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Get uncommitted changes (working tree diff)
|
|
271
|
+
* Scenario B: after_commit is null or equals before_commit
|
|
272
|
+
*/
|
|
273
|
+
async getUncommittedChanges(worktreePath) {
|
|
274
|
+
// Determine the working directory to check
|
|
275
|
+
const workDir = worktreePath || this.repoPath;
|
|
276
|
+
// Check if worktree still exists
|
|
277
|
+
if (worktreePath && !existsSync(worktreePath)) {
|
|
278
|
+
return {
|
|
279
|
+
available: false,
|
|
280
|
+
reason: "worktree_deleted_with_uncommitted_changes",
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
try {
|
|
284
|
+
// Get uncommitted changes relative to HEAD
|
|
285
|
+
const files = await this.calculateDiff(null, null, workDir);
|
|
286
|
+
// If no files changed, return empty result
|
|
287
|
+
if (files.length === 0) {
|
|
288
|
+
return {
|
|
289
|
+
available: true,
|
|
290
|
+
uncommitted: true,
|
|
291
|
+
commitRange: null,
|
|
292
|
+
changes: {
|
|
293
|
+
files: [],
|
|
294
|
+
summary: {
|
|
295
|
+
totalFiles: 0,
|
|
296
|
+
totalAdditions: 0,
|
|
297
|
+
totalDeletions: 0,
|
|
298
|
+
},
|
|
299
|
+
commitRange: null,
|
|
300
|
+
uncommitted: true,
|
|
301
|
+
},
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
return {
|
|
305
|
+
available: true,
|
|
306
|
+
uncommitted: true,
|
|
307
|
+
commitRange: null,
|
|
308
|
+
changes: {
|
|
309
|
+
files,
|
|
310
|
+
summary: this.calculateSummary(files),
|
|
311
|
+
commitRange: null,
|
|
312
|
+
uncommitted: true,
|
|
313
|
+
},
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
catch (error) {
|
|
317
|
+
console.error("[ExecutionChangesService] Error getting uncommitted changes:", error);
|
|
318
|
+
return {
|
|
319
|
+
available: false,
|
|
320
|
+
reason: "git_error",
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Calculate diff statistics using git commands
|
|
326
|
+
*
|
|
327
|
+
* @param beforeCommit - Before commit SHA (null for uncommitted)
|
|
328
|
+
* @param afterCommit - After commit SHA (null for uncommitted)
|
|
329
|
+
* @param workDir - Working directory for git commands
|
|
330
|
+
* @returns Array of file change statistics
|
|
331
|
+
*/
|
|
332
|
+
async calculateDiff(beforeCommit, afterCommit, workDir) {
|
|
333
|
+
// Build git diff command based on scenario
|
|
334
|
+
let numstatCmd;
|
|
335
|
+
let nameStatusCmd;
|
|
336
|
+
if (beforeCommit && afterCommit) {
|
|
337
|
+
// Committed changes: commit-to-commit diff
|
|
338
|
+
numstatCmd = `git diff --numstat --find-renames ${beforeCommit}..${afterCommit}`;
|
|
339
|
+
nameStatusCmd = `git diff --name-status --find-renames ${beforeCommit}..${afterCommit}`;
|
|
340
|
+
}
|
|
341
|
+
else {
|
|
342
|
+
// Uncommitted changes: working tree diff
|
|
343
|
+
numstatCmd = `git diff --numstat --find-renames HEAD`;
|
|
344
|
+
nameStatusCmd = `git diff --name-status --find-renames HEAD`;
|
|
345
|
+
}
|
|
346
|
+
// Execute git diff --numstat
|
|
347
|
+
const numstatOutput = execSync(numstatCmd, {
|
|
348
|
+
cwd: workDir,
|
|
349
|
+
encoding: "utf-8",
|
|
350
|
+
stdio: "pipe",
|
|
351
|
+
}).trim();
|
|
352
|
+
// Execute git diff --name-status
|
|
353
|
+
const nameStatusOutput = execSync(nameStatusCmd, {
|
|
354
|
+
cwd: workDir,
|
|
355
|
+
encoding: "utf-8",
|
|
356
|
+
stdio: "pipe",
|
|
357
|
+
}).trim();
|
|
358
|
+
// Parse outputs
|
|
359
|
+
const numstatData = this.parseNumstat(numstatOutput);
|
|
360
|
+
const statusData = this.parseNameStatus(nameStatusOutput);
|
|
361
|
+
// Combine numstat and status data
|
|
362
|
+
let files = this.combineFileData(numstatData, statusData);
|
|
363
|
+
// For uncommitted changes, also include untracked files
|
|
364
|
+
if (!beforeCommit && !afterCommit) {
|
|
365
|
+
const untrackedFiles = this.getUntrackedFiles(workDir);
|
|
366
|
+
files = files.concat(untrackedFiles);
|
|
367
|
+
}
|
|
368
|
+
return files;
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Parse git diff --numstat output
|
|
372
|
+
*
|
|
373
|
+
* Format: "additions\tdeletions\tfilepath"
|
|
374
|
+
* Binary files: "-\t-\tfilepath"
|
|
375
|
+
*/
|
|
376
|
+
parseNumstat(output) {
|
|
377
|
+
const data = new Map();
|
|
378
|
+
if (!output) {
|
|
379
|
+
return data;
|
|
380
|
+
}
|
|
381
|
+
const lines = output.split("\n");
|
|
382
|
+
for (const line of lines) {
|
|
383
|
+
if (!line.trim())
|
|
384
|
+
continue;
|
|
385
|
+
const parts = line.split("\t");
|
|
386
|
+
if (parts.length < 3)
|
|
387
|
+
continue;
|
|
388
|
+
const additions = parts[0] === "-" ? 0 : parseInt(parts[0], 10);
|
|
389
|
+
const deletions = parts[1] === "-" ? 0 : parseInt(parts[1], 10);
|
|
390
|
+
const filePath = parts.slice(2).join("\t"); // Handle filenames with tabs
|
|
391
|
+
data.set(filePath, { additions, deletions });
|
|
392
|
+
}
|
|
393
|
+
return data;
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Parse git diff --name-status output
|
|
397
|
+
*
|
|
398
|
+
* Format: "STATUS\tfilepath"
|
|
399
|
+
* Renamed files: "R100\toldpath\tnewpath"
|
|
400
|
+
*/
|
|
401
|
+
parseNameStatus(output) {
|
|
402
|
+
const data = new Map();
|
|
403
|
+
if (!output) {
|
|
404
|
+
return data;
|
|
405
|
+
}
|
|
406
|
+
const lines = output.split("\n");
|
|
407
|
+
for (const line of lines) {
|
|
408
|
+
if (!line.trim())
|
|
409
|
+
continue;
|
|
410
|
+
const parts = line.split("\t");
|
|
411
|
+
if (parts.length < 2)
|
|
412
|
+
continue;
|
|
413
|
+
const statusCode = parts[0];
|
|
414
|
+
let status;
|
|
415
|
+
if (statusCode.startsWith("A")) {
|
|
416
|
+
status = "A";
|
|
417
|
+
}
|
|
418
|
+
else if (statusCode.startsWith("M")) {
|
|
419
|
+
status = "M";
|
|
420
|
+
}
|
|
421
|
+
else if (statusCode.startsWith("D")) {
|
|
422
|
+
status = "D";
|
|
423
|
+
}
|
|
424
|
+
else if (statusCode.startsWith("R")) {
|
|
425
|
+
status = "R";
|
|
426
|
+
}
|
|
427
|
+
else {
|
|
428
|
+
// Default to modified for unknown status
|
|
429
|
+
status = "M";
|
|
430
|
+
}
|
|
431
|
+
// For renamed files, use the new path (last part)
|
|
432
|
+
const filePath = parts[parts.length - 1];
|
|
433
|
+
data.set(filePath, status);
|
|
434
|
+
}
|
|
435
|
+
return data;
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Combine numstat and name-status data into FileChangeStat array
|
|
439
|
+
*/
|
|
440
|
+
combineFileData(numstatData, statusData) {
|
|
441
|
+
const files = [];
|
|
442
|
+
// Iterate through all files from numstat
|
|
443
|
+
for (const [path, { additions, deletions }] of numstatData) {
|
|
444
|
+
const status = statusData.get(path) || "M"; // Default to modified
|
|
445
|
+
files.push({
|
|
446
|
+
path,
|
|
447
|
+
additions,
|
|
448
|
+
deletions,
|
|
449
|
+
status,
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
return files;
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* Calculate summary statistics from file changes
|
|
456
|
+
*/
|
|
457
|
+
calculateSummary(files) {
|
|
458
|
+
return {
|
|
459
|
+
totalFiles: files.length,
|
|
460
|
+
totalAdditions: files.reduce((sum, file) => sum + file.additions, 0),
|
|
461
|
+
totalDeletions: files.reduce((sum, file) => sum + file.deletions, 0),
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Get branch information (existence and current HEAD)
|
|
466
|
+
*/
|
|
467
|
+
getBranchInfo(branchName, workDir) {
|
|
468
|
+
try {
|
|
469
|
+
// Try to get the commit SHA for the branch
|
|
470
|
+
const head = execSync(`git rev-parse ${branchName}`, {
|
|
471
|
+
cwd: workDir,
|
|
472
|
+
encoding: "utf-8",
|
|
473
|
+
stdio: "pipe",
|
|
474
|
+
}).trim();
|
|
475
|
+
return {
|
|
476
|
+
exists: true,
|
|
477
|
+
head,
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
catch (error) {
|
|
481
|
+
// Branch doesn't exist
|
|
482
|
+
return {
|
|
483
|
+
exists: false,
|
|
484
|
+
head: null,
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* Count commits between two commit SHAs
|
|
490
|
+
*/
|
|
491
|
+
countCommitsBetween(fromCommit, toCommit, workDir) {
|
|
492
|
+
try {
|
|
493
|
+
const output = execSync(`git rev-list --count ${fromCommit}..${toCommit}`, {
|
|
494
|
+
cwd: workDir,
|
|
495
|
+
encoding: "utf-8",
|
|
496
|
+
stdio: "pipe",
|
|
497
|
+
}).trim();
|
|
498
|
+
return parseInt(output, 10) || 0;
|
|
499
|
+
}
|
|
500
|
+
catch (error) {
|
|
501
|
+
console.error("[ExecutionChangesService] Error counting commits:", error);
|
|
502
|
+
return 0;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Count commits the branch is ahead of target branch
|
|
507
|
+
* Uses merge-base to find the common ancestor
|
|
508
|
+
*/
|
|
509
|
+
countCommitsAhead(targetBranch, branchHead, workDir) {
|
|
510
|
+
try {
|
|
511
|
+
// Find the merge base between target branch and the current branch
|
|
512
|
+
const mergeBase = execSync(`git merge-base ${targetBranch} ${branchHead}`, {
|
|
513
|
+
cwd: workDir,
|
|
514
|
+
encoding: "utf-8",
|
|
515
|
+
stdio: "pipe",
|
|
516
|
+
}).trim();
|
|
517
|
+
// Count commits from merge base to branch head
|
|
518
|
+
const output = execSync(`git rev-list --count ${mergeBase}..${branchHead}`, {
|
|
519
|
+
cwd: workDir,
|
|
520
|
+
encoding: "utf-8",
|
|
521
|
+
stdio: "pipe",
|
|
522
|
+
}).trim();
|
|
523
|
+
return parseInt(output, 10) || 0;
|
|
524
|
+
}
|
|
525
|
+
catch (error) {
|
|
526
|
+
console.error("[ExecutionChangesService] Error counting commits ahead:", error);
|
|
527
|
+
return 0;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* Get untracked files (respecting .gitignore)
|
|
532
|
+
*/
|
|
533
|
+
getUntrackedFiles(workDir) {
|
|
534
|
+
try {
|
|
535
|
+
// Get untracked files, excluding .gitignore patterns
|
|
536
|
+
const output = execSync("git ls-files --others --exclude-standard", {
|
|
537
|
+
cwd: workDir,
|
|
538
|
+
encoding: "utf-8",
|
|
539
|
+
stdio: "pipe",
|
|
540
|
+
}).trim();
|
|
541
|
+
if (!output) {
|
|
542
|
+
return [];
|
|
543
|
+
}
|
|
544
|
+
const files = [];
|
|
545
|
+
const lines = output.split("\n");
|
|
546
|
+
for (const filePath of lines) {
|
|
547
|
+
if (!filePath.trim())
|
|
548
|
+
continue;
|
|
549
|
+
// Count lines in the file for additions
|
|
550
|
+
const fullPath = `${workDir}/${filePath}`;
|
|
551
|
+
let additions = 0;
|
|
552
|
+
try {
|
|
553
|
+
if (existsSync(fullPath)) {
|
|
554
|
+
const content = require("fs").readFileSync(fullPath, "utf-8");
|
|
555
|
+
additions = content.split("\n").length;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
catch (error) {
|
|
559
|
+
// If we can't read the file (binary, etc.), just set additions to 1
|
|
560
|
+
additions = 1;
|
|
561
|
+
}
|
|
562
|
+
files.push({
|
|
563
|
+
path: filePath,
|
|
564
|
+
additions,
|
|
565
|
+
deletions: 0,
|
|
566
|
+
status: "A", // Untracked files are "Added"
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
return files;
|
|
570
|
+
}
|
|
571
|
+
catch (error) {
|
|
572
|
+
console.error("[ExecutionChangesService] Error getting untracked files:", error);
|
|
573
|
+
return [];
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
/**
|
|
577
|
+
* Get diff content for a specific file
|
|
578
|
+
*
|
|
579
|
+
* @param executionId - Execution ID
|
|
580
|
+
* @param filePath - Path to the file
|
|
581
|
+
* @returns Object with oldContent and newContent
|
|
582
|
+
*/
|
|
583
|
+
async getFileDiff(executionId, filePath) {
|
|
584
|
+
try {
|
|
585
|
+
// 1. Load execution from database
|
|
586
|
+
const execution = getExecution(this.db, executionId);
|
|
587
|
+
if (!execution) {
|
|
588
|
+
return { success: false, error: "Execution not found" };
|
|
589
|
+
}
|
|
590
|
+
// 2. Find root execution for before_commit
|
|
591
|
+
const rootExecution = this.getRootExecution(execution);
|
|
592
|
+
const beforeCommit = rootExecution.before_commit || execution.before_commit;
|
|
593
|
+
const afterCommit = execution.after_commit;
|
|
594
|
+
if (!beforeCommit) {
|
|
595
|
+
return { success: false, error: "Missing before_commit" };
|
|
596
|
+
}
|
|
597
|
+
let oldContent = "";
|
|
598
|
+
let newContent = "";
|
|
599
|
+
// Normalize file path - remove leading './' if present
|
|
600
|
+
const normalizedPath = filePath.startsWith('./') ? filePath.slice(2) : filePath;
|
|
601
|
+
console.log(`[ExecutionChangesService] Getting diff for ${filePath}:`, {
|
|
602
|
+
beforeCommit,
|
|
603
|
+
afterCommit,
|
|
604
|
+
worktreePath: execution.worktree_path,
|
|
605
|
+
normalizedPath,
|
|
606
|
+
});
|
|
607
|
+
// 3. Get old content (from before_commit)
|
|
608
|
+
try {
|
|
609
|
+
const cmd = `git show ${beforeCommit}:${normalizedPath}`;
|
|
610
|
+
console.log(`[ExecutionChangesService] Running: ${cmd}`);
|
|
611
|
+
oldContent = execSync(cmd, {
|
|
612
|
+
cwd: this.repoPath,
|
|
613
|
+
encoding: "utf-8",
|
|
614
|
+
stdio: "pipe",
|
|
615
|
+
maxBuffer: 50 * 1024 * 1024, // 50MB buffer for large files
|
|
616
|
+
});
|
|
617
|
+
console.log(`[ExecutionChangesService] Old content length: ${oldContent.length}`);
|
|
618
|
+
}
|
|
619
|
+
catch (error) {
|
|
620
|
+
// File might not exist in before_commit (new file)
|
|
621
|
+
console.log(`[ExecutionChangesService] Failed to get old content:`, error instanceof Error ? error.message : error);
|
|
622
|
+
oldContent = "";
|
|
623
|
+
}
|
|
624
|
+
// 4. Get new content (depends on whether we have committed or uncommitted changes)
|
|
625
|
+
if (afterCommit && afterCommit !== beforeCommit) {
|
|
626
|
+
// Committed changes - get from after_commit
|
|
627
|
+
console.log(`[ExecutionChangesService] Fetching new content from after_commit: ${afterCommit}`);
|
|
628
|
+
try {
|
|
629
|
+
const cmd = `git show ${afterCommit}:${normalizedPath}`;
|
|
630
|
+
console.log(`[ExecutionChangesService] Running: ${cmd}`);
|
|
631
|
+
newContent = execSync(cmd, {
|
|
632
|
+
cwd: this.repoPath,
|
|
633
|
+
encoding: "utf-8",
|
|
634
|
+
stdio: "pipe",
|
|
635
|
+
maxBuffer: 50 * 1024 * 1024, // 50MB buffer for large files
|
|
636
|
+
});
|
|
637
|
+
console.log(`[ExecutionChangesService] New content length: ${newContent.length}`);
|
|
638
|
+
}
|
|
639
|
+
catch (error) {
|
|
640
|
+
// File might have been deleted
|
|
641
|
+
console.log(`[ExecutionChangesService] Failed to get new content:`, error instanceof Error ? error.message : error);
|
|
642
|
+
newContent = "";
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
else if (execution.worktree_path && existsSync(execution.worktree_path)) {
|
|
646
|
+
// Uncommitted changes - get from working tree
|
|
647
|
+
console.log(`[ExecutionChangesService] Fetching new content from worktree: ${execution.worktree_path}`);
|
|
648
|
+
try {
|
|
649
|
+
const { readFileSync } = await import("fs");
|
|
650
|
+
const { join } = await import("path");
|
|
651
|
+
const fullPath = join(execution.worktree_path, normalizedPath);
|
|
652
|
+
console.log(`[ExecutionChangesService] Checking file: ${fullPath}`);
|
|
653
|
+
if (existsSync(fullPath)) {
|
|
654
|
+
newContent = readFileSync(fullPath, "utf-8");
|
|
655
|
+
console.log(`[ExecutionChangesService] New content length: ${newContent.length}`);
|
|
656
|
+
}
|
|
657
|
+
else {
|
|
658
|
+
// File might have been deleted
|
|
659
|
+
console.log(`[ExecutionChangesService] File deleted in worktree`);
|
|
660
|
+
newContent = "";
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
catch (error) {
|
|
664
|
+
return { success: false, error: `Failed to read file: ${error}` };
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
else {
|
|
668
|
+
// No after_commit and no worktree - use HEAD
|
|
669
|
+
console.log(`[ExecutionChangesService] Fetching new content from HEAD`);
|
|
670
|
+
try {
|
|
671
|
+
newContent = execSync(`git show HEAD:${normalizedPath}`, {
|
|
672
|
+
cwd: this.repoPath,
|
|
673
|
+
encoding: "utf-8",
|
|
674
|
+
stdio: "pipe",
|
|
675
|
+
maxBuffer: 50 * 1024 * 1024, // 50MB buffer for large files
|
|
676
|
+
});
|
|
677
|
+
console.log(`[ExecutionChangesService] New content length: ${newContent.length}`);
|
|
678
|
+
}
|
|
679
|
+
catch (error) {
|
|
680
|
+
console.log(`[ExecutionChangesService] File deleted at HEAD`);
|
|
681
|
+
newContent = "";
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
console.log(`[ExecutionChangesService] Returning diff - oldContent: ${oldContent.length} chars, newContent: ${newContent.length} chars`);
|
|
685
|
+
return {
|
|
686
|
+
success: true,
|
|
687
|
+
oldContent,
|
|
688
|
+
newContent,
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
catch (error) {
|
|
692
|
+
console.error("[ExecutionChangesService] Error getting file diff:", error);
|
|
693
|
+
return {
|
|
694
|
+
success: false,
|
|
695
|
+
error: error instanceof Error ? error.message : String(error),
|
|
696
|
+
};
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
//# sourceMappingURL=execution-changes-service.js.map
|