@pikku/inspector 0.12.31 → 0.12.34
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 +52 -0
- package/dist/add/add-functions.js +4 -2
- package/dist/add/add-workflow.d.ts +2 -2
- package/dist/add/add-workflow.js +63 -9
- package/dist/error-codes.d.ts +1 -0
- package/dist/error-codes.js +1 -0
- package/dist/utils/workflow/dsl/extract-dsl-workflow.js +9 -4
- package/dist/utils/workflow/dsl/patterns.d.ts +12 -1
- package/dist/utils/workflow/dsl/patterns.js +37 -2
- package/dist/utils/workflow/graph/convert-dsl-to-graph.js +15 -2
- package/dist/utils/workflow/graph/workflow-graph.types.d.ts +10 -1
- package/package.json +2 -2
- package/src/add/add-functions.ts +6 -2
- package/src/add/add-workflow.ts +76 -10
- package/src/error-codes.ts +1 -0
- package/src/utils/workflow/dsl/extract-dsl-workflow.ts +12 -3
- package/src/utils/workflow/dsl/patterns.ts +48 -2
- package/src/utils/workflow/graph/convert-dsl-to-graph.ts +15 -2
- package/src/utils/workflow/graph/workflow-graph.types.ts +10 -1
- package/tsconfig.tsbuildinfo +1 -1
package/src/error-codes.ts
CHANGED
|
@@ -21,6 +21,7 @@ export enum ErrorCode {
|
|
|
21
21
|
MISSING_QUEUE_NAME = 'PKU384',
|
|
22
22
|
MISSING_CHANNEL_NAME = 'PKU400',
|
|
23
23
|
CLI_CLIENTSIDE_RENDERER_HAS_SERVICES = 'PKU672',
|
|
24
|
+
USER_FLOW_HAS_SERVICES = 'PKU673',
|
|
24
25
|
DYNAMIC_STEP_NAME = 'PKU529',
|
|
25
26
|
WORKFLOW_ORCHESTRATOR_NOT_CONFIGURED = 'PKU600',
|
|
26
27
|
INVALID_DSL_WORKFLOW = 'PKU641',
|
|
@@ -21,6 +21,8 @@ import type {
|
|
|
21
21
|
} from '@pikku/core/workflow'
|
|
22
22
|
import {
|
|
23
23
|
isWorkflowDoCall,
|
|
24
|
+
isWorkflowExpectEventuallyCall,
|
|
25
|
+
extractActorFromOptions,
|
|
24
26
|
isWorkflowSleepCall,
|
|
25
27
|
isWorkflowSuspendCall,
|
|
26
28
|
isThrowCancelException,
|
|
@@ -553,10 +555,15 @@ function extractRpcStep(
|
|
|
553
555
|
const inputs =
|
|
554
556
|
args.length >= 3 ? extractInputSources(args[2], context) : undefined
|
|
555
557
|
|
|
556
|
-
//
|
|
558
|
+
// do(step, rpc, data, options?) vs expectEventually(step, rpc, data, predicate, options?)
|
|
559
|
+
const expectEventually = isWorkflowExpectEventuallyCall(call)
|
|
560
|
+
const optionsIndex = expectEventually ? 4 : 3
|
|
561
|
+
const optionsArg =
|
|
562
|
+
args.length > optionsIndex ? args[optionsIndex] : undefined
|
|
563
|
+
|
|
557
564
|
const options =
|
|
558
|
-
|
|
559
|
-
? extractStepOptions(
|
|
565
|
+
optionsArg && ts.isObjectLiteralExpression(optionsArg)
|
|
566
|
+
? extractStepOptions(optionsArg, context)
|
|
560
567
|
: undefined
|
|
561
568
|
|
|
562
569
|
return {
|
|
@@ -566,6 +573,8 @@ function extractRpcStep(
|
|
|
566
573
|
outputVar,
|
|
567
574
|
inputs,
|
|
568
575
|
options,
|
|
576
|
+
actor: extractActorFromOptions(optionsArg),
|
|
577
|
+
expectEventually: expectEventually || undefined,
|
|
569
578
|
}
|
|
570
579
|
} catch (error) {
|
|
571
580
|
context.errors.push({
|
|
@@ -5,7 +5,8 @@ import * as ts from 'typescript'
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Check if a call expression is workflow.do()
|
|
8
|
+
* Check if a call expression is workflow.do() or workflow.expectEventually()
|
|
9
|
+
* (both are RPC steps; expectEventually is the polling variant used by user flows)
|
|
9
10
|
*/
|
|
10
11
|
export function isWorkflowDoCall(
|
|
11
12
|
node: ts.CallExpression,
|
|
@@ -17,12 +18,57 @@ export function isWorkflowDoCall(
|
|
|
17
18
|
|
|
18
19
|
const propAccess = node.expression
|
|
19
20
|
return (
|
|
20
|
-
propAccess.name.text === 'do'
|
|
21
|
+
(propAccess.name.text === 'do' ||
|
|
22
|
+
propAccess.name.text === 'expectEventually') &&
|
|
21
23
|
ts.isIdentifier(propAccess.expression) &&
|
|
22
24
|
propAccess.expression.text === 'workflow'
|
|
23
25
|
)
|
|
24
26
|
}
|
|
25
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Check if a call expression is workflow.expectEventually()
|
|
30
|
+
*/
|
|
31
|
+
export function isWorkflowExpectEventuallyCall(
|
|
32
|
+
node: ts.CallExpression
|
|
33
|
+
): boolean {
|
|
34
|
+
return (
|
|
35
|
+
ts.isPropertyAccessExpression(node.expression) &&
|
|
36
|
+
node.expression.name.text === 'expectEventually' &&
|
|
37
|
+
ts.isIdentifier(node.expression.expression) &&
|
|
38
|
+
node.expression.expression.text === 'workflow'
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Extract the actor NAME from a step options object literal:
|
|
44
|
+
* `{ actor: actors.x }` → 'x' (also `actors['x']`). Undefined when absent
|
|
45
|
+
* or not statically resolvable.
|
|
46
|
+
*/
|
|
47
|
+
export function extractActorFromOptions(
|
|
48
|
+
optionsArg: ts.Expression | undefined
|
|
49
|
+
): string | undefined {
|
|
50
|
+
if (!optionsArg || !ts.isObjectLiteralExpression(optionsArg)) return
|
|
51
|
+
for (const prop of optionsArg.properties) {
|
|
52
|
+
if (
|
|
53
|
+
ts.isPropertyAssignment(prop) &&
|
|
54
|
+
ts.isIdentifier(prop.name) &&
|
|
55
|
+
prop.name.text === 'actor'
|
|
56
|
+
) {
|
|
57
|
+
const init = prop.initializer
|
|
58
|
+
if (ts.isPropertyAccessExpression(init)) {
|
|
59
|
+
return init.name.text
|
|
60
|
+
}
|
|
61
|
+
if (
|
|
62
|
+
ts.isElementAccessExpression(init) &&
|
|
63
|
+
ts.isStringLiteral(init.argumentExpression)
|
|
64
|
+
) {
|
|
65
|
+
return init.argumentExpression.text
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
|
|
26
72
|
/**
|
|
27
73
|
* Check if a call expression is workflow.sleep()
|
|
28
74
|
*/
|
|
@@ -93,6 +93,12 @@ function convertStepToNode(
|
|
|
93
93
|
rpcName: step.rpcName,
|
|
94
94
|
next: nextNodeId,
|
|
95
95
|
}
|
|
96
|
+
if (step.actor) {
|
|
97
|
+
node.actor = step.actor
|
|
98
|
+
}
|
|
99
|
+
if (step.expectEventually) {
|
|
100
|
+
node.expectEventually = true
|
|
101
|
+
}
|
|
96
102
|
if (step.inputs) {
|
|
97
103
|
if (step.inputs === 'passthrough') {
|
|
98
104
|
// Entire data is passed through - store as reference to trigger
|
|
@@ -389,17 +395,24 @@ export function convertDslToGraph(
|
|
|
389
395
|
|
|
390
396
|
const entryNodeIds = nodes.length > 0 ? [nodes[0].nodeId] : []
|
|
391
397
|
|
|
392
|
-
// Determine source type
|
|
398
|
+
// Determine source type:
|
|
399
|
+
// - userFlow: complex workflow whose steps run as actors (user flow)
|
|
393
400
|
// - dsl === true: pure DSL workflow, can be serialized
|
|
394
401
|
// - dsl === false: complex workflow with inline steps, not serializable
|
|
395
|
-
const source = meta.
|
|
402
|
+
const source = meta.userFlow
|
|
403
|
+
? 'user-flow'
|
|
404
|
+
: meta.dsl === false
|
|
405
|
+
? 'complex'
|
|
406
|
+
: 'dsl'
|
|
396
407
|
|
|
397
408
|
return {
|
|
398
409
|
name: workflowName,
|
|
399
410
|
pikkuFuncId: meta.pikkuFuncId,
|
|
400
411
|
source,
|
|
412
|
+
title: meta.title,
|
|
401
413
|
description: meta.description,
|
|
402
414
|
tags: meta.tags,
|
|
415
|
+
actors: meta.actors,
|
|
403
416
|
context: meta.context,
|
|
404
417
|
nodes: nodesRecord,
|
|
405
418
|
entryNodeIds,
|
|
@@ -142,6 +142,10 @@ export interface FunctionNode extends BaseNode {
|
|
|
142
142
|
outputVar?: string
|
|
143
143
|
/** Hash of nodeId + RPC input/output schemas for version detection */
|
|
144
144
|
stepHash?: string
|
|
145
|
+
/** User-flow actor name this step runs as (workflow.do {actor: actors.x}) */
|
|
146
|
+
actor?: string
|
|
147
|
+
/** True for workflow.expectEventually polling steps (user flows) */
|
|
148
|
+
expectEventually?: boolean
|
|
145
149
|
}
|
|
146
150
|
|
|
147
151
|
/**
|
|
@@ -177,8 +181,9 @@ export const isFlowNode = (node: SerializedGraphNode): node is FlowNode =>
|
|
|
177
181
|
* - 'dsl': Pure DSL workflow (pikkuWorkflowFunc) - can be round-tripped to code
|
|
178
182
|
* - 'complex': Complex workflow (pikkuWorkflowComplexFunc) - contains inline steps, not serializable
|
|
179
183
|
* - 'graph': Graph-based workflow (pikkuWorkflowGraph)
|
|
184
|
+
* - 'user-flow': User flow (pikkuUserFlow) - complex workflow whose steps run as actors
|
|
180
185
|
*/
|
|
181
|
-
export type WorkflowSourceType = 'dsl' | 'complex' | 'graph'
|
|
186
|
+
export type WorkflowSourceType = 'dsl' | 'complex' | 'graph' | 'user-flow'
|
|
182
187
|
|
|
183
188
|
/**
|
|
184
189
|
* Serialized workflow graph - the canonical JSON format
|
|
@@ -190,10 +195,14 @@ export interface SerializedWorkflowGraph {
|
|
|
190
195
|
pikkuFuncId: string
|
|
191
196
|
/** Source type: 'dsl' for pikkuWorkflowFunc, 'graph' for pikkuWorkflowGraph */
|
|
192
197
|
source: WorkflowSourceType
|
|
198
|
+
/** Optional short display name */
|
|
199
|
+
title?: string
|
|
193
200
|
/** Optional description */
|
|
194
201
|
description?: string
|
|
195
202
|
/** Tags for organization */
|
|
196
203
|
tags?: string[]
|
|
204
|
+
/** Actor names a user flow's steps run as */
|
|
205
|
+
actors?: string[]
|
|
197
206
|
/** If true, workflow always executes inline without queues */
|
|
198
207
|
inline?: boolean
|
|
199
208
|
/** Workflow context/state variables (from Zod schema) */
|