@quanvo99/ai-rules 0.1.3 → 0.1.5
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/README.md +67 -105
- package/dist/cli/commands/generate-questions.d.ts +7 -0
- package/dist/cli/commands/generate-questions.d.ts.map +1 -0
- package/dist/cli/commands/generate-questions.js +120 -0
- package/dist/cli/commands/generate-questions.js.map +1 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +45 -0
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/lib/files.d.ts +8 -0
- package/dist/cli/lib/files.d.ts.map +1 -1
- package/dist/cli/lib/files.js +19 -0
- package/dist/cli/lib/files.js.map +1 -1
- package/dist/cli/lib/github.d.ts +9 -0
- package/dist/cli/lib/github.d.ts.map +1 -1
- package/dist/cli/lib/github.js +20 -0
- package/dist/cli/lib/github.js.map +1 -1
- package/dist/cli/lib/ollama-client.d.ts +66 -0
- package/dist/cli/lib/ollama-client.d.ts.map +1 -0
- package/dist/cli/lib/ollama-client.js +198 -0
- package/dist/cli/lib/ollama-client.js.map +1 -0
- package/dist/cli/lib/question-prompt.d.ts +37 -0
- package/dist/cli/lib/question-prompt.d.ts.map +1 -0
- package/dist/cli/lib/question-prompt.js +204 -0
- package/dist/cli/lib/question-prompt.js.map +1 -0
- package/dist/cli/lib/question-schema.d.ts +84 -0
- package/dist/cli/lib/question-schema.d.ts.map +1 -0
- package/dist/cli/lib/question-schema.js +135 -0
- package/dist/cli/lib/question-schema.js.map +1 -0
- package/dist/cli/lib/question-types.d.ts +72 -0
- package/dist/cli/lib/question-types.d.ts.map +1 -0
- package/dist/cli/lib/question-types.js +28 -0
- package/dist/cli/lib/question-types.js.map +1 -0
- package/dist/cli/lib/types.d.ts +2 -1
- package/dist/cli/lib/types.d.ts.map +1 -1
- package/dist/cli/lib/types.js +1 -0
- package/dist/cli/lib/types.js.map +1 -1
- package/dist/lib/question-types.d.ts +69 -0
- package/dist/lib/question-types.d.ts.map +1 -0
- package/dist/lib/question-types.js +3 -0
- package/dist/lib/question-types.js.map +1 -0
- package/dist/server/types.d.ts +47 -1
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/types.js +2 -1
- package/dist/server/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ollama LLM client for generating questions
|
|
3
|
+
* Handles connection, API calls, and response parsing
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Configuration for Ollama client
|
|
7
|
+
*/
|
|
8
|
+
interface OllamaConfig {
|
|
9
|
+
/** Ollama server URL */
|
|
10
|
+
baseUrl: string;
|
|
11
|
+
/** Default model to use */
|
|
12
|
+
defaultModel: string;
|
|
13
|
+
/** Request timeout in milliseconds */
|
|
14
|
+
timeout: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Error class for Ollama-specific errors
|
|
18
|
+
*/
|
|
19
|
+
export declare class OllamaError extends Error {
|
|
20
|
+
statusCode?: number | undefined;
|
|
21
|
+
constructor(message: string, statusCode?: number | undefined);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Checks if Ollama server is running and accessible
|
|
25
|
+
* @param config - Ollama configuration
|
|
26
|
+
* @returns Promise that resolves to true if server is accessible, false on any error
|
|
27
|
+
*/
|
|
28
|
+
export declare function checkOllamaHealth(config?: OllamaConfig): Promise<boolean>;
|
|
29
|
+
/**
|
|
30
|
+
* Calls Ollama API to generate text
|
|
31
|
+
* @param prompt - The prompt to send to the LLM
|
|
32
|
+
* @param model - Model to use (defaults to config default)
|
|
33
|
+
* @param config - Ollama configuration
|
|
34
|
+
* @returns Promise that resolves to the generated text
|
|
35
|
+
*/
|
|
36
|
+
export declare function callOllama(prompt: string, model?: string, config?: OllamaConfig): Promise<string>;
|
|
37
|
+
/**
|
|
38
|
+
* Extracts JSON from LLM response text
|
|
39
|
+
* Handles cases where LLM returns pure JSON or wraps it in markdown code blocks
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* // Pure JSON object
|
|
43
|
+
* extractJsonFromResponse('{"questions": [{"id": "1", "text": "test"}]}')
|
|
44
|
+
*
|
|
45
|
+
* // Pure JSON array
|
|
46
|
+
* extractJsonFromResponse('[{"id": "1", "text": "test"}]')
|
|
47
|
+
*
|
|
48
|
+
* // JSON in markdown code block
|
|
49
|
+
* extractJsonFromResponse('```json\n{"questions": []}\n```')
|
|
50
|
+
*
|
|
51
|
+
* // JSON with extra text
|
|
52
|
+
* extractJsonFromResponse('Here is the JSON: {"id": "1"}')
|
|
53
|
+
*
|
|
54
|
+
* @param response - Raw response from LLM
|
|
55
|
+
* @returns Extracted JSON string or null if not found
|
|
56
|
+
*/
|
|
57
|
+
export declare function extractJsonFromResponse(response: string): string | null;
|
|
58
|
+
/**
|
|
59
|
+
* Generates questions using Ollama with error handling
|
|
60
|
+
* @param prompt - The prompt to send to the LLM
|
|
61
|
+
* @param model - Model to use (optional)
|
|
62
|
+
* @returns Promise that resolves to the generated JSON string
|
|
63
|
+
*/
|
|
64
|
+
export declare function generateQuestionsWithOllama(prompt: string, model?: string): Promise<string>;
|
|
65
|
+
export {};
|
|
66
|
+
//# sourceMappingURL=ollama-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ollama-client.d.ts","sourceRoot":"","sources":["../../../../src/cli/lib/ollama-client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,UAAU,YAAY;IACrB,wBAAwB;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,2BAA2B;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,sCAAsC;IACtC,OAAO,EAAE,MAAM,CAAC;CAChB;AAoCD;;GAEG;AACH,qBAAa,WAAY,SAAQ,KAAK;IAG7B,UAAU,CAAC,EAAE,MAAM;gBAD1B,OAAO,EAAE,MAAM,EACR,UAAU,CAAC,EAAE,MAAM,YAAA;CAK3B;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,GAAE,YAA6B,GAAG,OAAO,CAAC,OAAO,CAAC,CAkB/F;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC/B,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,EACd,MAAM,GAAE,YAA6B,GACnC,OAAO,CAAC,MAAM,CAAC,CAkDjB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAmDvE;AAED;;;;;GAKG;AACH,wBAAsB,2BAA2B,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBjG"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Ollama LLM client for generating questions
|
|
4
|
+
* Handles connection, API calls, and response parsing
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.OllamaError = void 0;
|
|
8
|
+
exports.checkOllamaHealth = checkOllamaHealth;
|
|
9
|
+
exports.callOllama = callOllama;
|
|
10
|
+
exports.extractJsonFromResponse = extractJsonFromResponse;
|
|
11
|
+
exports.generateQuestionsWithOllama = generateQuestionsWithOllama;
|
|
12
|
+
/**
|
|
13
|
+
* Default configuration
|
|
14
|
+
*/
|
|
15
|
+
const DEFAULT_CONFIG = {
|
|
16
|
+
baseUrl: "http://localhost:11434",
|
|
17
|
+
defaultModel: process.env.OLLAMA_MODEL || "llama3.2",
|
|
18
|
+
timeout: parseInt(process.env.OLLAMA_TIMEOUT || "180000", 10), // 3 minutes default, configurable via env
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Error class for Ollama-specific errors
|
|
22
|
+
*/
|
|
23
|
+
class OllamaError extends Error {
|
|
24
|
+
constructor(message, statusCode) {
|
|
25
|
+
super(message);
|
|
26
|
+
this.statusCode = statusCode;
|
|
27
|
+
this.name = "OllamaError";
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.OllamaError = OllamaError;
|
|
31
|
+
/**
|
|
32
|
+
* Checks if Ollama server is running and accessible
|
|
33
|
+
* @param config - Ollama configuration
|
|
34
|
+
* @returns Promise that resolves to true if server is accessible, false on any error
|
|
35
|
+
*/
|
|
36
|
+
async function checkOllamaHealth(config = DEFAULT_CONFIG) {
|
|
37
|
+
const controller = new AbortController();
|
|
38
|
+
const timeoutId = setTimeout(() => controller.abort(), config.timeout);
|
|
39
|
+
try {
|
|
40
|
+
const response = await fetch(`${config.baseUrl}/api/tags`, {
|
|
41
|
+
method: "GET",
|
|
42
|
+
signal: controller.signal,
|
|
43
|
+
});
|
|
44
|
+
clearTimeout(timeoutId);
|
|
45
|
+
return response.ok;
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
clearTimeout(timeoutId);
|
|
49
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
50
|
+
return false; // Timeout occurred
|
|
51
|
+
}
|
|
52
|
+
return false; // Any other error means server is not accessible
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Calls Ollama API to generate text
|
|
57
|
+
* @param prompt - The prompt to send to the LLM
|
|
58
|
+
* @param model - Model to use (defaults to config default)
|
|
59
|
+
* @param config - Ollama configuration
|
|
60
|
+
* @returns Promise that resolves to the generated text
|
|
61
|
+
*/
|
|
62
|
+
async function callOllama(prompt, model, config = DEFAULT_CONFIG) {
|
|
63
|
+
const modelToUse = model || config.defaultModel;
|
|
64
|
+
const requestBody = {
|
|
65
|
+
model: modelToUse,
|
|
66
|
+
prompt,
|
|
67
|
+
stream: false,
|
|
68
|
+
options: {
|
|
69
|
+
temperature: 0.7,
|
|
70
|
+
max_tokens: 1500,
|
|
71
|
+
top_p: 0.9,
|
|
72
|
+
frequency_penalty: 0.5,
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
const controller = new AbortController();
|
|
76
|
+
const timeoutId = setTimeout(() => {
|
|
77
|
+
controller.abort();
|
|
78
|
+
}, config.timeout);
|
|
79
|
+
let response;
|
|
80
|
+
try {
|
|
81
|
+
response = await fetch(`${config.baseUrl}/api/generate`, {
|
|
82
|
+
method: "POST",
|
|
83
|
+
headers: {
|
|
84
|
+
"Content-Type": "application/json",
|
|
85
|
+
},
|
|
86
|
+
body: JSON.stringify(requestBody),
|
|
87
|
+
signal: controller.signal,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
clearTimeout(timeoutId);
|
|
92
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
93
|
+
throw new OllamaError(`Request timeout after ${config.timeout}ms`);
|
|
94
|
+
}
|
|
95
|
+
throw new OllamaError(`Request failed: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
96
|
+
}
|
|
97
|
+
clearTimeout(timeoutId);
|
|
98
|
+
if (!response.ok) {
|
|
99
|
+
throw new OllamaError(`HTTP ${response.status}: ${response.statusText}`, response.status);
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
const data = (await response.json());
|
|
103
|
+
return data.response;
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
throw new OllamaError(`Failed to parse JSON response: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Extracts JSON from LLM response text
|
|
111
|
+
* Handles cases where LLM returns pure JSON or wraps it in markdown code blocks
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* // Pure JSON object
|
|
115
|
+
* extractJsonFromResponse('{"questions": [{"id": "1", "text": "test"}]}')
|
|
116
|
+
*
|
|
117
|
+
* // Pure JSON array
|
|
118
|
+
* extractJsonFromResponse('[{"id": "1", "text": "test"}]')
|
|
119
|
+
*
|
|
120
|
+
* // JSON in markdown code block
|
|
121
|
+
* extractJsonFromResponse('```json\n{"questions": []}\n```')
|
|
122
|
+
*
|
|
123
|
+
* // JSON with extra text
|
|
124
|
+
* extractJsonFromResponse('Here is the JSON: {"id": "1"}')
|
|
125
|
+
*
|
|
126
|
+
* @param response - Raw response from LLM
|
|
127
|
+
* @returns Extracted JSON string or null if not found
|
|
128
|
+
*/
|
|
129
|
+
function extractJsonFromResponse(response) {
|
|
130
|
+
// Trim whitespace first
|
|
131
|
+
const trimmed = response.trim();
|
|
132
|
+
// Case 1: Response is pure JSON (starts and ends with {})
|
|
133
|
+
if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
|
|
134
|
+
try {
|
|
135
|
+
// Try to parse to validate it's valid JSON
|
|
136
|
+
JSON.parse(trimmed);
|
|
137
|
+
return trimmed;
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
// Not valid JSON, continue to other methods
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// Case 2: Response is pure JSON array (starts and ends with [])
|
|
144
|
+
if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
|
145
|
+
try {
|
|
146
|
+
// Try to parse to validate it's valid JSON
|
|
147
|
+
JSON.parse(trimmed);
|
|
148
|
+
return trimmed;
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
// Not valid JSON, continue to other methods
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// Case 3: JSON wrapped in markdown code blocks
|
|
155
|
+
const codeBlockMatch = response.match(/```(?:json)?\s*(\{[\s\S]*?\})\s*```/);
|
|
156
|
+
if (codeBlockMatch) {
|
|
157
|
+
return codeBlockMatch[1] ?? null;
|
|
158
|
+
}
|
|
159
|
+
// Case 4: JSON array wrapped in markdown code blocks
|
|
160
|
+
const arrayCodeBlockMatch = response.match(/```(?:json)?\s*(\[[\s\S]*?\])\s*```/);
|
|
161
|
+
if (arrayCodeBlockMatch) {
|
|
162
|
+
return arrayCodeBlockMatch[1] ?? null;
|
|
163
|
+
}
|
|
164
|
+
// Case 5: Find JSON object anywhere in the text (fallback)
|
|
165
|
+
const jsonObjectMatch = response.match(/\{[\s\S]*\}/);
|
|
166
|
+
if (jsonObjectMatch) {
|
|
167
|
+
return jsonObjectMatch[0] ?? null;
|
|
168
|
+
}
|
|
169
|
+
// Case 6: Find JSON array anywhere in the text (fallback)
|
|
170
|
+
const jsonArrayMatch = response.match(/\[[\s\S]*\]/);
|
|
171
|
+
if (jsonArrayMatch) {
|
|
172
|
+
return jsonArrayMatch[0] ?? null;
|
|
173
|
+
}
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Generates questions using Ollama with error handling
|
|
178
|
+
* @param prompt - The prompt to send to the LLM
|
|
179
|
+
* @param model - Model to use (optional)
|
|
180
|
+
* @returns Promise that resolves to the generated JSON string
|
|
181
|
+
*/
|
|
182
|
+
async function generateQuestionsWithOllama(prompt, model) {
|
|
183
|
+
const isHealthy = await checkOllamaHealth();
|
|
184
|
+
if (!isHealthy) {
|
|
185
|
+
throw new OllamaError("Ollama server is not running or not accessible at http://localhost:11434\n" +
|
|
186
|
+
"Please start Ollama and ensure the server is running.");
|
|
187
|
+
}
|
|
188
|
+
const response = await callOllama(prompt, model);
|
|
189
|
+
const jsonString = extractJsonFromResponse(response);
|
|
190
|
+
if (!jsonString) {
|
|
191
|
+
throw new OllamaError("LLM response does not contain valid JSON.\n" +
|
|
192
|
+
"Response received:\n" +
|
|
193
|
+
response.substring(0, 500) +
|
|
194
|
+
(response.length > 500 ? "..." : ""));
|
|
195
|
+
}
|
|
196
|
+
return jsonString;
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=ollama-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ollama-client.js","sourceRoot":"","sources":["../../../../src/cli/lib/ollama-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompt builder for question generation
|
|
3
|
+
* Reads rule content and builds structured prompts for LLM
|
|
4
|
+
*/
|
|
5
|
+
import type { Manifest } from "../../server/types";
|
|
6
|
+
/**
|
|
7
|
+
* Rule content structure for prompt building
|
|
8
|
+
*/
|
|
9
|
+
interface RuleContent {
|
|
10
|
+
/** Rule manifest metadata */
|
|
11
|
+
manifest: Manifest;
|
|
12
|
+
/** Content of all rule files */
|
|
13
|
+
files: Array<{
|
|
14
|
+
path: string;
|
|
15
|
+
content: string;
|
|
16
|
+
}>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Reads rule content from the repository
|
|
20
|
+
* @param rulePath - The path to the rule directory (e.g., 'rules/cursor/brainstorming')
|
|
21
|
+
* @returns Rule content with manifest and files
|
|
22
|
+
*/
|
|
23
|
+
export declare function readRuleContent(rulePath: string): RuleContent;
|
|
24
|
+
/**
|
|
25
|
+
* Builds context string from rule metadata and content
|
|
26
|
+
* @param ruleContent - Rule content structure
|
|
27
|
+
* @returns Formatted context string for LLM
|
|
28
|
+
*/
|
|
29
|
+
export declare function buildRuleContext(ruleContent: RuleContent): string;
|
|
30
|
+
/**
|
|
31
|
+
* Builds the complete prompt for LLM question generation
|
|
32
|
+
* @param rulePath - The path to the rule directory
|
|
33
|
+
* @returns Complete prompt string
|
|
34
|
+
*/
|
|
35
|
+
export declare function buildQuestionPrompt(rulePath: string): string;
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=question-prompt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"question-prompt.d.ts","sourceRoot":"","sources":["../../../../src/cli/lib/question-prompt.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnD;;GAEG;AACH,UAAU,WAAW;IACpB,6BAA6B;IAC7B,QAAQ,EAAE,QAAQ,CAAC;IACnB,gCAAgC;IAChC,KAAK,EAAE,KAAK,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;CACH;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CA+B7D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,CAcjE;AAmID;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAU5D"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Prompt builder for question generation
|
|
4
|
+
* Reads rule content and builds structured prompts for LLM
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.readRuleContent = readRuleContent;
|
|
8
|
+
exports.buildRuleContext = buildRuleContext;
|
|
9
|
+
exports.buildQuestionPrompt = buildQuestionPrompt;
|
|
10
|
+
const node_fs_1 = require("node:fs");
|
|
11
|
+
const node_path_1 = require("node:path");
|
|
12
|
+
/**
|
|
13
|
+
* Reads rule content from the repository
|
|
14
|
+
* @param rulePath - The path to the rule directory (e.g., 'rules/cursor/brainstorming')
|
|
15
|
+
* @returns Rule content with manifest and files
|
|
16
|
+
*/
|
|
17
|
+
function readRuleContent(rulePath) {
|
|
18
|
+
// Resolve the rule directory path
|
|
19
|
+
const ruleDir = rulePath.startsWith("/") ? rulePath : (0, node_path_1.join)(process.cwd(), rulePath);
|
|
20
|
+
if (!(0, node_fs_1.existsSync)(ruleDir)) {
|
|
21
|
+
throw new Error(`Rule directory not found: ${ruleDir}`);
|
|
22
|
+
}
|
|
23
|
+
// Read manifest
|
|
24
|
+
const manifestPath = (0, node_path_1.join)(ruleDir, "manifest.json");
|
|
25
|
+
if (!(0, node_fs_1.existsSync)(manifestPath)) {
|
|
26
|
+
throw new Error(`Manifest not found: ${manifestPath}`);
|
|
27
|
+
}
|
|
28
|
+
const manifest = JSON.parse((0, node_fs_1.readFileSync)(manifestPath, "utf-8"));
|
|
29
|
+
// Read all rule files
|
|
30
|
+
const files = manifest.files.map((file) => {
|
|
31
|
+
const filePath = (0, node_path_1.join)(ruleDir, file.path);
|
|
32
|
+
if (!(0, node_fs_1.existsSync)(filePath)) {
|
|
33
|
+
throw new Error(`Rule file not found: ${filePath}`);
|
|
34
|
+
}
|
|
35
|
+
const content = (0, node_fs_1.readFileSync)(filePath, "utf-8");
|
|
36
|
+
return {
|
|
37
|
+
path: file.path,
|
|
38
|
+
content,
|
|
39
|
+
};
|
|
40
|
+
});
|
|
41
|
+
return { manifest, files };
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Builds context string from rule metadata and content
|
|
45
|
+
* @param ruleContent - Rule content structure
|
|
46
|
+
* @returns Formatted context string for LLM
|
|
47
|
+
*/
|
|
48
|
+
function buildRuleContext(ruleContent) {
|
|
49
|
+
const { manifest, files } = ruleContent;
|
|
50
|
+
const context = `
|
|
51
|
+
Rule ID: ${manifest.id}
|
|
52
|
+
Category: ${manifest.category}
|
|
53
|
+
Tags: ${manifest.tags.join(", ")}
|
|
54
|
+
Description: ${manifest.description}
|
|
55
|
+
|
|
56
|
+
Rule Content:
|
|
57
|
+
${files.map((file) => `--- ${file.path} ---\n${file.content}`).join("\n\n")}
|
|
58
|
+
`;
|
|
59
|
+
return context.trim();
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* System prompt for question generation
|
|
63
|
+
* Includes instructions, schema, and examples
|
|
64
|
+
*/
|
|
65
|
+
const SYSTEM_PROMPT = `You are a question generation assistant for an AI rules library.
|
|
66
|
+
|
|
67
|
+
Your task: Generate 3-5 questions that identify if developers want/need help from this rule.
|
|
68
|
+
|
|
69
|
+
Context: Questions build context for fuzzy search rule discovery. User describes project → answers questions → keywords added to context → context searches rules.
|
|
70
|
+
|
|
71
|
+
Question Types:
|
|
72
|
+
1. yes-no: Binary questions. Must include "keywords" array (added to search context if user answers yes)
|
|
73
|
+
2. choice: Multiple choice. Must include "options" array with text and keywords for each
|
|
74
|
+
3. open-ended: Free text. Full answer added to search context.
|
|
75
|
+
|
|
76
|
+
All questions MUST include:
|
|
77
|
+
- "id": Unique identifier in kebab-case
|
|
78
|
+
- "text": Clear, concise question text
|
|
79
|
+
- "type": One of: yes-no, choice, open-ended
|
|
80
|
+
- "tags": Array of relevant search tags (technology names, concepts, patterns)
|
|
81
|
+
|
|
82
|
+
Requirements:
|
|
83
|
+
- ALWAYS lead with 1-2 high-level need/intent questions
|
|
84
|
+
- High-level questions should directly ask about wanting/needing help (e.g., "Do you want rules to help with X?")
|
|
85
|
+
- Then follow with specific usage or technical questions
|
|
86
|
+
- Questions can ask about current usage OR needs - both add keywords to context
|
|
87
|
+
- For core technologies (e.g., TypeScript, React, Next.js, Node.js), the FIRST question MUST be a usage-detection yes/no (e.g., "Are you using TypeScript?") when the rule clearly targets that technology
|
|
88
|
+
- Focus on what will help identify if this rule solves their problems
|
|
89
|
+
- Tags should match common terms developers use
|
|
90
|
+
- Keywords should include aliases and variations
|
|
91
|
+
- Keep questions clear and unambiguous
|
|
92
|
+
|
|
93
|
+
Return valid JSON matching this schema:
|
|
94
|
+
{
|
|
95
|
+
"questions": [
|
|
96
|
+
{
|
|
97
|
+
"id": "string (kebab-case, unique)",
|
|
98
|
+
"text": "string (the question)",
|
|
99
|
+
"type": "yes-no | choice | open-ended",
|
|
100
|
+
"tags": ["string", "..."],
|
|
101
|
+
"keywords": ["string", "..."], // for yes-no only
|
|
102
|
+
"options": [ // for choice only
|
|
103
|
+
{ "text": "string", "keywords": ["string", "..."] }
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
Examples:
|
|
110
|
+
|
|
111
|
+
Example for a TypeScript rule (usage detection MUST be first):
|
|
112
|
+
{
|
|
113
|
+
"id": "uses-typescript",
|
|
114
|
+
"text": "Are you using TypeScript?",
|
|
115
|
+
"type": "yes-no",
|
|
116
|
+
"tags": ["typescript", "language", "type-system"],
|
|
117
|
+
"keywords": ["typescript", "ts"]
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
Example for a React hooks rule (usage detection):
|
|
121
|
+
{
|
|
122
|
+
"id": "uses-react-hooks",
|
|
123
|
+
"text": "Are you using React hooks in your project?",
|
|
124
|
+
"type": "yes-no",
|
|
125
|
+
"tags": ["react", "hooks", "frontend"],
|
|
126
|
+
"keywords": ["react", "hooks", "useState", "useEffect"]
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
Example for a CSS framework choice:
|
|
130
|
+
{
|
|
131
|
+
"id": "css-framework",
|
|
132
|
+
"text": "What CSS framework are you using?",
|
|
133
|
+
"type": "choice",
|
|
134
|
+
"tags": ["css", "styling", "framework"],
|
|
135
|
+
"options": [
|
|
136
|
+
{ "text": "Tailwind CSS", "keywords": ["tailwind", "tailwindcss"] },
|
|
137
|
+
{ "text": "styled-components", "keywords": ["styled-components"] },
|
|
138
|
+
{ "text": "CSS Modules", "keywords": ["css-modules"] }
|
|
139
|
+
]
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
Example for a brainstorming rule (high-level need):
|
|
143
|
+
{
|
|
144
|
+
"id": "wants-brainstorming-help",
|
|
145
|
+
"text": "Do you want rules to help you brainstorm and document ideas methodically?",
|
|
146
|
+
"type": "yes-no",
|
|
147
|
+
"tags": ["brainstorming", "problem-solving", "documentation"],
|
|
148
|
+
"keywords": ["brainstorming", "structured-thinking", "documentation", "problem-definition"]
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
Example for open-ended (exploration):
|
|
152
|
+
{
|
|
153
|
+
"id": "project-challenges",
|
|
154
|
+
"text": "What are the main challenges you face in your development process?",
|
|
155
|
+
"type": "open-ended",
|
|
156
|
+
"tags": ["challenges", "problems", "workflow"]
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
Example for a React Server Components rule (usage detection):
|
|
160
|
+
{
|
|
161
|
+
"id": "uses-nextjs-app-router",
|
|
162
|
+
"text": "Are you using Next.js App Router?",
|
|
163
|
+
"type": "yes-no",
|
|
164
|
+
"tags": ["nextjs", "react", "app-router", "server-components"],
|
|
165
|
+
"keywords": ["nextjs", "app-router", "server-components", "next.js"]
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
Example for a React Server Components rule (architecture choice):
|
|
169
|
+
{
|
|
170
|
+
"id": "component-architecture",
|
|
171
|
+
"text": "What component architecture are you using?",
|
|
172
|
+
"type": "choice",
|
|
173
|
+
"tags": ["react", "architecture", "components"],
|
|
174
|
+
"options": [
|
|
175
|
+
{ "text": "Server Components with App Router", "keywords": ["server-components", "app-router", "rsc"] },
|
|
176
|
+
{ "text": "Client Components only", "keywords": ["client-components", "spa"] },
|
|
177
|
+
{ "text": "Pages Router", "keywords": ["pages-router", "getServerSideProps"] }
|
|
178
|
+
]
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
Example for a Server Components rule (need for guidance):
|
|
182
|
+
{
|
|
183
|
+
"id": "needs-server-component-patterns",
|
|
184
|
+
"text": "Do you need help with Server Component patterns and best practices?",
|
|
185
|
+
"type": "yes-no",
|
|
186
|
+
"tags": ["react", "server-components", "patterns", "best-practices"],
|
|
187
|
+
"keywords": ["server-components", "client-server-separation", "data-fetching", "composition"]
|
|
188
|
+
}`;
|
|
189
|
+
/**
|
|
190
|
+
* Builds the complete prompt for LLM question generation
|
|
191
|
+
* @param rulePath - The path to the rule directory
|
|
192
|
+
* @returns Complete prompt string
|
|
193
|
+
*/
|
|
194
|
+
function buildQuestionPrompt(rulePath) {
|
|
195
|
+
const ruleContent = readRuleContent(rulePath);
|
|
196
|
+
const context = buildRuleContext(ruleContent);
|
|
197
|
+
return `${SYSTEM_PROMPT}
|
|
198
|
+
|
|
199
|
+
Rule to analyze:
|
|
200
|
+
${context}
|
|
201
|
+
|
|
202
|
+
Generate 3-5 relevant questions for this rule. Return only valid JSON.`;
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=question-prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"question-prompt.js","sourceRoot":"","sources":["../../../../src/cli/lib/question-prompt.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAwBH,0CA+BC;AAOD,4CAcC;AAwID,kDAUC;AA5ND,qCAAmD;AACnD,yCAAiC;AAgBjC;;;;GAIG;AACH,SAAgB,eAAe,CAAC,QAAgB;IAC/C,kCAAkC;IAClC,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAA,gBAAI,EAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,CAAC;IAEpF,IAAI,CAAC,IAAA,oBAAU,EAAC,OAAO,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,6BAA6B,OAAO,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,gBAAgB;IAChB,MAAM,YAAY,GAAG,IAAA,gBAAI,EAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IACpD,IAAI,CAAC,IAAA,oBAAU,EAAC,YAAY,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,uBAAuB,YAAY,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,QAAQ,GAAa,IAAI,CAAC,KAAK,CAAC,IAAA,sBAAY,EAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC;IAE3E,sBAAsB;IACtB,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACzC,MAAM,QAAQ,GAAG,IAAA,gBAAI,EAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,CAAC,IAAA,oBAAU,EAAC,QAAQ,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,wBAAwB,QAAQ,EAAE,CAAC,CAAC;QACrD,CAAC;QAED,MAAM,OAAO,GAAG,IAAA,sBAAY,EAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAChD,OAAO;YACN,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO;SACP,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAC5B,CAAC;AAED;;;;GAIG;AACH,SAAgB,gBAAgB,CAAC,WAAwB;IACxD,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,WAAW,CAAC;IAExC,MAAM,OAAO,GAAG;WACN,QAAQ,CAAC,EAAE;YACV,QAAQ,CAAC,QAAQ;QACrB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;eACjB,QAAQ,CAAC,WAAW;;;EAGjC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,CAAC,IAAI,SAAS,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;CAC1E,CAAC;IAED,OAAO,OAAO,CAAC,IAAI,EAAE,CAAC;AACvB,CAAC;AAED;;;GAGG;AACH,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2HpB,CAAC;AAEH;;;;GAIG;AACH,SAAgB,mBAAmB,CAAC,QAAgB;IACnD,MAAM,WAAW,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAE9C,OAAO,GAAG,aAAa;;;EAGtB,OAAO;;uEAE8D,CAAC;AACxE,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zod schemas for validating question generation responses
|
|
3
|
+
* Provides type-safe validation with detailed error messages
|
|
4
|
+
*/
|
|
5
|
+
import type { Question, QuestionResponse } from "src/lib/question-types";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
/**
|
|
8
|
+
* Discriminated union schema for all question types
|
|
9
|
+
* Automatically validates based on the 'type' field
|
|
10
|
+
*/
|
|
11
|
+
export declare const QuestionSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
12
|
+
id: z.ZodString;
|
|
13
|
+
text: z.ZodString;
|
|
14
|
+
tags: z.ZodArray<z.ZodString>;
|
|
15
|
+
type: z.ZodLiteral<"yes-no">;
|
|
16
|
+
keywords: z.ZodArray<z.ZodString>;
|
|
17
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
18
|
+
id: z.ZodString;
|
|
19
|
+
text: z.ZodString;
|
|
20
|
+
tags: z.ZodArray<z.ZodString>;
|
|
21
|
+
type: z.ZodLiteral<"choice">;
|
|
22
|
+
options: z.ZodArray<z.ZodObject<{
|
|
23
|
+
text: z.ZodString;
|
|
24
|
+
keywords: z.ZodArray<z.ZodString>;
|
|
25
|
+
}, z.core.$strip>>;
|
|
26
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
27
|
+
id: z.ZodString;
|
|
28
|
+
text: z.ZodString;
|
|
29
|
+
tags: z.ZodArray<z.ZodString>;
|
|
30
|
+
type: z.ZodLiteral<"open-ended">;
|
|
31
|
+
}, z.core.$strip>], "type">;
|
|
32
|
+
/**
|
|
33
|
+
* Schema for the complete response containing questions array
|
|
34
|
+
*/
|
|
35
|
+
export declare const QuestionResponseSchema: z.ZodObject<{
|
|
36
|
+
questions: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
37
|
+
id: z.ZodString;
|
|
38
|
+
text: z.ZodString;
|
|
39
|
+
tags: z.ZodArray<z.ZodString>;
|
|
40
|
+
type: z.ZodLiteral<"yes-no">;
|
|
41
|
+
keywords: z.ZodArray<z.ZodString>;
|
|
42
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
43
|
+
id: z.ZodString;
|
|
44
|
+
text: z.ZodString;
|
|
45
|
+
tags: z.ZodArray<z.ZodString>;
|
|
46
|
+
type: z.ZodLiteral<"choice">;
|
|
47
|
+
options: z.ZodArray<z.ZodObject<{
|
|
48
|
+
text: z.ZodString;
|
|
49
|
+
keywords: z.ZodArray<z.ZodString>;
|
|
50
|
+
}, z.core.$strip>>;
|
|
51
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
52
|
+
id: z.ZodString;
|
|
53
|
+
text: z.ZodString;
|
|
54
|
+
tags: z.ZodArray<z.ZodString>;
|
|
55
|
+
type: z.ZodLiteral<"open-ended">;
|
|
56
|
+
}, z.core.$strip>], "type">>;
|
|
57
|
+
}, z.core.$strip>;
|
|
58
|
+
/**
|
|
59
|
+
* Validates a question response and returns typed result
|
|
60
|
+
* @param data - Raw data to validate
|
|
61
|
+
* @returns Success result with typed data or error details
|
|
62
|
+
*/
|
|
63
|
+
export declare function validateQuestionResponse(data: unknown): {
|
|
64
|
+
success: true;
|
|
65
|
+
data: QuestionResponse;
|
|
66
|
+
} | {
|
|
67
|
+
success: false;
|
|
68
|
+
error: string;
|
|
69
|
+
details?: z.ZodError;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Validates a single question
|
|
73
|
+
* @param data - Raw data to validate
|
|
74
|
+
* @returns Success result with typed question or error details
|
|
75
|
+
*/
|
|
76
|
+
export declare function validateQuestion(data: unknown): {
|
|
77
|
+
success: true;
|
|
78
|
+
data: Question;
|
|
79
|
+
} | {
|
|
80
|
+
success: false;
|
|
81
|
+
error: string;
|
|
82
|
+
details?: z.ZodError;
|
|
83
|
+
};
|
|
84
|
+
//# sourceMappingURL=question-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"question-schema.d.ts","sourceRoot":"","sources":["../../../../src/cli/lib/question-schema.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAsDxB;;;GAGG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;2BAIzB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;iBAKjC,CAAC;AAEH;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,OAAO,GACnD;IACA,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,EAAE,gBAAgB,CAAC;CACtB,GACD;IACA,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC;CACpB,CAyBH;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAC3C;IACA,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;CACd,GACD;IACA,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC;CACpB,CAyBH"}
|