@qodalis/mcp-cli 0.1.0 → 0.2.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 (42) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +137 -26
  3. package/dist/src/cli.js +21 -11
  4. package/dist/src/cli.js.map +1 -1
  5. package/dist/src/config.d.ts +10 -6
  6. package/dist/src/config.d.ts.map +1 -1
  7. package/dist/src/config.js +25 -6
  8. package/dist/src/config.js.map +1 -1
  9. package/dist/src/dev/api.d.ts +94 -0
  10. package/dist/src/dev/api.d.ts.map +1 -0
  11. package/dist/src/dev/api.js +425 -0
  12. package/dist/src/dev/api.js.map +1 -0
  13. package/dist/src/dev/docs.d.ts +93 -0
  14. package/dist/src/dev/docs.d.ts.map +1 -0
  15. package/dist/src/dev/docs.js +275 -0
  16. package/dist/src/dev/docs.js.map +1 -0
  17. package/dist/src/dev/prompts.d.ts +11 -0
  18. package/dist/src/dev/prompts.d.ts.map +1 -0
  19. package/dist/src/dev/prompts.js +141 -0
  20. package/dist/src/dev/prompts.js.map +1 -0
  21. package/dist/src/dev/scaffold.d.ts +55 -0
  22. package/dist/src/dev/scaffold.d.ts.map +1 -0
  23. package/dist/src/dev/scaffold.js +213 -0
  24. package/dist/src/dev/scaffold.js.map +1 -0
  25. package/dist/src/dev/tools.d.ts +170 -0
  26. package/dist/src/dev/tools.d.ts.map +1 -0
  27. package/dist/src/dev/tools.js +258 -0
  28. package/dist/src/dev/tools.js.map +1 -0
  29. package/dist/src/index.d.ts +7 -2
  30. package/dist/src/index.d.ts.map +1 -1
  31. package/dist/src/index.js +6 -1
  32. package/dist/src/index.js.map +1 -1
  33. package/dist/src/remote.d.ts +3 -1
  34. package/dist/src/remote.d.ts.map +1 -1
  35. package/dist/src/remote.js +17 -10
  36. package/dist/src/remote.js.map +1 -1
  37. package/dist/src/server.d.ts +11 -2
  38. package/dist/src/server.d.ts.map +1 -1
  39. package/dist/src/server.js +85 -15
  40. package/dist/src/server.js.map +1 -1
  41. package/docs/llms-full.txt +1740 -0
  42. package/package.json +7 -4
@@ -0,0 +1,275 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { fileURLToPath } from 'node:url';
3
+ /**
4
+ * The plugin-development guide (`llms-full.txt`): plain markdown with a
5
+ * `# Qodalis CLI plugin development` title, `## ` sections and `### ` topics,
6
+ * each topic self-contained and starting with a one-line summary.
7
+ */
8
+ export const DOCS_TITLE = '# Qodalis CLI plugin development';
9
+ /** How long fetched docs are reused before they are fetched again. */
10
+ export const DOCS_TTL_MS = 60 * 60_000;
11
+ /** After a failed download the URL is tried again after this long. */
12
+ export const DOCS_RETRY_MS = 5 * 60_000;
13
+ const FETCH_TIMEOUT_MS = 10_000;
14
+ export const slugify = (text) => text
15
+ .toLowerCase()
16
+ .replace(/[`'"]/g, '')
17
+ .replace(/[^a-z0-9]+/g, '-')
18
+ .replace(/^-+|-+$/g, '') || 'untitled';
19
+ const FENCE = /^\s*(```|~~~)/;
20
+ /** First prose line of a block: skips blank lines, code fences, tables and nested headings. */
21
+ const firstProseLine = (lines) => {
22
+ let inFence = false;
23
+ for (const line of lines) {
24
+ if (FENCE.test(line)) {
25
+ inFence = !inFence;
26
+ continue;
27
+ }
28
+ const trimmed = line.trim();
29
+ if (inFence || !trimmed || trimmed.startsWith('#') || trimmed.startsWith('|')) {
30
+ continue;
31
+ }
32
+ return trimmed.replace(/^[-*>]\s+/, '');
33
+ }
34
+ return '';
35
+ };
36
+ /** Splits the guide into `## ` sections and `### ` topics; headings inside code fences are ignored. */
37
+ export const parseDocs = (markdown, source = 'inline') => {
38
+ const lines = markdown.replace(/\r\n/g, '\n').split('\n');
39
+ const sections = [];
40
+ let section;
41
+ let topic;
42
+ const closed = [];
43
+ let inFence = false;
44
+ for (const line of lines) {
45
+ if (FENCE.test(line)) {
46
+ inFence = !inFence;
47
+ }
48
+ const h2 = !inFence && /^##\s+(.+?)\s*#*\s*$/.exec(line);
49
+ const h3 = !inFence && !h2 && /^###\s+(.+?)\s*#*\s*$/.exec(line);
50
+ if (h2 && !line.startsWith('###')) {
51
+ if (section) {
52
+ closed.push(section);
53
+ }
54
+ section = { lines: [line], title: h2[1], topics: [] };
55
+ topic = undefined;
56
+ continue;
57
+ }
58
+ if (h3 && section) {
59
+ topic = { lines: [line], section: section.title, title: h3[1] };
60
+ section.topics.push(topic);
61
+ section.lines.push(line);
62
+ continue;
63
+ }
64
+ section?.lines.push(line);
65
+ topic?.lines.push(line);
66
+ }
67
+ if (section) {
68
+ closed.push(section);
69
+ }
70
+ const sectionSlugs = new Set();
71
+ for (const open of closed) {
72
+ let slug = slugify(open.title);
73
+ for (let n = 2; sectionSlugs.has(slug); n++) {
74
+ slug = `${slugify(open.title)}-${n}`;
75
+ }
76
+ sectionSlugs.add(slug);
77
+ const topicSlugs = new Set();
78
+ const topics = open.topics.map((t) => {
79
+ let topicSlug = slugify(t.title);
80
+ for (let n = 2; topicSlugs.has(topicSlug); n++) {
81
+ topicSlug = `${slugify(t.title)}-${n}`;
82
+ }
83
+ topicSlugs.add(topicSlug);
84
+ return {
85
+ content: t.lines.join('\n').trim(),
86
+ section: open.title,
87
+ summary: firstProseLine(t.lines.slice(1)),
88
+ title: t.title,
89
+ uri: `${slug}/${topicSlug}`,
90
+ };
91
+ });
92
+ sections.push({ content: open.lines.join('\n').trim(), slug, title: open.title, topics });
93
+ }
94
+ return { sections, source, topics: sections.flatMap((s) => s.topics) };
95
+ };
96
+ const STOP_WORDS = new Set('a an and are as at be by can do does for from how i in is it my of on or the to use using what when with'.split(' '));
97
+ /** Lower-case search terms; `ICliModule`, `read-line` and `readLine` all stay searchable. */
98
+ export const searchTerms = (query) => [
99
+ ...new Set(query
100
+ .toLowerCase()
101
+ .split(/[^a-z0-9_.@/-]+/)
102
+ .map((term) => term.replace(/^[-./]+|[-./]+$/g, ''))
103
+ .filter((term) => term.length > 1 && !STOP_WORDS.has(term))),
104
+ ];
105
+ const countOccurrences = (haystack, needle) => {
106
+ let count = 0;
107
+ for (let i = haystack.indexOf(needle); i !== -1; i = haystack.indexOf(needle, i + needle.length)) {
108
+ count++;
109
+ }
110
+ return count;
111
+ };
112
+ /** A ~200-character line around the first body match. */
113
+ const excerptFor = (topic, terms) => {
114
+ const lines = topic.content.split('\n').slice(1);
115
+ const line = lines.find((l) => terms.some((t) => l.toLowerCase().includes(t)) && l.trim()) ?? '';
116
+ const trimmed = line.trim();
117
+ if (trimmed.length <= 200) {
118
+ return trimmed;
119
+ }
120
+ const at = Math.max(0, Math.min(...terms.map((t) => trimmed.toLowerCase().indexOf(t)).filter((i) => i >= 0)) - 60);
121
+ return `${at > 0 ? '…' : ''}${trimmed.slice(at, at + 200)}…`;
122
+ };
123
+ /**
124
+ * Keyword ranking over topics: a term in the title weighs most, then the summary and
125
+ * the section name, then occurrences in the body (capped); every matched term and an
126
+ * exact phrase match add a bonus, so topics covering the whole query come first.
127
+ */
128
+ export const searchDocs = (docs, query, limit = 5) => {
129
+ const terms = searchTerms(query);
130
+ if (terms.length === 0) {
131
+ return [];
132
+ }
133
+ const phrase = query.trim().toLowerCase();
134
+ const hits = [];
135
+ for (const topic of docs.topics) {
136
+ const title = topic.title.toLowerCase();
137
+ const summary = topic.summary.toLowerCase();
138
+ const section = topic.section.toLowerCase();
139
+ const body = topic.content.toLowerCase();
140
+ let score = 0;
141
+ let matched = 0;
142
+ for (const term of terms) {
143
+ const inBody = countOccurrences(body, term);
144
+ if (inBody === 0) {
145
+ continue;
146
+ }
147
+ matched++;
148
+ score += title.includes(term) ? 10 : 0;
149
+ score += summary.includes(term) ? 4 : 0;
150
+ score += section.includes(term) ? 2 : 0;
151
+ score += Math.min(inBody, 6);
152
+ }
153
+ if (matched === 0) {
154
+ continue;
155
+ }
156
+ score += (matched - 1) * 5;
157
+ score += phrase.length > 3 && body.includes(phrase) ? 8 : 0;
158
+ hits.push({ excerpt: excerptFor(topic, terms), score, topic });
159
+ }
160
+ return hits
161
+ .sort((a, b) => b.score - a.score || a.topic.uri.localeCompare(b.topic.uri))
162
+ .slice(0, Math.max(1, limit));
163
+ };
164
+ const normalize = (text) => text.toLowerCase().replace(/[`*_]/g, '').replace(/\s+/g, ' ').trim();
165
+ /**
166
+ * A topic by heading (case-insensitive), `Section › Topic`, `Section/Topic` or its
167
+ * resource path; a whole `## ` section by its heading; else a unique partial match.
168
+ */
169
+ export const readDocs = (docs, query) => {
170
+ const wanted = normalize(query.replace(/^qcli-docs:\/\//, ''));
171
+ if (!wanted) {
172
+ return { kind: 'not-found' };
173
+ }
174
+ const byUri = docs.topics.find((t) => t.uri === wanted);
175
+ if (byUri) {
176
+ return { kind: 'topics', topics: [byUri] };
177
+ }
178
+ const qualified = /^(.+?)\s*(?:›|>|\/|::)\s*(.+)$/.exec(wanted);
179
+ if (qualified) {
180
+ const [, sectionName, topicName] = qualified;
181
+ const found = docs.topics.filter((t) => (normalize(t.section) === sectionName || slugify(t.section) === sectionName) &&
182
+ (normalize(t.title) === topicName || slugify(t.title) === topicName));
183
+ if (found.length > 0) {
184
+ return { kind: 'topics', topics: found };
185
+ }
186
+ }
187
+ const exact = docs.topics.filter((t) => normalize(t.title) === wanted);
188
+ if (exact.length > 0) {
189
+ return { kind: 'topics', topics: exact };
190
+ }
191
+ const section = docs.sections.find((s) => normalize(s.title) === wanted || s.slug === wanted);
192
+ if (section) {
193
+ return { kind: 'section', section };
194
+ }
195
+ const partial = docs.topics.filter((t) => normalize(t.title).includes(wanted));
196
+ if (partial.length === 1) {
197
+ return { kind: 'topics', topics: partial };
198
+ }
199
+ return { kind: 'not-found' };
200
+ };
201
+ /** `Section › Topic` lines, grouped by section, for "not found" answers. */
202
+ export const listTopics = (docs) => docs.sections
203
+ .map((s) => `## ${s.title}\n${s.topics.map((t) => `- ${t.title}${t.summary ? `: ${t.summary}` : ''}`).join('\n')}`)
204
+ .join('\n\n');
205
+ /** The `docs/llms-full.txt` bundled with the package (one or two levels above this file). */
206
+ export const readBundledDocs = () => {
207
+ for (const candidate of ['../../docs/llms-full.txt', '../../../docs/llms-full.txt']) {
208
+ try {
209
+ return readFileSync(fileURLToPath(new URL(candidate, import.meta.url)), 'utf8');
210
+ }
211
+ catch {
212
+ // try the next location
213
+ }
214
+ }
215
+ throw new Error('The bundled docs snapshot (docs/llms-full.txt) is missing.');
216
+ };
217
+ /**
218
+ * The guide from `url` (cached for {@link DOCS_TTL_MS}), falling back to the last good
219
+ * download and then to the bundled snapshot, so the tools work offline and before the
220
+ * site publishes the file. A response that is not the guide (an HTML page) is ignored.
221
+ */
222
+ export class DocsSource {
223
+ options;
224
+ cached;
225
+ downloaded;
226
+ loading;
227
+ snapshotDocs;
228
+ constructor(options) {
229
+ this.options = options;
230
+ }
231
+ async get() {
232
+ const now = (this.options.now ?? Date.now)();
233
+ if (this.cached && now < this.cached.expires) {
234
+ return this.cached.docs;
235
+ }
236
+ this.loading ??= this.load(now).finally(() => (this.loading = undefined));
237
+ return this.loading;
238
+ }
239
+ async load(now) {
240
+ const { url } = this.options;
241
+ try {
242
+ const response = await (this.options.fetch ?? fetch)(url, {
243
+ headers: { accept: 'text/plain, text/markdown;q=0.9, */*;q=0.1' },
244
+ signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
245
+ });
246
+ if (!response.ok) {
247
+ throw new Error(`HTTP ${response.status}`);
248
+ }
249
+ const text = await response.text();
250
+ if (!text.trimStart().startsWith(DOCS_TITLE)) {
251
+ throw new Error(`not the plugin-development guide (expected "${DOCS_TITLE}")`);
252
+ }
253
+ this.downloaded = parseDocs(text, url);
254
+ this.cached = {
255
+ docs: this.downloaded,
256
+ expires: now + (this.options.ttlMs ?? DOCS_TTL_MS),
257
+ };
258
+ return this.downloaded;
259
+ }
260
+ catch (error) {
261
+ const reason = error instanceof Error ? error.message : String(error);
262
+ let docs = this.downloaded;
263
+ if (docs) {
264
+ this.options.log?.(`docs: ${url} failed (${reason}); reusing the last download`);
265
+ }
266
+ else {
267
+ this.options.log?.(`docs: ${url} failed (${reason}); using the bundled snapshot`);
268
+ docs = this.snapshotDocs ??= parseDocs((this.options.snapshot ?? readBundledDocs)(), 'bundled snapshot');
269
+ }
270
+ this.cached = { docs, expires: now + DOCS_RETRY_MS };
271
+ return docs;
272
+ }
273
+ }
274
+ }
275
+ //# sourceMappingURL=docs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs.js","sourceRoot":"","sources":["../../../src/dev/docs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { GetPromptResult, Prompt } from '@modelcontextprotocol/server';
2
+ /** MCP prompts that walk an assistant through plugin work with the `qcli_*` tools. */
3
+ export declare const PROMPTS: Prompt[];
4
+ export declare class PromptError extends Error {
5
+ }
6
+ export type PromptContext = {
7
+ /** qcli_scaffold_plugin is available (not read-only, not filtered out) */
8
+ canScaffold: boolean;
9
+ };
10
+ export declare const getPrompt: (name: string, args: Record<string, string> | undefined, ctx: PromptContext) => GetPromptResult;
11
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../src/dev/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAE5E,sFAAsF;AACtF,eAAO,MAAM,OAAO,EAAE,MAAM,EAqC3B,CAAC;AAEF,qBAAa,WAAY,SAAQ,KAAK;CAAG;AA+CzC,MAAM,MAAM,aAAa,GAAG;IACxB,0EAA0E;IAC1E,WAAW,EAAE,OAAO,CAAC;CACxB,CAAC;AAoEF,eAAO,MAAM,SAAS,GAClB,MAAM,MAAM,EACZ,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EACxC,KAAK,aAAa,KACnB,eASF,CAAC"}
@@ -0,0 +1,141 @@
1
+ /** MCP prompts that walk an assistant through plugin work with the `qcli_*` tools. */
2
+ export const PROMPTS = [
3
+ {
4
+ arguments: [
5
+ {
6
+ description: 'Plugin name: lowercase letters, digits and hyphens (e.g. "weather")',
7
+ name: 'name',
8
+ required: true,
9
+ },
10
+ {
11
+ description: 'One-line description of the plugin',
12
+ name: 'description',
13
+ required: true,
14
+ },
15
+ ],
16
+ description: 'Create a Qodalis web CLI plugin (a command for the browser terminal): scaffold, implement, test and register it.',
17
+ name: 'create-web-plugin',
18
+ title: 'Create a web CLI plugin',
19
+ },
20
+ {
21
+ arguments: [
22
+ {
23
+ description: 'Server language: node, dotnet or python',
24
+ name: 'language',
25
+ required: true,
26
+ },
27
+ {
28
+ description: 'Command name as typed in the terminal (e.g. "weather")',
29
+ name: 'command',
30
+ required: true,
31
+ },
32
+ ],
33
+ description: 'Add a command to a Qodalis CLI server (Node, .NET or Python) that the web terminal runs remotely.',
34
+ name: 'create-server-command',
35
+ title: 'Create a server command',
36
+ },
37
+ ];
38
+ export class PromptError extends Error {
39
+ }
40
+ const SERVER_LANGUAGES = {
41
+ dotnet: {
42
+ base: 'CliCommandProcessor (Qodalis.Cli) implementing ICliCommandProcessor from Qodalis.Cli.Abstractions',
43
+ handler: 'HandleAsync(CliProcessCommand command, CancellationToken cancellationToken)',
44
+ docs: '.NET',
45
+ label: '.NET',
46
+ register: 'register it in Program.cs: `builder.Services.AddCli(cli => cli.AddProcessor<YourProcessor>())` (or group several in a module with `cli.AddModule(...)`)',
47
+ test: '`dotnet build` and `dotnet test`',
48
+ },
49
+ node: {
50
+ base: 'CliCommandProcessor from @qodalis/cli-server-abstractions',
51
+ handler: 'handleAsync(command: CliProcessCommand, signal?: AbortSignal): Promise<string>',
52
+ docs: 'Node',
53
+ label: 'Node.js',
54
+ register: 'register it with the builder returned by createCliServer(): `builder.addProcessor(new YourProcessor())` (or `builder.addModule(...)`)',
55
+ test: '`npm run build` and `npm test` (vitest)',
56
+ },
57
+ python: {
58
+ base: 'CliCommandProcessor from qodalis_cli_server_abstractions',
59
+ handler: 'async def handle_async(self, command: CliProcessCommand, cancellation_event: asyncio.Event | None = None) -> str',
60
+ docs: 'Python',
61
+ label: 'Python',
62
+ register: 'register it with the builder of create_cli_server(): `builder.add_processor(YourProcessor())` (or `builder.add_module(...)`)',
63
+ test: '`pytest`',
64
+ },
65
+ };
66
+ const required = (args, name) => {
67
+ const value = args?.[name]?.trim();
68
+ if (!value) {
69
+ throw new PromptError(`Missing required argument "${name}".`);
70
+ }
71
+ return value;
72
+ };
73
+ const message = (text) => ({
74
+ messages: [{ content: { text, type: 'text' }, role: 'user' }],
75
+ });
76
+ const webPlugin = (args, ctx) => {
77
+ const name = required(args, 'name');
78
+ const description = required(args, 'description');
79
+ const scaffold = ctx.canScaffold
80
+ ? `Call \`qcli_scaffold_plugin\` with { "name": "${name}", "description": "${description}" } (add "directory" if the plugin should not go in the current project). Inside a web-cli checkout it creates packages/plugins/${name}; elsewhere a standalone qodalis-cli-${name} project. Read the files it reports.`
81
+ : `qcli_scaffold_plugin is not available in this session (read-only or filtered). Ask the user to run \`npx -y @qodalis/create-cli-plugin@latest --name ${name} --description "${description}"\` and continue once it has created the project.`;
82
+ return {
83
+ description: `Create the "${name}" web CLI plugin`,
84
+ ...message([
85
+ `Create a Qodalis web CLI plugin named "${name}": ${description}.`,
86
+ '',
87
+ 'Work through these steps, using the qcli_* tools rather than guessing APIs:',
88
+ '',
89
+ '1. Learn the plugin model: `qcli_docs_read` with "Recipe: a complete web plugin end to end", then `qcli_docs_search` for anything specific to this plugin (parameters, input reader, writer API, state store, services, translations). `qcli_docs_read` with "Web plugins" returns the whole section.',
90
+ '2. Look up the exact contracts with `qcli_api`: ICliCommandProcessor, CliProcessCommand, ICliExecutionContext, ICliModule, and ICliInputReader if the command asks the user anything. Use the "Related declarations" it lists to go deeper. Do not invent members that are not in the declarations.',
91
+ `3. ${scaffold}`,
92
+ `4. Implement the command in src/lib/processors/: set command, description and parameters; do the work in processCommand(command, context), writing output through context.writer; use sub-processors (\`processors\`) for sub-commands; honour context.signal for long work. Keep "${name}" as the command name unless the user says otherwise.`,
93
+ '5. Export everything through the module (ICliModule) in the public API, with a version and translations if the docs recommend them.',
94
+ '6. Write tests next to the scaffolded ones (src/tests/*.spec.ts) covering the main paths and invalid input.',
95
+ '7. Build and run the tests (the scaffold result lists the commands), fix every failure, then show the user how to register the module in a host app (`modules` input/prop, or engine.registerModule()).',
96
+ '',
97
+ 'Finish with a short summary: files changed, how to use the command, and anything left to decide.',
98
+ ].join('\n')),
99
+ };
100
+ };
101
+ const serverCommand = (args) => {
102
+ const language = required(args, 'language')
103
+ .toLowerCase()
104
+ .replace(/^\.?net$|^c#$|^csharp$/, 'dotnet');
105
+ const command = required(args, 'command');
106
+ if (!(language in SERVER_LANGUAGES)) {
107
+ throw new PromptError(`Unknown language "${language}": use node, dotnet or python.`);
108
+ }
109
+ if (!/^[a-z][a-z0-9-]*$/.test(command)) {
110
+ throw new PromptError(`Invalid command "${command}": lowercase letters, digits and hyphens, starting with a letter.`);
111
+ }
112
+ const lang = SERVER_LANGUAGES[language];
113
+ return {
114
+ description: `Add the "${command}" command to a ${lang.label} Qodalis CLI server`,
115
+ ...message([
116
+ `Add a "${command}" command to the ${lang.label} Qodalis CLI server in this project. The web terminal discovers server commands and runs them remotely.`,
117
+ '',
118
+ 'Steps (use the qcli_* tools instead of guessing APIs):',
119
+ '',
120
+ `1. Read the guide: \`qcli_docs_read\` with "${lang.docs}: minimal server processor" and "${lang.docs}: parameters, sub-commands and modules" (and "Recipe: a server command used from the browser terminal"); \`qcli_docs_search\` "${lang.docs} structured output", "${lang.docs} permissions" or "${lang.docs} testing" when you need them. If a topic is not found, \`qcli_docs_read\` lists the available ones.`,
121
+ '2. Find where the server is configured in this project (the createCliServer / AddCli / create_cli_server call) and how existing processors are organised; follow the same layout and naming.',
122
+ `3. Create a processor class deriving from ${lang.base}: set command = "${command}", a description, parameters (name, type, required, description) and the version; implement ${lang.handler}. Use sub-processors for sub-commands.`,
123
+ `4. ${lang.register.charAt(0).toUpperCase()}${lang.register.slice(1)}.`,
124
+ `5. Add tests for the processor alongside the existing ones and run ${lang.test}; fix every failure.`,
125
+ '6. If a server is running with MCP enabled and this session is connected to it (QCLI_URL), the new command appears as a tool after a restart: call it to verify. Otherwise tell the user how to start the server and run the command in the web terminal.',
126
+ '',
127
+ 'Finish with a short summary: files changed and how to use the command.',
128
+ ].join('\n')),
129
+ };
130
+ };
131
+ export const getPrompt = (name, args, ctx) => {
132
+ switch (name) {
133
+ case 'create-web-plugin':
134
+ return webPlugin(args, ctx);
135
+ case 'create-server-command':
136
+ return serverCommand(args);
137
+ default:
138
+ throw new PromptError(`Unknown prompt: ${name}`);
139
+ }
140
+ };
141
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../src/dev/prompts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * `qcli_scaffold_plugin`: runs `@qodalis/create-cli-plugin` non-interactively. Inside a
3
+ * web-cli checkout it creates `packages/plugins/<name>`; anywhere else a standalone
4
+ * `qodalis-cli-<name>` project (and installs its dependencies).
5
+ */
6
+ export declare const SCAFFOLD_PACKAGE = "@qodalis/create-cli-plugin@latest";
7
+ export declare const SCAFFOLD_TIMEOUT_MS: number;
8
+ export type ScaffoldArgs = {
9
+ description?: string | undefined;
10
+ directory?: string | undefined;
11
+ name: string;
12
+ processorName?: string | undefined;
13
+ };
14
+ export type ScaffoldPlan = {
15
+ /** Arguments after `npx` */
16
+ args: string[];
17
+ cwd: string;
18
+ monorepo: string | undefined;
19
+ name: string;
20
+ processorName: string;
21
+ /** Where create-cli-plugin will put the plugin */
22
+ target: string;
23
+ };
24
+ export declare class ScaffoldError extends Error {
25
+ constructor(message: string);
26
+ }
27
+ /** The web-cli monorepo root above `dir` (same rule as create-cli-plugin), if any. */
28
+ export declare const detectMonorepo: (dir: string) => string | undefined;
29
+ /** Validates the arguments and works out where the plugin goes; throws {@link ScaffoldError}. */
30
+ export declare const planScaffold: (input: ScaffoldArgs, cwd?: string) => ScaffoldPlan;
31
+ export type RunResult = {
32
+ code: number | null;
33
+ output: string;
34
+ timedOut: boolean;
35
+ };
36
+ export type Runner = (command: string, args: string[], options: {
37
+ cwd: string;
38
+ signal?: AbortSignal | undefined;
39
+ timeoutMs: number;
40
+ }) => Promise<RunResult>;
41
+ /** Runs a command without a TTY, stdin closed, capturing stdout and stderr together. */
42
+ export declare const runCommand: Runner;
43
+ /** Files under `dir`, relative, without node_modules / dist / .git. */
44
+ export declare const listFiles: (dir: string, limit?: number) => string[];
45
+ export type ScaffoldResult = {
46
+ isError: boolean;
47
+ text: string;
48
+ };
49
+ /** Runs create-cli-plugin for a validated plan and describes what it created. */
50
+ export declare const scaffoldPlugin: (plan: ScaffoldPlan, options?: {
51
+ runner?: Runner;
52
+ signal?: AbortSignal | undefined;
53
+ timeoutMs?: number;
54
+ }) => Promise<ScaffoldResult>;
55
+ //# sourceMappingURL=scaffold.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../../src/dev/scaffold.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,sCAAsC,CAAC;AACpE,eAAO,MAAM,mBAAmB,QAAa,CAAC;AAG9C,MAAM,MAAM,YAAY,GAAG;IACvB,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACvB,4BAA4B;IAC5B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,MAAM,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,qBAAa,aAAc,SAAQ,KAAK;gBACxB,OAAO,EAAE,MAAM;CAI9B;AAQD,sFAAsF;AACtF,eAAO,MAAM,cAAc,GAAI,KAAK,MAAM,KAAG,MAAM,GAAG,SAiBrD,CAAC;AAEF,iGAAiG;AACjG,eAAO,MAAM,YAAY,GAAI,OAAO,YAAY,EAAE,YAAmB,KAAG,YA8CvE,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC;AACnF,MAAM,MAAM,MAAM,GAAG,CACjB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,KAC5E,OAAO,CAAC,SAAS,CAAC,CAAC;AAExB,wFAAwF;AACxF,eAAO,MAAM,UAAU,EAAE,MAyDnB,CAAC;AAEP,uEAAuE;AACvE,eAAO,MAAM,SAAS,GAAI,KAAK,MAAM,EAAE,cAAW,KAAG,MAAM,EAsB1D,CAAC;AASF,MAAM,MAAM,cAAc,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhE,iFAAiF;AACjF,eAAO,MAAM,cAAc,GACvB,MAAM,YAAY,EAClB,UAAS;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,KACxF,OAAO,CAAC,cAAc,CAgDxB,CAAC"}