@pikku/inspector 0.11.1 → 0.12.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/CHANGELOG.md +26 -1
- package/OPTIMIZATION-PLAN.md +195 -0
- package/dist/add/add-ai-agent.d.ts +2 -0
- package/dist/add/add-ai-agent.js +314 -0
- package/dist/add/add-channel.js +69 -61
- package/dist/add/add-cli.js +36 -18
- package/dist/add/add-file-with-factory.js +2 -0
- package/dist/add/add-functions.js +327 -59
- package/dist/add/add-http-route.d.ts +19 -10
- package/dist/add/add-http-route.js +153 -44
- package/dist/add/add-http-routes.d.ts +5 -0
- package/dist/add/add-http-routes.js +159 -0
- package/dist/add/add-keyed-wiring.d.ts +12 -0
- package/dist/add/add-keyed-wiring.js +97 -0
- package/dist/add/add-mcp-prompt.js +14 -9
- package/dist/add/add-mcp-resource.js +14 -9
- package/dist/add/add-middleware.d.ts +1 -4
- package/dist/add/add-middleware.js +364 -79
- package/dist/add/add-permission.d.ts +1 -1
- package/dist/add/add-permission.js +152 -40
- package/dist/add/add-queue-worker.js +18 -12
- package/dist/add/add-rpc-invocations.d.ts +3 -0
- package/dist/add/add-rpc-invocations.js +65 -25
- package/dist/add/add-schedule.js +11 -5
- package/dist/add/add-secret.d.ts +3 -0
- package/dist/add/add-secret.js +82 -0
- package/dist/add/add-trigger.d.ts +2 -0
- package/dist/add/add-trigger.js +87 -0
- package/dist/add/add-variable.d.ts +1 -0
- package/dist/add/add-variable.js +8 -0
- package/dist/add/add-workflow-graph.d.ts +7 -0
- package/dist/add/add-workflow-graph.js +396 -0
- package/dist/add/add-workflow.js +124 -26
- package/dist/error-codes.d.ts +16 -1
- package/dist/error-codes.js +21 -1
- package/dist/index.d.ts +9 -5
- package/dist/index.js +5 -2
- package/dist/inspector.d.ts +1 -1
- package/dist/inspector.js +106 -13
- package/dist/schema-generator.d.ts +1 -0
- package/dist/schema-generator.js +1 -0
- package/dist/types-map.js +10 -1
- package/dist/types.d.ts +180 -30
- package/dist/utils/compute-required-schemas.d.ts +4 -0
- package/dist/utils/compute-required-schemas.js +41 -0
- package/dist/utils/contract-hashes.d.ts +35 -0
- package/dist/utils/contract-hashes.js +202 -0
- package/dist/utils/custom-types-generator.d.ts +9 -0
- package/dist/utils/custom-types-generator.js +71 -0
- package/dist/utils/detect-schema-vendor.d.ts +22 -0
- package/dist/utils/detect-schema-vendor.js +76 -0
- package/dist/utils/ensure-function-metadata.d.ts +5 -2
- package/dist/utils/ensure-function-metadata.js +220 -6
- package/dist/utils/extract-function-name.d.ts +5 -16
- package/dist/utils/extract-function-name.js +93 -298
- package/dist/utils/extract-services.d.ts +2 -1
- package/dist/utils/extract-services.js +25 -1
- package/dist/utils/filter-inspector-state.js +107 -23
- package/dist/utils/get-property-value.d.ts +8 -2
- package/dist/utils/get-property-value.js +33 -4
- package/dist/utils/hash.d.ts +2 -0
- package/dist/utils/hash.js +23 -0
- package/dist/utils/middleware.d.ts +7 -30
- package/dist/utils/middleware.js +80 -66
- package/dist/utils/permissions.d.ts +2 -2
- package/dist/utils/permissions.js +10 -10
- package/dist/utils/post-process.d.ts +9 -10
- package/dist/utils/post-process.js +231 -24
- package/dist/utils/resolve-external-package.d.ts +12 -0
- package/dist/utils/resolve-external-package.js +34 -0
- package/dist/utils/resolve-function-types.d.ts +6 -0
- package/dist/utils/resolve-function-types.js +29 -0
- package/dist/utils/resolve-identifier.d.ts +10 -0
- package/dist/utils/resolve-identifier.js +36 -0
- package/dist/utils/resolve-versions.d.ts +2 -0
- package/dist/utils/resolve-versions.js +78 -0
- package/dist/utils/schema-generator.d.ts +9 -0
- package/dist/utils/schema-generator.js +209 -0
- package/dist/utils/serialize-inspector-state.d.ts +73 -13
- package/dist/utils/serialize-inspector-state.js +102 -6
- package/dist/utils/serialize-mcp-json.d.ts +2 -0
- package/dist/utils/serialize-mcp-json.js +99 -0
- package/dist/utils/serialize-middleware-groups-meta.d.ts +12 -0
- package/dist/utils/serialize-middleware-groups-meta.js +28 -0
- package/dist/utils/serialize-openapi-json.d.ts +85 -0
- package/dist/utils/serialize-openapi-json.js +151 -0
- package/dist/utils/serialize-permissions-groups-meta.d.ts +6 -0
- package/dist/utils/serialize-permissions-groups-meta.js +31 -0
- package/dist/utils/workflow/dsl/deserialize-dsl-workflow.d.ts +24 -0
- package/dist/utils/workflow/dsl/deserialize-dsl-workflow.js +830 -0
- package/dist/{workflow/extract-simple-workflow.d.ts → utils/workflow/dsl/extract-dsl-workflow.d.ts} +4 -2
- package/dist/{workflow/extract-simple-workflow.js → utils/workflow/dsl/extract-dsl-workflow.js} +572 -72
- package/dist/utils/workflow/dsl/index.d.ts +7 -0
- package/dist/utils/workflow/dsl/index.js +7 -0
- package/dist/{workflow → utils/workflow/dsl}/patterns.d.ts +21 -0
- package/dist/{workflow → utils/workflow/dsl}/patterns.js +90 -10
- package/dist/{workflow → utils/workflow/dsl}/validation.d.ts +2 -0
- package/dist/{workflow → utils/workflow/dsl}/validation.js +25 -7
- package/dist/utils/workflow/graph/convert-dsl-to-graph.d.ts +13 -0
- package/dist/utils/workflow/graph/convert-dsl-to-graph.js +318 -0
- package/dist/utils/workflow/graph/finalize-workflow-wires.d.ts +3 -0
- package/dist/utils/workflow/graph/finalize-workflow-wires.js +276 -0
- package/dist/utils/workflow/graph/finalize-workflows.d.ts +2 -0
- package/dist/utils/workflow/graph/finalize-workflows.js +75 -0
- package/dist/utils/workflow/graph/index.d.ts +8 -0
- package/dist/utils/workflow/graph/index.js +8 -0
- package/dist/utils/workflow/graph/serialize-workflow-graph.d.ts +35 -0
- package/dist/utils/workflow/graph/serialize-workflow-graph.js +150 -0
- package/dist/utils/workflow/graph/workflow-graph.types.d.ts +203 -0
- package/dist/utils/workflow/graph/workflow-graph.types.js +38 -0
- package/dist/visit.js +13 -2
- package/package.json +26 -4
- package/src/add/add-ai-agent.ts +468 -0
- package/src/add/add-channel.ts +82 -79
- package/src/add/add-cli.ts +49 -20
- package/src/add/add-file-with-factory.ts +2 -0
- package/src/add/add-functions.ts +429 -71
- package/src/add/add-http-route.ts +246 -65
- package/src/add/add-http-routes.ts +228 -0
- package/src/add/add-keyed-wiring.ts +151 -0
- package/src/add/add-mcp-prompt.ts +26 -15
- package/src/add/add-mcp-resource.ts +27 -15
- package/src/add/add-middleware.ts +482 -80
- package/src/add/add-permission.ts +199 -40
- package/src/add/add-queue-worker.ts +24 -19
- package/src/add/add-rpc-invocations.ts +78 -31
- package/src/add/add-schedule.ts +16 -11
- package/src/add/add-secret.ts +140 -0
- package/src/add/add-trigger.ts +154 -0
- package/src/add/add-variable.ts +9 -0
- package/src/add/add-workflow-graph.ts +522 -0
- package/src/add/add-workflow.ts +117 -30
- package/src/error-codes.ts +26 -1
- package/src/index.ts +27 -8
- package/src/inspector.ts +145 -17
- package/src/schema-generator.ts +1 -0
- package/src/types-map.ts +12 -1
- package/src/types.ts +192 -51
- package/src/utils/compute-required-schemas.ts +49 -0
- package/src/utils/contract-hashes.test.ts +528 -0
- package/src/utils/contract-hashes.ts +290 -0
- package/src/utils/custom-types-generator.ts +88 -0
- package/src/utils/detect-schema-vendor.ts +90 -0
- package/src/utils/ensure-function-metadata.ts +324 -7
- package/src/utils/extract-function-name.ts +108 -358
- package/src/utils/extract-services.ts +35 -2
- package/src/utils/filter-inspector-state.test.ts +34 -20
- package/src/utils/filter-inspector-state.ts +140 -31
- package/src/utils/get-property-value.ts +50 -5
- package/src/utils/hash.ts +26 -0
- package/src/utils/middleware.test.ts +204 -0
- package/src/utils/middleware.ts +129 -67
- package/src/utils/permissions.test.ts +35 -12
- package/src/utils/permissions.ts +10 -10
- package/src/utils/post-process.ts +283 -43
- package/src/utils/resolve-external-package.ts +42 -0
- package/src/utils/resolve-function-types.ts +42 -0
- package/src/utils/resolve-identifier.ts +46 -0
- package/src/utils/resolve-versions.test.ts +249 -0
- package/src/utils/resolve-versions.ts +105 -0
- package/src/utils/schema-generator.ts +329 -0
- package/src/utils/serialize-inspector-state.ts +181 -20
- package/src/utils/serialize-mcp-json.ts +145 -0
- package/src/utils/serialize-middleware-groups-meta.ts +33 -0
- package/src/utils/serialize-openapi-json.ts +277 -0
- package/src/utils/serialize-permissions-groups-meta.ts +35 -0
- package/src/utils/test-data/inspector-state.json +69 -66
- package/src/utils/workflow/dsl/deserialize-dsl-workflow.ts +1104 -0
- package/src/{workflow/extract-simple-workflow.ts → utils/workflow/dsl/extract-dsl-workflow.ts} +678 -85
- package/src/utils/workflow/dsl/index.ts +11 -0
- package/src/{workflow → utils/workflow/dsl}/patterns.ts +108 -11
- package/src/{workflow → utils/workflow/dsl}/validation.ts +34 -7
- package/src/utils/workflow/graph/convert-dsl-to-graph.ts +422 -0
- package/src/utils/workflow/graph/finalize-workflow-wires.ts +310 -0
- package/src/utils/workflow/graph/finalize-workflows.ts +100 -0
- package/src/utils/workflow/graph/index.ts +11 -0
- package/src/utils/workflow/graph/serialize-workflow-graph.ts +216 -0
- package/src/utils/workflow/graph/workflow-graph.types.ts +231 -0
- package/src/visit.ts +14 -2
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/add/add-mcp-tool.d.ts +0 -2
- package/dist/add/add-mcp-tool.js +0 -81
- package/dist/utils/extract-service-metadata.d.ts +0 -19
- package/dist/utils/extract-service-metadata.js +0 -244
- package/dist/utils/write-service-metadata.d.ts +0 -13
- package/dist/utils/write-service-metadata.js +0 -37
- package/src/add/add-mcp-tool.ts +0 -141
- package/src/utils/extract-service-metadata.ts +0 -353
- package/src/utils/write-service-metadata.ts +0 -51
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as ts from 'typescript'
|
|
2
|
-
import { FunctionServicesMeta } from '@pikku/core'
|
|
2
|
+
import { FunctionServicesMeta, FunctionWiresMeta } from '@pikku/core'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Extract services from a function's first parameter destructuring pattern
|
|
@@ -26,10 +26,43 @@ export function extractServicesFromFunction(
|
|
|
26
26
|
services.services.push(original)
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
-
} else if (
|
|
29
|
+
} else if (
|
|
30
|
+
ts.isIdentifier(firstParam.name) &&
|
|
31
|
+
!firstParam.name.text.startsWith('_')
|
|
32
|
+
) {
|
|
30
33
|
services.optimized = false
|
|
31
34
|
}
|
|
32
35
|
}
|
|
33
36
|
|
|
34
37
|
return services
|
|
35
38
|
}
|
|
39
|
+
|
|
40
|
+
export function extractUsedWires(
|
|
41
|
+
handlerNode: ts.FunctionExpression | ts.ArrowFunction,
|
|
42
|
+
paramIndex: number
|
|
43
|
+
): FunctionWiresMeta {
|
|
44
|
+
const param = handlerNode.parameters[paramIndex]
|
|
45
|
+
if (param && ts.isObjectBindingPattern(param.name)) {
|
|
46
|
+
const wires: string[] = []
|
|
47
|
+
for (const elem of param.name.elements) {
|
|
48
|
+
const propertyName =
|
|
49
|
+
elem.propertyName && ts.isIdentifier(elem.propertyName)
|
|
50
|
+
? elem.propertyName.text
|
|
51
|
+
: ts.isIdentifier(elem.name)
|
|
52
|
+
? elem.name.text
|
|
53
|
+
: undefined
|
|
54
|
+
if (propertyName) {
|
|
55
|
+
wires.push(propertyName)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return { optimized: true, wires }
|
|
59
|
+
}
|
|
60
|
+
if (
|
|
61
|
+
param &&
|
|
62
|
+
ts.isIdentifier(param.name) &&
|
|
63
|
+
!param.name.text.startsWith('_')
|
|
64
|
+
) {
|
|
65
|
+
return { optimized: false, wires: [] }
|
|
66
|
+
}
|
|
67
|
+
return { optimized: true, wires: [] }
|
|
68
|
+
}
|
|
@@ -46,7 +46,7 @@ function createMockInspectorState(): Omit<InspectorState, 'typesLookup'> {
|
|
|
46
46
|
meta: {
|
|
47
47
|
get: {
|
|
48
48
|
'/api/users': {
|
|
49
|
-
|
|
49
|
+
pikkuFuncId: 'getUsers',
|
|
50
50
|
route: '/api/users',
|
|
51
51
|
method: 'GET',
|
|
52
52
|
tags: ['api', 'public'],
|
|
@@ -54,7 +54,7 @@ function createMockInspectorState(): Omit<InspectorState, 'typesLookup'> {
|
|
|
54
54
|
permissions: [],
|
|
55
55
|
},
|
|
56
56
|
'/admin/settings': {
|
|
57
|
-
|
|
57
|
+
pikkuFuncId: 'getAdminSettings',
|
|
58
58
|
route: '/admin/settings',
|
|
59
59
|
method: 'GET',
|
|
60
60
|
tags: ['admin'],
|
|
@@ -64,7 +64,7 @@ function createMockInspectorState(): Omit<InspectorState, 'typesLookup'> {
|
|
|
64
64
|
},
|
|
65
65
|
post: {
|
|
66
66
|
'/api/users': {
|
|
67
|
-
|
|
67
|
+
pikkuFuncId: 'createUser',
|
|
68
68
|
route: '/api/users',
|
|
69
69
|
method: 'POST',
|
|
70
70
|
tags: ['api'],
|
|
@@ -152,13 +152,13 @@ function createMockInspectorState(): Omit<InspectorState, 'typesLookup'> {
|
|
|
152
152
|
channels: {
|
|
153
153
|
meta: {
|
|
154
154
|
'chat-channel': {
|
|
155
|
-
|
|
155
|
+
pikkuFuncId: 'handleChatMessage',
|
|
156
156
|
tags: ['realtime', 'public'],
|
|
157
157
|
middleware: [],
|
|
158
158
|
permissions: [],
|
|
159
159
|
},
|
|
160
160
|
'admin-channel': {
|
|
161
|
-
|
|
161
|
+
pikkuFuncId: 'handleAdminMessage',
|
|
162
162
|
tags: ['realtime', 'admin'],
|
|
163
163
|
middleware: [{ type: 'wire', name: 'authMiddleware' }],
|
|
164
164
|
permissions: [],
|
|
@@ -169,13 +169,13 @@ function createMockInspectorState(): Omit<InspectorState, 'typesLookup'> {
|
|
|
169
169
|
scheduledTasks: {
|
|
170
170
|
meta: {
|
|
171
171
|
'daily-report': {
|
|
172
|
-
|
|
172
|
+
pikkuFuncId: 'dailyReport',
|
|
173
173
|
schedule: '0 0 * * *',
|
|
174
174
|
tags: ['cron', 'reports'],
|
|
175
175
|
middleware: [],
|
|
176
176
|
},
|
|
177
177
|
'hourly-cleanup': {
|
|
178
|
-
|
|
178
|
+
pikkuFuncId: 'hourlyCleanup',
|
|
179
179
|
schedule: '0 * * * *',
|
|
180
180
|
tags: ['cron', 'maintenance'],
|
|
181
181
|
middleware: [],
|
|
@@ -186,20 +186,27 @@ function createMockInspectorState(): Omit<InspectorState, 'typesLookup'> {
|
|
|
186
186
|
queueWorkers: {
|
|
187
187
|
meta: {
|
|
188
188
|
'email-worker': {
|
|
189
|
-
|
|
190
|
-
|
|
189
|
+
pikkuFuncId: 'sendEmailWorker',
|
|
190
|
+
name: 'email-queue',
|
|
191
191
|
tags: ['queue', 'email'],
|
|
192
192
|
middleware: [],
|
|
193
193
|
},
|
|
194
194
|
'notification-worker': {
|
|
195
|
-
|
|
196
|
-
|
|
195
|
+
pikkuFuncId: 'sendNotificationWorker',
|
|
196
|
+
name: 'notification-queue',
|
|
197
197
|
tags: ['queue', 'notifications'],
|
|
198
198
|
middleware: [],
|
|
199
199
|
},
|
|
200
200
|
},
|
|
201
201
|
files: new Set(['/test/project/src/workers/email.ts']),
|
|
202
202
|
},
|
|
203
|
+
workflows: {
|
|
204
|
+
meta: {},
|
|
205
|
+
files: new Map(),
|
|
206
|
+
graphMeta: {},
|
|
207
|
+
graphFiles: new Map(),
|
|
208
|
+
invokedWorkflows: new Set(),
|
|
209
|
+
},
|
|
203
210
|
rpc: {
|
|
204
211
|
internalMeta: {},
|
|
205
212
|
internalFiles: new Map(),
|
|
@@ -212,7 +219,7 @@ function createMockInspectorState(): Omit<InspectorState, 'typesLookup'> {
|
|
|
212
219
|
'search-tool': {
|
|
213
220
|
name: 'search-tool',
|
|
214
221
|
description: 'Search tool',
|
|
215
|
-
|
|
222
|
+
pikkuFuncId: 'mcpSearchTool',
|
|
216
223
|
tags: ['mcp', 'search'],
|
|
217
224
|
middleware: [],
|
|
218
225
|
permissions: [],
|
|
@@ -220,7 +227,7 @@ function createMockInspectorState(): Omit<InspectorState, 'typesLookup'> {
|
|
|
220
227
|
'analyze-tool': {
|
|
221
228
|
name: 'analyze-tool',
|
|
222
229
|
description: 'Analyze tool',
|
|
223
|
-
|
|
230
|
+
pikkuFuncId: 'mcpAnalyzeTool',
|
|
224
231
|
tags: ['mcp', 'analytics'],
|
|
225
232
|
middleware: [],
|
|
226
233
|
permissions: [],
|
|
@@ -231,7 +238,7 @@ function createMockInspectorState(): Omit<InspectorState, 'typesLookup'> {
|
|
|
231
238
|
title: 'Docs Resource',
|
|
232
239
|
description: 'Documentation resource',
|
|
233
240
|
uri: 'docs://resource',
|
|
234
|
-
|
|
241
|
+
pikkuFuncId: 'mcpDocsResource',
|
|
235
242
|
tags: ['mcp', 'docs'],
|
|
236
243
|
middleware: [],
|
|
237
244
|
permissions: [],
|
|
@@ -241,7 +248,7 @@ function createMockInspectorState(): Omit<InspectorState, 'typesLookup'> {
|
|
|
241
248
|
'help-prompt': {
|
|
242
249
|
name: 'help-prompt',
|
|
243
250
|
description: 'Help prompt',
|
|
244
|
-
|
|
251
|
+
pikkuFuncId: 'mcpHelpPrompt',
|
|
245
252
|
tags: ['mcp', 'help'],
|
|
246
253
|
middleware: [],
|
|
247
254
|
permissions: [],
|
|
@@ -255,14 +262,14 @@ function createMockInspectorState(): Omit<InspectorState, 'typesLookup'> {
|
|
|
255
262
|
'my-cli': {
|
|
256
263
|
commands: {
|
|
257
264
|
build: {
|
|
258
|
-
|
|
265
|
+
pikkuFuncId: 'cliCommand',
|
|
259
266
|
tags: ['cli', 'build'],
|
|
260
267
|
middleware: [],
|
|
261
268
|
positionals: [],
|
|
262
269
|
options: {},
|
|
263
270
|
} as any,
|
|
264
271
|
test: {
|
|
265
|
-
|
|
272
|
+
pikkuFuncId: 'cliTestCommand',
|
|
266
273
|
tags: ['cli', 'test'],
|
|
267
274
|
middleware: [],
|
|
268
275
|
positionals: [],
|
|
@@ -275,11 +282,18 @@ function createMockInspectorState(): Omit<InspectorState, 'typesLookup'> {
|
|
|
275
282
|
files: new Set(['/test/project/src/cli/commands.ts']),
|
|
276
283
|
},
|
|
277
284
|
middleware: {
|
|
278
|
-
|
|
285
|
+
definitions: {},
|
|
286
|
+
instances: {},
|
|
287
|
+
tagMiddleware: new Map(),
|
|
288
|
+
},
|
|
289
|
+
channelMiddleware: {
|
|
290
|
+
definitions: {},
|
|
291
|
+
instances: {},
|
|
279
292
|
tagMiddleware: new Map(),
|
|
280
293
|
},
|
|
281
294
|
permissions: {
|
|
282
|
-
|
|
295
|
+
definitions: {},
|
|
296
|
+
instances: {},
|
|
283
297
|
tagPermissions: new Map(),
|
|
284
298
|
},
|
|
285
299
|
serviceAggregation: {
|
|
@@ -413,7 +427,7 @@ describe('filterInspectorState', () => {
|
|
|
413
427
|
|
|
414
428
|
assert.equal(Object.keys(result.http.meta.get).length, 1)
|
|
415
429
|
assert.ok(result.http.meta.get['/api/users'])
|
|
416
|
-
assert.equal(result.http.meta.get['/api/users'].
|
|
430
|
+
assert.equal(result.http.meta.get['/api/users'].pikkuFuncId, 'getUsers')
|
|
417
431
|
})
|
|
418
432
|
|
|
419
433
|
test('should filter HTTP routes by name wildcard', () => {
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { InspectorState, InspectorFilters, InspectorLogger } from '../types.js'
|
|
2
|
-
import { PikkuWiringTypes } from '@pikku/core'
|
|
2
|
+
import { PikkuWiringTypes, parseVersionedId } from '@pikku/core'
|
|
3
3
|
import { aggregateRequiredServices } from './post-process.js'
|
|
4
4
|
|
|
5
|
+
// Module-level Set to track warned groups across multiple filter calls
|
|
6
|
+
const globalWarnedGroups = new Set<string>()
|
|
7
|
+
|
|
5
8
|
/**
|
|
6
9
|
* Match a value against a pattern with wildcard support
|
|
7
10
|
* Supports "*" at the beginning, end, or both (e.g., "send*", "*Payment", "*process*")
|
|
@@ -39,8 +42,10 @@ function matchesFilters(
|
|
|
39
42
|
filePath?: string
|
|
40
43
|
httpRoute?: string
|
|
41
44
|
httpMethod?: string
|
|
45
|
+
groupBasePath?: string
|
|
42
46
|
},
|
|
43
|
-
logger: InspectorLogger
|
|
47
|
+
logger: InspectorLogger,
|
|
48
|
+
warnedGroups?: Set<string>
|
|
44
49
|
): boolean {
|
|
45
50
|
// If no filters, allow everything
|
|
46
51
|
if (Object.keys(filters).length === 0) return true
|
|
@@ -87,10 +92,13 @@ function matchesFilters(
|
|
|
87
92
|
}
|
|
88
93
|
}
|
|
89
94
|
|
|
90
|
-
// Check name filter
|
|
95
|
+
// Check name filter (match against both full ID and base name for versioned functions)
|
|
91
96
|
if (filters.names && filters.names.length > 0) {
|
|
92
|
-
const
|
|
93
|
-
|
|
97
|
+
const { baseName } = parseVersionedId(meta.name)
|
|
98
|
+
const nameMatches = filters.names.some(
|
|
99
|
+
(pattern) =>
|
|
100
|
+
matchesWildcard(meta.name, pattern) ||
|
|
101
|
+
(baseName !== meta.name && matchesWildcard(baseName, pattern))
|
|
94
102
|
)
|
|
95
103
|
if (!nameMatches) {
|
|
96
104
|
logger.debug(`⒡ Filtered by name: ${meta.type}:${meta.name}`)
|
|
@@ -107,6 +115,23 @@ function matchesFilters(
|
|
|
107
115
|
logger.debug(`⒡ Filtered by HTTP route: ${meta.httpRoute}`)
|
|
108
116
|
return false
|
|
109
117
|
}
|
|
118
|
+
|
|
119
|
+
// If route is part of a wireHTTPRoutes group, check if filter is at group level
|
|
120
|
+
if (meta.groupBasePath && warnedGroups) {
|
|
121
|
+
const groupMatches = filters.httpRoutes.some(
|
|
122
|
+
(pattern) =>
|
|
123
|
+
matchesWildcard(meta.groupBasePath!, pattern) ||
|
|
124
|
+
matchesWildcard(meta.groupBasePath! + '/*', pattern)
|
|
125
|
+
)
|
|
126
|
+
if (!groupMatches && !warnedGroups.has(meta.groupBasePath)) {
|
|
127
|
+
warnedGroups.add(meta.groupBasePath)
|
|
128
|
+
logger.warn(
|
|
129
|
+
`Filtering within wireHTTPRoutes group is not yet supported. ` +
|
|
130
|
+
`Route '${meta.httpRoute}' is part of group '${meta.groupBasePath}'. ` +
|
|
131
|
+
`Use '--httpRoutes=${meta.groupBasePath}/*' to filter the entire group.`
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
110
135
|
}
|
|
111
136
|
|
|
112
137
|
// Check HTTP method filter
|
|
@@ -181,6 +206,11 @@ export function filterInspectorState(
|
|
|
181
206
|
meta: JSON.parse(JSON.stringify(state.channels.meta)),
|
|
182
207
|
files: new Set<string>(), // Will be repopulated with filtered files
|
|
183
208
|
},
|
|
209
|
+
triggers: {
|
|
210
|
+
...state.triggers,
|
|
211
|
+
meta: JSON.parse(JSON.stringify(state.triggers?.meta ?? {})),
|
|
212
|
+
files: new Set<string>(),
|
|
213
|
+
},
|
|
184
214
|
scheduledTasks: {
|
|
185
215
|
...state.scheduledTasks,
|
|
186
216
|
meta: JSON.parse(JSON.stringify(state.scheduledTasks.meta)),
|
|
@@ -198,7 +228,12 @@ export function filterInspectorState(
|
|
|
198
228
|
JSON.stringify(state.mcpEndpoints.resourcesMeta)
|
|
199
229
|
),
|
|
200
230
|
promptsMeta: JSON.parse(JSON.stringify(state.mcpEndpoints.promptsMeta)),
|
|
201
|
-
files: new Set<string>(),
|
|
231
|
+
files: new Set<string>(),
|
|
232
|
+
},
|
|
233
|
+
agents: {
|
|
234
|
+
...state.agents,
|
|
235
|
+
agentsMeta: JSON.parse(JSON.stringify(state.agents?.agentsMeta ?? {})),
|
|
236
|
+
files: new Map(),
|
|
202
237
|
},
|
|
203
238
|
cli: {
|
|
204
239
|
...state.cli,
|
|
@@ -214,31 +249,31 @@ export function filterInspectorState(
|
|
|
214
249
|
const routeMeta = routes[route]
|
|
215
250
|
|
|
216
251
|
// Get function file path for directory filtering
|
|
217
|
-
const funcFile = filteredState.functions.files.get(
|
|
218
|
-
routeMeta.pikkuFuncName
|
|
219
|
-
)
|
|
252
|
+
const funcFile = filteredState.functions.files.get(routeMeta.pikkuFuncId)
|
|
220
253
|
const filePath = funcFile?.path
|
|
221
254
|
|
|
222
255
|
const matches = matchesFilters(
|
|
223
256
|
filters,
|
|
224
257
|
{
|
|
225
258
|
type: 'http' as PikkuWiringTypes,
|
|
226
|
-
name: routeMeta.
|
|
259
|
+
name: routeMeta.pikkuFuncId, // Use function name, not route
|
|
227
260
|
tags: routeMeta.tags,
|
|
228
261
|
filePath,
|
|
229
262
|
httpRoute: routeMeta.route,
|
|
230
263
|
httpMethod: routeMeta.method,
|
|
264
|
+
groupBasePath: routeMeta.groupBasePath,
|
|
231
265
|
},
|
|
232
|
-
logger
|
|
266
|
+
logger,
|
|
267
|
+
globalWarnedGroups
|
|
233
268
|
)
|
|
234
269
|
|
|
235
270
|
if (!matches) {
|
|
236
271
|
delete routes[route]
|
|
237
272
|
} else {
|
|
238
273
|
// Track used functions/middleware/permissions
|
|
239
|
-
if (routeMeta.
|
|
274
|
+
if (routeMeta.pikkuFuncId) {
|
|
240
275
|
filteredState.serviceAggregation.usedFunctions.add(
|
|
241
|
-
routeMeta.
|
|
276
|
+
routeMeta.pikkuFuncId
|
|
242
277
|
)
|
|
243
278
|
}
|
|
244
279
|
extractWireNames(routeMeta.middleware).forEach((name: string) =>
|
|
@@ -275,9 +310,9 @@ export function filterInspectorState(
|
|
|
275
310
|
if (!matches) {
|
|
276
311
|
delete filteredState.channels.meta[name]
|
|
277
312
|
} else {
|
|
278
|
-
if (channelMeta.
|
|
313
|
+
if (channelMeta.pikkuFuncId) {
|
|
279
314
|
filteredState.serviceAggregation.usedFunctions.add(
|
|
280
|
-
channelMeta.
|
|
315
|
+
channelMeta.pikkuFuncId
|
|
281
316
|
)
|
|
282
317
|
}
|
|
283
318
|
extractWireNames(channelMeta.middleware).forEach((name: string) =>
|
|
@@ -294,6 +329,35 @@ export function filterInspectorState(
|
|
|
294
329
|
filteredState.channels.files = new Set(state.channels.files)
|
|
295
330
|
}
|
|
296
331
|
|
|
332
|
+
// Filter triggers
|
|
333
|
+
for (const name of Object.keys(filteredState.triggers.meta)) {
|
|
334
|
+
const triggerMeta = filteredState.triggers.meta[name]
|
|
335
|
+
const matches = matchesFilters(
|
|
336
|
+
filters,
|
|
337
|
+
{
|
|
338
|
+
type: 'trigger' as PikkuWiringTypes,
|
|
339
|
+
name,
|
|
340
|
+
tags: triggerMeta.tags,
|
|
341
|
+
},
|
|
342
|
+
logger
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
if (!matches) {
|
|
346
|
+
delete filteredState.triggers.meta[name]
|
|
347
|
+
} else {
|
|
348
|
+
if (triggerMeta.pikkuFuncId) {
|
|
349
|
+
filteredState.serviceAggregation.usedFunctions.add(
|
|
350
|
+
triggerMeta.pikkuFuncId
|
|
351
|
+
)
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Repopulate triggers.files if any triggers remain
|
|
357
|
+
if (Object.keys(filteredState.triggers.meta).length > 0) {
|
|
358
|
+
filteredState.triggers.files = new Set(state.triggers.files)
|
|
359
|
+
}
|
|
360
|
+
|
|
297
361
|
// Filter scheduled tasks
|
|
298
362
|
for (const name of Object.keys(filteredState.scheduledTasks.meta)) {
|
|
299
363
|
const taskMeta = filteredState.scheduledTasks.meta[name]
|
|
@@ -310,10 +374,8 @@ export function filterInspectorState(
|
|
|
310
374
|
if (!matches) {
|
|
311
375
|
delete filteredState.scheduledTasks.meta[name]
|
|
312
376
|
} else {
|
|
313
|
-
if (taskMeta.
|
|
314
|
-
filteredState.serviceAggregation.usedFunctions.add(
|
|
315
|
-
taskMeta.pikkuFuncName
|
|
316
|
-
)
|
|
377
|
+
if (taskMeta.pikkuFuncId) {
|
|
378
|
+
filteredState.serviceAggregation.usedFunctions.add(taskMeta.pikkuFuncId)
|
|
317
379
|
}
|
|
318
380
|
extractWireNames(taskMeta.middleware).forEach((name: string) =>
|
|
319
381
|
filteredState.serviceAggregation.usedMiddleware.add(name)
|
|
@@ -342,9 +404,9 @@ export function filterInspectorState(
|
|
|
342
404
|
if (!matches) {
|
|
343
405
|
delete filteredState.queueWorkers.meta[name]
|
|
344
406
|
} else {
|
|
345
|
-
if (workerMeta.
|
|
407
|
+
if (workerMeta.pikkuFuncId) {
|
|
346
408
|
filteredState.serviceAggregation.usedFunctions.add(
|
|
347
|
-
workerMeta.
|
|
409
|
+
workerMeta.pikkuFuncId
|
|
348
410
|
)
|
|
349
411
|
}
|
|
350
412
|
extractWireNames(workerMeta.middleware).forEach((name: string) =>
|
|
@@ -374,10 +436,8 @@ export function filterInspectorState(
|
|
|
374
436
|
if (!matches) {
|
|
375
437
|
delete filteredState.mcpEndpoints.toolsMeta[name]
|
|
376
438
|
} else {
|
|
377
|
-
if (toolMeta.
|
|
378
|
-
filteredState.serviceAggregation.usedFunctions.add(
|
|
379
|
-
toolMeta.pikkuFuncName
|
|
380
|
-
)
|
|
439
|
+
if (toolMeta.pikkuFuncId) {
|
|
440
|
+
filteredState.serviceAggregation.usedFunctions.add(toolMeta.pikkuFuncId)
|
|
381
441
|
}
|
|
382
442
|
extractWireNames(toolMeta.middleware).forEach((name: string) =>
|
|
383
443
|
filteredState.serviceAggregation.usedMiddleware.add(name)
|
|
@@ -404,9 +464,9 @@ export function filterInspectorState(
|
|
|
404
464
|
if (!matches) {
|
|
405
465
|
delete filteredState.mcpEndpoints.resourcesMeta[name]
|
|
406
466
|
} else {
|
|
407
|
-
if (resourceMeta.
|
|
467
|
+
if (resourceMeta.pikkuFuncId) {
|
|
408
468
|
filteredState.serviceAggregation.usedFunctions.add(
|
|
409
|
-
resourceMeta.
|
|
469
|
+
resourceMeta.pikkuFuncId
|
|
410
470
|
)
|
|
411
471
|
}
|
|
412
472
|
extractWireNames(resourceMeta.middleware).forEach((name: string) =>
|
|
@@ -434,9 +494,9 @@ export function filterInspectorState(
|
|
|
434
494
|
if (!matches) {
|
|
435
495
|
delete filteredState.mcpEndpoints.promptsMeta[name]
|
|
436
496
|
} else {
|
|
437
|
-
if (promptMeta.
|
|
497
|
+
if (promptMeta.pikkuFuncId) {
|
|
438
498
|
filteredState.serviceAggregation.usedFunctions.add(
|
|
439
|
-
promptMeta.
|
|
499
|
+
promptMeta.pikkuFuncId
|
|
440
500
|
)
|
|
441
501
|
}
|
|
442
502
|
extractWireNames(promptMeta.middleware).forEach((name: string) =>
|
|
@@ -457,6 +517,40 @@ export function filterInspectorState(
|
|
|
457
517
|
filteredState.mcpEndpoints.files = new Set(state.mcpEndpoints.files)
|
|
458
518
|
}
|
|
459
519
|
|
|
520
|
+
// Filter AI agents
|
|
521
|
+
for (const name of Object.keys(filteredState.agents.agentsMeta)) {
|
|
522
|
+
const agentMeta = filteredState.agents.agentsMeta[name]
|
|
523
|
+
const matches = matchesFilters(
|
|
524
|
+
filters,
|
|
525
|
+
{
|
|
526
|
+
type: 'agent' as PikkuWiringTypes,
|
|
527
|
+
name,
|
|
528
|
+
tags: agentMeta.tags,
|
|
529
|
+
},
|
|
530
|
+
logger
|
|
531
|
+
)
|
|
532
|
+
|
|
533
|
+
if (!matches) {
|
|
534
|
+
delete filteredState.agents.agentsMeta[name]
|
|
535
|
+
} else {
|
|
536
|
+
if (agentMeta.pikkuFuncId) {
|
|
537
|
+
filteredState.serviceAggregation.usedFunctions.add(
|
|
538
|
+
agentMeta.pikkuFuncId
|
|
539
|
+
)
|
|
540
|
+
}
|
|
541
|
+
extractWireNames(agentMeta.middleware).forEach((name: string) =>
|
|
542
|
+
filteredState.serviceAggregation.usedMiddleware.add(name)
|
|
543
|
+
)
|
|
544
|
+
extractWireNames(agentMeta.permissions).forEach((name: string) =>
|
|
545
|
+
filteredState.serviceAggregation.usedPermissions.add(name)
|
|
546
|
+
)
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
if (Object.keys(filteredState.agents.agentsMeta).length > 0) {
|
|
551
|
+
filteredState.agents.files = new Map(state.agents.files)
|
|
552
|
+
}
|
|
553
|
+
|
|
460
554
|
// Filter CLI programs (note: CLI filtering might be more complex with nested commands)
|
|
461
555
|
const referencedRenderers = new Set<string>()
|
|
462
556
|
|
|
@@ -479,9 +573,9 @@ export function filterInspectorState(
|
|
|
479
573
|
if (!matches) {
|
|
480
574
|
delete programMeta.commands[commandName]
|
|
481
575
|
} else {
|
|
482
|
-
if (commandMeta.
|
|
576
|
+
if (commandMeta.pikkuFuncId) {
|
|
483
577
|
filteredState.serviceAggregation.usedFunctions.add(
|
|
484
|
-
commandMeta.
|
|
578
|
+
commandMeta.pikkuFuncId
|
|
485
579
|
)
|
|
486
580
|
}
|
|
487
581
|
extractWireNames(commandMeta.middleware).forEach((name: string) =>
|
|
@@ -517,6 +611,21 @@ export function filterInspectorState(
|
|
|
517
611
|
filteredState.cli.files = new Set(state.cli.files)
|
|
518
612
|
}
|
|
519
613
|
|
|
614
|
+
// Post-filter version expansion: include all versions of matched functions
|
|
615
|
+
const includedBaseNames = new Set<string>()
|
|
616
|
+
for (const funcId of filteredState.serviceAggregation.usedFunctions) {
|
|
617
|
+
const { baseName } = parseVersionedId(funcId)
|
|
618
|
+
includedBaseNames.add(baseName)
|
|
619
|
+
}
|
|
620
|
+
if (includedBaseNames.size > 0) {
|
|
621
|
+
for (const funcId of Object.keys(state.functions.meta)) {
|
|
622
|
+
const { baseName } = parseVersionedId(funcId)
|
|
623
|
+
if (includedBaseNames.has(baseName)) {
|
|
624
|
+
filteredState.serviceAggregation.usedFunctions.add(funcId)
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
|
|
520
629
|
// Recalculate requiredServices based on filtered functions/middleware/permissions
|
|
521
630
|
// Need to cast to InspectorState temporarily for aggregateRequiredServices
|
|
522
631
|
const stateForAggregation = filteredState as InspectorState
|
|
@@ -1,10 +1,36 @@
|
|
|
1
1
|
import * as ts from 'typescript'
|
|
2
2
|
import { ErrorCode } from '../error-codes.js'
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Extracts an array of strings from an object property.
|
|
6
|
+
*/
|
|
7
|
+
export const getArrayPropertyValue = (
|
|
8
|
+
obj: ts.ObjectLiteralExpression,
|
|
9
|
+
propertyName: string
|
|
10
|
+
): string[] | null => {
|
|
11
|
+
const property = obj.properties.find(
|
|
12
|
+
(p) =>
|
|
13
|
+
ts.isPropertyAssignment(p) &&
|
|
14
|
+
ts.isIdentifier(p.name) &&
|
|
15
|
+
p.name.text === propertyName
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
if (property && ts.isPropertyAssignment(property)) {
|
|
19
|
+
const initializer = property.initializer
|
|
20
|
+
if (ts.isArrayLiteralExpression(initializer)) {
|
|
21
|
+
return initializer.elements
|
|
22
|
+
.filter(ts.isStringLiteral)
|
|
23
|
+
.map((element) => element.text)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return null
|
|
28
|
+
}
|
|
29
|
+
|
|
4
30
|
export const getPropertyValue = (
|
|
5
31
|
obj: ts.ObjectLiteralExpression,
|
|
6
32
|
propertyName: string
|
|
7
|
-
): string | string[] | null | boolean => {
|
|
33
|
+
): string | string[] | number | null | boolean => {
|
|
8
34
|
const property = obj.properties.find(
|
|
9
35
|
(p) =>
|
|
10
36
|
ts.isPropertyAssignment(p) &&
|
|
@@ -41,7 +67,13 @@ export const getPropertyValue = (
|
|
|
41
67
|
return false
|
|
42
68
|
}
|
|
43
69
|
|
|
44
|
-
|
|
70
|
+
if (ts.isNumericLiteral(initializer)) {
|
|
71
|
+
if (propertyName === 'name' || propertyName === 'schedule') {
|
|
72
|
+
return initializer.text
|
|
73
|
+
}
|
|
74
|
+
return Number(initializer.text)
|
|
75
|
+
}
|
|
76
|
+
|
|
45
77
|
if (
|
|
46
78
|
ts.isStringLiteral(initializer) ||
|
|
47
79
|
ts.isNoSubstitutionTemplateLiteral(initializer)
|
|
@@ -49,7 +81,6 @@ export const getPropertyValue = (
|
|
|
49
81
|
return initializer.text
|
|
50
82
|
}
|
|
51
83
|
|
|
52
|
-
// Handle other initializer types if necessary
|
|
53
84
|
return initializer.getText()
|
|
54
85
|
}
|
|
55
86
|
|
|
@@ -57,7 +88,7 @@ export const getPropertyValue = (
|
|
|
57
88
|
}
|
|
58
89
|
|
|
59
90
|
/**
|
|
60
|
-
* Extracts common wire metadata (tags, summary, description, errors) directly from an object
|
|
91
|
+
* Extracts common wire metadata (title, tags, summary, description, errors) directly from an object
|
|
61
92
|
* @param obj - The TypeScript object literal expression to extract metadata from
|
|
62
93
|
* @param wiringType - The type of wiring (e.g., 'HTTP route', 'Channel', 'Queue worker')
|
|
63
94
|
* @param wiringName - The name/identifier of the wiring (e.g., route path, channel name)
|
|
@@ -70,12 +101,16 @@ export const getCommonWireMetaData = (
|
|
|
70
101
|
wiringName: string | null,
|
|
71
102
|
logger?: { critical: (code: ErrorCode, message: string) => void }
|
|
72
103
|
): {
|
|
104
|
+
disabled?: true
|
|
105
|
+
title?: string
|
|
73
106
|
tags?: string[]
|
|
74
107
|
summary?: string
|
|
75
108
|
description?: string
|
|
76
109
|
errors?: string[]
|
|
77
110
|
} => {
|
|
78
111
|
const metadata: {
|
|
112
|
+
disabled?: true
|
|
113
|
+
title?: string
|
|
79
114
|
tags?: string[]
|
|
80
115
|
summary?: string
|
|
81
116
|
description?: string
|
|
@@ -86,7 +121,17 @@ export const getCommonWireMetaData = (
|
|
|
86
121
|
if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name)) {
|
|
87
122
|
const propName = prop.name.text
|
|
88
123
|
|
|
89
|
-
if (
|
|
124
|
+
if (
|
|
125
|
+
propName === 'disabled' &&
|
|
126
|
+
prop.initializer.kind === ts.SyntaxKind.TrueKeyword
|
|
127
|
+
) {
|
|
128
|
+
metadata.disabled = true
|
|
129
|
+
} else if (propName === 'title' && ts.isStringLiteral(prop.initializer)) {
|
|
130
|
+
metadata.title = prop.initializer.text
|
|
131
|
+
} else if (
|
|
132
|
+
propName === 'summary' &&
|
|
133
|
+
ts.isStringLiteral(prop.initializer)
|
|
134
|
+
) {
|
|
90
135
|
metadata.summary = prop.initializer.text
|
|
91
136
|
} else if (
|
|
92
137
|
propName === 'description' &&
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { createHash } from 'crypto'
|
|
2
|
+
|
|
3
|
+
export function canonicalJSON(obj: unknown): string {
|
|
4
|
+
return JSON.stringify(sortDeep(obj))
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function sortDeep(value: unknown): unknown {
|
|
8
|
+
if (value === null || value === undefined) {
|
|
9
|
+
return value
|
|
10
|
+
}
|
|
11
|
+
if (Array.isArray(value)) {
|
|
12
|
+
return value.map(sortDeep)
|
|
13
|
+
}
|
|
14
|
+
if (typeof value === 'object') {
|
|
15
|
+
const sorted: Record<string, unknown> = {}
|
|
16
|
+
for (const key of Object.keys(value as Record<string, unknown>).sort()) {
|
|
17
|
+
sorted[key] = sortDeep((value as Record<string, unknown>)[key])
|
|
18
|
+
}
|
|
19
|
+
return sorted
|
|
20
|
+
}
|
|
21
|
+
return value
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function hashString(input: string, length: number = 16): string {
|
|
25
|
+
return createHash('sha256').update(input).digest('hex').slice(0, length)
|
|
26
|
+
}
|