@code-insights/cli 2.0.0 → 3.0.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/CHANGELOG.md +39 -0
- package/README.md +146 -156
- package/dashboard-dist/assets/index-BMhL7wL8.css +1 -0
- package/dashboard-dist/assets/index-CuCBzQyQ.js +548 -0
- package/dashboard-dist/dist/assets/index-BMhL7wL8.css +1 -0
- package/dashboard-dist/dist/assets/index-CuCBzQyQ.js +548 -0
- package/dashboard-dist/dist/favicon.svg +4 -0
- package/dashboard-dist/dist/index.html +33 -0
- package/dashboard-dist/favicon.svg +4 -0
- package/dashboard-dist/index.html +33 -0
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +188 -69
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/dashboard.d.ts +16 -0
- package/dist/commands/dashboard.d.ts.map +1 -0
- package/dist/commands/dashboard.js +82 -0
- package/dist/commands/dashboard.js.map +1 -0
- package/dist/commands/init.d.ts +3 -4
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +24 -201
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/install-hook.d.ts.map +1 -1
- package/dist/commands/install-hook.js +4 -21
- package/dist/commands/install-hook.js.map +1 -1
- package/dist/commands/open.d.ts +2 -1
- package/dist/commands/open.d.ts.map +1 -1
- package/dist/commands/open.js +10 -21
- package/dist/commands/open.js.map +1 -1
- package/dist/commands/reset.d.ts.map +1 -1
- package/dist/commands/reset.js +38 -69
- package/dist/commands/reset.js.map +1 -1
- package/dist/commands/stats/actions/error-handler.d.ts.map +1 -1
- package/dist/commands/stats/actions/error-handler.js +1 -11
- package/dist/commands/stats/actions/error-handler.js.map +1 -1
- package/dist/commands/stats/actions/overview.js +2 -2
- package/dist/commands/stats/actions/overview.js.map +1 -1
- package/dist/commands/stats/actions/today.js +1 -1
- package/dist/commands/stats/actions/today.js.map +1 -1
- package/dist/commands/stats/data/firestore.d.ts +1 -1
- package/dist/commands/stats/data/firestore.d.ts.map +1 -1
- package/dist/commands/stats/data/firestore.js +24 -9
- package/dist/commands/stats/data/firestore.js.map +1 -1
- package/dist/commands/stats/data/local.d.ts +1 -3
- package/dist/commands/stats/data/local.d.ts.map +1 -1
- package/dist/commands/stats/data/local.js +45 -41
- package/dist/commands/stats/data/local.js.map +1 -1
- package/dist/commands/stats/data/source.d.ts +3 -9
- package/dist/commands/stats/data/source.d.ts.map +1 -1
- package/dist/commands/stats/data/source.js +3 -35
- package/dist/commands/stats/data/source.js.map +1 -1
- package/dist/commands/stats/data/types.d.ts +2 -13
- package/dist/commands/stats/data/types.d.ts.map +1 -1
- package/dist/commands/stats/data/types.js +0 -16
- package/dist/commands/stats/data/types.js.map +1 -1
- package/dist/commands/stats/shared.d.ts.map +1 -1
- package/dist/commands/stats/shared.js +1 -5
- package/dist/commands/stats/shared.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +53 -92
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/sync.d.ts +5 -5
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +56 -40
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/telemetry.d.ts.map +1 -1
- package/dist/commands/telemetry.js +0 -1
- package/dist/commands/telemetry.js.map +1 -1
- package/dist/constants/llm-providers.d.ts +5 -0
- package/dist/constants/llm-providers.d.ts.map +1 -0
- package/dist/constants/llm-providers.js +56 -0
- package/dist/constants/llm-providers.js.map +1 -0
- package/dist/db/client.d.ts +17 -0
- package/dist/db/client.d.ts.map +1 -0
- package/dist/db/client.js +53 -0
- package/dist/db/client.js.map +1 -0
- package/dist/db/migrate.d.ts +9 -0
- package/dist/db/migrate.d.ts.map +1 -0
- package/dist/db/migrate.js +31 -0
- package/dist/db/migrate.js.map +1 -0
- package/dist/db/read.d.ts +42 -0
- package/dist/db/read.d.ts.map +1 -0
- package/dist/db/read.js +194 -0
- package/dist/db/read.js.map +1 -0
- package/dist/db/schema.d.ts +3 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +129 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/db/write.d.ts +24 -0
- package/dist/db/write.d.ts.map +1 -0
- package/dist/db/write.js +287 -0
- package/dist/db/write.js.map +1 -0
- package/dist/firebase/client.d.ts +5 -0
- package/dist/firebase/client.d.ts.map +1 -1
- package/dist/firebase/client.js +23 -0
- package/dist/firebase/client.js.map +1 -1
- package/dist/index.js +12 -12
- package/dist/index.js.map +1 -1
- package/dist/providers/context.d.ts +3 -0
- package/dist/providers/context.d.ts.map +1 -0
- package/dist/providers/context.js +13 -0
- package/dist/providers/context.js.map +1 -0
- package/dist/providers/copilot.d.ts +18 -0
- package/dist/providers/copilot.d.ts.map +1 -0
- package/dist/providers/copilot.js +289 -0
- package/dist/providers/copilot.js.map +1 -0
- package/dist/providers/cursor.d.ts.map +1 -1
- package/dist/providers/cursor.js +99 -4
- package/dist/providers/cursor.js.map +1 -1
- package/dist/providers/registry.d.ts.map +1 -1
- package/dist/providers/registry.js +3 -0
- package/dist/providers/registry.js.map +1 -1
- package/dist/types.d.ts +38 -47
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/browser.d.ts +6 -0
- package/dist/utils/browser.d.ts.map +1 -0
- package/dist/utils/browser.js +23 -0
- package/dist/utils/browser.js.map +1 -0
- package/dist/utils/config.d.ts +9 -21
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +23 -50
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/telemetry.js +2 -7
- package/dist/utils/telemetry.js.map +1 -1
- package/dist/utils/tips.js +1 -1
- package/dist/utils/tips.js.map +1 -1
- package/dist/utils/welcome.d.ts +1 -1
- package/dist/utils/welcome.d.ts.map +1 -1
- package/dist/utils/welcome.js +20 -49
- package/dist/utils/welcome.js.map +1 -1
- package/package.json +19 -5
- package/server-dist/dist/index.d.ts +12 -0
- package/server-dist/dist/index.d.ts.map +1 -0
- package/server-dist/dist/index.js +92 -0
- package/server-dist/dist/index.js.map +1 -0
- package/server-dist/dist/llm/analysis.d.ts +80 -0
- package/server-dist/dist/llm/analysis.d.ts.map +1 -0
- package/server-dist/dist/llm/analysis.js +509 -0
- package/server-dist/dist/llm/analysis.js.map +1 -0
- package/server-dist/dist/llm/client.d.ts +27 -0
- package/server-dist/dist/llm/client.d.ts.map +1 -0
- package/server-dist/dist/llm/client.js +71 -0
- package/server-dist/dist/llm/client.js.map +1 -0
- package/server-dist/dist/llm/index.d.ts +7 -0
- package/server-dist/dist/llm/index.d.ts.map +1 -0
- package/server-dist/dist/llm/index.js +5 -0
- package/server-dist/dist/llm/index.js.map +1 -0
- package/server-dist/dist/llm/prompts.d.ts +73 -0
- package/server-dist/dist/llm/prompts.d.ts.map +1 -0
- package/server-dist/dist/llm/prompts.js +242 -0
- package/server-dist/dist/llm/prompts.js.map +1 -0
- package/server-dist/dist/llm/providers/anthropic.d.ts +3 -0
- package/server-dist/dist/llm/providers/anthropic.d.ts.map +1 -0
- package/server-dist/dist/llm/providers/anthropic.js +45 -0
- package/server-dist/dist/llm/providers/anthropic.js.map +1 -0
- package/server-dist/dist/llm/providers/gemini.d.ts +3 -0
- package/server-dist/dist/llm/providers/gemini.d.ts.map +1 -0
- package/server-dist/dist/llm/providers/gemini.js +51 -0
- package/server-dist/dist/llm/providers/gemini.js.map +1 -0
- package/server-dist/dist/llm/providers/ollama.d.ts +12 -0
- package/server-dist/dist/llm/providers/ollama.d.ts.map +1 -0
- package/server-dist/dist/llm/providers/ollama.js +61 -0
- package/server-dist/dist/llm/providers/ollama.js.map +1 -0
- package/server-dist/dist/llm/providers/openai.d.ts +3 -0
- package/server-dist/dist/llm/providers/openai.d.ts.map +1 -0
- package/server-dist/dist/llm/providers/openai.js +39 -0
- package/server-dist/dist/llm/providers/openai.js.map +1 -0
- package/server-dist/dist/llm/types.d.ts +22 -0
- package/server-dist/dist/llm/types.d.ts.map +1 -0
- package/server-dist/dist/llm/types.js +5 -0
- package/server-dist/dist/llm/types.js.map +1 -0
- package/server-dist/dist/routes/analysis.d.ts +4 -0
- package/server-dist/dist/routes/analysis.d.ts.map +1 -0
- package/server-dist/dist/routes/analysis.js +103 -0
- package/server-dist/dist/routes/analysis.js.map +1 -0
- package/server-dist/dist/routes/analytics.d.ts +4 -0
- package/server-dist/dist/routes/analytics.d.ts.map +1 -0
- package/server-dist/dist/routes/analytics.js +47 -0
- package/server-dist/dist/routes/analytics.js.map +1 -0
- package/server-dist/dist/routes/config.d.ts +4 -0
- package/server-dist/dist/routes/config.d.ts.map +1 -0
- package/server-dist/dist/routes/config.js +108 -0
- package/server-dist/dist/routes/config.js.map +1 -0
- package/server-dist/dist/routes/export.d.ts +4 -0
- package/server-dist/dist/routes/export.d.ts.map +1 -0
- package/server-dist/dist/routes/export.js +52 -0
- package/server-dist/dist/routes/export.js.map +1 -0
- package/server-dist/dist/routes/insights.d.ts +4 -0
- package/server-dist/dist/routes/insights.d.ts.map +1 -0
- package/server-dist/dist/routes/insights.js +80 -0
- package/server-dist/dist/routes/insights.js.map +1 -0
- package/server-dist/dist/routes/messages.d.ts +4 -0
- package/server-dist/dist/routes/messages.d.ts.map +1 -0
- package/server-dist/dist/routes/messages.js +19 -0
- package/server-dist/dist/routes/messages.js.map +1 -0
- package/server-dist/dist/routes/projects.d.ts +4 -0
- package/server-dist/dist/routes/projects.d.ts.map +1 -0
- package/server-dist/dist/routes/projects.js +32 -0
- package/server-dist/dist/routes/projects.js.map +1 -0
- package/server-dist/dist/routes/sessions.d.ts +4 -0
- package/server-dist/dist/routes/sessions.d.ts.map +1 -0
- package/server-dist/dist/routes/sessions.js +65 -0
- package/server-dist/dist/routes/sessions.js.map +1 -0
- package/server-dist/dist/utils.d.ts +6 -0
- package/server-dist/dist/utils.d.ts.map +1 -0
- package/server-dist/dist/utils.js +9 -0
- package/server-dist/dist/utils.js.map +1 -0
- package/server-dist/index.d.ts +12 -0
- package/server-dist/index.d.ts.map +1 -0
- package/server-dist/index.js +92 -0
- package/server-dist/index.js.map +1 -0
- package/server-dist/llm/analysis.d.ts +80 -0
- package/server-dist/llm/analysis.d.ts.map +1 -0
- package/server-dist/llm/analysis.js +509 -0
- package/server-dist/llm/analysis.js.map +1 -0
- package/server-dist/llm/client.d.ts +27 -0
- package/server-dist/llm/client.d.ts.map +1 -0
- package/server-dist/llm/client.js +71 -0
- package/server-dist/llm/client.js.map +1 -0
- package/server-dist/llm/index.d.ts +7 -0
- package/server-dist/llm/index.d.ts.map +1 -0
- package/server-dist/llm/index.js +5 -0
- package/server-dist/llm/index.js.map +1 -0
- package/server-dist/llm/prompts.d.ts +73 -0
- package/server-dist/llm/prompts.d.ts.map +1 -0
- package/server-dist/llm/prompts.js +242 -0
- package/server-dist/llm/prompts.js.map +1 -0
- package/server-dist/llm/providers/anthropic.d.ts +3 -0
- package/server-dist/llm/providers/anthropic.d.ts.map +1 -0
- package/server-dist/llm/providers/anthropic.js +45 -0
- package/server-dist/llm/providers/anthropic.js.map +1 -0
- package/server-dist/llm/providers/gemini.d.ts +3 -0
- package/server-dist/llm/providers/gemini.d.ts.map +1 -0
- package/server-dist/llm/providers/gemini.js +51 -0
- package/server-dist/llm/providers/gemini.js.map +1 -0
- package/server-dist/llm/providers/ollama.d.ts +12 -0
- package/server-dist/llm/providers/ollama.d.ts.map +1 -0
- package/server-dist/llm/providers/ollama.js +61 -0
- package/server-dist/llm/providers/ollama.js.map +1 -0
- package/server-dist/llm/providers/openai.d.ts +3 -0
- package/server-dist/llm/providers/openai.d.ts.map +1 -0
- package/server-dist/llm/providers/openai.js +39 -0
- package/server-dist/llm/providers/openai.js.map +1 -0
- package/server-dist/llm/types.d.ts +22 -0
- package/server-dist/llm/types.d.ts.map +1 -0
- package/server-dist/llm/types.js +5 -0
- package/server-dist/llm/types.js.map +1 -0
- package/server-dist/routes/analysis.d.ts +4 -0
- package/server-dist/routes/analysis.d.ts.map +1 -0
- package/server-dist/routes/analysis.js +103 -0
- package/server-dist/routes/analysis.js.map +1 -0
- package/server-dist/routes/analytics.d.ts +4 -0
- package/server-dist/routes/analytics.d.ts.map +1 -0
- package/server-dist/routes/analytics.js +47 -0
- package/server-dist/routes/analytics.js.map +1 -0
- package/server-dist/routes/config.d.ts +4 -0
- package/server-dist/routes/config.d.ts.map +1 -0
- package/server-dist/routes/config.js +108 -0
- package/server-dist/routes/config.js.map +1 -0
- package/server-dist/routes/export.d.ts +4 -0
- package/server-dist/routes/export.d.ts.map +1 -0
- package/server-dist/routes/export.js +52 -0
- package/server-dist/routes/export.js.map +1 -0
- package/server-dist/routes/insights.d.ts +4 -0
- package/server-dist/routes/insights.d.ts.map +1 -0
- package/server-dist/routes/insights.js +80 -0
- package/server-dist/routes/insights.js.map +1 -0
- package/server-dist/routes/messages.d.ts +4 -0
- package/server-dist/routes/messages.d.ts.map +1 -0
- package/server-dist/routes/messages.js +19 -0
- package/server-dist/routes/messages.js.map +1 -0
- package/server-dist/routes/projects.d.ts +4 -0
- package/server-dist/routes/projects.d.ts.map +1 -0
- package/server-dist/routes/projects.js +32 -0
- package/server-dist/routes/projects.js.map +1 -0
- package/server-dist/routes/sessions.d.ts +4 -0
- package/server-dist/routes/sessions.d.ts.map +1 -0
- package/server-dist/routes/sessions.js +65 -0
- package/server-dist/routes/sessions.js.map +1 -0
- package/server-dist/utils.d.ts +6 -0
- package/server-dist/utils.d.ts.map +1 -0
- package/server-dist/utils.js +9 -0
- package/server-dist/utils.js.map +1 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
export interface SQLiteMessageRow {
|
|
2
|
+
id: string;
|
|
3
|
+
session_id: string;
|
|
4
|
+
type: 'user' | 'assistant' | 'system';
|
|
5
|
+
content: string;
|
|
6
|
+
thinking: string | null;
|
|
7
|
+
tool_calls: string;
|
|
8
|
+
tool_results: string;
|
|
9
|
+
usage: string | null;
|
|
10
|
+
timestamp: string;
|
|
11
|
+
parent_id: string | null;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Format SQLite message rows for LLM consumption.
|
|
15
|
+
* Handles snake_case fields and JSON-encoded tool_calls/tool_results.
|
|
16
|
+
*/
|
|
17
|
+
export declare function formatMessagesForAnalysis(messages: SQLiteMessageRow[]): string;
|
|
18
|
+
/**
|
|
19
|
+
* System prompt for session analysis.
|
|
20
|
+
*/
|
|
21
|
+
export declare const SESSION_ANALYSIS_SYSTEM_PROMPT = "You are an expert at analyzing software development conversations and extracting valuable insights. Your task is to analyze an AI coding session (a conversation between a user and an AI coding assistant) and extract structured insights.\n\nYou will identify:\n1. **Summary**: A high-level narrative of what was accomplished\n2. **Decisions**: Technical choices made, including reasoning and alternatives considered (max 3)\n3. **Learnings**: Technical discoveries, gotchas, problem-solving approaches, debugging strategies, or transferable knowledge (max 5)\n\nQuality Standards:\n- Only include insights you would write in a team knowledge base for future reference\n- Each insight MUST reference concrete details: specific file names, library names, error messages, API endpoints, or code patterns\n- Do not invent file names, APIs, errors, or details not present in the conversation\n- Rate your confidence in each insight's value (0-100). Only include insights you rate 70+.\n- It is better to return 0 insights in a category than to include generic or trivial ones\n- If a session is straightforward with no notable decisions or learnings, say so in the summary and leave other categories empty\n- The summary must mention the most important concrete artifact changed (file, endpoint, or test) if any\n\nDO NOT include insights like these (too generic/trivial):\n- \"Used debugging techniques to fix an issue\"\n- \"Made architectural decisions about the codebase\"\n- \"Implemented a new feature\" (the summary already covers this)\n- \"Used React hooks for state management\" (too generic without specifics)\n- \"Fixed a bug in the code\" (what bug? what was the root cause?)\n- Anything that restates the task without adding transferable knowledge\n\nRespond with valid JSON only, wrapped in <json>...</json> tags. Do not include any other text.";
|
|
22
|
+
/**
|
|
23
|
+
* Generate the user prompt for session analysis.
|
|
24
|
+
*/
|
|
25
|
+
export declare function generateSessionAnalysisPrompt(projectName: string, sessionSummary: string | null, formattedMessages: string): string;
|
|
26
|
+
export interface AnalysisResponse {
|
|
27
|
+
summary: {
|
|
28
|
+
title: string;
|
|
29
|
+
content: string;
|
|
30
|
+
bullets: string[];
|
|
31
|
+
};
|
|
32
|
+
decisions: Array<{
|
|
33
|
+
title: string;
|
|
34
|
+
content: string;
|
|
35
|
+
reasoning: string;
|
|
36
|
+
alternatives?: string[];
|
|
37
|
+
confidence?: number;
|
|
38
|
+
evidence?: string[];
|
|
39
|
+
}>;
|
|
40
|
+
learnings: Array<{
|
|
41
|
+
title: string;
|
|
42
|
+
content: string;
|
|
43
|
+
context: string;
|
|
44
|
+
confidence?: number;
|
|
45
|
+
evidence?: string[];
|
|
46
|
+
}>;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Parse the LLM response into structured insights.
|
|
50
|
+
*/
|
|
51
|
+
export declare function parseAnalysisResponse(response: string): AnalysisResponse | null;
|
|
52
|
+
export declare const PROMPT_QUALITY_SYSTEM_PROMPT = "You are an expert at analyzing how effectively humans communicate with AI coding assistants. Your task is to review a conversation between a user and Claude Code, and evaluate the user's prompting efficiency.\n\nYou will identify:\n1. **Wasted turns**: User messages that led to clarifications, corrections, or repeated instructions because the original prompt was unclear, missing context, or too vague.\n2. **Anti-patterns**: Recurring bad habits in the user's prompting style.\n3. **Efficiency score**: A 0-100 rating of how optimally the user communicated.\n4. **Actionable tips**: Specific improvements the user can make.\n\nGuidelines:\n- Focus on USER messages only \u2014 don't critique the assistant's responses\n- A \"wasted turn\" is when the user had to send a follow-up message to clarify, correct, or repeat something that could have been included in the original prompt\n- Only mark a wasted turn if the assistant explicitly asked for clarification or corrected a misunderstanding\n- Common anti-patterns: vague instructions, missing file paths, not providing error messages, incomplete requirements, repeated instructions, not specifying what \"it\" refers to\n- Be constructive, not judgmental \u2014 the goal is to help users improve\n- Consider the context: some clarification exchanges are normal and expected\n- A score of 100 means every user message was perfectly clear and complete\n- A score of 50 means about half the messages could have been more efficient\n\nRespond with valid JSON only, wrapped in <json>...</json> tags. Do not include any other text.";
|
|
53
|
+
export declare function generatePromptQualityPrompt(projectName: string, formattedMessages: string, messageCount: number): string;
|
|
54
|
+
export interface WastedTurn {
|
|
55
|
+
messageIndex: number;
|
|
56
|
+
reason: string;
|
|
57
|
+
suggestedRewrite: string;
|
|
58
|
+
}
|
|
59
|
+
export interface AntiPattern {
|
|
60
|
+
name: string;
|
|
61
|
+
count: number;
|
|
62
|
+
examples: string[];
|
|
63
|
+
}
|
|
64
|
+
export interface PromptQualityResponse {
|
|
65
|
+
efficiencyScore: number;
|
|
66
|
+
potentialMessageReduction: number;
|
|
67
|
+
overallAssessment: string;
|
|
68
|
+
wastedTurns: WastedTurn[];
|
|
69
|
+
antiPatterns: AntiPattern[];
|
|
70
|
+
tips: string[];
|
|
71
|
+
}
|
|
72
|
+
export declare function parsePromptQualityResponse(response: string): PromptQualityResponse | null;
|
|
73
|
+
//# sourceMappingURL=prompts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/llm/prompts.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAUD;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,MAAM,CA8C9E;AAED;;GAEG;AACH,eAAO,MAAM,8BAA8B,k0DAwBoD,CAAC;AAEhG;;GAEG;AACH,wBAAgB,6BAA6B,CAC3C,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,GAAG,IAAI,EAC7B,iBAAiB,EAAE,MAAM,GACxB,MAAM,CAyCR;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC;IACF,SAAS,EAAE,KAAK,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;QACxB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC,CAAC;IACH,SAAS,EAAE,KAAK,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC,CAAC;CACJ;AASD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAuB/E;AAID,eAAO,MAAM,4BAA4B,kjDAkBsD,CAAC;AAEhG,wBAAgB,2BAA2B,CACzC,WAAW,EAAE,MAAM,EACnB,iBAAiB,EAAE,MAAM,EACzB,YAAY,EAAE,MAAM,GACnB,MAAM,CA2CR;AAED,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,eAAe,EAAE,MAAM,CAAC;IACxB,yBAAyB,EAAE,MAAM,CAAC;IAClC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,qBAAqB,GAAG,IAAI,CA2BzF"}
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
// Analysis prompts and response parsers for LLM session analysis.
|
|
2
|
+
// Ported from web repo (src/lib/llm/prompts.ts) with SQLite-aware message formatting.
|
|
3
|
+
/**
|
|
4
|
+
* Format SQLite message rows for LLM consumption.
|
|
5
|
+
* Handles snake_case fields and JSON-encoded tool_calls/tool_results.
|
|
6
|
+
*/
|
|
7
|
+
export function formatMessagesForAnalysis(messages) {
|
|
8
|
+
let userIndex = 0;
|
|
9
|
+
let assistantIndex = 0;
|
|
10
|
+
return messages
|
|
11
|
+
.map((m) => {
|
|
12
|
+
const role = m.type === 'user' ? 'User' : m.type === 'assistant' ? 'Assistant' : 'System';
|
|
13
|
+
const roleLabel = role === 'User'
|
|
14
|
+
? `User#${userIndex++}`
|
|
15
|
+
: role === 'Assistant'
|
|
16
|
+
? `Assistant#${assistantIndex++}`
|
|
17
|
+
: 'System';
|
|
18
|
+
// Parse JSON-encoded tool_calls
|
|
19
|
+
let toolCalls = [];
|
|
20
|
+
try {
|
|
21
|
+
toolCalls = m.tool_calls ? JSON.parse(m.tool_calls) : [];
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
toolCalls = [];
|
|
25
|
+
}
|
|
26
|
+
// Parse JSON-encoded tool_results
|
|
27
|
+
let toolResults = [];
|
|
28
|
+
try {
|
|
29
|
+
toolResults = m.tool_results ? JSON.parse(m.tool_results) : [];
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
toolResults = [];
|
|
33
|
+
}
|
|
34
|
+
const toolInfo = toolCalls.length > 0
|
|
35
|
+
? `\n[Tools used: ${toolCalls.map(t => t.name || 'unknown').join(', ')}]`
|
|
36
|
+
: '';
|
|
37
|
+
// Include thinking content — capped at 1000 chars to stay within token budget
|
|
38
|
+
const thinkingInfo = m.thinking
|
|
39
|
+
? `\n[Thinking: ${m.thinking.slice(0, 1000)}]`
|
|
40
|
+
: '';
|
|
41
|
+
// Include tool results for context — 200 chars per result
|
|
42
|
+
const resultInfo = toolResults.length > 0
|
|
43
|
+
? `\n[Tool results: ${toolResults.map(r => (r.output || '').slice(0, 200)).join(' | ')}]`
|
|
44
|
+
: '';
|
|
45
|
+
return `### ${roleLabel}:\n${m.content}${thinkingInfo}${toolInfo}${resultInfo}`;
|
|
46
|
+
})
|
|
47
|
+
.join('\n\n');
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* System prompt for session analysis.
|
|
51
|
+
*/
|
|
52
|
+
export const SESSION_ANALYSIS_SYSTEM_PROMPT = `You are an expert at analyzing software development conversations and extracting valuable insights. Your task is to analyze an AI coding session (a conversation between a user and an AI coding assistant) and extract structured insights.
|
|
53
|
+
|
|
54
|
+
You will identify:
|
|
55
|
+
1. **Summary**: A high-level narrative of what was accomplished
|
|
56
|
+
2. **Decisions**: Technical choices made, including reasoning and alternatives considered (max 3)
|
|
57
|
+
3. **Learnings**: Technical discoveries, gotchas, problem-solving approaches, debugging strategies, or transferable knowledge (max 5)
|
|
58
|
+
|
|
59
|
+
Quality Standards:
|
|
60
|
+
- Only include insights you would write in a team knowledge base for future reference
|
|
61
|
+
- Each insight MUST reference concrete details: specific file names, library names, error messages, API endpoints, or code patterns
|
|
62
|
+
- Do not invent file names, APIs, errors, or details not present in the conversation
|
|
63
|
+
- Rate your confidence in each insight's value (0-100). Only include insights you rate 70+.
|
|
64
|
+
- It is better to return 0 insights in a category than to include generic or trivial ones
|
|
65
|
+
- If a session is straightforward with no notable decisions or learnings, say so in the summary and leave other categories empty
|
|
66
|
+
- The summary must mention the most important concrete artifact changed (file, endpoint, or test) if any
|
|
67
|
+
|
|
68
|
+
DO NOT include insights like these (too generic/trivial):
|
|
69
|
+
- "Used debugging techniques to fix an issue"
|
|
70
|
+
- "Made architectural decisions about the codebase"
|
|
71
|
+
- "Implemented a new feature" (the summary already covers this)
|
|
72
|
+
- "Used React hooks for state management" (too generic without specifics)
|
|
73
|
+
- "Fixed a bug in the code" (what bug? what was the root cause?)
|
|
74
|
+
- Anything that restates the task without adding transferable knowledge
|
|
75
|
+
|
|
76
|
+
Respond with valid JSON only, wrapped in <json>...</json> tags. Do not include any other text.`;
|
|
77
|
+
/**
|
|
78
|
+
* Generate the user prompt for session analysis.
|
|
79
|
+
*/
|
|
80
|
+
export function generateSessionAnalysisPrompt(projectName, sessionSummary, formattedMessages) {
|
|
81
|
+
return `Analyze this AI coding session and extract insights.
|
|
82
|
+
|
|
83
|
+
Project: ${projectName}
|
|
84
|
+
${sessionSummary ? `Session Summary: ${sessionSummary}\n` : ''}
|
|
85
|
+
--- CONVERSATION ---
|
|
86
|
+
${formattedMessages}
|
|
87
|
+
--- END CONVERSATION ---
|
|
88
|
+
|
|
89
|
+
Extract insights in this JSON format:
|
|
90
|
+
{
|
|
91
|
+
"summary": {
|
|
92
|
+
"title": "Brief title describing main accomplishment (max 60 chars)",
|
|
93
|
+
"content": "2-3 sentence narrative of what was accomplished",
|
|
94
|
+
"bullets": ["Key point 1", "Key point 2", "Key point 3"]
|
|
95
|
+
},
|
|
96
|
+
"decisions": [
|
|
97
|
+
{
|
|
98
|
+
"title": "The specific decision made (max 60 chars)",
|
|
99
|
+
"content": "Detailed explanation with concrete details",
|
|
100
|
+
"reasoning": "Why this choice was made over alternatives",
|
|
101
|
+
"alternatives": ["Alternative 1 considered", "Alternative 2 considered"],
|
|
102
|
+
"confidence": 85,
|
|
103
|
+
"evidence": ["User#4: ...", "Assistant#5: ..."]
|
|
104
|
+
}
|
|
105
|
+
],
|
|
106
|
+
"learnings": [
|
|
107
|
+
{
|
|
108
|
+
"title": "Specific thing learned (max 60 chars)",
|
|
109
|
+
"content": "Detailed explanation with concrete details",
|
|
110
|
+
"context": "When/where this applies and why it matters",
|
|
111
|
+
"confidence": 80,
|
|
112
|
+
"evidence": ["User#7: ...", "Assistant#8: ..."]
|
|
113
|
+
}
|
|
114
|
+
]
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
Only include insights rated 70+ confidence. If you cannot cite evidence, drop the insight. Return empty arrays for categories with no strong insights. Max 3 decisions, 5 learnings.
|
|
118
|
+
Evidence should reference the labeled turns in the conversation (e.g., "User#2", "Assistant#5").
|
|
119
|
+
|
|
120
|
+
Respond with valid JSON only, wrapped in <json>...</json> tags. Do not include any other text.`;
|
|
121
|
+
}
|
|
122
|
+
function extractJsonPayload(response) {
|
|
123
|
+
const tagged = response.match(/<json>\s*([\s\S]*?)\s*<\/json>/i);
|
|
124
|
+
if (tagged?.[1])
|
|
125
|
+
return tagged[1].trim();
|
|
126
|
+
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
127
|
+
return jsonMatch ? jsonMatch[0] : null;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Parse the LLM response into structured insights.
|
|
131
|
+
*/
|
|
132
|
+
export function parseAnalysisResponse(response) {
|
|
133
|
+
try {
|
|
134
|
+
const jsonPayload = extractJsonPayload(response);
|
|
135
|
+
if (!jsonPayload) {
|
|
136
|
+
console.error('No JSON found in analysis response');
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
const parsed = JSON.parse(jsonPayload);
|
|
140
|
+
if (!parsed.summary || typeof parsed.summary.title !== 'string') {
|
|
141
|
+
console.error('Invalid analysis response structure');
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
parsed.decisions = parsed.decisions || [];
|
|
145
|
+
parsed.learnings = parsed.learnings || [];
|
|
146
|
+
return parsed;
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
console.error('Failed to parse analysis response:', error);
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// --- Prompt Quality Analysis ---
|
|
154
|
+
export const PROMPT_QUALITY_SYSTEM_PROMPT = `You are an expert at analyzing how effectively humans communicate with AI coding assistants. Your task is to review a conversation between a user and Claude Code, and evaluate the user's prompting efficiency.
|
|
155
|
+
|
|
156
|
+
You will identify:
|
|
157
|
+
1. **Wasted turns**: User messages that led to clarifications, corrections, or repeated instructions because the original prompt was unclear, missing context, or too vague.
|
|
158
|
+
2. **Anti-patterns**: Recurring bad habits in the user's prompting style.
|
|
159
|
+
3. **Efficiency score**: A 0-100 rating of how optimally the user communicated.
|
|
160
|
+
4. **Actionable tips**: Specific improvements the user can make.
|
|
161
|
+
|
|
162
|
+
Guidelines:
|
|
163
|
+
- Focus on USER messages only — don't critique the assistant's responses
|
|
164
|
+
- A "wasted turn" is when the user had to send a follow-up message to clarify, correct, or repeat something that could have been included in the original prompt
|
|
165
|
+
- Only mark a wasted turn if the assistant explicitly asked for clarification or corrected a misunderstanding
|
|
166
|
+
- Common anti-patterns: vague instructions, missing file paths, not providing error messages, incomplete requirements, repeated instructions, not specifying what "it" refers to
|
|
167
|
+
- Be constructive, not judgmental — the goal is to help users improve
|
|
168
|
+
- Consider the context: some clarification exchanges are normal and expected
|
|
169
|
+
- A score of 100 means every user message was perfectly clear and complete
|
|
170
|
+
- A score of 50 means about half the messages could have been more efficient
|
|
171
|
+
|
|
172
|
+
Respond with valid JSON only, wrapped in <json>...</json> tags. Do not include any other text.`;
|
|
173
|
+
export function generatePromptQualityPrompt(projectName, formattedMessages, messageCount) {
|
|
174
|
+
return `Analyze the user's prompting efficiency in this AI coding session.
|
|
175
|
+
|
|
176
|
+
Project: ${projectName}
|
|
177
|
+
Total messages: ${messageCount}
|
|
178
|
+
|
|
179
|
+
--- CONVERSATION ---
|
|
180
|
+
${formattedMessages}
|
|
181
|
+
--- END CONVERSATION ---
|
|
182
|
+
|
|
183
|
+
Evaluate the user's prompting quality and respond with this JSON format:
|
|
184
|
+
{
|
|
185
|
+
"efficiencyScore": 75,
|
|
186
|
+
"potentialMessageReduction": 3,
|
|
187
|
+
"overallAssessment": "2-3 sentence summary of the user's prompting style and efficiency",
|
|
188
|
+
"wastedTurns": [
|
|
189
|
+
{
|
|
190
|
+
"messageIndex": 5,
|
|
191
|
+
"reason": "Missing context — didn't specify which file to modify",
|
|
192
|
+
"suggestedRewrite": "A better version of the user's original message that would have avoided the follow-up"
|
|
193
|
+
}
|
|
194
|
+
],
|
|
195
|
+
"antiPatterns": [
|
|
196
|
+
{
|
|
197
|
+
"name": "Vague Instructions",
|
|
198
|
+
"count": 3,
|
|
199
|
+
"examples": ["fix it", "make it work", "do the thing"]
|
|
200
|
+
}
|
|
201
|
+
],
|
|
202
|
+
"tips": [
|
|
203
|
+
"Always include file paths when asking to modify code",
|
|
204
|
+
"Provide error messages verbatim when reporting bugs"
|
|
205
|
+
]
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
Rules:
|
|
209
|
+
- messageIndex refers to the 0-based index of the USER message, as labeled in the conversation (e.g., User#0)
|
|
210
|
+
- Only include genuinely wasted turns, not normal back-and-forth
|
|
211
|
+
- Tips should be specific and actionable, not generic; include the relevant user message index in parentheses
|
|
212
|
+
- If the user prompted well, say so — don't manufacture issues
|
|
213
|
+
- potentialMessageReduction is how many fewer messages the session could have taken with better prompts
|
|
214
|
+
|
|
215
|
+
Respond with valid JSON only, wrapped in <json>...</json> tags. Do not include any other text.`;
|
|
216
|
+
}
|
|
217
|
+
export function parsePromptQualityResponse(response) {
|
|
218
|
+
try {
|
|
219
|
+
const jsonPayload = extractJsonPayload(response);
|
|
220
|
+
if (!jsonPayload) {
|
|
221
|
+
console.error('No JSON found in prompt quality response');
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
const parsed = JSON.parse(jsonPayload);
|
|
225
|
+
if (typeof parsed.efficiencyScore !== 'number') {
|
|
226
|
+
console.error('Invalid prompt quality response: missing efficiencyScore');
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
parsed.efficiencyScore = Math.max(0, Math.min(100, Math.round(parsed.efficiencyScore)));
|
|
230
|
+
parsed.potentialMessageReduction = parsed.potentialMessageReduction || 0;
|
|
231
|
+
parsed.overallAssessment = parsed.overallAssessment || '';
|
|
232
|
+
parsed.wastedTurns = parsed.wastedTurns || [];
|
|
233
|
+
parsed.antiPatterns = parsed.antiPatterns || [];
|
|
234
|
+
parsed.tips = parsed.tips || [];
|
|
235
|
+
return parsed;
|
|
236
|
+
}
|
|
237
|
+
catch (error) {
|
|
238
|
+
console.error('Failed to parse prompt quality response:', error);
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/llm/prompts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/anthropic.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAwC,MAAM,aAAa,CAAC;AAEnF,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,CAiD9E"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Anthropic provider implementation (server-side, no browser dependencies)
|
|
2
|
+
// Note: 'anthropic-dangerous-direct-browser-access' header is intentionally omitted here —
|
|
3
|
+
// this runs server-side where direct API access is safe and expected.
|
|
4
|
+
export function createAnthropicClient(apiKey, model) {
|
|
5
|
+
return {
|
|
6
|
+
provider: 'anthropic',
|
|
7
|
+
model,
|
|
8
|
+
async chat(messages, options) {
|
|
9
|
+
// Extract system message if present
|
|
10
|
+
const systemMessage = messages.find(m => m.role === 'system');
|
|
11
|
+
const chatMessages = messages.filter(m => m.role !== 'system');
|
|
12
|
+
const response = await fetch('https://api.anthropic.com/v1/messages', {
|
|
13
|
+
method: 'POST',
|
|
14
|
+
headers: {
|
|
15
|
+
'Content-Type': 'application/json',
|
|
16
|
+
'x-api-key': apiKey,
|
|
17
|
+
'anthropic-version': '2023-06-01',
|
|
18
|
+
},
|
|
19
|
+
signal: options?.signal,
|
|
20
|
+
body: JSON.stringify({
|
|
21
|
+
model,
|
|
22
|
+
max_tokens: 4096,
|
|
23
|
+
system: systemMessage?.content,
|
|
24
|
+
messages: chatMessages.map(m => ({ role: m.role, content: m.content })),
|
|
25
|
+
}),
|
|
26
|
+
});
|
|
27
|
+
if (!response.ok) {
|
|
28
|
+
const error = await response.json().catch(() => ({}));
|
|
29
|
+
throw new Error(error.error?.message || `Anthropic API error: ${response.status}`);
|
|
30
|
+
}
|
|
31
|
+
const data = await response.json();
|
|
32
|
+
return {
|
|
33
|
+
content: data.content[0]?.text || '',
|
|
34
|
+
usage: data.usage ? {
|
|
35
|
+
inputTokens: data.usage.input_tokens,
|
|
36
|
+
outputTokens: data.usage.output_tokens,
|
|
37
|
+
} : undefined,
|
|
38
|
+
};
|
|
39
|
+
},
|
|
40
|
+
estimateTokens(text) {
|
|
41
|
+
return Math.ceil(text.length / 4);
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=anthropic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../../src/llm/providers/anthropic.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,2FAA2F;AAC3F,sEAAsE;AAItE,MAAM,UAAU,qBAAqB,CAAC,MAAc,EAAE,KAAa;IACjE,OAAO;QACL,QAAQ,EAAE,WAAW;QACrB,KAAK;QAEL,KAAK,CAAC,IAAI,CAAC,QAAsB,EAAE,OAAqB;YACtD,oCAAoC;YACpC,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;YAC9D,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;YAE/D,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,uCAAuC,EAAE;gBACpE,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,WAAW,EAAE,MAAM;oBACnB,mBAAmB,EAAE,YAAY;iBAClC;gBACD,MAAM,EAAE,OAAO,EAAE,MAAM;gBACvB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,KAAK;oBACL,UAAU,EAAE,IAAI;oBAChB,MAAM,EAAE,aAAa,EAAE,OAAO;oBAC9B,QAAQ,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;iBACxE,CAAC;aACH,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAqC,CAAC;gBAC1F,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,IAAI,wBAAwB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;YACrF,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAG/B,CAAC;YAEF,OAAO;gBACL,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,EAAE;gBACpC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;oBAClB,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY;oBACpC,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,aAAa;iBACvC,CAAC,CAAC,CAAC,SAAS;aACd,CAAC;QACJ,CAAC;QAED,cAAc,CAAC,IAAY;YACzB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACpC,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/gemini.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAwC,MAAM,aAAa,CAAC;AAEnF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,CA+D3E"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Gemini provider implementation (server-side, no browser dependencies)
|
|
2
|
+
export function createGeminiClient(apiKey, model) {
|
|
3
|
+
return {
|
|
4
|
+
provider: 'gemini',
|
|
5
|
+
model,
|
|
6
|
+
async chat(messages, options) {
|
|
7
|
+
const systemMessage = messages.find(m => m.role === 'system');
|
|
8
|
+
const chatMessages = messages.filter(m => m.role !== 'system');
|
|
9
|
+
const contents = chatMessages.map(m => ({
|
|
10
|
+
role: m.role === 'assistant' ? 'model' : 'user',
|
|
11
|
+
parts: [{ text: m.content }],
|
|
12
|
+
}));
|
|
13
|
+
const body = {
|
|
14
|
+
contents,
|
|
15
|
+
generationConfig: {
|
|
16
|
+
temperature: 0.7,
|
|
17
|
+
maxOutputTokens: 4096,
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
if (systemMessage) {
|
|
21
|
+
body.systemInstruction = {
|
|
22
|
+
parts: [{ text: systemMessage.content }],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
// Gemini REST API requires the API key as a query parameter (not a header).
|
|
26
|
+
// This is Google's documented authentication pattern for the Generative Language API.
|
|
27
|
+
const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${apiKey}`, {
|
|
28
|
+
method: 'POST',
|
|
29
|
+
headers: { 'Content-Type': 'application/json' },
|
|
30
|
+
signal: options?.signal,
|
|
31
|
+
body: JSON.stringify(body),
|
|
32
|
+
});
|
|
33
|
+
if (!response.ok) {
|
|
34
|
+
const error = await response.json().catch(() => ({}));
|
|
35
|
+
throw new Error(error.error?.message || `Gemini API error: ${response.status}`);
|
|
36
|
+
}
|
|
37
|
+
const data = await response.json();
|
|
38
|
+
return {
|
|
39
|
+
content: data.candidates?.[0]?.content?.parts?.[0]?.text || '',
|
|
40
|
+
usage: data.usageMetadata ? {
|
|
41
|
+
inputTokens: data.usageMetadata.promptTokenCount,
|
|
42
|
+
outputTokens: data.usageMetadata.candidatesTokenCount,
|
|
43
|
+
} : undefined,
|
|
44
|
+
};
|
|
45
|
+
},
|
|
46
|
+
estimateTokens(text) {
|
|
47
|
+
return Math.ceil(text.length / 4);
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=gemini.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../../src/llm/providers/gemini.ts"],"names":[],"mappings":"AAAA,wEAAwE;AAIxE,MAAM,UAAU,kBAAkB,CAAC,MAAc,EAAE,KAAa;IAC9D,OAAO;QACL,QAAQ,EAAE,QAAQ;QAClB,KAAK;QAEL,KAAK,CAAC,IAAI,CAAC,QAAsB,EAAE,OAAqB;YACtD,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;YAC9D,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;YAE/D,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACtC,IAAI,EAAE,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM;gBAC/C,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;aAC7B,CAAC,CAAC,CAAC;YAEJ,MAAM,IAAI,GAA4B;gBACpC,QAAQ;gBACR,gBAAgB,EAAE;oBAChB,WAAW,EAAE,GAAG;oBAChB,eAAe,EAAE,IAAI;iBACtB;aACF,CAAC;YAEF,IAAI,aAAa,EAAE,CAAC;gBAClB,IAAI,CAAC,iBAAiB,GAAG;oBACvB,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,aAAa,CAAC,OAAO,EAAE,CAAC;iBACzC,CAAC;YACJ,CAAC;YAED,4EAA4E;YAC5E,sFAAsF;YACtF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAC1B,2DAA2D,KAAK,wBAAwB,MAAM,EAAE,EAChG;gBACE,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,MAAM,EAAE,OAAO,EAAE,MAAM;gBACvB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;aAC3B,CACF,CAAC;YAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAqC,CAAC;gBAC1F,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,IAAI,qBAAqB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;YAClF,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAG/B,CAAC;YAEF,OAAO;gBACL,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,EAAE;gBAC9D,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC;oBAC1B,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,gBAAgB;oBAChD,YAAY,EAAE,IAAI,CAAC,aAAa,CAAC,oBAAoB;iBACtD,CAAC,CAAC,CAAC,SAAS;aACd,CAAC;QACJ,CAAC;QAED,cAAc,CAAC,IAAY;YACzB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACpC,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { LLMClient } from '../types.js';
|
|
2
|
+
export declare function createOllamaClient(model: string, baseUrl?: string): LLMClient;
|
|
3
|
+
/**
|
|
4
|
+
* Discover installed Ollama models by querying the local API.
|
|
5
|
+
* Returns empty array if Ollama is not running or unreachable.
|
|
6
|
+
*/
|
|
7
|
+
export declare function discoverOllamaModels(baseUrl?: string): Promise<Array<{
|
|
8
|
+
name: string;
|
|
9
|
+
size: number;
|
|
10
|
+
modifiedAt: string;
|
|
11
|
+
}>>;
|
|
12
|
+
//# sourceMappingURL=ollama.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ollama.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/ollama.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAwC,MAAM,aAAa,CAAC;AAInF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CA4C7E;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAgBpE"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Ollama provider implementation (local models, no API key required)
|
|
2
|
+
const DEFAULT_OLLAMA_URL = 'http://localhost:11434';
|
|
3
|
+
export function createOllamaClient(model, baseUrl) {
|
|
4
|
+
const url = baseUrl || DEFAULT_OLLAMA_URL;
|
|
5
|
+
return {
|
|
6
|
+
provider: 'ollama',
|
|
7
|
+
model,
|
|
8
|
+
async chat(messages, options) {
|
|
9
|
+
const response = await fetch(`${url}/api/chat`, {
|
|
10
|
+
method: 'POST',
|
|
11
|
+
headers: { 'Content-Type': 'application/json' },
|
|
12
|
+
signal: options?.signal,
|
|
13
|
+
body: JSON.stringify({
|
|
14
|
+
model,
|
|
15
|
+
messages: messages.map(m => ({ role: m.role, content: m.content })),
|
|
16
|
+
stream: false,
|
|
17
|
+
options: { temperature: 0.7 },
|
|
18
|
+
}),
|
|
19
|
+
});
|
|
20
|
+
if (!response.ok) {
|
|
21
|
+
const error = await response.text().catch(() => '');
|
|
22
|
+
throw new Error(`Ollama API error: ${response.status}${error ? ` - ${error}` : ''}`);
|
|
23
|
+
}
|
|
24
|
+
const data = await response.json();
|
|
25
|
+
return {
|
|
26
|
+
content: data.message?.content || '',
|
|
27
|
+
usage: {
|
|
28
|
+
inputTokens: data.prompt_eval_count || 0,
|
|
29
|
+
outputTokens: data.eval_count || 0,
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
estimateTokens(text) {
|
|
34
|
+
return Math.ceil(text.length / 4);
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Discover installed Ollama models by querying the local API.
|
|
40
|
+
* Returns empty array if Ollama is not running or unreachable.
|
|
41
|
+
*/
|
|
42
|
+
export async function discoverOllamaModels(baseUrl) {
|
|
43
|
+
const url = baseUrl || DEFAULT_OLLAMA_URL;
|
|
44
|
+
try {
|
|
45
|
+
const response = await fetch(`${url}/api/tags`, {
|
|
46
|
+
signal: AbortSignal.timeout(3000),
|
|
47
|
+
});
|
|
48
|
+
if (!response.ok)
|
|
49
|
+
return [];
|
|
50
|
+
const data = await response.json();
|
|
51
|
+
return (data.models || []).map(m => ({
|
|
52
|
+
name: m.name,
|
|
53
|
+
size: m.size,
|
|
54
|
+
modifiedAt: m.modified_at,
|
|
55
|
+
}));
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=ollama.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../../src/llm/providers/ollama.ts"],"names":[],"mappings":"AAAA,qEAAqE;AAIrE,MAAM,kBAAkB,GAAG,wBAAwB,CAAC;AAEpD,MAAM,UAAU,kBAAkB,CAAC,KAAa,EAAE,OAAgB;IAChE,MAAM,GAAG,GAAG,OAAO,IAAI,kBAAkB,CAAC;IAE1C,OAAO;QACL,QAAQ,EAAE,QAAQ;QAClB,KAAK;QAEL,KAAK,CAAC,IAAI,CAAC,QAAsB,EAAE,OAAqB;YACtD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,GAAG,WAAW,EAAE;gBAC9C,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,MAAM,EAAE,OAAO,EAAE,MAAM;gBACvB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,KAAK;oBACL,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;oBACnE,MAAM,EAAE,KAAK;oBACb,OAAO,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE;iBAC9B,CAAC;aACH,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;gBACpD,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACvF,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAI/B,CAAC;YAEF,OAAO;gBACL,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,IAAI,EAAE;gBACpC,KAAK,EAAE;oBACL,WAAW,EAAE,IAAI,CAAC,iBAAiB,IAAI,CAAC;oBACxC,YAAY,EAAE,IAAI,CAAC,UAAU,IAAI,CAAC;iBACnC;aACF,CAAC;QACJ,CAAC;QAED,cAAc,CAAC,IAAY;YACzB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACpC,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,OAAgB;IAEhB,MAAM,GAAG,GAAG,OAAO,IAAI,kBAAkB,CAAC;IAC1C,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,GAAG,WAAW,EAAE;YAC9C,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC;SAClC,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,CAAC,EAAE;YAAE,OAAO,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAA6E,CAAC;QAC9G,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACnC,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,UAAU,EAAE,CAAC,CAAC,WAAW;SAC1B,CAAC,CAAC,CAAC;IACN,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../../src/llm/providers/openai.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAwC,MAAM,aAAa,CAAC;AAEnF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,CA4C3E"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// OpenAI provider implementation (server-side, no browser dependencies)
|
|
2
|
+
export function createOpenAIClient(apiKey, model) {
|
|
3
|
+
return {
|
|
4
|
+
provider: 'openai',
|
|
5
|
+
model,
|
|
6
|
+
async chat(messages, options) {
|
|
7
|
+
const response = await fetch('https://api.openai.com/v1/chat/completions', {
|
|
8
|
+
method: 'POST',
|
|
9
|
+
headers: {
|
|
10
|
+
'Content-Type': 'application/json',
|
|
11
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
12
|
+
},
|
|
13
|
+
signal: options?.signal,
|
|
14
|
+
body: JSON.stringify({
|
|
15
|
+
model,
|
|
16
|
+
messages: messages.map(m => ({ role: m.role, content: m.content })),
|
|
17
|
+
temperature: 0.7,
|
|
18
|
+
}),
|
|
19
|
+
});
|
|
20
|
+
if (!response.ok) {
|
|
21
|
+
const error = await response.json().catch(() => ({}));
|
|
22
|
+
throw new Error(error.error?.message || `OpenAI API error: ${response.status}`);
|
|
23
|
+
}
|
|
24
|
+
const data = await response.json();
|
|
25
|
+
return {
|
|
26
|
+
content: data.choices[0]?.message?.content || '',
|
|
27
|
+
usage: data.usage ? {
|
|
28
|
+
inputTokens: data.usage.prompt_tokens,
|
|
29
|
+
outputTokens: data.usage.completion_tokens,
|
|
30
|
+
} : undefined,
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
estimateTokens(text) {
|
|
34
|
+
// Rough estimate: ~4 characters per token for English
|
|
35
|
+
return Math.ceil(text.length / 4);
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=openai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.js","sourceRoot":"","sources":["../../../src/llm/providers/openai.ts"],"names":[],"mappings":"AAAA,wEAAwE;AAIxE,MAAM,UAAU,kBAAkB,CAAC,MAAc,EAAE,KAAa;IAC9D,OAAO;QACL,QAAQ,EAAE,QAAQ;QAClB,KAAK;QAEL,KAAK,CAAC,IAAI,CAAC,QAAsB,EAAE,OAAqB;YACtD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,4CAA4C,EAAE;gBACzE,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,eAAe,EAAE,UAAU,MAAM,EAAE;iBACpC;gBACD,MAAM,EAAE,OAAO,EAAE,MAAM;gBACvB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,KAAK;oBACL,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;oBACnE,WAAW,EAAE,GAAG;iBACjB,CAAC;aACH,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAqC,CAAC;gBAC1F,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,IAAI,qBAAqB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;YAClF,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAG/B,CAAC;YAEF,OAAO;gBACL,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE;gBAChD,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;oBAClB,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,aAAa;oBACrC,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,iBAAiB;iBAC3C,CAAC,CAAC,CAAC,SAAS;aACd,CAAC;QACJ,CAAC;QAED,cAAc,CAAC,IAAY;YACzB,sDAAsD;YACtD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACpC,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type { LLMProvider, LLMProviderConfig, ProviderInfo, ProviderModelOption } from '@code-insights/cli/types';
|
|
2
|
+
export interface LLMMessage {
|
|
3
|
+
role: 'system' | 'user' | 'assistant';
|
|
4
|
+
content: string;
|
|
5
|
+
}
|
|
6
|
+
export interface LLMResponse {
|
|
7
|
+
content: string;
|
|
8
|
+
usage?: {
|
|
9
|
+
inputTokens: number;
|
|
10
|
+
outputTokens: number;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export interface ChatOptions {
|
|
14
|
+
signal?: AbortSignal;
|
|
15
|
+
}
|
|
16
|
+
export interface LLMClient {
|
|
17
|
+
chat(messages: LLMMessage[], options?: ChatOptions): Promise<LLMResponse>;
|
|
18
|
+
estimateTokens(text: string): number;
|
|
19
|
+
readonly provider: string;
|
|
20
|
+
readonly model: string;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/llm/types.ts"],"names":[],"mappings":"AAIA,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAElH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE;QACN,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC1E,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// LLM abstraction types for the server-side LLM engine.
|
|
2
|
+
// Provider metadata (PROVIDERS constant) lives in cli/src/constants/llm-providers.ts.
|
|
3
|
+
// LLMProvider, LLMProviderConfig, ProviderInfo are imported from CLI types (single source of truth).
|
|
4
|
+
export {};
|
|
5
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/llm/types.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,sFAAsF;AACtF,qGAAqG"}
|