@tekdi/coding-analytics 1.0.2 → 1.0.3

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 (58) hide show
  1. package/dist/analysis/analysis-prompt.d.ts +97 -0
  2. package/dist/analysis/analysis-prompt.d.ts.map +1 -0
  3. package/dist/analysis/analysis-prompt.js +312 -0
  4. package/dist/analysis/analysis-prompt.js.map +1 -0
  5. package/dist/analysis/feedback-aggregator.d.ts +15 -0
  6. package/dist/analysis/feedback-aggregator.d.ts.map +1 -0
  7. package/dist/analysis/feedback-aggregator.js +142 -0
  8. package/dist/analysis/feedback-aggregator.js.map +1 -0
  9. package/dist/analysis/llm-provider.d.ts +9 -0
  10. package/dist/analysis/llm-provider.d.ts.map +1 -0
  11. package/dist/analysis/llm-provider.js +23 -0
  12. package/dist/analysis/llm-provider.js.map +1 -0
  13. package/dist/analysis/providers/claude-provider.d.ts +11 -0
  14. package/dist/analysis/providers/claude-provider.d.ts.map +1 -0
  15. package/dist/analysis/providers/claude-provider.js +74 -0
  16. package/dist/analysis/providers/claude-provider.js.map +1 -0
  17. package/dist/analysis/providers/gemini-provider.d.ts +11 -0
  18. package/dist/analysis/providers/gemini-provider.d.ts.map +1 -0
  19. package/dist/analysis/providers/gemini-provider.js +58 -0
  20. package/dist/analysis/providers/gemini-provider.js.map +1 -0
  21. package/dist/analysis/providers/openai-provider.d.ts +11 -0
  22. package/dist/analysis/providers/openai-provider.d.ts.map +1 -0
  23. package/dist/analysis/providers/openai-provider.js +66 -0
  24. package/dist/analysis/providers/openai-provider.js.map +1 -0
  25. package/dist/analysis/providers/parse-helper.d.ts +7 -0
  26. package/dist/analysis/providers/parse-helper.d.ts.map +1 -0
  27. package/dist/analysis/providers/parse-helper.js +27 -0
  28. package/dist/analysis/providers/parse-helper.js.map +1 -0
  29. package/dist/analysis/session-analyzer.d.ts +8 -0
  30. package/dist/analysis/session-analyzer.d.ts.map +1 -0
  31. package/dist/analysis/session-analyzer.js +115 -0
  32. package/dist/analysis/session-analyzer.js.map +1 -0
  33. package/dist/analysis/session-builder.d.ts +19 -0
  34. package/dist/analysis/session-builder.d.ts.map +1 -0
  35. package/dist/analysis/session-builder.js +174 -0
  36. package/dist/analysis/session-builder.js.map +1 -0
  37. package/dist/analysis/types.d.ts +94 -0
  38. package/dist/analysis/types.d.ts.map +1 -0
  39. package/dist/analysis/types.js +3 -0
  40. package/dist/analysis/types.js.map +1 -0
  41. package/dist/artifact-extractor.d.ts +55 -0
  42. package/dist/artifact-extractor.d.ts.map +1 -0
  43. package/dist/artifact-extractor.js +146 -0
  44. package/dist/artifact-extractor.js.map +1 -0
  45. package/dist/claude-hooks-receiver.d.ts +9 -0
  46. package/dist/claude-hooks-receiver.d.ts.map +1 -1
  47. package/dist/claude-hooks-receiver.js +174 -2
  48. package/dist/claude-hooks-receiver.js.map +1 -1
  49. package/dist/cli.js +242 -0
  50. package/dist/cli.js.map +1 -1
  51. package/dist/config.d.ts +13 -0
  52. package/dist/config.d.ts.map +1 -1
  53. package/dist/config.js +14 -0
  54. package/dist/config.js.map +1 -1
  55. package/dist/logger.d.ts.map +1 -1
  56. package/dist/logger.js +16 -8
  57. package/dist/logger.js.map +1 -1
  58. package/package.json +9 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-provider.js","sourceRoot":"","sources":["../../analysis/llm-provider.ts"],"names":[],"mappings":";;AASA,8CAmBC;AAnBD,SAAgB,iBAAiB,CAAC,MAAc,EAAE,KAAK,GAAG,KAAK;IAC7D,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC;IAErC,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,6BAA6B,CAAC,CAAC;YAClE,OAAO,IAAI,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC3C,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,6BAA6B,CAAC,CAAC;YAClE,OAAO,IAAI,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC3C,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,6BAA6B,CAAC,CAAC;YAClE,OAAO,IAAI,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC3C,CAAC;QACD;YACE,MAAM,IAAI,KAAK,CAAC,+BAA+B,QAAQ,yCAAyC,CAAC,CAAC;IACtG,CAAC;AACH,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { LLMProvider } from '../llm-provider';
2
+ import { SessionContext, SessionFeedback } from '../types';
3
+ import { Config } from '../../config';
4
+ export declare class ClaudeProvider implements LLMProvider {
5
+ readonly name = "claude";
6
+ debug: boolean;
7
+ private config;
8
+ constructor(config: Config, debug?: boolean);
9
+ analyzeSession(session: SessionContext): Promise<SessionFeedback>;
10
+ }
11
+ //# sourceMappingURL=claude-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-provider.d.ts","sourceRoot":"","sources":["../../../analysis/providers/claude-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3D,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,qBAAa,cAAe,YAAW,WAAW;IAChD,QAAQ,CAAC,IAAI,YAAY;IACzB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,MAAM,EAAE,KAAK,UAAQ;IAKnC,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;CAmExE"}
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ClaudeProvider = void 0;
4
+ const analysis_prompt_1 = require("../analysis-prompt");
5
+ class ClaudeProvider {
6
+ constructor(config, debug = false) {
7
+ this.name = 'claude';
8
+ this.config = config;
9
+ this.debug = debug;
10
+ }
11
+ async analyzeSession(session) {
12
+ let Anthropic;
13
+ try {
14
+ Anthropic = require('@anthropic-ai/sdk');
15
+ }
16
+ catch {
17
+ throw new Error('Claude provider requires @anthropic-ai/sdk. Run: npm install @anthropic-ai/sdk');
18
+ }
19
+ const client = new Anthropic.default({ apiKey: this.config.analysis.apiKey });
20
+ const userMessage = (0, analysis_prompt_1.buildUserMessage)(session);
21
+ if (this.debug) {
22
+ console.error('\n── DEBUG: REQUEST ──────────────────────────────────────');
23
+ console.error(`Model: ${this.config.analysis.model || 'claude-sonnet-4-6'}`);
24
+ console.error(`Max tokens: ${this.config.analysis.maxOutputTokens}`);
25
+ console.error(`System prompt length: ${analysis_prompt_1.SYSTEM_PROMPT.length} chars`);
26
+ console.error(`User message length: ${userMessage.length} chars`);
27
+ console.error('\n── DEBUG: USER MESSAGE ─────────────────────────────────');
28
+ console.error(userMessage);
29
+ console.error('────────────────────────────────────────────────────────\n');
30
+ }
31
+ const response = await client.messages.create({
32
+ model: this.config.analysis.model || 'claude-sonnet-4-6',
33
+ max_tokens: this.config.analysis.maxOutputTokens,
34
+ system: analysis_prompt_1.SYSTEM_PROMPT,
35
+ messages: [{ role: 'user', content: userMessage }],
36
+ tools: [
37
+ {
38
+ name: 'session_feedback',
39
+ description: 'Return structured feedback for the session',
40
+ input_schema: analysis_prompt_1.FEEDBACK_SCHEMA,
41
+ },
42
+ ],
43
+ tool_choice: { type: 'tool', name: 'session_feedback' },
44
+ });
45
+ if (this.debug) {
46
+ console.error('\n── DEBUG: RESPONSE ─────────────────────────────────────');
47
+ console.error(`Stop reason: ${response.stop_reason}`);
48
+ console.error(`Input tokens: ${response.usage?.input_tokens}`);
49
+ console.error(`Output tokens: ${response.usage?.output_tokens}`);
50
+ console.error(`Content blocks: ${response.content.map((b) => b.type).join(', ')}`);
51
+ const toolUseBlock = response.content.find((b) => b.type === 'tool_use');
52
+ if (toolUseBlock) {
53
+ console.error('\n── DEBUG: RAW TOOL INPUT ───────────────────────────────');
54
+ console.error(JSON.stringify(toolUseBlock.input, null, 2));
55
+ }
56
+ else {
57
+ const textBlock = response.content.find((b) => b.type === 'text');
58
+ if (textBlock) {
59
+ console.error('\n── DEBUG: RAW TEXT RESPONSE (no tool_use block) ────────');
60
+ console.error(textBlock.text);
61
+ }
62
+ }
63
+ console.error('────────────────────────────────────────────────────────\n');
64
+ }
65
+ const toolUse = response.content.find((b) => b.type === 'tool_use');
66
+ if (!toolUse) {
67
+ throw new Error(`Claude did not return a tool_use block (stop_reason: ${response.stop_reason}). ` +
68
+ `Run with --debug to see the full response.`);
69
+ }
70
+ return toolUse.input;
71
+ }
72
+ }
73
+ exports.ClaudeProvider = ClaudeProvider;
74
+ //# sourceMappingURL=claude-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-provider.js","sourceRoot":"","sources":["../../../analysis/providers/claude-provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { LLMProvider } from '../llm-provider';
2
+ import { SessionContext, SessionFeedback } from '../types';
3
+ import { Config } from '../../config';
4
+ export declare class GeminiProvider implements LLMProvider {
5
+ readonly name = "gemini";
6
+ debug: boolean;
7
+ private config;
8
+ constructor(config: Config, debug?: boolean);
9
+ analyzeSession(session: SessionContext): Promise<SessionFeedback>;
10
+ }
11
+ //# sourceMappingURL=gemini-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini-provider.d.ts","sourceRoot":"","sources":["../../../analysis/providers/gemini-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3D,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAItC,qBAAa,cAAe,YAAW,WAAW;IAChD,QAAQ,CAAC,IAAI,YAAY;IACzB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,MAAM,EAAE,KAAK,UAAQ;IAKnC,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;CAoDxE"}
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GeminiProvider = void 0;
4
+ const analysis_prompt_1 = require("../analysis-prompt");
5
+ const parse_helper_1 = require("./parse-helper");
6
+ class GeminiProvider {
7
+ constructor(config, debug = false) {
8
+ this.name = 'gemini';
9
+ this.config = config;
10
+ this.debug = debug;
11
+ }
12
+ async analyzeSession(session) {
13
+ let GoogleGenerativeAI;
14
+ try {
15
+ ({ GoogleGenerativeAI } = require('@google/generative-ai'));
16
+ }
17
+ catch {
18
+ throw new Error('Gemini provider requires @google/generative-ai. Run: npm install @google/generative-ai');
19
+ }
20
+ const genAI = new GoogleGenerativeAI(this.config.analysis.apiKey);
21
+ const model = genAI.getGenerativeModel({
22
+ model: this.config.analysis.model || 'gemini-1.5-pro',
23
+ systemInstruction: analysis_prompt_1.SYSTEM_PROMPT,
24
+ generationConfig: {
25
+ responseMimeType: 'application/json',
26
+ maxOutputTokens: this.config.analysis.maxOutputTokens,
27
+ },
28
+ });
29
+ const userMessage = (0, analysis_prompt_1.buildUserMessage)(session);
30
+ if (this.debug) {
31
+ console.error('\n── DEBUG: REQUEST ──────────────────────────────────────');
32
+ console.error(`Model: ${this.config.analysis.model || 'gemini-1.5-pro'}`);
33
+ console.error(`Max tokens: ${this.config.analysis.maxOutputTokens}`);
34
+ console.error(`System prompt length: ${analysis_prompt_1.SYSTEM_PROMPT.length} chars`);
35
+ console.error(`User message length: ${userMessage.length} chars`);
36
+ console.error('\n── DEBUG: USER MESSAGE ─────────────────────────────────');
37
+ console.error(userMessage);
38
+ console.error('────────────────────────────────────────────────────────\n');
39
+ }
40
+ const result = await model.generateContent(userMessage);
41
+ const text = result.response.text();
42
+ if (this.debug) {
43
+ console.error('\n── DEBUG: RESPONSE ─────────────────────────────────────');
44
+ console.error(`Finish reason: ${result.response.candidates?.[0]?.finishReason}`);
45
+ console.error(`Token count: ${result.response.usageMetadata?.candidatesTokenCount}`);
46
+ console.error('\n── DEBUG: RAW CONTENT ──────────────────────────────────');
47
+ console.error(text || '(empty — model returned nothing)');
48
+ console.error('────────────────────────────────────────────────────────\n');
49
+ }
50
+ if (!text) {
51
+ throw new Error(`Gemini returned empty response (finish reason: ${result.response.candidates?.[0]?.finishReason}). ` +
52
+ `Run with --debug to investigate.`);
53
+ }
54
+ return (0, parse_helper_1.parseOrThrow)(text, 'Gemini', this.config.analysis.maxOutputTokens);
55
+ }
56
+ }
57
+ exports.GeminiProvider = GeminiProvider;
58
+ //# sourceMappingURL=gemini-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini-provider.js","sourceRoot":"","sources":["../../../analysis/providers/gemini-provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { LLMProvider } from '../llm-provider';
2
+ import { SessionContext, SessionFeedback } from '../types';
3
+ import { Config } from '../../config';
4
+ export declare class OpenAIProvider implements LLMProvider {
5
+ readonly name = "openai";
6
+ debug: boolean;
7
+ private config;
8
+ constructor(config: Config, debug?: boolean);
9
+ analyzeSession(session: SessionContext): Promise<SessionFeedback>;
10
+ }
11
+ //# sourceMappingURL=openai-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-provider.d.ts","sourceRoot":"","sources":["../../../analysis/providers/openai-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3D,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAGtC,qBAAa,cAAe,YAAW,WAAW;IAChD,QAAQ,CAAC,IAAI,YAAY;IACzB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,MAAM,EAAE,KAAK,UAAQ;IAKnC,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;CA2DxE"}
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OpenAIProvider = void 0;
4
+ const analysis_prompt_1 = require("../analysis-prompt");
5
+ const parse_helper_1 = require("./parse-helper");
6
+ class OpenAIProvider {
7
+ constructor(config, debug = false) {
8
+ this.name = 'openai';
9
+ this.config = config;
10
+ this.debug = debug;
11
+ }
12
+ async analyzeSession(session) {
13
+ let OpenAI;
14
+ try {
15
+ OpenAI = require('openai');
16
+ }
17
+ catch {
18
+ throw new Error('OpenAI provider requires openai. Run: npm install openai');
19
+ }
20
+ const client = new OpenAI.default({ apiKey: this.config.analysis.apiKey });
21
+ const userMessage = (0, analysis_prompt_1.buildUserMessage)(session);
22
+ if (this.debug) {
23
+ console.error('\n── DEBUG: REQUEST ──────────────────────────────────────');
24
+ console.error(`Model: ${this.config.analysis.model || 'gpt-4o'}`);
25
+ console.error(`Max tokens: ${this.config.analysis.maxOutputTokens}`);
26
+ console.error(`System prompt length: ${analysis_prompt_1.SYSTEM_PROMPT.length} chars`);
27
+ console.error(`User message length: ${userMessage.length} chars`);
28
+ console.error('\n── DEBUG: USER MESSAGE ─────────────────────────────────');
29
+ console.error(userMessage);
30
+ console.error('────────────────────────────────────────────────────────\n');
31
+ }
32
+ const response = await client.chat.completions.create({
33
+ model: this.config.analysis.model || 'gpt-4o',
34
+ max_tokens: this.config.analysis.maxOutputTokens,
35
+ messages: [
36
+ { role: 'system', content: analysis_prompt_1.SYSTEM_PROMPT },
37
+ { role: 'user', content: userMessage },
38
+ ],
39
+ response_format: {
40
+ type: 'json_schema',
41
+ json_schema: {
42
+ name: 'session_feedback',
43
+ strict: true,
44
+ schema: analysis_prompt_1.FEEDBACK_SCHEMA,
45
+ },
46
+ },
47
+ });
48
+ if (this.debug) {
49
+ console.error('\n── DEBUG: RESPONSE ─────────────────────────────────────');
50
+ console.error(`Finish reason: ${response.choices[0]?.finish_reason}`);
51
+ console.error(`Prompt tokens: ${response.usage?.prompt_tokens}`);
52
+ console.error(`Output tokens: ${response.usage?.completion_tokens}`);
53
+ console.error('\n── DEBUG: RAW CONTENT ──────────────────────────────────');
54
+ console.error(response.choices[0]?.message?.content);
55
+ console.error('────────────────────────────────────────────────────────\n');
56
+ }
57
+ const content = response.choices[0]?.message?.content;
58
+ if (!content) {
59
+ throw new Error(`OpenAI returned empty response (finish_reason: ${response.choices[0]?.finish_reason}). ` +
60
+ `Run with --debug to see the full response.`);
61
+ }
62
+ return (0, parse_helper_1.parseOrThrow)(content, 'OpenAI', this.config.analysis.maxOutputTokens);
63
+ }
64
+ }
65
+ exports.OpenAIProvider = OpenAIProvider;
66
+ //# sourceMappingURL=openai-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-provider.js","sourceRoot":"","sources":["../../../analysis/providers/openai-provider.ts"],"names":[],"mappings":";;;AAEA,wDAAsF;AAEtF,iDAA8C;AAE9C,MAAa,cAAc;IAKzB,YAAY,MAAc,EAAE,KAAK,GAAG,KAAK;QAJhC,SAAI,GAAG,QAAQ,CAAC;QAKvB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,OAAuB;QAC1C,IAAI,MAAW,CAAC;QAChB,IAAI,CAAC;YACH,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC7B,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;QAC9E,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAC3E,MAAM,WAAW,GAAG,IAAA,kCAAgB,EAAC,OAAO,CAAC,CAAC;QAE9C,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;YAC5E,OAAO,CAAC,KAAK,CAAC,eAAe,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,IAAI,QAAQ,EAAE,CAAC,CAAC;YACvE,OAAO,CAAC,KAAK,CAAC,eAAe,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,EAAE,CAAC,CAAC;YACrE,OAAO,CAAC,KAAK,CAAC,yBAAyB,+BAAa,CAAC,MAAM,QAAQ,CAAC,CAAC;YACrE,OAAO,CAAC,KAAK,CAAC,yBAAyB,WAAW,CAAC,MAAM,QAAQ,CAAC,CAAC;YACnE,OAAO,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;YAC5E,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YAC3B,OAAO,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAC9E,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;YACpD,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,IAAI,QAAQ;YAC7C,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe;YAChD,QAAQ,EAAE;gBACR,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,+BAAa,EAAE;gBAC1C,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE;aACvC;YACD,eAAe,EAAE;gBACf,IAAI,EAAE,aAAa;gBACnB,WAAW,EAAE;oBACX,IAAI,EAAE,kBAAkB;oBACxB,MAAM,EAAE,IAAI;oBACZ,MAAM,EAAE,iCAAe;iBACxB;aACF;SACF,CAAC,CAAC;QAEH,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;YAC5E,OAAO,CAAC,KAAK,CAAC,mBAAmB,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC;YACvE,OAAO,CAAC,KAAK,CAAC,mBAAmB,QAAQ,CAAC,KAAK,EAAE,aAAa,EAAE,CAAC,CAAC;YAClE,OAAO,CAAC,KAAK,CAAC,mBAAmB,QAAQ,CAAC,KAAK,EAAE,iBAAiB,EAAE,CAAC,CAAC;YACtE,OAAO,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;YAC5E,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;YACrD,OAAO,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAC9E,CAAC;QAED,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC;QACtD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,kDAAkD,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,aAAa,KAAK;gBACzF,4CAA4C,CAC7C,CAAC;QACJ,CAAC;QAED,OAAO,IAAA,2BAAY,EAAC,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;IAC/E,CAAC;CACF;AArED,wCAqEC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Parse JSON from an LLM response, giving a clear error when the response is truncated.
3
+ * "Unterminated string" / "Unexpected end of JSON" errors mean the model hit its output
4
+ * token limit mid-response — the remedy is to raise maxOutputTokens.
5
+ */
6
+ export declare function parseOrThrow(text: string, provider: string, maxOutputTokens: number): any;
7
+ //# sourceMappingURL=parse-helper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-helper.d.ts","sourceRoot":"","sources":["../../../analysis/providers/parse-helper.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,GAAG,CAqBzF"}
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseOrThrow = parseOrThrow;
4
+ /**
5
+ * Parse JSON from an LLM response, giving a clear error when the response is truncated.
6
+ * "Unterminated string" / "Unexpected end of JSON" errors mean the model hit its output
7
+ * token limit mid-response — the remedy is to raise maxOutputTokens.
8
+ */
9
+ function parseOrThrow(text, provider, maxOutputTokens) {
10
+ try {
11
+ return JSON.parse(text);
12
+ }
13
+ catch (err) {
14
+ const truncated = err.message?.includes('Unterminated') ||
15
+ err.message?.includes('Unexpected end') ||
16
+ err.message?.includes('Unexpected token');
17
+ if (truncated) {
18
+ throw new Error(`${provider} response was truncated before the JSON could be completed.\n` +
19
+ ` Response length: ${text.length} chars\n` +
20
+ ` Current maxOutputTokens: ${maxOutputTokens}\n` +
21
+ ` Fix: coding-analytics analyze configure --max-output-tokens ${Math.round(maxOutputTokens * 1.5)}\n` +
22
+ ` Run with --debug to see the full raw response.`);
23
+ }
24
+ throw new Error(`${provider} returned invalid JSON: ${err.message}\nRun with --debug to see the raw response.`);
25
+ }
26
+ }
27
+ //# sourceMappingURL=parse-helper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-helper.js","sourceRoot":"","sources":["../../../analysis/providers/parse-helper.ts"],"names":[],"mappings":";;AAKA,oCAqBC;AA1BD;;;;GAIG;AACH,SAAgB,YAAY,CAAC,IAAY,EAAE,QAAgB,EAAE,eAAuB;IAClF,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,MAAM,SAAS,GACb,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,cAAc,CAAC;YACrC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,gBAAgB,CAAC;YACvC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,kBAAkB,CAAC,CAAC;QAE5C,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CACb,GAAG,QAAQ,+DAA+D;gBAC1E,sBAAsB,IAAI,CAAC,MAAM,UAAU;gBAC3C,8BAA8B,eAAe,IAAI;gBACjD,iEAAiE,IAAI,CAAC,KAAK,CAAC,eAAe,GAAG,GAAG,CAAC,IAAI;gBACtG,kDAAkD,CACnD,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,2BAA2B,GAAG,CAAC,OAAO,6CAA6C,CAAC,CAAC;IAClH,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { SessionContext, SessionFeedback } from './types';
2
+ import { LLMProvider } from './llm-provider';
3
+ export declare class SessionAnalyzer {
4
+ private provider;
5
+ constructor(provider: LLMProvider);
6
+ analyze(session: SessionContext): Promise<SessionFeedback>;
7
+ }
8
+ //# sourceMappingURL=session-analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-analyzer.d.ts","sourceRoot":"","sources":["../../analysis/session-analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAc;gBAElB,QAAQ,EAAE,WAAW;IAI3B,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;CAwCjE"}
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SessionAnalyzer = void 0;
4
+ const logger_1 = require("../logger");
5
+ class SessionAnalyzer {
6
+ constructor(provider) {
7
+ this.provider = provider;
8
+ }
9
+ async analyze(session) {
10
+ logger_1.logger.debug('Analyzing session', {
11
+ sessionId: session.sessionId,
12
+ provider: this.provider.name,
13
+ turns: session.turns.length,
14
+ });
15
+ if (session.stats.totalPrompts === 0) {
16
+ throw new Error(`Session ${session.sessionId} has no prompts — nothing to analyze`);
17
+ }
18
+ const raw = await this.provider.analyzeSession(session);
19
+ if (this.provider.debug) {
20
+ console.error('\n── DEBUG: RAW KEYS BEFORE NORMALIZATION ────────────────');
21
+ console.error('Top-level keys:', Object.keys(raw ?? {}));
22
+ console.error('context_setup :', typeof raw?.context_setup, '→', JSON.stringify(raw?.context_setup)?.slice(0, 120));
23
+ console.error('patterns_to_improve:', Array.isArray(raw?.patterns_to_improve)
24
+ ? `array[${raw.patterns_to_improve.length}]`
25
+ : typeof raw?.patterns_to_improve, '→', JSON.stringify(raw?.patterns_to_improve)?.slice(0, 120));
26
+ console.error('scores :', typeof raw?.scores, '→ keys:', Object.keys(raw?.scores ?? {}));
27
+ console.error('quick_win :', typeof raw?.quick_win, '→', JSON.stringify(raw?.quick_win)?.slice(0, 120));
28
+ console.error('overview :', typeof raw?.overview, '→', JSON.stringify(raw?.overview)?.slice(0, 120));
29
+ console.error('────────────────────────────────────────────────────────\n');
30
+ }
31
+ const feedback = normalize(raw, this.provider.debug);
32
+ if (this.provider.debug) {
33
+ console.error('\n── DEBUG: AFTER NORMALIZATION ──────────────────────────');
34
+ console.error('overview :', feedback.overview?.slice(0, 100) || '(empty)');
35
+ console.error('context_setup :', feedback.context_setup?.slice(0, 100) || '(empty)');
36
+ console.error('patterns_count :', feedback.patterns_to_improve.length);
37
+ console.error('scores.prompt_clarity:', feedback.scores.prompt_clarity);
38
+ console.error('quick_win.action:', feedback.quick_win.action?.slice(0, 100) || '(empty)');
39
+ console.error('────────────────────────────────────────────────────────\n');
40
+ }
41
+ return feedback;
42
+ }
43
+ }
44
+ exports.SessionAnalyzer = SessionAnalyzer;
45
+ /**
46
+ * Coerce whatever the LLM returned into the expected SessionFeedback shape.
47
+ * LLMs occasionally use alternate field names, return the old schema shape,
48
+ * or omit fields when token budget runs short.
49
+ */
50
+ function normalize(raw, debug = false) {
51
+ // Resolve alternate top-level key names before delegating to field normalizers
52
+ const contextSetup = raw.context_setup ?? raw.contextSetup ?? raw.setup ?? raw.configuration;
53
+ const patterns = raw.patterns_to_improve ?? raw.patterns ?? raw.improvements ?? raw.issues;
54
+ const scores = raw.scores ?? raw.score ?? raw.dimensions;
55
+ const quickWin = raw.quick_win ?? raw.quickWin ?? raw.win ?? raw.recommendation ?? raw.next_step;
56
+ const overview = raw.overview ?? raw.summary ?? raw.description ?? raw.session_overview;
57
+ return {
58
+ overview: typeof overview === 'string' ? overview : '',
59
+ context_setup: normalizeContextSetup(contextSetup),
60
+ patterns_to_improve: normalizePatterns(patterns),
61
+ scores: normalizeScores(scores),
62
+ quick_win: normalizeQuickWin(quickWin),
63
+ };
64
+ }
65
+ function normalizeContextSetup(v) {
66
+ if (typeof v === 'string')
67
+ return v;
68
+ if (!v)
69
+ return '';
70
+ // Old schema returned { issues: [], suggestions: [], score: n }
71
+ const parts = [];
72
+ if (Array.isArray(v.issues))
73
+ parts.push(v.issues.join(' '));
74
+ if (Array.isArray(v.suggestions))
75
+ parts.push(v.suggestions.join(' '));
76
+ if (typeof v.description === 'string')
77
+ parts.push(v.description);
78
+ return parts.join('\n') || JSON.stringify(v);
79
+ }
80
+ function normalizePatterns(v) {
81
+ if (!Array.isArray(v))
82
+ return [];
83
+ return v.map((p) => ({
84
+ name: p.name ?? p.pattern ?? 'Unknown pattern',
85
+ prompt_references: Array.isArray(p.prompt_references) ? p.prompt_references : [],
86
+ explanation: p.explanation ?? p.description ?? '',
87
+ rewrite: p.rewrite ?? p.suggested ?? p.example ?? '',
88
+ }));
89
+ }
90
+ function normalizeScores(v) {
91
+ if (!v)
92
+ v = {};
93
+ // Accept both snake_case and alternate key names the LLM sometimes uses
94
+ return {
95
+ prompt_clarity: v.prompt_clarity ?? v.clarity ?? 0,
96
+ prompt_clarity_reason: v.prompt_clarity_reason ?? v.clarity_reason ?? '',
97
+ context_provision: v.context_provision ?? v.context ?? 0,
98
+ context_provision_reason: v.context_provision_reason ?? v.context_reason ?? '',
99
+ session_efficiency: v.session_efficiency ?? v.efficiency ?? 0,
100
+ session_efficiency_reason: v.session_efficiency_reason ?? v.efficiency_reason ?? '',
101
+ setup_and_tooling: v.setup_and_tooling ?? v.setup ?? v.tooling ?? 0,
102
+ setup_and_tooling_reason: v.setup_and_tooling_reason ?? v.setup_reason ?? v.tooling_reason ?? '',
103
+ };
104
+ }
105
+ function normalizeQuickWin(v) {
106
+ if (!v)
107
+ return { action: '', spec_sections_needed: [] };
108
+ if (typeof v === 'string')
109
+ return { action: v, spec_sections_needed: [] };
110
+ return {
111
+ action: v.action ?? v.text ?? v.recommendation ?? '',
112
+ spec_sections_needed: Array.isArray(v.spec_sections_needed) ? v.spec_sections_needed : [],
113
+ };
114
+ }
115
+ //# sourceMappingURL=session-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-analyzer.js","sourceRoot":"","sources":["../../analysis/session-analyzer.ts"],"names":[],"mappings":";;;AAEA,sCAAmC;AAEnC,MAAa,eAAe;IAG1B,YAAY,QAAqB;QAC/B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAuB;QACnC,eAAM,CAAC,KAAK,CAAC,mBAAmB,EAAE;YAChC,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI;YAC5B,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM;SAC5B,CAAC,CAAC;QAEH,IAAI,OAAO,CAAC,KAAK,CAAC,YAAY,KAAK,CAAC,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CAAC,WAAW,OAAO,CAAC,SAAS,sCAAsC,CAAC,CAAC;QACtF,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAExD,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;YACxB,OAAO,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;YAC5E,OAAO,CAAC,KAAK,CAAC,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC;YACzD,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,OAAO,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,aAAa,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YACrH,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,mBAAmB,CAAC;gBAC3E,CAAC,CAAC,SAAS,GAAG,CAAC,mBAAmB,CAAC,MAAM,GAAG;gBAC5C,CAAC,CAAC,OAAO,GAAG,EAAE,mBAAmB,EAAE,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,mBAAmB,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YACnG,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,OAAO,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC;YACjG,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,OAAO,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YAC7G,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,OAAO,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YAC3G,OAAO,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAC9E,CAAC;QAED,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAErD,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;YACxB,OAAO,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;YAC5E,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,SAAS,CAAC,CAAC;YACjF,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,QAAQ,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,SAAS,CAAC,CAAC;YACtF,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,QAAQ,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC;YACvE,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;YACxE,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,SAAS,CAAC,CAAC;YAC1F,OAAO,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAC9E,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF;AA/CD,0CA+CC;AAED;;;;GAIG;AACH,SAAS,SAAS,CAAC,GAAQ,EAAE,KAAK,GAAG,KAAK;IACxC,+EAA+E;IAC/E,MAAM,YAAY,GAAK,GAAG,CAAC,aAAa,IAAI,GAAG,CAAC,YAAY,IAAI,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,aAAa,CAAC;IAC/F,MAAM,QAAQ,GAAS,GAAG,CAAC,mBAAmB,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,YAAY,IAAI,GAAG,CAAC,MAAM,CAAC;IACjG,MAAM,MAAM,GAAW,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,UAAU,CAAC;IACjE,MAAM,QAAQ,GAAS,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,cAAc,IAAI,GAAG,CAAC,SAAS,CAAC;IACvG,MAAM,QAAQ,GAAS,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,gBAAgB,CAAC;IAE9F,OAAO;QACL,QAAQ,EAAE,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;QACtD,aAAa,EAAE,qBAAqB,CAAC,YAAY,CAAC;QAClD,mBAAmB,EAAE,iBAAiB,CAAC,QAAQ,CAAC;QAChD,MAAM,EAAE,eAAe,CAAC,MAAM,CAAC;QAC/B,SAAS,EAAE,iBAAiB,CAAC,QAAQ,CAAC;KACvC,CAAC;AACJ,CAAC;AAED,SAAS,qBAAqB,CAAC,CAAM;IACnC,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC;IACpC,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAClB,gEAAgE;IAChE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5D,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACtE,IAAI,OAAO,CAAC,CAAC,WAAW,KAAK,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IACjE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,iBAAiB,CAAC,CAAM;IAC/B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IACjC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC;QACxB,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,OAAO,IAAI,iBAAiB;QAC9C,iBAAiB,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE;QAChF,WAAW,EAAE,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,WAAW,IAAI,EAAE;QACjD,OAAO,EAAE,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,OAAO,IAAI,EAAE;KACrD,CAAC,CAAC,CAAC;AACN,CAAC;AAED,SAAS,eAAe,CAAC,CAAM;IAC7B,IAAI,CAAC,CAAC;QAAE,CAAC,GAAG,EAAE,CAAC;IACf,wEAAwE;IACxE,OAAO;QACL,cAAc,EAAE,CAAC,CAAC,cAAc,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC;QAClD,qBAAqB,EAAE,CAAC,CAAC,qBAAqB,IAAI,CAAC,CAAC,cAAc,IAAI,EAAE;QACxE,iBAAiB,EAAE,CAAC,CAAC,iBAAiB,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC;QACxD,wBAAwB,EAAE,CAAC,CAAC,wBAAwB,IAAI,CAAC,CAAC,cAAc,IAAI,EAAE;QAC9E,kBAAkB,EAAE,CAAC,CAAC,kBAAkB,IAAI,CAAC,CAAC,UAAU,IAAI,CAAC;QAC7D,yBAAyB,EAAE,CAAC,CAAC,yBAAyB,IAAI,CAAC,CAAC,iBAAiB,IAAI,EAAE;QACnF,iBAAiB,EAAE,CAAC,CAAC,iBAAiB,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC;QACnE,wBAAwB,EAAE,CAAC,CAAC,wBAAwB,IAAI,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC,cAAc,IAAI,EAAE;KACjG,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,CAAM;IAC/B,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,oBAAoB,EAAE,EAAE,EAAE,CAAC;IACxD,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,oBAAoB,EAAE,EAAE,EAAE,CAAC;IAC1E,OAAO;QACL,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,cAAc,IAAI,EAAE;QACpD,oBAAoB,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE;KAC1F,CAAC;AACJ,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { SessionContext } from './types';
2
+ import { Config } from '../config';
3
+ export declare class SessionBuilder {
4
+ private config;
5
+ constructor(config: Config);
6
+ build(sessionId: string): Promise<SessionContext>;
7
+ listSessionIds(distinctId: string, afterIso: string): Promise<string[]>;
8
+ private getQueryBase;
9
+ private authHeader;
10
+ private fetchEvents;
11
+ private fetchEventsByUser;
12
+ private paginate;
13
+ private assemble;
14
+ private detectProvider;
15
+ private extractMetadata;
16
+ private buildTurns;
17
+ private computeStats;
18
+ }
19
+ //# sourceMappingURL=session-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-builder.d.ts","sourceRoot":"","sources":["../../analysis/session-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAA8C,MAAM,SAAS,CAAC;AACrF,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AASnC,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,MAAM;IAIpB,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAQjD,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAW7E,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,UAAU;YAOJ,WAAW;YAQX,iBAAiB;YAKjB,QAAQ;IAoBtB,OAAO,CAAC,QAAQ;IAsBhB,OAAO,CAAC,cAAc;IAUtB,OAAO,CAAC,eAAe;IAwBvB,OAAO,CAAC,UAAU;IAuClB,OAAO,CAAC,YAAY;CAsBrB"}