@maxanatsko/llm-cli-bridge 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/LICENSE +26 -0
  2. package/README.md +203 -0
  3. package/dist/backends/codex.d.ts +37 -0
  4. package/dist/backends/codex.d.ts.map +1 -0
  5. package/dist/backends/codex.js +438 -0
  6. package/dist/backends/codex.js.map +1 -0
  7. package/dist/backends/gemini.d.ts +17 -0
  8. package/dist/backends/gemini.d.ts.map +1 -0
  9. package/dist/backends/gemini.js +174 -0
  10. package/dist/backends/gemini.js.map +1 -0
  11. package/dist/backends/index.d.ts +8 -0
  12. package/dist/backends/index.d.ts.map +1 -0
  13. package/dist/backends/index.js +9 -0
  14. package/dist/backends/index.js.map +1 -0
  15. package/dist/backends/registry.d.ts +33 -0
  16. package/dist/backends/registry.d.ts.map +1 -0
  17. package/dist/backends/registry.js +80 -0
  18. package/dist/backends/registry.js.map +1 -0
  19. package/dist/backends/types.d.ts +61 -0
  20. package/dist/backends/types.d.ts.map +1 -0
  21. package/dist/backends/types.js +5 -0
  22. package/dist/backends/types.js.map +1 -0
  23. package/dist/constants.d.ts +223 -0
  24. package/dist/constants.d.ts.map +1 -0
  25. package/dist/constants.js +228 -0
  26. package/dist/constants.js.map +1 -0
  27. package/dist/index.d.ts +3 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +192 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/tools/ask.tool.d.ts +4 -0
  32. package/dist/tools/ask.tool.d.ts.map +1 -0
  33. package/dist/tools/ask.tool.js +113 -0
  34. package/dist/tools/ask.tool.js.map +1 -0
  35. package/dist/tools/brainstorm.tool.d.ts +3 -0
  36. package/dist/tools/brainstorm.tool.d.ts.map +1 -0
  37. package/dist/tools/brainstorm.tool.js +250 -0
  38. package/dist/tools/brainstorm.tool.js.map +1 -0
  39. package/dist/tools/index.d.ts +5 -0
  40. package/dist/tools/index.d.ts.map +1 -0
  41. package/dist/tools/index.js +13 -0
  42. package/dist/tools/index.js.map +1 -0
  43. package/dist/tools/registry.d.ts +42 -0
  44. package/dist/tools/registry.d.ts.map +1 -0
  45. package/dist/tools/registry.js +85 -0
  46. package/dist/tools/registry.js.map +1 -0
  47. package/dist/tools/review-code.tool.d.ts +3 -0
  48. package/dist/tools/review-code.tool.d.ts.map +1 -0
  49. package/dist/tools/review-code.tool.js +279 -0
  50. package/dist/tools/review-code.tool.js.map +1 -0
  51. package/dist/tools/test-tool.example.d.ts +13 -0
  52. package/dist/tools/test-tool.example.d.ts.map +1 -0
  53. package/dist/tools/test-tool.example.js +32 -0
  54. package/dist/tools/test-tool.example.js.map +1 -0
  55. package/dist/tools/timeout-test.tool.d.ts +3 -0
  56. package/dist/tools/timeout-test.tool.d.ts.map +1 -0
  57. package/dist/tools/timeout-test.tool.js +38 -0
  58. package/dist/tools/timeout-test.tool.js.map +1 -0
  59. package/dist/utils/askSessionManager.d.ts +59 -0
  60. package/dist/utils/askSessionManager.d.ts.map +1 -0
  61. package/dist/utils/askSessionManager.js +123 -0
  62. package/dist/utils/askSessionManager.js.map +1 -0
  63. package/dist/utils/brainstormSessionManager.d.ts +67 -0
  64. package/dist/utils/brainstormSessionManager.d.ts.map +1 -0
  65. package/dist/utils/brainstormSessionManager.js +174 -0
  66. package/dist/utils/brainstormSessionManager.js.map +1 -0
  67. package/dist/utils/changeModeInstructions.d.ts +17 -0
  68. package/dist/utils/changeModeInstructions.d.ts.map +1 -0
  69. package/dist/utils/changeModeInstructions.js +100 -0
  70. package/dist/utils/changeModeInstructions.js.map +1 -0
  71. package/dist/utils/changeModeParser.d.ts +15 -0
  72. package/dist/utils/changeModeParser.d.ts.map +1 -0
  73. package/dist/utils/changeModeParser.js +81 -0
  74. package/dist/utils/changeModeParser.js.map +1 -0
  75. package/dist/utils/changeModeTranslator.d.ts +4 -0
  76. package/dist/utils/changeModeTranslator.d.ts.map +1 -0
  77. package/dist/utils/changeModeTranslator.js +42 -0
  78. package/dist/utils/changeModeTranslator.js.map +1 -0
  79. package/dist/utils/commandExecutor.d.ts +2 -0
  80. package/dist/utils/commandExecutor.d.ts.map +1 -0
  81. package/dist/utils/commandExecutor.js +76 -0
  82. package/dist/utils/commandExecutor.js.map +1 -0
  83. package/dist/utils/envAllowlist.d.ts +17 -0
  84. package/dist/utils/envAllowlist.d.ts.map +1 -0
  85. package/dist/utils/envAllowlist.js +54 -0
  86. package/dist/utils/envAllowlist.js.map +1 -0
  87. package/dist/utils/geminiExecutor.d.ts +3 -0
  88. package/dist/utils/geminiExecutor.d.ts.map +1 -0
  89. package/dist/utils/geminiExecutor.js +94 -0
  90. package/dist/utils/geminiExecutor.js.map +1 -0
  91. package/dist/utils/gitStateDetector.d.ts +32 -0
  92. package/dist/utils/gitStateDetector.d.ts.map +1 -0
  93. package/dist/utils/gitStateDetector.js +68 -0
  94. package/dist/utils/gitStateDetector.js.map +1 -0
  95. package/dist/utils/logger.d.ts +13 -0
  96. package/dist/utils/logger.d.ts.map +1 -0
  97. package/dist/utils/logger.js +42 -0
  98. package/dist/utils/logger.js.map +1 -0
  99. package/dist/utils/reviewFormatter.d.ts +35 -0
  100. package/dist/utils/reviewFormatter.d.ts.map +1 -0
  101. package/dist/utils/reviewFormatter.js +201 -0
  102. package/dist/utils/reviewFormatter.js.map +1 -0
  103. package/dist/utils/reviewPromptBuilder.d.ts +43 -0
  104. package/dist/utils/reviewPromptBuilder.d.ts.map +1 -0
  105. package/dist/utils/reviewPromptBuilder.js +170 -0
  106. package/dist/utils/reviewPromptBuilder.js.map +1 -0
  107. package/dist/utils/reviewResponseParser.d.ts +20 -0
  108. package/dist/utils/reviewResponseParser.d.ts.map +1 -0
  109. package/dist/utils/reviewResponseParser.js +149 -0
  110. package/dist/utils/reviewResponseParser.js.map +1 -0
  111. package/dist/utils/reviewSessionCache.d.ts +81 -0
  112. package/dist/utils/reviewSessionCache.d.ts.map +1 -0
  113. package/dist/utils/reviewSessionCache.js +220 -0
  114. package/dist/utils/reviewSessionCache.js.map +1 -0
  115. package/dist/utils/reviewSessionManager.d.ts +52 -0
  116. package/dist/utils/reviewSessionManager.d.ts.map +1 -0
  117. package/dist/utils/reviewSessionManager.js +65 -0
  118. package/dist/utils/reviewSessionManager.js.map +1 -0
  119. package/dist/utils/sessionManager.d.ts +95 -0
  120. package/dist/utils/sessionManager.d.ts.map +1 -0
  121. package/dist/utils/sessionManager.js +382 -0
  122. package/dist/utils/sessionManager.js.map +1 -0
  123. package/dist/utils/sessionSchemas.d.ts +140 -0
  124. package/dist/utils/sessionSchemas.d.ts.map +1 -0
  125. package/dist/utils/sessionSchemas.js +2 -0
  126. package/dist/utils/sessionSchemas.js.map +1 -0
  127. package/dist/utils/timeoutManager.d.ts +2 -0
  128. package/dist/utils/timeoutManager.d.ts.map +1 -0
  129. package/dist/utils/timeoutManager.js +2 -0
  130. package/dist/utils/timeoutManager.js.map +1 -0
  131. package/package.json +72 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reviewPromptBuilder.d.ts","sourceRoot":"","sources":["../../src/utils/reviewPromptBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,IAAI,iBAAiB,EAAe,MAAM,qBAAqB,CAAC;AACnG,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGjD,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,iBAAiB,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,OAAO,CAAC;IACxB,eAAe,EAAE,QAAQ,CAAC;CAC3B;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,CAiDpE;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAgBhE;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CA2CpE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,CA8CvE;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAU/D"}
@@ -0,0 +1,170 @@
1
+ import { REVIEW } from '../constants.js';
2
+ /**
3
+ * Builds a context-aware review prompt for the AI backend
4
+ * @param config Review prompt configuration
5
+ * @returns Formatted prompt string
6
+ */
7
+ export function buildReviewPrompt(config) {
8
+ const { userPrompt, session, files, reviewType, severity, includeHistory, currentGitState } = config;
9
+ // Build file references with @ syntax
10
+ const fileRefs = files?.map(f => `@${f}`).join(' ') || '';
11
+ let prompt = `# CODE REVIEW SESSION (Round ${session.totalRounds + 1})
12
+
13
+ ## Review Context
14
+ - Session ID: ${session.sessionId}
15
+ - Branch: ${currentGitState.branch}
16
+ - Commit: ${currentGitState.commitHash.slice(0, 8)}
17
+ - Review Type: ${reviewType}
18
+ - Severity Scope: ${severity}
19
+ - Files: ${files?.length || 'all tracked'} ${files ? 'specified' : 'files'}
20
+
21
+ ## Review Instructions
22
+ ${getReviewTypeInstructions(reviewType)}
23
+
24
+ ## Severity Filter
25
+ ${getSeverityInstructions(severity)}
26
+
27
+ ## Output Format
28
+ For each issue found, use this EXACT format:
29
+
30
+ **[SEVERITY: critical|important|suggestion|question]**
31
+ **File:** {filename}
32
+ **Lines:** {start}-{end} (if applicable, otherwise write "N/A")
33
+ **Issue:** {brief title}
34
+ **Details:** {explanation}
35
+ **Recommendation:** {suggested fix or action}
36
+
37
+ ---
38
+
39
+ `;
40
+ // Include conversation history if requested and exists
41
+ if (includeHistory && session.rounds.length > 0) {
42
+ prompt += formatPreviousRounds(session);
43
+ }
44
+ // Add user's current request
45
+ prompt += `\n## Current Review Request\n`;
46
+ if (fileRefs) {
47
+ prompt += `${fileRefs}\n\n`;
48
+ }
49
+ prompt += `${userPrompt}\n`;
50
+ return prompt;
51
+ }
52
+ /**
53
+ * Returns severity-specific instructions so the model does not waste time
54
+ * generating feedback that will be discarded after parsing.
55
+ * @param severity The requested severity scope
56
+ * @returns Formatted instructions string
57
+ */
58
+ export function getSeverityInstructions(severity) {
59
+ const instructions = {
60
+ 'critical-only': `Only report **critical** issues.
61
+ - Do not include important, suggestion, or question items.
62
+ - If no critical issues exist, respond with: "No critical issues found."`,
63
+ 'important-and-above': `Only report **critical** and **important** issues.
64
+ - Do not include suggestion or question items.
65
+ - If no critical or important issues exist, respond with: "No critical or important issues found."`,
66
+ all: `Report actionable issues across all supported severities.
67
+ - Prioritize critical and important issues first.
68
+ - Avoid low-value nitpicks.`
69
+ };
70
+ return instructions[severity] || instructions.all;
71
+ }
72
+ /**
73
+ * Returns review instructions based on review type
74
+ * @param reviewType The type of review to perform
75
+ * @returns Formatted instructions string
76
+ */
77
+ export function getReviewTypeInstructions(reviewType) {
78
+ const instructions = {
79
+ security: `Focus on:
80
+ - Input validation and sanitization
81
+ - Authentication and authorization flaws
82
+ - SQL injection, XSS, CSRF vulnerabilities
83
+ - Secrets exposure (hardcoded credentials, API keys)
84
+ - Dependency vulnerabilities
85
+ - Insecure cryptography and data handling`,
86
+ performance: `Focus on:
87
+ - Algorithm complexity (O(n) analysis)
88
+ - Unnecessary loops or computations
89
+ - Memory leaks and inefficient data structures
90
+ - Database query optimization (N+1 queries, missing indexes)
91
+ - Caching opportunities
92
+ - Resource cleanup and connection pooling`,
93
+ quality: `Focus on:
94
+ - Code clarity and readability
95
+ - Naming conventions and consistency
96
+ - DRY violations (repeated code)
97
+ - Error handling and edge cases
98
+ - Test coverage gaps
99
+ - Documentation completeness`,
100
+ architecture: `Focus on:
101
+ - Design patterns and principles (SOLID, DRY, KISS)
102
+ - Module coupling and cohesion
103
+ - Scalability concerns
104
+ - API design and contracts
105
+ - Separation of concerns
106
+ - Technical debt and maintainability`,
107
+ general: `Perform a comprehensive review covering:
108
+ - Security vulnerabilities
109
+ - Performance bottlenecks
110
+ - Code quality issues
111
+ - Architectural concerns
112
+ Prioritize critical and important issues.`
113
+ };
114
+ return instructions[reviewType] || instructions.general;
115
+ }
116
+ /**
117
+ * Formats previous review rounds for context inclusion
118
+ * @param session The current review session
119
+ * @returns Formatted history string
120
+ */
121
+ export function formatPreviousRounds(session) {
122
+ let historyText = `\n## Previous Review Rounds\n`;
123
+ // Get last N rounds based on constant
124
+ const recentRounds = session.rounds.slice(-REVIEW.MAX_HISTORY_ROUNDS);
125
+ for (const round of recentRounds) {
126
+ historyText += `\n### Round ${round.roundNumber} (${new Date(round.timestamp).toLocaleString()})\n`;
127
+ historyText += `**User Request:** ${round.userPrompt}\n`;
128
+ historyText += `**Issues Found:** ${round.commentsGenerated.length}\n`;
129
+ // Include resolved/modified comments
130
+ const resolvedComments = round.commentsGenerated.filter(c => c.status !== 'pending');
131
+ if (resolvedComments.length > 0) {
132
+ historyText += `\n**Resolved Issues:**\n`;
133
+ resolvedComments.forEach(c => {
134
+ const statusEmoji = c.status === 'accepted' ? '✅' : c.status === 'rejected' ? '❌' : '📝';
135
+ historyText += `- [${statusEmoji} ${c.status.toUpperCase()}] ${c.filePattern}: ${c.comment.split('\n')[0]}`;
136
+ if (c.resolution) {
137
+ historyText += ` - ${c.resolution}`;
138
+ }
139
+ historyText += '\n';
140
+ });
141
+ }
142
+ // Show pending critical/important issues
143
+ const pendingImportant = round.commentsGenerated.filter(c => c.status === 'pending' && (c.severity === 'critical' || c.severity === 'important'));
144
+ if (pendingImportant.length > 0) {
145
+ historyText += `\n**Still Pending (Critical/Important):**\n`;
146
+ pendingImportant.forEach(c => {
147
+ const emoji = REVIEW.SEVERITY_EMOJI[c.severity];
148
+ historyText += `- ${emoji} ${c.filePattern}: ${c.comment.split('\n')[0]}\n`;
149
+ });
150
+ }
151
+ }
152
+ historyText += `\n**Total Issues Across All Rounds:** ${session.allComments.length}\n`;
153
+ historyText += `**Files Reviewed:** ${session.filesTracked.length}\n\n`;
154
+ return historyText;
155
+ }
156
+ /**
157
+ * Extracts file patterns from a prompt containing @ references
158
+ * @param prompt The prompt to parse
159
+ * @returns Array of file patterns
160
+ */
161
+ export function extractFilesFromPrompt(prompt) {
162
+ const filePattern = /@([^\s]+)/g;
163
+ const matches = [];
164
+ let match;
165
+ while ((match = filePattern.exec(prompt)) !== null) {
166
+ matches.push(match[1]);
167
+ }
168
+ return matches;
169
+ }
170
+ //# sourceMappingURL=reviewPromptBuilder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reviewPromptBuilder.js","sourceRoot":"","sources":["../../src/utils/reviewPromptBuilder.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAYzC;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAA0B;IAC1D,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,eAAe,EAAE,GAAG,MAAM,CAAC;IAErG,sCAAsC;IACtC,MAAM,QAAQ,GAAG,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;IAE1D,IAAI,MAAM,GAAG,gCAAgC,OAAO,CAAC,WAAW,GAAG,CAAC;;;gBAGtD,OAAO,CAAC,SAAS;YACrB,eAAe,CAAC,MAAM;YACtB,eAAe,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;iBACjC,UAAU;oBACP,QAAQ;WACjB,KAAK,EAAE,MAAM,IAAI,aAAa,IAAI,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO;;;EAGxE,yBAAyB,CAAC,UAAU,CAAC;;;EAGrC,uBAAuB,CAAC,QAAQ,CAAC;;;;;;;;;;;;;;CAclC,CAAC;IAEA,uDAAuD;IACvD,IAAI,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC1C,CAAC;IAED,6BAA6B;IAC7B,MAAM,IAAI,+BAA+B,CAAC;IAC1C,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,IAAI,GAAG,QAAQ,MAAM,CAAC;IAC9B,CAAC;IACD,MAAM,IAAI,GAAG,UAAU,IAAI,CAAC;IAE5B,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,QAAgB;IACtD,MAAM,YAAY,GAA2B;QAC3C,eAAe,EAAE;;yEAEoD;QAErE,qBAAqB,EAAE;;mGAEwE;QAE/F,GAAG,EAAE;;4BAEmB;KACzB,CAAC;IAEF,OAAO,YAAY,CAAC,QAAQ,CAAC,IAAI,YAAY,CAAC,GAAG,CAAC;AACpD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CAAC,UAAkB;IAC1D,MAAM,YAAY,GAA2B;QAC3C,QAAQ,EAAE;;;;;;0CAM4B;QAEtC,WAAW,EAAE;;;;;;0CAMyB;QAEtC,OAAO,EAAE;;;;;;6BAMgB;QAEzB,YAAY,EAAE;;;;;;qCAMmB;QAEjC,OAAO,EAAE;;;;;0CAK6B;KACvC,CAAC;IAEF,OAAO,YAAY,CAAC,UAAU,CAAC,IAAI,YAAY,CAAC,OAAO,CAAC;AAC1D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAA0B;IAC7D,IAAI,WAAW,GAAG,+BAA+B,CAAC;IAElD,sCAAsC;IACtC,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;IAEtE,KAAK,MAAM,KAAK,IAAI,YAAY,EAAE,CAAC;QACjC,WAAW,IAAI,eAAe,KAAK,CAAC,WAAW,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,cAAc,EAAE,KAAK,CAAC;QACpG,WAAW,IAAI,qBAAqB,KAAK,CAAC,UAAU,IAAI,CAAC;QACzD,WAAW,IAAI,qBAAqB,KAAK,CAAC,iBAAiB,CAAC,MAAM,IAAI,CAAC;QAEvE,qCAAqC;QACrC,MAAM,gBAAgB,GAAG,KAAK,CAAC,iBAAiB,CAAC,MAAM,CACrD,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAC5B,CAAC;QAEF,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,WAAW,IAAI,0BAA0B,CAAC;YAC1C,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;gBAC3B,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;gBACzF,WAAW,IAAI,MAAM,WAAW,IAAI,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,WAAW,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5G,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;oBACjB,WAAW,IAAI,MAAM,CAAC,CAAC,UAAU,EAAE,CAAC;gBACtC,CAAC;gBACD,WAAW,IAAI,IAAI,CAAC;YACtB,CAAC,CAAC,CAAC;QACL,CAAC;QAED,yCAAyC;QACzC,MAAM,gBAAgB,GAAG,KAAK,CAAC,iBAAiB,CAAC,MAAM,CACrD,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,IAAI,CAAC,CAAC,QAAQ,KAAK,WAAW,CAAC,CACzF,CAAC;QAEF,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,WAAW,IAAI,6CAA6C,CAAC;YAC7D,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;gBAC3B,MAAM,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,QAA8C,CAAC,CAAC;gBACtF,WAAW,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,WAAW,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC9E,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,WAAW,IAAI,yCAAyC,OAAO,CAAC,WAAW,CAAC,MAAM,IAAI,CAAC;IACvF,WAAW,IAAI,uBAAuB,OAAO,CAAC,YAAY,CAAC,MAAM,MAAM,CAAC;IAExE,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAc;IACnD,MAAM,WAAW,GAAG,YAAY,CAAC;IACjC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,KAAK,CAAC;IAEV,OAAO,CAAC,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACnD,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { ReviewComment } from './sessionSchemas.js';
2
+ /**
3
+ * Parses review response into structured ReviewComment objects
4
+ * @param responseText The raw response from the AI backend
5
+ * @param roundNumber The current review round number
6
+ * @returns Array of parsed review comments
7
+ */
8
+ export declare function parseReviewResponse(responseText: string, roundNumber: number): ReviewComment[];
9
+ /**
10
+ * Generates a unique comment ID using cryptographically secure UUID
11
+ * @returns Comment ID string
12
+ */
13
+ export declare function generateCommentId(): string;
14
+ /**
15
+ * Validates parsed comments for completeness
16
+ * @param comments Array of comments to validate
17
+ * @returns Array of valid comments
18
+ */
19
+ export declare function validateComments(comments: ReviewComment[]): ReviewComment[];
20
+ //# sourceMappingURL=reviewResponseParser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reviewResponseParser.d.ts","sourceRoot":"","sources":["../../src/utils/reviewResponseParser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGzD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,GAClB,aAAa,EAAE,CA+DjB;AAiBD;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAqDD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,aAAa,EAAE,CAe3E"}
@@ -0,0 +1,149 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { Logger } from './logger.js';
3
+ /**
4
+ * Parses review response into structured ReviewComment objects
5
+ * @param responseText The raw response from the AI backend
6
+ * @param roundNumber The current review round number
7
+ * @returns Array of parsed review comments
8
+ */
9
+ export function parseReviewResponse(responseText, roundNumber) {
10
+ const comments = [];
11
+ try {
12
+ // Pattern to match review comments with more flexible formatting
13
+ // Handles variations in whitespace, asterisk count, and casing that LLMs might produce
14
+ // More robust: \*{2,3} allows 2-3 asterisks, \s+ for flexible spacing, case-insensitive matching
15
+ const commentPattern = /\*{2,3}\s*\[\s*SEVERITY\s*:\s*(critical|important|suggestion|question)\s*\]\s*\*{2,3}\s+\*{2,3}\s*File\s*:\s*\*{2,3}\s*([^\n]+?)\s+\*{2,3}\s*Lines\s*:\s*\*{2,3}\s*([^\n]+?)\s+\*{2,3}\s*Issue\s*:\s*\*{2,3}\s*([^\n]+?)\s+\*{2,3}\s*Details\s*:\s*\*{2,3}\s*([\s\S]+?)\s+\*{2,3}\s*Recommendation\s*:\s*\*{2,3}\s*([\s\S]+?)(?=\n\s*\*{2,3}\s*\[\s*SEVERITY|---|$)/gi;
16
+ let match;
17
+ let matchCount = 0;
18
+ while ((match = commentPattern.exec(responseText)) !== null) {
19
+ matchCount++;
20
+ const [_, severity, file, lines, issue, details, recommendation] = match;
21
+ // Parse line range
22
+ let lineRange;
23
+ const linesStr = lines.trim();
24
+ if (linesStr !== 'N/A' && linesStr.toLowerCase() !== 'n/a') {
25
+ const lineMatch = linesStr.match(/(\d+)-(\d+)/);
26
+ if (lineMatch) {
27
+ lineRange = {
28
+ start: parseInt(lineMatch[1], 10),
29
+ end: parseInt(lineMatch[2], 10)
30
+ };
31
+ }
32
+ else {
33
+ // Single line number
34
+ const singleLine = parseInt(linesStr, 10);
35
+ if (!isNaN(singleLine)) {
36
+ lineRange = { start: singleLine, end: singleLine };
37
+ }
38
+ }
39
+ }
40
+ const comment = {
41
+ id: generateCommentId(),
42
+ filePattern: file.trim(),
43
+ lineRange,
44
+ severity: severity.trim().toLowerCase(),
45
+ comment: formatCommentText(issue.trim(), details.trim(), recommendation.trim()),
46
+ roundGenerated: roundNumber,
47
+ status: 'pending'
48
+ };
49
+ comments.push(comment);
50
+ }
51
+ Logger.debug(`Parsed ${matchCount} review comments from response`);
52
+ // If no structured comments found, try fallback parsing
53
+ if (comments.length === 0) {
54
+ Logger.debug('No structured comments found, attempting fallback parsing');
55
+ const fallbackComments = fallbackParse(responseText, roundNumber);
56
+ comments.push(...fallbackComments);
57
+ }
58
+ }
59
+ catch (error) {
60
+ Logger.error(`Error parsing review response: ${error}`);
61
+ // Return empty array on parse error - caller can handle
62
+ }
63
+ return comments;
64
+ }
65
+ /**
66
+ * Formats the comment text from parsed components
67
+ * @param issue Brief issue title
68
+ * @param details Detailed explanation
69
+ * @param recommendation Suggested fix
70
+ * @returns Formatted comment string
71
+ */
72
+ function formatCommentText(issue, details, recommendation) {
73
+ return `${issue}
74
+
75
+ ${details}
76
+
77
+ **Recommendation:** ${recommendation}`;
78
+ }
79
+ /**
80
+ * Generates a unique comment ID using cryptographically secure UUID
81
+ * @returns Comment ID string
82
+ */
83
+ export function generateCommentId() {
84
+ return `cmt-${randomUUID()}`;
85
+ }
86
+ /**
87
+ * Fallback parser for when structured format isn't followed
88
+ * Attempts to extract any review-like content
89
+ * @param responseText The raw response
90
+ * @param roundNumber The round number
91
+ * @returns Array of comments (may be empty or contain unstructured feedback)
92
+ */
93
+ function fallbackParse(responseText, roundNumber) {
94
+ const comments = [];
95
+ // Look for common issue indicators
96
+ const issuePatterns = [
97
+ /(?:issue|problem|concern|warning|error):\s*(.+?)(?:\n\n|$)/gi,
98
+ /(?:critical|important|security|vulnerability):\s*(.+?)(?:\n\n|$)/gi,
99
+ /(?:recommendation|suggestion|fix):\s*(.+?)(?:\n\n|$)/gi,
100
+ ];
101
+ let foundAny = false;
102
+ for (const pattern of issuePatterns) {
103
+ let match;
104
+ while ((match = pattern.exec(responseText)) !== null) {
105
+ foundAny = true;
106
+ const comment = {
107
+ id: generateCommentId(),
108
+ filePattern: 'Unknown',
109
+ severity: 'suggestion',
110
+ comment: match[1].trim(),
111
+ roundGenerated: roundNumber,
112
+ status: 'pending'
113
+ };
114
+ comments.push(comment);
115
+ }
116
+ }
117
+ // If still nothing found and response has substantial content, create a general comment
118
+ if (!foundAny && responseText.trim().length > 50) {
119
+ Logger.debug('Creating general unstructured comment from response');
120
+ comments.push({
121
+ id: generateCommentId(),
122
+ filePattern: 'General',
123
+ severity: 'question',
124
+ comment: responseText.trim(),
125
+ roundGenerated: roundNumber,
126
+ status: 'pending'
127
+ });
128
+ }
129
+ return comments;
130
+ }
131
+ /**
132
+ * Validates parsed comments for completeness
133
+ * @param comments Array of comments to validate
134
+ * @returns Array of valid comments
135
+ */
136
+ export function validateComments(comments) {
137
+ return comments.filter(comment => {
138
+ const isValid = comment.id &&
139
+ comment.filePattern &&
140
+ comment.severity &&
141
+ comment.comment &&
142
+ comment.comment.trim().length > 0;
143
+ if (!isValid) {
144
+ Logger.debug(`Filtered out invalid comment: ${JSON.stringify(comment)}`);
145
+ }
146
+ return isValid;
147
+ });
148
+ }
149
+ //# sourceMappingURL=reviewResponseParser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reviewResponseParser.js","sourceRoot":"","sources":["../../src/utils/reviewResponseParser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * @deprecated This file is deprecated. Session management has been migrated to the shared infrastructure.
3
+ *
4
+ * - For session operations, use: src/utils/reviewSessionManager.ts
5
+ * - For type definitions, use: src/utils/sessionSchemas.ts
6
+ *
7
+ * This file is kept only for backward compatibility and type exports (ReviewComment, ReviewRound).
8
+ * The actual session cache functions (save/load/create) have been moved to reviewSessionManager.ts
9
+ */
10
+ import { GitState } from './gitStateDetector.js';
11
+ export interface ReviewComment {
12
+ id: string;
13
+ filePattern: string;
14
+ lineRange?: {
15
+ start: number;
16
+ end: number;
17
+ };
18
+ severity: 'critical' | 'important' | 'suggestion' | 'question';
19
+ comment: string;
20
+ roundGenerated: number;
21
+ status: 'pending' | 'accepted' | 'rejected' | 'modified' | 'deferred';
22
+ resolution?: string;
23
+ }
24
+ export interface ReviewRound {
25
+ roundNumber: number;
26
+ timestamp: number;
27
+ filesReviewed: string[];
28
+ userPrompt: string;
29
+ response: string;
30
+ commentsGenerated: ReviewComment[];
31
+ gitState: GitState;
32
+ }
33
+ export interface CodeReviewSession {
34
+ sessionId: string;
35
+ createdAt: number;
36
+ lastAccessedAt: number;
37
+ gitState: GitState;
38
+ currentGitState: GitState;
39
+ rounds: ReviewRound[];
40
+ allComments: ReviewComment[];
41
+ filesTracked: string[];
42
+ focusFiles?: string[];
43
+ reviewScope?: 'full' | 'changes-only' | 'focused';
44
+ totalRounds: number;
45
+ sessionState: 'active' | 'paused' | 'completed';
46
+ }
47
+ /**
48
+ * Saves a review session to the cache
49
+ * @param session The session to save
50
+ */
51
+ export declare function saveReviewSession(session: CodeReviewSession): void;
52
+ /**
53
+ * Loads a review session from the cache
54
+ * @param sessionId The session ID to load
55
+ * @returns The session or null if not found/expired
56
+ */
57
+ export declare function loadReviewSession(sessionId: string): CodeReviewSession | null;
58
+ /**
59
+ * Lists all active review sessions
60
+ * @returns Array of active sessions
61
+ */
62
+ export declare function listActiveSessions(): CodeReviewSession[];
63
+ /**
64
+ * Creates a new review session
65
+ * @param sessionId The session ID
66
+ * @param gitState The initial git state
67
+ * @param focusFiles Optional files to focus on
68
+ * @returns New CodeReviewSession object
69
+ */
70
+ export declare function createNewSession(sessionId: string, gitState: GitState, focusFiles?: string[]): CodeReviewSession;
71
+ /**
72
+ * Gets cache statistics
73
+ * @returns Cache stats object
74
+ */
75
+ export declare function getReviewCacheStats(): {
76
+ size: number;
77
+ ttl: number;
78
+ maxSize: number;
79
+ cacheDir: string;
80
+ };
81
+ //# sourceMappingURL=reviewSessionCache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reviewSessionCache.d.ts","sourceRoot":"","sources":["../../src/utils/reviewSessionCache.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,QAAQ,EAAE,UAAU,GAAG,WAAW,GAAG,YAAY,GAAG,UAAU,CAAC;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,UAAU,GAAG,UAAU,CAAC;IACtE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,aAAa,EAAE,CAAC;IACnC,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,QAAQ,CAAC;IACnB,eAAe,EAAE,QAAQ,CAAC;IAC1B,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,WAAW,EAAE,aAAa,EAAE,CAAC;IAC7B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAAC;IAClD,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAC;CACjD;AAuBD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAqBlE;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CA6B7E;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,iBAAiB,EAAE,CA6BxD;AAiED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,QAAQ,EAClB,UAAU,CAAC,EAAE,MAAM,EAAE,GACpB,iBAAiB,CAgBnB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAeA"}
@@ -0,0 +1,220 @@
1
+ /**
2
+ * @deprecated This file is deprecated. Session management has been migrated to the shared infrastructure.
3
+ *
4
+ * - For session operations, use: src/utils/reviewSessionManager.ts
5
+ * - For type definitions, use: src/utils/sessionSchemas.ts
6
+ *
7
+ * This file is kept only for backward compatibility and type exports (ReviewComment, ReviewRound).
8
+ * The actual session cache functions (save/load/create) have been moved to reviewSessionManager.ts
9
+ */
10
+ import * as fs from 'fs';
11
+ import * as path from 'path';
12
+ import * as os from 'os';
13
+ import { Logger } from './logger.js';
14
+ // Use persistent storage in user's home directory instead of tmp for session persistence across reboots
15
+ const REVIEW_CACHE_DIR = path.join(os.homedir(), '.gemini-mcp', 'review-sessions');
16
+ const REVIEW_SESSION_TTL = 24 * 60 * 60 * 1000; // 24 hours (increased from 60 min for better persistence)
17
+ const MAX_REVIEW_SESSIONS = 20;
18
+ /**
19
+ * Ensures the review cache directory exists
20
+ */
21
+ function ensureCacheDir() {
22
+ if (!fs.existsSync(REVIEW_CACHE_DIR)) {
23
+ fs.mkdirSync(REVIEW_CACHE_DIR, { recursive: true });
24
+ Logger.debug(`Created review cache directory: ${REVIEW_CACHE_DIR}`);
25
+ }
26
+ }
27
+ /**
28
+ * Saves a review session to the cache
29
+ * @param session The session to save
30
+ */
31
+ export function saveReviewSession(session) {
32
+ ensureCacheDir();
33
+ cleanExpiredSessions();
34
+ const filePath = path.join(REVIEW_CACHE_DIR, `${session.sessionId}.json`);
35
+ const cacheEntry = {
36
+ session,
37
+ timestamp: Date.now(),
38
+ expiryTime: Date.now() + REVIEW_SESSION_TTL
39
+ };
40
+ try {
41
+ fs.writeFileSync(filePath, JSON.stringify(cacheEntry, null, 2));
42
+ Logger.debug(`Saved review session: ${session.sessionId} (${session.totalRounds} rounds)`);
43
+ }
44
+ catch (error) {
45
+ Logger.error(`Failed to save review session: ${error}`);
46
+ throw new Error(`Failed to save review session: ${error}`);
47
+ }
48
+ enforceSessionLimits();
49
+ }
50
+ /**
51
+ * Loads a review session from the cache
52
+ * @param sessionId The session ID to load
53
+ * @returns The session or null if not found/expired
54
+ */
55
+ export function loadReviewSession(sessionId) {
56
+ const filePath = path.join(REVIEW_CACHE_DIR, `${sessionId}.json`);
57
+ try {
58
+ if (!fs.existsSync(filePath)) {
59
+ Logger.debug(`Session not found: ${sessionId}`);
60
+ return null;
61
+ }
62
+ const fileContent = fs.readFileSync(filePath, 'utf-8');
63
+ const cacheEntry = JSON.parse(fileContent);
64
+ // Check expiry
65
+ if (Date.now() > cacheEntry.expiryTime) {
66
+ fs.unlinkSync(filePath);
67
+ Logger.debug(`Session expired and deleted: ${sessionId}`);
68
+ return null;
69
+ }
70
+ Logger.debug(`Loaded review session: ${sessionId} (${cacheEntry.session.totalRounds} rounds)`);
71
+ return cacheEntry.session;
72
+ }
73
+ catch (error) {
74
+ Logger.error(`Failed to load review session ${sessionId}: ${error}`);
75
+ // Clean up corrupted file
76
+ try {
77
+ fs.unlinkSync(filePath);
78
+ }
79
+ catch { }
80
+ return null;
81
+ }
82
+ }
83
+ /**
84
+ * Lists all active review sessions
85
+ * @returns Array of active sessions
86
+ */
87
+ export function listActiveSessions() {
88
+ ensureCacheDir();
89
+ const sessions = [];
90
+ try {
91
+ const files = fs.readdirSync(REVIEW_CACHE_DIR);
92
+ const now = Date.now();
93
+ for (const file of files) {
94
+ if (!file.endsWith('.json'))
95
+ continue;
96
+ const filePath = path.join(REVIEW_CACHE_DIR, file);
97
+ try {
98
+ const fileContent = fs.readFileSync(filePath, 'utf-8');
99
+ const cacheEntry = JSON.parse(fileContent);
100
+ // Skip expired sessions
101
+ if (now <= cacheEntry.expiryTime) {
102
+ sessions.push(cacheEntry.session);
103
+ }
104
+ }
105
+ catch (error) {
106
+ Logger.debug(`Error reading session file ${file}: ${error}`);
107
+ }
108
+ }
109
+ }
110
+ catch (error) {
111
+ Logger.error(`Failed to list active sessions: ${error}`);
112
+ }
113
+ return sessions;
114
+ }
115
+ /**
116
+ * Cleans up expired session files
117
+ */
118
+ function cleanExpiredSessions() {
119
+ try {
120
+ ensureCacheDir();
121
+ const files = fs.readdirSync(REVIEW_CACHE_DIR);
122
+ const now = Date.now();
123
+ let cleaned = 0;
124
+ for (const file of files) {
125
+ if (!file.endsWith('.json'))
126
+ continue;
127
+ const filePath = path.join(REVIEW_CACHE_DIR, file);
128
+ try {
129
+ const stats = fs.statSync(filePath);
130
+ if (now - stats.mtimeMs > REVIEW_SESSION_TTL) {
131
+ fs.unlinkSync(filePath);
132
+ cleaned++;
133
+ }
134
+ }
135
+ catch (error) {
136
+ Logger.debug(`Error checking session file ${file}: ${error}`);
137
+ }
138
+ }
139
+ if (cleaned > 0) {
140
+ Logger.debug(`Cleaned ${cleaned} expired review sessions`);
141
+ }
142
+ }
143
+ catch (error) {
144
+ Logger.debug(`Session cleanup error: ${error}`);
145
+ }
146
+ }
147
+ /**
148
+ * Enforces the maximum session limit using FIFO
149
+ */
150
+ function enforceSessionLimits() {
151
+ try {
152
+ const files = fs
153
+ .readdirSync(REVIEW_CACHE_DIR)
154
+ .filter(f => f.endsWith('.json'))
155
+ .map(f => ({
156
+ name: f,
157
+ path: path.join(REVIEW_CACHE_DIR, f),
158
+ mtime: fs.statSync(path.join(REVIEW_CACHE_DIR, f)).mtimeMs
159
+ }))
160
+ .sort((a, b) => a.mtime - b.mtime); // Oldest first
161
+ // Remove oldest files if over limit
162
+ if (files.length > MAX_REVIEW_SESSIONS) {
163
+ const toRemove = files.slice(0, files.length - MAX_REVIEW_SESSIONS);
164
+ for (const file of toRemove) {
165
+ try {
166
+ fs.unlinkSync(file.path);
167
+ }
168
+ catch { }
169
+ }
170
+ Logger.debug(`Removed ${toRemove.length} old review sessions to enforce limit`);
171
+ }
172
+ }
173
+ catch (error) {
174
+ Logger.debug(`Error enforcing session limits: ${error}`);
175
+ }
176
+ }
177
+ /**
178
+ * Creates a new review session
179
+ * @param sessionId The session ID
180
+ * @param gitState The initial git state
181
+ * @param focusFiles Optional files to focus on
182
+ * @returns New CodeReviewSession object
183
+ */
184
+ export function createNewSession(sessionId, gitState, focusFiles) {
185
+ const now = Date.now();
186
+ return {
187
+ sessionId,
188
+ createdAt: now,
189
+ lastAccessedAt: now,
190
+ gitState,
191
+ currentGitState: gitState,
192
+ rounds: [],
193
+ allComments: [],
194
+ filesTracked: [],
195
+ focusFiles,
196
+ reviewScope: focusFiles ? 'focused' : 'full',
197
+ totalRounds: 0,
198
+ sessionState: 'active'
199
+ };
200
+ }
201
+ /**
202
+ * Gets cache statistics
203
+ * @returns Cache stats object
204
+ */
205
+ export function getReviewCacheStats() {
206
+ ensureCacheDir();
207
+ let size = 0;
208
+ try {
209
+ const files = fs.readdirSync(REVIEW_CACHE_DIR);
210
+ size = files.filter(f => f.endsWith('.json')).length;
211
+ }
212
+ catch { }
213
+ return {
214
+ size,
215
+ ttl: REVIEW_SESSION_TTL,
216
+ maxSize: MAX_REVIEW_SESSIONS,
217
+ cacheDir: REVIEW_CACHE_DIR
218
+ };
219
+ }
220
+ //# sourceMappingURL=reviewSessionCache.js.map