@vfarcic/dot-ai 0.174.0 → 0.176.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.
- package/dist/core/user-prompts-loader.d.ts +66 -0
- package/dist/core/user-prompts-loader.d.ts.map +1 -0
- package/dist/core/user-prompts-loader.js +319 -0
- package/dist/interfaces/rest-api.d.ts +45 -0
- package/dist/interfaces/rest-api.d.ts.map +1 -1
- package/dist/interfaces/rest-api.js +286 -0
- package/dist/tools/prompts.d.ts +21 -3
- package/dist/tools/prompts.d.ts.map +1 -1
- package/dist/tools/prompts.js +166 -26
- package/dist/tools/query.d.ts +13 -0
- package/dist/tools/query.d.ts.map +1 -1
- package/dist/tools/query.js +33 -1
- package/package.json +1 -1
- package/prompts/visualize-query.md +113 -0
- package/shared-prompts/prd-create.md +1 -3
- package/shared-prompts/prd-next.md +6 -6
- package/shared-prompts/prd-start.md +54 -112
- package/shared-prompts/prd-update-progress.md +2 -4
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User Prompts Loader
|
|
3
|
+
*
|
|
4
|
+
* Loads user-defined prompts from a git repository.
|
|
5
|
+
* Supports any git provider (GitHub, GitLab, Gitea, Forgejo, Bitbucket, etc.)
|
|
6
|
+
*
|
|
7
|
+
* Environment variables:
|
|
8
|
+
* - DOT_AI_USER_PROMPTS_REPO: Git repository URL (required to enable)
|
|
9
|
+
* - DOT_AI_USER_PROMPTS_BRANCH: Branch to use (default: main)
|
|
10
|
+
* - DOT_AI_USER_PROMPTS_PATH: Subdirectory within repo (default: root)
|
|
11
|
+
* - DOT_AI_GIT_TOKEN: Authentication token (optional)
|
|
12
|
+
* - DOT_AI_USER_PROMPTS_CACHE_TTL: Cache TTL in seconds (default: 86400 = 24h)
|
|
13
|
+
*/
|
|
14
|
+
import { Logger } from './error-handling';
|
|
15
|
+
import { Prompt } from '../tools/prompts';
|
|
16
|
+
/**
|
|
17
|
+
* Configuration for user prompts repository
|
|
18
|
+
*/
|
|
19
|
+
export interface UserPromptsConfig {
|
|
20
|
+
repoUrl: string;
|
|
21
|
+
branch: string;
|
|
22
|
+
subPath: string;
|
|
23
|
+
gitToken?: string;
|
|
24
|
+
cacheTtlSeconds: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Cache state for tracking repository freshness
|
|
28
|
+
*/
|
|
29
|
+
interface CacheState {
|
|
30
|
+
lastPullTime: number;
|
|
31
|
+
localPath: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Read user prompts configuration from environment variables
|
|
35
|
+
* Returns null if DOT_AI_USER_PROMPTS_REPO is not set
|
|
36
|
+
*/
|
|
37
|
+
export declare function getUserPromptsConfig(): UserPromptsConfig | null;
|
|
38
|
+
/**
|
|
39
|
+
* Get the cache directory for user prompts
|
|
40
|
+
* Tries project-relative tmp first, falls back to system temp
|
|
41
|
+
*/
|
|
42
|
+
export declare function getCacheDirectory(): string;
|
|
43
|
+
/**
|
|
44
|
+
* Insert authentication token into git URL
|
|
45
|
+
* Works with any HTTPS git URL (GitHub, GitLab, Gitea, Bitbucket, etc.)
|
|
46
|
+
*/
|
|
47
|
+
export declare function insertTokenInUrl(url: string, token: string): string;
|
|
48
|
+
/**
|
|
49
|
+
* Sanitize URL for logging (remove credentials)
|
|
50
|
+
*/
|
|
51
|
+
export declare function sanitizeUrlForLogging(url: string): string;
|
|
52
|
+
/**
|
|
53
|
+
* Load user prompts from the configured git repository
|
|
54
|
+
* Returns empty array if not configured or on error
|
|
55
|
+
*/
|
|
56
|
+
export declare function loadUserPrompts(logger: Logger, forceRefresh?: boolean): Promise<Prompt[]>;
|
|
57
|
+
/**
|
|
58
|
+
* Clear the cache state (useful for testing)
|
|
59
|
+
*/
|
|
60
|
+
export declare function clearUserPromptsCache(): void;
|
|
61
|
+
/**
|
|
62
|
+
* Get current cache state (for testing/debugging)
|
|
63
|
+
*/
|
|
64
|
+
export declare function getUserPromptsCacheState(): CacheState | null;
|
|
65
|
+
export {};
|
|
66
|
+
//# sourceMappingURL=user-prompts-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-prompts-loader.d.ts","sourceRoot":"","sources":["../../src/core/user-prompts-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,OAAO,EAAE,MAAM,EAAkB,MAAM,kBAAkB,CAAC;AAE1D;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,UAAU,UAAU;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAKD;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,iBAAiB,GAAG,IAAI,CAkB/D;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAqB1C;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CASnE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAUzD;AAmJD;;;GAGG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,YAAY,GAAE,OAAe,GAC5B,OAAO,CAAC,MAAM,EAAE,CAAC,CAmDnB;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,UAAU,GAAG,IAAI,CAE5D"}
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* User Prompts Loader
|
|
4
|
+
*
|
|
5
|
+
* Loads user-defined prompts from a git repository.
|
|
6
|
+
* Supports any git provider (GitHub, GitLab, Gitea, Forgejo, Bitbucket, etc.)
|
|
7
|
+
*
|
|
8
|
+
* Environment variables:
|
|
9
|
+
* - DOT_AI_USER_PROMPTS_REPO: Git repository URL (required to enable)
|
|
10
|
+
* - DOT_AI_USER_PROMPTS_BRANCH: Branch to use (default: main)
|
|
11
|
+
* - DOT_AI_USER_PROMPTS_PATH: Subdirectory within repo (default: root)
|
|
12
|
+
* - DOT_AI_GIT_TOKEN: Authentication token (optional)
|
|
13
|
+
* - DOT_AI_USER_PROMPTS_CACHE_TTL: Cache TTL in seconds (default: 86400 = 24h)
|
|
14
|
+
*/
|
|
15
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
18
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
19
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
20
|
+
}
|
|
21
|
+
Object.defineProperty(o, k2, desc);
|
|
22
|
+
}) : (function(o, m, k, k2) {
|
|
23
|
+
if (k2 === undefined) k2 = k;
|
|
24
|
+
o[k2] = m[k];
|
|
25
|
+
}));
|
|
26
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
27
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
28
|
+
}) : function(o, v) {
|
|
29
|
+
o["default"] = v;
|
|
30
|
+
});
|
|
31
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
32
|
+
var ownKeys = function(o) {
|
|
33
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
34
|
+
var ar = [];
|
|
35
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
36
|
+
return ar;
|
|
37
|
+
};
|
|
38
|
+
return ownKeys(o);
|
|
39
|
+
};
|
|
40
|
+
return function (mod) {
|
|
41
|
+
if (mod && mod.__esModule) return mod;
|
|
42
|
+
var result = {};
|
|
43
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
44
|
+
__setModuleDefault(result, mod);
|
|
45
|
+
return result;
|
|
46
|
+
};
|
|
47
|
+
})();
|
|
48
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
+
exports.getUserPromptsConfig = getUserPromptsConfig;
|
|
50
|
+
exports.getCacheDirectory = getCacheDirectory;
|
|
51
|
+
exports.insertTokenInUrl = insertTokenInUrl;
|
|
52
|
+
exports.sanitizeUrlForLogging = sanitizeUrlForLogging;
|
|
53
|
+
exports.loadUserPrompts = loadUserPrompts;
|
|
54
|
+
exports.clearUserPromptsCache = clearUserPromptsCache;
|
|
55
|
+
exports.getUserPromptsCacheState = getUserPromptsCacheState;
|
|
56
|
+
const fs = __importStar(require("fs"));
|
|
57
|
+
const path = __importStar(require("path"));
|
|
58
|
+
const os = __importStar(require("os"));
|
|
59
|
+
const platform_utils_1 = require("./platform-utils");
|
|
60
|
+
const prompts_1 = require("../tools/prompts");
|
|
61
|
+
// In-memory cache state (persists across requests within same process)
|
|
62
|
+
let cacheState = null;
|
|
63
|
+
/**
|
|
64
|
+
* Read user prompts configuration from environment variables
|
|
65
|
+
* Returns null if DOT_AI_USER_PROMPTS_REPO is not set
|
|
66
|
+
*/
|
|
67
|
+
function getUserPromptsConfig() {
|
|
68
|
+
const repoUrl = process.env.DOT_AI_USER_PROMPTS_REPO;
|
|
69
|
+
if (!repoUrl) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
// Validate cache TTL - fallback to default if invalid or negative
|
|
73
|
+
const parsedTtl = parseInt(process.env.DOT_AI_USER_PROMPTS_CACHE_TTL || '86400', 10);
|
|
74
|
+
const cacheTtlSeconds = Number.isNaN(parsedTtl) || parsedTtl < 0 ? 86400 : parsedTtl;
|
|
75
|
+
return {
|
|
76
|
+
repoUrl,
|
|
77
|
+
branch: process.env.DOT_AI_USER_PROMPTS_BRANCH || 'main',
|
|
78
|
+
subPath: process.env.DOT_AI_USER_PROMPTS_PATH || '',
|
|
79
|
+
gitToken: process.env.DOT_AI_GIT_TOKEN,
|
|
80
|
+
cacheTtlSeconds,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Get the cache directory for user prompts
|
|
85
|
+
* Tries project-relative tmp first, falls back to system temp
|
|
86
|
+
*/
|
|
87
|
+
function getCacheDirectory() {
|
|
88
|
+
// Try project-relative tmp directory first
|
|
89
|
+
const projectTmp = path.join(process.cwd(), 'tmp', 'user-prompts');
|
|
90
|
+
try {
|
|
91
|
+
// Ensure parent tmp directory exists
|
|
92
|
+
const parentTmp = path.join(process.cwd(), 'tmp');
|
|
93
|
+
if (!fs.existsSync(parentTmp)) {
|
|
94
|
+
fs.mkdirSync(parentTmp, { recursive: true });
|
|
95
|
+
}
|
|
96
|
+
// Test if we can write to it
|
|
97
|
+
const testFile = path.join(parentTmp, '.write-test');
|
|
98
|
+
fs.writeFileSync(testFile, 'test');
|
|
99
|
+
fs.unlinkSync(testFile);
|
|
100
|
+
return projectTmp;
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
// Fall back to system temp (works in Docker/K8s)
|
|
104
|
+
return path.join(os.tmpdir(), 'dot-ai-user-prompts');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Insert authentication token into git URL
|
|
109
|
+
* Works with any HTTPS git URL (GitHub, GitLab, Gitea, Bitbucket, etc.)
|
|
110
|
+
*/
|
|
111
|
+
function insertTokenInUrl(url, token) {
|
|
112
|
+
try {
|
|
113
|
+
const parsed = new URL(url);
|
|
114
|
+
parsed.username = token;
|
|
115
|
+
return parsed.toString();
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
// If URL parsing fails, return original
|
|
119
|
+
return url;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Sanitize URL for logging (remove credentials)
|
|
124
|
+
*/
|
|
125
|
+
function sanitizeUrlForLogging(url) {
|
|
126
|
+
try {
|
|
127
|
+
const parsed = new URL(url);
|
|
128
|
+
if (parsed.username)
|
|
129
|
+
parsed.username = '***';
|
|
130
|
+
if (parsed.password)
|
|
131
|
+
parsed.password = '***';
|
|
132
|
+
return parsed.toString();
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
// If URL parsing fails, do basic sanitization
|
|
136
|
+
return url.replace(/\/\/[^@]+@/, '//***@');
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Validate git branch name to prevent command injection
|
|
141
|
+
* Allows alphanumeric characters, hyphens, underscores, slashes, and dots
|
|
142
|
+
*/
|
|
143
|
+
function isValidGitBranch(branch) {
|
|
144
|
+
return /^[a-zA-Z0-9_.\-/]+$/.test(branch);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Clone the user prompts repository
|
|
148
|
+
*/
|
|
149
|
+
async function cloneRepository(config, localPath, logger) {
|
|
150
|
+
// Validate branch name to prevent command injection
|
|
151
|
+
if (!isValidGitBranch(config.branch)) {
|
|
152
|
+
throw new Error(`Invalid branch name: ${config.branch}`);
|
|
153
|
+
}
|
|
154
|
+
const authUrl = config.gitToken
|
|
155
|
+
? insertTokenInUrl(config.repoUrl, config.gitToken)
|
|
156
|
+
: config.repoUrl;
|
|
157
|
+
const sanitizedUrl = sanitizeUrlForLogging(config.repoUrl);
|
|
158
|
+
logger.info('Cloning user prompts repository', {
|
|
159
|
+
url: sanitizedUrl,
|
|
160
|
+
branch: config.branch,
|
|
161
|
+
localPath,
|
|
162
|
+
});
|
|
163
|
+
try {
|
|
164
|
+
// Ensure parent directory exists
|
|
165
|
+
const parentDir = path.dirname(localPath);
|
|
166
|
+
if (!fs.existsSync(parentDir)) {
|
|
167
|
+
fs.mkdirSync(parentDir, { recursive: true });
|
|
168
|
+
}
|
|
169
|
+
// Remove existing directory if it exists (clean clone)
|
|
170
|
+
if (fs.existsSync(localPath)) {
|
|
171
|
+
fs.rmSync(localPath, { recursive: true, force: true });
|
|
172
|
+
}
|
|
173
|
+
// Clone with shallow depth for faster operation
|
|
174
|
+
const cloneCommand = `git clone --depth 1 --branch ${config.branch} "${authUrl}" "${localPath}"`;
|
|
175
|
+
await (0, platform_utils_1.execAsync)(cloneCommand);
|
|
176
|
+
logger.info('Successfully cloned user prompts repository', {
|
|
177
|
+
url: sanitizedUrl,
|
|
178
|
+
branch: config.branch,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
183
|
+
// Sanitize error message in case it contains the token
|
|
184
|
+
const sanitizedError = config.gitToken
|
|
185
|
+
? errorMessage.replaceAll(config.gitToken, '***')
|
|
186
|
+
: errorMessage;
|
|
187
|
+
logger.error('Failed to clone user prompts repository', new Error(sanitizedError), {
|
|
188
|
+
url: sanitizedUrl,
|
|
189
|
+
branch: config.branch,
|
|
190
|
+
});
|
|
191
|
+
throw new Error(`Failed to clone user prompts repository: ${sanitizedError}`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Pull latest changes from the user prompts repository
|
|
196
|
+
*/
|
|
197
|
+
async function pullRepository(config, localPath, logger) {
|
|
198
|
+
const sanitizedUrl = sanitizeUrlForLogging(config.repoUrl);
|
|
199
|
+
logger.debug('Pulling user prompts repository', {
|
|
200
|
+
url: sanitizedUrl,
|
|
201
|
+
localPath,
|
|
202
|
+
});
|
|
203
|
+
try {
|
|
204
|
+
// Set up credentials for pull if token is provided
|
|
205
|
+
if (config.gitToken) {
|
|
206
|
+
const authUrl = insertTokenInUrl(config.repoUrl, config.gitToken);
|
|
207
|
+
await (0, platform_utils_1.execAsync)(`git -C "${localPath}" remote set-url origin "${authUrl}"`);
|
|
208
|
+
}
|
|
209
|
+
await (0, platform_utils_1.execAsync)(`git -C "${localPath}" pull --ff-only`);
|
|
210
|
+
logger.debug('Successfully pulled user prompts repository', {
|
|
211
|
+
url: sanitizedUrl,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
216
|
+
const sanitizedError = config.gitToken
|
|
217
|
+
? errorMessage.replaceAll(config.gitToken, '***')
|
|
218
|
+
: errorMessage;
|
|
219
|
+
logger.warn('Failed to pull user prompts repository, using cached version', {
|
|
220
|
+
url: sanitizedUrl,
|
|
221
|
+
error: sanitizedError,
|
|
222
|
+
});
|
|
223
|
+
// Don't throw - use cached version
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Ensure the repository is cloned and up-to-date
|
|
228
|
+
* Returns the path to the prompts directory within the repository
|
|
229
|
+
*/
|
|
230
|
+
async function ensureRepository(config, logger, forceRefresh = false) {
|
|
231
|
+
const localPath = getCacheDirectory();
|
|
232
|
+
const now = Date.now();
|
|
233
|
+
const ttlMs = config.cacheTtlSeconds * 1000;
|
|
234
|
+
// Check if we need to clone or pull
|
|
235
|
+
if (!cacheState || !fs.existsSync(cacheState.localPath)) {
|
|
236
|
+
// First time or cache directory was deleted - clone
|
|
237
|
+
await cloneRepository(config, localPath, logger);
|
|
238
|
+
cacheState = { lastPullTime: now, localPath };
|
|
239
|
+
}
|
|
240
|
+
else if (forceRefresh || now - cacheState.lastPullTime >= ttlMs) {
|
|
241
|
+
// Cache expired or force refresh - pull
|
|
242
|
+
await pullRepository(config, localPath, logger);
|
|
243
|
+
cacheState.lastPullTime = now;
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
logger.debug('Using cached user prompts repository', {
|
|
247
|
+
localPath,
|
|
248
|
+
cacheAge: Math.round((now - cacheState.lastPullTime) / 1000),
|
|
249
|
+
ttl: config.cacheTtlSeconds,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
// Return path to prompts directory (with optional subPath)
|
|
253
|
+
return config.subPath
|
|
254
|
+
? path.join(localPath, config.subPath)
|
|
255
|
+
: localPath;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Load user prompts from the configured git repository
|
|
259
|
+
* Returns empty array if not configured or on error
|
|
260
|
+
*/
|
|
261
|
+
async function loadUserPrompts(logger, forceRefresh = false) {
|
|
262
|
+
const config = getUserPromptsConfig();
|
|
263
|
+
if (!config) {
|
|
264
|
+
logger.debug('User prompts not configured (DOT_AI_USER_PROMPTS_REPO not set)');
|
|
265
|
+
return [];
|
|
266
|
+
}
|
|
267
|
+
try {
|
|
268
|
+
const promptsDir = await ensureRepository(config, logger, forceRefresh);
|
|
269
|
+
if (!fs.existsSync(promptsDir)) {
|
|
270
|
+
logger.warn('User prompts directory not found in repository', {
|
|
271
|
+
path: promptsDir,
|
|
272
|
+
subPath: config.subPath,
|
|
273
|
+
});
|
|
274
|
+
return [];
|
|
275
|
+
}
|
|
276
|
+
// Load all .md files from the prompts directory
|
|
277
|
+
const files = fs.readdirSync(promptsDir);
|
|
278
|
+
const promptFiles = files.filter(file => file.endsWith('.md'));
|
|
279
|
+
const prompts = [];
|
|
280
|
+
for (const file of promptFiles) {
|
|
281
|
+
try {
|
|
282
|
+
const filePath = path.join(promptsDir, file);
|
|
283
|
+
const prompt = (0, prompts_1.loadPromptFile)(filePath, 'user');
|
|
284
|
+
prompts.push(prompt);
|
|
285
|
+
logger.debug('Loaded user prompt', { name: prompt.name, file });
|
|
286
|
+
}
|
|
287
|
+
catch (error) {
|
|
288
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
289
|
+
logger.warn('Failed to load user prompt file, skipping', {
|
|
290
|
+
file,
|
|
291
|
+
error: errorMessage,
|
|
292
|
+
});
|
|
293
|
+
// Continue with other prompts
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
logger.info('Loaded user prompts from repository', {
|
|
297
|
+
total: prompts.length,
|
|
298
|
+
url: sanitizeUrlForLogging(config.repoUrl),
|
|
299
|
+
});
|
|
300
|
+
return prompts;
|
|
301
|
+
}
|
|
302
|
+
catch (error) {
|
|
303
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
304
|
+
logger.error('Failed to load user prompts, falling back to built-in only', new Error(errorMessage));
|
|
305
|
+
return [];
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Clear the cache state (useful for testing)
|
|
310
|
+
*/
|
|
311
|
+
function clearUserPromptsCache() {
|
|
312
|
+
cacheState = null;
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Get current cache state (for testing/debugging)
|
|
316
|
+
*/
|
|
317
|
+
function getUserPromptsCacheState() {
|
|
318
|
+
return cacheState ? { ...cacheState } : null;
|
|
319
|
+
}
|
|
@@ -57,6 +57,38 @@ export interface ToolDiscoveryResponse extends RestApiResponse {
|
|
|
57
57
|
tags?: string[];
|
|
58
58
|
};
|
|
59
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Visualization types supported by the API
|
|
62
|
+
*/
|
|
63
|
+
export type VisualizationType = 'mermaid' | 'cards' | 'code' | 'table';
|
|
64
|
+
/**
|
|
65
|
+
* Individual visualization item
|
|
66
|
+
*/
|
|
67
|
+
export interface Visualization {
|
|
68
|
+
id: string;
|
|
69
|
+
label: string;
|
|
70
|
+
type: VisualizationType;
|
|
71
|
+
content: string | {
|
|
72
|
+
language: string;
|
|
73
|
+
code: string;
|
|
74
|
+
} | {
|
|
75
|
+
headers: string[];
|
|
76
|
+
rows: string[][];
|
|
77
|
+
} | Array<{
|
|
78
|
+
id: string;
|
|
79
|
+
title: string;
|
|
80
|
+
description?: string;
|
|
81
|
+
tags?: string[];
|
|
82
|
+
}>;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Visualization endpoint response format
|
|
86
|
+
*/
|
|
87
|
+
export interface VisualizationResponse {
|
|
88
|
+
title: string;
|
|
89
|
+
visualizations: Visualization[];
|
|
90
|
+
insights: string[];
|
|
91
|
+
}
|
|
60
92
|
/**
|
|
61
93
|
* REST API router configuration
|
|
62
94
|
*/
|
|
@@ -101,6 +133,19 @@ export declare class RestApiRouter {
|
|
|
101
133
|
* Handle resource sync requests from controller
|
|
102
134
|
*/
|
|
103
135
|
private handleResourceSyncRequest;
|
|
136
|
+
/**
|
|
137
|
+
* Handle prompts list requests
|
|
138
|
+
*/
|
|
139
|
+
private handlePromptsListRequest;
|
|
140
|
+
/**
|
|
141
|
+
* Handle prompt get requests
|
|
142
|
+
*/
|
|
143
|
+
private handlePromptsGetRequest;
|
|
144
|
+
/**
|
|
145
|
+
* Handle visualization requests (PRD #317)
|
|
146
|
+
* Returns structured visualization data for a query session
|
|
147
|
+
*/
|
|
148
|
+
private handleVisualize;
|
|
104
149
|
/**
|
|
105
150
|
* Set CORS headers
|
|
106
151
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rest-api.d.ts","sourceRoot":"","sources":["../../src/interfaces/rest-api.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE5D,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE7D,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"rest-api.d.ts","sourceRoot":"","sources":["../../src/interfaces/rest-api.ts"],"names":[],"mappings":"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"}
|