@proletariat/cli 0.3.101 → 0.3.103
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/lib/orchestrate/actions.d.ts +6 -0
- package/dist/lib/orchestrate/actions.js +11 -5
- package/dist/lib/orchestrate/actions.js.map +1 -1
- package/dist/lib/orchestrate/engine.d.ts +19 -39
- package/dist/lib/orchestrate/engine.js +51 -215
- package/dist/lib/orchestrate/engine.js.map +1 -1
- package/dist/lib/orchestrate/poller.d.ts +2 -0
- package/dist/lib/orchestrate/poller.js +26 -9
- package/dist/lib/orchestrate/poller.js.map +1 -1
- package/dist/lib/orchestrate/presets.js +7 -2
- package/dist/lib/orchestrate/presets.js.map +1 -1
- package/dist/lib/orchestrate/types.d.ts +3 -11
- package/dist/lib/orchestrate/types.js +1 -2
- package/dist/lib/orchestrate/types.js.map +1 -1
- package/dist/lib/work-lifecycle/hooks/executor.js +2 -0
- package/dist/lib/work-lifecycle/hooks/executor.js.map +1 -1
- package/dist/lib/work-lifecycle/hooks/index.d.ts +5 -3
- package/dist/lib/work-lifecycle/hooks/index.js +3 -2
- package/dist/lib/work-lifecycle/hooks/index.js.map +1 -1
- package/dist/lib/work-lifecycle/hooks/manager.d.ts +93 -8
- package/dist/lib/work-lifecycle/hooks/manager.js +248 -20
- package/dist/lib/work-lifecycle/hooks/manager.js.map +1 -1
- package/dist/lib/work-lifecycle/hooks/storage.d.ts +1 -0
- package/dist/lib/work-lifecycle/hooks/storage.js +28 -6
- package/dist/lib/work-lifecycle/hooks/storage.js.map +1 -1
- package/dist/lib/work-lifecycle/hooks/types.d.ts +37 -0
- package/dist/lib/work-lifecycle/hooks/types.js +2 -0
- package/dist/lib/work-lifecycle/hooks/types.js.map +1 -1
- package/dist/lib/work-lifecycle/index.d.ts +2 -1
- package/dist/lib/work-lifecycle/index.js +1 -1
- package/dist/lib/work-lifecycle/index.js.map +1 -1
- package/oclif.manifest.json +846 -846
- package/package.json +1 -1
|
@@ -9,6 +9,12 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import type { OrchestrateEventContext, OrchestrateActionResult } from './types.js';
|
|
11
11
|
type ActionHandler = (ctx: OrchestrateEventContext, config?: Record<string, unknown>) => OrchestrateActionResult;
|
|
12
|
+
/**
|
|
13
|
+
* Timeout for actions that spawn agents via `prlt work start`.
|
|
14
|
+
* Container creation + clone + setup regularly exceeds 60s,
|
|
15
|
+
* so we allow 180s to avoid ETIMEDOUT on the execSync call.
|
|
16
|
+
*/
|
|
17
|
+
export declare const AGENT_SPAWN_TIMEOUT_MS = 180000;
|
|
12
18
|
/**
|
|
13
19
|
* Registry of built-in action handlers.
|
|
14
20
|
*/
|
|
@@ -8,6 +8,12 @@
|
|
|
8
8
|
* with manual invocations.
|
|
9
9
|
*/
|
|
10
10
|
import { execSync } from 'node:child_process';
|
|
11
|
+
/**
|
|
12
|
+
* Timeout for actions that spawn agents via `prlt work start`.
|
|
13
|
+
* Container creation + clone + setup regularly exceeds 60s,
|
|
14
|
+
* so we allow 180s to avoid ETIMEDOUT on the execSync call.
|
|
15
|
+
*/
|
|
16
|
+
export const AGENT_SPAWN_TIMEOUT_MS = 180_000;
|
|
11
17
|
/**
|
|
12
18
|
* Merge a PR via `prlt work ship`.
|
|
13
19
|
*/
|
|
@@ -40,7 +46,7 @@ const moveTicket = (ctx, config) => {
|
|
|
40
46
|
if (!ctx.ticket) {
|
|
41
47
|
return { action: 'move-ticket', success: false, error: 'No ticket in context', durationMs: Date.now() - start };
|
|
42
48
|
}
|
|
43
|
-
execSync(`prlt ticket move ${ctx.ticket}
|
|
49
|
+
execSync(`prlt ticket move ${ctx.ticket} "${target}"`, { timeout: 30_000, stdio: 'pipe' });
|
|
44
50
|
return { action: 'move-ticket', success: true, durationMs: Date.now() - start };
|
|
45
51
|
}
|
|
46
52
|
catch (err) {
|
|
@@ -69,7 +75,7 @@ const spawnAgent = (ctx) => {
|
|
|
69
75
|
if (!ctx.ticket) {
|
|
70
76
|
return { action: 'spawn-agent', success: false, error: 'No ticket in context', durationMs: Date.now() - start };
|
|
71
77
|
}
|
|
72
|
-
execSync(`prlt work start ${ctx.ticket} --yes --display background`, { timeout:
|
|
78
|
+
execSync(`prlt work start ${ctx.ticket} --yes --display background`, { timeout: AGENT_SPAWN_TIMEOUT_MS, stdio: 'pipe' });
|
|
73
79
|
return { action: 'spawn-agent', success: true, durationMs: Date.now() - start };
|
|
74
80
|
}
|
|
75
81
|
catch (err) {
|
|
@@ -85,7 +91,7 @@ const respawn = (ctx, config) => {
|
|
|
85
91
|
if (!ctx.ticket) {
|
|
86
92
|
return { action: 'respawn', success: false, error: 'No ticket in context', durationMs: Date.now() - start };
|
|
87
93
|
}
|
|
88
|
-
execSync(`prlt work start ${ctx.ticket} --yes --display background --force`, { timeout:
|
|
94
|
+
execSync(`prlt work start ${ctx.ticket} --yes --display background --force`, { timeout: AGENT_SPAWN_TIMEOUT_MS, stdio: 'pipe' });
|
|
89
95
|
return { action: 'respawn', success: true, durationMs: Date.now() - start };
|
|
90
96
|
}
|
|
91
97
|
catch (err) {
|
|
@@ -136,7 +142,7 @@ const spawnFixAgent = (ctx) => {
|
|
|
136
142
|
if (!ctx.ticket) {
|
|
137
143
|
return { action: 'spawn-fix-agent', success: false, error: 'No ticket in context', durationMs: Date.now() - start };
|
|
138
144
|
}
|
|
139
|
-
execSync(`prlt work start ${ctx.ticket} --action revise --yes --display background`, { timeout:
|
|
145
|
+
execSync(`prlt work start ${ctx.ticket} --action revise --yes --display background`, { timeout: AGENT_SPAWN_TIMEOUT_MS, stdio: 'pipe' });
|
|
140
146
|
return { action: 'spawn-fix-agent', success: true, durationMs: Date.now() - start };
|
|
141
147
|
}
|
|
142
148
|
catch (err) {
|
|
@@ -181,7 +187,7 @@ const resolveConflict = (ctx) => {
|
|
|
181
187
|
// Poke failed — agent is likely not running, respawn it
|
|
182
188
|
}
|
|
183
189
|
// Respawn the agent with resolve action
|
|
184
|
-
execSync(`prlt work start ${ctx.ticket} --action resolve --yes --display background`, { timeout:
|
|
190
|
+
execSync(`prlt work start ${ctx.ticket} --action resolve --yes --display background`, { timeout: AGENT_SPAWN_TIMEOUT_MS, stdio: 'pipe' });
|
|
185
191
|
return { action: 'resolve-conflict', success: true, durationMs: Date.now() - start };
|
|
186
192
|
}
|
|
187
193
|
catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../../../src/lib/orchestrate/actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAK7C;;GAEG;AACH,MAAM,OAAO,GAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;IAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IACxB,IAAI,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YAC3B,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,mCAAmC,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,CAAA;QAC3H,CAAC;QAED,MAAM,IAAI,GAAa,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;QAC/C,IAAI,GAAG,CAAC,MAAM;YAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;QACrC,IAAI,GAAG,CAAC,EAAE;YAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;QAC7C,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA,CAAC,oBAAoB;QAEvC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;QAC7D,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,CAAA;IAC9E,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,CAAA;IACxI,CAAC;AACH,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,UAAU,GAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;IAChD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IACxB,IAAI,CAAC;QACH,MAAM,MAAM,GAAI,MAAM,EAAE,MAAiB,IAAI,MAAM,CAAA;QACnD,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;YAChB,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,sBAAsB,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,CAAA;QACjH,CAAC;QAED,QAAQ,CAAC,oBAAoB,GAAG,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../../../src/lib/orchestrate/actions.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Orchestrate Engine
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* 2. Subscribes to EventBus events
|
|
7
|
-
* 3. Executes matching hooks with mode-aware behavior
|
|
8
|
-
* 4. Optionally polls external sources for events
|
|
4
|
+
* Thin orchestration layer that configures a HookManager with mode-aware
|
|
5
|
+
* execution, built-in action handlers, and confirmation routing.
|
|
9
6
|
*
|
|
10
|
-
* The engine
|
|
11
|
-
* and
|
|
7
|
+
* The engine itself handles:
|
|
8
|
+
* - Configuring HookManager with the correct callbacks and action handlers
|
|
9
|
+
* - Exposing the OrchestrateActionResult API expected by callers
|
|
10
|
+
* - Start/stop lifecycle management
|
|
11
|
+
*
|
|
12
|
+
* All hook matching, mode checking, and execution is delegated to HookManager.
|
|
12
13
|
*/
|
|
13
14
|
import type Database from 'better-sqlite3';
|
|
14
|
-
import type {
|
|
15
|
+
import type { OrchestrateActionResult } from './types.js';
|
|
15
16
|
export interface OrchestrateEngineOptions {
|
|
16
17
|
/** Database connection */
|
|
17
18
|
db: Database.Database;
|
|
@@ -23,17 +24,11 @@ export interface OrchestrateEngineOptions {
|
|
|
23
24
|
onNotify?: (hookName: string, event: string, action: string, result: OrchestrateActionResult) => void;
|
|
24
25
|
}
|
|
25
26
|
export declare class OrchestrateEngine {
|
|
26
|
-
private
|
|
27
|
-
private hookStorage;
|
|
28
|
-
private unsubscribers;
|
|
29
|
-
private log;
|
|
30
|
-
private onConfirm?;
|
|
31
|
-
private onNotify?;
|
|
27
|
+
private manager;
|
|
32
28
|
private running;
|
|
33
|
-
private pendingConfirmations;
|
|
34
29
|
constructor(options: OrchestrateEngineOptions);
|
|
35
30
|
/**
|
|
36
|
-
* Start the orchestrate engine —
|
|
31
|
+
* Start the orchestrate engine — delegates to HookManager.
|
|
37
32
|
*/
|
|
38
33
|
start(): void;
|
|
39
34
|
/**
|
|
@@ -44,11 +39,17 @@ export declare class OrchestrateEngine {
|
|
|
44
39
|
* Fire an event manually (used by `prlt hook fire`).
|
|
45
40
|
* This is the entry point for external event sources (GitHub Actions, polling, etc.).
|
|
46
41
|
*/
|
|
47
|
-
fireEvent(event: string, ctx:
|
|
42
|
+
fireEvent(event: string, ctx: Record<string, unknown>): Promise<OrchestrateActionResult[]>;
|
|
48
43
|
/**
|
|
49
44
|
* Get pending confirmations for hooks in confirm mode.
|
|
50
45
|
*/
|
|
51
|
-
getPendingConfirmations():
|
|
46
|
+
getPendingConfirmations(): Array<{
|
|
47
|
+
hookName: string;
|
|
48
|
+
event: string;
|
|
49
|
+
action: string;
|
|
50
|
+
ctx: Record<string, unknown>;
|
|
51
|
+
config?: Record<string, unknown>;
|
|
52
|
+
}>;
|
|
52
53
|
/**
|
|
53
54
|
* Approve a pending confirmation and execute it.
|
|
54
55
|
*/
|
|
@@ -57,27 +58,6 @@ export declare class OrchestrateEngine {
|
|
|
57
58
|
* Deny a pending confirmation.
|
|
58
59
|
*/
|
|
59
60
|
denyConfirmation(index: number): boolean;
|
|
60
|
-
/**
|
|
61
|
-
* Handle an event by finding and executing matching hooks.
|
|
62
|
-
*/
|
|
63
|
-
private handleEvent;
|
|
64
|
-
/**
|
|
65
|
-
* Get hooks for a given event from the database, ordered by priority.
|
|
66
|
-
*/
|
|
67
|
-
private getHooksForEvent;
|
|
68
|
-
/**
|
|
69
|
-
* Build an OrchestrateEventContext from raw event data.
|
|
70
|
-
*/
|
|
71
|
-
private buildContext;
|
|
72
|
-
/**
|
|
73
|
-
* Resolve the action name from a hook row.
|
|
74
|
-
* Built-in actions are referenced by name; shell hooks use the raw command.
|
|
75
|
-
*/
|
|
76
|
-
private resolveActionName;
|
|
77
|
-
/**
|
|
78
|
-
* Execute an action — either built-in or shell fallback.
|
|
79
|
-
*/
|
|
80
|
-
private executeAction;
|
|
81
61
|
}
|
|
82
62
|
/**
|
|
83
63
|
* Initialize and start the orchestrate engine.
|
|
@@ -1,263 +1,99 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Orchestrate Engine
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* 2. Subscribes to EventBus events
|
|
7
|
-
* 3. Executes matching hooks with mode-aware behavior
|
|
8
|
-
* 4. Optionally polls external sources for events
|
|
4
|
+
* Thin orchestration layer that configures a HookManager with mode-aware
|
|
5
|
+
* execution, built-in action handlers, and confirmation routing.
|
|
9
6
|
*
|
|
10
|
-
* The engine
|
|
11
|
-
* and
|
|
7
|
+
* The engine itself handles:
|
|
8
|
+
* - Configuring HookManager with the correct callbacks and action handlers
|
|
9
|
+
* - Exposing the OrchestrateActionResult API expected by callers
|
|
10
|
+
* - Start/stop lifecycle management
|
|
11
|
+
*
|
|
12
|
+
* All hook matching, mode checking, and execution is delegated to HookManager.
|
|
12
13
|
*/
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import { WorkHookStorage } from '../work-lifecycle/hooks/storage.js';
|
|
16
|
-
import { executeBuiltinAction, ACTION_HANDLERS } from './actions.js';
|
|
14
|
+
import { HookManager } from '../work-lifecycle/hooks/manager.js';
|
|
15
|
+
import { ACTION_HANDLERS } from './actions.js';
|
|
17
16
|
export class OrchestrateEngine {
|
|
18
|
-
|
|
19
|
-
hookStorage;
|
|
20
|
-
unsubscribers = [];
|
|
21
|
-
log;
|
|
22
|
-
onConfirm;
|
|
23
|
-
onNotify;
|
|
17
|
+
manager;
|
|
24
18
|
running = false;
|
|
25
|
-
pendingConfirmations = [];
|
|
26
19
|
constructor(options) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
20
|
+
// Map OrchestrateActionResult-based onNotify to HookExecutionResult-based onNotify
|
|
21
|
+
const onNotify = options.onNotify
|
|
22
|
+
? (hookName, event, action, result) => {
|
|
23
|
+
options.onNotify(hookName, event, action, toActionResult(result));
|
|
24
|
+
}
|
|
25
|
+
: undefined;
|
|
26
|
+
this.manager = new HookManager({
|
|
27
|
+
db: options.db,
|
|
28
|
+
log: options.log,
|
|
29
|
+
onConfirm: options.onConfirm,
|
|
30
|
+
onNotify,
|
|
31
|
+
actionHandlers: ACTION_HANDLERS,
|
|
32
|
+
});
|
|
32
33
|
}
|
|
33
34
|
/**
|
|
34
|
-
* Start the orchestrate engine —
|
|
35
|
+
* Start the orchestrate engine — delegates to HookManager.
|
|
35
36
|
*/
|
|
36
37
|
start() {
|
|
37
38
|
if (this.running)
|
|
38
39
|
return;
|
|
39
40
|
this.running = true;
|
|
40
|
-
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
'work:started',
|
|
44
|
-
'work:status_changed',
|
|
45
|
-
'work:pr_created',
|
|
46
|
-
'work:pr_merged',
|
|
47
|
-
'work:pr_closed',
|
|
48
|
-
'work:completed',
|
|
49
|
-
'agent:spawned',
|
|
50
|
-
'agent:stopped',
|
|
51
|
-
];
|
|
52
|
-
for (const eventName of standardEvents) {
|
|
53
|
-
this.unsubscribers.push(bus.on(eventName, (payload) => {
|
|
54
|
-
void this.handleEvent(eventName, payload);
|
|
55
|
-
}));
|
|
56
|
-
}
|
|
57
|
-
this.log('[orchestrate] Engine started, listening for events');
|
|
41
|
+
this.manager.start();
|
|
42
|
+
// Log is internal to the manager, but we can't access it here easily.
|
|
43
|
+
// The manager's log callback will handle logging.
|
|
58
44
|
}
|
|
59
45
|
/**
|
|
60
46
|
* Stop the engine and clean up subscriptions.
|
|
61
47
|
*/
|
|
62
48
|
stop() {
|
|
63
49
|
this.running = false;
|
|
64
|
-
|
|
65
|
-
unsub();
|
|
66
|
-
}
|
|
67
|
-
this.unsubscribers = [];
|
|
68
|
-
this.pendingConfirmations = [];
|
|
69
|
-
this.log('[orchestrate] Engine stopped');
|
|
50
|
+
this.manager.stop();
|
|
70
51
|
}
|
|
71
52
|
/**
|
|
72
53
|
* Fire an event manually (used by `prlt hook fire`).
|
|
73
54
|
* This is the entry point for external event sources (GitHub Actions, polling, etc.).
|
|
74
55
|
*/
|
|
75
56
|
async fireEvent(event, ctx) {
|
|
76
|
-
|
|
57
|
+
const results = await this.manager.fireEvent(event, ctx);
|
|
58
|
+
return results.map(toActionResult);
|
|
77
59
|
}
|
|
78
60
|
/**
|
|
79
61
|
* Get pending confirmations for hooks in confirm mode.
|
|
80
62
|
*/
|
|
81
63
|
getPendingConfirmations() {
|
|
82
|
-
return
|
|
64
|
+
return this.manager.getPendingConfirmations();
|
|
83
65
|
}
|
|
84
66
|
/**
|
|
85
67
|
* Approve a pending confirmation and execute it.
|
|
86
68
|
*/
|
|
87
69
|
async approveConfirmation(index) {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const pending = this.pendingConfirmations.splice(index, 1)[0];
|
|
91
|
-
const result = executeBuiltinAction(pending.action, pending.ctx, pending.config);
|
|
92
|
-
this.log(`[orchestrate] Approved: ${pending.hookName} → ${pending.action} (${result.success ? 'success' : 'failed'})`);
|
|
93
|
-
return result;
|
|
70
|
+
const result = await this.manager.approveConfirmation(index);
|
|
71
|
+
return result ? toActionResult(result) : null;
|
|
94
72
|
}
|
|
95
73
|
/**
|
|
96
74
|
* Deny a pending confirmation.
|
|
97
75
|
*/
|
|
98
76
|
denyConfirmation(index) {
|
|
99
|
-
|
|
100
|
-
return false;
|
|
101
|
-
const pending = this.pendingConfirmations.splice(index, 1)[0];
|
|
102
|
-
this.log(`[orchestrate] Denied: ${pending.hookName} → ${pending.action}`);
|
|
103
|
-
return true;
|
|
104
|
-
}
|
|
105
|
-
// ===========================================================================
|
|
106
|
-
// Private
|
|
107
|
-
// ===========================================================================
|
|
108
|
-
/**
|
|
109
|
-
* Handle an event by finding and executing matching hooks.
|
|
110
|
-
*/
|
|
111
|
-
async handleEvent(eventName, eventData) {
|
|
112
|
-
const results = [];
|
|
113
|
-
try {
|
|
114
|
-
// Query hooks matching this event, ordered by priority
|
|
115
|
-
const hooks = this.getHooksForEvent(eventName);
|
|
116
|
-
if (hooks.length === 0)
|
|
117
|
-
return results;
|
|
118
|
-
// Build event context from the payload
|
|
119
|
-
const ctx = this.buildContext(eventName, eventData);
|
|
120
|
-
for (const hook of hooks) {
|
|
121
|
-
const mode = (hook.mode || 'auto');
|
|
122
|
-
const config = hook.config ? JSON.parse(hook.config) : undefined;
|
|
123
|
-
// Determine action — either a built-in action name or the raw action_value
|
|
124
|
-
const actionName = this.resolveActionName(hook);
|
|
125
|
-
if (mode === 'off') {
|
|
126
|
-
results.push({ action: actionName, success: true, durationMs: 0, skipped: true });
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
|
-
if (mode === 'confirm') {
|
|
130
|
-
// Queue for confirmation
|
|
131
|
-
if (this.onConfirm) {
|
|
132
|
-
const approved = await this.onConfirm(hook.name, eventName, actionName);
|
|
133
|
-
if (!approved) {
|
|
134
|
-
this.log(`[orchestrate] Skipped (not confirmed): ${hook.name} → ${actionName}`);
|
|
135
|
-
results.push({ action: actionName, success: true, durationMs: 0, skipped: true });
|
|
136
|
-
continue;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
else {
|
|
140
|
-
// No confirm handler — queue for later approval
|
|
141
|
-
this.pendingConfirmations.push({
|
|
142
|
-
hookName: hook.name,
|
|
143
|
-
event: eventName,
|
|
144
|
-
action: actionName,
|
|
145
|
-
ctx,
|
|
146
|
-
config,
|
|
147
|
-
});
|
|
148
|
-
this.log(`[orchestrate] Queued for confirmation: ${hook.name} → ${actionName}`);
|
|
149
|
-
results.push({ action: actionName, success: true, durationMs: 0, awaitingConfirmation: true });
|
|
150
|
-
continue;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
// Execute the action
|
|
154
|
-
const result = this.executeAction(actionName, ctx, config);
|
|
155
|
-
results.push(result);
|
|
156
|
-
this.log(`[orchestrate] ${hook.name} → ${actionName}: ${result.success ? 'success' : `failed: ${result.error}`} (${result.durationMs}ms)`);
|
|
157
|
-
// For notify mode, also fire the notification callback
|
|
158
|
-
if (mode === 'notify' && this.onNotify) {
|
|
159
|
-
this.onNotify(hook.name, eventName, actionName, result);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
catch (err) {
|
|
164
|
-
this.log(`[orchestrate] Error handling event ${eventName}: ${err instanceof Error ? err.message : String(err)}`);
|
|
165
|
-
}
|
|
166
|
-
return results;
|
|
167
|
-
}
|
|
168
|
-
/**
|
|
169
|
-
* Get hooks for a given event from the database, ordered by priority.
|
|
170
|
-
*/
|
|
171
|
-
getHooksForEvent(eventName) {
|
|
172
|
-
try {
|
|
173
|
-
return this.db.prepare(`
|
|
174
|
-
SELECT id, name, event, action_type, action_value, enabled, description, mode, priority, config
|
|
175
|
-
FROM pmo_work_hooks
|
|
176
|
-
WHERE event = ? AND enabled = 1
|
|
177
|
-
ORDER BY priority ASC, created_at ASC
|
|
178
|
-
`).all(eventName);
|
|
179
|
-
}
|
|
180
|
-
catch {
|
|
181
|
-
// Fallback without mode/priority columns (pre-migration)
|
|
182
|
-
try {
|
|
183
|
-
const basic = this.db.prepare(`
|
|
184
|
-
SELECT id, name, event, action_type, action_value, enabled, description
|
|
185
|
-
FROM pmo_work_hooks
|
|
186
|
-
WHERE event = ? AND enabled = 1
|
|
187
|
-
ORDER BY created_at ASC
|
|
188
|
-
`).all(eventName);
|
|
189
|
-
return basic;
|
|
190
|
-
}
|
|
191
|
-
catch {
|
|
192
|
-
return [];
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
/**
|
|
197
|
-
* Build an OrchestrateEventContext from raw event data.
|
|
198
|
-
*/
|
|
199
|
-
buildContext(eventName, data) {
|
|
200
|
-
return {
|
|
201
|
-
event: eventName,
|
|
202
|
-
ticket: (data.ticketId ?? data.workItemId ?? data.ticket),
|
|
203
|
-
pr: (data.prNumber ?? data.pr),
|
|
204
|
-
branch: data.branch,
|
|
205
|
-
agent: (data.agentName ?? data.agent ?? data.sessionId),
|
|
206
|
-
container: data.containerId,
|
|
207
|
-
executionId: data.executionId,
|
|
208
|
-
prUrl: data.prUrl,
|
|
209
|
-
projectId: data.projectId,
|
|
210
|
-
...data,
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
|
-
/**
|
|
214
|
-
* Resolve the action name from a hook row.
|
|
215
|
-
* Built-in actions are referenced by name; shell hooks use the raw command.
|
|
216
|
-
*/
|
|
217
|
-
resolveActionName(hook) {
|
|
218
|
-
// If the action_value starts with "prlt hook fire", extract the --action value
|
|
219
|
-
const actionMatch = hook.action_value.match(/--action\s+(\S+)/);
|
|
220
|
-
if (actionMatch)
|
|
221
|
-
return actionMatch[1];
|
|
222
|
-
// If it's a known built-in action name directly
|
|
223
|
-
if (ACTION_HANDLERS[hook.action_value])
|
|
224
|
-
return hook.action_value;
|
|
225
|
-
// Otherwise it's a raw shell command — use the action_value as-is
|
|
226
|
-
return hook.action_value;
|
|
227
|
-
}
|
|
228
|
-
/**
|
|
229
|
-
* Execute an action — either built-in or shell fallback.
|
|
230
|
-
*/
|
|
231
|
-
executeAction(actionName, ctx, config) {
|
|
232
|
-
// Try built-in action first
|
|
233
|
-
if (ACTION_HANDLERS[actionName]) {
|
|
234
|
-
return executeBuiltinAction(actionName, ctx, config);
|
|
235
|
-
}
|
|
236
|
-
// Fallback to shell execution
|
|
237
|
-
const start = Date.now();
|
|
238
|
-
try {
|
|
239
|
-
const env = {
|
|
240
|
-
...process.env,
|
|
241
|
-
PRLT_HOOK_EVENT: ctx.event,
|
|
242
|
-
PRLT_HOOK_TICKET: ctx.ticket ?? '',
|
|
243
|
-
PRLT_HOOK_PR: ctx.pr ? String(ctx.pr) : '',
|
|
244
|
-
PRLT_HOOK_BRANCH: ctx.branch ?? '',
|
|
245
|
-
PRLT_HOOK_AGENT: ctx.agent ?? '',
|
|
246
|
-
};
|
|
247
|
-
execSync(actionName, { env, timeout: 30_000, stdio: 'pipe' });
|
|
248
|
-
return { action: actionName, success: true, durationMs: Date.now() - start };
|
|
249
|
-
}
|
|
250
|
-
catch (err) {
|
|
251
|
-
return {
|
|
252
|
-
action: actionName,
|
|
253
|
-
success: false,
|
|
254
|
-
error: err instanceof Error ? err.message : String(err),
|
|
255
|
-
durationMs: Date.now() - start,
|
|
256
|
-
};
|
|
257
|
-
}
|
|
77
|
+
return this.manager.denyConfirmation(index);
|
|
258
78
|
}
|
|
259
79
|
}
|
|
260
80
|
// =============================================================================
|
|
81
|
+
// Result Mapping
|
|
82
|
+
// =============================================================================
|
|
83
|
+
/**
|
|
84
|
+
* Convert a HookExecutionResult to an OrchestrateActionResult.
|
|
85
|
+
*/
|
|
86
|
+
function toActionResult(result) {
|
|
87
|
+
return {
|
|
88
|
+
action: result.action,
|
|
89
|
+
success: result.success,
|
|
90
|
+
error: result.error,
|
|
91
|
+
durationMs: result.durationMs,
|
|
92
|
+
skipped: result.skipped,
|
|
93
|
+
awaitingConfirmation: result.awaitingConfirmation,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
// =============================================================================
|
|
261
97
|
// Singleton
|
|
262
98
|
// =============================================================================
|
|
263
99
|
let _engine;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../../src/lib/orchestrate/engine.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../../src/lib/orchestrate/engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -27,6 +27,8 @@ export declare class OrchestratePoller {
|
|
|
27
27
|
private trackedPRs;
|
|
28
28
|
/** Track which tickets we've already fired on_ticket_ready for. */
|
|
29
29
|
private firedReadyTickets;
|
|
30
|
+
/** Track tickets with active conflict resolution to prevent duplicate agent spawns. */
|
|
31
|
+
private activeConflictResolutions;
|
|
30
32
|
/** Track known agent lifecycle states. */
|
|
31
33
|
private lastAgentStates;
|
|
32
34
|
private ghAvailable;
|
|
@@ -26,6 +26,8 @@ export class OrchestratePoller {
|
|
|
26
26
|
trackedPRs = new Map();
|
|
27
27
|
/** Track which tickets we've already fired on_ticket_ready for. */
|
|
28
28
|
firedReadyTickets = new Set();
|
|
29
|
+
/** Track tickets with active conflict resolution to prevent duplicate agent spawns. */
|
|
30
|
+
activeConflictResolutions = new Set();
|
|
29
31
|
/** Track known agent lifecycle states. */
|
|
30
32
|
lastAgentStates = new Map();
|
|
31
33
|
ghAvailable = null;
|
|
@@ -225,19 +227,34 @@ export class OrchestratePoller {
|
|
|
225
227
|
}
|
|
226
228
|
}
|
|
227
229
|
catch {
|
|
228
|
-
// gh command failed
|
|
230
|
+
// gh command failed — preserve previous mergeable state to avoid
|
|
231
|
+
// CONFLICTING→UNKNOWN→CONFLICTING re-fire cycles
|
|
232
|
+
mergeable = tracked?.lastMergeable ?? 'UNKNOWN';
|
|
233
|
+
}
|
|
234
|
+
// Clear conflict resolution tracking when PR becomes mergeable
|
|
235
|
+
if (mergeable === 'MERGEABLE' && ticketId) {
|
|
236
|
+
this.activeConflictResolutions.delete(ticketId);
|
|
229
237
|
}
|
|
230
238
|
// Fire on_pr_conflicting on first observation or when transitioning to CONFLICTING
|
|
231
239
|
const isNewConflict = mergeable === 'CONFLICTING' && (!tracked || tracked.lastMergeable !== 'CONFLICTING');
|
|
232
240
|
if (isNewConflict) {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
+
// Dedup: skip if we already have an active conflict resolution for this ticket
|
|
242
|
+
if (ticketId && this.activeConflictResolutions.has(ticketId)) {
|
|
243
|
+
this.log(`[poll] PR #${pr.number} conflicting but resolution already active for ${ticketId}, skipping`);
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
if (ticketId) {
|
|
247
|
+
this.activeConflictResolutions.add(ticketId);
|
|
248
|
+
}
|
|
249
|
+
this.log(`[poll] PR conflicting: PR #${pr.number}`);
|
|
250
|
+
await this.engine.fireEvent('on_pr_conflicting', {
|
|
251
|
+
event: 'on_pr_conflicting',
|
|
252
|
+
pr: pr.number,
|
|
253
|
+
branch: pr.headBranch,
|
|
254
|
+
ticket: ticketId,
|
|
255
|
+
prUrl: pr.url,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
241
258
|
}
|
|
242
259
|
// Update tracking
|
|
243
260
|
this.trackedPRs.set(pr.number, {
|