@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.
Files changed (189) hide show
  1. package/CHANGELOG.md +26 -1
  2. package/OPTIMIZATION-PLAN.md +195 -0
  3. package/dist/add/add-ai-agent.d.ts +2 -0
  4. package/dist/add/add-ai-agent.js +314 -0
  5. package/dist/add/add-channel.js +69 -61
  6. package/dist/add/add-cli.js +36 -18
  7. package/dist/add/add-file-with-factory.js +2 -0
  8. package/dist/add/add-functions.js +327 -59
  9. package/dist/add/add-http-route.d.ts +19 -10
  10. package/dist/add/add-http-route.js +153 -44
  11. package/dist/add/add-http-routes.d.ts +5 -0
  12. package/dist/add/add-http-routes.js +159 -0
  13. package/dist/add/add-keyed-wiring.d.ts +12 -0
  14. package/dist/add/add-keyed-wiring.js +97 -0
  15. package/dist/add/add-mcp-prompt.js +14 -9
  16. package/dist/add/add-mcp-resource.js +14 -9
  17. package/dist/add/add-middleware.d.ts +1 -4
  18. package/dist/add/add-middleware.js +364 -79
  19. package/dist/add/add-permission.d.ts +1 -1
  20. package/dist/add/add-permission.js +152 -40
  21. package/dist/add/add-queue-worker.js +18 -12
  22. package/dist/add/add-rpc-invocations.d.ts +3 -0
  23. package/dist/add/add-rpc-invocations.js +65 -25
  24. package/dist/add/add-schedule.js +11 -5
  25. package/dist/add/add-secret.d.ts +3 -0
  26. package/dist/add/add-secret.js +82 -0
  27. package/dist/add/add-trigger.d.ts +2 -0
  28. package/dist/add/add-trigger.js +87 -0
  29. package/dist/add/add-variable.d.ts +1 -0
  30. package/dist/add/add-variable.js +8 -0
  31. package/dist/add/add-workflow-graph.d.ts +7 -0
  32. package/dist/add/add-workflow-graph.js +396 -0
  33. package/dist/add/add-workflow.js +124 -26
  34. package/dist/error-codes.d.ts +16 -1
  35. package/dist/error-codes.js +21 -1
  36. package/dist/index.d.ts +9 -5
  37. package/dist/index.js +5 -2
  38. package/dist/inspector.d.ts +1 -1
  39. package/dist/inspector.js +106 -13
  40. package/dist/schema-generator.d.ts +1 -0
  41. package/dist/schema-generator.js +1 -0
  42. package/dist/types-map.js +10 -1
  43. package/dist/types.d.ts +180 -30
  44. package/dist/utils/compute-required-schemas.d.ts +4 -0
  45. package/dist/utils/compute-required-schemas.js +41 -0
  46. package/dist/utils/contract-hashes.d.ts +35 -0
  47. package/dist/utils/contract-hashes.js +202 -0
  48. package/dist/utils/custom-types-generator.d.ts +9 -0
  49. package/dist/utils/custom-types-generator.js +71 -0
  50. package/dist/utils/detect-schema-vendor.d.ts +22 -0
  51. package/dist/utils/detect-schema-vendor.js +76 -0
  52. package/dist/utils/ensure-function-metadata.d.ts +5 -2
  53. package/dist/utils/ensure-function-metadata.js +220 -6
  54. package/dist/utils/extract-function-name.d.ts +5 -16
  55. package/dist/utils/extract-function-name.js +93 -298
  56. package/dist/utils/extract-services.d.ts +2 -1
  57. package/dist/utils/extract-services.js +25 -1
  58. package/dist/utils/filter-inspector-state.js +107 -23
  59. package/dist/utils/get-property-value.d.ts +8 -2
  60. package/dist/utils/get-property-value.js +33 -4
  61. package/dist/utils/hash.d.ts +2 -0
  62. package/dist/utils/hash.js +23 -0
  63. package/dist/utils/middleware.d.ts +7 -30
  64. package/dist/utils/middleware.js +80 -66
  65. package/dist/utils/permissions.d.ts +2 -2
  66. package/dist/utils/permissions.js +10 -10
  67. package/dist/utils/post-process.d.ts +9 -10
  68. package/dist/utils/post-process.js +231 -24
  69. package/dist/utils/resolve-external-package.d.ts +12 -0
  70. package/dist/utils/resolve-external-package.js +34 -0
  71. package/dist/utils/resolve-function-types.d.ts +6 -0
  72. package/dist/utils/resolve-function-types.js +29 -0
  73. package/dist/utils/resolve-identifier.d.ts +10 -0
  74. package/dist/utils/resolve-identifier.js +36 -0
  75. package/dist/utils/resolve-versions.d.ts +2 -0
  76. package/dist/utils/resolve-versions.js +78 -0
  77. package/dist/utils/schema-generator.d.ts +9 -0
  78. package/dist/utils/schema-generator.js +209 -0
  79. package/dist/utils/serialize-inspector-state.d.ts +73 -13
  80. package/dist/utils/serialize-inspector-state.js +102 -6
  81. package/dist/utils/serialize-mcp-json.d.ts +2 -0
  82. package/dist/utils/serialize-mcp-json.js +99 -0
  83. package/dist/utils/serialize-middleware-groups-meta.d.ts +12 -0
  84. package/dist/utils/serialize-middleware-groups-meta.js +28 -0
  85. package/dist/utils/serialize-openapi-json.d.ts +85 -0
  86. package/dist/utils/serialize-openapi-json.js +151 -0
  87. package/dist/utils/serialize-permissions-groups-meta.d.ts +6 -0
  88. package/dist/utils/serialize-permissions-groups-meta.js +31 -0
  89. package/dist/utils/workflow/dsl/deserialize-dsl-workflow.d.ts +24 -0
  90. package/dist/utils/workflow/dsl/deserialize-dsl-workflow.js +830 -0
  91. package/dist/{workflow/extract-simple-workflow.d.ts → utils/workflow/dsl/extract-dsl-workflow.d.ts} +4 -2
  92. package/dist/{workflow/extract-simple-workflow.js → utils/workflow/dsl/extract-dsl-workflow.js} +572 -72
  93. package/dist/utils/workflow/dsl/index.d.ts +7 -0
  94. package/dist/utils/workflow/dsl/index.js +7 -0
  95. package/dist/{workflow → utils/workflow/dsl}/patterns.d.ts +21 -0
  96. package/dist/{workflow → utils/workflow/dsl}/patterns.js +90 -10
  97. package/dist/{workflow → utils/workflow/dsl}/validation.d.ts +2 -0
  98. package/dist/{workflow → utils/workflow/dsl}/validation.js +25 -7
  99. package/dist/utils/workflow/graph/convert-dsl-to-graph.d.ts +13 -0
  100. package/dist/utils/workflow/graph/convert-dsl-to-graph.js +318 -0
  101. package/dist/utils/workflow/graph/finalize-workflow-wires.d.ts +3 -0
  102. package/dist/utils/workflow/graph/finalize-workflow-wires.js +276 -0
  103. package/dist/utils/workflow/graph/finalize-workflows.d.ts +2 -0
  104. package/dist/utils/workflow/graph/finalize-workflows.js +75 -0
  105. package/dist/utils/workflow/graph/index.d.ts +8 -0
  106. package/dist/utils/workflow/graph/index.js +8 -0
  107. package/dist/utils/workflow/graph/serialize-workflow-graph.d.ts +35 -0
  108. package/dist/utils/workflow/graph/serialize-workflow-graph.js +150 -0
  109. package/dist/utils/workflow/graph/workflow-graph.types.d.ts +203 -0
  110. package/dist/utils/workflow/graph/workflow-graph.types.js +38 -0
  111. package/dist/visit.js +13 -2
  112. package/package.json +26 -4
  113. package/src/add/add-ai-agent.ts +468 -0
  114. package/src/add/add-channel.ts +82 -79
  115. package/src/add/add-cli.ts +49 -20
  116. package/src/add/add-file-with-factory.ts +2 -0
  117. package/src/add/add-functions.ts +429 -71
  118. package/src/add/add-http-route.ts +246 -65
  119. package/src/add/add-http-routes.ts +228 -0
  120. package/src/add/add-keyed-wiring.ts +151 -0
  121. package/src/add/add-mcp-prompt.ts +26 -15
  122. package/src/add/add-mcp-resource.ts +27 -15
  123. package/src/add/add-middleware.ts +482 -80
  124. package/src/add/add-permission.ts +199 -40
  125. package/src/add/add-queue-worker.ts +24 -19
  126. package/src/add/add-rpc-invocations.ts +78 -31
  127. package/src/add/add-schedule.ts +16 -11
  128. package/src/add/add-secret.ts +140 -0
  129. package/src/add/add-trigger.ts +154 -0
  130. package/src/add/add-variable.ts +9 -0
  131. package/src/add/add-workflow-graph.ts +522 -0
  132. package/src/add/add-workflow.ts +117 -30
  133. package/src/error-codes.ts +26 -1
  134. package/src/index.ts +27 -8
  135. package/src/inspector.ts +145 -17
  136. package/src/schema-generator.ts +1 -0
  137. package/src/types-map.ts +12 -1
  138. package/src/types.ts +192 -51
  139. package/src/utils/compute-required-schemas.ts +49 -0
  140. package/src/utils/contract-hashes.test.ts +528 -0
  141. package/src/utils/contract-hashes.ts +290 -0
  142. package/src/utils/custom-types-generator.ts +88 -0
  143. package/src/utils/detect-schema-vendor.ts +90 -0
  144. package/src/utils/ensure-function-metadata.ts +324 -7
  145. package/src/utils/extract-function-name.ts +108 -358
  146. package/src/utils/extract-services.ts +35 -2
  147. package/src/utils/filter-inspector-state.test.ts +34 -20
  148. package/src/utils/filter-inspector-state.ts +140 -31
  149. package/src/utils/get-property-value.ts +50 -5
  150. package/src/utils/hash.ts +26 -0
  151. package/src/utils/middleware.test.ts +204 -0
  152. package/src/utils/middleware.ts +129 -67
  153. package/src/utils/permissions.test.ts +35 -12
  154. package/src/utils/permissions.ts +10 -10
  155. package/src/utils/post-process.ts +283 -43
  156. package/src/utils/resolve-external-package.ts +42 -0
  157. package/src/utils/resolve-function-types.ts +42 -0
  158. package/src/utils/resolve-identifier.ts +46 -0
  159. package/src/utils/resolve-versions.test.ts +249 -0
  160. package/src/utils/resolve-versions.ts +105 -0
  161. package/src/utils/schema-generator.ts +329 -0
  162. package/src/utils/serialize-inspector-state.ts +181 -20
  163. package/src/utils/serialize-mcp-json.ts +145 -0
  164. package/src/utils/serialize-middleware-groups-meta.ts +33 -0
  165. package/src/utils/serialize-openapi-json.ts +277 -0
  166. package/src/utils/serialize-permissions-groups-meta.ts +35 -0
  167. package/src/utils/test-data/inspector-state.json +69 -66
  168. package/src/utils/workflow/dsl/deserialize-dsl-workflow.ts +1104 -0
  169. package/src/{workflow/extract-simple-workflow.ts → utils/workflow/dsl/extract-dsl-workflow.ts} +678 -85
  170. package/src/utils/workflow/dsl/index.ts +11 -0
  171. package/src/{workflow → utils/workflow/dsl}/patterns.ts +108 -11
  172. package/src/{workflow → utils/workflow/dsl}/validation.ts +34 -7
  173. package/src/utils/workflow/graph/convert-dsl-to-graph.ts +422 -0
  174. package/src/utils/workflow/graph/finalize-workflow-wires.ts +310 -0
  175. package/src/utils/workflow/graph/finalize-workflows.ts +100 -0
  176. package/src/utils/workflow/graph/index.ts +11 -0
  177. package/src/utils/workflow/graph/serialize-workflow-graph.ts +216 -0
  178. package/src/utils/workflow/graph/workflow-graph.types.ts +231 -0
  179. package/src/visit.ts +14 -2
  180. package/tsconfig.tsbuildinfo +1 -1
  181. package/dist/add/add-mcp-tool.d.ts +0 -2
  182. package/dist/add/add-mcp-tool.js +0 -81
  183. package/dist/utils/extract-service-metadata.d.ts +0 -19
  184. package/dist/utils/extract-service-metadata.js +0 -244
  185. package/dist/utils/write-service-metadata.d.ts +0 -13
  186. package/dist/utils/write-service-metadata.js +0 -37
  187. package/src/add/add-mcp-tool.ts +0 -141
  188. package/src/utils/extract-service-metadata.ts +0 -353
  189. package/src/utils/write-service-metadata.ts +0 -51
@@ -0,0 +1,209 @@
1
+ import * as ts from 'typescript';
2
+ import { dirname, join, resolve } from 'path';
3
+ import { createGenerator, RootlessError } from 'ts-json-schema-generator';
4
+ import { tsImport } from 'tsx/esm/api';
5
+ import * as z from 'zod';
6
+ import { zodToTs, createAuxiliaryTypeStore } from 'zod-to-ts';
7
+ import { ErrorCode } from '../error-codes.js';
8
+ import { generateCustomTypes } from './custom-types-generator.js';
9
+ const PRIMITIVE_TYPES = new Set([
10
+ 'boolean',
11
+ 'string',
12
+ 'number',
13
+ 'null',
14
+ 'undefined',
15
+ 'void',
16
+ 'any',
17
+ 'unknown',
18
+ 'never',
19
+ ]);
20
+ function primitiveTypeToSchema(typeStr) {
21
+ const normalized = typeStr.trim();
22
+ if (normalized === 'void' ||
23
+ normalized === 'undefined' ||
24
+ normalized === 'never') {
25
+ return null;
26
+ }
27
+ if (normalized === 'boolean' ||
28
+ normalized === 'false | true' ||
29
+ normalized === 'true | false') {
30
+ return { type: 'boolean' };
31
+ }
32
+ if (normalized === 'true') {
33
+ return { const: true };
34
+ }
35
+ if (normalized === 'false') {
36
+ return { const: false };
37
+ }
38
+ if (normalized === 'string') {
39
+ return { type: 'string' };
40
+ }
41
+ if (normalized === 'number') {
42
+ return { type: 'number' };
43
+ }
44
+ if (normalized === 'null') {
45
+ return { type: 'null' };
46
+ }
47
+ return null;
48
+ }
49
+ function createProgramWithVirtualFile(tsconfig, virtualFilePath, virtualFileContent) {
50
+ const configPath = resolve(tsconfig);
51
+ const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
52
+ const basePath = dirname(configPath);
53
+ const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, basePath);
54
+ const resolvedVirtualPath = resolve(virtualFilePath);
55
+ const fileNames = [...parsedConfig.fileNames, resolvedVirtualPath];
56
+ const defaultHost = ts.createCompilerHost(parsedConfig.options);
57
+ const customHost = {
58
+ ...defaultHost,
59
+ getSourceFile(fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile) {
60
+ if (resolve(fileName) === resolvedVirtualPath) {
61
+ return ts.createSourceFile(fileName, virtualFileContent, languageVersionOrOptions);
62
+ }
63
+ return defaultHost.getSourceFile(fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile);
64
+ },
65
+ fileExists(fileName) {
66
+ if (resolve(fileName) === resolvedVirtualPath)
67
+ return true;
68
+ return defaultHost.fileExists(fileName);
69
+ },
70
+ readFile(fileName) {
71
+ if (resolve(fileName) === resolvedVirtualPath)
72
+ return virtualFileContent;
73
+ return defaultHost.readFile(fileName);
74
+ },
75
+ };
76
+ return ts.createProgram(fileNames, parsedConfig.options, customHost);
77
+ }
78
+ function generateTSSchemas(logger, tsconfig, customTypesContent, typesMap, functionMeta, httpWiringsMeta, additionalTypes, additionalProperties = false, schemaLookup) {
79
+ const schemasSet = new Set(typesMap.customTypes.keys());
80
+ for (const { inputs, outputs } of Object.values(functionMeta)) {
81
+ const types = [...(inputs || []), ...(outputs || [])];
82
+ for (const type of types) {
83
+ try {
84
+ const uniqueName = typesMap.getUniqueName(type);
85
+ if (uniqueName) {
86
+ schemasSet.add(uniqueName);
87
+ }
88
+ }
89
+ catch {
90
+ // Skip types not in typesMap (e.g., inline types in generated workflow workers)
91
+ }
92
+ }
93
+ }
94
+ for (const wiringRoutes of Object.values(httpWiringsMeta)) {
95
+ for (const { inputTypes } of Object.values(wiringRoutes)) {
96
+ if (inputTypes?.body) {
97
+ schemasSet.add(inputTypes.body);
98
+ }
99
+ if (inputTypes?.query) {
100
+ schemasSet.add(inputTypes.query);
101
+ }
102
+ if (inputTypes?.params) {
103
+ schemasSet.add(inputTypes.params);
104
+ }
105
+ }
106
+ }
107
+ if (additionalTypes) {
108
+ for (const type of additionalTypes) {
109
+ schemasSet.add(type);
110
+ }
111
+ }
112
+ const virtualFilePath = join(dirname(resolve(tsconfig)), '__pikku_virtual_types__.ts');
113
+ const program = createProgramWithVirtualFile(tsconfig, virtualFilePath, customTypesContent);
114
+ const generator = createGenerator({
115
+ tsProgram: program,
116
+ skipTypeCheck: true,
117
+ topRef: false,
118
+ discriminatorType: 'open-api',
119
+ expose: 'export',
120
+ jsDoc: 'extended',
121
+ sortProps: true,
122
+ strictTuples: false,
123
+ encodeRefs: false,
124
+ additionalProperties,
125
+ });
126
+ const schemas = {};
127
+ schemasSet.forEach((schema) => {
128
+ if (PRIMITIVE_TYPES.has(schema)) {
129
+ return;
130
+ }
131
+ if (schemaLookup?.has(schema)) {
132
+ return;
133
+ }
134
+ try {
135
+ schemas[schema] = generator.createSchema(schema);
136
+ }
137
+ catch (e) {
138
+ if (e instanceof RootlessError) {
139
+ const customType = typesMap.customTypes.get(schema);
140
+ if (customType) {
141
+ const primitiveSchema = primitiveTypeToSchema(customType.type);
142
+ if (primitiveSchema) {
143
+ schemas[schema] = primitiveSchema;
144
+ }
145
+ }
146
+ return;
147
+ }
148
+ const customType = typesMap.customTypes.get(schema);
149
+ logger.error(`[${ErrorCode.SCHEMA_GENERATION_ERROR}] Error generating schema: ${schema}. Message: ${e.message}. Type info: ${customType ? `type=${customType.type}` : 'not in typesMap'}`);
150
+ }
151
+ });
152
+ return schemas;
153
+ }
154
+ async function generateZodSchemas(logger, schemaLookup, typesMap) {
155
+ const schemas = {};
156
+ const auxiliaryTypeStore = createAuxiliaryTypeStore();
157
+ const printer = ts.createPrinter();
158
+ const fakeSourceFile = ts.createSourceFile('zod-types.ts', '', ts.ScriptTarget.ESNext, false, ts.ScriptKind.TS);
159
+ for (const [schemaName, ref] of schemaLookup.entries()) {
160
+ if (ref.vendor && ref.vendor !== 'zod') {
161
+ throw new Error(`Schema '${schemaName}' uses ${ref.vendor} which is not yet supported for JSON Schema generation. ` +
162
+ `Currently only Zod schemas can be converted to JSON Schema. ` +
163
+ `Please use Zod or contribute support for ${ref.vendor}.`);
164
+ }
165
+ try {
166
+ const module = await tsImport(ref.sourceFile, import.meta.url);
167
+ const zodSchema = module[ref.variableName];
168
+ if (!zodSchema) {
169
+ logger.warn(`Could not find exported schema '${ref.variableName}' in ${ref.sourceFile} for ${schemaName}. Available exports: ${Object.keys(module).join(', ')}`);
170
+ continue;
171
+ }
172
+ const schema = z.toJSONSchema(zodSchema, {
173
+ unrepresentable: 'any',
174
+ override: ({ zodSchema, jsonSchema }) => {
175
+ if (zodSchema._zod?.def?.type === 'date') {
176
+ ;
177
+ jsonSchema.type = 'string';
178
+ jsonSchema.format = 'date-time';
179
+ }
180
+ },
181
+ });
182
+ if (schema.required && schema.properties) {
183
+ schema.required = schema.required.filter((fieldName) => {
184
+ const prop = schema.properties[fieldName];
185
+ return prop && prop.default === undefined;
186
+ });
187
+ if (schema.required.length === 0) {
188
+ delete schema.required;
189
+ }
190
+ }
191
+ schemas[schemaName] = schema;
192
+ const { node: tsType } = zodToTs(zodSchema, { auxiliaryTypeStore });
193
+ const typeText = printer.printNode(ts.EmitHint.Unspecified, tsType, fakeSourceFile);
194
+ typesMap.addCustomType(schemaName, typeText, []);
195
+ logger.debug(`• Generated schema from Zod: ${schemaName}`);
196
+ }
197
+ catch (e) {
198
+ logger.warn(`Could not convert Zod schema '${schemaName}': ${e instanceof Error ? e.message : e}`);
199
+ }
200
+ }
201
+ return schemas;
202
+ }
203
+ export async function generateAllSchemas(logger, config, state) {
204
+ const zodSchemas = await generateZodSchemas(logger, state.schemaLookup, state.functions.typesMap);
205
+ const requiredTypes = new Set();
206
+ const customTypesContent = generateCustomTypes(state.functions.typesMap, requiredTypes);
207
+ const tsSchemas = generateTSSchemas(logger, config.tsconfig, customTypesContent, state.functions.typesMap, state.functions.meta, state.http.meta, config.schemasFromTypes, config.schema?.additionalProperties, state.schemaLookup);
208
+ return { ...tsSchemas, ...zodSchemas };
209
+ }
@@ -1,4 +1,5 @@
1
- import { InspectorState } from '../types.js';
1
+ import { JSONValue } from '@pikku/core';
2
+ import { InspectorDiagnostic, InspectorState } from '../types.js';
2
3
  /**
3
4
  * Serializable version of InspectorState that can be saved to JSON
4
5
  * Omits typesLookup (contains non-serializable ts.Type objects) and converts Maps/Sets to arrays
@@ -74,6 +75,15 @@ export interface SerializableInspectorState {
74
75
  }[]
75
76
  ]>
76
77
  ]>;
78
+ schemaLookup: Array<[
79
+ string,
80
+ {
81
+ variableName: string;
82
+ sourceFile: string;
83
+ vendor?: 'zod' | 'valibot' | 'arktype' | 'effect' | 'unknown';
84
+ }
85
+ ]>;
86
+ schemas: Record<string, JSONValue>;
77
87
  functions: {
78
88
  typesMap: {
79
89
  map: Array<[string, {
@@ -115,6 +125,11 @@ export interface SerializableInspectorState {
115
125
  files: string[];
116
126
  meta: InspectorState['channels']['meta'];
117
127
  };
128
+ triggers: {
129
+ meta: InspectorState['triggers']['meta'];
130
+ sourceMeta: InspectorState['triggers']['sourceMeta'];
131
+ files: string[];
132
+ };
118
133
  scheduledTasks: {
119
134
  meta: InspectorState['scheduledTasks']['meta'];
120
135
  files: string[];
@@ -129,6 +144,12 @@ export interface SerializableInspectorState {
129
144
  path: string;
130
145
  exportedName: string;
131
146
  }]>;
147
+ graphMeta: InspectorState['workflows']['graphMeta'];
148
+ graphFiles: Array<[string, {
149
+ path: string;
150
+ exportedName: string;
151
+ }]>;
152
+ invokedWorkflows: string[];
132
153
  };
133
154
  rpc: {
134
155
  internalMeta: InspectorState['rpc']['internalMeta'];
@@ -142,6 +163,7 @@ export interface SerializableInspectorState {
142
163
  exportedName: string;
143
164
  }]>;
144
165
  invokedFunctions: string[];
166
+ usedExternalPackages: string[];
145
167
  };
146
168
  mcpEndpoints: {
147
169
  resourcesMeta: InspectorState['mcpEndpoints']['resourcesMeta'];
@@ -149,19 +171,52 @@ export interface SerializableInspectorState {
149
171
  promptsMeta: InspectorState['mcpEndpoints']['promptsMeta'];
150
172
  files: string[];
151
173
  };
174
+ agents: {
175
+ agentsMeta: InspectorState['agents']['agentsMeta'];
176
+ files: [string, {
177
+ path: string;
178
+ exportedName: string;
179
+ }][];
180
+ };
152
181
  cli: {
153
182
  meta: InspectorState['cli']['meta'];
154
183
  files: string[];
155
184
  };
185
+ nodes: {
186
+ meta: InspectorState['nodes']['meta'];
187
+ files: string[];
188
+ };
189
+ secrets: {
190
+ definitions: InspectorState['secrets']['definitions'];
191
+ files: string[];
192
+ };
193
+ variables: {
194
+ definitions: InspectorState['variables']['definitions'];
195
+ files: string[];
196
+ };
197
+ manifest: InspectorState['manifest'];
156
198
  middleware: {
157
- meta: InspectorState['middleware']['meta'];
199
+ definitions: InspectorState['middleware']['definitions'];
200
+ instances: InspectorState['middleware']['instances'];
158
201
  tagMiddleware: Array<[
159
202
  string,
160
203
  InspectorState['middleware']['tagMiddleware'] extends Map<string, infer V> ? V : never
161
204
  ]>;
162
205
  };
206
+ channelMiddleware: {
207
+ definitions: InspectorState['channelMiddleware']['definitions'];
208
+ instances: InspectorState['channelMiddleware']['instances'];
209
+ tagMiddleware: Array<[
210
+ string,
211
+ InspectorState['channelMiddleware']['tagMiddleware'] extends Map<string, infer V> ? V : never
212
+ ]>;
213
+ };
214
+ aiMiddleware: {
215
+ definitions: InspectorState['aiMiddleware']['definitions'];
216
+ };
163
217
  permissions: {
164
- meta: InspectorState['permissions']['meta'];
218
+ definitions: InspectorState['permissions']['definitions'];
219
+ instances: InspectorState['permissions']['instances'];
165
220
  tagPermissions: Array<[
166
221
  string,
167
222
  InspectorState['permissions']['tagPermissions'] extends Map<string, infer V> ? V : never
@@ -175,16 +230,15 @@ export interface SerializableInspectorState {
175
230
  allSingletonServices: string[];
176
231
  allWireServices: string[];
177
232
  };
178
- serviceMetadata: Array<{
179
- name: string;
180
- summary: string;
181
- description: string;
182
- package: string;
183
- path: string;
184
- version: string;
185
- interface: string;
186
- expandedProperties: Record<string, string>;
233
+ resolvedIOTypes: Record<string, {
234
+ inputType: string;
235
+ outputType: string;
187
236
  }>;
237
+ middlewareGroupsMeta: InspectorState['middlewareGroupsMeta'];
238
+ permissionsGroupsMeta: InspectorState['permissionsGroupsMeta'];
239
+ requiredSchemas: string[];
240
+ openAPISpec: Record<string, any> | null;
241
+ diagnostics: InspectorDiagnostic[];
188
242
  }
189
243
  /**
190
244
  * Serializes InspectorState to a JSON-compatible format
@@ -195,4 +249,10 @@ export declare function serializeInspectorState(state: InspectorState): Serializ
195
249
  * Deserializes JSON data back to InspectorState
196
250
  * Creates a partial state suitable for filtering/generation (without typesLookup)
197
251
  */
198
- export declare function deserializeInspectorState(data: SerializableInspectorState): Omit<InspectorState, 'typesLookup'>;
252
+ export declare function deserializeInspectorState(data: SerializableInspectorState): Omit<InspectorState, 'typesLookup' | 'schemaLookup'> & {
253
+ schemaLookup: Map<string, {
254
+ variableName: string;
255
+ sourceFile: string;
256
+ vendor?: 'zod' | 'valibot' | 'arktype' | 'effect' | 'unknown';
257
+ }>;
258
+ };
@@ -26,6 +26,8 @@ export function serializeInspectorState(state) {
26
26
  configFactories: Array.from(state.configFactories.entries()),
27
27
  filesAndMethods: state.filesAndMethods,
28
28
  filesAndMethodsErrors: Array.from(state.filesAndMethodsErrors.entries()).map(([key, mapValue]) => [key, Array.from(mapValue.entries())]),
29
+ schemaLookup: Array.from(state.schemaLookup.entries()),
30
+ schemas: state.schemas,
29
31
  functions: {
30
32
  typesMap: serializeTypesMap(state.functions.typesMap),
31
33
  meta: state.functions.meta,
@@ -42,6 +44,11 @@ export function serializeInspectorState(state) {
42
44
  files: Array.from(state.channels.files),
43
45
  meta: state.channels.meta,
44
46
  },
47
+ triggers: {
48
+ meta: state.triggers.meta,
49
+ sourceMeta: state.triggers.sourceMeta,
50
+ files: Array.from(state.triggers.files),
51
+ },
45
52
  scheduledTasks: {
46
53
  meta: state.scheduledTasks.meta,
47
54
  files: Array.from(state.scheduledTasks.files),
@@ -53,6 +60,9 @@ export function serializeInspectorState(state) {
53
60
  workflows: {
54
61
  meta: state.workflows.meta,
55
62
  files: Array.from(state.workflows.files.entries()),
63
+ graphMeta: state.workflows.graphMeta,
64
+ graphFiles: Array.from(state.workflows.graphFiles.entries()),
65
+ invokedWorkflows: Array.from(state.workflows.invokedWorkflows),
56
66
  },
57
67
  rpc: {
58
68
  internalMeta: state.rpc.internalMeta,
@@ -60,6 +70,7 @@ export function serializeInspectorState(state) {
60
70
  exposedMeta: state.rpc.exposedMeta,
61
71
  exposedFiles: Array.from(state.rpc.exposedFiles.entries()),
62
72
  invokedFunctions: Array.from(state.rpc.invokedFunctions),
73
+ usedExternalPackages: Array.from(state.rpc.usedExternalPackages),
63
74
  },
64
75
  mcpEndpoints: {
65
76
  resourcesMeta: state.mcpEndpoints.resourcesMeta,
@@ -67,16 +78,43 @@ export function serializeInspectorState(state) {
67
78
  promptsMeta: state.mcpEndpoints.promptsMeta,
68
79
  files: Array.from(state.mcpEndpoints.files),
69
80
  },
81
+ agents: {
82
+ agentsMeta: state.agents?.agentsMeta ?? {},
83
+ files: Array.from(state.agents?.files?.entries() ?? []),
84
+ },
70
85
  cli: {
71
86
  meta: state.cli.meta,
72
87
  files: Array.from(state.cli.files),
73
88
  },
89
+ nodes: {
90
+ meta: state.nodes.meta,
91
+ files: Array.from(state.nodes.files),
92
+ },
93
+ secrets: {
94
+ definitions: state.secrets.definitions,
95
+ files: Array.from(state.secrets.files),
96
+ },
97
+ variables: {
98
+ definitions: state.variables.definitions,
99
+ files: Array.from(state.variables.files),
100
+ },
101
+ manifest: state.manifest,
74
102
  middleware: {
75
- meta: state.middleware.meta,
103
+ definitions: state.middleware.definitions,
104
+ instances: state.middleware.instances,
76
105
  tagMiddleware: Array.from(state.middleware.tagMiddleware.entries()),
77
106
  },
107
+ channelMiddleware: {
108
+ definitions: state.channelMiddleware.definitions,
109
+ instances: state.channelMiddleware.instances,
110
+ tagMiddleware: Array.from(state.channelMiddleware.tagMiddleware.entries()),
111
+ },
112
+ aiMiddleware: {
113
+ definitions: state.aiMiddleware.definitions,
114
+ },
78
115
  permissions: {
79
- meta: state.permissions.meta,
116
+ definitions: state.permissions.definitions,
117
+ instances: state.permissions.instances,
80
118
  tagPermissions: Array.from(state.permissions.tagPermissions.entries()),
81
119
  },
82
120
  serviceAggregation: {
@@ -87,7 +125,12 @@ export function serializeInspectorState(state) {
87
125
  allSingletonServices: state.serviceAggregation.allSingletonServices,
88
126
  allWireServices: state.serviceAggregation.allWireServices,
89
127
  },
90
- serviceMetadata: state.serviceMetadata,
128
+ resolvedIOTypes: state.resolvedIOTypes,
129
+ middlewareGroupsMeta: state.middlewareGroupsMeta,
130
+ permissionsGroupsMeta: state.permissionsGroupsMeta,
131
+ requiredSchemas: Array.from(state.requiredSchemas),
132
+ openAPISpec: state.openAPISpec,
133
+ diagnostics: state.diagnostics,
91
134
  };
92
135
  }
93
136
  /**
@@ -118,6 +161,8 @@ export function deserializeInspectorState(data) {
118
161
  key,
119
162
  new Map(entries),
120
163
  ])),
164
+ schemaLookup: new Map(data.schemaLookup || []),
165
+ schemas: data.schemas || {},
121
166
  functions: {
122
167
  typesMap: deserializeTypesMap(data.functions.typesMap),
123
168
  meta: data.functions.meta,
@@ -134,6 +179,11 @@ export function deserializeInspectorState(data) {
134
179
  files: new Set(data.channels.files),
135
180
  meta: data.channels.meta,
136
181
  },
182
+ triggers: {
183
+ meta: data.triggers?.meta ?? {},
184
+ sourceMeta: data.triggers?.sourceMeta ?? {},
185
+ files: new Set(data.triggers?.files ?? []),
186
+ },
137
187
  scheduledTasks: {
138
188
  meta: data.scheduledTasks.meta,
139
189
  files: new Set(data.scheduledTasks.files),
@@ -145,6 +195,9 @@ export function deserializeInspectorState(data) {
145
195
  workflows: {
146
196
  meta: data.workflows.meta,
147
197
  files: new Map(data.workflows.files),
198
+ graphMeta: data.workflows.graphMeta || {},
199
+ graphFiles: new Map(data.workflows.graphFiles || []),
200
+ invokedWorkflows: new Set(data.workflows.invokedWorkflows || []),
148
201
  },
149
202
  rpc: {
150
203
  internalMeta: data.rpc.internalMeta,
@@ -152,6 +205,7 @@ export function deserializeInspectorState(data) {
152
205
  exposedMeta: data.rpc.exposedMeta,
153
206
  exposedFiles: new Map(data.rpc.exposedFiles),
154
207
  invokedFunctions: new Set(data.rpc.invokedFunctions),
208
+ usedExternalPackages: new Set(data.rpc.usedExternalPackages || []),
155
209
  },
156
210
  mcpEndpoints: {
157
211
  resourcesMeta: data.mcpEndpoints.resourcesMeta,
@@ -159,16 +213,43 @@ export function deserializeInspectorState(data) {
159
213
  promptsMeta: data.mcpEndpoints.promptsMeta,
160
214
  files: new Set(data.mcpEndpoints.files),
161
215
  },
216
+ agents: {
217
+ agentsMeta: data.agents?.agentsMeta || {},
218
+ files: new Map(data.agents?.files || []),
219
+ },
162
220
  cli: {
163
221
  meta: data.cli.meta,
164
222
  files: new Set(data.cli.files),
165
223
  },
224
+ nodes: {
225
+ meta: data.nodes?.meta || {},
226
+ files: new Set(data.nodes?.files || []),
227
+ },
228
+ secrets: {
229
+ definitions: data.secrets?.definitions || [],
230
+ files: new Set(data.secrets?.files || []),
231
+ },
232
+ variables: {
233
+ definitions: data.variables?.definitions || [],
234
+ files: new Set(data.variables?.files || []),
235
+ },
236
+ manifest: data.manifest || { initial: null, current: null, errors: [] },
166
237
  middleware: {
167
- meta: data.middleware.meta,
238
+ definitions: data.middleware.definitions,
239
+ instances: data.middleware.instances || {},
168
240
  tagMiddleware: new Map(data.middleware.tagMiddleware),
169
241
  },
242
+ channelMiddleware: {
243
+ definitions: data.channelMiddleware?.definitions || {},
244
+ instances: data.channelMiddleware?.instances || {},
245
+ tagMiddleware: new Map(data.channelMiddleware?.tagMiddleware || []),
246
+ },
247
+ aiMiddleware: {
248
+ definitions: data.aiMiddleware?.definitions || {},
249
+ },
170
250
  permissions: {
171
- meta: data.permissions.meta,
251
+ definitions: data.permissions.definitions,
252
+ instances: data.permissions.instances || {},
172
253
  tagPermissions: new Map(data.permissions.tagPermissions),
173
254
  },
174
255
  serviceAggregation: {
@@ -179,6 +260,21 @@ export function deserializeInspectorState(data) {
179
260
  allSingletonServices: data.serviceAggregation.allSingletonServices,
180
261
  allWireServices: data.serviceAggregation.allWireServices,
181
262
  },
182
- serviceMetadata: data.serviceMetadata || [],
263
+ resolvedIOTypes: data.resolvedIOTypes || {},
264
+ middlewareGroupsMeta: data.middlewareGroupsMeta || {
265
+ definitions: {},
266
+ instances: {},
267
+ httpGroups: {},
268
+ tagGroups: {},
269
+ channelMiddleware: { definitions: {}, instances: {}, tagGroups: {} },
270
+ },
271
+ permissionsGroupsMeta: data.permissionsGroupsMeta || {
272
+ definitions: {},
273
+ httpGroups: {},
274
+ tagGroups: {},
275
+ },
276
+ requiredSchemas: new Set(data.requiredSchemas || []),
277
+ openAPISpec: data.openAPISpec || null,
278
+ diagnostics: data.diagnostics || [],
183
279
  };
184
280
  }
@@ -0,0 +1,2 @@
1
+ import type { InspectorLogger, InspectorState } from '../types.js';
2
+ export declare const serializeMCPJson: (logger: InspectorLogger, state: InspectorState) => string;
@@ -0,0 +1,99 @@
1
+ export const serializeMCPJson = (logger, state) => {
2
+ const { mcpEndpoints, functions, schemas } = state;
3
+ const { meta: functionsMeta, typesMap } = functions;
4
+ const { resourcesMeta, toolsMeta, promptsMeta } = mcpEndpoints;
5
+ const tools = [];
6
+ const resources = [];
7
+ const prompts = [];
8
+ const loadSchema = (typeName) => {
9
+ if (!typeName ||
10
+ [
11
+ 'boolean',
12
+ 'string',
13
+ 'number',
14
+ 'null',
15
+ 'undefined',
16
+ 'void',
17
+ 'unknown',
18
+ 'never',
19
+ ].includes(typeName)) {
20
+ return undefined;
21
+ }
22
+ const uniqueName = typesMap.getUniqueName(typeName);
23
+ if (!uniqueName) {
24
+ return undefined;
25
+ }
26
+ const schema = schemas[uniqueName];
27
+ if (!schema) {
28
+ logger.warn(`Serialize MCP: Could not find schema for type: ${uniqueName}`);
29
+ return undefined;
30
+ }
31
+ return schema;
32
+ };
33
+ for (const [name, endpointMeta] of Object.entries(resourcesMeta)) {
34
+ const functionMeta = functionsMeta[endpointMeta.pikkuFuncId];
35
+ if (!functionMeta) {
36
+ logger.warn(`Function ${endpointMeta.pikkuFuncId} not found in functionsMeta. Skipping resource ${name}.`);
37
+ continue;
38
+ }
39
+ const inputType = functionMeta.inputs?.[0];
40
+ const outputType = functionMeta.outputs?.[0];
41
+ const parameters = loadSchema(inputType);
42
+ const returns = loadSchema(outputType);
43
+ resources.push({
44
+ uri: name,
45
+ name,
46
+ description: endpointMeta.description,
47
+ ...(parameters && { parameters }),
48
+ ...(returns && { returns }),
49
+ ...(endpointMeta.streaming && { streaming: true }),
50
+ });
51
+ }
52
+ for (const [name, endpointMeta] of Object.entries(toolsMeta)) {
53
+ const functionMeta = functionsMeta[endpointMeta.pikkuFuncId];
54
+ if (!functionMeta) {
55
+ logger.warn(`Function ${endpointMeta.pikkuFuncId} not found in functionsMeta. Skipping tool ${name}.`);
56
+ continue;
57
+ }
58
+ const inputType = functionMeta.inputs?.[0];
59
+ const outputType = functionMeta.outputs?.[0];
60
+ const parameters = loadSchema(inputType);
61
+ const returns = loadSchema(outputType);
62
+ tools.push({
63
+ name,
64
+ description: endpointMeta.description,
65
+ ...(parameters && { parameters }),
66
+ ...(returns && { returns }),
67
+ ...(endpointMeta.streaming && { streaming: true }),
68
+ });
69
+ }
70
+ for (const [name, endpointMeta] of Object.entries(promptsMeta)) {
71
+ const functionMeta = functionsMeta[endpointMeta.pikkuFuncId];
72
+ if (!functionMeta) {
73
+ logger.warn(`Function ${endpointMeta.pikkuFuncId} not found in functionsMeta. Skipping prompt ${name}.`);
74
+ continue;
75
+ }
76
+ const inputType = functionMeta.inputs?.[0];
77
+ const inputSchema = loadSchema(inputType);
78
+ const argumentsArray = [];
79
+ if (inputSchema &&
80
+ typeof inputSchema === 'object' &&
81
+ !(inputSchema instanceof Array)) {
82
+ const properties = inputSchema.properties;
83
+ const required = inputSchema.required || [];
84
+ for (const [propName, propSchema] of Object.entries(properties)) {
85
+ argumentsArray.push({
86
+ name: propName,
87
+ description: propSchema.description || `${propName} parameter`,
88
+ required: required.includes(propName),
89
+ });
90
+ }
91
+ }
92
+ prompts.push({
93
+ name,
94
+ description: endpointMeta.description,
95
+ arguments: argumentsArray,
96
+ });
97
+ }
98
+ return JSON.stringify({ tools, resources, prompts }, null, 2);
99
+ };
@@ -0,0 +1,12 @@
1
+ import type { InspectorState } from '../types.js';
2
+ export declare const serializeMiddlewareGroupsMeta: (state: InspectorState) => {
3
+ definitions: Record<string, import("../types.js").InspectorMiddlewareDefinition>;
4
+ instances: Record<string, import("../types.js").InspectorMiddlewareInstance>;
5
+ httpGroups: Record<string, any>;
6
+ tagGroups: Record<string, any>;
7
+ channelMiddleware: {
8
+ definitions: Record<string, import("../types.js").InspectorMiddlewareDefinition>;
9
+ instances: Record<string, import("../types.js").InspectorMiddlewareInstance>;
10
+ tagGroups: Record<string, any>;
11
+ };
12
+ };