steroids-api 0.2.7
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/dist/API/src/index.d.ts +10 -0
- package/dist/API/src/index.d.ts.map +1 -0
- package/dist/API/src/index.js +130 -0
- package/dist/API/src/index.js.map +1 -0
- package/dist/API/src/routes/activity.d.ts +7 -0
- package/dist/API/src/routes/activity.d.ts.map +1 -0
- package/dist/API/src/routes/activity.js +252 -0
- package/dist/API/src/routes/activity.js.map +1 -0
- package/dist/API/src/routes/config.d.ts +7 -0
- package/dist/API/src/routes/config.d.ts.map +1 -0
- package/dist/API/src/routes/config.js +521 -0
- package/dist/API/src/routes/config.js.map +1 -0
- package/dist/API/src/routes/health.d.ts +7 -0
- package/dist/API/src/routes/health.d.ts.map +1 -0
- package/dist/API/src/routes/health.js +172 -0
- package/dist/API/src/routes/health.js.map +1 -0
- package/dist/API/src/routes/incidents.d.ts +7 -0
- package/dist/API/src/routes/incidents.d.ts.map +1 -0
- package/dist/API/src/routes/incidents.js +117 -0
- package/dist/API/src/routes/incidents.js.map +1 -0
- package/dist/API/src/routes/projects.d.ts +7 -0
- package/dist/API/src/routes/projects.d.ts.map +1 -0
- package/dist/API/src/routes/projects.js +398 -0
- package/dist/API/src/routes/projects.js.map +1 -0
- package/dist/API/src/routes/runners.d.ts +7 -0
- package/dist/API/src/routes/runners.d.ts.map +1 -0
- package/dist/API/src/routes/runners.js +242 -0
- package/dist/API/src/routes/runners.js.map +1 -0
- package/dist/API/src/routes/tasks.d.ts +7 -0
- package/dist/API/src/routes/tasks.d.ts.map +1 -0
- package/dist/API/src/routes/tasks.js +1007 -0
- package/dist/API/src/routes/tasks.js.map +1 -0
- package/dist/API/src/utils/validation.d.ts +22 -0
- package/dist/API/src/utils/validation.d.ts.map +1 -0
- package/dist/API/src/utils/validation.js +50 -0
- package/dist/API/src/utils/validation.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +184 -0
- package/dist/index.js.map +1 -0
- package/dist/routes/activity.d.ts +7 -0
- package/dist/routes/activity.d.ts.map +1 -0
- package/dist/routes/activity.js +252 -0
- package/dist/routes/activity.js.map +1 -0
- package/dist/routes/config.d.ts +7 -0
- package/dist/routes/config.d.ts.map +1 -0
- package/dist/routes/config.js +647 -0
- package/dist/routes/config.js.map +1 -0
- package/dist/routes/credit-alerts.d.ts +2 -0
- package/dist/routes/credit-alerts.d.ts.map +1 -0
- package/dist/routes/credit-alerts.js +97 -0
- package/dist/routes/credit-alerts.js.map +1 -0
- package/dist/routes/health.d.ts +7 -0
- package/dist/routes/health.d.ts.map +1 -0
- package/dist/routes/health.js +200 -0
- package/dist/routes/health.js.map +1 -0
- package/dist/routes/incidents.d.ts +7 -0
- package/dist/routes/incidents.d.ts.map +1 -0
- package/dist/routes/incidents.js +117 -0
- package/dist/routes/incidents.js.map +1 -0
- package/dist/routes/projects.d.ts +7 -0
- package/dist/routes/projects.d.ts.map +1 -0
- package/dist/routes/projects.js +643 -0
- package/dist/routes/projects.js.map +1 -0
- package/dist/routes/runners.d.ts +7 -0
- package/dist/routes/runners.d.ts.map +1 -0
- package/dist/routes/runners.js +299 -0
- package/dist/routes/runners.js.map +1 -0
- package/dist/routes/skills.d.ts +3 -0
- package/dist/routes/skills.d.ts.map +1 -0
- package/dist/routes/skills.js +109 -0
- package/dist/routes/skills.js.map +1 -0
- package/dist/routes/storage.d.ts +7 -0
- package/dist/routes/storage.d.ts.map +1 -0
- package/dist/routes/storage.js +93 -0
- package/dist/routes/storage.js.map +1 -0
- package/dist/routes/tasks.d.ts +7 -0
- package/dist/routes/tasks.d.ts.map +1 -0
- package/dist/routes/tasks.js +1145 -0
- package/dist/routes/tasks.js.map +1 -0
- package/dist/src/cleanup/invocation-logs.d.ts +30 -0
- package/dist/src/cleanup/invocation-logs.d.ts.map +1 -0
- package/dist/src/cleanup/invocation-logs.js +66 -0
- package/dist/src/cleanup/invocation-logs.js.map +1 -0
- package/dist/src/commands/loop-phases.d.ts +11 -0
- package/dist/src/commands/loop-phases.d.ts.map +1 -0
- package/dist/src/commands/loop-phases.js +304 -0
- package/dist/src/commands/loop-phases.js.map +1 -0
- package/dist/src/config/loader.d.ts +160 -0
- package/dist/src/config/loader.d.ts.map +1 -0
- package/dist/src/config/loader.js +276 -0
- package/dist/src/config/loader.js.map +1 -0
- package/dist/src/database/connection.d.ts +35 -0
- package/dist/src/database/connection.d.ts.map +1 -0
- package/dist/src/database/connection.js +197 -0
- package/dist/src/database/connection.js.map +1 -0
- package/dist/src/database/queries.d.ts +220 -0
- package/dist/src/database/queries.d.ts.map +1 -0
- package/dist/src/database/queries.js +589 -0
- package/dist/src/database/queries.js.map +1 -0
- package/dist/src/database/schema.d.ts +8 -0
- package/dist/src/database/schema.d.ts.map +1 -0
- package/dist/src/database/schema.js +184 -0
- package/dist/src/database/schema.js.map +1 -0
- package/dist/src/git/push.d.ts +26 -0
- package/dist/src/git/push.d.ts.map +1 -0
- package/dist/src/git/push.js +91 -0
- package/dist/src/git/push.js.map +1 -0
- package/dist/src/git/status.d.ts +83 -0
- package/dist/src/git/status.d.ts.map +1 -0
- package/dist/src/git/status.js +315 -0
- package/dist/src/git/status.js.map +1 -0
- package/dist/src/health/stuck-task-detector.d.ts +131 -0
- package/dist/src/health/stuck-task-detector.d.ts.map +1 -0
- package/dist/src/health/stuck-task-detector.js +233 -0
- package/dist/src/health/stuck-task-detector.js.map +1 -0
- package/dist/src/health/stuck-task-recovery.d.ts +45 -0
- package/dist/src/health/stuck-task-recovery.d.ts.map +1 -0
- package/dist/src/health/stuck-task-recovery.js +309 -0
- package/dist/src/health/stuck-task-recovery.js.map +1 -0
- package/dist/src/index.d.ts +10 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +130 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/locking/queries.d.ts +116 -0
- package/dist/src/locking/queries.d.ts.map +1 -0
- package/dist/src/locking/queries.js +232 -0
- package/dist/src/locking/queries.js.map +1 -0
- package/dist/src/locking/section-lock.d.ts +74 -0
- package/dist/src/locking/section-lock.d.ts.map +1 -0
- package/dist/src/locking/section-lock.js +196 -0
- package/dist/src/locking/section-lock.js.map +1 -0
- package/dist/src/locking/task-lock.d.ts +92 -0
- package/dist/src/locking/task-lock.d.ts.map +1 -0
- package/dist/src/locking/task-lock.js +233 -0
- package/dist/src/locking/task-lock.js.map +1 -0
- package/dist/src/migrations/index.d.ts +7 -0
- package/dist/src/migrations/index.d.ts.map +1 -0
- package/dist/src/migrations/index.js +9 -0
- package/dist/src/migrations/index.js.map +1 -0
- package/dist/src/migrations/manifest.d.ts +92 -0
- package/dist/src/migrations/manifest.d.ts.map +1 -0
- package/dist/src/migrations/manifest.js +255 -0
- package/dist/src/migrations/manifest.js.map +1 -0
- package/dist/src/migrations/runner.d.ts +84 -0
- package/dist/src/migrations/runner.d.ts.map +1 -0
- package/dist/src/migrations/runner.js +338 -0
- package/dist/src/migrations/runner.js.map +1 -0
- package/dist/src/orchestrator/coder.d.ts +32 -0
- package/dist/src/orchestrator/coder.d.ts.map +1 -0
- package/dist/src/orchestrator/coder.js +170 -0
- package/dist/src/orchestrator/coder.js.map +1 -0
- package/dist/src/orchestrator/coordinator.d.ts +28 -0
- package/dist/src/orchestrator/coordinator.d.ts.map +1 -0
- package/dist/src/orchestrator/coordinator.js +252 -0
- package/dist/src/orchestrator/coordinator.js.map +1 -0
- package/dist/src/orchestrator/fallback-handler.d.ts +24 -0
- package/dist/src/orchestrator/fallback-handler.d.ts.map +1 -0
- package/dist/src/orchestrator/fallback-handler.js +280 -0
- package/dist/src/orchestrator/fallback-handler.js.map +1 -0
- package/dist/src/orchestrator/invoke.d.ts +14 -0
- package/dist/src/orchestrator/invoke.d.ts.map +1 -0
- package/dist/src/orchestrator/invoke.js +76 -0
- package/dist/src/orchestrator/invoke.js.map +1 -0
- package/dist/src/orchestrator/post-coder.d.ts +10 -0
- package/dist/src/orchestrator/post-coder.d.ts.map +1 -0
- package/dist/src/orchestrator/post-coder.js +198 -0
- package/dist/src/orchestrator/post-coder.js.map +1 -0
- package/dist/src/orchestrator/post-reviewer.d.ts +10 -0
- package/dist/src/orchestrator/post-reviewer.d.ts.map +1 -0
- package/dist/src/orchestrator/post-reviewer.js +199 -0
- package/dist/src/orchestrator/post-reviewer.js.map +1 -0
- package/dist/src/orchestrator/reviewer.d.ts +35 -0
- package/dist/src/orchestrator/reviewer.d.ts.map +1 -0
- package/dist/src/orchestrator/reviewer.js +237 -0
- package/dist/src/orchestrator/reviewer.js.map +1 -0
- package/dist/src/orchestrator/schemas.d.ts +10 -0
- package/dist/src/orchestrator/schemas.d.ts.map +1 -0
- package/dist/src/orchestrator/schemas.js +81 -0
- package/dist/src/orchestrator/schemas.js.map +1 -0
- package/dist/src/orchestrator/task-selector.d.ts +102 -0
- package/dist/src/orchestrator/task-selector.d.ts.map +1 -0
- package/dist/src/orchestrator/task-selector.js +326 -0
- package/dist/src/orchestrator/task-selector.js.map +1 -0
- package/dist/src/orchestrator/types.d.ts +74 -0
- package/dist/src/orchestrator/types.d.ts.map +1 -0
- package/dist/src/orchestrator/types.js +5 -0
- package/dist/src/orchestrator/types.js.map +1 -0
- package/dist/src/prompts/coder.d.ts +36 -0
- package/dist/src/prompts/coder.d.ts.map +1 -0
- package/dist/src/prompts/coder.js +303 -0
- package/dist/src/prompts/coder.js.map +1 -0
- package/dist/src/prompts/prompt-helpers.d.ts +51 -0
- package/dist/src/prompts/prompt-helpers.d.ts.map +1 -0
- package/dist/src/prompts/prompt-helpers.js +299 -0
- package/dist/src/prompts/prompt-helpers.js.map +1 -0
- package/dist/src/prompts/reviewer.d.ts +40 -0
- package/dist/src/prompts/reviewer.d.ts.map +1 -0
- package/dist/src/prompts/reviewer.js +416 -0
- package/dist/src/prompts/reviewer.js.map +1 -0
- package/dist/src/providers/claude.d.ts +53 -0
- package/dist/src/providers/claude.d.ts.map +1 -0
- package/dist/src/providers/claude.js +227 -0
- package/dist/src/providers/claude.js.map +1 -0
- package/dist/src/providers/codex.d.ts +53 -0
- package/dist/src/providers/codex.d.ts.map +1 -0
- package/dist/src/providers/codex.js +253 -0
- package/dist/src/providers/codex.js.map +1 -0
- package/dist/src/providers/gemini.d.ts +58 -0
- package/dist/src/providers/gemini.d.ts.map +1 -0
- package/dist/src/providers/gemini.js +240 -0
- package/dist/src/providers/gemini.js.map +1 -0
- package/dist/src/providers/interface.d.ts +185 -0
- package/dist/src/providers/interface.d.ts.map +1 -0
- package/dist/src/providers/interface.js +92 -0
- package/dist/src/providers/interface.js.map +1 -0
- package/dist/src/providers/invocation-logger.d.ts +97 -0
- package/dist/src/providers/invocation-logger.d.ts.map +1 -0
- package/dist/src/providers/invocation-logger.js +378 -0
- package/dist/src/providers/invocation-logger.js.map +1 -0
- package/dist/src/providers/openai.d.ts +53 -0
- package/dist/src/providers/openai.d.ts.map +1 -0
- package/dist/src/providers/openai.js +230 -0
- package/dist/src/providers/openai.js.map +1 -0
- package/dist/src/providers/registry.d.ts +100 -0
- package/dist/src/providers/registry.d.ts.map +1 -0
- package/dist/src/providers/registry.js +170 -0
- package/dist/src/providers/registry.js.map +1 -0
- package/dist/src/routes/activity.d.ts +7 -0
- package/dist/src/routes/activity.d.ts.map +1 -0
- package/dist/src/routes/activity.js +252 -0
- package/dist/src/routes/activity.js.map +1 -0
- package/dist/src/routes/config.d.ts +7 -0
- package/dist/src/routes/config.d.ts.map +1 -0
- package/dist/src/routes/config.js +521 -0
- package/dist/src/routes/config.js.map +1 -0
- package/dist/src/routes/health.d.ts +7 -0
- package/dist/src/routes/health.d.ts.map +1 -0
- package/dist/src/routes/health.js +172 -0
- package/dist/src/routes/health.js.map +1 -0
- package/dist/src/routes/incidents.d.ts +7 -0
- package/dist/src/routes/incidents.d.ts.map +1 -0
- package/dist/src/routes/incidents.js +117 -0
- package/dist/src/routes/incidents.js.map +1 -0
- package/dist/src/routes/projects.d.ts +7 -0
- package/dist/src/routes/projects.d.ts.map +1 -0
- package/dist/src/routes/projects.js +398 -0
- package/dist/src/routes/projects.js.map +1 -0
- package/dist/src/routes/runners.d.ts +7 -0
- package/dist/src/routes/runners.d.ts.map +1 -0
- package/dist/src/routes/runners.js +242 -0
- package/dist/src/routes/runners.js.map +1 -0
- package/dist/src/routes/tasks.d.ts +7 -0
- package/dist/src/routes/tasks.d.ts.map +1 -0
- package/dist/src/routes/tasks.js +1007 -0
- package/dist/src/routes/tasks.js.map +1 -0
- package/dist/src/runners/activity-log.d.ts +65 -0
- package/dist/src/runners/activity-log.d.ts.map +1 -0
- package/dist/src/runners/activity-log.js +140 -0
- package/dist/src/runners/activity-log.js.map +1 -0
- package/dist/src/runners/cron.d.ts +30 -0
- package/dist/src/runners/cron.d.ts.map +1 -0
- package/dist/src/runners/cron.js +333 -0
- package/dist/src/runners/cron.js.map +1 -0
- package/dist/src/runners/daemon.d.ts +71 -0
- package/dist/src/runners/daemon.d.ts.map +1 -0
- package/dist/src/runners/daemon.js +233 -0
- package/dist/src/runners/daemon.js.map +1 -0
- package/dist/src/runners/global-db.d.ts +31 -0
- package/dist/src/runners/global-db.d.ts.map +1 -0
- package/dist/src/runners/global-db.js +220 -0
- package/dist/src/runners/global-db.js.map +1 -0
- package/dist/src/runners/hang-detector.d.ts +38 -0
- package/dist/src/runners/hang-detector.d.ts.map +1 -0
- package/dist/src/runners/hang-detector.js +130 -0
- package/dist/src/runners/hang-detector.js.map +1 -0
- package/dist/src/runners/heartbeat.d.ts +39 -0
- package/dist/src/runners/heartbeat.d.ts.map +1 -0
- package/dist/src/runners/heartbeat.js +71 -0
- package/dist/src/runners/heartbeat.js.map +1 -0
- package/dist/src/runners/lock.d.ts +47 -0
- package/dist/src/runners/lock.d.ts.map +1 -0
- package/dist/src/runners/lock.js +140 -0
- package/dist/src/runners/lock.js.map +1 -0
- package/dist/src/runners/orchestrator-loop.d.ts +20 -0
- package/dist/src/runners/orchestrator-loop.d.ts.map +1 -0
- package/dist/src/runners/orchestrator-loop.js +208 -0
- package/dist/src/runners/orchestrator-loop.js.map +1 -0
- package/dist/src/runners/projects.d.ts +96 -0
- package/dist/src/runners/projects.d.ts.map +1 -0
- package/dist/src/runners/projects.js +243 -0
- package/dist/src/runners/projects.js.map +1 -0
- package/dist/src/runners/wakeup.d.ts +37 -0
- package/dist/src/runners/wakeup.d.ts.map +1 -0
- package/dist/src/runners/wakeup.js +355 -0
- package/dist/src/runners/wakeup.js.map +1 -0
- package/dist/src/utils/validation.d.ts +22 -0
- package/dist/src/utils/validation.d.ts.map +1 -0
- package/dist/src/utils/validation.js +50 -0
- package/dist/src/utils/validation.js.map +1 -0
- package/dist/utils/sqlite.d.ts +17 -0
- package/dist/utils/sqlite.d.ts.map +1 -0
- package/dist/utils/sqlite.js +27 -0
- package/dist/utils/sqlite.js.map +1 -0
- package/dist/utils/storage-cache.d.ts +33 -0
- package/dist/utils/storage-cache.d.ts.map +1 -0
- package/dist/utils/storage-cache.js +81 -0
- package/dist/utils/storage-cache.js.map +1 -0
- package/dist/utils/validation.d.ts +22 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +51 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +39 -0
- package/src/index.ts +199 -0
- package/src/routes/activity.ts +302 -0
- package/src/routes/config.ts +723 -0
- package/src/routes/credit-alerts.ts +73 -0
- package/src/routes/health.ts +219 -0
- package/src/routes/incidents.ts +131 -0
- package/src/routes/projects.ts +854 -0
- package/src/routes/runners.ts +357 -0
- package/src/routes/skills.ts +127 -0
- package/src/routes/storage.ts +108 -0
- package/src/routes/tasks.ts +1372 -0
- package/src/utils/sqlite.ts +36 -0
- package/src/utils/storage-cache.ts +107 -0
- package/src/utils/validation.ts +61 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runner daemon - background process that executes tasks
|
|
3
|
+
*/
|
|
4
|
+
export type RunnerStatus = 'idle' | 'running' | 'stopping';
|
|
5
|
+
export interface Runner {
|
|
6
|
+
id: string;
|
|
7
|
+
status: RunnerStatus;
|
|
8
|
+
pid: number | null;
|
|
9
|
+
project_path: string | null;
|
|
10
|
+
section_id: string | null;
|
|
11
|
+
current_task_id: string | null;
|
|
12
|
+
started_at: string | null;
|
|
13
|
+
heartbeat_at: string;
|
|
14
|
+
}
|
|
15
|
+
export interface DaemonOptions {
|
|
16
|
+
projectPath?: string;
|
|
17
|
+
sectionId?: string;
|
|
18
|
+
onTaskStart?: (taskId: string) => void;
|
|
19
|
+
onTaskComplete?: (taskId: string) => void;
|
|
20
|
+
onShutdown?: () => void;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Register a new runner in the database
|
|
24
|
+
*/
|
|
25
|
+
export declare function registerRunner(projectPath?: string, sectionId?: string): {
|
|
26
|
+
runnerId: string;
|
|
27
|
+
close: () => void;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Update runner status
|
|
31
|
+
*/
|
|
32
|
+
export declare function updateRunnerStatus(runnerId: string, status: RunnerStatus, currentTaskId?: string | null): void;
|
|
33
|
+
/**
|
|
34
|
+
* Update runner heartbeat timestamp
|
|
35
|
+
*/
|
|
36
|
+
export declare function updateRunnerHeartbeat(runnerId: string): void;
|
|
37
|
+
/**
|
|
38
|
+
* Sync project stats to global database
|
|
39
|
+
* Called during heartbeat to cache stats for API/WebUI
|
|
40
|
+
*/
|
|
41
|
+
export declare function syncProjectStats(projectPath: string): void;
|
|
42
|
+
/**
|
|
43
|
+
* Update runner's current task
|
|
44
|
+
*/
|
|
45
|
+
export declare function updateRunnerCurrentTask(runnerId: string, taskId: string | null): void;
|
|
46
|
+
/**
|
|
47
|
+
* Remove runner from database
|
|
48
|
+
*/
|
|
49
|
+
export declare function unregisterRunner(runnerId: string): void;
|
|
50
|
+
/**
|
|
51
|
+
* Get all runners
|
|
52
|
+
*/
|
|
53
|
+
export declare function listRunners(): Runner[];
|
|
54
|
+
/**
|
|
55
|
+
* Get runner by ID
|
|
56
|
+
*/
|
|
57
|
+
export declare function getRunner(runnerId: string): Runner | null;
|
|
58
|
+
/**
|
|
59
|
+
* Start the runner daemon
|
|
60
|
+
* This is the main entry point for background task processing
|
|
61
|
+
*/
|
|
62
|
+
export declare function startDaemon(options?: DaemonOptions): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Check if daemon can be started (no existing lock or project-specific runner)
|
|
65
|
+
*/
|
|
66
|
+
export declare function canStartDaemon(projectPath?: string): {
|
|
67
|
+
canStart: boolean;
|
|
68
|
+
reason?: string;
|
|
69
|
+
existingPid?: number;
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=daemon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../../../../src/runners/daemon.ts"],"names":[],"mappings":"AAAA;;GAEG;AAYH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC;AAE3D,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,YAAY,CAAC;IACrB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,WAAW,CAAC,EAAE,MAAM,EACpB,SAAS,CAAC,EAAE,MAAM,GACjB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,IAAI,CAAA;CAAE,CAUzC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,YAAY,EACpB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,GAC5B,IAAI,CAiBN;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAS5D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAc1D;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GAAG,IAAI,GACpB,IAAI,CASN;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAOvD;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,MAAM,EAAE,CAOtC;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASzD;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgG5E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG;IACpD,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAwBA"}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runner daemon - background process that executes tasks
|
|
3
|
+
*/
|
|
4
|
+
import { resolve } from 'node:path';
|
|
5
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
6
|
+
import { openGlobalDatabase } from './global-db.js';
|
|
7
|
+
import { createHeartbeatManager } from './heartbeat.js';
|
|
8
|
+
import { hasActiveRunnerForProject } from './wakeup.js';
|
|
9
|
+
import { runOrchestratorLoop } from './orchestrator-loop.js';
|
|
10
|
+
import { updateProjectStats, getRegisteredProject } from './projects.js';
|
|
11
|
+
import { openDatabase } from '../database/connection.js';
|
|
12
|
+
import { getTaskCountsByStatus } from '../database/queries.js';
|
|
13
|
+
/**
|
|
14
|
+
* Register a new runner in the database
|
|
15
|
+
*/
|
|
16
|
+
export function registerRunner(projectPath, sectionId) {
|
|
17
|
+
const { db, close } = openGlobalDatabase();
|
|
18
|
+
const runnerId = uuidv4();
|
|
19
|
+
db.prepare(`INSERT INTO runners (id, status, pid, project_path, section_id, started_at, heartbeat_at)
|
|
20
|
+
VALUES (?, 'idle', ?, ?, ?, datetime('now'), datetime('now'))`).run(runnerId, process.pid, projectPath ?? null, sectionId ?? null);
|
|
21
|
+
return { runnerId, close };
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Update runner status
|
|
25
|
+
*/
|
|
26
|
+
export function updateRunnerStatus(runnerId, status, currentTaskId) {
|
|
27
|
+
const { db, close } = openGlobalDatabase();
|
|
28
|
+
try {
|
|
29
|
+
if (currentTaskId !== undefined) {
|
|
30
|
+
db.prepare(`UPDATE runners SET status = ?, current_task_id = ?, heartbeat_at = datetime('now')
|
|
31
|
+
WHERE id = ?`).run(status, currentTaskId, runnerId);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
db.prepare(`UPDATE runners SET status = ?, heartbeat_at = datetime('now')
|
|
35
|
+
WHERE id = ?`).run(status, runnerId);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
finally {
|
|
39
|
+
close();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Update runner heartbeat timestamp
|
|
44
|
+
*/
|
|
45
|
+
export function updateRunnerHeartbeat(runnerId) {
|
|
46
|
+
const { db, close } = openGlobalDatabase();
|
|
47
|
+
try {
|
|
48
|
+
db.prepare(`UPDATE runners SET heartbeat_at = datetime('now') WHERE id = ?`).run(runnerId);
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
close();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Sync project stats to global database
|
|
56
|
+
* Called during heartbeat to cache stats for API/WebUI
|
|
57
|
+
*/
|
|
58
|
+
export function syncProjectStats(projectPath) {
|
|
59
|
+
try {
|
|
60
|
+
const { db, close } = openDatabase(projectPath);
|
|
61
|
+
try {
|
|
62
|
+
const stats = getTaskCountsByStatus(db);
|
|
63
|
+
updateProjectStats(projectPath, stats);
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
close();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
// Silently fail if project DB is unavailable
|
|
71
|
+
// (e.g., during initialization or corruption)
|
|
72
|
+
console.error(`Failed to sync stats for ${projectPath}:`, error);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Update runner's current task
|
|
77
|
+
*/
|
|
78
|
+
export function updateRunnerCurrentTask(runnerId, taskId) {
|
|
79
|
+
const { db, close } = openGlobalDatabase();
|
|
80
|
+
try {
|
|
81
|
+
db.prepare(`UPDATE runners SET current_task_id = ?, heartbeat_at = datetime('now') WHERE id = ?`).run(taskId, runnerId);
|
|
82
|
+
}
|
|
83
|
+
finally {
|
|
84
|
+
close();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Remove runner from database
|
|
89
|
+
*/
|
|
90
|
+
export function unregisterRunner(runnerId) {
|
|
91
|
+
const { db, close } = openGlobalDatabase();
|
|
92
|
+
try {
|
|
93
|
+
db.prepare('DELETE FROM runners WHERE id = ?').run(runnerId);
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
close();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Get all runners
|
|
101
|
+
*/
|
|
102
|
+
export function listRunners() {
|
|
103
|
+
const { db, close } = openGlobalDatabase();
|
|
104
|
+
try {
|
|
105
|
+
return db.prepare('SELECT * FROM runners').all();
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
close();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Get runner by ID
|
|
113
|
+
*/
|
|
114
|
+
export function getRunner(runnerId) {
|
|
115
|
+
const { db, close } = openGlobalDatabase();
|
|
116
|
+
try {
|
|
117
|
+
return db
|
|
118
|
+
.prepare('SELECT * FROM runners WHERE id = ?')
|
|
119
|
+
.get(runnerId);
|
|
120
|
+
}
|
|
121
|
+
finally {
|
|
122
|
+
close();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Start the runner daemon
|
|
127
|
+
* This is the main entry point for background task processing
|
|
128
|
+
*/
|
|
129
|
+
export async function startDaemon(options = {}) {
|
|
130
|
+
// Compute effective project path - default to cwd if not specified
|
|
131
|
+
// Always resolve to absolute path for consistent tracking
|
|
132
|
+
const effectiveProjectPath = resolve(options.projectPath ?? process.cwd());
|
|
133
|
+
// Check if project is disabled in the global registry
|
|
134
|
+
const registeredProject = getRegisteredProject(effectiveProjectPath);
|
|
135
|
+
if (registeredProject && !registeredProject.enabled) {
|
|
136
|
+
console.error(`Project is disabled: ${effectiveProjectPath}`);
|
|
137
|
+
console.error('Run "steroids projects enable" to enable it.');
|
|
138
|
+
process.exit(7); // Project disabled exit code
|
|
139
|
+
}
|
|
140
|
+
// Check if there's already an active runner for this specific project
|
|
141
|
+
if (hasActiveRunnerForProject(effectiveProjectPath)) {
|
|
142
|
+
console.error(`A runner is already active for project: ${effectiveProjectPath}`);
|
|
143
|
+
console.error('Only one runner per project is allowed.');
|
|
144
|
+
process.exit(6); // Resource locked exit code
|
|
145
|
+
}
|
|
146
|
+
// Register runner with effective project path and section ID
|
|
147
|
+
// Note: Per-project isolation is enforced by hasActiveRunnerForProject() above
|
|
148
|
+
const { runnerId, close: closeDb } = registerRunner(effectiveProjectPath, options.sectionId);
|
|
149
|
+
const { db } = openGlobalDatabase();
|
|
150
|
+
// Start heartbeat
|
|
151
|
+
const heartbeat = createHeartbeatManager(db, runnerId);
|
|
152
|
+
heartbeat.start();
|
|
153
|
+
let isShuttingDown = false;
|
|
154
|
+
// Graceful shutdown handler
|
|
155
|
+
const shutdown = async (signal) => {
|
|
156
|
+
if (isShuttingDown)
|
|
157
|
+
return;
|
|
158
|
+
isShuttingDown = true;
|
|
159
|
+
console.log(`\nReceived ${signal}, shutting down gracefully...`);
|
|
160
|
+
// Stop heartbeat
|
|
161
|
+
heartbeat.stop();
|
|
162
|
+
// Update status
|
|
163
|
+
updateRunnerStatus(runnerId, 'stopping');
|
|
164
|
+
// Call shutdown callback
|
|
165
|
+
if (options.onShutdown) {
|
|
166
|
+
options.onShutdown();
|
|
167
|
+
}
|
|
168
|
+
// Clean up
|
|
169
|
+
unregisterRunner(runnerId);
|
|
170
|
+
closeDb();
|
|
171
|
+
console.log('Runner stopped.');
|
|
172
|
+
process.exit(0);
|
|
173
|
+
};
|
|
174
|
+
// Register signal handlers
|
|
175
|
+
process.on('SIGTERM', () => shutdown('SIGTERM'));
|
|
176
|
+
process.on('SIGINT', () => shutdown('SIGINT'));
|
|
177
|
+
console.log(`Runner started (ID: ${runnerId}, PID: ${process.pid})`);
|
|
178
|
+
updateRunnerStatus(runnerId, 'running');
|
|
179
|
+
// Track if shutdown was requested
|
|
180
|
+
let shutdownRequested = false;
|
|
181
|
+
// Run the orchestrator loop
|
|
182
|
+
try {
|
|
183
|
+
await runOrchestratorLoop({
|
|
184
|
+
projectPath: effectiveProjectPath,
|
|
185
|
+
sectionId: options.sectionId,
|
|
186
|
+
runnerId, // Pass runner ID for activity logging
|
|
187
|
+
shouldStop: () => shutdownRequested,
|
|
188
|
+
onIteration: (iteration) => {
|
|
189
|
+
// Update heartbeat on each iteration
|
|
190
|
+
updateRunnerHeartbeat(runnerId);
|
|
191
|
+
// Sync project stats to global DB for API/WebUI access
|
|
192
|
+
syncProjectStats(effectiveProjectPath);
|
|
193
|
+
},
|
|
194
|
+
onTaskStart: (taskId) => {
|
|
195
|
+
updateRunnerCurrentTask(runnerId, taskId);
|
|
196
|
+
},
|
|
197
|
+
onTaskComplete: () => {
|
|
198
|
+
updateRunnerCurrentTask(runnerId, null);
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
console.error('Loop error:', error);
|
|
204
|
+
}
|
|
205
|
+
// Cleanup and exit
|
|
206
|
+
shutdown('completed');
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Check if daemon can be started (no existing lock or project-specific runner)
|
|
210
|
+
*/
|
|
211
|
+
export function canStartDaemon(projectPath) {
|
|
212
|
+
// Default to cwd if not specified for consistent per-project tracking
|
|
213
|
+
// Always resolve to absolute path
|
|
214
|
+
const effectivePath = resolve(projectPath ?? process.cwd());
|
|
215
|
+
// Check if project is disabled
|
|
216
|
+
const registeredProject = getRegisteredProject(effectivePath);
|
|
217
|
+
if (registeredProject && !registeredProject.enabled) {
|
|
218
|
+
return {
|
|
219
|
+
canStart: false,
|
|
220
|
+
reason: `Project is disabled: ${effectivePath}. Run "steroids projects enable" to enable it.`,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
// Check for project-specific runner (one runner per project allowed)
|
|
224
|
+
if (hasActiveRunnerForProject(effectivePath)) {
|
|
225
|
+
return {
|
|
226
|
+
canStart: false,
|
|
227
|
+
reason: `A runner is already active for project: ${effectivePath}`,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
// Multiple projects can run in parallel - no global lock check
|
|
231
|
+
return { canStart: true };
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=daemon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../../../src/runners/daemon.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAuB/D;;GAEG;AACH,MAAM,UAAU,cAAc,CAC5B,WAAoB,EACpB,SAAkB;IAElB,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,kBAAkB,EAAE,CAAC;IAC3C,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC;IAE1B,EAAE,CAAC,OAAO,CACR;mEAC+D,CAChE,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG,EAAE,WAAW,IAAI,IAAI,EAAE,SAAS,IAAI,IAAI,CAAC,CAAC;IAErE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAC7B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAChC,QAAgB,EAChB,MAAoB,EACpB,aAA6B;IAE7B,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,kBAAkB,EAAE,CAAC;IAC3C,IAAI,CAAC;QACH,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;YAChC,EAAE,CAAC,OAAO,CACR;sBACc,CACf,CAAC,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,EAAE,CAAC,OAAO,CACR;sBACc,CACf,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;YAAS,CAAC;QACT,KAAK,EAAE,CAAC;IACV,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAgB;IACpD,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,kBAAkB,EAAE,CAAC;IAC3C,IAAI,CAAC;QACH,EAAE,CAAC,OAAO,CACR,gEAAgE,CACjE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAClB,CAAC;YAAS,CAAC;QACT,KAAK,EAAE,CAAC;IACV,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,WAAmB;IAClD,IAAI,CAAC;QACH,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;QAChD,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,qBAAqB,CAAC,EAAE,CAAC,CAAC;YACxC,kBAAkB,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;QACzC,CAAC;gBAAS,CAAC;YACT,KAAK,EAAE,CAAC;QACV,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,6CAA6C;QAC7C,8CAA8C;QAC9C,OAAO,CAAC,KAAK,CAAC,4BAA4B,WAAW,GAAG,EAAE,KAAK,CAAC,CAAC;IACnE,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CACrC,QAAgB,EAChB,MAAqB;IAErB,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,kBAAkB,EAAE,CAAC;IAC3C,IAAI,CAAC;QACH,EAAE,CAAC,OAAO,CACR,qFAAqF,CACtF,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC1B,CAAC;YAAS,CAAC;QACT,KAAK,EAAE,CAAC;IACV,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,kBAAkB,EAAE,CAAC;IAC3C,IAAI,CAAC;QACH,EAAE,CAAC,OAAO,CAAC,kCAAkC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC/D,CAAC;YAAS,CAAC;QACT,KAAK,EAAE,CAAC;IACV,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW;IACzB,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,kBAAkB,EAAE,CAAC;IAC3C,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC,GAAG,EAAc,CAAC;IAC/D,CAAC;YAAS,CAAC;QACT,KAAK,EAAE,CAAC;IACV,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,QAAgB;IACxC,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,kBAAkB,EAAE,CAAC;IAC3C,IAAI,CAAC;QACH,OAAO,EAAE;aACN,OAAO,CAAC,oCAAoC,CAAC;aAC7C,GAAG,CAAC,QAAQ,CAAkB,CAAC;IACpC,CAAC;YAAS,CAAC;QACT,KAAK,EAAE,CAAC;IACV,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,UAAyB,EAAE;IAC3D,mEAAmE;IACnE,0DAA0D;IAC1D,MAAM,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAE3E,sDAAsD;IACtD,MAAM,iBAAiB,GAAG,oBAAoB,CAAC,oBAAoB,CAAC,CAAC;IACrE,IAAI,iBAAiB,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE,CAAC;QACpD,OAAO,CAAC,KAAK,CAAC,wBAAwB,oBAAoB,EAAE,CAAC,CAAC;QAC9D,OAAO,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,6BAA6B;IAChD,CAAC;IAED,sEAAsE;IACtE,IAAI,yBAAyB,CAAC,oBAAoB,CAAC,EAAE,CAAC;QACpD,OAAO,CAAC,KAAK,CACX,2CAA2C,oBAAoB,EAAE,CAClE,CAAC;QACF,OAAO,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;QACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,4BAA4B;IAC/C,CAAC;IAED,6DAA6D;IAC7D,+EAA+E;IAC/E,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,cAAc,CAAC,oBAAoB,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IAC7F,MAAM,EAAE,EAAE,EAAE,GAAG,kBAAkB,EAAE,CAAC;IAEpC,kBAAkB;IAClB,MAAM,SAAS,GAAG,sBAAsB,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;IACvD,SAAS,CAAC,KAAK,EAAE,CAAC;IAElB,IAAI,cAAc,GAAG,KAAK,CAAC;IAE3B,4BAA4B;IAC5B,MAAM,QAAQ,GAAG,KAAK,EAAE,MAAc,EAAiB,EAAE;QACvD,IAAI,cAAc;YAAE,OAAO;QAC3B,cAAc,GAAG,IAAI,CAAC;QAEtB,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,+BAA+B,CAAC,CAAC;QAEjE,iBAAiB;QACjB,SAAS,CAAC,IAAI,EAAE,CAAC;QAEjB,gBAAgB;QAChB,kBAAkB,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAEzC,yBAAyB;QACzB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;YACvB,OAAO,CAAC,UAAU,EAAE,CAAC;QACvB,CAAC;QAED,WAAW;QACX,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAC3B,OAAO,EAAE,CAAC;QAEV,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;QAC/B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IAEF,2BAA2B;IAC3B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;IACjD,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IAE/C,OAAO,CAAC,GAAG,CAAC,uBAAuB,QAAQ,UAAU,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC;IACrE,kBAAkB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAExC,kCAAkC;IAClC,IAAI,iBAAiB,GAAG,KAAK,CAAC;IAE9B,4BAA4B;IAC5B,IAAI,CAAC;QACH,MAAM,mBAAmB,CAAC;YACxB,WAAW,EAAE,oBAAoB;YACjC,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,QAAQ,EAAG,sCAAsC;YACjD,UAAU,EAAE,GAAG,EAAE,CAAC,iBAAiB;YACnC,WAAW,EAAE,CAAC,SAAS,EAAE,EAAE;gBACzB,qCAAqC;gBACrC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;gBAEhC,uDAAuD;gBACvD,gBAAgB,CAAC,oBAAoB,CAAC,CAAC;YACzC,CAAC;YACD,WAAW,EAAE,CAAC,MAAM,EAAE,EAAE;gBACtB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAC5C,CAAC;YACD,cAAc,EAAE,GAAG,EAAE;gBACnB,uBAAuB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAC1C,CAAC;SACF,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;IACtC,CAAC;IAED,mBAAmB;IACnB,QAAQ,CAAC,WAAW,CAAC,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,WAAoB;IAKjD,sEAAsE;IACtE,kCAAkC;IAClC,MAAM,aAAa,GAAG,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAE5D,+BAA+B;IAC/B,MAAM,iBAAiB,GAAG,oBAAoB,CAAC,aAAa,CAAC,CAAC;IAC9D,IAAI,iBAAiB,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE,CAAC;QACpD,OAAO;YACL,QAAQ,EAAE,KAAK;YACf,MAAM,EAAE,wBAAwB,aAAa,gDAAgD;SAC9F,CAAC;IACJ,CAAC;IAED,qEAAqE;IACrE,IAAI,yBAAyB,CAAC,aAAa,CAAC,EAAE,CAAC;QAC7C,OAAO;YACL,QAAQ,EAAE,KAAK;YACf,MAAM,EAAE,2CAA2C,aAAa,EAAE;SACnE,CAAC;IACJ,CAAC;IAED,+DAA+D;IAC/D,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global database for runner state
|
|
3
|
+
* Located at ~/.steroids/steroids.db (user home, not project)
|
|
4
|
+
*/
|
|
5
|
+
import Database from 'better-sqlite3';
|
|
6
|
+
export interface GlobalDatabaseConnection {
|
|
7
|
+
db: Database.Database;
|
|
8
|
+
close: () => void;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Get the path to the global steroids directory
|
|
12
|
+
*/
|
|
13
|
+
export declare function getGlobalSteroidsDir(): string;
|
|
14
|
+
/**
|
|
15
|
+
* Get the path to the global database
|
|
16
|
+
*/
|
|
17
|
+
export declare function getGlobalDbPath(): string;
|
|
18
|
+
/**
|
|
19
|
+
* Check if global database exists
|
|
20
|
+
*/
|
|
21
|
+
export declare function isGlobalDbInitialized(): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Initialize and open the global database
|
|
24
|
+
* Creates it if it doesn't exist
|
|
25
|
+
*/
|
|
26
|
+
export declare function openGlobalDatabase(): GlobalDatabaseConnection;
|
|
27
|
+
/**
|
|
28
|
+
* Get global schema version
|
|
29
|
+
*/
|
|
30
|
+
export declare function getGlobalSchemaVersion(db: Database.Database): string | null;
|
|
31
|
+
//# sourceMappingURL=global-db.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global-db.d.ts","sourceRoot":"","sources":["../../../../src/runners/global-db.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAQtC,MAAM,WAAW,wBAAwB;IACvC,EAAE,EAAE,QAAQ,CAAC,QAAQ,CAAC;IACtB,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAuGD;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAE/C;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,wBAAwB,CAyG7D;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,MAAM,GAAG,IAAI,CAS3E"}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global database for runner state
|
|
3
|
+
* Located at ~/.steroids/steroids.db (user home, not project)
|
|
4
|
+
*/
|
|
5
|
+
import Database from 'better-sqlite3';
|
|
6
|
+
import { existsSync, mkdirSync } from 'node:fs';
|
|
7
|
+
import { join } from 'node:path';
|
|
8
|
+
import { homedir } from 'node:os';
|
|
9
|
+
const STEROIDS_DIR = '.steroids';
|
|
10
|
+
const DB_NAME = 'steroids.db';
|
|
11
|
+
/**
|
|
12
|
+
* Schema for global database (runners and locks)
|
|
13
|
+
*/
|
|
14
|
+
const GLOBAL_SCHEMA_SQL = `
|
|
15
|
+
-- Runners table for tracking runner state
|
|
16
|
+
CREATE TABLE IF NOT EXISTS runners (
|
|
17
|
+
id TEXT PRIMARY KEY,
|
|
18
|
+
status TEXT NOT NULL DEFAULT 'idle',
|
|
19
|
+
pid INTEGER,
|
|
20
|
+
project_path TEXT,
|
|
21
|
+
current_task_id TEXT,
|
|
22
|
+
started_at TEXT,
|
|
23
|
+
heartbeat_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
-- Runner lock for singleton enforcement
|
|
27
|
+
-- Only one row allowed (id = 1)
|
|
28
|
+
CREATE TABLE IF NOT EXISTS runner_lock (
|
|
29
|
+
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
30
|
+
runner_id TEXT NOT NULL,
|
|
31
|
+
acquired_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
-- Schema metadata
|
|
35
|
+
CREATE TABLE IF NOT EXISTS _global_schema (
|
|
36
|
+
key TEXT PRIMARY KEY,
|
|
37
|
+
value TEXT NOT NULL
|
|
38
|
+
);
|
|
39
|
+
`;
|
|
40
|
+
/**
|
|
41
|
+
* Schema upgrade from version 1 to version 2: Add projects table
|
|
42
|
+
*/
|
|
43
|
+
const GLOBAL_SCHEMA_V2_SQL = `
|
|
44
|
+
-- Projects table for tracking registered projects
|
|
45
|
+
CREATE TABLE IF NOT EXISTS projects (
|
|
46
|
+
path TEXT PRIMARY KEY,
|
|
47
|
+
name TEXT,
|
|
48
|
+
registered_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
49
|
+
last_seen_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
50
|
+
enabled INTEGER NOT NULL DEFAULT 1
|
|
51
|
+
);
|
|
52
|
+
`;
|
|
53
|
+
/**
|
|
54
|
+
* Schema upgrade from version 2 to version 3: Add stats columns to projects table
|
|
55
|
+
*/
|
|
56
|
+
const GLOBAL_SCHEMA_V3_SQL = `
|
|
57
|
+
-- Add task stats columns (for API/WebUI display without accessing project DBs)
|
|
58
|
+
ALTER TABLE projects ADD COLUMN pending_count INTEGER DEFAULT 0;
|
|
59
|
+
ALTER TABLE projects ADD COLUMN in_progress_count INTEGER DEFAULT 0;
|
|
60
|
+
ALTER TABLE projects ADD COLUMN review_count INTEGER DEFAULT 0;
|
|
61
|
+
ALTER TABLE projects ADD COLUMN completed_count INTEGER DEFAULT 0;
|
|
62
|
+
ALTER TABLE projects ADD COLUMN stats_updated_at TEXT;
|
|
63
|
+
`;
|
|
64
|
+
/**
|
|
65
|
+
* Schema upgrade from version 3 to version 4: Add section_id to runners table
|
|
66
|
+
*/
|
|
67
|
+
const GLOBAL_SCHEMA_V4_SQL = `
|
|
68
|
+
-- Add section_id column to runners for section focus feature
|
|
69
|
+
ALTER TABLE runners ADD COLUMN section_id TEXT;
|
|
70
|
+
`;
|
|
71
|
+
/**
|
|
72
|
+
* Schema upgrade from version 4 to version 5: Add activity_log table
|
|
73
|
+
*/
|
|
74
|
+
const GLOBAL_SCHEMA_V5_SQL = `
|
|
75
|
+
-- Activity log for tracking task completions across all projects
|
|
76
|
+
CREATE TABLE IF NOT EXISTS activity_log (
|
|
77
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
78
|
+
project_path TEXT NOT NULL,
|
|
79
|
+
runner_id TEXT NOT NULL,
|
|
80
|
+
task_id TEXT NOT NULL,
|
|
81
|
+
task_title TEXT NOT NULL,
|
|
82
|
+
section_name TEXT,
|
|
83
|
+
final_status TEXT NOT NULL,
|
|
84
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
85
|
+
);
|
|
86
|
+
CREATE INDEX IF NOT EXISTS idx_activity_log_created_at ON activity_log(created_at);
|
|
87
|
+
CREATE INDEX IF NOT EXISTS idx_activity_log_project ON activity_log(project_path);
|
|
88
|
+
`;
|
|
89
|
+
/**
|
|
90
|
+
* Schema upgrade from version 5 to version 6: Add commit_message to activity_log
|
|
91
|
+
*/
|
|
92
|
+
const GLOBAL_SCHEMA_V6_SQL = `
|
|
93
|
+
-- Add commit_message column to activity_log for storing coder's final message
|
|
94
|
+
ALTER TABLE activity_log ADD COLUMN commit_message TEXT;
|
|
95
|
+
`;
|
|
96
|
+
/**
|
|
97
|
+
* Schema upgrade from version 6 to version 7: Add commit_sha to activity_log
|
|
98
|
+
*/
|
|
99
|
+
const GLOBAL_SCHEMA_V7_SQL = `
|
|
100
|
+
-- Add commit_sha column to activity_log for GitHub links
|
|
101
|
+
ALTER TABLE activity_log ADD COLUMN commit_sha TEXT;
|
|
102
|
+
`;
|
|
103
|
+
const GLOBAL_SCHEMA_VERSION = '7';
|
|
104
|
+
/**
|
|
105
|
+
* Get the path to the global steroids directory
|
|
106
|
+
*/
|
|
107
|
+
export function getGlobalSteroidsDir() {
|
|
108
|
+
return join(homedir(), STEROIDS_DIR);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Get the path to the global database
|
|
112
|
+
*/
|
|
113
|
+
export function getGlobalDbPath() {
|
|
114
|
+
return join(getGlobalSteroidsDir(), DB_NAME);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Check if global database exists
|
|
118
|
+
*/
|
|
119
|
+
export function isGlobalDbInitialized() {
|
|
120
|
+
return existsSync(getGlobalDbPath());
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Initialize and open the global database
|
|
124
|
+
* Creates it if it doesn't exist
|
|
125
|
+
*/
|
|
126
|
+
export function openGlobalDatabase() {
|
|
127
|
+
const dbPath = getGlobalDbPath();
|
|
128
|
+
const steroidsDir = getGlobalSteroidsDir();
|
|
129
|
+
// Create ~/.steroids directory if it doesn't exist
|
|
130
|
+
if (!existsSync(steroidsDir)) {
|
|
131
|
+
mkdirSync(steroidsDir, { recursive: true });
|
|
132
|
+
}
|
|
133
|
+
const db = new Database(dbPath);
|
|
134
|
+
// Configure SQLite for optimal performance and safety
|
|
135
|
+
db.pragma('journal_mode = WAL');
|
|
136
|
+
db.pragma('busy_timeout = 5000');
|
|
137
|
+
// Create base schema (IF NOT EXISTS makes this idempotent)
|
|
138
|
+
db.exec(GLOBAL_SCHEMA_SQL);
|
|
139
|
+
// Get current version
|
|
140
|
+
const versionRow = db
|
|
141
|
+
.prepare('SELECT value FROM _global_schema WHERE key = ?')
|
|
142
|
+
.get('version');
|
|
143
|
+
const currentVersion = versionRow?.value;
|
|
144
|
+
if (!currentVersion) {
|
|
145
|
+
// Fresh database - apply all schemas and set to latest version
|
|
146
|
+
db.exec(GLOBAL_SCHEMA_V2_SQL);
|
|
147
|
+
db.exec(GLOBAL_SCHEMA_V3_SQL);
|
|
148
|
+
db.exec(GLOBAL_SCHEMA_V4_SQL);
|
|
149
|
+
db.exec(GLOBAL_SCHEMA_V5_SQL);
|
|
150
|
+
db.exec(GLOBAL_SCHEMA_V6_SQL);
|
|
151
|
+
db.exec(GLOBAL_SCHEMA_V7_SQL);
|
|
152
|
+
db.prepare('INSERT INTO _global_schema (key, value) VALUES (?, ?)').run('version', GLOBAL_SCHEMA_VERSION);
|
|
153
|
+
db.prepare('INSERT INTO _global_schema (key, value) VALUES (?, ?)').run('created_at', new Date().toISOString());
|
|
154
|
+
}
|
|
155
|
+
else if (currentVersion === '1') {
|
|
156
|
+
// Upgrade from version 1 to latest
|
|
157
|
+
db.exec(GLOBAL_SCHEMA_V2_SQL);
|
|
158
|
+
db.exec(GLOBAL_SCHEMA_V3_SQL);
|
|
159
|
+
db.exec(GLOBAL_SCHEMA_V4_SQL);
|
|
160
|
+
db.exec(GLOBAL_SCHEMA_V5_SQL);
|
|
161
|
+
db.exec(GLOBAL_SCHEMA_V6_SQL);
|
|
162
|
+
db.exec(GLOBAL_SCHEMA_V7_SQL);
|
|
163
|
+
db.prepare('UPDATE _global_schema SET value = ? WHERE key = ?').run(GLOBAL_SCHEMA_VERSION, 'version');
|
|
164
|
+
}
|
|
165
|
+
else if (currentVersion === '2') {
|
|
166
|
+
// Upgrade from version 2 to latest
|
|
167
|
+
db.exec(GLOBAL_SCHEMA_V3_SQL);
|
|
168
|
+
db.exec(GLOBAL_SCHEMA_V4_SQL);
|
|
169
|
+
db.exec(GLOBAL_SCHEMA_V5_SQL);
|
|
170
|
+
db.exec(GLOBAL_SCHEMA_V6_SQL);
|
|
171
|
+
db.exec(GLOBAL_SCHEMA_V7_SQL);
|
|
172
|
+
db.prepare('UPDATE _global_schema SET value = ? WHERE key = ?').run(GLOBAL_SCHEMA_VERSION, 'version');
|
|
173
|
+
}
|
|
174
|
+
else if (currentVersion === '3') {
|
|
175
|
+
// Upgrade from version 3 to latest
|
|
176
|
+
db.exec(GLOBAL_SCHEMA_V4_SQL);
|
|
177
|
+
db.exec(GLOBAL_SCHEMA_V5_SQL);
|
|
178
|
+
db.exec(GLOBAL_SCHEMA_V6_SQL);
|
|
179
|
+
db.exec(GLOBAL_SCHEMA_V7_SQL);
|
|
180
|
+
db.prepare('UPDATE _global_schema SET value = ? WHERE key = ?').run(GLOBAL_SCHEMA_VERSION, 'version');
|
|
181
|
+
}
|
|
182
|
+
else if (currentVersion === '4') {
|
|
183
|
+
// Upgrade from version 4 to latest
|
|
184
|
+
db.exec(GLOBAL_SCHEMA_V5_SQL);
|
|
185
|
+
db.exec(GLOBAL_SCHEMA_V6_SQL);
|
|
186
|
+
db.exec(GLOBAL_SCHEMA_V7_SQL);
|
|
187
|
+
db.prepare('UPDATE _global_schema SET value = ? WHERE key = ?').run(GLOBAL_SCHEMA_VERSION, 'version');
|
|
188
|
+
}
|
|
189
|
+
else if (currentVersion === '5') {
|
|
190
|
+
// Upgrade from version 5 to latest
|
|
191
|
+
db.exec(GLOBAL_SCHEMA_V6_SQL);
|
|
192
|
+
db.exec(GLOBAL_SCHEMA_V7_SQL);
|
|
193
|
+
db.prepare('UPDATE _global_schema SET value = ? WHERE key = ?').run(GLOBAL_SCHEMA_VERSION, 'version');
|
|
194
|
+
}
|
|
195
|
+
else if (currentVersion === '6') {
|
|
196
|
+
// Upgrade from version 6 to version 7
|
|
197
|
+
db.exec(GLOBAL_SCHEMA_V7_SQL);
|
|
198
|
+
db.prepare('UPDATE _global_schema SET value = ? WHERE key = ?').run(GLOBAL_SCHEMA_VERSION, 'version');
|
|
199
|
+
}
|
|
200
|
+
// Future upgrades would be handled here with additional conditions
|
|
201
|
+
return {
|
|
202
|
+
db,
|
|
203
|
+
close: () => db.close(),
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Get global schema version
|
|
208
|
+
*/
|
|
209
|
+
export function getGlobalSchemaVersion(db) {
|
|
210
|
+
try {
|
|
211
|
+
const row = db
|
|
212
|
+
.prepare('SELECT value FROM _global_schema WHERE key = ?')
|
|
213
|
+
.get('version');
|
|
214
|
+
return row?.value ?? null;
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=global-db.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global-db.js","sourceRoot":"","sources":["../../../../src/runners/global-db.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,MAAM,YAAY,GAAG,WAAW,CAAC;AACjC,MAAM,OAAO,GAAG,aAAa,CAAC;AAO9B;;GAEG;AACH,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;CAyBzB,CAAC;AAEF;;GAEG;AACH,MAAM,oBAAoB,GAAG;;;;;;;;;CAS5B,CAAC;AAEF;;GAEG;AACH,MAAM,oBAAoB,GAAG;;;;;;;CAO5B,CAAC;AAEF;;GAEG;AACH,MAAM,oBAAoB,GAAG;;;CAG5B,CAAC;AAEF;;GAEG;AACH,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;CAc5B,CAAC;AAEF;;GAEG;AACH,MAAM,oBAAoB,GAAG;;;CAG5B,CAAC;AAEF;;GAEG;AACH,MAAM,oBAAoB,GAAG;;;CAG5B,CAAC;AAEF,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAElC;;GAEG;AACH,MAAM,UAAU,oBAAoB;IAClC,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC;AACvC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,IAAI,CAAC,oBAAoB,EAAE,EAAE,OAAO,CAAC,CAAC;AAC/C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB;IACnC,OAAO,UAAU,CAAC,eAAe,EAAE,CAAC,CAAC;AACvC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB;IAChC,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;IACjC,MAAM,WAAW,GAAG,oBAAoB,EAAE,CAAC;IAE3C,mDAAmD;IACnD,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7B,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;IAEhC,sDAAsD;IACtD,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAChC,EAAE,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;IAEjC,2DAA2D;IAC3D,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAE3B,sBAAsB;IACtB,MAAM,UAAU,GAAG,EAAE;SAClB,OAAO,CAAC,gDAAgD,CAAC;SACzD,GAAG,CAAC,SAAS,CAAkC,CAAC;IAEnD,MAAM,cAAc,GAAG,UAAU,EAAE,KAAK,CAAC;IAEzC,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,+DAA+D;QAC/D,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,EAAE,CAAC,OAAO,CAAC,uDAAuD,CAAC,CAAC,GAAG,CACrE,SAAS,EACT,qBAAqB,CACtB,CAAC;QACF,EAAE,CAAC,OAAO,CAAC,uDAAuD,CAAC,CAAC,GAAG,CACrE,YAAY,EACZ,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CACzB,CAAC;IACJ,CAAC;SAAM,IAAI,cAAc,KAAK,GAAG,EAAE,CAAC;QAClC,mCAAmC;QACnC,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,EAAE,CAAC,OAAO,CAAC,mDAAmD,CAAC,CAAC,GAAG,CACjE,qBAAqB,EACrB,SAAS,CACV,CAAC;IACJ,CAAC;SAAM,IAAI,cAAc,KAAK,GAAG,EAAE,CAAC;QAClC,mCAAmC;QACnC,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,EAAE,CAAC,OAAO,CAAC,mDAAmD,CAAC,CAAC,GAAG,CACjE,qBAAqB,EACrB,SAAS,CACV,CAAC;IACJ,CAAC;SAAM,IAAI,cAAc,KAAK,GAAG,EAAE,CAAC;QAClC,mCAAmC;QACnC,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,EAAE,CAAC,OAAO,CAAC,mDAAmD,CAAC,CAAC,GAAG,CACjE,qBAAqB,EACrB,SAAS,CACV,CAAC;IACJ,CAAC;SAAM,IAAI,cAAc,KAAK,GAAG,EAAE,CAAC;QAClC,mCAAmC;QACnC,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,EAAE,CAAC,OAAO,CAAC,mDAAmD,CAAC,CAAC,GAAG,CACjE,qBAAqB,EACrB,SAAS,CACV,CAAC;IACJ,CAAC;SAAM,IAAI,cAAc,KAAK,GAAG,EAAE,CAAC;QAClC,mCAAmC;QACnC,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,EAAE,CAAC,OAAO,CAAC,mDAAmD,CAAC,CAAC,GAAG,CACjE,qBAAqB,EACrB,SAAS,CACV,CAAC;IACJ,CAAC;SAAM,IAAI,cAAc,KAAK,GAAG,EAAE,CAAC;QAClC,sCAAsC;QACtC,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9B,EAAE,CAAC,OAAO,CAAC,mDAAmD,CAAC,CAAC,GAAG,CACjE,qBAAqB,EACrB,SAAS,CACV,CAAC;IACJ,CAAC;IACD,mEAAmE;IAEnE,OAAO;QACL,EAAE;QACF,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE;KACxB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,EAAqB;IAC1D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE;aACX,OAAO,CAAC,gDAAgD,CAAC;aACzD,GAAG,CAAC,SAAS,CAAkC,CAAC;QACnD,OAAO,GAAG,EAAE,KAAK,IAAI,IAAI,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subprocess hang detection
|
|
3
|
+
* Monitors log output and kills processes that appear stuck
|
|
4
|
+
*/
|
|
5
|
+
import type { ChildProcess } from 'node:child_process';
|
|
6
|
+
export interface HangDetectorOptions {
|
|
7
|
+
timeoutMs?: number;
|
|
8
|
+
onHang?: (lastOutput: Date, elapsedMs: number) => void;
|
|
9
|
+
onOutput?: () => void;
|
|
10
|
+
}
|
|
11
|
+
export interface HangDetector {
|
|
12
|
+
recordOutput: () => void;
|
|
13
|
+
isHung: () => boolean;
|
|
14
|
+
getLastOutputTime: () => Date;
|
|
15
|
+
getElapsedSinceOutput: () => number;
|
|
16
|
+
stop: () => void;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Create a hang detector for a subprocess
|
|
20
|
+
* Monitors output activity and detects when a process appears stuck
|
|
21
|
+
*/
|
|
22
|
+
export declare function createHangDetector(options?: HangDetectorOptions): HangDetector;
|
|
23
|
+
/**
|
|
24
|
+
* Attach hang detection to a child process
|
|
25
|
+
* Monitors stdout/stderr for output activity
|
|
26
|
+
*/
|
|
27
|
+
export declare function attachHangDetector(child: ChildProcess, options?: HangDetectorOptions & {
|
|
28
|
+
killOnHang?: boolean;
|
|
29
|
+
}): HangDetector;
|
|
30
|
+
/**
|
|
31
|
+
* Get default hang timeout in milliseconds
|
|
32
|
+
*/
|
|
33
|
+
export declare function getDefaultHangTimeout(): number;
|
|
34
|
+
/**
|
|
35
|
+
* Format elapsed time for display
|
|
36
|
+
*/
|
|
37
|
+
export declare function formatElapsed(ms: number): string;
|
|
38
|
+
//# sourceMappingURL=hang-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hang-detector.d.ts","sourceRoot":"","sources":["../../../../src/runners/hang-detector.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAIvD,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,CAAC,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACvD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,OAAO,CAAC;IACtB,iBAAiB,EAAE,MAAM,IAAI,CAAC;IAC9B,qBAAqB,EAAE,MAAM,MAAM,CAAC;IACpC,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,GAAE,mBAAwB,GAChC,YAAY,CAmDd;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,YAAY,EACnB,OAAO,GAAE,mBAAmB,GAAG;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,GAC3D,YAAY,CA2Dd;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAYhD"}
|