@qaick/executor 0.1.0-alpha.3 → 0.2.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/dist/executor.d.ts +17 -4
- package/dist/executor.js +532 -244
- package/dist/migrated-artifact-hash.d.ts +1 -1
- package/dist/migrated-executor.d.ts +6 -4
- package/dist/migrated-executor.js +32 -10
- package/dist/types.d.ts +82 -6
- package/package.json +3 -3
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { ExecutionPackage } from './types';
|
|
1
|
+
import type { ExecutionPackage } from './migrated-types';
|
|
2
2
|
/** Stable, dependency-free content identity for the normalized execution package. */
|
|
3
3
|
export declare function hashExecutionPackage(pack: ExecutionPackage): string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ActionExecutor, Executor, ExecutorConfiguration, ExecutorEvent, ExecutorRequest, ExecutorResult, ExecutorRun, ControlCommand, ExecutionControlState } from './types.js';
|
|
1
|
+
import type { ActReplayTarget, ActReplayHandle, OperationReplayHandle, ActionExecutor, Executor, ExecutorConfiguration, ExecutorEvent, ExecutorRequest, ExecutorResult, ExecutorRun, ControlCommand, ExecutionControlState } from './types.js';
|
|
2
2
|
export declare function createMigratedExecutor(configuration?: ExecutorConfiguration): Executor;
|
|
3
3
|
/**
|
|
4
4
|
* Compatibility facade over the extracted Runner engine. The facade owns the
|
|
@@ -6,6 +6,8 @@ export declare function createMigratedExecutor(configuration?: ExecutorConfigura
|
|
|
6
6
|
* remains the migrated Runner implementation.
|
|
7
7
|
*/
|
|
8
8
|
export declare class MigratedExecutor implements Executor {
|
|
9
|
+
private readonly routineRuns;
|
|
10
|
+
private readonly routine;
|
|
9
11
|
private readonly adapters;
|
|
10
12
|
private readonly engine;
|
|
11
13
|
constructor(configuration?: ExecutorConfiguration);
|
|
@@ -16,7 +18,7 @@ export declare class MigratedExecutor implements Executor {
|
|
|
16
18
|
controlState(requestId: string): ExecutionControlState | undefined;
|
|
17
19
|
events(requestId: string): AsyncIterable<ExecutorEvent>;
|
|
18
20
|
result(requestId: string): Promise<ExecutorResult>;
|
|
19
|
-
retryAction(requestId: string,
|
|
20
|
-
retryOperation(requestId: string,
|
|
21
|
-
runFromHere(requestId: string,
|
|
21
|
+
retryAction(requestId: string, target: ActReplayTarget): Promise<ActReplayHandle>;
|
|
22
|
+
retryOperation(requestId: string, target: ActReplayTarget): Promise<OperationReplayHandle>;
|
|
23
|
+
runFromHere(requestId: string, target: ActReplayTarget): Promise<ExecutorRun>;
|
|
22
24
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createExecutor } from './executor.js';
|
|
1
2
|
import { MigratedRunnerEngine } from './migrated-runner-engine.js';
|
|
2
3
|
import { MigratedProjectRunnerEngine } from './migrated-project-engine.js';
|
|
3
4
|
export function createMigratedExecutor(configuration = {}) {
|
|
@@ -9,20 +10,30 @@ export function createMigratedExecutor(configuration = {}) {
|
|
|
9
10
|
* remains the migrated Runner implementation.
|
|
10
11
|
*/
|
|
11
12
|
export class MigratedExecutor {
|
|
13
|
+
routineRuns = new Set();
|
|
14
|
+
routine;
|
|
12
15
|
adapters;
|
|
13
16
|
engine;
|
|
14
17
|
constructor(configuration = {}) {
|
|
18
|
+
this.routine = createExecutor(configuration);
|
|
15
19
|
this.adapters = (configuration.actionExecutors ?? []).map(toActionAdapter);
|
|
16
20
|
this.engine = new MigratedProjectRunnerEngine(new MigratedRunnerEngine(this.adapters));
|
|
17
21
|
}
|
|
18
|
-
registerActionExecutor(executor) { this.adapters.push(toActionAdapter(executor)); }
|
|
22
|
+
registerActionExecutor(executor) { this.routine.registerActionExecutor(executor); this.adapters.push(toActionAdapter(executor)); }
|
|
19
23
|
async execute(request) {
|
|
24
|
+
if (request.executionPackage.ordering === 'routine') {
|
|
25
|
+
this.routineRuns.add(request.requestId);
|
|
26
|
+
return this.routine.execute(request);
|
|
27
|
+
}
|
|
20
28
|
const runnerRequest = request;
|
|
21
29
|
await this.engine.submit(runnerRequest);
|
|
22
30
|
return { requestId: request.requestId, result: this.result(request.requestId) };
|
|
23
31
|
}
|
|
24
|
-
async cancel(requestId) {
|
|
32
|
+
async cancel(requestId) { if (this.routineRuns.has(requestId))
|
|
33
|
+
return this.routine.cancel(requestId); await this.engine.cancel(requestId); }
|
|
25
34
|
async control(requestId, command) {
|
|
35
|
+
if (this.routineRuns.has(requestId))
|
|
36
|
+
return this.routine.control(requestId, command);
|
|
26
37
|
if (command.type === 'pause')
|
|
27
38
|
return this.engine.pauseExecution(requestId);
|
|
28
39
|
if (command.type === 'resume')
|
|
@@ -34,14 +45,25 @@ export class MigratedExecutor {
|
|
|
34
45
|
if (command.type === 'stop-after')
|
|
35
46
|
return;
|
|
36
47
|
}
|
|
37
|
-
controlState(requestId) { return this.engine.controlState(requestId); }
|
|
38
|
-
async *events(requestId) { yield* this.engine.events(requestId); }
|
|
39
|
-
async result(requestId) { return this.engine.result(requestId); }
|
|
40
|
-
async retryAction(requestId,
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
48
|
+
controlState(requestId) { return this.routineRuns.has(requestId) ? this.routine.controlState(requestId) : this.engine.controlState(requestId); }
|
|
49
|
+
async *events(requestId) { yield* (this.routineRuns.has(requestId) ? this.routine.events(requestId) : this.engine.events(requestId)); }
|
|
50
|
+
async result(requestId) { return (this.routineRuns.has(requestId) ? this.routine.result(requestId) : this.engine.result(requestId)); }
|
|
51
|
+
async retryAction(requestId, target) {
|
|
52
|
+
if (this.routineRuns.has(requestId))
|
|
53
|
+
return this.routine.retryAction(requestId, target);
|
|
54
|
+
throw { code: 'unsupported-execution-context', message: 'Structural Act replay requires the canonical execution path.' };
|
|
55
|
+
}
|
|
56
|
+
async retryOperation(requestId, target) {
|
|
57
|
+
if (this.routineRuns.has(requestId))
|
|
58
|
+
return this.routine.retryOperation(requestId, target);
|
|
59
|
+
throw { code: 'unsupported-execution-context', message: 'Structural Operation replay requires the canonical execution path.' };
|
|
60
|
+
}
|
|
61
|
+
async runFromHere(requestId, target) {
|
|
62
|
+
if (!this.routineRuns.has(requestId))
|
|
63
|
+
throw { code: 'unsupported-execution-context', message: 'Structural Run From Here requires the canonical execution path.' };
|
|
64
|
+
const started = await this.routine.runFromHere(requestId, target);
|
|
65
|
+
this.routineRuns.add(started.requestId);
|
|
66
|
+
return started;
|
|
45
67
|
}
|
|
46
68
|
}
|
|
47
69
|
function toActionAdapter(executor) {
|
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ExecutionPackage, ExecutionStep, ExecutionState, InvocationState, TerminalReason } from '@qaick/contract';
|
|
2
|
-
export type { ExecutionPackage, ExecutionStep, ExecutionState, InvocationState, TerminalReason } from '@qaick/contract';
|
|
1
|
+
import type { ExecutionPackageV7 as ExecutionPackage, ExecutionStepV7 as ExecutionStep, ExecutionState, InvocationState, TerminalReason } from '@qaick/contract';
|
|
2
|
+
export type { ExecutionPackageV7 as ExecutionPackage, ExecutionStepV7 as ExecutionStep, ExecutionState, InvocationState, TerminalReason } from '@qaick/contract';
|
|
3
3
|
export type ActionFailureCode = 'ACTION_FAILED' | 'ACTION_TIMEOUT' | 'ACTION_CANCELLED' | 'UNSUPPORTED_ACTION' | 'BINDING_RESOLUTION_ERROR' | 'CONTROL_BLOCK_ERROR' | 'PREFLIGHT_ERROR' | 'INTERNAL_EXECUTION_ERROR';
|
|
4
4
|
export interface ActionFailure {
|
|
5
5
|
code: string;
|
|
@@ -12,7 +12,7 @@ export interface ActionExecutionContext {
|
|
|
12
12
|
inputs: Record<string, unknown>;
|
|
13
13
|
environment: string;
|
|
14
14
|
runtimeValues: Record<string, unknown>;
|
|
15
|
-
step: ExecutionStep
|
|
15
|
+
step: Pick<ExecutionStep, 'id' | 'name' | 'action' | 'output' | 'adapterConfig'>;
|
|
16
16
|
signal: AbortSignal;
|
|
17
17
|
}
|
|
18
18
|
export interface ActionExecutionResult {
|
|
@@ -63,6 +63,8 @@ export interface ExecutorStepResult {
|
|
|
63
63
|
inputs: Record<string, unknown>;
|
|
64
64
|
outputs: Record<string, unknown>;
|
|
65
65
|
durationMs: number;
|
|
66
|
+
structuralAddress?: import('@qaick/contract').HierarchyAddress;
|
|
67
|
+
iterations?: import('@qaick/contract').IterationSelection[];
|
|
66
68
|
invocationId?: string;
|
|
67
69
|
invocationPath?: string[];
|
|
68
70
|
kind?: 'action' | 'operation' | 'control-block';
|
|
@@ -78,6 +80,7 @@ export interface ExecutorStepResult {
|
|
|
78
80
|
error?: ActionFailure;
|
|
79
81
|
}
|
|
80
82
|
export interface ExecutorResult {
|
|
83
|
+
readonly debugProvenance?: RunFromHereProvenance;
|
|
81
84
|
requestId: string;
|
|
82
85
|
state: Exclude<ExecutionState, 'created' | 'preflighting' | 'running'>;
|
|
83
86
|
target: ExecutionPackage['target'];
|
|
@@ -100,6 +103,9 @@ export interface ExecutorResult {
|
|
|
100
103
|
};
|
|
101
104
|
}
|
|
102
105
|
export interface ExecutorEvent {
|
|
106
|
+
structuralAddress?: import('@qaick/contract').HierarchyAddress;
|
|
107
|
+
iterations?: import('@qaick/contract').IterationSelection[];
|
|
108
|
+
kind?: 'action' | 'operation' | 'control-block';
|
|
103
109
|
requestId: string;
|
|
104
110
|
sequence: number;
|
|
105
111
|
type: 'run_started' | 'preflight_started' | 'step_started' | 'waiting' | 'step_finished' | 'run_finished';
|
|
@@ -138,9 +144,79 @@ export type ControlCommand = {
|
|
|
138
144
|
};
|
|
139
145
|
export type ExecutionControlState = 'idle' | 'running' | 'pause-requested' | 'paused' | 'resuming' | 'stopped' | 'failed' | 'completed';
|
|
140
146
|
export interface ExecutorRun {
|
|
147
|
+
readonly debugProvenance?: RunFromHereProvenance;
|
|
141
148
|
requestId: string;
|
|
142
149
|
result: Promise<ExecutorResult>;
|
|
143
150
|
}
|
|
151
|
+
/** Runtime diagnostic target; never serialized into an Execution v7 package. */
|
|
152
|
+
export interface ActReplayTarget {
|
|
153
|
+
structuralAddress: import('@qaick/contract').HierarchyAddress;
|
|
154
|
+
iterations: import('@qaick/contract').IterationSelection[];
|
|
155
|
+
}
|
|
156
|
+
/** Descriptive runtime provenance, not an execution operand or persisted package field. */
|
|
157
|
+
export interface RunFromHereProvenance {
|
|
158
|
+
readonly kind: 'run-from-here';
|
|
159
|
+
readonly sourceRequestId: string;
|
|
160
|
+
readonly selection: Readonly<ActReplayTarget>;
|
|
161
|
+
readonly inputSeed: {
|
|
162
|
+
readonly kind: 'captured-inputs';
|
|
163
|
+
readonly inputs: Readonly<Record<string, unknown>>;
|
|
164
|
+
readonly lexicalScope?: Readonly<Record<string, unknown>>;
|
|
165
|
+
};
|
|
166
|
+
readonly omittedOccurrences: readonly import('@qaick/contract').HierarchyAddress[];
|
|
167
|
+
}
|
|
168
|
+
export interface ActReplayResult {
|
|
169
|
+
readonly parentRequestId: string;
|
|
170
|
+
readonly sessionId: string;
|
|
171
|
+
readonly target: Readonly<ActReplayTarget>;
|
|
172
|
+
readonly kind: 'action';
|
|
173
|
+
readonly state: 'completed' | 'failed' | 'cancelled';
|
|
174
|
+
readonly terminalReason: 'completed' | 'failed' | 'cancelled' | 'timeout';
|
|
175
|
+
readonly startedAt: string;
|
|
176
|
+
readonly finishedAt: string;
|
|
177
|
+
readonly durationMs: number;
|
|
178
|
+
readonly inputs: Readonly<Record<string, unknown>>;
|
|
179
|
+
readonly outputs: Readonly<Record<string, unknown>>;
|
|
180
|
+
readonly evidence?: Readonly<Record<string, unknown>>;
|
|
181
|
+
readonly attempts: readonly ExecutionAttempt[];
|
|
182
|
+
readonly error?: Readonly<ActionFailure>;
|
|
183
|
+
}
|
|
184
|
+
export interface ActReplayEvent {
|
|
185
|
+
readonly parentRequestId: string;
|
|
186
|
+
readonly sessionId: string;
|
|
187
|
+
readonly sequence: number;
|
|
188
|
+
readonly timestamp: string;
|
|
189
|
+
readonly structuralAddress: import('@qaick/contract').HierarchyAddress;
|
|
190
|
+
readonly iterations: import('@qaick/contract').IterationSelection[];
|
|
191
|
+
readonly kind: 'action';
|
|
192
|
+
readonly type: 'replay_started' | 'attempt_started' | 'attempt_finished' | 'replay_finished';
|
|
193
|
+
readonly state: 'running' | 'finished' | 'completed' | 'failed' | 'cancelled';
|
|
194
|
+
readonly attempt?: number;
|
|
195
|
+
readonly terminalReason?: ActReplayResult['terminalReason'];
|
|
196
|
+
}
|
|
197
|
+
/** A replay is associated with a historical Run; this is not a new ExecutorRun. */
|
|
198
|
+
export interface ActReplayHandle {
|
|
199
|
+
readonly parentRequestId: string;
|
|
200
|
+
readonly sessionId: string;
|
|
201
|
+
readonly target: Readonly<ActReplayTarget>;
|
|
202
|
+
readonly result: Promise<ActReplayResult>;
|
|
203
|
+
events(): AsyncIterable<ActReplayEvent>;
|
|
204
|
+
cancel(): Promise<void>;
|
|
205
|
+
}
|
|
206
|
+
export interface OperationReplayResult extends Omit<ActReplayResult, 'kind' | 'attempts' | 'evidence'> {
|
|
207
|
+
readonly kind: 'operation';
|
|
208
|
+
readonly lexicalScope: Readonly<Record<string, unknown>>;
|
|
209
|
+
readonly children: readonly ExecutorStepResult[];
|
|
210
|
+
}
|
|
211
|
+
export interface OperationReplayEvent extends Omit<ActReplayEvent, 'kind' | 'type' | 'state'> {
|
|
212
|
+
readonly kind: 'action' | 'operation' | 'control-block';
|
|
213
|
+
readonly type: ActReplayEvent['type'] | 'step_started' | 'step_finished' | 'waiting';
|
|
214
|
+
readonly state: ActReplayEvent['state'] | 'waiting' | 'skipped';
|
|
215
|
+
}
|
|
216
|
+
export interface OperationReplayHandle extends Omit<ActReplayHandle, 'result' | 'events'> {
|
|
217
|
+
readonly result: Promise<OperationReplayResult>;
|
|
218
|
+
events(): AsyncIterable<OperationReplayEvent>;
|
|
219
|
+
}
|
|
144
220
|
export interface ExecutorConfiguration {
|
|
145
221
|
actionExecutors?: ActionExecutor[];
|
|
146
222
|
maxTimeoutMs?: number;
|
|
@@ -152,8 +228,8 @@ export interface Executor {
|
|
|
152
228
|
controlState(requestId: string): ExecutionControlState | undefined;
|
|
153
229
|
events(requestId: string): AsyncIterable<ExecutorEvent>;
|
|
154
230
|
result(requestId: string): Promise<ExecutorResult>;
|
|
155
|
-
retryAction(requestId: string,
|
|
156
|
-
retryOperation(requestId: string,
|
|
157
|
-
runFromHere(requestId: string,
|
|
231
|
+
retryAction(requestId: string, target: ActReplayTarget): Promise<ActReplayHandle>;
|
|
232
|
+
retryOperation(requestId: string, target: ActReplayTarget): Promise<OperationReplayHandle>;
|
|
233
|
+
runFromHere(requestId: string, target: ActReplayTarget): Promise<ExecutorRun>;
|
|
158
234
|
registerActionExecutor(executor: ActionExecutor): void;
|
|
159
235
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qaick/executor",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Host-neutral QAick action execution primitives.",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
},
|
|
12
12
|
"publishConfig": {
|
|
13
13
|
"access": "public",
|
|
14
|
-
"tag": "
|
|
14
|
+
"tag": "latest"
|
|
15
15
|
},
|
|
16
16
|
"repository": {
|
|
17
17
|
"type": "git",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"prepublishOnly": "npm run typecheck && npm test && npm run build"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@qaick/contract": "0.
|
|
37
|
+
"@qaick/contract": "0.3.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/node": "^24.13.3",
|