@jaypie/mcp 0.7.9 → 0.7.11
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/dist/suites/aws/aws.d.ts +10 -0
- package/dist/suites/aws/aws.js +42 -1
- package/dist/suites/aws/aws.js.map +1 -1
- package/dist/suites/aws/help.md +52 -7
- package/dist/suites/aws/index.d.ts +2 -36
- package/dist/suites/aws/index.js +146 -7
- package/dist/suites/aws/index.js.map +1 -1
- package/dist/suites/datadog/datadog.d.ts +15 -0
- package/dist/suites/datadog/datadog.js +25 -1
- package/dist/suites/datadog/datadog.js.map +1 -1
- package/dist/suites/datadog/help.md +37 -5
- package/dist/suites/datadog/index.d.ts +1 -23
- package/dist/suites/datadog/index.js +139 -43
- package/dist/suites/datadog/index.js.map +1 -1
- package/dist/suites/docs/index.js +60 -4
- package/dist/suites/docs/index.js.map +1 -1
- package/dist/suites/llm/help.md +21 -3
- package/dist/suites/llm/index.d.ts +1 -10
- package/dist/suites/llm/index.js +21 -7
- package/dist/suites/llm/index.js.map +1 -1
- package/dist/suites/llm/llm.d.ts +18 -0
- package/dist/suites/llm/llm.js +28 -1
- package/dist/suites/llm/llm.js.map +1 -1
- package/package.json +1 -1
- package/release-notes/mcp/0.7.10.md +45 -0
- package/release-notes/mcp/0.7.11.md +12 -0
- package/skills/tools-aws.md +65 -23
- package/skills/tools-datadog.md +71 -39
- package/skills/tools-dynamodb.md +27 -16
- package/skills/tools-llm.md +30 -21
|
@@ -2,7 +2,7 @@ import { fabricService } from '@jaypie/fabric';
|
|
|
2
2
|
import * as fs from 'node:fs/promises';
|
|
3
3
|
import * as path from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
|
-
import { getDatadogCredentials, searchDatadogRum, queryDatadogMetrics, getDatadogSyntheticResults, listDatadogSynthetics, listDatadogMonitors, aggregateDatadogLogs, searchDatadogLogs } from './datadog.js';
|
|
5
|
+
import { getDatadogCredentials, searchDatadogRum, queryDatadogMetrics, getDatadogSyntheticResults, listDatadogSynthetics, listDatadogMonitors, aggregateDatadogLogs, searchDatadogLogs, validateDatadogSetup } from './datadog.js';
|
|
6
6
|
export { buildDatadogQuery, validateDatadogCredentials } from './datadog.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -21,18 +21,99 @@ const datadogService = fabricService({
|
|
|
21
21
|
alias: "datadog",
|
|
22
22
|
description: "Access Datadog observability data. Commands: logs, log_analytics, monitors, synthetics, metrics, rum. Call with no args for help.",
|
|
23
23
|
input: {
|
|
24
|
+
aggregation: {
|
|
25
|
+
description: "Aggregation type for log_analytics (count, avg, sum, min, max, cardinality)",
|
|
26
|
+
required: false,
|
|
27
|
+
type: String,
|
|
28
|
+
},
|
|
24
29
|
command: {
|
|
25
|
-
description: "Command to execute (omit for help)",
|
|
30
|
+
description: "Command to execute: logs, log_analytics, monitors, synthetics, metrics, rum (omit for help)",
|
|
26
31
|
required: false,
|
|
27
32
|
type: String,
|
|
28
33
|
},
|
|
29
|
-
|
|
30
|
-
description: "
|
|
34
|
+
env: {
|
|
35
|
+
description: "Environment filter (e.g., production, staging)",
|
|
31
36
|
required: false,
|
|
32
|
-
type:
|
|
37
|
+
type: String,
|
|
38
|
+
},
|
|
39
|
+
from: {
|
|
40
|
+
description: "Start time (e.g., now-1h, now-15m, now-1d, or ISO 8601 timestamp)",
|
|
41
|
+
required: false,
|
|
42
|
+
type: String,
|
|
43
|
+
},
|
|
44
|
+
groupBy: {
|
|
45
|
+
description: "Fields to group by for log_analytics (comma-separated, e.g., service,status)",
|
|
46
|
+
required: false,
|
|
47
|
+
type: String,
|
|
48
|
+
},
|
|
49
|
+
limit: {
|
|
50
|
+
description: "Maximum number of results to return",
|
|
51
|
+
required: false,
|
|
52
|
+
type: Number,
|
|
53
|
+
},
|
|
54
|
+
metric: {
|
|
55
|
+
description: "Metric field for aggregation (e.g., @duration)",
|
|
56
|
+
required: false,
|
|
57
|
+
type: String,
|
|
58
|
+
},
|
|
59
|
+
monitorTags: {
|
|
60
|
+
description: "Monitor tags filter (comma-separated)",
|
|
61
|
+
required: false,
|
|
62
|
+
type: String,
|
|
63
|
+
},
|
|
64
|
+
name: {
|
|
65
|
+
description: "Name filter for monitors",
|
|
66
|
+
required: false,
|
|
67
|
+
type: String,
|
|
68
|
+
},
|
|
69
|
+
query: {
|
|
70
|
+
description: 'Datadog query string (e.g., status:error, @lambda.arn:"arn:aws:...")',
|
|
71
|
+
required: false,
|
|
72
|
+
type: String,
|
|
73
|
+
},
|
|
74
|
+
service: {
|
|
75
|
+
description: "Service name filter",
|
|
76
|
+
required: false,
|
|
77
|
+
type: String,
|
|
78
|
+
},
|
|
79
|
+
sort: {
|
|
80
|
+
description: "Sort order (timestamp or -timestamp)",
|
|
81
|
+
required: false,
|
|
82
|
+
type: String,
|
|
83
|
+
},
|
|
84
|
+
source: {
|
|
85
|
+
description: "Log source filter (default: lambda)",
|
|
86
|
+
required: false,
|
|
87
|
+
type: String,
|
|
88
|
+
},
|
|
89
|
+
status: {
|
|
90
|
+
description: "Monitor status filter (comma-separated: Alert, Warn, No Data, OK)",
|
|
91
|
+
required: false,
|
|
92
|
+
type: String,
|
|
93
|
+
},
|
|
94
|
+
tags: {
|
|
95
|
+
description: "Tags filter (comma-separated)",
|
|
96
|
+
required: false,
|
|
97
|
+
type: String,
|
|
98
|
+
},
|
|
99
|
+
testId: {
|
|
100
|
+
description: "Synthetic test ID for getting results",
|
|
101
|
+
required: false,
|
|
102
|
+
type: String,
|
|
103
|
+
},
|
|
104
|
+
to: {
|
|
105
|
+
description: "End time (e.g., now, or ISO 8601 timestamp)",
|
|
106
|
+
required: false,
|
|
107
|
+
type: String,
|
|
108
|
+
},
|
|
109
|
+
type: {
|
|
110
|
+
description: "Synthetic test type filter (api or browser)",
|
|
111
|
+
required: false,
|
|
112
|
+
type: String,
|
|
33
113
|
},
|
|
34
114
|
},
|
|
35
|
-
service: async (
|
|
115
|
+
service: async (params) => {
|
|
116
|
+
const { command } = params;
|
|
36
117
|
if (!command || command === "help") {
|
|
37
118
|
return getHelp();
|
|
38
119
|
}
|
|
@@ -40,75 +121,90 @@ const datadogService = fabricService({
|
|
|
40
121
|
if (!credentials) {
|
|
41
122
|
throw new Error("Datadog credentials not found. Set DATADOG_API_KEY and DATADOG_APP_KEY.");
|
|
42
123
|
}
|
|
43
|
-
|
|
124
|
+
// Helper to parse comma-separated strings into arrays
|
|
125
|
+
const parseArray = (value) => {
|
|
126
|
+
if (!value)
|
|
127
|
+
return undefined;
|
|
128
|
+
return value.split(",").map((s) => s.trim());
|
|
129
|
+
};
|
|
44
130
|
switch (command) {
|
|
131
|
+
case "validate": {
|
|
132
|
+
return validateDatadogSetup();
|
|
133
|
+
}
|
|
45
134
|
case "logs": {
|
|
46
135
|
const result = await searchDatadogLogs(credentials, {
|
|
47
|
-
env:
|
|
48
|
-
from:
|
|
49
|
-
limit:
|
|
50
|
-
query:
|
|
51
|
-
service:
|
|
52
|
-
sort:
|
|
53
|
-
source:
|
|
54
|
-
to:
|
|
136
|
+
env: params.env,
|
|
137
|
+
from: params.from,
|
|
138
|
+
limit: params.limit,
|
|
139
|
+
query: params.query,
|
|
140
|
+
service: params.service,
|
|
141
|
+
sort: params.sort,
|
|
142
|
+
source: params.source,
|
|
143
|
+
to: params.to,
|
|
55
144
|
}, log);
|
|
56
145
|
if (!result.success)
|
|
57
146
|
throw new Error(result.error);
|
|
58
147
|
return result;
|
|
59
148
|
}
|
|
60
149
|
case "log_analytics": {
|
|
61
|
-
|
|
62
|
-
|
|
150
|
+
const groupByArray = parseArray(params.groupBy);
|
|
151
|
+
if (!groupByArray || groupByArray.length === 0) {
|
|
152
|
+
throw new Error("groupBy is required (comma-separated field names, e.g., service,status)");
|
|
63
153
|
}
|
|
64
|
-
const compute =
|
|
65
|
-
? [
|
|
154
|
+
const compute = params.aggregation
|
|
155
|
+
? [
|
|
156
|
+
{
|
|
157
|
+
aggregation: params.aggregation,
|
|
158
|
+
metric: params.metric,
|
|
159
|
+
},
|
|
160
|
+
]
|
|
66
161
|
: [{ aggregation: "count" }];
|
|
67
162
|
const result = await aggregateDatadogLogs(credentials, {
|
|
68
163
|
compute,
|
|
69
|
-
env:
|
|
70
|
-
from:
|
|
71
|
-
groupBy:
|
|
72
|
-
query:
|
|
73
|
-
service:
|
|
74
|
-
source:
|
|
75
|
-
to:
|
|
164
|
+
env: params.env,
|
|
165
|
+
from: params.from,
|
|
166
|
+
groupBy: groupByArray,
|
|
167
|
+
query: params.query,
|
|
168
|
+
service: params.service,
|
|
169
|
+
source: params.source,
|
|
170
|
+
to: params.to,
|
|
76
171
|
}, log);
|
|
77
172
|
if (!result.success)
|
|
78
173
|
throw new Error(result.error);
|
|
79
174
|
return result;
|
|
80
175
|
}
|
|
81
176
|
case "monitors": {
|
|
177
|
+
const statusArray = parseArray(params.status);
|
|
82
178
|
const result = await listDatadogMonitors(credentials, {
|
|
83
|
-
monitorTags:
|
|
84
|
-
name:
|
|
85
|
-
status:
|
|
86
|
-
tags:
|
|
179
|
+
monitorTags: parseArray(params.monitorTags),
|
|
180
|
+
name: params.name,
|
|
181
|
+
status: statusArray,
|
|
182
|
+
tags: parseArray(params.tags),
|
|
87
183
|
}, log);
|
|
88
184
|
if (!result.success)
|
|
89
185
|
throw new Error(result.error);
|
|
90
186
|
return result;
|
|
91
187
|
}
|
|
92
188
|
case "synthetics": {
|
|
93
|
-
if (
|
|
94
|
-
const result = await getDatadogSyntheticResults(credentials,
|
|
189
|
+
if (params.testId) {
|
|
190
|
+
const result = await getDatadogSyntheticResults(credentials, params.testId, log);
|
|
95
191
|
if (!result.success)
|
|
96
192
|
throw new Error(result.error);
|
|
97
193
|
return result;
|
|
98
194
|
}
|
|
99
195
|
const result = await listDatadogSynthetics(credentials, {
|
|
100
|
-
tags:
|
|
101
|
-
type:
|
|
196
|
+
tags: parseArray(params.tags),
|
|
197
|
+
type: params.type,
|
|
102
198
|
}, log);
|
|
103
199
|
if (!result.success)
|
|
104
200
|
throw new Error(result.error);
|
|
105
201
|
return result;
|
|
106
202
|
}
|
|
107
203
|
case "metrics": {
|
|
108
|
-
if (!
|
|
204
|
+
if (!params.query)
|
|
109
205
|
throw new Error("query is required for metrics");
|
|
110
206
|
const now = Math.floor(Date.now() / 1000);
|
|
111
|
-
const fromStr =
|
|
207
|
+
const fromStr = params.from || "1h";
|
|
112
208
|
let fromTs;
|
|
113
209
|
if (fromStr.match(/^\d+$/)) {
|
|
114
210
|
fromTs = parseInt(fromStr, 10);
|
|
@@ -128,19 +224,19 @@ const datadogService = fabricService({
|
|
|
128
224
|
else {
|
|
129
225
|
fromTs = now - 3600;
|
|
130
226
|
}
|
|
131
|
-
const toStr =
|
|
227
|
+
const toStr = params.to || "now";
|
|
132
228
|
const toTs = toStr === "now" ? now : parseInt(toStr, 10);
|
|
133
|
-
const result = await queryDatadogMetrics(credentials, { from: fromTs, query:
|
|
229
|
+
const result = await queryDatadogMetrics(credentials, { from: fromTs, query: params.query, to: toTs }, log);
|
|
134
230
|
if (!result.success)
|
|
135
231
|
throw new Error(result.error);
|
|
136
232
|
return result;
|
|
137
233
|
}
|
|
138
234
|
case "rum": {
|
|
139
235
|
const result = await searchDatadogRum(credentials, {
|
|
140
|
-
from:
|
|
141
|
-
limit:
|
|
142
|
-
query:
|
|
143
|
-
to:
|
|
236
|
+
from: params.from,
|
|
237
|
+
limit: params.limit,
|
|
238
|
+
query: params.query,
|
|
239
|
+
to: params.to,
|
|
144
240
|
}, log);
|
|
145
241
|
if (!result.success)
|
|
146
242
|
throw new Error(result.error);
|
|
@@ -152,5 +248,5 @@ const datadogService = fabricService({
|
|
|
152
248
|
},
|
|
153
249
|
});
|
|
154
250
|
|
|
155
|
-
export { aggregateDatadogLogs, datadogService, getDatadogCredentials, getDatadogSyntheticResults, listDatadogMonitors, listDatadogSynthetics, queryDatadogMetrics, searchDatadogLogs, searchDatadogRum };
|
|
251
|
+
export { aggregateDatadogLogs, datadogService, getDatadogCredentials, getDatadogSyntheticResults, listDatadogMonitors, listDatadogSynthetics, queryDatadogMetrics, searchDatadogLogs, searchDatadogRum, validateDatadogSetup };
|
|
156
252
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/suites/datadog/index.ts"],"sourcesContent":["/**\n * Datadog Suite - Unified Datadog observability access\n */\nimport { fabricService } from \"@jaypie/fabric\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport {\n aggregateDatadogLogs,\n getDatadogCredentials,\n getDatadogSyntheticResults,\n listDatadogMonitors,\n listDatadogSynthetics,\n queryDatadogMetrics,\n searchDatadogLogs,\n searchDatadogRum,\n} from \"./datadog.js\";\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\n// Silent logger for direct execution\nconst log = {\n error: () => {},\n info: () => {},\n};\n\nasync function getHelp(): Promise<string> {\n return fs.readFile(path.join(__dirname, \"help.md\"), \"utf-8\");\n}\n\n// Input type for the unified Datadog service\ninterface DatadogInput {\n aggregation?: \"count\" | \"avg\" | \"sum\" | \"min\" | \"max\" | \"cardinality\";\n env?: string;\n from?: string;\n groupBy?: string[];\n limit?: number;\n metric?: string;\n monitorTags?: string[];\n name?: string;\n query?: string;\n service?: string;\n sort?: \"timestamp\" | \"-timestamp\";\n source?: string;\n status?: (\"Alert\" | \"Warn\" | \"No Data\" | \"OK\")[];\n tags?: string[];\n testId?: string;\n to?: string;\n type?: \"api\" | \"browser\";\n}\n\nexport const datadogService = fabricService({\n alias: \"datadog\",\n description:\n \"Access Datadog observability data. Commands: logs, log_analytics, monitors, synthetics, metrics, rum. Call with no args for help.\",\n input: {\n command: {\n description: \"Command to execute (omit for help)\",\n required: false,\n type: String,\n },\n input: {\n description: \"Command parameters\",\n required: false,\n type: Object,\n },\n },\n service: async ({\n command,\n input: params,\n }: {\n command?: string;\n input?: DatadogInput;\n }) => {\n if (!command || command === \"help\") {\n return getHelp();\n }\n\n const credentials = getDatadogCredentials();\n if (!credentials) {\n throw new Error(\n \"Datadog credentials not found. Set DATADOG_API_KEY and DATADOG_APP_KEY.\",\n );\n }\n\n const p = params || {};\n\n switch (command) {\n case \"logs\": {\n const result = await searchDatadogLogs(\n credentials,\n {\n env: p.env,\n from: p.from,\n limit: p.limit,\n query: p.query,\n service: p.service,\n sort: p.sort,\n source: p.source,\n to: p.to,\n },\n log,\n );\n if (!result.success) throw new Error(result.error);\n return result;\n }\n\n case \"log_analytics\": {\n if (!p.groupBy || p.groupBy.length === 0) {\n throw new Error(\"groupBy is required (array of field names)\");\n }\n const compute = p.aggregation\n ? [{ aggregation: p.aggregation, metric: p.metric }]\n : [{ aggregation: \"count\" as const }];\n const result = await aggregateDatadogLogs(\n credentials,\n {\n compute,\n env: p.env,\n from: p.from,\n groupBy: p.groupBy,\n query: p.query,\n service: p.service,\n source: p.source,\n to: p.to,\n },\n log,\n );\n if (!result.success) throw new Error(result.error);\n return result;\n }\n\n case \"monitors\": {\n const result = await listDatadogMonitors(\n credentials,\n {\n monitorTags: p.monitorTags,\n name: p.name,\n status: p.status,\n tags: p.tags,\n },\n log,\n );\n if (!result.success) throw new Error(result.error);\n return result;\n }\n\n case \"synthetics\": {\n if (p.testId) {\n const result = await getDatadogSyntheticResults(\n credentials,\n p.testId,\n log,\n );\n if (!result.success) throw new Error(result.error);\n return result;\n }\n const result = await listDatadogSynthetics(\n credentials,\n {\n tags: p.tags,\n type: p.type,\n },\n log,\n );\n if (!result.success) throw new Error(result.error);\n return result;\n }\n\n case \"metrics\": {\n if (!p.query) throw new Error(\"query is required for metrics\");\n const now = Math.floor(Date.now() / 1000);\n const fromStr = p.from || \"1h\";\n let fromTs: number;\n if (fromStr.match(/^\\d+$/)) {\n fromTs = parseInt(fromStr, 10);\n } else if (fromStr.match(/^(\\d+)h$/)) {\n const hours = parseInt(fromStr.match(/^(\\d+)h$/)![1], 10);\n fromTs = now - hours * 3600;\n } else if (fromStr.match(/^(\\d+)m$/)) {\n const minutes = parseInt(fromStr.match(/^(\\d+)m$/)![1], 10);\n fromTs = now - minutes * 60;\n } else if (fromStr.match(/^(\\d+)d$/)) {\n const days = parseInt(fromStr.match(/^(\\d+)d$/)![1], 10);\n fromTs = now - days * 86400;\n } else {\n fromTs = now - 3600;\n }\n const toStr = p.to || \"now\";\n const toTs = toStr === \"now\" ? now : parseInt(toStr, 10);\n const result = await queryDatadogMetrics(\n credentials,\n { from: fromTs, query: p.query, to: toTs },\n log,\n );\n if (!result.success) throw new Error(result.error);\n return result;\n }\n\n case \"rum\": {\n const result = await searchDatadogRum(\n credentials,\n {\n from: p.from,\n limit: p.limit,\n query: p.query,\n to: p.to,\n },\n log,\n );\n if (!result.success) throw new Error(result.error);\n return result;\n }\n\n default:\n throw new Error(`Unknown command: ${command}. Use datadog() for help.`);\n }\n },\n});\n\n// Re-export types and functions for testing\nexport * from \"./datadog.js\";\n"],"names":["__dirname"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/suites/datadog/index.ts"],"sourcesContent":["/**\n * Datadog Suite - Unified Datadog observability access\n */\nimport { fabricService } from \"@jaypie/fabric\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport {\n aggregateDatadogLogs,\n getDatadogCredentials,\n getDatadogSyntheticResults,\n listDatadogMonitors,\n listDatadogSynthetics,\n queryDatadogMetrics,\n searchDatadogLogs,\n searchDatadogRum,\n validateDatadogSetup,\n} from \"./datadog.js\";\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\n// Silent logger for direct execution\nconst log = {\n error: () => {},\n info: () => {},\n};\n\nasync function getHelp(): Promise<string> {\n return fs.readFile(path.join(__dirname, \"help.md\"), \"utf-8\");\n}\n\n// Flattened input type for the unified Datadog service\ninterface DatadogInput {\n aggregation?: string;\n command?: string;\n env?: string;\n from?: string;\n groupBy?: string;\n limit?: number;\n metric?: string;\n monitorTags?: string;\n name?: string;\n query?: string;\n service?: string;\n sort?: string;\n source?: string;\n status?: string;\n tags?: string;\n testId?: string;\n to?: string;\n type?: string;\n}\n\nexport const datadogService = fabricService({\n alias: \"datadog\",\n description:\n \"Access Datadog observability data. Commands: logs, log_analytics, monitors, synthetics, metrics, rum. Call with no args for help.\",\n input: {\n aggregation: {\n description:\n \"Aggregation type for log_analytics (count, avg, sum, min, max, cardinality)\",\n required: false,\n type: String,\n },\n command: {\n description:\n \"Command to execute: logs, log_analytics, monitors, synthetics, metrics, rum (omit for help)\",\n required: false,\n type: String,\n },\n env: {\n description: \"Environment filter (e.g., production, staging)\",\n required: false,\n type: String,\n },\n from: {\n description:\n \"Start time (e.g., now-1h, now-15m, now-1d, or ISO 8601 timestamp)\",\n required: false,\n type: String,\n },\n groupBy: {\n description:\n \"Fields to group by for log_analytics (comma-separated, e.g., service,status)\",\n required: false,\n type: String,\n },\n limit: {\n description: \"Maximum number of results to return\",\n required: false,\n type: Number,\n },\n metric: {\n description: \"Metric field for aggregation (e.g., @duration)\",\n required: false,\n type: String,\n },\n monitorTags: {\n description: \"Monitor tags filter (comma-separated)\",\n required: false,\n type: String,\n },\n name: {\n description: \"Name filter for monitors\",\n required: false,\n type: String,\n },\n query: {\n description:\n 'Datadog query string (e.g., status:error, @lambda.arn:\"arn:aws:...\")',\n required: false,\n type: String,\n },\n service: {\n description: \"Service name filter\",\n required: false,\n type: String,\n },\n sort: {\n description: \"Sort order (timestamp or -timestamp)\",\n required: false,\n type: String,\n },\n source: {\n description: \"Log source filter (default: lambda)\",\n required: false,\n type: String,\n },\n status: {\n description:\n \"Monitor status filter (comma-separated: Alert, Warn, No Data, OK)\",\n required: false,\n type: String,\n },\n tags: {\n description: \"Tags filter (comma-separated)\",\n required: false,\n type: String,\n },\n testId: {\n description: \"Synthetic test ID for getting results\",\n required: false,\n type: String,\n },\n to: {\n description: \"End time (e.g., now, or ISO 8601 timestamp)\",\n required: false,\n type: String,\n },\n type: {\n description: \"Synthetic test type filter (api or browser)\",\n required: false,\n type: String,\n },\n },\n service: async (params: DatadogInput) => {\n const { command } = params;\n\n if (!command || command === \"help\") {\n return getHelp();\n }\n\n const credentials = getDatadogCredentials();\n if (!credentials) {\n throw new Error(\n \"Datadog credentials not found. Set DATADOG_API_KEY and DATADOG_APP_KEY.\",\n );\n }\n\n // Helper to parse comma-separated strings into arrays\n const parseArray = (value?: string): string[] | undefined => {\n if (!value) return undefined;\n return value.split(\",\").map((s) => s.trim());\n };\n\n switch (command) {\n case \"validate\": {\n return validateDatadogSetup();\n }\n\n case \"logs\": {\n const result = await searchDatadogLogs(\n credentials,\n {\n env: params.env,\n from: params.from,\n limit: params.limit,\n query: params.query,\n service: params.service,\n sort: params.sort as \"timestamp\" | \"-timestamp\" | undefined,\n source: params.source,\n to: params.to,\n },\n log,\n );\n if (!result.success) throw new Error(result.error);\n return result;\n }\n\n case \"log_analytics\": {\n const groupByArray = parseArray(params.groupBy);\n if (!groupByArray || groupByArray.length === 0) {\n throw new Error(\n \"groupBy is required (comma-separated field names, e.g., service,status)\",\n );\n }\n const compute = params.aggregation\n ? [\n {\n aggregation: params.aggregation as\n | \"count\"\n | \"avg\"\n | \"sum\"\n | \"min\"\n | \"max\"\n | \"cardinality\",\n metric: params.metric,\n },\n ]\n : [{ aggregation: \"count\" as const }];\n const result = await aggregateDatadogLogs(\n credentials,\n {\n compute,\n env: params.env,\n from: params.from,\n groupBy: groupByArray,\n query: params.query,\n service: params.service,\n source: params.source,\n to: params.to,\n },\n log,\n );\n if (!result.success) throw new Error(result.error);\n return result;\n }\n\n case \"monitors\": {\n const statusArray = parseArray(params.status) as\n | (\"Alert\" | \"Warn\" | \"No Data\" | \"OK\")[]\n | undefined;\n const result = await listDatadogMonitors(\n credentials,\n {\n monitorTags: parseArray(params.monitorTags),\n name: params.name,\n status: statusArray,\n tags: parseArray(params.tags),\n },\n log,\n );\n if (!result.success) throw new Error(result.error);\n return result;\n }\n\n case \"synthetics\": {\n if (params.testId) {\n const result = await getDatadogSyntheticResults(\n credentials,\n params.testId,\n log,\n );\n if (!result.success) throw new Error(result.error);\n return result;\n }\n const result = await listDatadogSynthetics(\n credentials,\n {\n tags: parseArray(params.tags),\n type: params.type as \"api\" | \"browser\" | undefined,\n },\n log,\n );\n if (!result.success) throw new Error(result.error);\n return result;\n }\n\n case \"metrics\": {\n if (!params.query) throw new Error(\"query is required for metrics\");\n const now = Math.floor(Date.now() / 1000);\n const fromStr = params.from || \"1h\";\n let fromTs: number;\n if (fromStr.match(/^\\d+$/)) {\n fromTs = parseInt(fromStr, 10);\n } else if (fromStr.match(/^(\\d+)h$/)) {\n const hours = parseInt(fromStr.match(/^(\\d+)h$/)![1], 10);\n fromTs = now - hours * 3600;\n } else if (fromStr.match(/^(\\d+)m$/)) {\n const minutes = parseInt(fromStr.match(/^(\\d+)m$/)![1], 10);\n fromTs = now - minutes * 60;\n } else if (fromStr.match(/^(\\d+)d$/)) {\n const days = parseInt(fromStr.match(/^(\\d+)d$/)![1], 10);\n fromTs = now - days * 86400;\n } else {\n fromTs = now - 3600;\n }\n const toStr = params.to || \"now\";\n const toTs = toStr === \"now\" ? now : parseInt(toStr, 10);\n const result = await queryDatadogMetrics(\n credentials,\n { from: fromTs, query: params.query, to: toTs },\n log,\n );\n if (!result.success) throw new Error(result.error);\n return result;\n }\n\n case \"rum\": {\n const result = await searchDatadogRum(\n credentials,\n {\n from: params.from,\n limit: params.limit,\n query: params.query,\n to: params.to,\n },\n log,\n );\n if (!result.success) throw new Error(result.error);\n return result;\n }\n\n default:\n throw new Error(`Unknown command: ${command}. Use datadog() for help.`);\n }\n },\n});\n\n// Re-export types and functions for testing\nexport * from \"./datadog.js\";\n"],"names":["__dirname"],"mappings":"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"}
|
|
@@ -9,7 +9,7 @@ import { gt } from 'semver';
|
|
|
9
9
|
/**
|
|
10
10
|
* Docs Suite - Documentation services (skill, version, release_notes)
|
|
11
11
|
*/
|
|
12
|
-
const BUILD_VERSION_STRING = "@jaypie/mcp@0.7.
|
|
12
|
+
const BUILD_VERSION_STRING = "@jaypie/mcp@0.7.11#d7ce271c"
|
|
13
13
|
;
|
|
14
14
|
const __filename$1 = fileURLToPath(import.meta.url);
|
|
15
15
|
const __dirname$1 = path.dirname(__filename$1);
|
|
@@ -95,6 +95,44 @@ function filterReleaseNotesSince(notes, sinceVersion) {
|
|
|
95
95
|
// =============================================================================
|
|
96
96
|
// SKILL SERVICE
|
|
97
97
|
// =============================================================================
|
|
98
|
+
/**
|
|
99
|
+
* Generate alternative spellings for plural/singular matching
|
|
100
|
+
*/
|
|
101
|
+
function getAlternativeSpellings(alias) {
|
|
102
|
+
const alternatives = [];
|
|
103
|
+
if (alias.endsWith("es")) {
|
|
104
|
+
// "indexes" -> try "indexe" and "index"
|
|
105
|
+
alternatives.push(alias.slice(0, -1)); // Remove "s" -> "indexe"
|
|
106
|
+
alternatives.push(alias.slice(0, -2)); // Remove "es" -> "index"
|
|
107
|
+
}
|
|
108
|
+
else if (alias.endsWith("s")) {
|
|
109
|
+
// "skills" -> try "skill"
|
|
110
|
+
alternatives.push(alias.slice(0, -1)); // Remove "s" -> "skill"
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
// "fish" -> try "fishs" and "fishes"
|
|
114
|
+
alternatives.push(alias + "s");
|
|
115
|
+
alternatives.push(alias + "es");
|
|
116
|
+
}
|
|
117
|
+
return alternatives;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Add alias to frontmatter indicating the canonical skill name
|
|
121
|
+
*/
|
|
122
|
+
function addAliasToFrontmatter(content, matchedAlias) {
|
|
123
|
+
if (content.startsWith("---")) {
|
|
124
|
+
// Find the end of frontmatter
|
|
125
|
+
const endIndex = content.indexOf("---", 3);
|
|
126
|
+
if (endIndex !== -1) {
|
|
127
|
+
// Insert alias before the closing ---
|
|
128
|
+
const beforeClose = content.slice(0, endIndex);
|
|
129
|
+
const afterClose = content.slice(endIndex);
|
|
130
|
+
return `${beforeClose}alias: ${matchedAlias}\n${afterClose}`;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// No frontmatter exists, create one
|
|
134
|
+
return `---\nalias: ${matchedAlias}\n---\n\n${content}`;
|
|
135
|
+
}
|
|
98
136
|
const skillService = fabricService({
|
|
99
137
|
alias: "skill",
|
|
100
138
|
description: "Access Jaypie development documentation. Pass a skill alias (e.g., 'aws', 'tests', 'errors') to get that documentation. Pass 'index' or no argument to list all available skills.",
|
|
@@ -123,13 +161,31 @@ const skillService = fabricService({
|
|
|
123
161
|
}
|
|
124
162
|
return `# Jaypie Skills\n\n## Available Skills\n\n${skillList}`;
|
|
125
163
|
}
|
|
126
|
-
|
|
164
|
+
// Try exact match first
|
|
165
|
+
let skill = await skillStore.get(alias);
|
|
166
|
+
let matchedAlias = alias;
|
|
167
|
+
// If no exact match, try alternative spellings (plural/singular)
|
|
168
|
+
if (!skill) {
|
|
169
|
+
const alternatives = getAlternativeSpellings(alias);
|
|
170
|
+
for (const alt of alternatives) {
|
|
171
|
+
skill = await skillStore.get(alt);
|
|
172
|
+
if (skill) {
|
|
173
|
+
matchedAlias = alt;
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
127
178
|
if (!skill) {
|
|
128
179
|
throw new Error(`Skill "${alias}" not found. Use skill("index") to list available skills.`);
|
|
129
180
|
}
|
|
130
181
|
// Return raw file content for non-index skills (preserve frontmatter)
|
|
131
|
-
const skillPath = path.join(SKILLS_PATH, `${
|
|
132
|
-
|
|
182
|
+
const skillPath = path.join(SKILLS_PATH, `${matchedAlias}.md`);
|
|
183
|
+
let content = await fs.readFile(skillPath, "utf-8");
|
|
184
|
+
// If we matched via alternative spelling, add alias to indicate canonical name
|
|
185
|
+
if (matchedAlias !== alias) {
|
|
186
|
+
content = addAliasToFrontmatter(content, matchedAlias);
|
|
187
|
+
}
|
|
188
|
+
return content;
|
|
133
189
|
},
|
|
134
190
|
});
|
|
135
191
|
// =============================================================================
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/suites/docs/index.ts"],"sourcesContent":["/**\n * Docs Suite - Documentation services (skill, version, release_notes)\n */\nimport { fabricService } from \"@jaypie/fabric\";\nimport {\n createMarkdownStore,\n isValidAlias,\n normalizeAlias,\n type SkillRecord,\n} from \"@jaypie/tildeskill\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport matter from \"gray-matter\";\nimport { gt } from \"semver\";\n\n// Build-time constants\ndeclare const __BUILD_VERSION_STRING__: string;\nconst BUILD_VERSION_STRING =\n typeof __BUILD_VERSION_STRING__ !== \"undefined\"\n ? __BUILD_VERSION_STRING__\n : \"@jaypie/mcp@0.0.0\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n// From dist/suites/docs/, go up 3 levels to package root where skills/ and release-notes/ live\nconst RELEASE_NOTES_PATH = path.join(\n __dirname,\n \"..\",\n \"..\",\n \"..\",\n \"release-notes\",\n);\nconst SKILLS_PATH = path.join(__dirname, \"..\", \"..\", \"..\", \"skills\");\n\n// Create skill store using tildeskill\nconst skillStore = createMarkdownStore({ path: SKILLS_PATH });\n\n// =============================================================================\n// HELPER FUNCTIONS\n// =============================================================================\n\ninterface ReleaseNoteFrontMatter {\n date?: string;\n summary?: string;\n version?: string;\n}\n\nasync function parseReleaseNoteFile(filePath: string): Promise<{\n date?: string;\n filename: string;\n summary?: string;\n version?: string;\n}> {\n try {\n const content = await fs.readFile(filePath, \"utf-8\");\n const filename = path.basename(filePath, \".md\");\n\n if (content.startsWith(\"---\")) {\n const parsed = matter(content);\n const frontMatter = parsed.data as ReleaseNoteFrontMatter;\n return {\n date: frontMatter.date,\n filename,\n summary: frontMatter.summary,\n version: frontMatter.version || filename,\n };\n }\n\n return { filename, version: filename };\n } catch {\n return { filename: path.basename(filePath, \".md\") };\n }\n}\n\nfunction formatReleaseNoteListItem(note: {\n date?: string;\n filename: string;\n packageName: string;\n summary?: string;\n version?: string;\n}): string {\n const { date, packageName, summary, version } = note;\n const parts = [`* ${packageName}@${version}`];\n\n if (date) {\n parts.push(`(${date})`);\n }\n\n if (summary) {\n parts.push(`- ${summary}`);\n }\n\n return parts.join(\" \");\n}\n\nfunction formatSkillListItem(skill: SkillRecord): string {\n const { alias, description } = skill;\n if (description) {\n return `* ${alias} - ${description}`;\n }\n return `* ${alias}`;\n}\n\nasync function getPackageReleaseNotes(packageName: string): Promise<\n Array<{\n date?: string;\n filename: string;\n packageName: string;\n summary?: string;\n version?: string;\n }>\n> {\n const packageDir = path.join(RELEASE_NOTES_PATH, packageName);\n try {\n const files = await fs.readdir(packageDir);\n const mdFiles = files.filter((file) => file.endsWith(\".md\"));\n\n const notes = await Promise.all(\n mdFiles.map(async (file) => {\n const parsed = await parseReleaseNoteFile(path.join(packageDir, file));\n return { ...parsed, packageName };\n }),\n );\n\n return notes.sort((a, b) => {\n if (!a.version || !b.version) return 0;\n try {\n return gt(a.version, b.version) ? -1 : 1;\n } catch {\n return b.version.localeCompare(a.version);\n }\n });\n } catch {\n return [];\n }\n}\n\nfunction filterReleaseNotesSince(\n notes: Array<{\n date?: string;\n filename: string;\n packageName: string;\n summary?: string;\n version?: string;\n }>,\n sinceVersion: string,\n): Array<{\n date?: string;\n filename: string;\n packageName: string;\n summary?: string;\n version?: string;\n}> {\n return notes.filter((note) => {\n if (!note.version) return false;\n try {\n return gt(note.version, sinceVersion);\n } catch {\n return false;\n }\n });\n}\n\n// =============================================================================\n// SKILL SERVICE\n// =============================================================================\n\nexport const skillService = fabricService({\n alias: \"skill\",\n description:\n \"Access Jaypie development documentation. Pass a skill alias (e.g., 'aws', 'tests', 'errors') to get that documentation. Pass 'index' or no argument to list all available skills.\",\n input: {\n alias: {\n description:\n \"Skill alias (e.g., 'aws', 'tests'). Omit or use 'index' to list all skills.\",\n required: false,\n type: String,\n },\n },\n service: async ({ alias: inputAlias }: { alias?: string }) => {\n const alias = normalizeAlias(inputAlias || \"index\");\n\n if (!isValidAlias(alias)) {\n throw new Error(\n `Invalid skill alias \"${alias}\". Use alphanumeric characters, hyphens, and underscores only.`,\n );\n }\n\n if (alias === \"index\") {\n // Get index content\n const indexRecord = await skillStore.get(\"index\");\n const indexContent = indexRecord?.content || \"\";\n\n // List all skills except index\n const allSkills = await skillStore.list();\n const skills = allSkills.filter((s) => s.alias !== \"index\");\n const skillList = skills.map(formatSkillListItem).join(\"\\n\");\n\n if (indexContent) {\n return `${indexContent}\\n\\n## Available Skills\\n\\n${skillList}`;\n }\n return `# Jaypie Skills\\n\\n## Available Skills\\n\\n${skillList}`;\n }\n\n const skill = await skillStore.get(alias);\n if (!skill) {\n throw new Error(\n `Skill \"${alias}\" not found. Use skill(\"index\") to list available skills.`,\n );\n }\n\n // Return raw file content for non-index skills (preserve frontmatter)\n const skillPath = path.join(SKILLS_PATH, `${alias}.md`);\n return fs.readFile(skillPath, \"utf-8\");\n },\n});\n\n// =============================================================================\n// VERSION SERVICE\n// =============================================================================\n\nexport const versionService = fabricService({\n alias: \"version\",\n description: `Prints the current version and hash, \\`${BUILD_VERSION_STRING}\\``,\n input: {},\n service: async () => BUILD_VERSION_STRING,\n});\n\n// =============================================================================\n// RELEASE NOTES SERVICE\n// =============================================================================\n\nasync function getReleaseNotesHelp(): Promise<string> {\n return fs.readFile(path.join(__dirname, \"release-notes\", \"help.md\"), \"utf-8\");\n}\n\ninterface ReleaseNotesInput {\n package?: string;\n since_version?: string;\n version?: string;\n}\n\nexport const releaseNotesService = fabricService({\n alias: \"release_notes\",\n description:\n \"Browse Jaypie package release notes. Commands: list, read. Call with no args for help.\",\n input: {\n command: {\n description: \"Command to execute (omit for help)\",\n required: false,\n type: String,\n },\n input: {\n description: \"Command parameters\",\n required: false,\n type: Object,\n },\n },\n service: async ({\n command,\n input: params,\n }: {\n command?: string;\n input?: ReleaseNotesInput;\n }) => {\n if (!command || command === \"help\") {\n return getReleaseNotesHelp();\n }\n\n const p = params || {};\n\n switch (command) {\n case \"list\": {\n const entries = await fs.readdir(RELEASE_NOTES_PATH, {\n withFileTypes: true,\n });\n const packageDirs = entries\n .filter((entry) => entry.isDirectory())\n .map((entry) => entry.name);\n const packagesToList = p.package\n ? packageDirs.filter((pkg) => pkg === p.package)\n : packageDirs;\n\n if (packagesToList.length === 0 && p.package) {\n return `No release notes found for package \"${p.package}\".`;\n }\n\n const allNotes = await Promise.all(\n packagesToList.map((pkg) => getPackageReleaseNotes(pkg)),\n );\n let flatNotes = allNotes.flat();\n\n if (p.since_version) {\n flatNotes = filterReleaseNotesSince(flatNotes, p.since_version);\n }\n\n if (flatNotes.length === 0) {\n const filterDesc = p.since_version\n ? ` newer than ${p.since_version}`\n : \"\";\n return `No release notes found${filterDesc}.`;\n }\n\n return flatNotes.map(formatReleaseNoteListItem).join(\"\\n\");\n }\n\n case \"read\": {\n if (!p.package) throw new Error(\"package is required\");\n if (!p.version) throw new Error(\"version is required\");\n const filePath = path.join(\n RELEASE_NOTES_PATH,\n p.package,\n `${p.version}.md`,\n );\n return fs.readFile(filePath, \"utf-8\");\n }\n\n default:\n throw new Error(\n `Unknown command: ${command}. Use release_notes() for help.`,\n );\n }\n },\n});\n"],"names":["__filename","__dirname"],"mappings":";;;;;;;;AAAA;;AAEG;AAgBH,MAAM,oBAAoB,GAEpB;IACmB;AAEzB,MAAMA,YAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;AACjD,MAAMC,WAAS,GAAG,IAAI,CAAC,OAAO,CAACD,YAAU,CAAC;AAC1C;AACA,MAAM,kBAAkB,GAAG,IAAI,CAAC,IAAI,CAClCC,WAAS,EACT,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,eAAe,CAChB;AACD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAACA,WAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC;AAEpE;AACA,MAAM,UAAU,GAAG,mBAAmB,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;AAY7D,eAAe,oBAAoB,CAAC,QAAgB,EAAA;AAMlD,IAAA,IAAI;QACF,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;QACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC;AAE/C,QAAA,IAAI,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE;AAC7B,YAAA,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC;AAC9B,YAAA,MAAM,WAAW,GAAG,MAAM,CAAC,IAA8B;YACzD,OAAO;gBACL,IAAI,EAAE,WAAW,CAAC,IAAI;gBACtB,QAAQ;gBACR,OAAO,EAAE,WAAW,CAAC,OAAO;AAC5B,gBAAA,OAAO,EAAE,WAAW,CAAC,OAAO,IAAI,QAAQ;aACzC;QACH;AAEA,QAAA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE;IACxC;AAAE,IAAA,MAAM;AACN,QAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE;IACrD;AACF;AAEA,SAAS,yBAAyB,CAAC,IAMlC,EAAA;IACC,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,IAAI;IACpD,MAAM,KAAK,GAAG,CAAC,CAAA,EAAA,EAAK,WAAW,CAAA,CAAA,EAAI,OAAO,CAAA,CAAE,CAAC;IAE7C,IAAI,IAAI,EAAE;AACR,QAAA,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,CAAA,CAAA,CAAG,CAAC;IACzB;IAEA,IAAI,OAAO,EAAE;AACX,QAAA,KAAK,CAAC,IAAI,CAAC,KAAK,OAAO,CAAA,CAAE,CAAC;IAC5B;AAEA,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;AACxB;AAEA,SAAS,mBAAmB,CAAC,KAAkB,EAAA;AAC7C,IAAA,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,KAAK;IACpC,IAAI,WAAW,EAAE;AACf,QAAA,OAAO,CAAA,EAAA,EAAK,KAAK,CAAA,GAAA,EAAM,WAAW,EAAE;IACtC;IACA,OAAO,CAAA,EAAA,EAAK,KAAK,CAAA,CAAE;AACrB;AAEA,eAAe,sBAAsB,CAAC,WAAmB,EAAA;IASvD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,WAAW,CAAC;AAC7D,IAAA,IAAI;QACF,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC;AAC1C,QAAA,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAE5D,QAAA,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,GAAG,CAC7B,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,KAAI;AACzB,YAAA,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AACtE,YAAA,OAAO,EAAE,GAAG,MAAM,EAAE,WAAW,EAAE;QACnC,CAAC,CAAC,CACH;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAI;YACzB,IAAI,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO;AAAE,gBAAA,OAAO,CAAC;AACtC,YAAA,IAAI;AACF,gBAAA,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC;YAC1C;AAAE,YAAA,MAAM;gBACN,OAAO,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC;YAC3C;AACF,QAAA,CAAC,CAAC;IACJ;AAAE,IAAA,MAAM;AACN,QAAA,OAAO,EAAE;IACX;AACF;AAEA,SAAS,uBAAuB,CAC9B,KAME,EACF,YAAoB,EAAA;AAQpB,IAAA,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,KAAI;QAC3B,IAAI,CAAC,IAAI,CAAC,OAAO;AAAE,YAAA,OAAO,KAAK;AAC/B,QAAA,IAAI;YACF,OAAO,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC;QACvC;AAAE,QAAA,MAAM;AACN,YAAA,OAAO,KAAK;QACd;AACF,IAAA,CAAC,CAAC;AACJ;AAEA;AACA;AACA;AAEO,MAAM,YAAY,GAAG,aAAa,CAAC;AACxC,IAAA,KAAK,EAAE,OAAO;AACd,IAAA,WAAW,EACT,mLAAmL;AACrL,IAAA,KAAK,EAAE;AACL,QAAA,KAAK,EAAE;AACL,YAAA,WAAW,EACT,6EAA6E;AAC/E,YAAA,QAAQ,EAAE,KAAK;AACf,YAAA,IAAI,EAAE,MAAM;AACb,SAAA;AACF,KAAA;IACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAsB,KAAI;QAC3D,MAAM,KAAK,GAAG,cAAc,CAAC,UAAU,IAAI,OAAO,CAAC;AAEnD,QAAA,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE;AACxB,YAAA,MAAM,IAAI,KAAK,CACb,wBAAwB,KAAK,CAAA,8DAAA,CAAgE,CAC9F;QACH;AAEA,QAAA,IAAI,KAAK,KAAK,OAAO,EAAE;;YAErB,MAAM,WAAW,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC;AACjD,YAAA,MAAM,YAAY,GAAG,WAAW,EAAE,OAAO,IAAI,EAAE;;AAG/C,YAAA,MAAM,SAAS,GAAG,MAAM,UAAU,CAAC,IAAI,EAAE;AACzC,YAAA,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,KAAK,OAAO,CAAC;AAC3D,YAAA,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;YAE5D,IAAI,YAAY,EAAE;AAChB,gBAAA,OAAO,CAAA,EAAG,YAAY,CAAA,2BAAA,EAA8B,SAAS,EAAE;YACjE;YACA,OAAO,CAAA,0CAAA,EAA6C,SAAS,CAAA,CAAE;QACjE;QAEA,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;QACzC,IAAI,CAAC,KAAK,EAAE;AACV,YAAA,MAAM,IAAI,KAAK,CACb,UAAU,KAAK,CAAA,yDAAA,CAA2D,CAC3E;QACH;;AAGA,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAA,EAAG,KAAK,CAAA,GAAA,CAAK,CAAC;QACvD,OAAO,EAAE,CAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IACxC,CAAC;AACF,CAAA;AAED;AACA;AACA;AAEO,MAAM,cAAc,GAAG,aAAa,CAAC;AAC1C,IAAA,KAAK,EAAE,SAAS;IAChB,WAAW,EAAE,CAAA,uCAAA,EAA0C,oBAAoB,CAAA,EAAA,CAAI;AAC/E,IAAA,KAAK,EAAE,EAAE;AACT,IAAA,OAAO,EAAE,YAAY,oBAAoB;AAC1C,CAAA;AAED;AACA;AACA;AAEA,eAAe,mBAAmB,GAAA;AAChC,IAAA,OAAO,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAACA,WAAS,EAAE,eAAe,EAAE,SAAS,CAAC,EAAE,OAAO,CAAC;AAC/E;AAQO,MAAM,mBAAmB,GAAG,aAAa,CAAC;AAC/C,IAAA,KAAK,EAAE,eAAe;AACtB,IAAA,WAAW,EACT,wFAAwF;AAC1F,IAAA,KAAK,EAAE;AACL,QAAA,OAAO,EAAE;AACP,YAAA,WAAW,EAAE,oCAAoC;AACjD,YAAA,QAAQ,EAAE,KAAK;AACf,YAAA,IAAI,EAAE,MAAM;AACb,SAAA;AACD,QAAA,KAAK,EAAE;AACL,YAAA,WAAW,EAAE,oBAAoB;AACjC,YAAA,QAAQ,EAAE,KAAK;AACf,YAAA,IAAI,EAAE,MAAM;AACb,SAAA;AACF,KAAA;IACD,OAAO,EAAE,OAAO,EACd,OAAO,EACP,KAAK,EAAE,MAAM,GAId,KAAI;AACH,QAAA,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,MAAM,EAAE;YAClC,OAAO,mBAAmB,EAAE;QAC9B;AAEA,QAAA,MAAM,CAAC,GAAG,MAAM,IAAI,EAAE;QAEtB,QAAQ,OAAO;YACb,KAAK,MAAM,EAAE;gBACX,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,kBAAkB,EAAE;AACnD,oBAAA,aAAa,EAAE,IAAI;AACpB,iBAAA,CAAC;gBACF,MAAM,WAAW,GAAG;qBACjB,MAAM,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,WAAW,EAAE;qBACrC,GAAG,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,IAAI,CAAC;AAC7B,gBAAA,MAAM,cAAc,GAAG,CAAC,CAAC;AACvB,sBAAE,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,GAAG,KAAK,CAAC,CAAC,OAAO;sBAC7C,WAAW;gBAEf,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE;AAC5C,oBAAA,OAAO,CAAA,oCAAA,EAAuC,CAAC,CAAC,OAAO,IAAI;gBAC7D;gBAEA,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAChC,cAAc,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,sBAAsB,CAAC,GAAG,CAAC,CAAC,CACzD;AACD,gBAAA,IAAI,SAAS,GAAG,QAAQ,CAAC,IAAI,EAAE;AAE/B,gBAAA,IAAI,CAAC,CAAC,aAAa,EAAE;oBACnB,SAAS,GAAG,uBAAuB,CAAC,SAAS,EAAE,CAAC,CAAC,aAAa,CAAC;gBACjE;AAEA,gBAAA,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE;AAC1B,oBAAA,MAAM,UAAU,GAAG,CAAC,CAAC;AACnB,0BAAE,CAAA,YAAA,EAAe,CAAC,CAAC,aAAa,CAAA;0BAC9B,EAAE;oBACN,OAAO,CAAA,sBAAA,EAAyB,UAAU,CAAA,CAAA,CAAG;gBAC/C;gBAEA,OAAO,SAAS,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;YAC5D;YAEA,KAAK,MAAM,EAAE;gBACX,IAAI,CAAC,CAAC,CAAC,OAAO;AAAE,oBAAA,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC;gBACtD,IAAI,CAAC,CAAC,CAAC,OAAO;AAAE,oBAAA,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC;AACtD,gBAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CACxB,kBAAkB,EAClB,CAAC,CAAC,OAAO,EACT,CAAA,EAAG,CAAC,CAAC,OAAO,CAAA,GAAA,CAAK,CAClB;gBACD,OAAO,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;YACvC;AAEA,YAAA;AACE,gBAAA,MAAM,IAAI,KAAK,CACb,oBAAoB,OAAO,CAAA,+BAAA,CAAiC,CAC7D;;IAEP,CAAC;AACF,CAAA;;;;"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/suites/docs/index.ts"],"sourcesContent":["/**\n * Docs Suite - Documentation services (skill, version, release_notes)\n */\nimport { fabricService } from \"@jaypie/fabric\";\nimport {\n createMarkdownStore,\n isValidAlias,\n normalizeAlias,\n type SkillRecord,\n} from \"@jaypie/tildeskill\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport matter from \"gray-matter\";\nimport { gt } from \"semver\";\n\n// Build-time constants\ndeclare const __BUILD_VERSION_STRING__: string;\nconst BUILD_VERSION_STRING =\n typeof __BUILD_VERSION_STRING__ !== \"undefined\"\n ? __BUILD_VERSION_STRING__\n : \"@jaypie/mcp@0.0.0\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n// From dist/suites/docs/, go up 3 levels to package root where skills/ and release-notes/ live\nconst RELEASE_NOTES_PATH = path.join(\n __dirname,\n \"..\",\n \"..\",\n \"..\",\n \"release-notes\",\n);\nconst SKILLS_PATH = path.join(__dirname, \"..\", \"..\", \"..\", \"skills\");\n\n// Create skill store using tildeskill\nconst skillStore = createMarkdownStore({ path: SKILLS_PATH });\n\n// =============================================================================\n// HELPER FUNCTIONS\n// =============================================================================\n\ninterface ReleaseNoteFrontMatter {\n date?: string;\n summary?: string;\n version?: string;\n}\n\nasync function parseReleaseNoteFile(filePath: string): Promise<{\n date?: string;\n filename: string;\n summary?: string;\n version?: string;\n}> {\n try {\n const content = await fs.readFile(filePath, \"utf-8\");\n const filename = path.basename(filePath, \".md\");\n\n if (content.startsWith(\"---\")) {\n const parsed = matter(content);\n const frontMatter = parsed.data as ReleaseNoteFrontMatter;\n return {\n date: frontMatter.date,\n filename,\n summary: frontMatter.summary,\n version: frontMatter.version || filename,\n };\n }\n\n return { filename, version: filename };\n } catch {\n return { filename: path.basename(filePath, \".md\") };\n }\n}\n\nfunction formatReleaseNoteListItem(note: {\n date?: string;\n filename: string;\n packageName: string;\n summary?: string;\n version?: string;\n}): string {\n const { date, packageName, summary, version } = note;\n const parts = [`* ${packageName}@${version}`];\n\n if (date) {\n parts.push(`(${date})`);\n }\n\n if (summary) {\n parts.push(`- ${summary}`);\n }\n\n return parts.join(\" \");\n}\n\nfunction formatSkillListItem(skill: SkillRecord): string {\n const { alias, description } = skill;\n if (description) {\n return `* ${alias} - ${description}`;\n }\n return `* ${alias}`;\n}\n\nasync function getPackageReleaseNotes(packageName: string): Promise<\n Array<{\n date?: string;\n filename: string;\n packageName: string;\n summary?: string;\n version?: string;\n }>\n> {\n const packageDir = path.join(RELEASE_NOTES_PATH, packageName);\n try {\n const files = await fs.readdir(packageDir);\n const mdFiles = files.filter((file) => file.endsWith(\".md\"));\n\n const notes = await Promise.all(\n mdFiles.map(async (file) => {\n const parsed = await parseReleaseNoteFile(path.join(packageDir, file));\n return { ...parsed, packageName };\n }),\n );\n\n return notes.sort((a, b) => {\n if (!a.version || !b.version) return 0;\n try {\n return gt(a.version, b.version) ? -1 : 1;\n } catch {\n return b.version.localeCompare(a.version);\n }\n });\n } catch {\n return [];\n }\n}\n\nfunction filterReleaseNotesSince(\n notes: Array<{\n date?: string;\n filename: string;\n packageName: string;\n summary?: string;\n version?: string;\n }>,\n sinceVersion: string,\n): Array<{\n date?: string;\n filename: string;\n packageName: string;\n summary?: string;\n version?: string;\n}> {\n return notes.filter((note) => {\n if (!note.version) return false;\n try {\n return gt(note.version, sinceVersion);\n } catch {\n return false;\n }\n });\n}\n\n// =============================================================================\n// SKILL SERVICE\n// =============================================================================\n\n/**\n * Generate alternative spellings for plural/singular matching\n */\nfunction getAlternativeSpellings(alias: string): string[] {\n const alternatives: string[] = [];\n\n if (alias.endsWith(\"es\")) {\n // \"indexes\" -> try \"indexe\" and \"index\"\n alternatives.push(alias.slice(0, -1)); // Remove \"s\" -> \"indexe\"\n alternatives.push(alias.slice(0, -2)); // Remove \"es\" -> \"index\"\n } else if (alias.endsWith(\"s\")) {\n // \"skills\" -> try \"skill\"\n alternatives.push(alias.slice(0, -1)); // Remove \"s\" -> \"skill\"\n } else {\n // \"fish\" -> try \"fishs\" and \"fishes\"\n alternatives.push(alias + \"s\");\n alternatives.push(alias + \"es\");\n }\n\n return alternatives;\n}\n\n/**\n * Add alias to frontmatter indicating the canonical skill name\n */\nfunction addAliasToFrontmatter(content: string, matchedAlias: string): string {\n if (content.startsWith(\"---\")) {\n // Find the end of frontmatter\n const endIndex = content.indexOf(\"---\", 3);\n if (endIndex !== -1) {\n // Insert alias before the closing ---\n const beforeClose = content.slice(0, endIndex);\n const afterClose = content.slice(endIndex);\n return `${beforeClose}alias: ${matchedAlias}\\n${afterClose}`;\n }\n }\n // No frontmatter exists, create one\n return `---\\nalias: ${matchedAlias}\\n---\\n\\n${content}`;\n}\n\nexport const skillService = fabricService({\n alias: \"skill\",\n description:\n \"Access Jaypie development documentation. Pass a skill alias (e.g., 'aws', 'tests', 'errors') to get that documentation. Pass 'index' or no argument to list all available skills.\",\n input: {\n alias: {\n description:\n \"Skill alias (e.g., 'aws', 'tests'). Omit or use 'index' to list all skills.\",\n required: false,\n type: String,\n },\n },\n service: async ({ alias: inputAlias }: { alias?: string }) => {\n const alias = normalizeAlias(inputAlias || \"index\");\n\n if (!isValidAlias(alias)) {\n throw new Error(\n `Invalid skill alias \"${alias}\". Use alphanumeric characters, hyphens, and underscores only.`,\n );\n }\n\n if (alias === \"index\") {\n // Get index content\n const indexRecord = await skillStore.get(\"index\");\n const indexContent = indexRecord?.content || \"\";\n\n // List all skills except index\n const allSkills = await skillStore.list();\n const skills = allSkills.filter((s) => s.alias !== \"index\");\n const skillList = skills.map(formatSkillListItem).join(\"\\n\");\n\n if (indexContent) {\n return `${indexContent}\\n\\n## Available Skills\\n\\n${skillList}`;\n }\n return `# Jaypie Skills\\n\\n## Available Skills\\n\\n${skillList}`;\n }\n\n // Try exact match first\n let skill = await skillStore.get(alias);\n let matchedAlias = alias;\n\n // If no exact match, try alternative spellings (plural/singular)\n if (!skill) {\n const alternatives = getAlternativeSpellings(alias);\n for (const alt of alternatives) {\n skill = await skillStore.get(alt);\n if (skill) {\n matchedAlias = alt;\n break;\n }\n }\n }\n\n if (!skill) {\n throw new Error(\n `Skill \"${alias}\" not found. Use skill(\"index\") to list available skills.`,\n );\n }\n\n // Return raw file content for non-index skills (preserve frontmatter)\n const skillPath = path.join(SKILLS_PATH, `${matchedAlias}.md`);\n let content = await fs.readFile(skillPath, \"utf-8\");\n\n // If we matched via alternative spelling, add alias to indicate canonical name\n if (matchedAlias !== alias) {\n content = addAliasToFrontmatter(content, matchedAlias);\n }\n\n return content;\n },\n});\n\n// =============================================================================\n// VERSION SERVICE\n// =============================================================================\n\nexport const versionService = fabricService({\n alias: \"version\",\n description: `Prints the current version and hash, \\`${BUILD_VERSION_STRING}\\``,\n input: {},\n service: async () => BUILD_VERSION_STRING,\n});\n\n// =============================================================================\n// RELEASE NOTES SERVICE\n// =============================================================================\n\nasync function getReleaseNotesHelp(): Promise<string> {\n return fs.readFile(path.join(__dirname, \"release-notes\", \"help.md\"), \"utf-8\");\n}\n\ninterface ReleaseNotesInput {\n package?: string;\n since_version?: string;\n version?: string;\n}\n\nexport const releaseNotesService = fabricService({\n alias: \"release_notes\",\n description:\n \"Browse Jaypie package release notes. Commands: list, read. Call with no args for help.\",\n input: {\n command: {\n description: \"Command to execute (omit for help)\",\n required: false,\n type: String,\n },\n input: {\n description: \"Command parameters\",\n required: false,\n type: Object,\n },\n },\n service: async ({\n command,\n input: params,\n }: {\n command?: string;\n input?: ReleaseNotesInput;\n }) => {\n if (!command || command === \"help\") {\n return getReleaseNotesHelp();\n }\n\n const p = params || {};\n\n switch (command) {\n case \"list\": {\n const entries = await fs.readdir(RELEASE_NOTES_PATH, {\n withFileTypes: true,\n });\n const packageDirs = entries\n .filter((entry) => entry.isDirectory())\n .map((entry) => entry.name);\n const packagesToList = p.package\n ? packageDirs.filter((pkg) => pkg === p.package)\n : packageDirs;\n\n if (packagesToList.length === 0 && p.package) {\n return `No release notes found for package \"${p.package}\".`;\n }\n\n const allNotes = await Promise.all(\n packagesToList.map((pkg) => getPackageReleaseNotes(pkg)),\n );\n let flatNotes = allNotes.flat();\n\n if (p.since_version) {\n flatNotes = filterReleaseNotesSince(flatNotes, p.since_version);\n }\n\n if (flatNotes.length === 0) {\n const filterDesc = p.since_version\n ? ` newer than ${p.since_version}`\n : \"\";\n return `No release notes found${filterDesc}.`;\n }\n\n return flatNotes.map(formatReleaseNoteListItem).join(\"\\n\");\n }\n\n case \"read\": {\n if (!p.package) throw new Error(\"package is required\");\n if (!p.version) throw new Error(\"version is required\");\n const filePath = path.join(\n RELEASE_NOTES_PATH,\n p.package,\n `${p.version}.md`,\n );\n return fs.readFile(filePath, \"utf-8\");\n }\n\n default:\n throw new Error(\n `Unknown command: ${command}. Use release_notes() for help.`,\n );\n }\n },\n});\n"],"names":["__filename","__dirname"],"mappings":"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"}
|
package/dist/suites/llm/help.md
CHANGED
|
@@ -6,8 +6,20 @@ Debug and inspect LLM provider responses. Useful for understanding how providers
|
|
|
6
6
|
|
|
7
7
|
| Command | Description | Required Parameters |
|
|
8
8
|
|---------|-------------|---------------------|
|
|
9
|
+
| `validate` | Validate LLM setup (check API keys) | - |
|
|
9
10
|
| `debug_call` | Make a debug call and inspect response | `provider`, `message` |
|
|
10
11
|
|
|
12
|
+
## Parameters
|
|
13
|
+
|
|
14
|
+
All parameters are passed at the top level (flat structure):
|
|
15
|
+
|
|
16
|
+
| Parameter | Type | Description |
|
|
17
|
+
|-----------|------|-------------|
|
|
18
|
+
| `command` | string | Command to execute (omit for help) |
|
|
19
|
+
| `provider` | string | LLM provider: anthropic, openai, google, openrouter |
|
|
20
|
+
| `message` | string | Message to send to the LLM provider |
|
|
21
|
+
| `model` | string | Model to use (provider-specific, e.g., gpt-4, claude-3-sonnet) |
|
|
22
|
+
|
|
11
23
|
## Providers
|
|
12
24
|
|
|
13
25
|
Supported providers: `openai`, `anthropic`, `gemini`, `openrouter`
|
|
@@ -18,14 +30,20 @@ Supported providers: `openai`, `anthropic`, `gemini`, `openrouter`
|
|
|
18
30
|
|----------|-------------|
|
|
19
31
|
| `OPENAI_API_KEY` | OpenAI API key |
|
|
20
32
|
| `ANTHROPIC_API_KEY` | Anthropic API key |
|
|
21
|
-
| `GOOGLE_API_KEY` | Google/Gemini API key |
|
|
33
|
+
| `GOOGLE_API_KEY` or `GEMINI_API_KEY` | Google/Gemini API key |
|
|
22
34
|
| `OPENROUTER_API_KEY` | OpenRouter API key |
|
|
23
35
|
|
|
24
36
|
## Examples
|
|
25
37
|
|
|
26
38
|
```
|
|
27
|
-
|
|
28
|
-
llm(
|
|
39
|
+
# Debug OpenAI call
|
|
40
|
+
llm({ command: "debug_call", provider: "openai", message: "Hello, world!" })
|
|
41
|
+
|
|
42
|
+
# Debug with specific model
|
|
43
|
+
llm({ command: "debug_call", provider: "openai", model: "o3-mini", message: "What is 15 * 17? Think step by step." })
|
|
44
|
+
|
|
45
|
+
# Debug Anthropic call
|
|
46
|
+
llm({ command: "debug_call", provider: "anthropic", message: "Explain quantum computing" })
|
|
29
47
|
```
|
|
30
48
|
|
|
31
49
|
## Response Fields
|
|
@@ -1,11 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
interface LlmInput {
|
|
3
|
-
message?: string;
|
|
4
|
-
model?: string;
|
|
5
|
-
provider?: LlmProvider;
|
|
6
|
-
}
|
|
7
|
-
export declare const llmService: import("@jaypie/fabric").Service<{
|
|
8
|
-
command?: string;
|
|
9
|
-
input?: LlmInput;
|
|
10
|
-
}, string | import("./llm.js").LlmDebugCallResult, string | import("./llm.js").LlmDebugCallResult>;
|
|
1
|
+
export declare const llmService: import("@jaypie/fabric").Service<Record<string, unknown>, string | import("./llm.js").LlmDebugCallResult | import("./llm.js").LlmValidationResult, string | import("./llm.js").LlmDebugCallResult | import("./llm.js").LlmValidationResult>;
|
|
11
2
|
export * from "./llm.js";
|
package/dist/suites/llm/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { fabricService } from '@jaypie/fabric';
|
|
|
2
2
|
import * as fs from 'node:fs/promises';
|
|
3
3
|
import * as path from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
|
-
import { debugLlmCall } from './llm.js';
|
|
5
|
+
import { debugLlmCall, validateLlmSetup } from './llm.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* LLM Suite - Unified LLM debugging and inspection
|
|
@@ -25,18 +25,32 @@ const llmService = fabricService({
|
|
|
25
25
|
required: false,
|
|
26
26
|
type: String,
|
|
27
27
|
},
|
|
28
|
-
|
|
29
|
-
description: "
|
|
28
|
+
message: {
|
|
29
|
+
description: "Message to send to the LLM provider",
|
|
30
30
|
required: false,
|
|
31
|
-
type:
|
|
31
|
+
type: String,
|
|
32
|
+
},
|
|
33
|
+
model: {
|
|
34
|
+
description: "Model to use (provider-specific, e.g., gpt-4, claude-3-sonnet)",
|
|
35
|
+
required: false,
|
|
36
|
+
type: String,
|
|
37
|
+
},
|
|
38
|
+
provider: {
|
|
39
|
+
description: "LLM provider: anthropic, openai, google, openrouter",
|
|
40
|
+
required: false,
|
|
41
|
+
type: String,
|
|
32
42
|
},
|
|
33
43
|
},
|
|
34
|
-
service: async (
|
|
44
|
+
service: async (params) => {
|
|
45
|
+
const { command } = params;
|
|
35
46
|
if (!command || command === "help") {
|
|
36
47
|
return getHelp();
|
|
37
48
|
}
|
|
38
|
-
const p = params
|
|
49
|
+
const p = params;
|
|
39
50
|
switch (command) {
|
|
51
|
+
case "validate": {
|
|
52
|
+
return validateLlmSetup();
|
|
53
|
+
}
|
|
40
54
|
case "debug_call": {
|
|
41
55
|
if (!p.provider)
|
|
42
56
|
throw new Error("provider is required");
|
|
@@ -57,5 +71,5 @@ const llmService = fabricService({
|
|
|
57
71
|
},
|
|
58
72
|
});
|
|
59
73
|
|
|
60
|
-
export { debugLlmCall, llmService };
|
|
74
|
+
export { debugLlmCall, llmService, validateLlmSetup };
|
|
61
75
|
//# sourceMappingURL=index.js.map
|