@pikku/inspector 0.12.75 → 0.12.82

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.
Files changed (223) hide show
  1. package/CHANGELOG.md +357 -0
  2. package/dist/add/add-analytics.d.ts +9 -0
  3. package/dist/add/add-analytics.js +178 -0
  4. package/dist/add/add-auth.js +0 -54
  5. package/dist/add/add-feature-flag.d.ts +2 -0
  6. package/dist/add/add-feature-flag.js +162 -0
  7. package/dist/add/add-middleware.js +66 -42
  8. package/dist/add/add-wire-addon.js +7 -4
  9. package/dist/add/add-wire-remote-addon.js +1 -0
  10. package/dist/error-codes.d.ts +1 -0
  11. package/dist/error-codes.js +1 -0
  12. package/dist/index.d.ts +3 -1
  13. package/dist/index.js +3 -1
  14. package/dist/inspector.js +5 -0
  15. package/dist/surface/collect-surface.d.ts +58 -0
  16. package/dist/surface/collect-surface.js +613 -0
  17. package/dist/types.d.ts +36 -12
  18. package/dist/utils/filter-inspector-state.js +14 -0
  19. package/dist/utils/load-addon-functions-meta.js +24 -11
  20. package/dist/utils/post-process.js +15 -0
  21. package/dist/utils/read-module-specifiers.d.ts +8 -0
  22. package/dist/utils/read-module-specifiers.js +23 -0
  23. package/dist/utils/read-tsconfig-out-dir.d.ts +5 -0
  24. package/dist/utils/read-tsconfig-out-dir.js +12 -0
  25. package/dist/utils/resolve-deploy-target.d.ts +7 -0
  26. package/dist/utils/resolve-deploy-target.js +15 -7
  27. package/dist/utils/serialize-inspector-state.d.ts +6 -0
  28. package/dist/utils/serialize-inspector-state.js +10 -0
  29. package/dist/visit.js +4 -0
  30. package/package.json +16 -6
  31. package/run-tests.sh +21 -6
  32. package/src/add/add-addon-bans.ts +0 -85
  33. package/src/add/add-agent-scorer.test.ts +0 -197
  34. package/src/add/add-agent-scorer.ts +0 -83
  35. package/src/add/add-agent.test.ts +0 -87
  36. package/src/add/add-agent.ts +0 -638
  37. package/src/add/add-approval-description.ts +0 -76
  38. package/src/add/add-auth.test.ts +0 -791
  39. package/src/add/add-auth.ts +0 -424
  40. package/src/add/add-channel.ts +0 -778
  41. package/src/add/add-cli-renderers.test.ts +0 -74
  42. package/src/add/add-cli.ts +0 -1006
  43. package/src/add/add-credential.ts +0 -186
  44. package/src/add/add-feature.test.ts +0 -306
  45. package/src/add/add-feature.ts +0 -253
  46. package/src/add/add-file-extends-core-type.ts +0 -66
  47. package/src/add/add-file-with-config.ts +0 -45
  48. package/src/add/add-file-with-factory.test.ts +0 -134
  49. package/src/add/add-file-with-factory.ts +0 -288
  50. package/src/add/add-functions.test.ts +0 -743
  51. package/src/add/add-functions.ts +0 -1548
  52. package/src/add/add-gateway.ts +0 -143
  53. package/src/add/add-http-route-ref.test.ts +0 -149
  54. package/src/add/add-http-route.ts +0 -530
  55. package/src/add/add-http-routes.ts +0 -471
  56. package/src/add/add-keyed-wiring.ts +0 -180
  57. package/src/add/add-mcp-prompt.ts +0 -157
  58. package/src/add/add-mcp-resource.ts +0 -175
  59. package/src/add/add-middleware.test.ts +0 -196
  60. package/src/add/add-middleware.ts +0 -879
  61. package/src/add/add-permission-auth.test.ts +0 -59
  62. package/src/add/add-permission.ts +0 -311
  63. package/src/add/add-personas.test.ts +0 -406
  64. package/src/add/add-personas.ts +0 -287
  65. package/src/add/add-queue-worker.ts +0 -117
  66. package/src/add/add-rpc-invocations.test.ts +0 -287
  67. package/src/add/add-rpc-invocations.ts +0 -221
  68. package/src/add/add-scenario-step.test.ts +0 -509
  69. package/src/add/add-schedule.ts +0 -120
  70. package/src/add/add-scope.test.ts +0 -419
  71. package/src/add/add-scope.ts +0 -221
  72. package/src/add/add-secret.ts +0 -10
  73. package/src/add/add-subject-scenario-steps.test.ts +0 -161
  74. package/src/add/add-system-role.test.ts +0 -297
  75. package/src/add/add-system-role.ts +0 -162
  76. package/src/add/add-trigger.ts +0 -165
  77. package/src/add/add-variable.ts +0 -10
  78. package/src/add/add-wire-addon.test.ts +0 -185
  79. package/src/add/add-wire-addon.ts +0 -146
  80. package/src/add/add-wire-remote-addon.ts +0 -80
  81. package/src/add/add-workflow-edge-cases.test.ts +0 -201
  82. package/src/add/add-workflow-fanout.test.ts +0 -166
  83. package/src/add/add-workflow-graph-foreach.test.ts +0 -174
  84. package/src/add/add-workflow-graph-input.test.ts +0 -94
  85. package/src/add/add-workflow-graph-notes.test.ts +0 -74
  86. package/src/add/add-workflow-graph.ts +0 -644
  87. package/src/add/add-workflow-on-error.test.ts +0 -118
  88. package/src/add/add-workflow-return-switch.test.ts +0 -121
  89. package/src/add/add-workflow-silent-drops.test.ts +0 -261
  90. package/src/add/add-workflow-sleep-expression.test.ts +0 -96
  91. package/src/add/add-workflow.test.ts +0 -155
  92. package/src/add/add-workflow.ts +0 -482
  93. package/src/add/addon-bans.test.ts +0 -121
  94. package/src/add/addon-contracts.test.ts +0 -221
  95. package/src/add/allow-escape-hatches.test.ts +0 -144
  96. package/src/add/audit-meta.test.ts +0 -75
  97. package/src/add/classified-sink-check.test.ts +0 -347
  98. package/src/add/config-value-metadata.test.ts +0 -263
  99. package/src/add/dynamic-import-check.test.ts +0 -119
  100. package/src/add/expect-eventually-scenario-only.test.ts +0 -108
  101. package/src/add/function-body-span.test.ts +0 -96
  102. package/src/add/inline-wiring-function.test.ts +0 -104
  103. package/src/add/pii-check.test.ts +0 -258
  104. package/src/add/rpc-type-cast.test.ts +0 -123
  105. package/src/add/scenario-instrumentation.test.ts +0 -89
  106. package/src/add/scenario-instrumentation.ts +0 -42
  107. package/src/add/scenario-marker.test.ts +0 -89
  108. package/src/add/scenario-not-extractable.test.ts +0 -159
  109. package/src/add/scenario-services.test.ts +0 -103
  110. package/src/add/scenario-skip.test.ts +0 -83
  111. package/src/add/validate-workflow-graph-addons.test.ts +0 -102
  112. package/src/add/wire-name-literal.test.ts +0 -117
  113. package/src/error-codes-emitted.test.ts +0 -76
  114. package/src/error-codes.ts +0 -145
  115. package/src/index.ts +0 -66
  116. package/src/inspector.ts +0 -575
  117. package/src/schema-generator.ts +0 -1
  118. package/src/source-file-cache.ts +0 -73
  119. package/src/tsconfig-paths.test.ts +0 -90
  120. package/src/types-map.ts +0 -141
  121. package/src/types.ts +0 -775
  122. package/src/utils/annotate-http-route-auth.test.ts +0 -161
  123. package/src/utils/annotate-http-route-auth.ts +0 -53
  124. package/src/utils/check-classified-sinks.ts +0 -215
  125. package/src/utils/check-pii-output.ts +0 -120
  126. package/src/utils/compute-diagnostics.test.ts +0 -106
  127. package/src/utils/compute-required-schemas.ts +0 -48
  128. package/src/utils/contract-hashes.test.ts +0 -553
  129. package/src/utils/contract-hashes.ts +0 -387
  130. package/src/utils/custom-types-generator.test.ts +0 -124
  131. package/src/utils/custom-types-generator.ts +0 -150
  132. package/src/utils/detect-schema-vendor.test.ts +0 -123
  133. package/src/utils/detect-schema-vendor.ts +0 -120
  134. package/src/utils/does-type-extend-core-type.ts +0 -53
  135. package/src/utils/ensure-function-metadata.ts +0 -385
  136. package/src/utils/extract-function-name.ts +0 -612
  137. package/src/utils/extract-function-node.ts +0 -70
  138. package/src/utils/extract-node-value.test.ts +0 -117
  139. package/src/utils/extract-node-value.ts +0 -172
  140. package/src/utils/extract-secret-usage.test.ts +0 -81
  141. package/src/utils/extract-secret-usage.ts +0 -73
  142. package/src/utils/extract-services.ts +0 -70
  143. package/src/utils/extract-surface-usage.test.ts +0 -147
  144. package/src/utils/extract-surface-usage.ts +0 -121
  145. package/src/utils/filter-inspector-state.test.ts +0 -2232
  146. package/src/utils/filter-inspector-state.ts +0 -1298
  147. package/src/utils/filter-utils.test.ts +0 -843
  148. package/src/utils/filter-utils.ts +0 -161
  149. package/src/utils/find-root-dir.ts +0 -68
  150. package/src/utils/find-zod-transform.test.ts +0 -70
  151. package/src/utils/find-zod-transform.ts +0 -103
  152. package/src/utils/get-exported-variable-name.ts +0 -48
  153. package/src/utils/get-files-and-methods.ts +0 -157
  154. package/src/utils/get-property-value.test.ts +0 -141
  155. package/src/utils/get-property-value.ts +0 -331
  156. package/src/utils/hash.ts +0 -26
  157. package/src/utils/literal-properties.ts +0 -97
  158. package/src/utils/load-addon-functions-meta.test.ts +0 -157
  159. package/src/utils/load-addon-functions-meta.ts +0 -508
  160. package/src/utils/load-addon-scopes.test.ts +0 -138
  161. package/src/utils/middleware.test.ts +0 -204
  162. package/src/utils/middleware.ts +0 -303
  163. package/src/utils/nested-project-filter.test.ts +0 -53
  164. package/src/utils/nested-project-filter.ts +0 -28
  165. package/src/utils/permissions-shorthand.test.ts +0 -79
  166. package/src/utils/permissions.test.ts +0 -125
  167. package/src/utils/permissions.ts +0 -129
  168. package/src/utils/post-process.test.ts +0 -1094
  169. package/src/utils/post-process.ts +0 -1604
  170. package/src/utils/resolve-addon-package.ts +0 -106
  171. package/src/utils/resolve-core-type.test.ts +0 -142
  172. package/src/utils/resolve-core-type.ts +0 -35
  173. package/src/utils/resolve-deploy-target.test.ts +0 -135
  174. package/src/utils/resolve-deploy-target.ts +0 -65
  175. package/src/utils/resolve-function-meta.ts +0 -25
  176. package/src/utils/resolve-function-types.ts +0 -42
  177. package/src/utils/resolve-identifier.ts +0 -46
  178. package/src/utils/resolve-ref-contract.ts +0 -71
  179. package/src/utils/resolve-versions.test.ts +0 -499
  180. package/src/utils/resolve-versions.ts +0 -228
  181. package/src/utils/schema-cache.test.ts +0 -124
  182. package/src/utils/schema-generator.test.ts +0 -272
  183. package/src/utils/schema-generator.ts +0 -780
  184. package/src/utils/secret-alias-services.test.ts +0 -146
  185. package/src/utils/secret-alias-services.ts +0 -58
  186. package/src/utils/serialize-inspector-state.ts +0 -742
  187. package/src/utils/serialize-mcp-json.ts +0 -150
  188. package/src/utils/serialize-middleware-groups-meta.ts +0 -36
  189. package/src/utils/serialize-openapi-json.ts +0 -277
  190. package/src/utils/serialize-permissions-groups-meta.ts +0 -7
  191. package/src/utils/single-declaration.ts +0 -57
  192. package/src/utils/type-utils.ts +0 -145
  193. package/src/utils/validate-auth-sessionless.ts +0 -30
  194. package/src/utils/validate-exposed-functions-gated.test.ts +0 -230
  195. package/src/utils/validate-exposed-functions-gated.ts +0 -103
  196. package/src/utils/validate-tags-resolve-to-middleware.test.ts +0 -108
  197. package/src/utils/validate-tags-resolve-to-middleware.ts +0 -48
  198. package/src/utils/workflow/derive-workflow-plan.test.ts +0 -178
  199. package/src/utils/workflow/derive-workflow-plan.ts +0 -117
  200. package/src/utils/workflow/dsl/deserialize-dsl-workflow.ts +0 -1465
  201. package/src/utils/workflow/dsl/deserialize-fanout-body.test.ts +0 -71
  202. package/src/utils/workflow/dsl/deserialize-fanout-fidelity.test.ts +0 -99
  203. package/src/utils/workflow/dsl/deserialize-graph-next.test.ts +0 -161
  204. package/src/utils/workflow/dsl/deserialize-roundtrip-bindings.test.ts +0 -121
  205. package/src/utils/workflow/dsl/deserialize-roundtrip-values.test.ts +0 -116
  206. package/src/utils/workflow/dsl/deserialize-roundtrip.test.ts +0 -145
  207. package/src/utils/workflow/dsl/extract-approval-policy.test.ts +0 -71
  208. package/src/utils/workflow/dsl/extract-dsl-workflow.ts +0 -2254
  209. package/src/utils/workflow/dsl/index.ts +0 -11
  210. package/src/utils/workflow/dsl/patterns.ts +0 -440
  211. package/src/utils/workflow/dsl/validation.ts +0 -203
  212. package/src/utils/workflow/graph/convert-dsl-to-graph-skip.test.ts +0 -35
  213. package/src/utils/workflow/graph/convert-dsl-to-graph.ts +0 -543
  214. package/src/utils/workflow/graph/fanout-node-identity.test.ts +0 -105
  215. package/src/utils/workflow/graph/finalize-workflow-wires.ts +0 -310
  216. package/src/utils/workflow/graph/finalize-workflows.test.ts +0 -50
  217. package/src/utils/workflow/graph/finalize-workflows.ts +0 -130
  218. package/src/utils/workflow/graph/index.ts +0 -28
  219. package/src/utils/workflow/graph/serialize-workflow-graph.ts +0 -240
  220. package/src/utils/workflow/graph/workflow-graph.types.ts +0 -281
  221. package/src/visit.ts +0 -181
  222. package/tsconfig.json +0 -19
  223. package/tsconfig.tsbuildinfo +0 -1
@@ -1,310 +0,0 @@
1
- import type { InspectorState } from '../../../types.js'
2
- import type {
3
- SerializedWorkflowGraph,
4
- WorkflowWires,
5
- } from './workflow-graph.types.js'
6
- import type { CLICommandMeta } from '@pikku/core/cli'
7
-
8
- function parseWorkflowFuncId(
9
- pikkuFuncId: string
10
- ): { workflowName: string; startNode?: string } | null {
11
- for (const prefix of ['workflowStart:', 'workflow:']) {
12
- if (pikkuFuncId.startsWith(prefix)) {
13
- return { workflowName: pikkuFuncId.slice(prefix.length) }
14
- }
15
- }
16
- if (pikkuFuncId.startsWith('graphStart:')) {
17
- const rest = pikkuFuncId.slice('graphStart:'.length)
18
- const colonIdx = rest.indexOf(':')
19
- if (colonIdx !== -1) {
20
- return {
21
- workflowName: rest.slice(0, colonIdx),
22
- startNode: rest.slice(colonIdx + 1),
23
- }
24
- }
25
- }
26
- return null
27
- }
28
-
29
- function resolveStartNode(
30
- parsed: { workflowName: string; startNode?: string },
31
- graph: SerializedWorkflowGraph
32
- ): string {
33
- return parsed.startNode ?? graph.entryNodeIds[0]
34
- }
35
-
36
- function getOrCreateWires(graph: SerializedWorkflowGraph): WorkflowWires {
37
- if (!graph.wires) {
38
- graph.wires = {}
39
- }
40
- return graph.wires
41
- }
42
-
43
- export function finalizeWorkflowHelperTypes(state: InspectorState): void {
44
- const { functions, workflows } = state
45
- const graphMeta = workflows.graphMeta
46
-
47
- for (const meta of Object.values(functions.meta)) {
48
- if (meta.functionType !== 'helper') continue
49
- if (meta.pikkuFuncId.startsWith('workflowStatus:')) continue
50
-
51
- const parsed = parseWorkflowFuncId(meta.pikkuFuncId)
52
- if (!parsed) continue
53
-
54
- const graph = graphMeta[parsed.workflowName]
55
- if (!graph) continue
56
-
57
- const startNodeId = resolveStartNode(parsed, graph)
58
- const startNode = graph.nodes[startNodeId]
59
- if (!startNode || !('rpcName' in startNode)) continue
60
-
61
- const rpcMeta = functions.meta[startNode.rpcName as string]
62
- if (!rpcMeta) continue
63
-
64
- if (rpcMeta.inputSchemaName) {
65
- meta.inputSchemaName = rpcMeta.inputSchemaName
66
- }
67
- if (rpcMeta.inputs && rpcMeta.inputs.length > 0) {
68
- meta.inputs = rpcMeta.inputs
69
- }
70
- }
71
- }
72
-
73
- export function finalizeWorkflowWires(state: InspectorState): void {
74
- const { workflows } = state
75
- const graphMeta = workflows.graphMeta
76
-
77
- scanHTTP(state, graphMeta)
78
- scanScheduledTasks(state, graphMeta)
79
- scanTriggers(state, graphMeta)
80
- scanQueueWorkers(state, graphMeta)
81
- scanChannels(state, graphMeta)
82
- scanMCPEndpoints(state, graphMeta)
83
- scanCLI(state, graphMeta)
84
- }
85
-
86
- function scanHTTP(
87
- state: InspectorState,
88
- graphMeta: Record<string, SerializedWorkflowGraph>
89
- ): void {
90
- for (const [method, routes] of Object.entries(state.http.meta)) {
91
- for (const [route, meta] of Object.entries(routes)) {
92
- const parsed = parseWorkflowFuncId(meta.pikkuFuncId)
93
- if (!parsed) continue
94
- const graph = graphMeta[parsed.workflowName]
95
- if (!graph) continue
96
- const wires = getOrCreateWires(graph)
97
- if (!wires.http) wires.http = []
98
- wires.http.push({
99
- route,
100
- method,
101
- startNode: resolveStartNode(parsed, graph),
102
- })
103
- }
104
- }
105
- }
106
-
107
- function scanScheduledTasks(
108
- state: InspectorState,
109
- graphMeta: Record<string, SerializedWorkflowGraph>
110
- ): void {
111
- for (const meta of Object.values(state.scheduledTasks.meta)) {
112
- const parsed = parseWorkflowFuncId(meta.pikkuFuncId)
113
- if (!parsed) continue
114
- const graph = graphMeta[parsed.workflowName]
115
- if (!graph) continue
116
- const wires = getOrCreateWires(graph)
117
- if (!wires.schedule) wires.schedule = []
118
- wires.schedule.push({
119
- cron: meta.schedule,
120
- startNode: resolveStartNode(parsed, graph),
121
- })
122
- }
123
- }
124
-
125
- function scanTriggers(
126
- state: InspectorState,
127
- graphMeta: Record<string, SerializedWorkflowGraph>
128
- ): void {
129
- for (const meta of Object.values(state.triggers.meta)) {
130
- const parsed = parseWorkflowFuncId(meta.pikkuFuncId)
131
- if (!parsed) continue
132
- const graph = graphMeta[parsed.workflowName]
133
- if (!graph) continue
134
- const wires = getOrCreateWires(graph)
135
- if (!wires.trigger) wires.trigger = []
136
- wires.trigger.push({
137
- name: meta.name,
138
- startNode: resolveStartNode(parsed, graph),
139
- })
140
- }
141
- }
142
-
143
- function scanQueueWorkers(
144
- state: InspectorState,
145
- graphMeta: Record<string, SerializedWorkflowGraph>
146
- ): void {
147
- for (const meta of Object.values(state.queueWorkers.meta)) {
148
- const parsed = parseWorkflowFuncId(meta.pikkuFuncId)
149
- if (!parsed) continue
150
- const graph = graphMeta[parsed.workflowName]
151
- if (!graph) continue
152
- const wires = getOrCreateWires(graph)
153
- if (!wires.queue) wires.queue = []
154
- wires.queue.push({
155
- name: meta.name,
156
- startNode: resolveStartNode(parsed, graph),
157
- })
158
- }
159
- }
160
-
161
- function scanChannels(
162
- state: InspectorState,
163
- graphMeta: Record<string, SerializedWorkflowGraph>
164
- ): void {
165
- for (const channelMeta of Object.values(state.channels.meta)) {
166
- const wire: NonNullable<WorkflowWires['channel']>[number] = {
167
- name: channelMeta.name,
168
- route: channelMeta.route,
169
- }
170
- let targetWorkflow: SerializedWorkflowGraph | undefined
171
-
172
- if (channelMeta.connect) {
173
- const parsed = parseWorkflowFuncId(channelMeta.connect.pikkuFuncId)
174
- if (parsed) {
175
- const graph = graphMeta[parsed.workflowName]
176
- if (graph) {
177
- targetWorkflow = graph
178
- wire.onConnect = resolveStartNode(parsed, graph)
179
- }
180
- }
181
- }
182
-
183
- if (channelMeta.disconnect) {
184
- const parsed = parseWorkflowFuncId(channelMeta.disconnect.pikkuFuncId)
185
- if (parsed) {
186
- const graph = graphMeta[parsed.workflowName]
187
- if (graph) {
188
- targetWorkflow = targetWorkflow ?? graph
189
- wire.onDisconnect = resolveStartNode(parsed, graph)
190
- }
191
- }
192
- }
193
-
194
- if (channelMeta.message) {
195
- const parsed = parseWorkflowFuncId(channelMeta.message.pikkuFuncId)
196
- if (parsed) {
197
- const graph = graphMeta[parsed.workflowName]
198
- if (graph) {
199
- targetWorkflow = targetWorkflow ?? graph
200
- wire.onMessage = resolveStartNode(parsed, graph)
201
- }
202
- }
203
- }
204
-
205
- for (const [routingProp, routeMap] of Object.entries(
206
- channelMeta.messageWirings
207
- )) {
208
- for (const [routeValue, messageMeta] of Object.entries(routeMap)) {
209
- const parsed = parseWorkflowFuncId(messageMeta.pikkuFuncId)
210
- if (!parsed) continue
211
- const graph = graphMeta[parsed.workflowName]
212
- if (!graph) continue
213
- targetWorkflow = targetWorkflow ?? graph
214
- if (!wire.onMessageRoute) wire.onMessageRoute = {}
215
- wire.onMessageRoute[`${routingProp}:${routeValue}`] = resolveStartNode(
216
- parsed,
217
- graph
218
- )
219
- }
220
- }
221
-
222
- if (targetWorkflow) {
223
- const wires = getOrCreateWires(targetWorkflow)
224
- if (!wires.channel) wires.channel = []
225
- wires.channel.push(wire)
226
- }
227
- }
228
- }
229
-
230
- function scanMCPEndpoints(
231
- state: InspectorState,
232
- graphMeta: Record<string, SerializedWorkflowGraph>
233
- ): void {
234
- for (const meta of Object.values(state.mcpEndpoints.toolsMeta)) {
235
- const parsed = parseWorkflowFuncId(meta.pikkuFuncId)
236
- if (!parsed) continue
237
- const graph = graphMeta[parsed.workflowName]
238
- if (!graph) continue
239
- const wires = getOrCreateWires(graph)
240
- if (!wires.mcp) wires.mcp = {}
241
- if (!wires.mcp.tool) wires.mcp.tool = []
242
- wires.mcp.tool.push({
243
- name: meta.name,
244
- startNode: resolveStartNode(parsed, graph),
245
- })
246
- }
247
-
248
- for (const meta of Object.values(state.mcpEndpoints.promptsMeta)) {
249
- const parsed = parseWorkflowFuncId(meta.pikkuFuncId)
250
- if (!parsed) continue
251
- const graph = graphMeta[parsed.workflowName]
252
- if (!graph) continue
253
- const wires = getOrCreateWires(graph)
254
- if (!wires.mcp) wires.mcp = {}
255
- if (!wires.mcp.prompt) wires.mcp.prompt = []
256
- wires.mcp.prompt.push({
257
- name: meta.name,
258
- startNode: resolveStartNode(parsed, graph),
259
- })
260
- }
261
-
262
- for (const meta of Object.values(state.mcpEndpoints.resourcesMeta)) {
263
- const parsed = parseWorkflowFuncId(meta.pikkuFuncId)
264
- if (!parsed) continue
265
- const graph = graphMeta[parsed.workflowName]
266
- if (!graph) continue
267
- const wires = getOrCreateWires(graph)
268
- if (!wires.mcp) wires.mcp = {}
269
- if (!wires.mcp.resource) wires.mcp.resource = []
270
- wires.mcp.resource.push({
271
- uri: meta.uri,
272
- startNode: resolveStartNode(parsed, graph),
273
- })
274
- }
275
- }
276
-
277
- function visitCLICommands(
278
- commands: Record<string, CLICommandMeta>,
279
- programName: string,
280
- path: string[],
281
- graphMeta: Record<string, SerializedWorkflowGraph>
282
- ): void {
283
- for (const [name, command] of Object.entries(commands)) {
284
- const currentPath = [...path, name]
285
- const parsed = parseWorkflowFuncId(command.pikkuFuncId)
286
- if (parsed) {
287
- const graph = graphMeta[parsed.workflowName]
288
- if (graph) {
289
- const wires = getOrCreateWires(graph)
290
- if (!wires.cli) wires.cli = []
291
- wires.cli.push({
292
- command: `${programName} ${currentPath.join(' ')}`,
293
- startNode: resolveStartNode(parsed, graph),
294
- })
295
- }
296
- }
297
- if (command.subcommands) {
298
- visitCLICommands(command.subcommands, programName, currentPath, graphMeta)
299
- }
300
- }
301
- }
302
-
303
- function scanCLI(
304
- state: InspectorState,
305
- graphMeta: Record<string, SerializedWorkflowGraph>
306
- ): void {
307
- for (const program of Object.values(state.cli.meta.programs)) {
308
- visitCLICommands(program.commands, program.program, [], graphMeta)
309
- }
310
- }
@@ -1,50 +0,0 @@
1
- import { test } from 'node:test'
2
- import assert from 'node:assert'
3
- import { computeGraphHash } from './finalize-workflows.js'
4
- import type {
5
- SerializedWorkflowGraph,
6
- FunctionNode,
7
- } from './workflow-graph.types.js'
8
-
9
- function graph(
10
- overrides: Partial<SerializedWorkflowGraph> = {},
11
- nodeOverrides: Partial<FunctionNode> = {}
12
- ): SerializedWorkflowGraph {
13
- const node: FunctionNode = {
14
- nodeId: 'a',
15
- rpcName: 'doThing',
16
- input: { x: { $ref: 'trigger', path: 'x' } },
17
- next: 'b',
18
- ...nodeOverrides,
19
- }
20
- return {
21
- name: 'wf',
22
- pikkuFuncId: 'wf',
23
- source: 'graph',
24
- nodes: { a: node, b: { nodeId: 'b', rpcName: 'finish' } },
25
- entryNodeIds: ['a'],
26
- ...overrides,
27
- }
28
- }
29
-
30
- test('computeGraphHash: node-level notes do not change the hash', () => {
31
- const without = computeGraphHash(graph())
32
- const withNote = computeGraphHash(
33
- graph({}, { notes: 'imported node "Do Thing"' })
34
- )
35
- assert.strictEqual(withNote, without)
36
- })
37
-
38
- test('computeGraphHash: graph-level notes do not change the hash', () => {
39
- const without = computeGraphHash(graph())
40
- const withNotes = computeGraphHash(
41
- graph({ notes: ['sticky note one', 'sticky note two'] })
42
- )
43
- assert.strictEqual(withNotes, without)
44
- })
45
-
46
- test('computeGraphHash: a topology change DOES change the hash', () => {
47
- const base = computeGraphHash(graph())
48
- const changed = computeGraphHash(graph({}, { next: 'c' }))
49
- assert.notStrictEqual(changed, base)
50
- })
@@ -1,130 +0,0 @@
1
- import type { FunctionsMeta } from '@pikku/core/services'
2
- import {
3
- isVersionedId,
4
- formatVersionedId,
5
- parseVersionedId,
6
- } from '@pikku/core/utils'
7
- import type { SerializedWorkflowGraph } from './workflow-graph.types.js'
8
- import { canonicalJSON, hashString } from '../../hash.js'
9
- import { convertDslToGraph } from './convert-dsl-to-graph.js'
10
- import { deriveWorkflowPlan } from '../derive-workflow-plan.js'
11
- import type { InspectorState } from '../../../types.js'
12
-
13
- export function finalizeWorkflows(state: InspectorState): void {
14
- const { workflows, functions } = state
15
- const functionsMeta = functions.meta
16
-
17
- for (const [name, meta] of Object.entries(workflows.meta)) {
18
- const graph = convertDslToGraph(name, meta)
19
- stampVersionsOnGraph(graph, functionsMeta)
20
- computeStepHashes(graph, functionsMeta)
21
- graph.graphHash = computeGraphHash(graph)
22
- // Predictable (loopless) DSL workflows carry their full step list so a UI
23
- // can render the skeleton up front without executing the run. Only DSL is
24
- // gated: a complex workflow's step tree is incomplete (inline JS branches
25
- // aren't captured) and flattens loops into plain steps, so its plan would
26
- // lie about determinism.
27
- if (graph.source === 'dsl') {
28
- const { deterministic, plannedSteps } = deriveWorkflowPlan(meta.steps)
29
- graph.deterministic = deterministic
30
- // Omit an empty list — a deterministic workflow with no plannedSteps is
31
- // simply one with no named steps (e.g. a bare return).
32
- if (plannedSteps?.length) {
33
- graph.plannedSteps = plannedSteps
34
- }
35
- }
36
- workflows.graphMeta[name] = graph
37
- }
38
-
39
- for (const graph of Object.values(workflows.graphMeta)) {
40
- if (graph.graphHash) {
41
- continue
42
- }
43
- stampVersionsOnGraph(graph, functionsMeta)
44
- computeStepHashes(graph, functionsMeta)
45
- graph.graphHash = computeGraphHash(graph)
46
- }
47
- }
48
-
49
- function stampVersionsOnGraph(
50
- graph: SerializedWorkflowGraph,
51
- functionsMeta: FunctionsMeta
52
- ): void {
53
- for (const node of Object.values(graph.nodes)) {
54
- if (!('rpcName' in node) || typeof node.rpcName !== 'string') {
55
- continue
56
- }
57
-
58
- if (isVersionedId(node.rpcName)) {
59
- continue
60
- }
61
-
62
- const meta = functionsMeta[node.rpcName]
63
- if (meta?.version !== undefined) {
64
- node.rpcName = formatVersionedId(node.rpcName, meta.version)
65
- } else {
66
- const latestVersion = findLatestVersion(node.rpcName, functionsMeta)
67
- if (latestVersion > 0) {
68
- node.rpcName = formatVersionedId(node.rpcName, latestVersion)
69
- }
70
- }
71
- }
72
- }
73
-
74
- function findLatestVersion(
75
- baseName: string,
76
- functionsMeta: FunctionsMeta
77
- ): number {
78
- let max = 0
79
- for (const id of Object.keys(functionsMeta)) {
80
- const parsed = parseVersionedId(id)
81
- if (parsed.baseName === baseName && parsed.version !== null) {
82
- max = Math.max(max, parsed.version)
83
- }
84
- }
85
- return max
86
- }
87
-
88
- function computeStepHashes(
89
- graph: SerializedWorkflowGraph,
90
- functionsMeta: FunctionsMeta
91
- ): void {
92
- for (const node of Object.values(graph.nodes)) {
93
- if (!('rpcName' in node) || typeof node.rpcName !== 'string') {
94
- continue
95
- }
96
- const rpcName: string = node.rpcName
97
- let meta = functionsMeta[rpcName]
98
- if (!meta) {
99
- const { baseName } = parseVersionedId(rpcName)
100
- meta = functionsMeta[baseName]
101
- }
102
- ;(node as Record<string, unknown>).stepHash = hashString(
103
- `${node.nodeId}:${meta?.contractHash ?? ''}`,
104
- 12
105
- )
106
- }
107
- }
108
-
109
- /**
110
- * Hash of graph topology only. `notes` (node- and graph-level) is deliberately
111
- * excluded so editing documentation never changes the hash / marks the workflow
112
- * as a new version.
113
- */
114
- export function computeGraphHash(graph: SerializedWorkflowGraph): string {
115
- const nodesForHash = Object.fromEntries(
116
- Object.entries(graph.nodes).map(([nodeId, node]) => {
117
- const { notes: _notes, ...rest } = node as { notes?: string }
118
- return [nodeId, rest]
119
- })
120
- )
121
- return hashString(
122
- canonicalJSON({
123
- source: graph.source,
124
- context: graph.context,
125
- nodes: nodesForHash,
126
- entryNodeIds: graph.entryNodeIds,
127
- }),
128
- 12
129
- )
130
- }
@@ -1,28 +0,0 @@
1
- /**
2
- * Workflow graph serialization exports
3
- */
4
- export {
5
- isDataRef,
6
- isFunctionNode,
7
- ref,
8
- state,
9
- } from './workflow-graph.types.js'
10
- export type {
11
- BranchCondition,
12
- ContextVariable,
13
- DataRef,
14
- FlowNode,
15
- ForEachMode,
16
- FunctionNode,
17
- NodeOptions,
18
- SerializedWorkflowGraph,
19
- SerializedWorkflowGraphs,
20
- WorkflowContext,
21
- } from './workflow-graph.types.js'
22
- export { serializeWorkflowGraph } from './serialize-workflow-graph.js'
23
- export { convertDslToGraph } from './convert-dsl-to-graph.js'
24
- export { finalizeWorkflows } from './finalize-workflows.js'
25
- export {
26
- finalizeWorkflowHelperTypes,
27
- finalizeWorkflowWires,
28
- } from './finalize-workflow-wires.js'