@vfarcic/dot-ai 0.104.0 → 0.106.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 (67) hide show
  1. package/README.md +6 -1
  2. package/dist/core/ai-provider-factory.d.ts +90 -0
  3. package/dist/core/ai-provider-factory.d.ts.map +1 -0
  4. package/dist/core/ai-provider-factory.js +187 -0
  5. package/dist/core/ai-provider.interface.d.ts +208 -0
  6. package/dist/core/ai-provider.interface.d.ts.map +1 -0
  7. package/dist/core/ai-provider.interface.js +14 -0
  8. package/dist/core/capabilities.d.ts +3 -3
  9. package/dist/core/capabilities.d.ts.map +1 -1
  10. package/dist/core/capabilities.js +4 -4
  11. package/dist/core/capability-scan-workflow.d.ts.map +1 -1
  12. package/dist/core/capability-scan-workflow.js +29 -14
  13. package/dist/core/doc-testing-session.d.ts +1 -1
  14. package/dist/core/doc-testing-session.js +1 -1
  15. package/dist/core/error-handling.js +2 -2
  16. package/dist/core/index.d.ts +4 -6
  17. package/dist/core/index.d.ts.map +1 -1
  18. package/dist/core/index.js +11 -22
  19. package/dist/core/platform-operations.d.ts +9 -15
  20. package/dist/core/platform-operations.d.ts.map +1 -1
  21. package/dist/core/platform-operations.js +28 -49
  22. package/dist/core/platform-utils.d.ts +16 -0
  23. package/dist/core/platform-utils.d.ts.map +1 -0
  24. package/dist/core/platform-utils.js +68 -0
  25. package/dist/core/providers/anthropic-provider.d.ts +44 -0
  26. package/dist/core/providers/anthropic-provider.d.ts.map +1 -0
  27. package/dist/core/providers/anthropic-provider.js +281 -0
  28. package/dist/core/providers/provider-debug-utils.d.ts +27 -0
  29. package/dist/core/providers/provider-debug-utils.d.ts.map +1 -0
  30. package/dist/core/providers/provider-debug-utils.js +122 -0
  31. package/dist/core/providers/vercel-provider.d.ts +47 -0
  32. package/dist/core/providers/vercel-provider.d.ts.map +1 -0
  33. package/dist/core/providers/vercel-provider.js +152 -0
  34. package/dist/core/schema.d.ts +4 -7
  35. package/dist/core/schema.d.ts.map +1 -1
  36. package/dist/core/schema.js +13 -11
  37. package/dist/core/unified-creation-session.d.ts.map +1 -1
  38. package/dist/core/unified-creation-session.js +13 -14
  39. package/dist/interfaces/mcp.d.ts +1 -1
  40. package/dist/interfaces/mcp.d.ts.map +1 -1
  41. package/dist/interfaces/mcp.js +29 -8
  42. package/dist/interfaces/rest-api.js +1 -1
  43. package/dist/mcp/server.d.ts +1 -1
  44. package/dist/mcp/server.js +2 -2
  45. package/dist/tools/answer-question.d.ts.map +1 -1
  46. package/dist/tools/answer-question.js +8 -10
  47. package/dist/tools/build-platform.js +3 -3
  48. package/dist/tools/generate-manifests.d.ts.map +1 -1
  49. package/dist/tools/generate-manifests.js +7 -8
  50. package/dist/tools/organizational-data.d.ts.map +1 -1
  51. package/dist/tools/organizational-data.js +3 -2
  52. package/dist/tools/platform/discover-operations.tool.d.ts +35 -0
  53. package/dist/tools/platform/discover-operations.tool.d.ts.map +1 -0
  54. package/dist/tools/platform/discover-operations.tool.js +88 -0
  55. package/dist/tools/recommend.d.ts.map +1 -1
  56. package/dist/tools/recommend.js +50 -30
  57. package/dist/tools/remediate.d.ts.map +1 -1
  58. package/dist/tools/remediate.js +23 -39
  59. package/dist/tools/version.d.ts +3 -2
  60. package/dist/tools/version.d.ts.map +1 -1
  61. package/dist/tools/version.js +35 -23
  62. package/package.json +5 -2
  63. package/prompts/{parse-script-operations.md → platform-operations-parse-script-help.md} +4 -8
  64. package/prompts/question-generation.md +31 -3
  65. package/dist/core/claude.d.ts +0 -88
  66. package/dist/core/claude.d.ts.map +0 -1
  67. package/dist/core/claude.js +0 -414
@@ -0,0 +1,281 @@
1
+ "use strict";
2
+ /**
3
+ * Anthropic AI Provider Implementation
4
+ *
5
+ * Implements AIProvider interface using Anthropic SDK directly.
6
+ * Supports streaming for long operations and debug logging.
7
+ */
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.AnthropicProvider = void 0;
13
+ const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
14
+ const provider_debug_utils_1 = require("./provider-debug-utils");
15
+ class AnthropicProvider {
16
+ client;
17
+ apiKey;
18
+ model;
19
+ debugMode;
20
+ constructor(config) {
21
+ this.apiKey = config.apiKey;
22
+ this.model = config.model || this.getDefaultModel();
23
+ this.debugMode = config.debugMode ?? (process.env.DEBUG_DOT_AI === 'true');
24
+ this.validateApiKey();
25
+ this.client = new sdk_1.default({
26
+ apiKey: this.apiKey,
27
+ });
28
+ }
29
+ validateApiKey() {
30
+ if (!this.apiKey) {
31
+ throw new Error('API key is required for Anthropic provider');
32
+ }
33
+ if (this.apiKey.length === 0) {
34
+ throw new Error('Invalid API key: API key cannot be empty');
35
+ }
36
+ }
37
+ getProviderType() {
38
+ return 'anthropic';
39
+ }
40
+ getDefaultModel() {
41
+ return 'claude-sonnet-4-5-20250929';
42
+ }
43
+ isInitialized() {
44
+ return this.client !== undefined;
45
+ }
46
+ async sendMessage(message, operation = 'generic') {
47
+ if (!this.client) {
48
+ throw new Error('Anthropic client not initialized');
49
+ }
50
+ const startTime = Date.now();
51
+ try {
52
+ // Make real API call to Anthropic with streaming
53
+ const stream = await this.client.messages.create({
54
+ model: this.model,
55
+ max_tokens: 64000,
56
+ messages: [{ role: 'user', content: message }],
57
+ stream: true // Enable streaming by default to support long operations (>10 minutes)
58
+ });
59
+ let content = '';
60
+ let input_tokens = 0;
61
+ let output_tokens = 0;
62
+ for await (const chunk of stream) {
63
+ if (chunk.type === 'message_start') {
64
+ input_tokens = chunk.message.usage.input_tokens;
65
+ }
66
+ else if (chunk.type === 'content_block_delta') {
67
+ if (chunk.delta.type === 'text_delta') {
68
+ content += chunk.delta.text;
69
+ }
70
+ }
71
+ else if (chunk.type === 'message_delta') {
72
+ output_tokens = chunk.usage.output_tokens;
73
+ }
74
+ }
75
+ const response = {
76
+ content,
77
+ usage: {
78
+ input_tokens,
79
+ output_tokens
80
+ }
81
+ };
82
+ const durationMs = Date.now() - startTime;
83
+ // Debug log the interaction if enabled
84
+ if (this.debugMode) {
85
+ const debugId = (0, provider_debug_utils_1.generateDebugId)(operation);
86
+ (0, provider_debug_utils_1.debugLogInteraction)(debugId, message, response, operation, this.getProviderType(), this.model, this.debugMode);
87
+ (0, provider_debug_utils_1.logMetrics)(operation, this.getProviderType(), response.usage, durationMs, this.debugMode);
88
+ }
89
+ return response;
90
+ }
91
+ catch (error) {
92
+ throw new Error(`Anthropic API error: ${error}`);
93
+ }
94
+ }
95
+ /**
96
+ * Agentic tool loop implementation
97
+ *
98
+ * NOTE: This method is currently NOT USED in the codebase (as of PRD #136 completion).
99
+ *
100
+ * Analysis showed that SDK-based tool loops and JSON-based agentic loops are functionally
101
+ * equivalent - both allow AI to decide which tools to call and when to stop. The JSON-based
102
+ * approach we already use provides the same capabilities without the token overhead of
103
+ * tool schemas in every request.
104
+ *
105
+ * This implementation is kept for potential future use cases where SDK-managed tool loops
106
+ * might provide advantages (e.g., better provider-specific optimizations, simpler code for
107
+ * highly exploratory workflows).
108
+ *
109
+ * ONLY IMPLEMENTED IN ANTHROPIC PROVIDER - VercelAIProvider does not implement this method
110
+ * as it's not needed for current workflows. If you need toolLoop for other providers, you'll
111
+ * need to implement it there as well.
112
+ *
113
+ * See PRD #136 for full architecture analysis and decision rationale.
114
+ */
115
+ async toolLoop(config) {
116
+ if (!this.client) {
117
+ throw new Error('Anthropic client not initialized');
118
+ }
119
+ const startTime = Date.now();
120
+ // Convert AITool[] to Anthropic Tool format
121
+ const tools = config.tools.map(t => ({
122
+ name: t.name,
123
+ description: t.description,
124
+ input_schema: t.inputSchema
125
+ }));
126
+ // Initialize conversation history
127
+ const initialContent = config.systemPrompt + '\n\n' + config.userMessage;
128
+ const conversationHistory = [
129
+ {
130
+ role: 'user',
131
+ content: initialContent
132
+ }
133
+ ];
134
+ let iterations = 0;
135
+ const toolCallsExecuted = [];
136
+ const totalTokens = { input: 0, output: 0 };
137
+ const maxIterations = config.maxIterations || 20;
138
+ try {
139
+ while (iterations < maxIterations) {
140
+ iterations++;
141
+ // Call Anthropic API with tools
142
+ const response = await this.client.messages.create({
143
+ model: this.model,
144
+ max_tokens: 4096,
145
+ messages: conversationHistory,
146
+ tools: tools
147
+ });
148
+ // Track token usage
149
+ totalTokens.input += response.usage.input_tokens;
150
+ totalTokens.output += response.usage.output_tokens;
151
+ // Check if AI wants to use tools
152
+ const toolUses = response.content.filter((c) => c.type === 'tool_use');
153
+ if (toolUses.length === 0) {
154
+ // AI is done - extract final text message
155
+ const textContent = response.content.find((c) => c.type === 'text');
156
+ const result = {
157
+ finalMessage: textContent?.text || '',
158
+ iterations,
159
+ toolCallsExecuted,
160
+ totalTokens
161
+ };
162
+ // Log metrics for the entire tool loop
163
+ const durationMs = Date.now() - startTime;
164
+ if (this.debugMode) {
165
+ const operation = config.operation || 'tool-loop';
166
+ (0, provider_debug_utils_1.logMetrics)(operation, this.getProviderType(), {
167
+ input_tokens: totalTokens.input,
168
+ output_tokens: totalTokens.output
169
+ }, durationMs, this.debugMode);
170
+ }
171
+ return result;
172
+ }
173
+ // Execute all requested tools
174
+ const toolResults = [];
175
+ for (const toolUse of toolUses) {
176
+ try {
177
+ const result = await config.toolExecutor(toolUse.name, toolUse.input);
178
+ toolCallsExecuted.push({
179
+ tool: toolUse.name,
180
+ input: toolUse.input,
181
+ output: result
182
+ });
183
+ toolResults.push({
184
+ type: 'tool_result',
185
+ tool_use_id: toolUse.id,
186
+ content: JSON.stringify(result)
187
+ });
188
+ }
189
+ catch (error) {
190
+ // Feed error back to AI as tool result
191
+ const errorMessage = error instanceof Error ? error.message : String(error);
192
+ toolResults.push({
193
+ type: 'tool_result',
194
+ tool_use_id: toolUse.id,
195
+ content: JSON.stringify({ error: errorMessage }),
196
+ is_error: true
197
+ });
198
+ }
199
+ }
200
+ // Add AI response and tool results to conversation history
201
+ conversationHistory.push({ role: 'assistant', content: response.content }, { role: 'user', content: toolResults });
202
+ // Invoke iteration callback if provided
203
+ if (config.onIteration) {
204
+ config.onIteration(iterations, toolCallsExecuted);
205
+ }
206
+ }
207
+ throw new Error(`Tool loop exceeded max iterations (${maxIterations})`);
208
+ }
209
+ catch (error) {
210
+ if (error instanceof Error && error.message.includes('exceeded max iterations')) {
211
+ throw error;
212
+ }
213
+ throw new Error(`Anthropic tool loop error: ${error}`);
214
+ }
215
+ }
216
+ async sendMessageWithTools(message, tools, toolExecutor, operation = 'tool-call') {
217
+ if (!this.client) {
218
+ throw new Error('Anthropic client not initialized');
219
+ }
220
+ // Convert AITool[] to Anthropic Tool format
221
+ const anthropicTools = tools.map(t => ({
222
+ name: t.name,
223
+ description: t.description,
224
+ input_schema: t.inputSchema
225
+ }));
226
+ try {
227
+ // Single API call with tools
228
+ const response = await this.client.messages.create({
229
+ model: this.model,
230
+ max_tokens: 4096,
231
+ messages: [{ role: 'user', content: message }],
232
+ tools: anthropicTools
233
+ });
234
+ const toolCalls = [];
235
+ let textContent = '';
236
+ // Process response content
237
+ for (const block of response.content) {
238
+ if (block.type === 'text') {
239
+ textContent += block.text;
240
+ }
241
+ else if (block.type === 'tool_use') {
242
+ // Execute the tool
243
+ try {
244
+ const result = await toolExecutor(block.name, block.input);
245
+ toolCalls.push({
246
+ tool: block.name,
247
+ input: block.input,
248
+ output: result
249
+ });
250
+ }
251
+ catch (error) {
252
+ const errorMessage = error instanceof Error ? error.message : String(error);
253
+ toolCalls.push({
254
+ tool: block.name,
255
+ input: block.input,
256
+ error: errorMessage
257
+ });
258
+ }
259
+ }
260
+ }
261
+ const aiResponse = {
262
+ content: textContent,
263
+ usage: {
264
+ input_tokens: response.usage.input_tokens,
265
+ output_tokens: response.usage.output_tokens
266
+ },
267
+ toolCalls: toolCalls.length > 0 ? toolCalls : undefined
268
+ };
269
+ // Debug log if enabled
270
+ if (this.debugMode) {
271
+ const debugId = (0, provider_debug_utils_1.generateDebugId)(operation);
272
+ (0, provider_debug_utils_1.debugLogInteraction)(debugId, message, aiResponse, operation, this.getProviderType(), this.model, this.debugMode);
273
+ }
274
+ return aiResponse;
275
+ }
276
+ catch (error) {
277
+ throw new Error(`Anthropic tool call error: ${error}`);
278
+ }
279
+ }
280
+ }
281
+ exports.AnthropicProvider = AnthropicProvider;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Shared debugging utilities for AI providers
3
+ *
4
+ * Common functions for logging metrics and debugging AI interactions
5
+ * when DEBUG_DOT_AI=true
6
+ */
7
+ import { AIResponse } from '../ai-provider.interface';
8
+ /**
9
+ * Create debug directory if it doesn't exist
10
+ */
11
+ export declare function ensureDebugDirectory(): string;
12
+ /**
13
+ * Generate unique identifier for debug files with operation context
14
+ */
15
+ export declare function generateDebugId(operation: string): string;
16
+ /**
17
+ * Log metrics for token usage and execution time when DEBUG_DOT_AI=true
18
+ */
19
+ export declare function logMetrics(operation: string, provider: string, usage: {
20
+ input_tokens: number;
21
+ output_tokens: number;
22
+ }, durationMs: number, debugMode: boolean): void;
23
+ /**
24
+ * Save AI interaction for debugging when DEBUG_DOT_AI=true
25
+ */
26
+ export declare function debugLogInteraction(debugId: string, prompt: string, response: AIResponse, operation: string, provider: string, model: string, debugMode: boolean): void;
27
+ //# sourceMappingURL=provider-debug-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-debug-utils.d.ts","sourceRoot":"","sources":["../../../src/core/providers/provider-debug-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEtD;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAM7C;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAKzD;AAED;;GAEG;AACH,wBAAgB,UAAU,CACxB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,EACtD,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,OAAO,GACjB,IAAI,CAoBN;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,UAAU,EACpB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,OAAO,GACjB,IAAI,CAkCN"}
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ /**
3
+ * Shared debugging utilities for AI providers
4
+ *
5
+ * Common functions for logging metrics and debugging AI interactions
6
+ * when DEBUG_DOT_AI=true
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.ensureDebugDirectory = ensureDebugDirectory;
43
+ exports.generateDebugId = generateDebugId;
44
+ exports.logMetrics = logMetrics;
45
+ exports.debugLogInteraction = debugLogInteraction;
46
+ const fs = __importStar(require("fs"));
47
+ const path = __importStar(require("path"));
48
+ const crypto = __importStar(require("crypto"));
49
+ /**
50
+ * Create debug directory if it doesn't exist
51
+ */
52
+ function ensureDebugDirectory() {
53
+ const debugDir = path.join(process.cwd(), 'tmp', 'debug-ai');
54
+ if (!fs.existsSync(debugDir)) {
55
+ fs.mkdirSync(debugDir, { recursive: true });
56
+ }
57
+ return debugDir;
58
+ }
59
+ /**
60
+ * Generate unique identifier for debug files with operation context
61
+ */
62
+ function generateDebugId(operation) {
63
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '').split('T');
64
+ const dateTime = timestamp[0] + 'T' + timestamp[1].substring(0, 6);
65
+ const randomHex = crypto.randomBytes(4).toString('hex');
66
+ return `${dateTime}_${randomHex}_${operation}`;
67
+ }
68
+ /**
69
+ * Log metrics for token usage and execution time when DEBUG_DOT_AI=true
70
+ */
71
+ function logMetrics(operation, provider, usage, durationMs, debugMode) {
72
+ if (!debugMode)
73
+ return;
74
+ try {
75
+ const debugDir = ensureDebugDirectory();
76
+ const metricsFile = path.join(debugDir, 'metrics.jsonl');
77
+ const entry = JSON.stringify({
78
+ timestamp: new Date().toISOString(),
79
+ provider,
80
+ operation,
81
+ inputTokens: usage.input_tokens,
82
+ outputTokens: usage.output_tokens,
83
+ durationMs
84
+ }) + '\n';
85
+ fs.appendFileSync(metricsFile, entry);
86
+ }
87
+ catch (error) {
88
+ console.warn('Failed to log metrics:', error);
89
+ }
90
+ }
91
+ /**
92
+ * Save AI interaction for debugging when DEBUG_DOT_AI=true
93
+ */
94
+ function debugLogInteraction(debugId, prompt, response, operation, provider, model, debugMode) {
95
+ if (!debugMode)
96
+ return;
97
+ try {
98
+ const debugDir = ensureDebugDirectory();
99
+ // Save prompt with descriptive naming
100
+ const promptFile = path.join(debugDir, `${debugId}_prompt.md`);
101
+ fs.writeFileSync(promptFile, `# AI Prompt - ${operation}\n\nTimestamp: ${new Date().toISOString()}\nProvider: ${provider}\nModel: ${model}\nOperation: ${operation}\n\n---\n\n${prompt}`);
102
+ // Save response with matching naming
103
+ const responseFile = path.join(debugDir, `${debugId}_response.md`);
104
+ const responseContent = `# AI Response - ${operation}
105
+
106
+ Timestamp: ${new Date().toISOString()}
107
+ Provider: ${provider}
108
+ Model: ${model}
109
+ Operation: ${operation}
110
+ Input Tokens: ${response.usage.input_tokens}
111
+ Output Tokens: ${response.usage.output_tokens}
112
+
113
+ ---
114
+
115
+ ${response.content}`;
116
+ fs.writeFileSync(responseFile, responseContent);
117
+ console.log(`🐛 DEBUG: AI interaction logged to tmp/debug-ai/${debugId}_*.md`);
118
+ }
119
+ catch (error) {
120
+ console.warn('Failed to log AI debug interaction:', error);
121
+ }
122
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Vercel AI Provider Implementation
3
+ *
4
+ * Implements AIProvider interface using Vercel AI SDK.
5
+ * Supports OpenAI and Google Gemini providers through unified interface.
6
+ */
7
+ import { AIProvider, AIResponse, AIProviderConfig, AITool, ToolExecutor, ToolLoopConfig, AgenticResult } from '../ai-provider.interface';
8
+ export declare class VercelProvider implements AIProvider {
9
+ private providerType;
10
+ private model;
11
+ private apiKey;
12
+ private debugMode;
13
+ private modelInstance;
14
+ constructor(config: AIProviderConfig);
15
+ private validateConfiguration;
16
+ private initializeModel;
17
+ getProviderType(): string;
18
+ getDefaultModel(): string;
19
+ isInitialized(): boolean;
20
+ sendMessage(message: string, operation?: string): Promise<AIResponse>;
21
+ /**
22
+ * Agentic tool loop - NOT IMPLEMENTED for Vercel provider
23
+ *
24
+ * This method is intentionally not implemented because:
25
+ * 1. toolLoop() is currently NOT USED anywhere in the codebase (see PRD #136)
26
+ * 2. JSON-based agentic loops already provide equivalent functionality
27
+ * 3. No current workflows require SDK-managed tool loops
28
+ *
29
+ * If future requirements necessitate toolLoop() for non-Anthropic providers,
30
+ * this would need to be implemented using Vercel AI SDK's tool calling API.
31
+ *
32
+ * See AnthropicProvider.toolLoop() and PRD #136 for implementation reference.
33
+ */
34
+ toolLoop(_config: ToolLoopConfig): Promise<AgenticResult>;
35
+ /**
36
+ * Single-shot tool calling - NOT IMPLEMENTED for Vercel provider
37
+ *
38
+ * Same reasoning as toolLoop(): not currently needed in codebase.
39
+ * JSON-based approach achieves same functionality without SDK overhead.
40
+ *
41
+ * See AnthropicProvider.sendMessageWithTools() for reference implementation.
42
+ */
43
+ sendMessageWithTools(_message: string, _tools: AITool[], _toolExecutor: ToolExecutor, _operation?: string): Promise<AIResponse & {
44
+ toolCalls?: any[];
45
+ }>;
46
+ }
47
+ //# sourceMappingURL=vercel-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vercel-provider.d.ts","sourceRoot":"","sources":["../../../src/core/providers/vercel-provider.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EACL,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,MAAM,EACN,YAAY,EACZ,cAAc,EACd,aAAa,EACd,MAAM,0BAA0B,CAAC;AAclC,qBAAa,cAAe,YAAW,UAAU;IAC/C,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAU;IAC3B,OAAO,CAAC,aAAa,CAAM;gBAEf,MAAM,EAAE,gBAAgB;IAUpC,OAAO,CAAC,qBAAqB;IAU7B,OAAO,CAAC,eAAe;IAgCvB,eAAe,IAAI,MAAM;IAIzB,eAAe,IAAI,MAAM;IAIzB,aAAa,IAAI,OAAO;IAIlB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,GAAE,MAAkB,GAAG,OAAO,CAAC,UAAU,CAAC;IAuCtF;;;;;;;;;;;;OAYG;IACG,QAAQ,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAQ/D;;;;;;;OAOG;IACG,oBAAoB,CACxB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EAAE,EAChB,aAAa,EAAE,YAAY,EAC3B,UAAU,GAAE,MAAoB,GAC/B,OAAO,CAAC,UAAU,GAAG;QAAE,SAAS,CAAC,EAAE,GAAG,EAAE,CAAA;KAAE,CAAC;CAO/C"}
@@ -0,0 +1,152 @@
1
+ "use strict";
2
+ /**
3
+ * Vercel AI Provider Implementation
4
+ *
5
+ * Implements AIProvider interface using Vercel AI SDK.
6
+ * Supports OpenAI and Google Gemini providers through unified interface.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.VercelProvider = void 0;
10
+ const ai_1 = require("ai");
11
+ const openai_1 = require("@ai-sdk/openai");
12
+ const google_1 = require("@ai-sdk/google");
13
+ const anthropic_1 = require("@ai-sdk/anthropic");
14
+ const provider_debug_utils_1 = require("./provider-debug-utils");
15
+ /**
16
+ * Provider-specific default models
17
+ */
18
+ const PROVIDER_MODELS = {
19
+ openai: 'gpt-5',
20
+ google: 'gemini-2.5-pro',
21
+ anthropic: 'claude-sonnet-4-5-20250929'
22
+ };
23
+ class VercelProvider {
24
+ providerType;
25
+ model;
26
+ apiKey;
27
+ debugMode;
28
+ modelInstance; // Vercel AI SDK model instance
29
+ constructor(config) {
30
+ this.apiKey = config.apiKey;
31
+ this.providerType = config.provider;
32
+ this.model = config.model || this.getDefaultModel();
33
+ this.debugMode = config.debugMode ?? (process.env.DEBUG_DOT_AI === 'true');
34
+ this.validateConfiguration();
35
+ this.initializeModel();
36
+ }
37
+ validateConfiguration() {
38
+ if (!this.apiKey) {
39
+ throw new Error(`API key is required for ${this.providerType} provider`);
40
+ }
41
+ if (!['openai', 'google', 'anthropic'].includes(this.providerType)) {
42
+ throw new Error(`Unsupported provider: ${this.providerType}. Must be 'openai', 'google', or 'anthropic'`);
43
+ }
44
+ }
45
+ initializeModel() {
46
+ try {
47
+ switch (this.providerType) {
48
+ case 'openai': {
49
+ const provider = (0, openai_1.createOpenAI)({
50
+ apiKey: this.apiKey
51
+ });
52
+ this.modelInstance = provider(this.model);
53
+ break;
54
+ }
55
+ case 'google': {
56
+ const provider = (0, google_1.createGoogleGenerativeAI)({
57
+ apiKey: this.apiKey
58
+ });
59
+ this.modelInstance = provider(this.model);
60
+ break;
61
+ }
62
+ case 'anthropic': {
63
+ const provider = (0, anthropic_1.createAnthropic)({
64
+ apiKey: this.apiKey
65
+ });
66
+ this.modelInstance = provider(this.model);
67
+ break;
68
+ }
69
+ default:
70
+ throw new Error(`Cannot initialize model for provider: ${this.providerType}`);
71
+ }
72
+ }
73
+ catch (error) {
74
+ throw new Error(`Failed to initialize ${this.providerType} model: ${error}`);
75
+ }
76
+ }
77
+ getProviderType() {
78
+ return this.providerType;
79
+ }
80
+ getDefaultModel() {
81
+ return PROVIDER_MODELS[this.providerType];
82
+ }
83
+ isInitialized() {
84
+ return this.modelInstance !== undefined;
85
+ }
86
+ async sendMessage(message, operation = 'generic') {
87
+ if (!this.isInitialized()) {
88
+ throw new Error(`${this.providerType} provider not initialized`);
89
+ }
90
+ const startTime = Date.now();
91
+ try {
92
+ // Use Vercel AI SDK generateText
93
+ // Note: maxTokens omitted - let SDK/provider use model-specific optimal defaults
94
+ const result = await (0, ai_1.generateText)({
95
+ model: this.modelInstance,
96
+ prompt: message,
97
+ });
98
+ const response = {
99
+ content: result.text,
100
+ usage: {
101
+ input_tokens: result.usage.inputTokens || 0,
102
+ output_tokens: result.usage.outputTokens || 0
103
+ }
104
+ };
105
+ const durationMs = Date.now() - startTime;
106
+ // Debug log the interaction if enabled
107
+ if (this.debugMode) {
108
+ const debugId = (0, provider_debug_utils_1.generateDebugId)(operation);
109
+ (0, provider_debug_utils_1.debugLogInteraction)(debugId, message, response, operation, this.getProviderType(), this.model, this.debugMode);
110
+ (0, provider_debug_utils_1.logMetrics)(operation, this.getProviderType(), response.usage, durationMs, this.debugMode);
111
+ }
112
+ return response;
113
+ }
114
+ catch (error) {
115
+ throw new Error(`${this.providerType} API error: ${error}`);
116
+ }
117
+ }
118
+ /**
119
+ * Agentic tool loop - NOT IMPLEMENTED for Vercel provider
120
+ *
121
+ * This method is intentionally not implemented because:
122
+ * 1. toolLoop() is currently NOT USED anywhere in the codebase (see PRD #136)
123
+ * 2. JSON-based agentic loops already provide equivalent functionality
124
+ * 3. No current workflows require SDK-managed tool loops
125
+ *
126
+ * If future requirements necessitate toolLoop() for non-Anthropic providers,
127
+ * this would need to be implemented using Vercel AI SDK's tool calling API.
128
+ *
129
+ * See AnthropicProvider.toolLoop() and PRD #136 for implementation reference.
130
+ */
131
+ async toolLoop(_config) {
132
+ if (!this.isInitialized()) {
133
+ throw new Error(`${this.providerType} provider not initialized`);
134
+ }
135
+ throw new Error(`toolLoop() not implemented for ${this.providerType} provider. Use AnthropicProvider for tool-based workflows, or use JSON-based agentic loops (recommended).`);
136
+ }
137
+ /**
138
+ * Single-shot tool calling - NOT IMPLEMENTED for Vercel provider
139
+ *
140
+ * Same reasoning as toolLoop(): not currently needed in codebase.
141
+ * JSON-based approach achieves same functionality without SDK overhead.
142
+ *
143
+ * See AnthropicProvider.sendMessageWithTools() for reference implementation.
144
+ */
145
+ async sendMessageWithTools(_message, _tools, _toolExecutor, _operation = 'tool-call') {
146
+ if (!this.isInitialized()) {
147
+ throw new Error(`${this.providerType} provider not initialized`);
148
+ }
149
+ throw new Error(`sendMessageWithTools() not implemented for ${this.providerType} provider. Use AnthropicProvider for tool-based workflows, or use JSON-based approach (recommended).`);
150
+ }
151
+ }
152
+ exports.VercelProvider = VercelProvider;
@@ -5,6 +5,7 @@
5
5
  * Fetches structured OpenAPI schemas from Kubernetes API server and validates manifests
6
6
  */
7
7
  import { ResourceExplanation } from './discovery';
8
+ import { AIProvider } from './ai-provider.interface';
8
9
  export interface FieldConstraints {
9
10
  minimum?: number;
10
11
  maximum?: number;
@@ -97,9 +98,6 @@ export interface ResourceSolution {
97
98
  patternInfluences?: PatternInfluence[];
98
99
  usedPatterns?: boolean;
99
100
  }
100
- export interface AIRankingConfig {
101
- claudeApiKey: string;
102
- }
103
101
  export interface ClusterOptions {
104
102
  namespaces: string[];
105
103
  storageClasses: string[];
@@ -151,12 +149,11 @@ export declare class ManifestValidator {
151
149
  * ResourceRecommender determines which resources best meet user needs using AI
152
150
  */
153
151
  export declare class ResourceRecommender {
154
- private claudeIntegration;
155
- private config;
152
+ private aiProvider;
156
153
  private patternService?;
157
154
  private capabilityService?;
158
155
  private policyService?;
159
- constructor(config: AIRankingConfig);
156
+ constructor(aiProvider?: AIProvider);
160
157
  /**
161
158
  * Find the best resource solution(s) for user intent using two-phase analysis
162
159
  */
@@ -239,7 +236,7 @@ export declare class ResourceRecommender {
239
236
  .replace('{patterns}', patternsContext);
240
237
 
241
238
 
242
- const response = await this.claudeIntegration.sendMessage(selectionPrompt, 'resource-selection');
239
+ const response = await this.aiProvider.sendMessage(selectionPrompt, 'resource-selection');
243
240
 
244
241
  try {
245
242
  // Extract JSON from response with robust parsing