@pikku/core 0.12.69 → 0.12.71
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/CHANGELOG.md +422 -0
- package/LICENSE +21 -0
- package/README.md +34 -2
- package/dist/function/functions.types.d.ts +27 -0
- package/dist/index.d.ts +1 -1
- package/dist/internal.d.ts +1 -1
- package/dist/internal.js +1 -1
- package/dist/pikku-state.js +1 -0
- package/dist/services/http-scenario-actors.d.ts +12 -4
- package/dist/services/http-scenario-actors.js +47 -45
- package/dist/services/in-memory-queue-service.d.ts +6 -0
- package/dist/services/in-memory-queue-service.js +8 -1
- package/dist/services/in-memory-workflow-service.d.ts +3 -5
- package/dist/services/in-memory-workflow-service.js +10 -19
- package/dist/services/index.d.ts +2 -1
- package/dist/services/index.js +1 -0
- package/dist/services/meta-service.d.ts +5 -1
- package/dist/services/meta-service.js +44 -18
- package/dist/services/scenario-actors-service.d.ts +108 -2
- package/dist/services/scenario-actors-service.js +40 -1
- package/dist/services/workflow-service.d.ts +7 -5
- package/dist/types/core.types.d.ts +28 -3
- package/dist/types/state.types.d.ts +3 -1
- package/dist/wirings/actor-flow/actor-flow.types.d.ts +1 -1
- package/dist/wirings/actor-flow/index.d.ts +1 -1
- package/dist/wirings/actor-flow/run-conversation.d.ts +10 -10
- package/dist/wirings/actor-flow/run-conversation.js +27 -27
- package/dist/wirings/ai-agent/ai-agent-agui.js +0 -8
- package/dist/wirings/ai-agent/ai-agent-prepare.js +1 -2
- package/dist/wirings/ai-agent/ai-agent.types.d.ts +0 -6
- package/dist/wirings/cli/command-parser.js +11 -1
- package/dist/wirings/rpc/rpc-runner.js +1 -1
- package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +52 -3
- package/dist/wirings/workflow/feature.d.ts +28 -0
- package/dist/wirings/workflow/feature.js +57 -0
- package/dist/wirings/workflow/graph/graph-runner.js +3 -2
- package/dist/wirings/workflow/graph/graph-validation.d.ts +0 -2
- package/dist/wirings/workflow/graph/graph-validation.js +0 -142
- package/dist/wirings/workflow/graph/index.d.ts +1 -1
- package/dist/wirings/workflow/graph/index.js +1 -1
- package/dist/wirings/workflow/index.d.ts +13 -3
- package/dist/wirings/workflow/index.js +15 -2
- package/dist/wirings/workflow/pikku-scenario-service.d.ts +121 -0
- package/dist/wirings/workflow/pikku-scenario-service.js +419 -0
- package/dist/wirings/workflow/pikku-workflow-service.d.ts +170 -23
- package/dist/wirings/workflow/pikku-workflow-service.js +338 -297
- package/dist/wirings/workflow/scenario-cookie-jar.d.ts +29 -0
- package/dist/wirings/workflow/scenario-cookie-jar.js +51 -0
- package/dist/wirings/workflow/scenario-poll.d.ts +20 -0
- package/dist/wirings/workflow/scenario-poll.js +25 -0
- package/dist/wirings/workflow/scenario-prose.d.ts +38 -0
- package/dist/wirings/workflow/scenario-prose.js +45 -0
- package/dist/wirings/workflow/scenario-step-guards.d.ts +16 -0
- package/dist/wirings/workflow/scenario-step-guards.js +29 -0
- package/dist/wirings/workflow/scenario-step.types.d.ts +148 -0
- package/dist/wirings/workflow/scenario-step.types.js +1 -0
- package/dist/wirings/workflow/workflow.types.d.ts +82 -8
- package/package.json +3 -1
- package/src/function/functions.types.ts +32 -0
- package/src/index.ts +1 -0
- package/src/internal.ts +5 -1
- package/src/pikku-state.ts +1 -0
- package/src/services/http-scenario-actors.test.ts +85 -1
- package/src/services/http-scenario-actors.ts +65 -51
- package/src/services/in-memory-queue-service.test.ts +66 -1
- package/src/services/in-memory-queue-service.ts +13 -2
- package/src/services/in-memory-workflow-service.ts +12 -25
- package/src/services/index.ts +5 -0
- package/src/services/meta-service.test.ts +79 -0
- package/src/services/meta-service.ts +61 -26
- package/src/services/scenario-actors-service.ts +157 -2
- package/src/services/workflow-service.ts +7 -4
- package/src/types/core.types.ts +34 -2
- package/src/types/state.types.ts +3 -0
- package/src/wirings/actor-flow/actor-flow.types.ts +1 -1
- package/src/wirings/actor-flow/index.ts +1 -1
- package/src/wirings/actor-flow/run-conversation.test.ts +12 -6
- package/src/wirings/actor-flow/run-conversation.ts +36 -41
- package/src/wirings/ai-agent/ai-agent-agui.test.ts +0 -16
- package/src/wirings/ai-agent/ai-agent-agui.ts +0 -9
- package/src/wirings/ai-agent/ai-agent-prepare.ts +1 -2
- package/src/wirings/ai-agent/ai-agent.types.ts +0 -7
- package/src/wirings/cli/command-parser.test.ts +60 -0
- package/src/wirings/cli/command-parser.ts +12 -1
- package/src/wirings/rpc/rpc-runner.test.ts +28 -5
- package/src/wirings/rpc/rpc-runner.ts +1 -1
- package/src/wirings/workflow/dsl/workflow-dsl.types.ts +86 -2
- package/src/wirings/workflow/feature.test.ts +131 -0
- package/src/wirings/workflow/feature.ts +78 -0
- package/src/wirings/workflow/graph/graph-runner.ts +3 -2
- package/src/wirings/workflow/graph/graph-validation.test.ts +1 -144
- package/src/wirings/workflow/graph/graph-validation.ts +0 -196
- package/src/wirings/workflow/graph/index.ts +1 -5
- package/src/wirings/workflow/index.ts +73 -6
- package/src/wirings/workflow/pikku-scenario-service.ts +682 -0
- package/src/wirings/workflow/pikku-workflow-service.test.ts +55 -0
- package/src/wirings/workflow/pikku-workflow-service.ts +572 -419
- package/src/wirings/workflow/scenario-cookie-jar.test.ts +108 -0
- package/src/wirings/workflow/scenario-cookie-jar.ts +65 -0
- package/src/wirings/workflow/scenario-expectations.test.ts +153 -0
- package/src/wirings/workflow/scenario-hooks.test.ts +212 -0
- package/src/wirings/workflow/scenario-poll.test.ts +66 -0
- package/src/wirings/workflow/scenario-poll.ts +36 -0
- package/src/wirings/workflow/scenario-prose.test.ts +152 -0
- package/src/wirings/workflow/scenario-prose.ts +79 -0
- package/src/wirings/workflow/scenario-service.test.ts +155 -0
- package/src/wirings/workflow/scenario-step-guards.ts +43 -0
- package/src/wirings/workflow/scenario-step.test.ts +442 -9
- package/src/wirings/workflow/scenario-step.types.ts +157 -0
- package/src/wirings/workflow/workflow-dispatch-durability.test.ts +1 -1
- package/src/wirings/workflow/workflow-dispatch-payload.test.ts +59 -0
- package/src/wirings/workflow/workflow-mirror.test.ts +178 -0
- package/src/wirings/workflow/workflow-replay-snapshot.test.ts +139 -0
- package/src/wirings/workflow/workflow-run-context.test.ts +177 -0
- package/src/wirings/workflow/workflow-run-polling.test.ts +132 -0
- package/src/wirings/workflow/workflow-step-ordinal.test.ts +4 -4
- package/src/wirings/workflow/workflow.types.ts +99 -5
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { pikkuState } from '../../../pikku-state.js';
|
|
2
|
-
import { resolveNamespace } from '../../rpc/rpc-runner.js';
|
|
3
1
|
function normalizeTargets(value) {
|
|
4
2
|
if (!value)
|
|
5
3
|
return [];
|
|
@@ -16,146 +14,6 @@ function normalizeTargets(value) {
|
|
|
16
14
|
}
|
|
17
15
|
return [];
|
|
18
16
|
}
|
|
19
|
-
function collectRefs(value, refs) {
|
|
20
|
-
if (typeof value === 'object' &&
|
|
21
|
-
value !== null &&
|
|
22
|
-
'$ref' in value &&
|
|
23
|
-
typeof value.$ref === 'string') {
|
|
24
|
-
refs.add(value.$ref);
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
if (Array.isArray(value)) {
|
|
28
|
-
for (const item of value)
|
|
29
|
-
collectRefs(item, refs);
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
if (typeof value === 'object' && value !== null) {
|
|
33
|
-
for (const v of Object.values(value))
|
|
34
|
-
collectRefs(v, refs);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
function resolveToolMeta(toolName) {
|
|
38
|
-
const resolved = toolName.includes(':') ? resolveNamespace(toolName) : null;
|
|
39
|
-
if (resolved) {
|
|
40
|
-
const fnMeta = pikkuState(resolved.package, 'function', 'meta')[resolved.function];
|
|
41
|
-
const schemas = pikkuState(resolved.package, 'misc', 'schemas');
|
|
42
|
-
return fnMeta ? { fnMeta, schemas } : null;
|
|
43
|
-
}
|
|
44
|
-
const rpcMeta = pikkuState(null, 'rpc', 'meta');
|
|
45
|
-
const pikkuFuncId = rpcMeta[toolName];
|
|
46
|
-
if (!pikkuFuncId)
|
|
47
|
-
return null;
|
|
48
|
-
const fnMeta = pikkuState(null, 'function', 'meta')[pikkuFuncId];
|
|
49
|
-
const schemas = pikkuState(null, 'misc', 'schemas');
|
|
50
|
-
return fnMeta ? { fnMeta, schemas } : null;
|
|
51
|
-
}
|
|
52
|
-
export function computeEntryNodeIds(nodes) {
|
|
53
|
-
const referenced = new Set();
|
|
54
|
-
for (const node of Object.values(nodes)) {
|
|
55
|
-
if (node.next) {
|
|
56
|
-
for (const target of normalizeTargets(node.next)) {
|
|
57
|
-
referenced.add(target);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
if (node.onError) {
|
|
61
|
-
for (const target of normalizeTargets(node.onError)) {
|
|
62
|
-
referenced.add(target);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
return Object.keys(nodes).filter((id) => !referenced.has(id));
|
|
67
|
-
}
|
|
68
|
-
export function validateWorkflowWiring(nodes, toolNames) {
|
|
69
|
-
const errors = [];
|
|
70
|
-
const nodeIds = new Set(Object.keys(nodes));
|
|
71
|
-
const toolSet = new Set(toolNames);
|
|
72
|
-
for (const [nodeId, node] of Object.entries(nodes)) {
|
|
73
|
-
if (!node.rpcName) {
|
|
74
|
-
errors.push(`Node '${nodeId}' is missing 'rpcName'`);
|
|
75
|
-
continue;
|
|
76
|
-
}
|
|
77
|
-
if (!toolSet.has(node.rpcName)) {
|
|
78
|
-
errors.push(`Node '${nodeId}' references unknown tool '${node.rpcName}'. Available tools: ${toolNames.join(', ')}`);
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
81
|
-
const nextTargets = normalizeTargets(node.next);
|
|
82
|
-
for (const target of nextTargets) {
|
|
83
|
-
if (!nodeIds.has(target)) {
|
|
84
|
-
errors.push(`Node '${nodeId}' routes to unknown node '${target}' in 'next'`);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
const errorTargets = normalizeTargets(node.onError);
|
|
88
|
-
for (const target of errorTargets) {
|
|
89
|
-
if (!nodeIds.has(target)) {
|
|
90
|
-
errors.push(`Node '${nodeId}' routes to unknown node '${target}' in 'onError'`);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
if (!node.input)
|
|
94
|
-
continue;
|
|
95
|
-
const refs = new Set();
|
|
96
|
-
collectRefs(node.input, refs);
|
|
97
|
-
for (const ref of refs) {
|
|
98
|
-
if (ref === 'trigger' || ref === '$item') {
|
|
99
|
-
const targetMeta = resolveToolMeta(node.rpcName);
|
|
100
|
-
if (targetMeta?.fnMeta?.inputSchemaName) {
|
|
101
|
-
const targetSchema = targetMeta.schemas.get(targetMeta.fnMeta.inputSchemaName);
|
|
102
|
-
if (targetSchema?.properties) {
|
|
103
|
-
for (const [field, fieldValue] of Object.entries(node.input)) {
|
|
104
|
-
if (typeof fieldValue === 'object' &&
|
|
105
|
-
fieldValue !== null &&
|
|
106
|
-
fieldValue.$ref === ref &&
|
|
107
|
-
!fieldValue.path) {
|
|
108
|
-
const targetType = targetSchema.properties[field]?.type;
|
|
109
|
-
if (targetType && targetType !== 'object') {
|
|
110
|
-
errors.push(`Node '${nodeId}' input field '${field}' expects type '${targetType}', but references the whole ${ref} object without a path. Use { $ref: "${ref}", path: "${field}" } to extract the field.`);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
continue;
|
|
117
|
-
}
|
|
118
|
-
if (!nodeIds.has(ref)) {
|
|
119
|
-
errors.push(`Node '${nodeId}' references unknown node '${ref}' in input`);
|
|
120
|
-
continue;
|
|
121
|
-
}
|
|
122
|
-
const sourceNode = nodes[ref];
|
|
123
|
-
if (!sourceNode?.rpcName)
|
|
124
|
-
continue;
|
|
125
|
-
const sourceMeta = resolveToolMeta(sourceNode.rpcName);
|
|
126
|
-
if (!sourceMeta?.fnMeta?.outputSchemaName)
|
|
127
|
-
continue;
|
|
128
|
-
const sourceSchema = sourceMeta.schemas.get(sourceMeta.fnMeta.outputSchemaName);
|
|
129
|
-
if (!sourceSchema?.properties)
|
|
130
|
-
continue;
|
|
131
|
-
for (const [field, fieldValue] of Object.entries(node.input)) {
|
|
132
|
-
if (typeof fieldValue === 'object' &&
|
|
133
|
-
fieldValue !== null &&
|
|
134
|
-
fieldValue.$ref === ref &&
|
|
135
|
-
fieldValue.path) {
|
|
136
|
-
const pathRoot = fieldValue.path.split('.')[0];
|
|
137
|
-
if (sourceSchema.properties &&
|
|
138
|
-
!(pathRoot in sourceSchema.properties)) {
|
|
139
|
-
errors.push(`Node '${nodeId}' input field '${field}' references path '${fieldValue.path}' but node '${ref}' (${sourceNode.rpcName}) output has no property '${pathRoot}'`);
|
|
140
|
-
continue;
|
|
141
|
-
}
|
|
142
|
-
const targetMeta = resolveToolMeta(node.rpcName);
|
|
143
|
-
if (!targetMeta?.fnMeta?.inputSchemaName)
|
|
144
|
-
continue;
|
|
145
|
-
const targetSchema = targetMeta.schemas.get(targetMeta.fnMeta.inputSchemaName);
|
|
146
|
-
if (!targetSchema?.properties?.[field])
|
|
147
|
-
continue;
|
|
148
|
-
const sourceType = sourceSchema.properties[pathRoot]?.type;
|
|
149
|
-
const targetType = targetSchema.properties[field].type;
|
|
150
|
-
if (sourceType && targetType && sourceType !== targetType) {
|
|
151
|
-
errors.push(`Node '${nodeId}' input field '${field}' expects type '${targetType}', but node '${ref}' output field '${pathRoot}' is type '${sourceType}'`);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
return errors;
|
|
158
|
-
}
|
|
159
17
|
export function generateMermaidDiagram(workflowName, nodes, entryNodeIds) {
|
|
160
18
|
const lines = ['graph TD'];
|
|
161
19
|
for (const [nodeId, node] of Object.entries(nodes)) {
|
|
@@ -2,4 +2,4 @@ export { continueGraph, executeGraphStep, onGraphNodeComplete, runFromMeta, runW
|
|
|
2
2
|
export { template } from './template.js';
|
|
3
3
|
export type { TemplateString } from './template.js';
|
|
4
4
|
export { pikkuWorkflowGraph, type PikkuWorkflowGraphConfig, type PikkuWorkflowGraphResult, } from './wire-workflow-graph.js';
|
|
5
|
-
export {
|
|
5
|
+
export { generateMermaidDiagram } from './graph-validation.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { continueGraph, executeGraphStep, onGraphNodeComplete, runFromMeta, runWorkflowGraph, } from './graph-runner.js';
|
|
2
2
|
export { template } from './template.js';
|
|
3
3
|
export { pikkuWorkflowGraph, } from './wire-workflow-graph.js';
|
|
4
|
-
export {
|
|
4
|
+
export { generateMermaidDiagram } from './graph-validation.js';
|
|
@@ -2,14 +2,24 @@
|
|
|
2
2
|
* Workflow module exports
|
|
3
3
|
*/
|
|
4
4
|
export { PikkuWorkflowService, WorkflowCancelledException, WorkflowSuspendedException, WorkflowDispatchException, WorkflowNotFoundError, WorkflowRunNotFoundError, WorkflowApprovalResolvedError, DEFAULT_STEP_RETRIES, } from './pikku-workflow-service.js';
|
|
5
|
+
export type { RunLifecycleContext, WorkflowRunEngine, WorkflowRunExtension, } from './pikku-workflow-service.js';
|
|
5
6
|
export { deriveInvocationId, uuidv5 } from './workflow-invocation-id.js';
|
|
6
7
|
export { buildRunTimeline, reconstructStateAt, reconstructFinalState, } from './run-timeline.js';
|
|
7
8
|
export type { RunTimeline, RunTimelineEvent, ReconstructedRunState, ReconstructedStep, RunPhase, } from './run-timeline.js';
|
|
8
9
|
export { addWorkflow } from './dsl/workflow-runner.js';
|
|
10
|
+
export { addFeature, resolveFeatureScenarios } from './feature.js';
|
|
9
11
|
export { template, type TemplateString } from './graph/template.js';
|
|
10
12
|
export { pikkuWorkflowGraph, type PikkuWorkflowGraphConfig, type PikkuWorkflowGraphResult, } from './graph/wire-workflow-graph.js';
|
|
11
|
-
export { validateWorkflowWiring, computeEntryNodeIds, } from './graph/graph-validation.js';
|
|
12
13
|
export { pikkuWorkflowWorkerFunc, pikkuWorkflowOrchestratorFunc, pikkuWorkflowSleeperFunc, } from './workflow-queue-workers.js';
|
|
13
14
|
export type { WorkflowStepInput as WorkflowStepQueueInput, PikkuWorkflowOrchestratorInput, PikkuWorkflowSleeperInput, } from './workflow-queue-workers.js';
|
|
14
|
-
export type { WorkflowService, WorkflowQueueOptions, WorkflowServiceConfig, WorkflowPlannedStep, WorkflowRunWire, WorkflowStatus, WorkflowVersionStatus, StepStatus, WorkflowRun, WorkflowRunStatus, StepState, WorkflowRunService, WorkflowRunMirror, CoreWorkflow, PikkuWorkflow, ContextVariable, WorkflowContext, WorkflowsMeta, WorkflowRuntimeMeta, WorkflowsRuntimeMeta, WorkflowStepInput, WorkflowOrchestratorInput, WorkflowSleeperInput, } from './workflow.types.js';
|
|
15
|
-
export type { WorkflowStepOptions, WorkflowWireDoRPC, WorkflowWireDoInline, WorkflowWireSleep, WorkflowWireSuspend, WorkflowWireApproval, WorkflowApprovalOptions, ApprovalOutcome, InputSource, OutputBinding, RpcStepMeta, SimpleCondition, Condition, BranchCase, BranchStepMeta, ParallelGroupStepMeta, FanoutStepMeta, ReturnStepMeta, InlineStepMeta, SleepStepMeta, CancelStepMeta, SuspendStepMeta, ApprovalStepMeta, SetStepMeta, SwitchCaseMeta, SwitchStepMeta, FilterStepMeta, ArrayPredicateStepMeta, WorkflowStepMeta, WorkflowStepWire, PikkuWorkflowWire, PikkuScenarioWire, } from './workflow.types.js';
|
|
15
|
+
export type { WorkflowService, WorkflowQueueOptions, WorkflowServiceConfig, WorkflowPlannedStep, WorkflowRunWire, WorkflowStatus, WorkflowVersionStatus, StepStatus, WorkflowRun, WorkflowRunStatus, StepState, WorkflowRunService, WorkflowRunMirror, CoreWorkflow, CoreFeature, CoreFeatureScenario, FeatureMeta, FeatureMetaEntry, FeaturesMeta, FeaturePlanEntry, PikkuWorkflow, ContextVariable, WorkflowContext, WorkflowsMeta, WorkflowRuntimeMeta, WorkflowsRuntimeMeta, WorkflowStepInput, WorkflowOrchestratorInput, WorkflowSleeperInput, } from './workflow.types.js';
|
|
16
|
+
export type { WorkflowStepOptions, WorkflowWireDoRPC, WorkflowWireDoInline, WorkflowWireSleep, WorkflowWireSuspend, WorkflowWireApproval, WorkflowApprovalOptions, ApprovalOutcome, InputSource, OutputBinding, RpcStepMeta, SimpleCondition, Condition, BranchCase, BranchStepMeta, ParallelGroupStepMeta, FanoutStepMeta, ReturnStepMeta, InlineStepMeta, SleepStepMeta, CancelStepMeta, SuspendStepMeta, ApprovalStepMeta, SetStepMeta, SwitchCaseMeta, SwitchStepMeta, FilterStepMeta, ArrayPredicateStepMeta, ScenarioStepInvocation, ScenarioStepMeta, WorkflowStepMeta, WorkflowStepWire, PikkuWorkflowWire, PikkuScenarioWire, } from './workflow.types.js';
|
|
17
|
+
export type { ScenarioStepPhase, ScenarioStepOptions, PikkuScenarioStepWire, ScenarioEnvironment, } from './scenario-step.types.js';
|
|
18
|
+
export { requireActor, requireScenarioEnv } from './scenario-step-guards.js';
|
|
19
|
+
export { pollUntil, type PollOptions } from './scenario-poll.js';
|
|
20
|
+
export { createCookieJar } from './scenario-cookie-jar.js';
|
|
21
|
+
export type { ScenarioCookieJar } from './scenario-cookie-jar.js';
|
|
22
|
+
export type { ScenarioHttpResponse, ScenarioJsonRequest, } from '../../services/scenario-actors-service.js';
|
|
23
|
+
export { readScenarioHttpResponse, postScenarioJson, } from '../../services/scenario-actors-service.js';
|
|
24
|
+
export type { PikkuBrowserWire, TestIdSelector, ScenarioBrowserProvider, ScenarioBrowserFailure, } from './scenario-step.types.js';
|
|
25
|
+
export { composeStepProse, renderStepTemplate } from './scenario-prose.js';
|
|
@@ -7,10 +7,23 @@ export { deriveInvocationId, uuidv5 } from './workflow-invocation-id.js';
|
|
|
7
7
|
export { buildRunTimeline, reconstructStateAt, reconstructFinalState, } from './run-timeline.js';
|
|
8
8
|
// Internal registration functions (used by generated code)
|
|
9
9
|
export { addWorkflow } from './dsl/workflow-runner.js';
|
|
10
|
+
export { addFeature, resolveFeatureScenarios } from './feature.js';
|
|
10
11
|
// Graph helpers (template, pikkuWorkflowGraph)
|
|
11
12
|
export { template } from './graph/template.js';
|
|
12
13
|
export { pikkuWorkflowGraph, } from './graph/wire-workflow-graph.js';
|
|
13
|
-
// Graph validation and dynamic workflow utilities
|
|
14
|
-
export { validateWorkflowWiring, computeEntryNodeIds, } from './graph/graph-validation.js';
|
|
15
14
|
// Queue worker functions (registered by codegen, executed at runtime)
|
|
16
15
|
export { pikkuWorkflowWorkerFunc, pikkuWorkflowOrchestratorFunc, pikkuWorkflowSleeperFunc, } from './workflow-queue-workers.js';
|
|
16
|
+
// Narrows the optional halves of the step wire, with a message that says what to do
|
|
17
|
+
export { requireActor, requireScenarioEnv } from './scenario-step-guards.js';
|
|
18
|
+
// Waits for the target to catch up, without every step writing the loop again
|
|
19
|
+
export { pollUntil } from './scenario-poll.js';
|
|
20
|
+
// Persists cookies across a step's requests, the way a browser would
|
|
21
|
+
export { createCookieJar } from './scenario-cookie-jar.js';
|
|
22
|
+
export { readScenarioHttpResponse, postScenarioJson, } from '../../services/scenario-actors-service.js';
|
|
23
|
+
/* ------------------------------------------------------------------ *
|
|
24
|
+
* Scenarios — reporting a run
|
|
25
|
+
*
|
|
26
|
+
* Used by the CLI reporter and the console, so the two render the same
|
|
27
|
+
* sentence for the same step. A step body needs none of it.
|
|
28
|
+
* ------------------------------------------------------------------ */
|
|
29
|
+
export { composeStepProse, renderStepTemplate } from './scenario-prose.js';
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { PikkuError } from '../../errors/error-handler.js';
|
|
2
|
+
import { InMemoryWorkflowService } from '../../services/in-memory-workflow-service.js';
|
|
3
|
+
import { type RunLifecycleContext, type WorkflowRunEngine, type WorkflowRunExtension } from './pikku-workflow-service.js';
|
|
4
|
+
import type { PikkuWire } from '../../types/core.types.js';
|
|
5
|
+
import type { ScenarioActors } from '../../services/scenario-actors-service.js';
|
|
6
|
+
import type { ScenarioBrowserProvider, ScenarioEnvironment } from './scenario-step.types.js';
|
|
7
|
+
import type { PikkuWorkflowWire, WorkflowQueueOptions } from './workflow.types.js';
|
|
8
|
+
/**
|
|
9
|
+
* A workflow service with the scenario capability attached — the two lines
|
|
10
|
+
* `pikku scenario run` needs, in one call so no caller has to remember that the
|
|
11
|
+
* capability is installed rather than inherited.
|
|
12
|
+
*
|
|
13
|
+
* The in-memory service is the right engine because a scenario run is a single
|
|
14
|
+
* external process driving a deployed app over its real transport: there is
|
|
15
|
+
* nothing to persist and no second worker to resume it.
|
|
16
|
+
*/
|
|
17
|
+
export declare const createScenarioRunner: (options?: WorkflowQueueOptions) => {
|
|
18
|
+
workflowService: InMemoryWorkflowService;
|
|
19
|
+
scenarioService: PikkuScenarioService;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* A scenario's `before` or `after` hook threw. The original error is kept as
|
|
23
|
+
* the `cause` so the failure that actually happened is never lost behind the
|
|
24
|
+
* label saying which phase it happened in.
|
|
25
|
+
*/
|
|
26
|
+
export declare class ScenarioHookError extends PikkuError {
|
|
27
|
+
readonly scenarioName: string;
|
|
28
|
+
readonly phase: 'before' | 'after';
|
|
29
|
+
constructor(scenarioName: string, phase: 'before' | 'after', cause: unknown);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The scenario capability, layered onto a workflow service rather than being
|
|
33
|
+
* one.
|
|
34
|
+
*
|
|
35
|
+
* Every scenario affordance — steps, actors, lifecycle hooks, the browser
|
|
36
|
+
* provider, the assertion wire members — lives here rather than on
|
|
37
|
+
* `PikkuWorkflowService`, because a bundler drops an unused *module* but never
|
|
38
|
+
* an unused class member: anything declared on the workflow service ships in
|
|
39
|
+
* every server built on Pikku, along with everything it imports. Scenarios only
|
|
40
|
+
* ever run from `pikku scenario run`, so the whole surface stays behind an
|
|
41
|
+
* import only that runner makes.
|
|
42
|
+
*
|
|
43
|
+
* It is not a workflow service because a scenario is not a different kind of
|
|
44
|
+
* run — it is the same durable run with a step vocabulary on top. What it
|
|
45
|
+
* needs from the engine it gets through the narrow `WorkflowRunEngine` handle,
|
|
46
|
+
* which is why recording a step never became public API.
|
|
47
|
+
*
|
|
48
|
+
* ```ts
|
|
49
|
+
* const workflowService = new InMemoryWorkflowService()
|
|
50
|
+
* const scenarioService = workflowService.setRunExtension(
|
|
51
|
+
* (engine) => new PikkuScenarioService(engine)
|
|
52
|
+
* )
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export declare class PikkuScenarioService implements WorkflowRunExtension {
|
|
56
|
+
private readonly engine;
|
|
57
|
+
private runActors;
|
|
58
|
+
private scenarioBrowserProvider?;
|
|
59
|
+
private scenarioEnvironment?;
|
|
60
|
+
constructor(engine: WorkflowRunEngine);
|
|
61
|
+
/**
|
|
62
|
+
* Registered by `@pikku/playwright` (or any other driver) before a scenario
|
|
63
|
+
* runs. Absent means browser steps cannot run, which the CLI checks up front
|
|
64
|
+
* so a run fails fast rather than mid-flow.
|
|
65
|
+
*/
|
|
66
|
+
setScenarioBrowserProvider(provider: ScenarioBrowserProvider | undefined): void;
|
|
67
|
+
getScenarioBrowserProvider(): ScenarioBrowserProvider | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* The environment scenario steps run against, set once by the runner. It is
|
|
70
|
+
* per-service rather than per-run because a runner process targets exactly
|
|
71
|
+
* one environment for every scenario it executes.
|
|
72
|
+
*/
|
|
73
|
+
setScenarioEnvironment(env: ScenarioEnvironment | undefined): void;
|
|
74
|
+
getScenarioEnvironment(): ScenarioEnvironment | undefined;
|
|
75
|
+
attachRunContext(runId: string, workflowMeta: any, options?: {
|
|
76
|
+
actors?: ScenarioActors;
|
|
77
|
+
}): Promise<void>;
|
|
78
|
+
detachRunContext(runId: string): void;
|
|
79
|
+
decorateRunWire(wire: PikkuWire, context: {
|
|
80
|
+
runId: string;
|
|
81
|
+
workflowMeta: any;
|
|
82
|
+
workflowWire: PikkuWorkflowWire;
|
|
83
|
+
}): void;
|
|
84
|
+
onBeforeRunFunc(context: RunLifecycleContext): Promise<void>;
|
|
85
|
+
onAfterRunFunc(context: RunLifecycleContext, outcome: 'completed' | 'failed' | 'interrupted', failure: unknown): Promise<void>;
|
|
86
|
+
/**
|
|
87
|
+
* Hooks are a scenario affordance only: a plain workflow is durable and
|
|
88
|
+
* resumable, so a callback that reruns on every replay has no honest meaning
|
|
89
|
+
* there.
|
|
90
|
+
*/
|
|
91
|
+
private scenarioHooks;
|
|
92
|
+
/**
|
|
93
|
+
* Run a scenario `before`/`after` hook.
|
|
94
|
+
*
|
|
95
|
+
* A hook is not a pikku function: it has no id, no meta and no schema, so it
|
|
96
|
+
* cannot go through `runPikkuFunc` and the runner records nothing for it. It
|
|
97
|
+
* gets exactly what the scenario body gets — the same wire (so `actors` is
|
|
98
|
+
* how it reaches the app), and singleton services composed with this
|
|
99
|
+
* invocation's wire services — and nothing else.
|
|
100
|
+
*/
|
|
101
|
+
private runScenarioHook;
|
|
102
|
+
/**
|
|
103
|
+
* Build HTTP scenario actors for a run started without them; undefined when
|
|
104
|
+
* SCENARIO_ACTOR_SECRET or the API URL is missing.
|
|
105
|
+
*
|
|
106
|
+
* The actor client is imported lazily so that even a runner bundle only pays
|
|
107
|
+
* for the AI persona conversation loop it pulls in when a scenario actually
|
|
108
|
+
* signs an actor in.
|
|
109
|
+
*/
|
|
110
|
+
resolveScenarioActors(): Promise<ScenarioActors | undefined>;
|
|
111
|
+
decorateWorkflowWire(wire: PikkuWorkflowWire, context: {
|
|
112
|
+
name: string;
|
|
113
|
+
runId: string;
|
|
114
|
+
rpcService: any;
|
|
115
|
+
addonNamespace?: string | null;
|
|
116
|
+
}): void;
|
|
117
|
+
private scenarioStep;
|
|
118
|
+
private scenarioStepConfig;
|
|
119
|
+
private scenarioStepDescription;
|
|
120
|
+
private requiresBrowser;
|
|
121
|
+
}
|