@code-insights/cli 2.1.0 → 3.0.1

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 (271) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +146 -156
  3. package/dashboard-dist/assets/index-BMhL7wL8.css +1 -0
  4. package/dashboard-dist/assets/index-CuCBzQyQ.js +548 -0
  5. package/dashboard-dist/dist/assets/index-BMhL7wL8.css +1 -0
  6. package/dashboard-dist/dist/assets/index-CUWKxcRo.js +548 -0
  7. package/dashboard-dist/dist/assets/index-CuCBzQyQ.js +548 -0
  8. package/dashboard-dist/dist/favicon.svg +4 -0
  9. package/dashboard-dist/dist/index.html +33 -0
  10. package/dashboard-dist/favicon.svg +4 -0
  11. package/dashboard-dist/index.html +33 -0
  12. package/dist/commands/config.d.ts.map +1 -1
  13. package/dist/commands/config.js +188 -69
  14. package/dist/commands/config.js.map +1 -1
  15. package/dist/commands/dashboard.d.ts +16 -0
  16. package/dist/commands/dashboard.d.ts.map +1 -0
  17. package/dist/commands/dashboard.js +82 -0
  18. package/dist/commands/dashboard.js.map +1 -0
  19. package/dist/commands/init.d.ts +3 -4
  20. package/dist/commands/init.d.ts.map +1 -1
  21. package/dist/commands/init.js +24 -201
  22. package/dist/commands/init.js.map +1 -1
  23. package/dist/commands/install-hook.d.ts.map +1 -1
  24. package/dist/commands/install-hook.js +4 -21
  25. package/dist/commands/install-hook.js.map +1 -1
  26. package/dist/commands/open.d.ts +2 -1
  27. package/dist/commands/open.d.ts.map +1 -1
  28. package/dist/commands/open.js +10 -21
  29. package/dist/commands/open.js.map +1 -1
  30. package/dist/commands/reset.d.ts.map +1 -1
  31. package/dist/commands/reset.js +38 -69
  32. package/dist/commands/reset.js.map +1 -1
  33. package/dist/commands/stats/actions/error-handler.d.ts.map +1 -1
  34. package/dist/commands/stats/actions/error-handler.js +1 -11
  35. package/dist/commands/stats/actions/error-handler.js.map +1 -1
  36. package/dist/commands/stats/data/local.d.ts +0 -2
  37. package/dist/commands/stats/data/local.d.ts.map +1 -1
  38. package/dist/commands/stats/data/local.js +44 -44
  39. package/dist/commands/stats/data/local.js.map +1 -1
  40. package/dist/commands/stats/data/source.d.ts +3 -9
  41. package/dist/commands/stats/data/source.d.ts.map +1 -1
  42. package/dist/commands/stats/data/source.js +3 -35
  43. package/dist/commands/stats/data/source.js.map +1 -1
  44. package/dist/commands/stats/data/types.d.ts +1 -12
  45. package/dist/commands/stats/data/types.d.ts.map +1 -1
  46. package/dist/commands/stats/data/types.js +0 -16
  47. package/dist/commands/stats/data/types.js.map +1 -1
  48. package/dist/commands/stats/shared.d.ts.map +1 -1
  49. package/dist/commands/stats/shared.js +1 -5
  50. package/dist/commands/stats/shared.js.map +1 -1
  51. package/dist/commands/status.d.ts.map +1 -1
  52. package/dist/commands/status.js +53 -92
  53. package/dist/commands/status.js.map +1 -1
  54. package/dist/commands/sync.d.ts +5 -5
  55. package/dist/commands/sync.d.ts.map +1 -1
  56. package/dist/commands/sync.js +31 -39
  57. package/dist/commands/sync.js.map +1 -1
  58. package/dist/commands/telemetry.d.ts.map +1 -1
  59. package/dist/commands/telemetry.js +0 -1
  60. package/dist/commands/telemetry.js.map +1 -1
  61. package/dist/constants/llm-providers.d.ts +5 -0
  62. package/dist/constants/llm-providers.d.ts.map +1 -0
  63. package/dist/constants/llm-providers.js +56 -0
  64. package/dist/constants/llm-providers.js.map +1 -0
  65. package/dist/db/client.d.ts +17 -0
  66. package/dist/db/client.d.ts.map +1 -0
  67. package/dist/db/client.js +53 -0
  68. package/dist/db/client.js.map +1 -0
  69. package/dist/db/migrate.d.ts +9 -0
  70. package/dist/db/migrate.d.ts.map +1 -0
  71. package/dist/db/migrate.js +31 -0
  72. package/dist/db/migrate.js.map +1 -0
  73. package/dist/db/read.d.ts +42 -0
  74. package/dist/db/read.d.ts.map +1 -0
  75. package/dist/db/read.js +194 -0
  76. package/dist/db/read.js.map +1 -0
  77. package/dist/db/schema.d.ts +3 -0
  78. package/dist/db/schema.d.ts.map +1 -0
  79. package/dist/db/schema.js +129 -0
  80. package/dist/db/schema.js.map +1 -0
  81. package/dist/db/write.d.ts +24 -0
  82. package/dist/db/write.d.ts.map +1 -0
  83. package/dist/db/write.js +287 -0
  84. package/dist/db/write.js.map +1 -0
  85. package/dist/firebase/client.d.ts +5 -0
  86. package/dist/firebase/client.d.ts.map +1 -1
  87. package/dist/firebase/client.js +23 -0
  88. package/dist/firebase/client.js.map +1 -1
  89. package/dist/index.js +12 -12
  90. package/dist/index.js.map +1 -1
  91. package/dist/providers/context.d.ts +3 -0
  92. package/dist/providers/context.d.ts.map +1 -0
  93. package/dist/providers/context.js +13 -0
  94. package/dist/providers/context.js.map +1 -0
  95. package/dist/providers/copilot.d.ts +18 -0
  96. package/dist/providers/copilot.d.ts.map +1 -0
  97. package/dist/providers/copilot.js +289 -0
  98. package/dist/providers/copilot.js.map +1 -0
  99. package/dist/providers/cursor.d.ts.map +1 -1
  100. package/dist/providers/cursor.js +8 -3
  101. package/dist/providers/cursor.js.map +1 -1
  102. package/dist/providers/registry.d.ts.map +1 -1
  103. package/dist/providers/registry.js +3 -0
  104. package/dist/providers/registry.js.map +1 -1
  105. package/dist/types.d.ts +38 -47
  106. package/dist/types.d.ts.map +1 -1
  107. package/dist/utils/browser.d.ts +6 -0
  108. package/dist/utils/browser.d.ts.map +1 -0
  109. package/dist/utils/browser.js +23 -0
  110. package/dist/utils/browser.js.map +1 -0
  111. package/dist/utils/config.d.ts +9 -21
  112. package/dist/utils/config.d.ts.map +1 -1
  113. package/dist/utils/config.js +23 -50
  114. package/dist/utils/config.js.map +1 -1
  115. package/dist/utils/telemetry.js +2 -7
  116. package/dist/utils/telemetry.js.map +1 -1
  117. package/dist/utils/tips.js +1 -1
  118. package/dist/utils/tips.js.map +1 -1
  119. package/package.json +19 -5
  120. package/server-dist/dist/index.d.ts +12 -0
  121. package/server-dist/dist/index.d.ts.map +1 -0
  122. package/server-dist/dist/index.js +92 -0
  123. package/server-dist/dist/index.js.map +1 -0
  124. package/server-dist/dist/llm/analysis.d.ts +80 -0
  125. package/server-dist/dist/llm/analysis.d.ts.map +1 -0
  126. package/server-dist/dist/llm/analysis.js +509 -0
  127. package/server-dist/dist/llm/analysis.js.map +1 -0
  128. package/server-dist/dist/llm/client.d.ts +27 -0
  129. package/server-dist/dist/llm/client.d.ts.map +1 -0
  130. package/server-dist/dist/llm/client.js +71 -0
  131. package/server-dist/dist/llm/client.js.map +1 -0
  132. package/server-dist/dist/llm/index.d.ts +7 -0
  133. package/server-dist/dist/llm/index.d.ts.map +1 -0
  134. package/server-dist/dist/llm/index.js +5 -0
  135. package/server-dist/dist/llm/index.js.map +1 -0
  136. package/server-dist/dist/llm/prompts.d.ts +73 -0
  137. package/server-dist/dist/llm/prompts.d.ts.map +1 -0
  138. package/server-dist/dist/llm/prompts.js +242 -0
  139. package/server-dist/dist/llm/prompts.js.map +1 -0
  140. package/server-dist/dist/llm/providers/anthropic.d.ts +3 -0
  141. package/server-dist/dist/llm/providers/anthropic.d.ts.map +1 -0
  142. package/server-dist/dist/llm/providers/anthropic.js +45 -0
  143. package/server-dist/dist/llm/providers/anthropic.js.map +1 -0
  144. package/server-dist/dist/llm/providers/gemini.d.ts +3 -0
  145. package/server-dist/dist/llm/providers/gemini.d.ts.map +1 -0
  146. package/server-dist/dist/llm/providers/gemini.js +51 -0
  147. package/server-dist/dist/llm/providers/gemini.js.map +1 -0
  148. package/server-dist/dist/llm/providers/ollama.d.ts +12 -0
  149. package/server-dist/dist/llm/providers/ollama.d.ts.map +1 -0
  150. package/server-dist/dist/llm/providers/ollama.js +61 -0
  151. package/server-dist/dist/llm/providers/ollama.js.map +1 -0
  152. package/server-dist/dist/llm/providers/openai.d.ts +3 -0
  153. package/server-dist/dist/llm/providers/openai.d.ts.map +1 -0
  154. package/server-dist/dist/llm/providers/openai.js +39 -0
  155. package/server-dist/dist/llm/providers/openai.js.map +1 -0
  156. package/server-dist/dist/llm/types.d.ts +22 -0
  157. package/server-dist/dist/llm/types.d.ts.map +1 -0
  158. package/server-dist/dist/llm/types.js +5 -0
  159. package/server-dist/dist/llm/types.js.map +1 -0
  160. package/server-dist/dist/routes/analysis.d.ts +4 -0
  161. package/server-dist/dist/routes/analysis.d.ts.map +1 -0
  162. package/server-dist/dist/routes/analysis.js +103 -0
  163. package/server-dist/dist/routes/analysis.js.map +1 -0
  164. package/server-dist/dist/routes/analytics.d.ts +4 -0
  165. package/server-dist/dist/routes/analytics.d.ts.map +1 -0
  166. package/server-dist/dist/routes/analytics.js +47 -0
  167. package/server-dist/dist/routes/analytics.js.map +1 -0
  168. package/server-dist/dist/routes/config.d.ts +4 -0
  169. package/server-dist/dist/routes/config.d.ts.map +1 -0
  170. package/server-dist/dist/routes/config.js +108 -0
  171. package/server-dist/dist/routes/config.js.map +1 -0
  172. package/server-dist/dist/routes/export.d.ts +4 -0
  173. package/server-dist/dist/routes/export.d.ts.map +1 -0
  174. package/server-dist/dist/routes/export.js +52 -0
  175. package/server-dist/dist/routes/export.js.map +1 -0
  176. package/server-dist/dist/routes/insights.d.ts +4 -0
  177. package/server-dist/dist/routes/insights.d.ts.map +1 -0
  178. package/server-dist/dist/routes/insights.js +80 -0
  179. package/server-dist/dist/routes/insights.js.map +1 -0
  180. package/server-dist/dist/routes/messages.d.ts +4 -0
  181. package/server-dist/dist/routes/messages.d.ts.map +1 -0
  182. package/server-dist/dist/routes/messages.js +19 -0
  183. package/server-dist/dist/routes/messages.js.map +1 -0
  184. package/server-dist/dist/routes/projects.d.ts +4 -0
  185. package/server-dist/dist/routes/projects.d.ts.map +1 -0
  186. package/server-dist/dist/routes/projects.js +32 -0
  187. package/server-dist/dist/routes/projects.js.map +1 -0
  188. package/server-dist/dist/routes/sessions.d.ts +4 -0
  189. package/server-dist/dist/routes/sessions.d.ts.map +1 -0
  190. package/server-dist/dist/routes/sessions.js +65 -0
  191. package/server-dist/dist/routes/sessions.js.map +1 -0
  192. package/server-dist/dist/utils.d.ts +6 -0
  193. package/server-dist/dist/utils.d.ts.map +1 -0
  194. package/server-dist/dist/utils.js +9 -0
  195. package/server-dist/dist/utils.js.map +1 -0
  196. package/server-dist/index.d.ts +12 -0
  197. package/server-dist/index.d.ts.map +1 -0
  198. package/server-dist/index.js +92 -0
  199. package/server-dist/index.js.map +1 -0
  200. package/server-dist/llm/analysis.d.ts +80 -0
  201. package/server-dist/llm/analysis.d.ts.map +1 -0
  202. package/server-dist/llm/analysis.js +509 -0
  203. package/server-dist/llm/analysis.js.map +1 -0
  204. package/server-dist/llm/client.d.ts +27 -0
  205. package/server-dist/llm/client.d.ts.map +1 -0
  206. package/server-dist/llm/client.js +71 -0
  207. package/server-dist/llm/client.js.map +1 -0
  208. package/server-dist/llm/index.d.ts +7 -0
  209. package/server-dist/llm/index.d.ts.map +1 -0
  210. package/server-dist/llm/index.js +5 -0
  211. package/server-dist/llm/index.js.map +1 -0
  212. package/server-dist/llm/prompts.d.ts +73 -0
  213. package/server-dist/llm/prompts.d.ts.map +1 -0
  214. package/server-dist/llm/prompts.js +242 -0
  215. package/server-dist/llm/prompts.js.map +1 -0
  216. package/server-dist/llm/providers/anthropic.d.ts +3 -0
  217. package/server-dist/llm/providers/anthropic.d.ts.map +1 -0
  218. package/server-dist/llm/providers/anthropic.js +45 -0
  219. package/server-dist/llm/providers/anthropic.js.map +1 -0
  220. package/server-dist/llm/providers/gemini.d.ts +3 -0
  221. package/server-dist/llm/providers/gemini.d.ts.map +1 -0
  222. package/server-dist/llm/providers/gemini.js +51 -0
  223. package/server-dist/llm/providers/gemini.js.map +1 -0
  224. package/server-dist/llm/providers/ollama.d.ts +12 -0
  225. package/server-dist/llm/providers/ollama.d.ts.map +1 -0
  226. package/server-dist/llm/providers/ollama.js +61 -0
  227. package/server-dist/llm/providers/ollama.js.map +1 -0
  228. package/server-dist/llm/providers/openai.d.ts +3 -0
  229. package/server-dist/llm/providers/openai.d.ts.map +1 -0
  230. package/server-dist/llm/providers/openai.js +39 -0
  231. package/server-dist/llm/providers/openai.js.map +1 -0
  232. package/server-dist/llm/types.d.ts +22 -0
  233. package/server-dist/llm/types.d.ts.map +1 -0
  234. package/server-dist/llm/types.js +5 -0
  235. package/server-dist/llm/types.js.map +1 -0
  236. package/server-dist/routes/analysis.d.ts +4 -0
  237. package/server-dist/routes/analysis.d.ts.map +1 -0
  238. package/server-dist/routes/analysis.js +103 -0
  239. package/server-dist/routes/analysis.js.map +1 -0
  240. package/server-dist/routes/analytics.d.ts +4 -0
  241. package/server-dist/routes/analytics.d.ts.map +1 -0
  242. package/server-dist/routes/analytics.js +47 -0
  243. package/server-dist/routes/analytics.js.map +1 -0
  244. package/server-dist/routes/config.d.ts +4 -0
  245. package/server-dist/routes/config.d.ts.map +1 -0
  246. package/server-dist/routes/config.js +108 -0
  247. package/server-dist/routes/config.js.map +1 -0
  248. package/server-dist/routes/export.d.ts +4 -0
  249. package/server-dist/routes/export.d.ts.map +1 -0
  250. package/server-dist/routes/export.js +52 -0
  251. package/server-dist/routes/export.js.map +1 -0
  252. package/server-dist/routes/insights.d.ts +4 -0
  253. package/server-dist/routes/insights.d.ts.map +1 -0
  254. package/server-dist/routes/insights.js +80 -0
  255. package/server-dist/routes/insights.js.map +1 -0
  256. package/server-dist/routes/messages.d.ts +4 -0
  257. package/server-dist/routes/messages.d.ts.map +1 -0
  258. package/server-dist/routes/messages.js +19 -0
  259. package/server-dist/routes/messages.js.map +1 -0
  260. package/server-dist/routes/projects.d.ts +4 -0
  261. package/server-dist/routes/projects.d.ts.map +1 -0
  262. package/server-dist/routes/projects.js +32 -0
  263. package/server-dist/routes/projects.js.map +1 -0
  264. package/server-dist/routes/sessions.d.ts +4 -0
  265. package/server-dist/routes/sessions.d.ts.map +1 -0
  266. package/server-dist/routes/sessions.js +65 -0
  267. package/server-dist/routes/sessions.js.map +1 -0
  268. package/server-dist/utils.d.ts +6 -0
  269. package/server-dist/utils.d.ts.map +1 -0
  270. package/server-dist/utils.js +9 -0
  271. package/server-dist/utils.js.map +1 -0
@@ -0,0 +1,509 @@
1
+ // Core analysis engine — server-side.
2
+ // Ported from web repo (src/lib/llm/analysis.ts) with SQLite persistence replacing Firestore.
3
+ // Key differences from web repo:
4
+ // - Uses SQLiteMessageRow instead of web Message type
5
+ // - Writes insights directly to SQLite via getDb() (not Firestore)
6
+ // - Abort handling uses error.name === 'AbortError' (not DOMException)
7
+ // - Uses session's existing project_id from SQLite (not re-derived hash)
8
+ import { randomUUID } from 'crypto';
9
+ import { getDb } from '@code-insights/cli/db/client';
10
+ import { createLLMClient, isLLMConfigured } from './client.js';
11
+ import { SESSION_ANALYSIS_SYSTEM_PROMPT, generateSessionAnalysisPrompt, formatMessagesForAnalysis, parseAnalysisResponse, PROMPT_QUALITY_SYSTEM_PROMPT, generatePromptQualityPrompt, parsePromptQualityResponse, } from './prompts.js';
12
+ // Maximum tokens to send to LLM (leaving room for response)
13
+ const MAX_INPUT_TOKENS = 80000;
14
+ const ANALYSIS_VERSION = '2.0.0';
15
+ /**
16
+ * Analyze a session and generate insights, saving them to SQLite.
17
+ */
18
+ export async function analyzeSession(session, messages, options) {
19
+ if (!isLLMConfigured()) {
20
+ return {
21
+ success: false,
22
+ insights: [],
23
+ error: 'LLM not configured. Run `code-insights config llm` to configure a provider.',
24
+ };
25
+ }
26
+ if (messages.length === 0) {
27
+ return {
28
+ success: false,
29
+ insights: [],
30
+ error: 'No messages found for this session.',
31
+ };
32
+ }
33
+ try {
34
+ const client = createLLMClient();
35
+ const formattedMessages = formatMessagesForAnalysis(messages);
36
+ const estimatedTokens = client.estimateTokens(formattedMessages);
37
+ let analysisResponse;
38
+ let totalInputTokens = 0;
39
+ let totalOutputTokens = 0;
40
+ if (estimatedTokens > MAX_INPUT_TOKENS) {
41
+ // Chunk the messages and analyze separately
42
+ const chunks = chunkMessages(messages, client.estimateTokens.bind(client));
43
+ const chunkResponses = [];
44
+ const totalChunks = chunks.length;
45
+ for (let i = 0; i < chunks.length; i++) {
46
+ const chunk = chunks[i];
47
+ options?.onProgress?.({ phase: 'analyzing', currentChunk: i + 1, totalChunks });
48
+ const chunkFormatted = formatMessagesForAnalysis(chunk);
49
+ const prompt = generateSessionAnalysisPrompt(session.project_name, session.summary, chunkFormatted);
50
+ const response = await client.chat([
51
+ { role: 'system', content: SESSION_ANALYSIS_SYSTEM_PROMPT },
52
+ { role: 'user', content: prompt },
53
+ ], { signal: options?.signal });
54
+ if (response.usage) {
55
+ totalInputTokens += response.usage.inputTokens;
56
+ totalOutputTokens += response.usage.outputTokens;
57
+ }
58
+ const parsed = parseAnalysisResponse(response.content);
59
+ if (parsed)
60
+ chunkResponses.push(parsed);
61
+ }
62
+ analysisResponse = mergeAnalysisResponses(chunkResponses);
63
+ }
64
+ else {
65
+ options?.onProgress?.({ phase: 'analyzing', currentChunk: 1, totalChunks: 1 });
66
+ const prompt = generateSessionAnalysisPrompt(session.project_name, session.summary, formattedMessages);
67
+ const response = await client.chat([
68
+ { role: 'system', content: SESSION_ANALYSIS_SYSTEM_PROMPT },
69
+ { role: 'user', content: prompt },
70
+ ], { signal: options?.signal });
71
+ if (response.usage) {
72
+ totalInputTokens = response.usage.inputTokens;
73
+ totalOutputTokens = response.usage.outputTokens;
74
+ }
75
+ const parsed = parseAnalysisResponse(response.content);
76
+ if (!parsed) {
77
+ return {
78
+ success: false,
79
+ insights: [],
80
+ error: 'Failed to parse LLM response. Please try again.',
81
+ };
82
+ }
83
+ analysisResponse = parsed;
84
+ }
85
+ options?.onProgress?.({ phase: 'saving' });
86
+ const insights = convertToInsightRows(analysisResponse, session);
87
+ // Save new insights first, then delete old non-prompt-quality insights
88
+ // (safe order: if save fails, old data is preserved)
89
+ saveInsightsToDb(insights);
90
+ deleteSessionInsights(session.id, {
91
+ excludeTypes: ['prompt_quality'],
92
+ excludeIds: insights.map(i => i.id),
93
+ });
94
+ return {
95
+ success: true,
96
+ insights,
97
+ usage: { inputTokens: totalInputTokens, outputTokens: totalOutputTokens },
98
+ };
99
+ }
100
+ catch (error) {
101
+ if (error instanceof Error && error.name === 'AbortError') {
102
+ return { success: false, insights: [], error: 'Analysis cancelled' };
103
+ }
104
+ return {
105
+ success: false,
106
+ insights: [],
107
+ error: error instanceof Error ? error.message : 'Analysis failed',
108
+ };
109
+ }
110
+ }
111
+ /**
112
+ * Analyze prompt quality for a session.
113
+ */
114
+ export async function analyzePromptQuality(session, messages, options) {
115
+ if (!isLLMConfigured()) {
116
+ return {
117
+ success: false,
118
+ insights: [],
119
+ error: 'LLM not configured. Run `code-insights config llm` to configure a provider.',
120
+ };
121
+ }
122
+ if (messages.length === 0) {
123
+ return {
124
+ success: false,
125
+ insights: [],
126
+ error: 'No messages found for this session.',
127
+ };
128
+ }
129
+ const userMessages = messages.filter(m => m.type === 'user');
130
+ if (userMessages.length < 2) {
131
+ return {
132
+ success: false,
133
+ insights: [],
134
+ error: 'Not enough user messages to analyze prompt quality (need at least 2).',
135
+ };
136
+ }
137
+ try {
138
+ const client = createLLMClient();
139
+ const formattedMessages = formatMessagesForAnalysis(messages);
140
+ let analysisInput = formattedMessages;
141
+ const estimatedTokens = client.estimateTokens(formattedMessages);
142
+ if (estimatedTokens > MAX_INPUT_TOKENS) {
143
+ const targetLength = Math.floor((MAX_INPUT_TOKENS / estimatedTokens) * formattedMessages.length * 0.8);
144
+ analysisInput = formattedMessages.slice(0, targetLength) + '\n\n[... conversation truncated for analysis ...]';
145
+ }
146
+ const prompt = generatePromptQualityPrompt(session.project_name, analysisInput, messages.length);
147
+ options?.onProgress?.({ phase: 'analyzing' });
148
+ const response = await client.chat([
149
+ { role: 'system', content: PROMPT_QUALITY_SYSTEM_PROMPT },
150
+ { role: 'user', content: prompt },
151
+ ], { signal: options?.signal });
152
+ const parsed = parsePromptQualityResponse(response.content);
153
+ if (!parsed) {
154
+ return {
155
+ success: false,
156
+ insights: [],
157
+ error: 'Failed to parse prompt quality analysis. Please try again.',
158
+ };
159
+ }
160
+ options?.onProgress?.({ phase: 'saving' });
161
+ const insight = convertPromptQualityToInsightRow(parsed, session);
162
+ // Save new insight, then delete old prompt_quality insights
163
+ saveInsightsToDb([insight]);
164
+ deleteSessionInsights(session.id, {
165
+ includeOnlyTypes: ['prompt_quality'],
166
+ excludeIds: [insight.id],
167
+ });
168
+ return {
169
+ success: true,
170
+ insights: [insight],
171
+ usage: response.usage ? {
172
+ inputTokens: response.usage.inputTokens,
173
+ outputTokens: response.usage.outputTokens,
174
+ } : undefined,
175
+ };
176
+ }
177
+ catch (error) {
178
+ if (error instanceof Error && error.name === 'AbortError') {
179
+ return { success: false, insights: [], error: 'Analysis cancelled' };
180
+ }
181
+ return {
182
+ success: false,
183
+ insights: [],
184
+ error: error instanceof Error ? error.message : 'Prompt quality analysis failed',
185
+ };
186
+ }
187
+ }
188
+ /**
189
+ * Find recurring patterns across multiple insights and write bidirectional links to SQLite.
190
+ */
191
+ export async function findRecurringInsights(insights) {
192
+ if (!isLLMConfigured()) {
193
+ return { success: false, groups: [], updatedCount: 0, error: 'LLM not configured.' };
194
+ }
195
+ const candidates = insights
196
+ .filter(i => i.type !== 'summary' && i.type !== 'prompt_quality')
197
+ .slice(0, 200);
198
+ if (candidates.length < 2) {
199
+ return {
200
+ success: false,
201
+ groups: [],
202
+ updatedCount: 0,
203
+ error: 'Need at least 2 non-summary insights to find patterns.',
204
+ };
205
+ }
206
+ try {
207
+ const client = createLLMClient();
208
+ const insightData = candidates.map(i => ({
209
+ id: i.id,
210
+ type: i.type === 'technique' ? 'learning' : i.type,
211
+ title: i.title,
212
+ summary: i.summary.slice(0, 150),
213
+ projectName: i.project_name,
214
+ sessionId: i.session_id,
215
+ }));
216
+ const prompt = `Analyze these insights from coding sessions and find groups of semantically similar or duplicate insights — ones that express the same learning or decision even if worded differently.
217
+
218
+ RULES:
219
+ - Only group insights that are genuinely about the same concept/topic
220
+ - Insights in a group should be from DIFFERENT sessions (same sessionId = not recurring)
221
+ - A group must have at least 2 insights
222
+ - An insight can only belong to one group
223
+ - Provide a brief "theme" describing what the group shares
224
+ - If no recurring patterns exist, return an empty groups array
225
+
226
+ INSIGHTS:
227
+ ${JSON.stringify(insightData, null, 2)}
228
+
229
+ Respond with valid JSON only:
230
+ {
231
+ "groups": [
232
+ {
233
+ "insightIds": ["insight_abc", "insight_def"],
234
+ "theme": "Brief description of the shared concept"
235
+ }
236
+ ]
237
+ }`;
238
+ const response = await client.chat([
239
+ {
240
+ role: 'system',
241
+ content: 'You are an expert at identifying recurring patterns and themes across software development insights. You find semantically similar insights even when they are worded differently. Respond with valid JSON only.',
242
+ },
243
+ { role: 'user', content: prompt },
244
+ ]);
245
+ const jsonMatch = response.content.match(/\{[\s\S]*\}/);
246
+ if (!jsonMatch) {
247
+ return { success: false, groups: [], updatedCount: 0, error: 'Failed to parse recurring insights response.' };
248
+ }
249
+ const parsed = JSON.parse(jsonMatch[0]);
250
+ const groups = parsed.groups || [];
251
+ const validIds = new Set(candidates.map(i => i.id));
252
+ const validGroups = groups
253
+ .map(g => ({
254
+ ...g,
255
+ insightIds: g.insightIds.filter(id => validIds.has(id)),
256
+ }))
257
+ .filter(g => g.insightIds.length >= 2);
258
+ if (validGroups.length === 0) {
259
+ return {
260
+ success: true,
261
+ groups: [],
262
+ updatedCount: 0,
263
+ usage: response.usage
264
+ ? { inputTokens: response.usage.inputTokens, outputTokens: response.usage.outputTokens }
265
+ : undefined,
266
+ };
267
+ }
268
+ // Build bidirectional links
269
+ const linkMap = new Map();
270
+ for (const group of validGroups) {
271
+ for (const id of group.insightIds) {
272
+ const others = group.insightIds.filter(otherId => otherId !== id);
273
+ const existing = linkMap.get(id) || [];
274
+ linkMap.set(id, [...new Set([...existing, ...others])]);
275
+ }
276
+ }
277
+ // Write links to SQLite
278
+ const db = getDb();
279
+ const updateLinks = db.prepare(`UPDATE insights SET linked_insight_ids = ? WHERE id = ?`);
280
+ for (const [insightId, linkedIds] of linkMap.entries()) {
281
+ updateLinks.run(JSON.stringify(linkedIds), insightId);
282
+ }
283
+ return {
284
+ success: true,
285
+ groups: validGroups,
286
+ updatedCount: linkMap.size,
287
+ usage: response.usage
288
+ ? { inputTokens: response.usage.inputTokens, outputTokens: response.usage.outputTokens }
289
+ : undefined,
290
+ };
291
+ }
292
+ catch (error) {
293
+ return {
294
+ success: false,
295
+ groups: [],
296
+ updatedCount: 0,
297
+ error: error instanceof Error ? error.message : 'Failed to find recurring insights',
298
+ };
299
+ }
300
+ }
301
+ // --- Internal helpers ---
302
+ function chunkMessages(messages, estimateTokens) {
303
+ const chunks = [];
304
+ let currentChunk = [];
305
+ let currentTokens = 0;
306
+ const chunkLimit = MAX_INPUT_TOKENS * 0.8;
307
+ for (const message of messages) {
308
+ let toolResults = [];
309
+ try {
310
+ toolResults = message.tool_results ? JSON.parse(message.tool_results) : [];
311
+ }
312
+ catch {
313
+ toolResults = [];
314
+ }
315
+ const messageText = [
316
+ message.content,
317
+ message.thinking?.slice(0, 1000) ?? '',
318
+ ...toolResults.map(r => (r.output || '').slice(0, 200)),
319
+ ].join(' ');
320
+ const messageTokens = estimateTokens(messageText);
321
+ if (currentTokens + messageTokens > chunkLimit && currentChunk.length > 0) {
322
+ chunks.push(currentChunk);
323
+ currentChunk = [];
324
+ currentTokens = 0;
325
+ }
326
+ currentChunk.push(message);
327
+ currentTokens += messageTokens;
328
+ }
329
+ if (currentChunk.length > 0) {
330
+ chunks.push(currentChunk);
331
+ }
332
+ return chunks;
333
+ }
334
+ function mergeAnalysisResponses(responses) {
335
+ if (responses.length === 0) {
336
+ return {
337
+ summary: { title: 'Analysis failed', content: '', bullets: [] },
338
+ decisions: [],
339
+ learnings: [],
340
+ };
341
+ }
342
+ if (responses.length === 1)
343
+ return responses[0];
344
+ const merged = {
345
+ summary: responses[0].summary,
346
+ decisions: [],
347
+ learnings: [],
348
+ };
349
+ for (const response of responses) {
350
+ merged.decisions.push(...response.decisions);
351
+ merged.learnings.push(...response.learnings);
352
+ }
353
+ merged.decisions = deduplicateByTitle(merged.decisions).slice(0, 3);
354
+ merged.learnings = deduplicateByTitle(merged.learnings).slice(0, 5);
355
+ return merged;
356
+ }
357
+ function deduplicateByTitle(items) {
358
+ const seen = new Set();
359
+ return items.filter((item) => {
360
+ const normalized = item.title.toLowerCase().trim();
361
+ if (seen.has(normalized))
362
+ return false;
363
+ seen.add(normalized);
364
+ return true;
365
+ });
366
+ }
367
+ function convertToInsightRows(response, session) {
368
+ const insights = [];
369
+ const now = new Date().toISOString();
370
+ insights.push({
371
+ id: randomUUID(),
372
+ session_id: session.id,
373
+ project_id: session.project_id,
374
+ project_name: session.project_name,
375
+ type: 'summary',
376
+ title: response.summary.title,
377
+ content: response.summary.content,
378
+ summary: response.summary.content,
379
+ bullets: JSON.stringify(response.summary.bullets),
380
+ confidence: 0.9,
381
+ source: 'llm',
382
+ metadata: null,
383
+ timestamp: session.ended_at,
384
+ created_at: now,
385
+ scope: 'session',
386
+ analysis_version: ANALYSIS_VERSION,
387
+ });
388
+ for (const decision of response.decisions) {
389
+ const confidence = decision.confidence ?? 85;
390
+ if (confidence < 70)
391
+ continue;
392
+ insights.push({
393
+ id: randomUUID(),
394
+ session_id: session.id,
395
+ project_id: session.project_id,
396
+ project_name: session.project_name,
397
+ type: 'decision',
398
+ title: decision.title,
399
+ content: decision.content,
400
+ summary: decision.content.slice(0, 200),
401
+ bullets: JSON.stringify(decision.alternatives || []),
402
+ confidence: confidence / 100,
403
+ source: 'llm',
404
+ metadata: JSON.stringify({
405
+ reasoning: decision.reasoning,
406
+ alternatives: decision.alternatives,
407
+ evidence: decision.evidence,
408
+ }),
409
+ timestamp: session.ended_at,
410
+ created_at: now,
411
+ scope: 'session',
412
+ analysis_version: ANALYSIS_VERSION,
413
+ });
414
+ }
415
+ for (const learning of response.learnings) {
416
+ const confidence = learning.confidence ?? 80;
417
+ if (confidence < 70)
418
+ continue;
419
+ insights.push({
420
+ id: randomUUID(),
421
+ session_id: session.id,
422
+ project_id: session.project_id,
423
+ project_name: session.project_name,
424
+ type: 'learning',
425
+ title: learning.title,
426
+ content: learning.content,
427
+ summary: learning.content.slice(0, 200),
428
+ bullets: JSON.stringify([]),
429
+ confidence: confidence / 100,
430
+ source: 'llm',
431
+ metadata: JSON.stringify({
432
+ context: learning.context,
433
+ evidence: learning.evidence,
434
+ }),
435
+ timestamp: session.ended_at,
436
+ created_at: now,
437
+ scope: 'session',
438
+ analysis_version: ANALYSIS_VERSION,
439
+ });
440
+ }
441
+ return insights;
442
+ }
443
+ function convertPromptQualityToInsightRow(response, session) {
444
+ const now = new Date().toISOString();
445
+ return {
446
+ id: randomUUID(),
447
+ session_id: session.id,
448
+ project_id: session.project_id,
449
+ project_name: session.project_name,
450
+ type: 'prompt_quality',
451
+ title: `Prompt Efficiency: ${response.efficiencyScore}/100`,
452
+ content: response.overallAssessment,
453
+ summary: response.overallAssessment,
454
+ bullets: JSON.stringify(response.tips),
455
+ confidence: 0.85,
456
+ source: 'llm',
457
+ metadata: JSON.stringify({
458
+ efficiencyScore: response.efficiencyScore,
459
+ wastedTurns: response.wastedTurns,
460
+ antiPatterns: response.antiPatterns,
461
+ potentialMessageReduction: response.potentialMessageReduction,
462
+ }),
463
+ timestamp: session.ended_at,
464
+ created_at: now,
465
+ scope: 'session',
466
+ analysis_version: ANALYSIS_VERSION,
467
+ };
468
+ }
469
+ /**
470
+ * Write insight rows to SQLite using prepared statements.
471
+ */
472
+ function saveInsightsToDb(insights) {
473
+ const db = getDb();
474
+ const insert = db.prepare(`
475
+ INSERT OR REPLACE INTO insights (
476
+ id, session_id, project_id, project_name, type, title, content,
477
+ summary, bullets, confidence, source, metadata, timestamp,
478
+ created_at, scope, analysis_version
479
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
480
+ `);
481
+ const insertMany = db.transaction((rows) => {
482
+ for (const row of rows) {
483
+ insert.run(row.id, row.session_id, row.project_id, row.project_name, row.type, row.title, row.content, row.summary, row.bullets, row.confidence, row.source, row.metadata, row.timestamp, row.created_at, row.scope, row.analysis_version);
484
+ }
485
+ });
486
+ insertMany(insights);
487
+ }
488
+ /**
489
+ * Delete insights for a session, with optional type and ID exclusions.
490
+ */
491
+ function deleteSessionInsights(sessionId, opts) {
492
+ const db = getDb();
493
+ const conditions = ['session_id = ?'];
494
+ const params = [sessionId];
495
+ if (opts.excludeTypes && opts.excludeTypes.length > 0) {
496
+ conditions.push(`type NOT IN (${opts.excludeTypes.map(() => '?').join(', ')})`);
497
+ params.push(...opts.excludeTypes);
498
+ }
499
+ if (opts.includeOnlyTypes && opts.includeOnlyTypes.length > 0) {
500
+ conditions.push(`type IN (${opts.includeOnlyTypes.map(() => '?').join(', ')})`);
501
+ params.push(...opts.includeOnlyTypes);
502
+ }
503
+ if (opts.excludeIds && opts.excludeIds.length > 0) {
504
+ conditions.push(`id NOT IN (${opts.excludeIds.map(() => '?').join(', ')})`);
505
+ params.push(...opts.excludeIds);
506
+ }
507
+ db.prepare(`DELETE FROM insights WHERE ${conditions.join(' AND ')}`).run(...params);
508
+ }
509
+ //# sourceMappingURL=analysis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analysis.js","sourceRoot":"","sources":["../../src/llm/analysis.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { LLMClient } from './types.js';
2
+ import type { LLMProviderConfig } from './types.js';
3
+ /**
4
+ * Load LLM config from the CLI config file.
5
+ */
6
+ export declare function loadLLMConfig(): LLMProviderConfig | null;
7
+ /**
8
+ * Check if LLM is configured.
9
+ */
10
+ export declare function isLLMConfigured(): boolean;
11
+ /**
12
+ * Create an LLM client from the current config.
13
+ * Throws if LLM is not configured.
14
+ */
15
+ export declare function createLLMClient(): LLMClient;
16
+ /**
17
+ * Create an LLM client from a specific config object (used for testing).
18
+ */
19
+ export declare function createClientFromConfig(config: LLMProviderConfig): LLMClient;
20
+ /**
21
+ * Test LLM connectivity with the given config.
22
+ */
23
+ export declare function testLLMConfig(config: LLMProviderConfig): Promise<{
24
+ success: boolean;
25
+ error?: string;
26
+ }>;
27
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/llm/client.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAMpD;;GAEG;AACH,wBAAgB,aAAa,IAAI,iBAAiB,GAAG,IAAI,CAGxD;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAKzC;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,SAAS,CAM3C;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,iBAAiB,GAAG,SAAS,CAa3E;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAW5G"}
@@ -0,0 +1,71 @@
1
+ // LLM client factory — server-side.
2
+ // Config is loaded from ~/.code-insights/config.json via the CLI config system.
3
+ // No localStorage or browser APIs used here.
4
+ import { loadConfig } from '@code-insights/cli/utils/config';
5
+ import { createOpenAIClient } from './providers/openai.js';
6
+ import { createAnthropicClient } from './providers/anthropic.js';
7
+ import { createGeminiClient } from './providers/gemini.js';
8
+ import { createOllamaClient } from './providers/ollama.js';
9
+ /**
10
+ * Load LLM config from the CLI config file.
11
+ */
12
+ export function loadLLMConfig() {
13
+ const config = loadConfig();
14
+ return config?.dashboard?.llm ?? null;
15
+ }
16
+ /**
17
+ * Check if LLM is configured.
18
+ */
19
+ export function isLLMConfigured() {
20
+ const llm = loadLLMConfig();
21
+ if (!llm)
22
+ return false;
23
+ if (llm.provider === 'ollama')
24
+ return !!llm.model;
25
+ return !!llm.apiKey && !!llm.model;
26
+ }
27
+ /**
28
+ * Create an LLM client from the current config.
29
+ * Throws if LLM is not configured.
30
+ */
31
+ export function createLLMClient() {
32
+ const config = loadLLMConfig();
33
+ if (!config) {
34
+ throw new Error('LLM not configured. Run `code-insights config llm` to configure a provider.');
35
+ }
36
+ return createClientFromConfig(config);
37
+ }
38
+ /**
39
+ * Create an LLM client from a specific config object (used for testing).
40
+ */
41
+ export function createClientFromConfig(config) {
42
+ switch (config.provider) {
43
+ case 'openai':
44
+ return createOpenAIClient(config.apiKey ?? '', config.model);
45
+ case 'anthropic':
46
+ return createAnthropicClient(config.apiKey ?? '', config.model);
47
+ case 'gemini':
48
+ return createGeminiClient(config.apiKey ?? '', config.model);
49
+ case 'ollama':
50
+ return createOllamaClient(config.model, config.baseUrl);
51
+ default:
52
+ throw new Error(`Unknown LLM provider: ${config.provider}`);
53
+ }
54
+ }
55
+ /**
56
+ * Test LLM connectivity with the given config.
57
+ */
58
+ export async function testLLMConfig(config) {
59
+ try {
60
+ const client = createClientFromConfig(config);
61
+ await client.chat([{ role: 'user', content: 'Say "ok" and nothing else.' }]);
62
+ return { success: true };
63
+ }
64
+ catch (error) {
65
+ return {
66
+ success: false,
67
+ error: error instanceof Error ? error.message : 'Unknown error',
68
+ };
69
+ }
70
+ }
71
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/llm/client.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,gFAAgF;AAChF,6CAA6C;AAE7C,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAG7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D;;GAEG;AACH,MAAM,UAAU,aAAa;IAC3B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,OAAO,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,IAAI,CAAC;AACxC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;IAC5B,IAAI,CAAC,GAAG;QAAE,OAAO,KAAK,CAAC;IACvB,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC;IAClD,OAAO,CAAC,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC;AACrC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAC/B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC;IACjG,CAAC;IACD,OAAO,sBAAsB,CAAC,MAAM,CAAC,CAAC;AACxC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAyB;IAC9D,QAAQ,MAAM,CAAC,QAAQ,EAAE,CAAC;QACxB,KAAK,QAAQ;YACX,OAAO,kBAAkB,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAC/D,KAAK,WAAW;YACd,OAAO,qBAAqB,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAClE,KAAK,QAAQ;YACX,OAAO,kBAAkB,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAC/D,KAAK,QAAQ;YACX,OAAO,kBAAkB,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QAC1D;YACE,MAAM,IAAI,KAAK,CAAC,yBAAyB,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;IAChE,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAyB;IAC3D,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,sBAAsB,CAAC,MAAM,CAAC,CAAC;QAC9C,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,4BAA4B,EAAE,CAAC,CAAC,CAAC;QAC7E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe;SAChE,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ export type { LLMClient, LLMMessage, LLMResponse, ChatOptions } from './types.js';
2
+ export type { LLMProvider, LLMProviderConfig } from './types.js';
3
+ export { createLLMClient, createClientFromConfig, loadLLMConfig, isLLMConfigured, testLLMConfig } from './client.js';
4
+ export { analyzeSession, analyzePromptQuality, findRecurringInsights } from './analysis.js';
5
+ export type { AnalysisResult, InsightRow, SessionData, RecurringInsightResult } from './analysis.js';
6
+ export { discoverOllamaModels } from './providers/ollama.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/llm/index.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAClF,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,aAAa,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACrH,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAC5F,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACrG,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,5 @@
1
+ // Public API for the server-side LLM engine.
2
+ export { createLLMClient, createClientFromConfig, loadLLMConfig, isLLMConfigured, testLLMConfig } from './client.js';
3
+ export { analyzeSession, analyzePromptQuality, findRecurringInsights } from './analysis.js';
4
+ export { discoverOllamaModels } from './providers/ollama.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/llm/index.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAI7C,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,aAAa,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACrH,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAE5F,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC"}