@pikku/inspector 0.9.5 → 0.10.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 (133) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/add/add-channel.d.ts +17 -0
  3. package/dist/{add-channel.js → add/add-channel.js} +60 -34
  4. package/dist/add/add-cli.d.ts +9 -0
  5. package/dist/add/add-cli.js +566 -0
  6. package/dist/{add-file-extends-core-type.d.ts → add/add-file-extends-core-type.d.ts} +2 -2
  7. package/dist/{add-file-extends-core-type.js → add/add-file-extends-core-type.js} +17 -4
  8. package/dist/{add-file-with-config.d.ts → add/add-file-with-config.d.ts} +1 -1
  9. package/dist/{add-file-with-config.js → add/add-file-with-config.js} +1 -1
  10. package/dist/{add-file-with-factory.d.ts → add/add-file-with-factory.d.ts} +2 -2
  11. package/dist/{add-file-with-factory.js → add/add-file-with-factory.js} +38 -5
  12. package/dist/add/add-functions.d.ts +6 -0
  13. package/dist/{add-functions.js → add/add-functions.js} +77 -10
  14. package/dist/{add-http-route.d.ts → add/add-http-route.d.ts} +2 -3
  15. package/dist/{add-http-route.js → add/add-http-route.js} +26 -13
  16. package/dist/add/add-mcp-prompt.d.ts +2 -0
  17. package/dist/add/add-mcp-prompt.js +74 -0
  18. package/dist/add/add-mcp-resource.d.ts +2 -0
  19. package/dist/add/add-mcp-resource.js +84 -0
  20. package/dist/add/add-mcp-tool.d.ts +2 -0
  21. package/dist/add/add-mcp-tool.js +80 -0
  22. package/dist/add/add-middleware.d.ts +5 -0
  23. package/dist/add/add-middleware.js +290 -0
  24. package/dist/add/add-permission.d.ts +5 -0
  25. package/dist/add/add-permission.js +292 -0
  26. package/dist/add/add-queue-worker.d.ts +2 -0
  27. package/dist/add/add-queue-worker.js +52 -0
  28. package/dist/{add-rpc-invocations.d.ts → add/add-rpc-invocations.d.ts} +1 -1
  29. package/dist/add/add-schedule.d.ts +2 -0
  30. package/dist/{add-schedule.js → add/add-schedule.js} +16 -11
  31. package/dist/error-codes.d.ts +35 -0
  32. package/dist/error-codes.js +40 -0
  33. package/dist/index.d.ts +6 -0
  34. package/dist/index.js +4 -0
  35. package/dist/inspector.d.ts +2 -3
  36. package/dist/inspector.js +38 -8
  37. package/dist/types.d.ts +108 -1
  38. package/dist/utils/ensure-function-metadata.d.ts +6 -0
  39. package/dist/utils/ensure-function-metadata.js +18 -0
  40. package/dist/utils/extract-function-name.d.ts +31 -0
  41. package/dist/{utils.js → utils/extract-function-name.js} +35 -149
  42. package/dist/utils/extract-services.d.ts +6 -0
  43. package/dist/utils/extract-services.js +29 -0
  44. package/dist/utils/filter-inspector-state.d.ts +6 -0
  45. package/dist/utils/filter-inspector-state.js +382 -0
  46. package/dist/utils/filter-utils.d.ts +19 -0
  47. package/dist/utils/filter-utils.js +109 -0
  48. package/dist/utils/find-root-dir.d.ts +23 -0
  49. package/dist/utils/find-root-dir.js +55 -0
  50. package/dist/utils/get-files-and-methods.d.ts +22 -0
  51. package/dist/utils/get-files-and-methods.js +61 -0
  52. package/dist/utils/get-property-value.d.ts +12 -0
  53. package/dist/{get-property-value.js → utils/get-property-value.js} +20 -0
  54. package/dist/utils/middleware.d.ts +39 -0
  55. package/dist/utils/middleware.js +157 -0
  56. package/dist/utils/permissions.d.ts +43 -0
  57. package/dist/utils/permissions.js +178 -0
  58. package/dist/utils/post-process.d.ts +16 -0
  59. package/dist/utils/post-process.js +132 -0
  60. package/dist/utils/serialize-inspector-state.d.ts +179 -0
  61. package/dist/utils/serialize-inspector-state.js +170 -0
  62. package/dist/utils/type-utils.d.ts +3 -0
  63. package/dist/utils/type-utils.js +50 -0
  64. package/dist/visit.d.ts +3 -3
  65. package/dist/visit.js +35 -31
  66. package/package.json +5 -6
  67. package/src/{add-channel.ts → add/add-channel.ts} +108 -56
  68. package/src/add/add-cli.ts +822 -0
  69. package/src/{add-file-extends-core-type.ts → add/add-file-extends-core-type.ts} +23 -5
  70. package/src/{add-file-with-config.ts → add/add-file-with-config.ts} +2 -2
  71. package/src/{add-file-with-factory.ts → add/add-file-with-factory.ts} +49 -6
  72. package/src/{add-functions.ts → add/add-functions.ts} +89 -19
  73. package/src/{add-http-route.ts → add/add-http-route.ts} +66 -32
  74. package/src/add/add-mcp-prompt.ts +128 -0
  75. package/src/add/add-mcp-prompt.ts.tmp +0 -0
  76. package/src/add/add-mcp-resource.ts +145 -0
  77. package/src/add/add-mcp-resource.ts.tmp +0 -0
  78. package/src/add/add-mcp-tool.ts +137 -0
  79. package/src/add/add-middleware.ts +385 -0
  80. package/src/add/add-permission.ts +391 -0
  81. package/src/add/add-queue-worker.ts +92 -0
  82. package/src/{add-rpc-invocations.ts → add/add-rpc-invocations.ts} +1 -1
  83. package/src/{add-schedule.ts → add/add-schedule.ts} +30 -28
  84. package/src/error-codes.ts +43 -0
  85. package/src/index.ts +12 -0
  86. package/src/inspector.ts +41 -17
  87. package/src/types.ts +128 -1
  88. package/src/utils/ensure-function-metadata.ts +24 -0
  89. package/src/{utils.ts → utils/extract-function-name.ts} +44 -206
  90. package/src/utils/extract-services.ts +35 -0
  91. package/src/utils/filter-inspector-state.test.ts +1433 -0
  92. package/src/utils/filter-inspector-state.ts +526 -0
  93. package/src/{utils.test.ts → utils/filter-utils.test.ts} +351 -2
  94. package/src/utils/filter-utils.ts +152 -0
  95. package/src/utils/find-root-dir.ts +68 -0
  96. package/src/utils/get-files-and-methods.ts +151 -0
  97. package/src/{get-property-value.ts → utils/get-property-value.ts} +27 -0
  98. package/src/utils/middleware.ts +241 -0
  99. package/src/utils/permissions.test.ts +327 -0
  100. package/src/utils/permissions.ts +262 -0
  101. package/src/utils/post-process.ts +178 -0
  102. package/src/utils/serialize-inspector-state.ts +375 -0
  103. package/src/utils/test-data/inspector-state.json +1680 -0
  104. package/src/utils/type-utils.ts +74 -0
  105. package/src/visit.ts +50 -34
  106. package/tsconfig.tsbuildinfo +1 -1
  107. package/dist/add-channel.d.ts +0 -13
  108. package/dist/add-functions.d.ts +0 -7
  109. package/dist/add-mcp-prompt.d.ts +0 -3
  110. package/dist/add-mcp-prompt.js +0 -61
  111. package/dist/add-mcp-resource.d.ts +0 -3
  112. package/dist/add-mcp-resource.js +0 -68
  113. package/dist/add-mcp-tool.d.ts +0 -3
  114. package/dist/add-mcp-tool.js +0 -64
  115. package/dist/add-middleware.d.ts +0 -7
  116. package/dist/add-middleware.js +0 -35
  117. package/dist/add-permission.d.ts +0 -7
  118. package/dist/add-permission.js +0 -35
  119. package/dist/add-queue-worker.d.ts +0 -3
  120. package/dist/add-queue-worker.js +0 -48
  121. package/dist/add-schedule.d.ts +0 -3
  122. package/dist/get-property-value.d.ts +0 -3
  123. package/dist/utils.d.ts +0 -39
  124. package/src/add-mcp-prompt.ts +0 -104
  125. package/src/add-mcp-resource.ts +0 -116
  126. package/src/add-mcp-tool.ts +0 -107
  127. package/src/add-middleware.ts +0 -51
  128. package/src/add-permission.ts +0 -53
  129. package/src/add-queue-worker.ts +0 -92
  130. /package/dist/{add-rpc-invocations.js → add/add-rpc-invocations.js} +0 -0
  131. /package/dist/{does-type-extend-core-type.d.ts → utils/does-type-extend-core-type.d.ts} +0 -0
  132. /package/dist/{does-type-extend-core-type.js → utils/does-type-extend-core-type.js} +0 -0
  133. /package/src/{does-type-extend-core-type.ts → utils/does-type-extend-core-type.ts} +0 -0
@@ -1,3 +0,0 @@
1
- import * as ts from 'typescript';
2
- import { InspectorFilters, InspectorState, InspectorLogger } from './types.js';
3
- export declare const addMCPResource: (node: ts.Node, checker: ts.TypeChecker, state: InspectorState, filters: InspectorFilters, logger: InspectorLogger) => void;
@@ -1,68 +0,0 @@
1
- import * as ts from 'typescript';
2
- import { getPropertyValue } from './get-property-value.js';
3
- import { PikkuWiringTypes } from '@pikku/core';
4
- import { extractFunctionName, getPropertyAssignmentInitializer, matchesFilters, } from './utils.js';
5
- export const addMCPResource = (node, checker, state, filters, logger) => {
6
- if (!ts.isCallExpression(node)) {
7
- return;
8
- }
9
- const args = node.arguments;
10
- const firstArg = args[0];
11
- const expression = node.expression;
12
- // Check if the call is to wireMCPResource
13
- if (!ts.isIdentifier(expression) || expression.text !== 'wireMCPResource') {
14
- return;
15
- }
16
- if (!firstArg) {
17
- return;
18
- }
19
- if (ts.isObjectLiteralExpression(firstArg)) {
20
- const obj = firstArg;
21
- const uriValue = getPropertyValue(obj, 'uri');
22
- const titleValue = getPropertyValue(obj, 'title');
23
- const descriptionValue = getPropertyValue(obj, 'description');
24
- const streamingValue = getPropertyValue(obj, 'streaming');
25
- const tags = getPropertyValue(obj, 'tags') || undefined;
26
- const funcInitializer = getPropertyAssignmentInitializer(obj, 'func', true, checker);
27
- if (!funcInitializer) {
28
- console.error(`• No valid 'func' property for MCP resource '${uriValue}'.`);
29
- return;
30
- }
31
- const pikkuFuncName = extractFunctionName(funcInitializer, checker).pikkuFuncName;
32
- if (!uriValue) {
33
- console.error(`• MCP resource is missing the required 'uri' property.`);
34
- return;
35
- }
36
- if (!titleValue) {
37
- console.error(`• MCP resource '${uriValue}' is missing the required 'title' property.`);
38
- return;
39
- }
40
- if (!descriptionValue) {
41
- console.error(`• MCP resource '${uriValue}' is missing a description.`);
42
- return;
43
- }
44
- const filePath = node.getSourceFile().fileName;
45
- if (!matchesFilters(filters, { tags }, { type: PikkuWiringTypes.mcp, name: uriValue, filePath }, logger)) {
46
- return;
47
- }
48
- // lookup existing function metadata
49
- const fnMeta = state.functions.meta[pikkuFuncName];
50
- if (!fnMeta) {
51
- console.error(`• No function metadata found for '${pikkuFuncName}'.`);
52
- return;
53
- }
54
- const inputSchema = fnMeta.inputs?.[0] || null;
55
- const outputSchema = fnMeta.outputs?.[0] || null;
56
- state.mcpEndpoints.files.add(node.getSourceFile().fileName);
57
- state.mcpEndpoints.resourcesMeta[uriValue] = {
58
- pikkuFuncName,
59
- uri: uriValue,
60
- title: titleValue,
61
- description: descriptionValue,
62
- ...(streamingValue !== null && { streaming: streamingValue }),
63
- tags,
64
- inputSchema,
65
- outputSchema,
66
- };
67
- }
68
- };
@@ -1,3 +0,0 @@
1
- import * as ts from 'typescript';
2
- import { InspectorFilters, InspectorState, InspectorLogger } from './types.js';
3
- export declare const addMCPTool: (node: ts.Node, checker: ts.TypeChecker, state: InspectorState, filters: InspectorFilters, logger: InspectorLogger) => void;
@@ -1,64 +0,0 @@
1
- import * as ts from 'typescript';
2
- import { getPropertyValue } from './get-property-value.js';
3
- import { PikkuWiringTypes } from '@pikku/core';
4
- import { extractFunctionName, getPropertyAssignmentInitializer, matchesFilters, } from './utils.js';
5
- export const addMCPTool = (node, checker, state, filters, logger) => {
6
- if (!ts.isCallExpression(node)) {
7
- return;
8
- }
9
- const args = node.arguments;
10
- const firstArg = args[0];
11
- const expression = node.expression;
12
- // Check if the call is to wireMCPTool
13
- if (!ts.isIdentifier(expression) || expression.text !== 'wireMCPTool') {
14
- return;
15
- }
16
- if (!firstArg) {
17
- return;
18
- }
19
- if (ts.isObjectLiteralExpression(firstArg)) {
20
- const obj = firstArg;
21
- const nameValue = getPropertyValue(obj, 'name');
22
- const titleValue = getPropertyValue(obj, 'title');
23
- const descriptionValue = getPropertyValue(obj, 'description');
24
- const streamingValue = getPropertyValue(obj, 'streaming');
25
- const tags = getPropertyValue(obj, 'tags') || undefined;
26
- const funcInitializer = getPropertyAssignmentInitializer(obj, 'func', true, checker);
27
- if (!funcInitializer) {
28
- console.error(`• No valid 'func' property for MCP tool '${nameValue}'.`);
29
- return;
30
- }
31
- const pikkuFuncName = extractFunctionName(funcInitializer, checker).pikkuFuncName;
32
- if (!nameValue) {
33
- console.error(`• MCP tool is missing the required 'name' property.`);
34
- return;
35
- }
36
- if (!descriptionValue) {
37
- console.error(`• MCP tool '${nameValue}' is missing a description.`);
38
- return;
39
- }
40
- const filePath = node.getSourceFile().fileName;
41
- if (!matchesFilters(filters, { tags }, { type: PikkuWiringTypes.mcp, name: nameValue, filePath }, logger)) {
42
- return;
43
- }
44
- // lookup existing function metadata
45
- const fnMeta = state.functions.meta[pikkuFuncName];
46
- if (!fnMeta) {
47
- console.error(`• No function metadata found for '${pikkuFuncName}'.`);
48
- return;
49
- }
50
- const inputSchema = fnMeta.inputs?.[0] || null;
51
- const outputSchema = fnMeta.outputs?.[0] || null;
52
- state.mcpEndpoints.files.add(node.getSourceFile().fileName);
53
- state.mcpEndpoints.toolsMeta[nameValue] = {
54
- pikkuFuncName,
55
- name: nameValue,
56
- title: titleValue || undefined,
57
- description: descriptionValue,
58
- ...(streamingValue !== null && { streaming: streamingValue }),
59
- tags,
60
- inputSchema,
61
- outputSchema,
62
- };
63
- }
64
- };
@@ -1,7 +0,0 @@
1
- import * as ts from 'typescript';
2
- import { InspectorLogger, InspectorState } from './types.js';
3
- /**
4
- * Inspect pikkuMiddleware calls and extract first-arg destructuring
5
- * for tree shaking optimization.
6
- */
7
- export declare function addMiddleware(node: ts.Node, checker: ts.TypeChecker, state: InspectorState, logger: InspectorLogger): void;
@@ -1,35 +0,0 @@
1
- import * as ts from 'typescript';
2
- import { extractFunctionName, extractServicesFromFunction } from './utils.js';
3
- /**
4
- * Inspect pikkuMiddleware calls and extract first-arg destructuring
5
- * for tree shaking optimization.
6
- */
7
- export function addMiddleware(node, checker, state, logger) {
8
- if (!ts.isCallExpression(node))
9
- return;
10
- const { expression, arguments: args } = node;
11
- // only handle calls like pikkuMiddleware(...)
12
- if (!ts.isIdentifier(expression)) {
13
- return;
14
- }
15
- if (expression.text !== 'pikkuMiddleware') {
16
- return;
17
- }
18
- const handlerNode = args[0];
19
- if (!handlerNode)
20
- return;
21
- if (!ts.isArrowFunction(handlerNode) &&
22
- !ts.isFunctionExpression(handlerNode)) {
23
- logger.error(`• Handler for pikkuMiddleware is not a function.`);
24
- return;
25
- }
26
- const services = extractServicesFromFunction(handlerNode);
27
- const { pikkuFuncName, exportedName } = extractFunctionName(node, checker);
28
- state.middleware.meta[pikkuFuncName] = {
29
- services,
30
- sourceFile: node.getSourceFile().fileName,
31
- position: node.getStart(),
32
- exportedName,
33
- };
34
- logger.debug(`• Found middleware with services: ${services.services.join(', ')}`);
35
- }
@@ -1,7 +0,0 @@
1
- import * as ts from 'typescript';
2
- import { InspectorLogger, InspectorState } from './types.js';
3
- /**
4
- * Inspect pikkuPermission calls and extract first-arg destructuring
5
- * for tree shaking optimization.
6
- */
7
- export declare function addPermission(node: ts.Node, checker: ts.TypeChecker, state: InspectorState, logger: InspectorLogger): void;
@@ -1,35 +0,0 @@
1
- import * as ts from 'typescript';
2
- import { extractFunctionName, extractServicesFromFunction } from './utils.js';
3
- /**
4
- * Inspect pikkuPermission calls and extract first-arg destructuring
5
- * for tree shaking optimization.
6
- */
7
- export function addPermission(node, checker, state, logger) {
8
- if (!ts.isCallExpression(node))
9
- return;
10
- const { expression, arguments: args } = node;
11
- // only handle calls like pikkuPermission(...)
12
- if (!ts.isIdentifier(expression)) {
13
- return;
14
- }
15
- if (expression.text !== 'pikkuPermission') {
16
- return;
17
- }
18
- const handlerNode = args[0];
19
- if (!handlerNode)
20
- return;
21
- if (!ts.isArrowFunction(handlerNode) &&
22
- !ts.isFunctionExpression(handlerNode)) {
23
- logger.error(`• Handler for pikkuPermission is not a function.`);
24
- return;
25
- }
26
- const services = extractServicesFromFunction(handlerNode);
27
- const { pikkuFuncName, exportedName } = extractFunctionName(node, checker);
28
- state.permissions.meta[pikkuFuncName] = {
29
- services,
30
- sourceFile: node.getSourceFile().fileName,
31
- position: node.getStart(),
32
- exportedName,
33
- };
34
- logger.debug(`• Found permission with services: ${services.services.join(', ')}`);
35
- }
@@ -1,3 +0,0 @@
1
- import * as ts from 'typescript';
2
- import { InspectorFilters, InspectorState, InspectorLogger } from './types.js';
3
- export declare const addQueueWorker: (node: ts.Node, checker: ts.TypeChecker, state: InspectorState, filters: InspectorFilters, logger: InspectorLogger) => void;
@@ -1,48 +0,0 @@
1
- import * as ts from 'typescript';
2
- import { getPropertyValue } from './get-property-value.js';
3
- import { PikkuWiringTypes } from '@pikku/core';
4
- import { extractFunctionName, getPropertyAssignmentInitializer, matchesFilters, } from './utils.js';
5
- export const addQueueWorker = (node, checker, state, filters, logger) => {
6
- if (!ts.isCallExpression(node)) {
7
- return;
8
- }
9
- const args = node.arguments;
10
- const firstArg = args[0];
11
- const expression = node.expression;
12
- // Check if the call is to addQueueWorker
13
- if (!ts.isIdentifier(expression) || expression.text !== 'wireQueueWorker') {
14
- return;
15
- }
16
- if (!firstArg) {
17
- return;
18
- }
19
- if (ts.isObjectLiteralExpression(firstArg)) {
20
- const obj = firstArg;
21
- const queueName = getPropertyValue(obj, 'queueName');
22
- const docs = getPropertyValue(obj, 'docs') || undefined;
23
- const tags = getPropertyValue(obj, 'tags') || undefined;
24
- // --- find the referenced function ---
25
- const funcInitializer = getPropertyAssignmentInitializer(obj, 'func', true, checker);
26
- if (!funcInitializer) {
27
- console.error(`• No valid 'func' property for queue processor '${queueName}'.`);
28
- return;
29
- }
30
- const pikkuFuncName = extractFunctionName(funcInitializer, checker).pikkuFuncName;
31
- if (!queueName) {
32
- console.error(`• No 'queueName' provided for queue processor function '${pikkuFuncName}'.`);
33
- return;
34
- }
35
- const filePath = node.getSourceFile().fileName;
36
- if (!matchesFilters(filters, { tags }, { type: PikkuWiringTypes.queue, name: queueName, filePath }, logger)) {
37
- console.info(`• Skipping queue processor '${pikkuFuncName}' for queue '${queueName}' due to filter mismatch.`);
38
- return;
39
- }
40
- state.queueWorkers.files.add(node.getSourceFile().fileName);
41
- state.queueWorkers.meta[queueName] = {
42
- pikkuFuncName,
43
- queueName,
44
- docs,
45
- tags,
46
- };
47
- }
48
- };
@@ -1,3 +0,0 @@
1
- import * as ts from 'typescript';
2
- import { InspectorFilters, InspectorState, InspectorLogger } from './types.js';
3
- export declare const addSchedule: (node: ts.Node, checker: ts.TypeChecker, state: InspectorState, filters: InspectorFilters, logger: InspectorLogger) => void;
@@ -1,3 +0,0 @@
1
- import { PikkuDocs } from '@pikku/core';
2
- import * as ts from 'typescript';
3
- export declare const getPropertyValue: (obj: ts.ObjectLiteralExpression, propertyName: string) => string | string[] | null | PikkuDocs | boolean;
package/dist/utils.d.ts DELETED
@@ -1,39 +0,0 @@
1
- import * as ts from 'typescript';
2
- import { InspectorFilters, InspectorLogger } from './types.js';
3
- import { PikkuWiringTypes, FunctionServicesMeta } from '@pikku/core';
4
- type ExtractedFunctionName = {
5
- pikkuFuncName: string;
6
- name: string;
7
- explicitName: string | null;
8
- exportedName: string | null;
9
- localName: string | null;
10
- propertyName: string | null;
11
- };
12
- /**
13
- * Generate a deterministic "anonymous" name for any expression node,
14
- * but if it's an Identifier pointing to a function, resolve it back
15
- * to the function's declaration (so you get the true source location).
16
- */
17
- export declare function makeDeterministicAnonName(start: ts.Node, checker: ts.TypeChecker): string;
18
- /**
19
- * Updated function to extract and prioritize function names correctly
20
- * This function follows the priority:
21
- * 1. Object with a name property
22
- * 2. Exported name
23
- * 3. Fallback to deterministic name
24
- */
25
- export declare function extractFunctionName(callExpr: ts.Node, checker: ts.TypeChecker): ExtractedFunctionName;
26
- export declare const extractTypeKeys: (type: ts.Type) => string[];
27
- export declare function getPropertyAssignmentInitializer(obj: ts.ObjectLiteralExpression, propName: string, followShorthand?: boolean, checker?: ts.TypeChecker): ts.Expression | undefined;
28
- export declare const matchesFilters: (filters: InspectorFilters, params: {
29
- tags?: string[];
30
- }, meta: {
31
- type: PikkuWiringTypes;
32
- name: string;
33
- filePath?: string;
34
- }, logger: InspectorLogger) => boolean;
35
- /**
36
- * Extract services from a function's first parameter destructuring pattern
37
- */
38
- export declare function extractServicesFromFunction(handlerNode: ts.FunctionExpression | ts.ArrowFunction): FunctionServicesMeta;
39
- export {};
@@ -1,104 +0,0 @@
1
- import * as ts from 'typescript'
2
- import { getPropertyValue } from './get-property-value.js'
3
- import { PikkuWiringTypes } from '@pikku/core'
4
- import { InspectorFilters, InspectorState, InspectorLogger } from './types.js'
5
- import {
6
- extractFunctionName,
7
- getPropertyAssignmentInitializer,
8
- matchesFilters,
9
- } from './utils.js'
10
-
11
- export const addMCPPrompt = (
12
- node: ts.Node,
13
- checker: ts.TypeChecker,
14
- state: InspectorState,
15
- filters: InspectorFilters,
16
- logger: InspectorLogger
17
- ) => {
18
- if (!ts.isCallExpression(node)) {
19
- return
20
- }
21
-
22
- const args = node.arguments
23
- const firstArg = args[0]
24
- const expression = node.expression
25
-
26
- // Check if the call is to wireMCPPrompt
27
- if (!ts.isIdentifier(expression) || expression.text !== 'wireMCPPrompt') {
28
- return
29
- }
30
-
31
- if (!firstArg) {
32
- return
33
- }
34
-
35
- if (ts.isObjectLiteralExpression(firstArg)) {
36
- const obj = firstArg
37
-
38
- const nameValue = getPropertyValue(obj, 'name') as string | null
39
- const descriptionValue = getPropertyValue(obj, 'description') as
40
- | string
41
- | null
42
- const tags = (getPropertyValue(obj, 'tags') as string[]) || undefined
43
-
44
- const funcInitializer = getPropertyAssignmentInitializer(
45
- obj,
46
- 'func',
47
- true,
48
- checker
49
- )
50
- if (!funcInitializer) {
51
- console.error(`• No valid 'func' property for MCP prompt '${nameValue}'.`)
52
- return
53
- }
54
-
55
- const pikkuFuncName = extractFunctionName(
56
- funcInitializer,
57
- checker
58
- ).pikkuFuncName
59
-
60
- if (!nameValue) {
61
- console.error(`• MCP prompt is missing the required 'name' property.`)
62
- return
63
- }
64
-
65
- if (!descriptionValue) {
66
- console.error(`• MCP prompt '${nameValue}' is missing a description.`)
67
- return
68
- }
69
-
70
- const filePath = node.getSourceFile().fileName
71
-
72
- if (
73
- !matchesFilters(
74
- filters,
75
- { tags },
76
- { type: PikkuWiringTypes.mcp, name: nameValue, filePath },
77
- logger
78
- )
79
- ) {
80
- return
81
- }
82
-
83
- // lookup existing function metadata
84
- const fnMeta = state.functions.meta[pikkuFuncName]
85
- if (!fnMeta) {
86
- console.error(`• No function metadata found for '${pikkuFuncName}'.`)
87
- return
88
- }
89
- const inputSchema = fnMeta.inputs?.[0] || null
90
- const outputSchema = fnMeta.outputs?.[0] || null
91
-
92
- state.mcpEndpoints.files.add(node.getSourceFile().fileName)
93
-
94
- state.mcpEndpoints.promptsMeta[nameValue] = {
95
- pikkuFuncName,
96
- name: nameValue,
97
- description: descriptionValue,
98
- tags,
99
- inputSchema,
100
- outputSchema,
101
- arguments: [], // Will be populated by CLI during serialization
102
- }
103
- }
104
- }
@@ -1,116 +0,0 @@
1
- import * as ts from 'typescript'
2
- import { getPropertyValue } from './get-property-value.js'
3
- import { PikkuWiringTypes } from '@pikku/core'
4
- import { InspectorFilters, InspectorState, InspectorLogger } from './types.js'
5
- import {
6
- extractFunctionName,
7
- getPropertyAssignmentInitializer,
8
- matchesFilters,
9
- } from './utils.js'
10
-
11
- export const addMCPResource = (
12
- node: ts.Node,
13
- checker: ts.TypeChecker,
14
- state: InspectorState,
15
- filters: InspectorFilters,
16
- logger: InspectorLogger
17
- ) => {
18
- if (!ts.isCallExpression(node)) {
19
- return
20
- }
21
-
22
- const args = node.arguments
23
- const firstArg = args[0]
24
- const expression = node.expression
25
-
26
- // Check if the call is to wireMCPResource
27
- if (!ts.isIdentifier(expression) || expression.text !== 'wireMCPResource') {
28
- return
29
- }
30
-
31
- if (!firstArg) {
32
- return
33
- }
34
-
35
- if (ts.isObjectLiteralExpression(firstArg)) {
36
- const obj = firstArg
37
-
38
- const uriValue = getPropertyValue(obj, 'uri') as string | null
39
- const titleValue = getPropertyValue(obj, 'title') as string | null
40
- const descriptionValue = getPropertyValue(obj, 'description') as
41
- | string
42
- | null
43
- const streamingValue = getPropertyValue(obj, 'streaming') as boolean | null
44
- const tags = (getPropertyValue(obj, 'tags') as string[]) || undefined
45
-
46
- const funcInitializer = getPropertyAssignmentInitializer(
47
- obj,
48
- 'func',
49
- true,
50
- checker
51
- )
52
- if (!funcInitializer) {
53
- console.error(
54
- `• No valid 'func' property for MCP resource '${uriValue}'.`
55
- )
56
- return
57
- }
58
-
59
- const pikkuFuncName = extractFunctionName(
60
- funcInitializer,
61
- checker
62
- ).pikkuFuncName
63
-
64
- if (!uriValue) {
65
- console.error(`• MCP resource is missing the required 'uri' property.`)
66
- return
67
- }
68
-
69
- if (!titleValue) {
70
- console.error(
71
- `• MCP resource '${uriValue}' is missing the required 'title' property.`
72
- )
73
- return
74
- }
75
-
76
- if (!descriptionValue) {
77
- console.error(`• MCP resource '${uriValue}' is missing a description.`)
78
- return
79
- }
80
-
81
- const filePath = node.getSourceFile().fileName
82
-
83
- if (
84
- !matchesFilters(
85
- filters,
86
- { tags },
87
- { type: PikkuWiringTypes.mcp, name: uriValue, filePath },
88
- logger
89
- )
90
- ) {
91
- return
92
- }
93
-
94
- // lookup existing function metadata
95
- const fnMeta = state.functions.meta[pikkuFuncName]
96
- if (!fnMeta) {
97
- console.error(`• No function metadata found for '${pikkuFuncName}'.`)
98
- return
99
- }
100
- const inputSchema = fnMeta.inputs?.[0] || null
101
- const outputSchema = fnMeta.outputs?.[0] || null
102
-
103
- state.mcpEndpoints.files.add(node.getSourceFile().fileName)
104
-
105
- state.mcpEndpoints.resourcesMeta[uriValue] = {
106
- pikkuFuncName,
107
- uri: uriValue,
108
- title: titleValue,
109
- description: descriptionValue,
110
- ...(streamingValue !== null && { streaming: streamingValue }),
111
- tags,
112
- inputSchema,
113
- outputSchema,
114
- }
115
- }
116
- }
@@ -1,107 +0,0 @@
1
- import * as ts from 'typescript'
2
- import { getPropertyValue } from './get-property-value.js'
3
- import { PikkuWiringTypes } from '@pikku/core'
4
- import { InspectorFilters, InspectorState, InspectorLogger } from './types.js'
5
- import {
6
- extractFunctionName,
7
- getPropertyAssignmentInitializer,
8
- matchesFilters,
9
- } from './utils.js'
10
-
11
- export const addMCPTool = (
12
- node: ts.Node,
13
- checker: ts.TypeChecker,
14
- state: InspectorState,
15
- filters: InspectorFilters,
16
- logger: InspectorLogger
17
- ) => {
18
- if (!ts.isCallExpression(node)) {
19
- return
20
- }
21
-
22
- const args = node.arguments
23
- const firstArg = args[0]
24
- const expression = node.expression
25
-
26
- // Check if the call is to wireMCPTool
27
- if (!ts.isIdentifier(expression) || expression.text !== 'wireMCPTool') {
28
- return
29
- }
30
-
31
- if (!firstArg) {
32
- return
33
- }
34
-
35
- if (ts.isObjectLiteralExpression(firstArg)) {
36
- const obj = firstArg
37
-
38
- const nameValue = getPropertyValue(obj, 'name') as string | null
39
- const titleValue = getPropertyValue(obj, 'title') as string | null
40
- const descriptionValue = getPropertyValue(obj, 'description') as
41
- | string
42
- | null
43
- const streamingValue = getPropertyValue(obj, 'streaming') as boolean | null
44
- const tags = (getPropertyValue(obj, 'tags') as string[]) || undefined
45
-
46
- const funcInitializer = getPropertyAssignmentInitializer(
47
- obj,
48
- 'func',
49
- true,
50
- checker
51
- )
52
- if (!funcInitializer) {
53
- console.error(`• No valid 'func' property for MCP tool '${nameValue}'.`)
54
- return
55
- }
56
-
57
- const pikkuFuncName = extractFunctionName(
58
- funcInitializer,
59
- checker
60
- ).pikkuFuncName
61
-
62
- if (!nameValue) {
63
- console.error(`• MCP tool is missing the required 'name' property.`)
64
- return
65
- }
66
-
67
- if (!descriptionValue) {
68
- console.error(`• MCP tool '${nameValue}' is missing a description.`)
69
- return
70
- }
71
-
72
- const filePath = node.getSourceFile().fileName
73
-
74
- if (
75
- !matchesFilters(
76
- filters,
77
- { tags },
78
- { type: PikkuWiringTypes.mcp, name: nameValue, filePath },
79
- logger
80
- )
81
- ) {
82
- return
83
- }
84
-
85
- // lookup existing function metadata
86
- const fnMeta = state.functions.meta[pikkuFuncName]
87
- if (!fnMeta) {
88
- console.error(`• No function metadata found for '${pikkuFuncName}'.`)
89
- return
90
- }
91
- const inputSchema = fnMeta.inputs?.[0] || null
92
- const outputSchema = fnMeta.outputs?.[0] || null
93
-
94
- state.mcpEndpoints.files.add(node.getSourceFile().fileName)
95
-
96
- state.mcpEndpoints.toolsMeta[nameValue] = {
97
- pikkuFuncName,
98
- name: nameValue,
99
- title: titleValue || undefined,
100
- description: descriptionValue,
101
- ...(streamingValue !== null && { streaming: streamingValue }),
102
- tags,
103
- inputSchema,
104
- outputSchema,
105
- }
106
- }
107
- }