mcp-agent-foundry 1.0.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/LICENSE +21 -0
- package/README.md +477 -0
- package/dist/cli/install-skills.d.ts +11 -0
- package/dist/cli/install-skills.d.ts.map +1 -0
- package/dist/cli/install-skills.js +143 -0
- package/dist/cli/install-skills.js.map +1 -0
- package/dist/cli/recovery-commands.d.ts +41 -0
- package/dist/cli/recovery-commands.d.ts.map +1 -0
- package/dist/cli/recovery-commands.js +241 -0
- package/dist/cli/recovery-commands.js.map +1 -0
- package/dist/cli/setup-wizard.d.ts +25 -0
- package/dist/cli/setup-wizard.d.ts.map +1 -0
- package/dist/cli/setup-wizard.js +1417 -0
- package/dist/cli/setup-wizard.js.map +1 -0
- package/dist/cli/test-connection.d.ts +45 -0
- package/dist/cli/test-connection.d.ts.map +1 -0
- package/dist/cli/test-connection.js +317 -0
- package/dist/cli/test-connection.js.map +1 -0
- package/dist/cli.d.ts +75 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +704 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/defaults.d.ts +57 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +99 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/index.d.ts +14 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +22 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/manager.d.ts +184 -0
- package/dist/config/manager.d.ts.map +1 -0
- package/dist/config/manager.js +347 -0
- package/dist/config/manager.js.map +1 -0
- package/dist/config/merger.d.ts +76 -0
- package/dist/config/merger.d.ts.map +1 -0
- package/dist/config/merger.js +189 -0
- package/dist/config/merger.js.map +1 -0
- package/dist/config/schema.d.ts +20 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +20 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/config/validator.d.ts +254 -0
- package/dist/config/validator.d.ts.map +1 -0
- package/dist/config/validator.js +363 -0
- package/dist/config/validator.js.map +1 -0
- package/dist/config/worktree-defaults.d.ts +23 -0
- package/dist/config/worktree-defaults.d.ts.map +1 -0
- package/dist/config/worktree-defaults.js +78 -0
- package/dist/config/worktree-defaults.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/tools/compare-agents.d.ts +25 -0
- package/dist/mcp/tools/compare-agents.d.ts.map +1 -0
- package/dist/mcp/tools/compare-agents.js +177 -0
- package/dist/mcp/tools/compare-agents.js.map +1 -0
- package/dist/mcp/tools/critique-plan.d.ts +26 -0
- package/dist/mcp/tools/critique-plan.d.ts.map +1 -0
- package/dist/mcp/tools/critique-plan.js +162 -0
- package/dist/mcp/tools/critique-plan.js.map +1 -0
- package/dist/mcp/tools/design-feedback.d.ts +26 -0
- package/dist/mcp/tools/design-feedback.d.ts.map +1 -0
- package/dist/mcp/tools/design-feedback.js +216 -0
- package/dist/mcp/tools/design-feedback.js.map +1 -0
- package/dist/mcp/tools/index.d.ts +50 -0
- package/dist/mcp/tools/index.d.ts.map +1 -0
- package/dist/mcp/tools/index.js +191 -0
- package/dist/mcp/tools/index.js.map +1 -0
- package/dist/mcp/tools/invoke-agent.d.ts +25 -0
- package/dist/mcp/tools/invoke-agent.d.ts.map +1 -0
- package/dist/mcp/tools/invoke-agent.js +141 -0
- package/dist/mcp/tools/invoke-agent.js.map +1 -0
- package/dist/mcp/tools/review-code.d.ts +25 -0
- package/dist/mcp/tools/review-code.d.ts.map +1 -0
- package/dist/mcp/tools/review-code.js +170 -0
- package/dist/mcp/tools/review-code.js.map +1 -0
- package/dist/mcp/tools/tasks/claim-next-task.d.ts +22 -0
- package/dist/mcp/tools/tasks/claim-next-task.d.ts.map +1 -0
- package/dist/mcp/tools/tasks/claim-next-task.js +203 -0
- package/dist/mcp/tools/tasks/claim-next-task.js.map +1 -0
- package/dist/mcp/tools/tasks/create-routed-task.d.ts +17 -0
- package/dist/mcp/tools/tasks/create-routed-task.d.ts.map +1 -0
- package/dist/mcp/tools/tasks/create-routed-task.js +178 -0
- package/dist/mcp/tools/tasks/create-routed-task.js.map +1 -0
- package/dist/mcp/tools/tasks/execute-pipeline.d.ts +22 -0
- package/dist/mcp/tools/tasks/execute-pipeline.d.ts.map +1 -0
- package/dist/mcp/tools/tasks/execute-pipeline.js +401 -0
- package/dist/mcp/tools/tasks/execute-pipeline.js.map +1 -0
- package/dist/mcp/tools/tasks/execute-task.d.ts +32 -0
- package/dist/mcp/tools/tasks/execute-task.d.ts.map +1 -0
- package/dist/mcp/tools/tasks/execute-task.js +284 -0
- package/dist/mcp/tools/tasks/execute-task.js.map +1 -0
- package/dist/mcp/tools/tasks/get-pipeline-status.d.ts +26 -0
- package/dist/mcp/tools/tasks/get-pipeline-status.d.ts.map +1 -0
- package/dist/mcp/tools/tasks/get-pipeline-status.js +460 -0
- package/dist/mcp/tools/tasks/get-pipeline-status.js.map +1 -0
- package/dist/mcp/tools/tasks/index.d.ts +36 -0
- package/dist/mcp/tools/tasks/index.d.ts.map +1 -0
- package/dist/mcp/tools/tasks/index.js +66 -0
- package/dist/mcp/tools/tasks/index.js.map +1 -0
- package/dist/mcp/tools/worktree/cleanup-worktrees.d.ts +17 -0
- package/dist/mcp/tools/worktree/cleanup-worktrees.d.ts.map +1 -0
- package/dist/mcp/tools/worktree/cleanup-worktrees.js +147 -0
- package/dist/mcp/tools/worktree/cleanup-worktrees.js.map +1 -0
- package/dist/mcp/tools/worktree/get-worktree-status.d.ts +17 -0
- package/dist/mcp/tools/worktree/get-worktree-status.d.ts.map +1 -0
- package/dist/mcp/tools/worktree/get-worktree-status.js +123 -0
- package/dist/mcp/tools/worktree/get-worktree-status.js.map +1 -0
- package/dist/mcp/tools/worktree/index.d.ts +41 -0
- package/dist/mcp/tools/worktree/index.d.ts.map +1 -0
- package/dist/mcp/tools/worktree/index.js +69 -0
- package/dist/mcp/tools/worktree/index.js.map +1 -0
- package/dist/mcp/tools/worktree/list-worktrees.d.ts +17 -0
- package/dist/mcp/tools/worktree/list-worktrees.d.ts.map +1 -0
- package/dist/mcp/tools/worktree/list-worktrees.js +136 -0
- package/dist/mcp/tools/worktree/list-worktrees.js.map +1 -0
- package/dist/mcp/tools/worktree/resolve-conflicts.d.ts +19 -0
- package/dist/mcp/tools/worktree/resolve-conflicts.d.ts.map +1 -0
- package/dist/mcp/tools/worktree/resolve-conflicts.js +228 -0
- package/dist/mcp/tools/worktree/resolve-conflicts.js.map +1 -0
- package/dist/mcp/transport/stdio.d.ts +13 -0
- package/dist/mcp/transport/stdio.d.ts.map +1 -0
- package/dist/mcp/transport/stdio.js +15 -0
- package/dist/mcp/transport/stdio.js.map +1 -0
- package/dist/observability/logger.d.ts +137 -0
- package/dist/observability/logger.d.ts.map +1 -0
- package/dist/observability/logger.js +235 -0
- package/dist/observability/logger.js.map +1 -0
- package/dist/observability/metrics.d.ts +250 -0
- package/dist/observability/metrics.d.ts.map +1 -0
- package/dist/observability/metrics.js +364 -0
- package/dist/observability/metrics.js.map +1 -0
- package/dist/persistence/index.d.ts +9 -0
- package/dist/persistence/index.d.ts.map +1 -0
- package/dist/persistence/index.js +9 -0
- package/dist/persistence/index.js.map +1 -0
- package/dist/persistence/state-schema.d.ts +116 -0
- package/dist/persistence/state-schema.d.ts.map +1 -0
- package/dist/persistence/state-schema.js +28 -0
- package/dist/persistence/state-schema.js.map +1 -0
- package/dist/persistence/state-store.d.ts +111 -0
- package/dist/persistence/state-store.d.ts.map +1 -0
- package/dist/persistence/state-store.js +291 -0
- package/dist/persistence/state-store.js.map +1 -0
- package/dist/providers/anthropic.d.ts +164 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +500 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/base.d.ts +151 -0
- package/dist/providers/base.d.ts.map +1 -0
- package/dist/providers/base.js +227 -0
- package/dist/providers/base.js.map +1 -0
- package/dist/providers/gemini.d.ts +85 -0
- package/dist/providers/gemini.d.ts.map +1 -0
- package/dist/providers/gemini.js +414 -0
- package/dist/providers/gemini.js.map +1 -0
- package/dist/providers/kimi.d.ts +19 -0
- package/dist/providers/kimi.d.ts.map +1 -0
- package/dist/providers/kimi.js +20 -0
- package/dist/providers/kimi.js.map +1 -0
- package/dist/providers/manager.d.ts +160 -0
- package/dist/providers/manager.d.ts.map +1 -0
- package/dist/providers/manager.js +264 -0
- package/dist/providers/manager.js.map +1 -0
- package/dist/providers/ollama.d.ts +83 -0
- package/dist/providers/ollama.d.ts.map +1 -0
- package/dist/providers/ollama.js +453 -0
- package/dist/providers/ollama.js.map +1 -0
- package/dist/providers/openai.d.ts +96 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +457 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/zai.d.ts +19 -0
- package/dist/providers/zai.d.ts.map +1 -0
- package/dist/providers/zai.js +20 -0
- package/dist/providers/zai.js.map +1 -0
- package/dist/router/context-manager.d.ts +2 -0
- package/dist/router/context-manager.d.ts.map +1 -0
- package/dist/router/context-manager.js +3 -0
- package/dist/router/context-manager.js.map +1 -0
- package/dist/router/engine.d.ts +169 -0
- package/dist/router/engine.d.ts.map +1 -0
- package/dist/router/engine.js +435 -0
- package/dist/router/engine.js.map +1 -0
- package/dist/router/pattern-executor.d.ts +317 -0
- package/dist/router/pattern-executor.d.ts.map +1 -0
- package/dist/router/pattern-executor.js +571 -0
- package/dist/router/pattern-executor.js.map +1 -0
- package/dist/router/role-resolver.d.ts +59 -0
- package/dist/router/role-resolver.d.ts.map +1 -0
- package/dist/router/role-resolver.js +95 -0
- package/dist/router/role-resolver.js.map +1 -0
- package/dist/server.d.ts +32 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +223 -0
- package/dist/server.js.map +1 -0
- package/dist/startup.d.ts +78 -0
- package/dist/startup.d.ts.map +1 -0
- package/dist/startup.js +107 -0
- package/dist/startup.js.map +1 -0
- package/dist/tasks/coordinator.d.ts +141 -0
- package/dist/tasks/coordinator.d.ts.map +1 -0
- package/dist/tasks/coordinator.js +331 -0
- package/dist/tasks/coordinator.js.map +1 -0
- package/dist/tasks/index.d.ts +13 -0
- package/dist/tasks/index.d.ts.map +1 -0
- package/dist/tasks/index.js +13 -0
- package/dist/tasks/index.js.map +1 -0
- package/dist/tasks/persistent-state-coordinator.d.ts +89 -0
- package/dist/tasks/persistent-state-coordinator.d.ts.map +1 -0
- package/dist/tasks/persistent-state-coordinator.js +371 -0
- package/dist/tasks/persistent-state-coordinator.js.map +1 -0
- package/dist/tasks/pipeline-manager.d.ts +103 -0
- package/dist/tasks/pipeline-manager.d.ts.map +1 -0
- package/dist/tasks/pipeline-manager.js +358 -0
- package/dist/tasks/pipeline-manager.js.map +1 -0
- package/dist/tasks/state-coordinator.d.ts +79 -0
- package/dist/tasks/state-coordinator.d.ts.map +1 -0
- package/dist/tasks/state-coordinator.js +200 -0
- package/dist/tasks/state-coordinator.js.map +1 -0
- package/dist/tasks/worker-mode.d.ts +65 -0
- package/dist/tasks/worker-mode.d.ts.map +1 -0
- package/dist/tasks/worker-mode.js +208 -0
- package/dist/tasks/worker-mode.js.map +1 -0
- package/dist/translation/errors.d.ts +203 -0
- package/dist/translation/errors.d.ts.map +1 -0
- package/dist/translation/errors.js +477 -0
- package/dist/translation/errors.js.map +1 -0
- package/dist/translation/index.d.ts +12 -0
- package/dist/translation/index.d.ts.map +1 -0
- package/dist/translation/index.js +32 -0
- package/dist/translation/index.js.map +1 -0
- package/dist/translation/messages.d.ts +295 -0
- package/dist/translation/messages.d.ts.map +1 -0
- package/dist/translation/messages.js +557 -0
- package/dist/translation/messages.js.map +1 -0
- package/dist/translation/streaming.d.ts +226 -0
- package/dist/translation/streaming.d.ts.map +1 -0
- package/dist/translation/streaming.js +520 -0
- package/dist/translation/streaming.js.map +1 -0
- package/dist/translation/tools.d.ts +209 -0
- package/dist/translation/tools.d.ts.map +1 -0
- package/dist/translation/tools.js +331 -0
- package/dist/translation/tools.js.map +1 -0
- package/dist/types.d.ts +747 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +86 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/circuit-breaker.d.ts +175 -0
- package/dist/utils/circuit-breaker.d.ts.map +1 -0
- package/dist/utils/circuit-breaker.js +315 -0
- package/dist/utils/circuit-breaker.js.map +1 -0
- package/dist/utils/env.d.ts +2 -0
- package/dist/utils/env.d.ts.map +1 -0
- package/dist/utils/env.js +3 -0
- package/dist/utils/env.js.map +1 -0
- package/dist/utils/git.d.ts +58 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +197 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/index.d.ts +9 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +9 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/merge-ordering.d.ts +45 -0
- package/dist/utils/merge-ordering.d.ts.map +1 -0
- package/dist/utils/merge-ordering.js +128 -0
- package/dist/utils/merge-ordering.js.map +1 -0
- package/dist/utils/retry.d.ts +106 -0
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/utils/retry.js +188 -0
- package/dist/utils/retry.js.map +1 -0
- package/dist/worktrees/branch-manager.d.ts +55 -0
- package/dist/worktrees/branch-manager.d.ts.map +1 -0
- package/dist/worktrees/branch-manager.js +129 -0
- package/dist/worktrees/branch-manager.js.map +1 -0
- package/dist/worktrees/conflict-handler.d.ts +72 -0
- package/dist/worktrees/conflict-handler.d.ts.map +1 -0
- package/dist/worktrees/conflict-handler.js +287 -0
- package/dist/worktrees/conflict-handler.js.map +1 -0
- package/dist/worktrees/conflict-parser.d.ts +28 -0
- package/dist/worktrees/conflict-parser.d.ts.map +1 -0
- package/dist/worktrees/conflict-parser.js +140 -0
- package/dist/worktrees/conflict-parser.js.map +1 -0
- package/dist/worktrees/index.d.ts +20 -0
- package/dist/worktrees/index.d.ts.map +1 -0
- package/dist/worktrees/index.js +20 -0
- package/dist/worktrees/index.js.map +1 -0
- package/dist/worktrees/instructions.d.ts +20 -0
- package/dist/worktrees/instructions.d.ts.map +1 -0
- package/dist/worktrees/instructions.js +84 -0
- package/dist/worktrees/instructions.js.map +1 -0
- package/dist/worktrees/manager.d.ts +76 -0
- package/dist/worktrees/manager.d.ts.map +1 -0
- package/dist/worktrees/manager.js +277 -0
- package/dist/worktrees/manager.js.map +1 -0
- package/dist/worktrees/pipeline-merge-orchestrator.d.ts +55 -0
- package/dist/worktrees/pipeline-merge-orchestrator.d.ts.map +1 -0
- package/dist/worktrees/pipeline-merge-orchestrator.js +221 -0
- package/dist/worktrees/pipeline-merge-orchestrator.js.map +1 -0
- package/dist/worktrees/pool.d.ts +95 -0
- package/dist/worktrees/pool.d.ts.map +1 -0
- package/dist/worktrees/pool.js +271 -0
- package/dist/worktrees/pool.js.map +1 -0
- package/dist/worktrees/recovery.d.ts +94 -0
- package/dist/worktrees/recovery.d.ts.map +1 -0
- package/dist/worktrees/recovery.js +371 -0
- package/dist/worktrees/recovery.js.map +1 -0
- package/dist/worktrees/resource-manager.d.ts +74 -0
- package/dist/worktrees/resource-manager.d.ts.map +1 -0
- package/dist/worktrees/resource-manager.js +228 -0
- package/dist/worktrees/resource-manager.js.map +1 -0
- package/package.json +88 -0
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persistent State Coordinator
|
|
3
|
+
*
|
|
4
|
+
* Extends StateCoordinator to automatically persist all state changes
|
|
5
|
+
* to disk using StateStore. Supports state restoration on initialization.
|
|
6
|
+
*/
|
|
7
|
+
import { StateCoordinator } from './state-coordinator.js';
|
|
8
|
+
import { createLogger } from '../observability/logger.js';
|
|
9
|
+
const logger = createLogger({ name: 'persistent-state-coordinator' });
|
|
10
|
+
/**
|
|
11
|
+
* PersistentStateCoordinator extends StateCoordinator with automatic
|
|
12
|
+
* state persistence. All state changes are automatically saved to disk
|
|
13
|
+
* via the StateStore, and state is restored on initialization.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* const stateStore = new StateStore({ stateDir: '.agent-foundry' });
|
|
18
|
+
* const coordinator = new PersistentStateCoordinator(stateStore, '/path/to/repo');
|
|
19
|
+
*
|
|
20
|
+
* await coordinator.initialize();
|
|
21
|
+
*
|
|
22
|
+
* // All state changes are automatically persisted
|
|
23
|
+
* coordinator.createTask('task-1', 'coder');
|
|
24
|
+
* coordinator.startTask('task-1');
|
|
25
|
+
*
|
|
26
|
+
* // Clean shutdown ensures all pending writes complete
|
|
27
|
+
* await coordinator.shutdown();
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export class PersistentStateCoordinator extends StateCoordinator {
|
|
31
|
+
stateStore;
|
|
32
|
+
repoPath;
|
|
33
|
+
initialized = false;
|
|
34
|
+
constructor(stateStore, repoPath) {
|
|
35
|
+
super();
|
|
36
|
+
this.stateStore = stateStore;
|
|
37
|
+
this.repoPath = repoPath;
|
|
38
|
+
this.setupPersistenceHooks();
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Initialize the coordinator - load persisted state and restore it.
|
|
42
|
+
*/
|
|
43
|
+
async initialize() {
|
|
44
|
+
if (this.initialized) {
|
|
45
|
+
logger.warn('PersistentStateCoordinator already initialized');
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
await this.stateStore.initialize(this.repoPath);
|
|
49
|
+
this.restoreFromPersistedState();
|
|
50
|
+
this.initialized = true;
|
|
51
|
+
logger.info('PersistentStateCoordinator initialized', {
|
|
52
|
+
repoPath: this.repoPath,
|
|
53
|
+
stats: this.getStats(),
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Check if the coordinator has been initialized.
|
|
58
|
+
*/
|
|
59
|
+
isInitialized() {
|
|
60
|
+
return this.initialized;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Setup event listeners to persist state changes.
|
|
64
|
+
* Called in constructor before initialize.
|
|
65
|
+
*/
|
|
66
|
+
setupPersistenceHooks() {
|
|
67
|
+
// Task lifecycle events
|
|
68
|
+
this.on('task:created', (task) => {
|
|
69
|
+
this.persistTaskCreated(task);
|
|
70
|
+
});
|
|
71
|
+
this.on('task:started', (task) => {
|
|
72
|
+
this.persistTaskUpdated(task);
|
|
73
|
+
});
|
|
74
|
+
this.on('task:completed', (task) => {
|
|
75
|
+
this.persistTaskUpdated(task);
|
|
76
|
+
});
|
|
77
|
+
this.on('task:failed', (task) => {
|
|
78
|
+
this.persistTaskUpdated(task);
|
|
79
|
+
});
|
|
80
|
+
// Worktree linking events
|
|
81
|
+
this.on('worktree:linked', (taskId, worktreeId) => {
|
|
82
|
+
this.persistWorktreeLink(taskId, worktreeId);
|
|
83
|
+
});
|
|
84
|
+
this.on('worktree:unlinked', (taskId, worktreeId) => {
|
|
85
|
+
this.persistWorktreeUnlink(taskId, worktreeId);
|
|
86
|
+
});
|
|
87
|
+
// Conflict events
|
|
88
|
+
this.on('conflict:detected', (taskId, state) => {
|
|
89
|
+
this.persistConflictDetected(taskId, state);
|
|
90
|
+
});
|
|
91
|
+
this.on('conflict:resolved', (taskId, state) => {
|
|
92
|
+
this.persistConflictResolved(taskId, state);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Restore in-memory state from persisted state.
|
|
97
|
+
* Handles stale/orphaned entries gracefully.
|
|
98
|
+
*/
|
|
99
|
+
restoreFromPersistedState() {
|
|
100
|
+
const persistedState = this.stateStore.getState();
|
|
101
|
+
// Restore tasks
|
|
102
|
+
let restoredTasks = 0;
|
|
103
|
+
let skippedTasks = 0;
|
|
104
|
+
for (const persistedTask of persistedState.tasks) {
|
|
105
|
+
// Skip tasks in terminal states that are old (cleanup can handle them)
|
|
106
|
+
if ((persistedTask.status === 'completed' || persistedTask.status === 'failed') &&
|
|
107
|
+
Date.now() - persistedTask.updatedAt > 24 * 60 * 60 * 1000 // 24 hours
|
|
108
|
+
) {
|
|
109
|
+
skippedTasks++;
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
// Recreate task via parent class createTask, then update status
|
|
113
|
+
// We need to access the internal maps, so we use the parent methods carefully
|
|
114
|
+
const task = super.createTask(persistedTask.taskId, persistedTask.role);
|
|
115
|
+
// Update task fields to match persisted state
|
|
116
|
+
if (persistedTask.status === 'running') {
|
|
117
|
+
super.startTask(persistedTask.taskId);
|
|
118
|
+
}
|
|
119
|
+
else if (persistedTask.status === 'completed') {
|
|
120
|
+
// Need to set startedAt first for proper state
|
|
121
|
+
const internalTask = super.getTask(persistedTask.taskId);
|
|
122
|
+
if (internalTask) {
|
|
123
|
+
internalTask.startedAt = persistedTask.createdAt;
|
|
124
|
+
}
|
|
125
|
+
super.completeTask(persistedTask.taskId);
|
|
126
|
+
}
|
|
127
|
+
else if (persistedTask.status === 'failed') {
|
|
128
|
+
const internalTask = super.getTask(persistedTask.taskId);
|
|
129
|
+
if (internalTask) {
|
|
130
|
+
internalTask.startedAt = persistedTask.createdAt;
|
|
131
|
+
}
|
|
132
|
+
super.failTask(persistedTask.taskId, persistedTask.error || 'Unknown error');
|
|
133
|
+
}
|
|
134
|
+
restoredTasks++;
|
|
135
|
+
}
|
|
136
|
+
// Restore worktree links
|
|
137
|
+
let restoredLinks = 0;
|
|
138
|
+
for (const persistedWorktree of persistedState.worktrees) {
|
|
139
|
+
if (persistedWorktree.taskId) {
|
|
140
|
+
const task = super.getTask(persistedWorktree.taskId);
|
|
141
|
+
if (task) {
|
|
142
|
+
try {
|
|
143
|
+
super.linkTaskToWorktree(persistedWorktree.taskId, persistedWorktree.id);
|
|
144
|
+
restoredLinks++;
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
logger.warn('Failed to restore worktree link', {
|
|
148
|
+
taskId: persistedWorktree.taskId,
|
|
149
|
+
worktreeId: persistedWorktree.id,
|
|
150
|
+
error: error instanceof Error ? error.message : String(error),
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// Restore conflicts
|
|
157
|
+
let restoredConflicts = 0;
|
|
158
|
+
for (const persistedConflict of persistedState.conflicts) {
|
|
159
|
+
// Only restore unresolved conflicts for active tasks
|
|
160
|
+
if (!persistedConflict.resolved) {
|
|
161
|
+
const task = super.getTask(persistedConflict.taskId);
|
|
162
|
+
if (task) {
|
|
163
|
+
const conflictState = {
|
|
164
|
+
taskId: persistedConflict.taskId,
|
|
165
|
+
worktreeId: persistedConflict.worktreeId,
|
|
166
|
+
detectedAt: persistedConflict.detectedAt,
|
|
167
|
+
files: persistedConflict.files.map(file => ({
|
|
168
|
+
file,
|
|
169
|
+
conflicts: [], // Full conflict markers not persisted
|
|
170
|
+
totalConflicts: 1,
|
|
171
|
+
})),
|
|
172
|
+
totalConflicts: persistedConflict.files.length,
|
|
173
|
+
resolved: persistedConflict.resolved,
|
|
174
|
+
resolutionStrategy: persistedConflict.strategy,
|
|
175
|
+
resolvedAt: persistedConflict.resolvedAt,
|
|
176
|
+
};
|
|
177
|
+
super.setConflictState(persistedConflict.taskId, conflictState);
|
|
178
|
+
restoredConflicts++;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
logger.info('State restored from persistence', {
|
|
183
|
+
restoredTasks,
|
|
184
|
+
skippedTasks,
|
|
185
|
+
restoredLinks,
|
|
186
|
+
restoredConflicts,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
// ==========================================================================
|
|
190
|
+
// Persistence Methods
|
|
191
|
+
// ==========================================================================
|
|
192
|
+
/**
|
|
193
|
+
* Persist a newly created task.
|
|
194
|
+
*/
|
|
195
|
+
persistTaskCreated(task) {
|
|
196
|
+
const now = Date.now();
|
|
197
|
+
this.stateStore.updateState((state) => {
|
|
198
|
+
// Check if task already exists (shouldn't happen, but be safe)
|
|
199
|
+
const existingIndex = state.tasks.findIndex(t => t.taskId === task.taskId);
|
|
200
|
+
if (existingIndex !== -1) {
|
|
201
|
+
state.tasks[existingIndex] = this.toPersistedTask(task, now);
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
state.tasks.push(this.toPersistedTask(task, now));
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
logger.debug('Persisted task creation', { taskId: task.taskId });
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Persist a task status update.
|
|
211
|
+
*/
|
|
212
|
+
persistTaskUpdated(task) {
|
|
213
|
+
const now = Date.now();
|
|
214
|
+
this.stateStore.updateState((state) => {
|
|
215
|
+
const index = state.tasks.findIndex(t => t.taskId === task.taskId);
|
|
216
|
+
if (index !== -1) {
|
|
217
|
+
state.tasks[index] = {
|
|
218
|
+
...state.tasks[index],
|
|
219
|
+
status: task.status,
|
|
220
|
+
worktreeId: task.worktreeId,
|
|
221
|
+
updatedAt: now,
|
|
222
|
+
error: task.error,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
// Task doesn't exist in persisted state, create it
|
|
227
|
+
state.tasks.push(this.toPersistedTask(task, now));
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
logger.debug('Persisted task update', { taskId: task.taskId, status: task.status });
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Persist a worktree link.
|
|
234
|
+
*/
|
|
235
|
+
persistWorktreeLink(taskId, worktreeId) {
|
|
236
|
+
const now = Date.now();
|
|
237
|
+
this.stateStore.updateState((state) => {
|
|
238
|
+
// Update task's worktreeId
|
|
239
|
+
const taskIndex = state.tasks.findIndex(t => t.taskId === taskId);
|
|
240
|
+
if (taskIndex !== -1) {
|
|
241
|
+
state.tasks[taskIndex].worktreeId = worktreeId;
|
|
242
|
+
state.tasks[taskIndex].updatedAt = now;
|
|
243
|
+
}
|
|
244
|
+
// Find or create worktree entry
|
|
245
|
+
const worktreeIndex = state.worktrees.findIndex(w => w.id === worktreeId);
|
|
246
|
+
if (worktreeIndex !== -1) {
|
|
247
|
+
state.worktrees[worktreeIndex].taskId = taskId;
|
|
248
|
+
state.worktrees[worktreeIndex].lastActivityAt = now;
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
// Create minimal worktree entry if it doesn't exist
|
|
252
|
+
// This handles cases where worktree was created outside the coordinator
|
|
253
|
+
state.worktrees.push({
|
|
254
|
+
id: worktreeId,
|
|
255
|
+
path: '', // Will be populated by worktree manager
|
|
256
|
+
branch: '',
|
|
257
|
+
baseBranch: '',
|
|
258
|
+
status: 'assigned',
|
|
259
|
+
taskId,
|
|
260
|
+
createdAt: now,
|
|
261
|
+
lastActivityAt: now,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
logger.debug('Persisted worktree link', { taskId, worktreeId });
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Persist a worktree unlink.
|
|
269
|
+
*/
|
|
270
|
+
persistWorktreeUnlink(taskId, worktreeId) {
|
|
271
|
+
const now = Date.now();
|
|
272
|
+
this.stateStore.updateState((state) => {
|
|
273
|
+
// Clear task's worktreeId
|
|
274
|
+
const taskIndex = state.tasks.findIndex(t => t.taskId === taskId);
|
|
275
|
+
if (taskIndex !== -1) {
|
|
276
|
+
state.tasks[taskIndex].worktreeId = undefined;
|
|
277
|
+
state.tasks[taskIndex].updatedAt = now;
|
|
278
|
+
}
|
|
279
|
+
// Clear worktree's taskId
|
|
280
|
+
const worktreeIndex = state.worktrees.findIndex(w => w.id === worktreeId);
|
|
281
|
+
if (worktreeIndex !== -1) {
|
|
282
|
+
state.worktrees[worktreeIndex].taskId = undefined;
|
|
283
|
+
state.worktrees[worktreeIndex].status = 'available';
|
|
284
|
+
state.worktrees[worktreeIndex].lastActivityAt = now;
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
logger.debug('Persisted worktree unlink', { taskId, worktreeId });
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Persist a conflict detection.
|
|
291
|
+
*/
|
|
292
|
+
persistConflictDetected(taskId, conflictState) {
|
|
293
|
+
const now = Date.now();
|
|
294
|
+
this.stateStore.updateState((state) => {
|
|
295
|
+
// Check if conflict already exists for this task
|
|
296
|
+
const existingIndex = state.conflicts.findIndex(c => c.taskId === taskId);
|
|
297
|
+
const persistedConflict = {
|
|
298
|
+
taskId: conflictState.taskId,
|
|
299
|
+
worktreeId: conflictState.worktreeId,
|
|
300
|
+
files: conflictState.files.map(f => f.file),
|
|
301
|
+
resolved: conflictState.resolved,
|
|
302
|
+
strategy: conflictState.resolutionStrategy,
|
|
303
|
+
detectedAt: conflictState.detectedAt,
|
|
304
|
+
resolvedAt: conflictState.resolvedAt,
|
|
305
|
+
};
|
|
306
|
+
if (existingIndex !== -1) {
|
|
307
|
+
state.conflicts[existingIndex] = persistedConflict;
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
state.conflicts.push(persistedConflict);
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
logger.debug('Persisted conflict detection', { taskId, files: conflictState.files.length });
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Persist a conflict resolution.
|
|
317
|
+
*/
|
|
318
|
+
persistConflictResolved(taskId, conflictState) {
|
|
319
|
+
this.stateStore.updateState((state) => {
|
|
320
|
+
const index = state.conflicts.findIndex(c => c.taskId === taskId);
|
|
321
|
+
if (index !== -1) {
|
|
322
|
+
state.conflicts[index] = {
|
|
323
|
+
...state.conflicts[index],
|
|
324
|
+
resolved: true,
|
|
325
|
+
strategy: conflictState.resolutionStrategy,
|
|
326
|
+
resolvedAt: conflictState.resolvedAt || Date.now(),
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
logger.debug('Persisted conflict resolution', { taskId });
|
|
331
|
+
}
|
|
332
|
+
// ==========================================================================
|
|
333
|
+
// Helper Methods
|
|
334
|
+
// ==========================================================================
|
|
335
|
+
/**
|
|
336
|
+
* Convert TaskState to PersistedTaskState.
|
|
337
|
+
*/
|
|
338
|
+
toPersistedTask(task, timestamp) {
|
|
339
|
+
return {
|
|
340
|
+
taskId: task.taskId,
|
|
341
|
+
role: task.role,
|
|
342
|
+
status: task.status,
|
|
343
|
+
worktreeId: task.worktreeId,
|
|
344
|
+
createdAt: task.startedAt || timestamp,
|
|
345
|
+
updatedAt: timestamp,
|
|
346
|
+
error: task.error,
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
// ==========================================================================
|
|
350
|
+
// Shutdown
|
|
351
|
+
// ==========================================================================
|
|
352
|
+
/**
|
|
353
|
+
* Shutdown the coordinator and ensure all state is persisted.
|
|
354
|
+
*/
|
|
355
|
+
async shutdown() {
|
|
356
|
+
if (!this.initialized) {
|
|
357
|
+
logger.warn('PersistentStateCoordinator not initialized, skipping shutdown');
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
await this.stateStore.shutdown(this.repoPath);
|
|
361
|
+
this.initialized = false;
|
|
362
|
+
logger.info('PersistentStateCoordinator shutdown complete');
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Force an immediate save of all pending state changes.
|
|
366
|
+
*/
|
|
367
|
+
async saveNow() {
|
|
368
|
+
await this.stateStore.saveNow(this.repoPath);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
//# sourceMappingURL=persistent-state-coordinator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persistent-state-coordinator.js","sourceRoot":"","sources":["../../src/tasks/persistent-state-coordinator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pipeline Manager
|
|
3
|
+
*
|
|
4
|
+
* Manages multi-step task DAGs with dependency resolution.
|
|
5
|
+
* Generates TaskCreate instructions for Claude to execute.
|
|
6
|
+
*/
|
|
7
|
+
import type { Logger } from "../observability/logger.js";
|
|
8
|
+
import type { WorktreeManager } from "../worktrees/manager.js";
|
|
9
|
+
import type { AgentResponse, PipelineDefinition, PipelineExecution, PipelineStep, StepWorktreeAllocation } from "../types.js";
|
|
10
|
+
export declare class PipelineManager {
|
|
11
|
+
private executions;
|
|
12
|
+
private stepWorktrees;
|
|
13
|
+
private logger;
|
|
14
|
+
constructor(logger: Logger);
|
|
15
|
+
/**
|
|
16
|
+
* Allocate a worktree for a pipeline step.
|
|
17
|
+
*/
|
|
18
|
+
allocateWorktreeForStep(stepId: string, allocation: StepWorktreeAllocation): void;
|
|
19
|
+
/**
|
|
20
|
+
* Get the worktree allocation for a step.
|
|
21
|
+
*/
|
|
22
|
+
getStepWorktree(stepId: string): StepWorktreeAllocation | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Get all allocated worktrees.
|
|
25
|
+
*/
|
|
26
|
+
getAllocatedWorktrees(): Map<string, StepWorktreeAllocation>;
|
|
27
|
+
/**
|
|
28
|
+
* Update the status of a step's worktree allocation.
|
|
29
|
+
*/
|
|
30
|
+
updateStepWorktreeStatus(stepId: string, status: StepWorktreeAllocation['status']): void;
|
|
31
|
+
/**
|
|
32
|
+
* Validate pipeline definition for cycles and missing dependencies.
|
|
33
|
+
* Uses topological sort (Kahn's algorithm) to detect cycles.
|
|
34
|
+
* @throws Error if validation fails
|
|
35
|
+
*/
|
|
36
|
+
validateDefinition(definition: PipelineDefinition): void;
|
|
37
|
+
/**
|
|
38
|
+
* Generate TaskCreate instructions for all pipeline steps.
|
|
39
|
+
* Returns a string with all the TaskCreate calls Claude should execute.
|
|
40
|
+
*/
|
|
41
|
+
generatePipelineCreation(definition: PipelineDefinition): string;
|
|
42
|
+
/**
|
|
43
|
+
* Create a new pipeline execution tracker.
|
|
44
|
+
*/
|
|
45
|
+
createExecution(definition: PipelineDefinition): PipelineExecution;
|
|
46
|
+
/**
|
|
47
|
+
* Get a pipeline execution by ID.
|
|
48
|
+
*/
|
|
49
|
+
getExecution(pipelineId: string): PipelineExecution | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* Register task IDs after Claude creates the tasks.
|
|
52
|
+
*/
|
|
53
|
+
registerTaskIds(pipelineId: string, taskIdMap: Map<string, string>): void;
|
|
54
|
+
/**
|
|
55
|
+
* Determine which steps are ready to execute (all dependencies complete).
|
|
56
|
+
*/
|
|
57
|
+
getReadySteps(execution: PipelineExecution): PipelineStep[];
|
|
58
|
+
/**
|
|
59
|
+
* Mark a step as completed with its result.
|
|
60
|
+
*/
|
|
61
|
+
completeStep(pipelineId: string, stepName: string, result: AgentResponse): void;
|
|
62
|
+
/**
|
|
63
|
+
* Mark a step as failed.
|
|
64
|
+
*/
|
|
65
|
+
failStep(pipelineId: string, stepName: string, error: Error): void;
|
|
66
|
+
/**
|
|
67
|
+
* Build context for a step, including results from completed dependencies.
|
|
68
|
+
* Truncates if total context exceeds MAX_CONTEXT_LENGTH.
|
|
69
|
+
*/
|
|
70
|
+
buildStepContext(execution: PipelineExecution, step: PipelineStep): string;
|
|
71
|
+
/**
|
|
72
|
+
* Get all active pipeline executions.
|
|
73
|
+
*/
|
|
74
|
+
getActiveExecutions(): PipelineExecution[];
|
|
75
|
+
/**
|
|
76
|
+
* Cleanup worktrees after successful pipeline merge.
|
|
77
|
+
* @param pipelineId - Pipeline to cleanup
|
|
78
|
+
* @param worktreeManager - WorktreeManager instance
|
|
79
|
+
* @param deleteBranches - Whether to delete the merged branches
|
|
80
|
+
*/
|
|
81
|
+
cleanupPipelineWorktrees(pipelineId: string, worktreeManager: WorktreeManager, deleteBranches?: boolean): Promise<{
|
|
82
|
+
cleaned: number;
|
|
83
|
+
errors: string[];
|
|
84
|
+
}>;
|
|
85
|
+
/**
|
|
86
|
+
* Mark a pipeline as failed and preserve worktrees for debugging.
|
|
87
|
+
* @param pipelineId - Pipeline to rollback
|
|
88
|
+
* @param reason - Failure reason
|
|
89
|
+
*/
|
|
90
|
+
markPipelineFailed(pipelineId: string, reason: string): void;
|
|
91
|
+
/**
|
|
92
|
+
* Get cleanup summary for a pipeline.
|
|
93
|
+
*/
|
|
94
|
+
getWorktreeCleanupSummary(): {
|
|
95
|
+
total: number;
|
|
96
|
+
pending: number;
|
|
97
|
+
active: number;
|
|
98
|
+
completed: number;
|
|
99
|
+
merged: number;
|
|
100
|
+
conflict: number;
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=pipeline-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline-manager.d.ts","sourceRoot":"","sources":["../../src/tasks/pipeline-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EACV,aAAa,EACb,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACZ,sBAAsB,EACvB,MAAM,aAAa,CAAC;AAKrB,qBAAa,eAAe;IAC1B,OAAO,CAAC,UAAU,CAA6C;IAC/D,OAAO,CAAC,aAAa,CAAkD;IACvE,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,MAAM;IAI1B;;OAEG;IACH,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,sBAAsB,GAAG,IAAI;IASjF;;OAEG;IACH,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,sBAAsB,GAAG,SAAS;IAInE;;OAEG;IACH,qBAAqB,IAAI,GAAG,CAAC,MAAM,EAAE,sBAAsB,CAAC;IAI5D;;OAEG;IACH,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,sBAAsB,CAAC,QAAQ,CAAC,GAAG,IAAI;IAYxF;;;;OAIG;IACH,kBAAkB,CAAC,UAAU,EAAE,kBAAkB,GAAG,IAAI;IAyDxD;;;OAGG;IACH,wBAAwB,CAAC,UAAU,EAAE,kBAAkB,GAAG,MAAM;IA2ChE;;OAEG;IACH,eAAe,CAAC,UAAU,EAAE,kBAAkB,GAAG,iBAAiB;IAuBlE;;OAEG;IACH,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS;IAI/D;;OAEG;IACH,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IASzE;;OAEG;IACH,aAAa,CAAC,SAAS,EAAE,iBAAiB,GAAG,YAAY,EAAE;IAc3D;;OAEG;IACH,YAAY,CACV,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,aAAa,GACpB,IAAI;IAsBP;;OAEG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI;IAUlE;;;OAGG;IACH,gBAAgB,CAAC,SAAS,EAAE,iBAAiB,EAAE,IAAI,EAAE,YAAY,GAAG,MAAM;IA8C1E;;OAEG;IACH,mBAAmB,IAAI,iBAAiB,EAAE;IAM1C;;;;;OAKG;IACG,wBAAwB,CAC5B,UAAU,EAAE,MAAM,EAClB,eAAe,EAAE,eAAe,EAChC,cAAc,UAAO,GACpB,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAyBjD;;;;OAIG;IACH,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAe5D;;OAEG;IACH,yBAAyB,IAAI;QAC3B,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;KAClB;CAkCF"}
|