apcore-js 0.16.0 → 0.17.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/README.md +1 -1
- package/dist/builtin-steps.d.ts +27 -12
- package/dist/builtin-steps.d.ts.map +1 -1
- package/dist/builtin-steps.js +89 -139
- package/dist/builtin-steps.js.map +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +1 -1
- package/dist/client.js.map +1 -1
- package/dist/executor.d.ts +27 -30
- package/dist/executor.d.ts.map +1 -1
- package/dist/executor.js +231 -395
- package/dist/executor.js.map +1 -1
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/pipeline-config.d.ts +68 -0
- package/dist/pipeline-config.d.ts.map +1 -0
- package/dist/pipeline-config.js +153 -0
- package/dist/pipeline-config.js.map +1 -0
- package/dist/pipeline.d.ts +16 -0
- package/dist/pipeline.d.ts.map +1 -1
- package/dist/pipeline.js +88 -2
- package/dist/pipeline.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ apcore is an AI-Perceivable module standard that makes every interface naturally
|
|
|
19
19
|
## Features
|
|
20
20
|
|
|
21
21
|
- **Schema-driven modules** — Define input/output schemas with TypeBox for runtime validation
|
|
22
|
-
- **Executor pipeline** — Secured execution lifecycle: context →
|
|
22
|
+
- **Executor pipeline** — Secured execution lifecycle: context → call chain guard → lookup → ACL → approval gate → middleware before → validation → execute → output validation → middleware after → return
|
|
23
23
|
- **Registry system** — File-based module discovery with metadata, dependencies, and topological ordering
|
|
24
24
|
- **Binding loader** — YAML-based module registration for no-code integration
|
|
25
25
|
- **Access control (ACL)** — Pattern-based rules with identity types, roles, and call-depth conditions
|
package/dist/builtin-steps.d.ts
CHANGED
|
@@ -14,20 +14,22 @@ import type { Step, StepResult, PipelineContext } from './pipeline.js';
|
|
|
14
14
|
import { ExecutionStrategy } from './pipeline.js';
|
|
15
15
|
/** Creates or inherits execution Context and sets the global deadline. */
|
|
16
16
|
export declare class BuiltinContextCreation implements Step {
|
|
17
|
-
readonly name = "
|
|
17
|
+
readonly name = "context_creation";
|
|
18
18
|
readonly description = "Create or inherit execution context and set global deadline";
|
|
19
19
|
readonly removable = false;
|
|
20
20
|
readonly replaceable = false;
|
|
21
|
+
readonly pure = true;
|
|
21
22
|
private _globalTimeout;
|
|
22
23
|
constructor(config: Config | null);
|
|
23
24
|
execute(ctx: PipelineContext): Promise<StepResult>;
|
|
24
25
|
}
|
|
25
26
|
/** Validates call chain depth, repeat limits, and cancel token. */
|
|
26
|
-
export declare class
|
|
27
|
-
readonly name = "
|
|
27
|
+
export declare class BuiltinCallChainGuard implements Step {
|
|
28
|
+
readonly name = "call_chain_guard";
|
|
28
29
|
readonly description = "Call chain guard: depth, repeat limits, cancel token";
|
|
29
30
|
readonly removable = true;
|
|
30
31
|
readonly replaceable = true;
|
|
32
|
+
readonly pure = true;
|
|
31
33
|
private _maxCallDepth;
|
|
32
34
|
private _maxModuleRepeat;
|
|
33
35
|
constructor(config: Config | null);
|
|
@@ -35,86 +37,99 @@ export declare class BuiltinSafetyCheck implements Step {
|
|
|
35
37
|
}
|
|
36
38
|
/** Resolves the module from the registry and sets ctx.module. */
|
|
37
39
|
export declare class BuiltinModuleLookup implements Step {
|
|
38
|
-
readonly name = "
|
|
40
|
+
readonly name = "module_lookup";
|
|
39
41
|
readonly description = "Resolve module from registry";
|
|
40
42
|
readonly removable = false;
|
|
41
43
|
readonly replaceable = false;
|
|
44
|
+
readonly pure = true;
|
|
42
45
|
private _registry;
|
|
43
46
|
constructor(registry: Registry);
|
|
44
47
|
execute(ctx: PipelineContext): Promise<StepResult>;
|
|
45
48
|
}
|
|
46
49
|
/** Enforces access control via the ACL provider. */
|
|
47
50
|
export declare class BuiltinACLCheck implements Step {
|
|
48
|
-
readonly name = "
|
|
51
|
+
readonly name = "acl_check";
|
|
49
52
|
readonly description = "Access control list enforcement";
|
|
50
53
|
readonly removable = true;
|
|
51
54
|
readonly replaceable = true;
|
|
55
|
+
readonly pure = true;
|
|
52
56
|
private _acl;
|
|
53
57
|
constructor(acl: ACL | null);
|
|
58
|
+
/** Update the ACL provider at runtime. */
|
|
59
|
+
setAcl(acl: ACL): void;
|
|
54
60
|
execute(ctx: PipelineContext): Promise<StepResult>;
|
|
55
61
|
}
|
|
56
62
|
/** Handles approval flow for modules that require explicit approval. */
|
|
57
63
|
export declare class BuiltinApprovalGate implements Step {
|
|
58
|
-
readonly name = "
|
|
64
|
+
readonly name = "approval_gate";
|
|
59
65
|
readonly description = "Approval handler flow";
|
|
60
66
|
readonly removable = true;
|
|
61
67
|
readonly replaceable = true;
|
|
68
|
+
readonly pure = false;
|
|
62
69
|
private _handler;
|
|
63
70
|
constructor(handler: ApprovalHandler | null);
|
|
71
|
+
/** Update the approval handler at runtime. */
|
|
72
|
+
setApprovalHandler(handler: ApprovalHandler): void;
|
|
64
73
|
execute(ctx: PipelineContext): Promise<StepResult>;
|
|
65
74
|
}
|
|
66
75
|
/** Validates inputs against module schema and redacts sensitive fields. */
|
|
67
76
|
export declare class BuiltinInputValidation implements Step {
|
|
68
|
-
readonly name = "
|
|
77
|
+
readonly name = "input_validation";
|
|
69
78
|
readonly description = "Schema validation and redaction for inputs";
|
|
70
79
|
readonly removable = true;
|
|
71
80
|
readonly replaceable = true;
|
|
81
|
+
readonly pure = true;
|
|
72
82
|
execute(ctx: PipelineContext): Promise<StepResult>;
|
|
73
83
|
}
|
|
74
84
|
/** Executes before-middleware chain via MiddlewareManager. */
|
|
75
85
|
export declare class BuiltinMiddlewareBefore implements Step {
|
|
76
|
-
readonly name = "
|
|
86
|
+
readonly name = "middleware_before";
|
|
77
87
|
readonly description = "Execute before-middleware chain";
|
|
78
88
|
readonly removable = true;
|
|
79
89
|
readonly replaceable = false;
|
|
90
|
+
readonly pure = false;
|
|
80
91
|
private _middlewareManager;
|
|
81
92
|
constructor(middlewares: MiddlewareManager);
|
|
82
93
|
execute(ctx: PipelineContext): Promise<StepResult>;
|
|
83
94
|
}
|
|
84
95
|
/** Executes the module with timeout enforcement. Sets ctx.output. */
|
|
85
96
|
export declare class BuiltinExecute implements Step {
|
|
86
|
-
readonly name = "
|
|
97
|
+
readonly name = "execute";
|
|
87
98
|
readonly description = "Execute module with timeout";
|
|
88
99
|
readonly removable = false;
|
|
89
100
|
readonly replaceable = true;
|
|
101
|
+
readonly pure = false;
|
|
90
102
|
private _defaultTimeout;
|
|
91
103
|
constructor(config: Config | null);
|
|
92
104
|
execute(ctx: PipelineContext): Promise<StepResult>;
|
|
93
105
|
}
|
|
94
106
|
/** Validates output against module schema and redacts sensitive fields. */
|
|
95
107
|
export declare class BuiltinOutputValidation implements Step {
|
|
96
|
-
readonly name = "
|
|
108
|
+
readonly name = "output_validation";
|
|
97
109
|
readonly description = "Schema validation and redaction for output";
|
|
98
110
|
readonly removable = true;
|
|
99
111
|
readonly replaceable = true;
|
|
112
|
+
readonly pure = true;
|
|
100
113
|
execute(ctx: PipelineContext): Promise<StepResult>;
|
|
101
114
|
}
|
|
102
115
|
/** Executes after-middleware chain via MiddlewareManager. */
|
|
103
116
|
export declare class BuiltinMiddlewareAfter implements Step {
|
|
104
|
-
readonly name = "
|
|
117
|
+
readonly name = "middleware_after";
|
|
105
118
|
readonly description = "Execute after-middleware chain";
|
|
106
119
|
readonly removable = true;
|
|
107
120
|
readonly replaceable = false;
|
|
121
|
+
readonly pure = false;
|
|
108
122
|
private _middlewareManager;
|
|
109
123
|
constructor(middlewares: MiddlewareManager);
|
|
110
124
|
execute(ctx: PipelineContext): Promise<StepResult>;
|
|
111
125
|
}
|
|
112
126
|
/** Finalizes the pipeline result. Output is already on ctx.output. */
|
|
113
127
|
export declare class BuiltinReturnResult implements Step {
|
|
114
|
-
readonly name = "
|
|
128
|
+
readonly name = "return_result";
|
|
115
129
|
readonly description = "Finalize pipeline result";
|
|
116
130
|
readonly removable = false;
|
|
117
131
|
readonly replaceable = false;
|
|
132
|
+
readonly pure = true;
|
|
118
133
|
execute(_ctx: PipelineContext): Promise<StepResult>;
|
|
119
134
|
}
|
|
120
135
|
export interface StandardStrategyDeps {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builtin-steps.d.ts","sourceRoot":"","sources":["../src/builtin-steps.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,KAAK,EAAE,eAAe,EAAmC,MAAM,eAAe,CAAC;AAEtF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAc1C,OAAO,EAAwB,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAIlF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAmElD,0EAA0E;AAC1E,qBAAa,sBAAuB,YAAW,IAAI;IACjD,QAAQ,CAAC,IAAI,
|
|
1
|
+
{"version":3,"file":"builtin-steps.d.ts","sourceRoot":"","sources":["../src/builtin-steps.ts"],"names":[],"mappings":"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"}
|
package/dist/builtin-steps.js
CHANGED
|
@@ -10,8 +10,7 @@ import { Value } from '@sinclair/typebox/value';
|
|
|
10
10
|
import { jsonSchemaToTypeBox } from './schema/loader.js';
|
|
11
11
|
import { createApprovalRequest } from './approval.js';
|
|
12
12
|
import { Context } from './context.js';
|
|
13
|
-
import {
|
|
14
|
-
import { ModuleTimeoutError, SchemaValidationError, } from './errors.js';
|
|
13
|
+
import { ACLDeniedError, ApprovalDeniedError, ApprovalPendingError, ApprovalTimeoutError, InvalidInputError, ModuleNotFoundError, ModuleTimeoutError, SchemaValidationError, } from './errors.js';
|
|
15
14
|
import { MiddlewareChainError } from './middleware/manager.js';
|
|
16
15
|
import { guardCallChain } from './utils/call-chain.js';
|
|
17
16
|
import { DEFAULT_ANNOTATIONS } from './module.js';
|
|
@@ -78,10 +77,11 @@ function dictToAnnotations(dict) {
|
|
|
78
77
|
// ---------------------------------------------------------------------------
|
|
79
78
|
/** Creates or inherits execution Context and sets the global deadline. */
|
|
80
79
|
export class BuiltinContextCreation {
|
|
81
|
-
name = '
|
|
80
|
+
name = 'context_creation';
|
|
82
81
|
description = 'Create or inherit execution context and set global deadline';
|
|
83
82
|
removable = false;
|
|
84
83
|
replaceable = false;
|
|
84
|
+
pure = true;
|
|
85
85
|
_globalTimeout;
|
|
86
86
|
constructor(config) {
|
|
87
87
|
if (config !== null) {
|
|
@@ -104,14 +104,15 @@ export class BuiltinContextCreation {
|
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
106
|
// ---------------------------------------------------------------------------
|
|
107
|
-
// 2.
|
|
107
|
+
// 2. BuiltinCallChainGuard
|
|
108
108
|
// ---------------------------------------------------------------------------
|
|
109
109
|
/** Validates call chain depth, repeat limits, and cancel token. */
|
|
110
|
-
export class
|
|
111
|
-
name = '
|
|
110
|
+
export class BuiltinCallChainGuard {
|
|
111
|
+
name = 'call_chain_guard';
|
|
112
112
|
description = 'Call chain guard: depth, repeat limits, cancel token';
|
|
113
113
|
removable = true;
|
|
114
114
|
replaceable = true;
|
|
115
|
+
pure = true;
|
|
115
116
|
_maxCallDepth;
|
|
116
117
|
_maxModuleRepeat;
|
|
117
118
|
constructor(config) {
|
|
@@ -125,31 +126,12 @@ export class BuiltinSafetyCheck {
|
|
|
125
126
|
}
|
|
126
127
|
}
|
|
127
128
|
async execute(ctx) {
|
|
128
|
-
// Check cancel token first
|
|
129
|
+
// Check cancel token first — throw directly for error type preservation
|
|
129
130
|
if (ctx.context.cancelToken !== null) {
|
|
130
|
-
|
|
131
|
-
ctx.context.cancelToken.check();
|
|
132
|
-
}
|
|
133
|
-
catch (e) {
|
|
134
|
-
if (e instanceof ExecutionCancelledError) {
|
|
135
|
-
return {
|
|
136
|
-
action: 'abort',
|
|
137
|
-
explanation: `Execution cancelled: ${e.message}`,
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
throw e;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
// Call chain safety guard
|
|
144
|
-
try {
|
|
145
|
-
guardCallChain(ctx.moduleId, ctx.context.callChain, this._maxCallDepth, this._maxModuleRepeat);
|
|
146
|
-
}
|
|
147
|
-
catch (e) {
|
|
148
|
-
return {
|
|
149
|
-
action: 'abort',
|
|
150
|
-
explanation: e instanceof Error ? e.message : String(e),
|
|
151
|
-
};
|
|
131
|
+
ctx.context.cancelToken.check();
|
|
152
132
|
}
|
|
133
|
+
// Call chain safety guard — throws CallDepthExceededError, CircularCallError, etc.
|
|
134
|
+
guardCallChain(ctx.moduleId, ctx.context.callChain, this._maxCallDepth, this._maxModuleRepeat);
|
|
153
135
|
return { action: 'continue' };
|
|
154
136
|
}
|
|
155
137
|
}
|
|
@@ -158,10 +140,11 @@ export class BuiltinSafetyCheck {
|
|
|
158
140
|
// ---------------------------------------------------------------------------
|
|
159
141
|
/** Resolves the module from the registry and sets ctx.module. */
|
|
160
142
|
export class BuiltinModuleLookup {
|
|
161
|
-
name = '
|
|
143
|
+
name = 'module_lookup';
|
|
162
144
|
description = 'Resolve module from registry';
|
|
163
145
|
removable = false;
|
|
164
146
|
replaceable = false;
|
|
147
|
+
pure = true;
|
|
165
148
|
_registry;
|
|
166
149
|
constructor(registry) {
|
|
167
150
|
this._registry = registry;
|
|
@@ -169,10 +152,7 @@ export class BuiltinModuleLookup {
|
|
|
169
152
|
async execute(ctx) {
|
|
170
153
|
const mod = this._registry.get(ctx.moduleId);
|
|
171
154
|
if (mod === null) {
|
|
172
|
-
|
|
173
|
-
action: 'abort',
|
|
174
|
-
explanation: `Module not found: ${ctx.moduleId}`,
|
|
175
|
-
};
|
|
155
|
+
throw new ModuleNotFoundError(ctx.moduleId);
|
|
176
156
|
}
|
|
177
157
|
ctx.module = mod;
|
|
178
158
|
return { action: 'continue' };
|
|
@@ -183,24 +163,26 @@ export class BuiltinModuleLookup {
|
|
|
183
163
|
// ---------------------------------------------------------------------------
|
|
184
164
|
/** Enforces access control via the ACL provider. */
|
|
185
165
|
export class BuiltinACLCheck {
|
|
186
|
-
name = '
|
|
166
|
+
name = 'acl_check';
|
|
187
167
|
description = 'Access control list enforcement';
|
|
188
168
|
removable = true;
|
|
189
169
|
replaceable = true;
|
|
170
|
+
pure = true;
|
|
190
171
|
_acl;
|
|
191
172
|
constructor(acl) {
|
|
192
173
|
this._acl = acl;
|
|
193
174
|
}
|
|
175
|
+
/** Update the ACL provider at runtime. */
|
|
176
|
+
setAcl(acl) {
|
|
177
|
+
this._acl = acl;
|
|
178
|
+
}
|
|
194
179
|
async execute(ctx) {
|
|
195
180
|
if (this._acl === null) {
|
|
196
181
|
return { action: 'continue' };
|
|
197
182
|
}
|
|
198
183
|
const allowed = this._acl.check(ctx.context.callerId, ctx.moduleId, ctx.context);
|
|
199
184
|
if (!allowed) {
|
|
200
|
-
|
|
201
|
-
action: 'abort',
|
|
202
|
-
explanation: `Access denied: ${ctx.context.callerId} -> ${ctx.moduleId}`,
|
|
203
|
-
};
|
|
185
|
+
throw new ACLDeniedError(ctx.context.callerId, ctx.moduleId);
|
|
204
186
|
}
|
|
205
187
|
return { action: 'continue' };
|
|
206
188
|
}
|
|
@@ -210,14 +192,19 @@ export class BuiltinACLCheck {
|
|
|
210
192
|
// ---------------------------------------------------------------------------
|
|
211
193
|
/** Handles approval flow for modules that require explicit approval. */
|
|
212
194
|
export class BuiltinApprovalGate {
|
|
213
|
-
name = '
|
|
195
|
+
name = 'approval_gate';
|
|
214
196
|
description = 'Approval handler flow';
|
|
215
197
|
removable = true;
|
|
216
198
|
replaceable = true;
|
|
199
|
+
pure = false;
|
|
217
200
|
_handler;
|
|
218
201
|
constructor(handler) {
|
|
219
202
|
this._handler = handler;
|
|
220
203
|
}
|
|
204
|
+
/** Update the approval handler at runtime. */
|
|
205
|
+
setApprovalHandler(handler) {
|
|
206
|
+
this._handler = handler;
|
|
207
|
+
}
|
|
221
208
|
async execute(ctx) {
|
|
222
209
|
if (this._handler === null) {
|
|
223
210
|
return { action: 'continue' };
|
|
@@ -273,22 +260,13 @@ export class BuiltinApprovalGate {
|
|
|
273
260
|
return { action: 'continue' };
|
|
274
261
|
}
|
|
275
262
|
if (result.status === 'timeout') {
|
|
276
|
-
|
|
277
|
-
action: 'abort',
|
|
278
|
-
explanation: `Approval timed out for module ${ctx.moduleId}`,
|
|
279
|
-
};
|
|
263
|
+
throw new ApprovalTimeoutError(result, ctx.moduleId);
|
|
280
264
|
}
|
|
281
265
|
if (result.status === 'pending') {
|
|
282
|
-
|
|
283
|
-
action: 'abort',
|
|
284
|
-
explanation: `Approval pending for module ${ctx.moduleId}: ${result.approvalId ?? 'unknown'}`,
|
|
285
|
-
};
|
|
266
|
+
throw new ApprovalPendingError(result, ctx.moduleId);
|
|
286
267
|
}
|
|
287
268
|
// rejected or unknown
|
|
288
|
-
|
|
289
|
-
action: 'abort',
|
|
290
|
-
explanation: `Approval denied for module ${ctx.moduleId}: ${result.reason ?? 'no reason'}`,
|
|
291
|
-
};
|
|
269
|
+
throw new ApprovalDeniedError(result, ctx.moduleId);
|
|
292
270
|
}
|
|
293
271
|
}
|
|
294
272
|
// ---------------------------------------------------------------------------
|
|
@@ -296,10 +274,11 @@ export class BuiltinApprovalGate {
|
|
|
296
274
|
// ---------------------------------------------------------------------------
|
|
297
275
|
/** Validates inputs against module schema and redacts sensitive fields. */
|
|
298
276
|
export class BuiltinInputValidation {
|
|
299
|
-
name = '
|
|
277
|
+
name = 'input_validation';
|
|
300
278
|
description = 'Schema validation and redaction for inputs';
|
|
301
279
|
removable = true;
|
|
302
280
|
replaceable = true;
|
|
281
|
+
pure = true;
|
|
303
282
|
async execute(ctx) {
|
|
304
283
|
const mod = ctx.module;
|
|
305
284
|
const inputSchema = resolveSchema(mod, 'inputSchema');
|
|
@@ -307,18 +286,8 @@ export class BuiltinInputValidation {
|
|
|
307
286
|
ctx.validatedInputs = ctx.inputs;
|
|
308
287
|
return { action: 'continue' };
|
|
309
288
|
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
}
|
|
313
|
-
catch (e) {
|
|
314
|
-
if (e instanceof SchemaValidationError) {
|
|
315
|
-
return {
|
|
316
|
-
action: 'abort',
|
|
317
|
-
explanation: e.message,
|
|
318
|
-
};
|
|
319
|
-
}
|
|
320
|
-
throw e;
|
|
321
|
-
}
|
|
289
|
+
// Throws SchemaValidationError directly for error type preservation
|
|
290
|
+
validateSchema(inputSchema, ctx.inputs, 'Input');
|
|
322
291
|
ctx.context.redactedInputs = redactSensitive(ctx.inputs, inputSchema);
|
|
323
292
|
ctx.validatedInputs = ctx.inputs;
|
|
324
293
|
return { action: 'continue' };
|
|
@@ -329,25 +298,31 @@ export class BuiltinInputValidation {
|
|
|
329
298
|
// ---------------------------------------------------------------------------
|
|
330
299
|
/** Executes before-middleware chain via MiddlewareManager. */
|
|
331
300
|
export class BuiltinMiddlewareBefore {
|
|
332
|
-
name = '
|
|
301
|
+
name = 'middleware_before';
|
|
333
302
|
description = 'Execute before-middleware chain';
|
|
334
303
|
removable = true;
|
|
335
304
|
replaceable = false;
|
|
305
|
+
pure = false;
|
|
336
306
|
_middlewareManager;
|
|
337
307
|
constructor(middlewares) {
|
|
338
308
|
this._middlewareManager = middlewares;
|
|
339
309
|
}
|
|
340
310
|
async execute(ctx) {
|
|
341
311
|
try {
|
|
342
|
-
const [effectiveInputs] = this._middlewareManager.executeBefore(ctx.moduleId, ctx.inputs, ctx.context);
|
|
312
|
+
const [effectiveInputs, executedMiddlewares] = this._middlewareManager.executeBefore(ctx.moduleId, ctx.inputs, ctx.context);
|
|
343
313
|
ctx.inputs = effectiveInputs;
|
|
314
|
+
ctx.executedMiddlewares = executedMiddlewares;
|
|
344
315
|
}
|
|
345
316
|
catch (e) {
|
|
346
317
|
if (e instanceof MiddlewareChainError) {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
318
|
+
ctx.executedMiddlewares = e.executedMiddlewares;
|
|
319
|
+
// Try on_error recovery
|
|
320
|
+
const recovery = this._middlewareManager.executeOnError(ctx.moduleId, ctx.inputs, e.original, ctx.context, e.executedMiddlewares);
|
|
321
|
+
if (recovery !== null) {
|
|
322
|
+
ctx.output = recovery;
|
|
323
|
+
return { action: 'skip_to', skipTo: 'return_result' };
|
|
324
|
+
}
|
|
325
|
+
throw e.original;
|
|
351
326
|
}
|
|
352
327
|
throw e;
|
|
353
328
|
}
|
|
@@ -359,10 +334,11 @@ export class BuiltinMiddlewareBefore {
|
|
|
359
334
|
// ---------------------------------------------------------------------------
|
|
360
335
|
/** Executes the module with timeout enforcement. Sets ctx.output. */
|
|
361
336
|
export class BuiltinExecute {
|
|
362
|
-
name = '
|
|
337
|
+
name = 'execute';
|
|
363
338
|
description = 'Execute module with timeout';
|
|
364
339
|
removable = false;
|
|
365
340
|
replaceable = true;
|
|
341
|
+
pure = false;
|
|
366
342
|
_defaultTimeout;
|
|
367
343
|
constructor(config) {
|
|
368
344
|
if (config !== null) {
|
|
@@ -374,20 +350,9 @@ export class BuiltinExecute {
|
|
|
374
350
|
}
|
|
375
351
|
async execute(ctx) {
|
|
376
352
|
const mod = ctx.module;
|
|
377
|
-
// Cancel check before execution
|
|
353
|
+
// Cancel check before execution — throw directly for error type preservation
|
|
378
354
|
if (ctx.context.cancelToken !== null) {
|
|
379
|
-
|
|
380
|
-
ctx.context.cancelToken.check();
|
|
381
|
-
}
|
|
382
|
-
catch (e) {
|
|
383
|
-
if (e instanceof ExecutionCancelledError) {
|
|
384
|
-
return {
|
|
385
|
-
action: 'abort',
|
|
386
|
-
explanation: `Execution cancelled: ${e.message}`,
|
|
387
|
-
};
|
|
388
|
-
}
|
|
389
|
-
throw e;
|
|
390
|
-
}
|
|
355
|
+
ctx.context.cancelToken.check();
|
|
391
356
|
}
|
|
392
357
|
// Streaming path: store the generator on ctx.outputStream
|
|
393
358
|
if (ctx.stream) {
|
|
@@ -404,10 +369,7 @@ export class BuiltinExecute {
|
|
|
404
369
|
if (globalDeadline !== undefined) {
|
|
405
370
|
const remaining = globalDeadline - Date.now();
|
|
406
371
|
if (remaining <= 0) {
|
|
407
|
-
|
|
408
|
-
action: 'abort',
|
|
409
|
-
explanation: `Module timed out: ${ctx.moduleId} (global deadline exceeded)`,
|
|
410
|
-
};
|
|
372
|
+
throw new ModuleTimeoutError(ctx.moduleId, 0);
|
|
411
373
|
}
|
|
412
374
|
if (timeoutMs === 0 || remaining < timeoutMs) {
|
|
413
375
|
timeoutMs = remaining;
|
|
@@ -415,37 +377,23 @@ export class BuiltinExecute {
|
|
|
415
377
|
}
|
|
416
378
|
const executeFn = mod['execute'];
|
|
417
379
|
if (typeof executeFn !== 'function') {
|
|
418
|
-
|
|
419
|
-
action: 'abort',
|
|
420
|
-
explanation: `Module '${ctx.moduleId}' has no execute method`,
|
|
421
|
-
};
|
|
380
|
+
throw new InvalidInputError(`Module '${ctx.moduleId}' has no execute method`);
|
|
422
381
|
}
|
|
423
382
|
const executionPromise = Promise.resolve(executeFn
|
|
424
383
|
.call(mod, ctx.inputs, ctx.context));
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
ctx.output = await executionPromise;
|
|
428
|
-
}
|
|
429
|
-
else {
|
|
430
|
-
let timer;
|
|
431
|
-
const timeoutPromise = new Promise((_, reject) => {
|
|
432
|
-
timer = setTimeout(() => {
|
|
433
|
-
reject(new ModuleTimeoutError(ctx.moduleId, timeoutMs));
|
|
434
|
-
}, timeoutMs);
|
|
435
|
-
});
|
|
436
|
-
ctx.output = await Promise.race([executionPromise, timeoutPromise]).finally(() => {
|
|
437
|
-
clearTimeout(timer);
|
|
438
|
-
});
|
|
439
|
-
}
|
|
384
|
+
if (timeoutMs === 0) {
|
|
385
|
+
ctx.output = await executionPromise;
|
|
440
386
|
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
};
|
|
447
|
-
}
|
|
448
|
-
|
|
387
|
+
else {
|
|
388
|
+
let timer;
|
|
389
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
390
|
+
timer = setTimeout(() => {
|
|
391
|
+
reject(new ModuleTimeoutError(ctx.moduleId, timeoutMs));
|
|
392
|
+
}, timeoutMs);
|
|
393
|
+
});
|
|
394
|
+
ctx.output = await Promise.race([executionPromise, timeoutPromise]).finally(() => {
|
|
395
|
+
clearTimeout(timer);
|
|
396
|
+
});
|
|
449
397
|
}
|
|
450
398
|
return { action: 'continue' };
|
|
451
399
|
}
|
|
@@ -455,30 +403,26 @@ export class BuiltinExecute {
|
|
|
455
403
|
// ---------------------------------------------------------------------------
|
|
456
404
|
/** Validates output against module schema and redacts sensitive fields. */
|
|
457
405
|
export class BuiltinOutputValidation {
|
|
458
|
-
name = '
|
|
406
|
+
name = 'output_validation';
|
|
459
407
|
description = 'Schema validation and redaction for output';
|
|
460
408
|
removable = true;
|
|
461
409
|
replaceable = true;
|
|
410
|
+
pure = true;
|
|
462
411
|
async execute(ctx) {
|
|
412
|
+
// Skip when no output is available: streaming (Phase 3 handles it),
|
|
413
|
+
// dry_run (execute step was skipped), etc.
|
|
414
|
+
if (ctx.output == null) {
|
|
415
|
+
return { action: 'continue' };
|
|
416
|
+
}
|
|
463
417
|
const mod = ctx.module;
|
|
464
|
-
const output = ctx.output
|
|
418
|
+
const output = ctx.output;
|
|
465
419
|
const outputSchema = resolveSchema(mod, 'outputSchema');
|
|
466
420
|
if (outputSchema == null) {
|
|
467
421
|
ctx.validatedOutput = output;
|
|
468
422
|
return { action: 'continue' };
|
|
469
423
|
}
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
}
|
|
473
|
-
catch (e) {
|
|
474
|
-
if (e instanceof SchemaValidationError) {
|
|
475
|
-
return {
|
|
476
|
-
action: 'abort',
|
|
477
|
-
explanation: e.message,
|
|
478
|
-
};
|
|
479
|
-
}
|
|
480
|
-
throw e;
|
|
481
|
-
}
|
|
424
|
+
// Throws SchemaValidationError directly for error type preservation
|
|
425
|
+
validateSchema(outputSchema, output, 'Output');
|
|
482
426
|
ctx.validatedOutput = output;
|
|
483
427
|
return { action: 'continue' };
|
|
484
428
|
}
|
|
@@ -488,16 +432,21 @@ export class BuiltinOutputValidation {
|
|
|
488
432
|
// ---------------------------------------------------------------------------
|
|
489
433
|
/** Executes after-middleware chain via MiddlewareManager. */
|
|
490
434
|
export class BuiltinMiddlewareAfter {
|
|
491
|
-
name = '
|
|
435
|
+
name = 'middleware_after';
|
|
492
436
|
description = 'Execute after-middleware chain';
|
|
493
437
|
removable = true;
|
|
494
438
|
replaceable = false;
|
|
439
|
+
pure = false;
|
|
495
440
|
_middlewareManager;
|
|
496
441
|
constructor(middlewares) {
|
|
497
442
|
this._middlewareManager = middlewares;
|
|
498
443
|
}
|
|
499
444
|
async execute(ctx) {
|
|
500
|
-
|
|
445
|
+
// Skip when no output is available (streaming Phase 1, dry_run, etc.)
|
|
446
|
+
if (ctx.output == null) {
|
|
447
|
+
return { action: 'continue' };
|
|
448
|
+
}
|
|
449
|
+
const output = ctx.output;
|
|
501
450
|
const transformed = this._middlewareManager.executeAfter(ctx.moduleId, ctx.inputs, output, ctx.context);
|
|
502
451
|
ctx.output = transformed;
|
|
503
452
|
return { action: 'continue' };
|
|
@@ -508,10 +457,11 @@ export class BuiltinMiddlewareAfter {
|
|
|
508
457
|
// ---------------------------------------------------------------------------
|
|
509
458
|
/** Finalizes the pipeline result. Output is already on ctx.output. */
|
|
510
459
|
export class BuiltinReturnResult {
|
|
511
|
-
name = '
|
|
460
|
+
name = 'return_result';
|
|
512
461
|
description = 'Finalize pipeline result';
|
|
513
462
|
removable = false;
|
|
514
463
|
replaceable = false;
|
|
464
|
+
pure = true;
|
|
515
465
|
async execute(_ctx) {
|
|
516
466
|
// No-op: output is already on ctx.output from previous steps
|
|
517
467
|
return { action: 'continue' };
|
|
@@ -521,12 +471,12 @@ export class BuiltinReturnResult {
|
|
|
521
471
|
export function buildStandardStrategy(deps) {
|
|
522
472
|
return new ExecutionStrategy('standard', [
|
|
523
473
|
new BuiltinContextCreation(deps.config),
|
|
524
|
-
new
|
|
474
|
+
new BuiltinCallChainGuard(deps.config),
|
|
525
475
|
new BuiltinModuleLookup(deps.registry),
|
|
526
476
|
new BuiltinACLCheck(deps.acl),
|
|
527
477
|
new BuiltinApprovalGate(deps.approvalHandler),
|
|
528
|
-
new BuiltinInputValidation(),
|
|
529
478
|
new BuiltinMiddlewareBefore(deps.middlewareManager),
|
|
479
|
+
new BuiltinInputValidation(),
|
|
530
480
|
new BuiltinExecute(deps.config),
|
|
531
481
|
new BuiltinOutputValidation(),
|
|
532
482
|
new BuiltinMiddlewareAfter(deps.middlewareManager),
|
|
@@ -540,10 +490,10 @@ export function buildStandardStrategy(deps) {
|
|
|
540
490
|
export function buildInternalStrategy(deps) {
|
|
541
491
|
return new ExecutionStrategy('internal', [
|
|
542
492
|
new BuiltinContextCreation(deps.config),
|
|
543
|
-
new
|
|
493
|
+
new BuiltinCallChainGuard(deps.config),
|
|
544
494
|
new BuiltinModuleLookup(deps.registry),
|
|
545
|
-
new BuiltinInputValidation(),
|
|
546
495
|
new BuiltinMiddlewareBefore(deps.middlewareManager),
|
|
496
|
+
new BuiltinInputValidation(),
|
|
547
497
|
new BuiltinExecute(deps.config),
|
|
548
498
|
new BuiltinOutputValidation(),
|
|
549
499
|
new BuiltinMiddlewareAfter(deps.middlewareManager),
|
|
@@ -569,11 +519,11 @@ export function buildTestingStrategy(deps) {
|
|
|
569
519
|
export function buildPerformanceStrategy(deps) {
|
|
570
520
|
return new ExecutionStrategy('performance', [
|
|
571
521
|
new BuiltinContextCreation(deps.config),
|
|
572
|
-
new
|
|
522
|
+
new BuiltinCallChainGuard(deps.config),
|
|
573
523
|
new BuiltinModuleLookup(deps.registry),
|
|
574
524
|
new BuiltinACLCheck(deps.acl),
|
|
575
|
-
new BuiltinInputValidation(),
|
|
576
525
|
new BuiltinMiddlewareBefore(deps.middlewareManager),
|
|
526
|
+
new BuiltinInputValidation(),
|
|
577
527
|
new BuiltinExecute(deps.config),
|
|
578
528
|
new BuiltinMiddlewareAfter(deps.middlewareManager),
|
|
579
529
|
new BuiltinReturnResult(),
|