@maxanatsko/gemini-mcp-tool 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/LICENSE +25 -0
  2. package/README.md +230 -0
  3. package/dist/constants.d.ts +153 -0
  4. package/dist/constants.d.ts.map +1 -0
  5. package/dist/constants.js +150 -0
  6. package/dist/constants.js.map +1 -0
  7. package/dist/index.d.ts +3 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +188 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/tools/ask-gemini.tool.d.ts +3 -0
  12. package/dist/tools/ask-gemini.tool.d.ts.map +1 -0
  13. package/dist/tools/ask-gemini.tool.js +74 -0
  14. package/dist/tools/ask-gemini.tool.js.map +1 -0
  15. package/dist/tools/brainstorm.tool.d.ts +3 -0
  16. package/dist/tools/brainstorm.tool.d.ts.map +1 -0
  17. package/dist/tools/brainstorm.tool.js +202 -0
  18. package/dist/tools/brainstorm.tool.js.map +1 -0
  19. package/dist/tools/fetch-chunk.tool.d.ts +3 -0
  20. package/dist/tools/fetch-chunk.tool.d.ts.map +1 -0
  21. package/dist/tools/fetch-chunk.tool.js +62 -0
  22. package/dist/tools/fetch-chunk.tool.js.map +1 -0
  23. package/dist/tools/index.d.ts +2 -0
  24. package/dist/tools/index.d.ts.map +1 -0
  25. package/dist/tools/index.js +11 -0
  26. package/dist/tools/index.js.map +1 -0
  27. package/dist/tools/registry.d.ts +25 -0
  28. package/dist/tools/registry.d.ts.map +1 -0
  29. package/dist/tools/registry.js +80 -0
  30. package/dist/tools/registry.js.map +1 -0
  31. package/dist/tools/review-code.tool.d.ts +3 -0
  32. package/dist/tools/review-code.tool.d.ts.map +1 -0
  33. package/dist/tools/review-code.tool.js +186 -0
  34. package/dist/tools/review-code.tool.js.map +1 -0
  35. package/dist/tools/simple-tools.d.ts +4 -0
  36. package/dist/tools/simple-tools.d.ts.map +1 -0
  37. package/dist/tools/simple-tools.js +32 -0
  38. package/dist/tools/simple-tools.js.map +1 -0
  39. package/dist/tools/test-tool.example.d.ts +13 -0
  40. package/dist/tools/test-tool.example.d.ts.map +1 -0
  41. package/dist/tools/test-tool.example.js +32 -0
  42. package/dist/tools/test-tool.example.js.map +1 -0
  43. package/dist/tools/timeout-test.tool.d.ts +3 -0
  44. package/dist/tools/timeout-test.tool.d.ts.map +1 -0
  45. package/dist/tools/timeout-test.tool.js +32 -0
  46. package/dist/tools/timeout-test.tool.js.map +1 -0
  47. package/dist/utils/askGeminiSessionManager.d.ts +57 -0
  48. package/dist/utils/askGeminiSessionManager.d.ts.map +1 -0
  49. package/dist/utils/askGeminiSessionManager.js +110 -0
  50. package/dist/utils/askGeminiSessionManager.js.map +1 -0
  51. package/dist/utils/brainstormSessionManager.d.ts +67 -0
  52. package/dist/utils/brainstormSessionManager.d.ts.map +1 -0
  53. package/dist/utils/brainstormSessionManager.js +165 -0
  54. package/dist/utils/brainstormSessionManager.js.map +1 -0
  55. package/dist/utils/changeModeChunker.d.ts +11 -0
  56. package/dist/utils/changeModeChunker.d.ts.map +1 -0
  57. package/dist/utils/changeModeChunker.js +89 -0
  58. package/dist/utils/changeModeChunker.js.map +1 -0
  59. package/dist/utils/changeModeParser.d.ts +15 -0
  60. package/dist/utils/changeModeParser.d.ts.map +1 -0
  61. package/dist/utils/changeModeParser.js +67 -0
  62. package/dist/utils/changeModeParser.js.map +1 -0
  63. package/dist/utils/changeModeTranslator.d.ts +8 -0
  64. package/dist/utils/changeModeTranslator.d.ts.map +1 -0
  65. package/dist/utils/changeModeTranslator.js +70 -0
  66. package/dist/utils/changeModeTranslator.js.map +1 -0
  67. package/dist/utils/chunkCache.d.ts +22 -0
  68. package/dist/utils/chunkCache.d.ts.map +1 -0
  69. package/dist/utils/chunkCache.js +161 -0
  70. package/dist/utils/chunkCache.js.map +1 -0
  71. package/dist/utils/commandExecutor.d.ts +2 -0
  72. package/dist/utils/commandExecutor.d.ts.map +1 -0
  73. package/dist/utils/commandExecutor.js +74 -0
  74. package/dist/utils/commandExecutor.js.map +1 -0
  75. package/dist/utils/geminiExecutor.d.ts +3 -0
  76. package/dist/utils/geminiExecutor.d.ts.map +1 -0
  77. package/dist/utils/geminiExecutor.js +170 -0
  78. package/dist/utils/geminiExecutor.js.map +1 -0
  79. package/dist/utils/gitStateDetector.d.ts +31 -0
  80. package/dist/utils/gitStateDetector.d.ts.map +1 -0
  81. package/dist/utils/gitStateDetector.js +67 -0
  82. package/dist/utils/gitStateDetector.js.map +1 -0
  83. package/dist/utils/logger.d.ts +13 -0
  84. package/dist/utils/logger.d.ts.map +1 -0
  85. package/dist/utils/logger.js +42 -0
  86. package/dist/utils/logger.js.map +1 -0
  87. package/dist/utils/reviewFormatter.d.ts +35 -0
  88. package/dist/utils/reviewFormatter.d.ts.map +1 -0
  89. package/dist/utils/reviewFormatter.js +198 -0
  90. package/dist/utils/reviewFormatter.js.map +1 -0
  91. package/dist/utils/reviewPromptBuilder.d.ts +35 -0
  92. package/dist/utils/reviewPromptBuilder.d.ts.map +1 -0
  93. package/dist/utils/reviewPromptBuilder.js +146 -0
  94. package/dist/utils/reviewPromptBuilder.js.map +1 -0
  95. package/dist/utils/reviewResponseParser.d.ts +20 -0
  96. package/dist/utils/reviewResponseParser.d.ts.map +1 -0
  97. package/dist/utils/reviewResponseParser.js +149 -0
  98. package/dist/utils/reviewResponseParser.js.map +1 -0
  99. package/dist/utils/reviewSessionCache.d.ts +81 -0
  100. package/dist/utils/reviewSessionCache.d.ts.map +1 -0
  101. package/dist/utils/reviewSessionCache.js +220 -0
  102. package/dist/utils/reviewSessionCache.js.map +1 -0
  103. package/dist/utils/reviewSessionManager.d.ts +52 -0
  104. package/dist/utils/reviewSessionManager.d.ts.map +1 -0
  105. package/dist/utils/reviewSessionManager.js +65 -0
  106. package/dist/utils/reviewSessionManager.js.map +1 -0
  107. package/dist/utils/sessionManager.d.ts +94 -0
  108. package/dist/utils/sessionManager.d.ts.map +1 -0
  109. package/dist/utils/sessionManager.js +374 -0
  110. package/dist/utils/sessionManager.js.map +1 -0
  111. package/dist/utils/sessionSchemas.d.ts +126 -0
  112. package/dist/utils/sessionSchemas.d.ts.map +1 -0
  113. package/dist/utils/sessionSchemas.js +2 -0
  114. package/dist/utils/sessionSchemas.js.map +1 -0
  115. package/dist/utils/timeoutManager.d.ts +2 -0
  116. package/dist/utils/timeoutManager.d.ts.map +1 -0
  117. package/dist/utils/timeoutManager.js +2 -0
  118. package/dist/utils/timeoutManager.js.map +1 -0
  119. package/package.json +71 -0
@@ -0,0 +1,161 @@
1
+ import { createHash } from 'crypto';
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
4
+ import * as os from 'os';
5
+ import { Logger } from './logger.js';
6
+ const CACHE_DIR = path.join(os.tmpdir(), 'gemini-mcp-chunks');
7
+ const CACHE_TTL = 10 * 60 * 1000;
8
+ const MAX_CACHE_FILES = 50;
9
+ function ensureCacheDir() {
10
+ if (!fs.existsSync(CACHE_DIR)) {
11
+ fs.mkdirSync(CACHE_DIR, { recursive: true });
12
+ }
13
+ }
14
+ /**
15
+ * Caches chunks from a changeMode response
16
+ * @param prompt The original prompt (used for hash generation)
17
+ * @param chunks The parsed and chunked edits
18
+ * @returns A short cache key for retrieval
19
+ */
20
+ export function cacheChunks(prompt, chunks) {
21
+ ensureCacheDir();
22
+ cleanExpiredFiles(); // Cleanup on each write
23
+ // Generate deterministic cache key from prompt
24
+ const promptHash = createHash('sha256').update(prompt).digest('hex');
25
+ const cacheKey = promptHash.slice(0, 8);
26
+ const filePath = path.join(CACHE_DIR, `${cacheKey}.json`);
27
+ // Store with metadata
28
+ const cacheData = {
29
+ chunks,
30
+ timestamp: Date.now(),
31
+ promptHash
32
+ };
33
+ try {
34
+ fs.writeFileSync(filePath, JSON.stringify(cacheData));
35
+ Logger.debug(`Cached ${chunks.length} chunks to file: ${cacheKey}.json`);
36
+ }
37
+ catch (error) {
38
+ Logger.error(`Failed to cache chunks: ${error}`);
39
+ }
40
+ enforceFileLimits();
41
+ return cacheKey;
42
+ }
43
+ /**
44
+ * Retrieves cached chunks if they exist and haven't expired
45
+ * @param cacheKey The cache key returned from cacheChunks
46
+ * @returns The cached chunks or null if expired/not found
47
+ */
48
+ export function getChunks(cacheKey) {
49
+ const filePath = path.join(CACHE_DIR, `${cacheKey}.json`);
50
+ try {
51
+ if (!fs.existsSync(filePath)) {
52
+ return null;
53
+ }
54
+ const fileContent = fs.readFileSync(filePath, 'utf-8');
55
+ const data = JSON.parse(fileContent);
56
+ if (Date.now() - data.timestamp > CACHE_TTL) {
57
+ fs.unlinkSync(filePath);
58
+ Logger.debug(`Cache expired for ${cacheKey}, deleted file`);
59
+ return null;
60
+ }
61
+ Logger.debug(`Cache hit for ${cacheKey}, returning ${data.chunks.length} chunks`);
62
+ return data.chunks;
63
+ }
64
+ catch (error) {
65
+ Logger.debug(`Cache read error for ${cacheKey}: ${error}`);
66
+ try {
67
+ fs.unlinkSync(filePath); // Clean up bad file
68
+ }
69
+ catch { }
70
+ return null;
71
+ }
72
+ }
73
+ function cleanExpiredFiles() {
74
+ try {
75
+ ensureCacheDir();
76
+ const files = fs.readdirSync(CACHE_DIR);
77
+ const now = Date.now();
78
+ let cleaned = 0;
79
+ for (const file of files) {
80
+ if (!file.endsWith('.json'))
81
+ continue;
82
+ const filePath = path.join(CACHE_DIR, file);
83
+ try {
84
+ const stats = fs.statSync(filePath);
85
+ if (now - stats.mtimeMs > CACHE_TTL) {
86
+ fs.unlinkSync(filePath);
87
+ cleaned++;
88
+ }
89
+ }
90
+ catch (error) {
91
+ // Individual file error - continue with others
92
+ Logger.debug(`Error checking file ${file}: ${error}`);
93
+ }
94
+ }
95
+ if (cleaned > 0) {
96
+ Logger.debug(`Cleaned ${cleaned} expired cache files`);
97
+ }
98
+ }
99
+ catch (error) {
100
+ // Non-critical, just log
101
+ Logger.debug(`Cache cleanup error: ${error}`);
102
+ }
103
+ }
104
+ // maximum file count limit (FIFO) --> LRU?
105
+ function enforceFileLimits() {
106
+ try {
107
+ const files = fs.readdirSync(CACHE_DIR)
108
+ .filter(f => f.endsWith('.json'))
109
+ .map(f => ({
110
+ name: f,
111
+ path: path.join(CACHE_DIR, f),
112
+ mtime: fs.statSync(path.join(CACHE_DIR, f)).mtimeMs
113
+ }))
114
+ .sort((a, b) => a.mtime - b.mtime); // Oldest first
115
+ // Remove oldest files if over limit
116
+ if (files.length > MAX_CACHE_FILES) {
117
+ const toRemove = files.slice(0, files.length - MAX_CACHE_FILES);
118
+ for (const file of toRemove) {
119
+ try {
120
+ fs.unlinkSync(file.path);
121
+ }
122
+ catch { }
123
+ }
124
+ Logger.debug(`Removed ${toRemove.length} old cache files to enforce limit`);
125
+ }
126
+ }
127
+ catch (error) {
128
+ Logger.debug(`Error enforcing file limits: ${error}`);
129
+ }
130
+ }
131
+ export function getCacheStats() {
132
+ ensureCacheDir();
133
+ let size = 0;
134
+ try {
135
+ const files = fs.readdirSync(CACHE_DIR);
136
+ size = files.filter(f => f.endsWith('.json')).length;
137
+ }
138
+ catch { }
139
+ return {
140
+ size,
141
+ ttl: CACHE_TTL,
142
+ maxSize: MAX_CACHE_FILES,
143
+ cacheDir: CACHE_DIR
144
+ };
145
+ }
146
+ export function clearCache() {
147
+ try {
148
+ ensureCacheDir();
149
+ const files = fs.readdirSync(CACHE_DIR);
150
+ for (const file of files) {
151
+ if (file.endsWith('.json')) {
152
+ fs.unlinkSync(path.join(CACHE_DIR, file));
153
+ }
154
+ }
155
+ Logger.debug('Cache emptied');
156
+ }
157
+ catch (error) {
158
+ Logger.error(`Failed to empty cache: ${error}`);
159
+ }
160
+ }
161
+ //# sourceMappingURL=chunkCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunkCache.js","sourceRoot":"","sources":["../../src/utils/chunkCache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function executeCommand(command: string, args: string[], onProgress?: (newOutput: string) => void): Promise<string>;
2
+ //# sourceMappingURL=commandExecutor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commandExecutor.d.ts","sourceRoot":"","sources":["../../src/utils/commandExecutor.ts"],"names":[],"mappings":"AAGA,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,GACvC,OAAO,CAAC,MAAM,CAAC,CA6EjB"}
@@ -0,0 +1,74 @@
1
+ import { spawn } from "child_process";
2
+ import { Logger } from "./logger.js";
3
+ export async function executeCommand(command, args, onProgress) {
4
+ return new Promise((resolve, reject) => {
5
+ const startTime = Date.now();
6
+ Logger.commandExecution(command, args, startTime);
7
+ const childProcess = spawn(command, args, {
8
+ env: process.env,
9
+ shell: false,
10
+ stdio: ["ignore", "pipe", "pipe"],
11
+ });
12
+ let stdout = "";
13
+ let stderr = "";
14
+ let isResolved = false;
15
+ let lastReportedLength = 0;
16
+ childProcess.stdout.on("data", (data) => {
17
+ stdout += data.toString();
18
+ // Report new content if callback provided
19
+ if (onProgress && stdout.length > lastReportedLength) {
20
+ const newContent = stdout.substring(lastReportedLength);
21
+ lastReportedLength = stdout.length;
22
+ onProgress(newContent);
23
+ }
24
+ });
25
+ // CLI level errors
26
+ childProcess.stderr.on("data", (data) => {
27
+ stderr += data.toString();
28
+ // find RESOURCE_EXHAUSTED when gemini-2.5-pro quota is exceeded
29
+ if (stderr.includes("RESOURCE_EXHAUSTED")) {
30
+ const modelMatch = stderr.match(/Quota exceeded for quota metric '([^']+)'/);
31
+ const statusMatch = stderr.match(/status["\s]*[:=]\s*(\d+)/);
32
+ const reasonMatch = stderr.match(/"reason":\s*"([^"]+)"/);
33
+ const model = modelMatch ? modelMatch[1] : "Unknown Model";
34
+ const status = statusMatch ? statusMatch[1] : "429";
35
+ const reason = reasonMatch ? reasonMatch[1] : "rateLimitExceeded";
36
+ const errorJson = {
37
+ error: {
38
+ code: parseInt(status),
39
+ message: `GMCPT: --> Quota exceeded for ${model}`,
40
+ details: {
41
+ model: model,
42
+ reason: reason,
43
+ statusText: "Too Many Requests -- > try using gemini-2.5-flash by asking",
44
+ }
45
+ }
46
+ };
47
+ Logger.error(`Gemini Quota Error: ${JSON.stringify(errorJson, null, 2)}`);
48
+ }
49
+ });
50
+ childProcess.on("error", (error) => {
51
+ if (!isResolved) {
52
+ isResolved = true;
53
+ Logger.error(`Process error:`, error);
54
+ reject(new Error(`Failed to spawn command: ${error.message}`));
55
+ }
56
+ });
57
+ childProcess.on("close", (code) => {
58
+ if (!isResolved) {
59
+ isResolved = true;
60
+ if (code === 0) {
61
+ Logger.commandComplete(startTime, code, stdout.length);
62
+ resolve(stdout.trim());
63
+ }
64
+ else {
65
+ Logger.commandComplete(startTime, code);
66
+ Logger.error(`Failed with exit code ${code}`);
67
+ const errorMessage = stderr.trim() || "Unknown error";
68
+ reject(new Error(`Command failed with exit code ${code}: ${errorMessage}`));
69
+ }
70
+ }
71
+ });
72
+ });
73
+ }
74
+ //# sourceMappingURL=commandExecutor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commandExecutor.js","sourceRoot":"","sources":["../../src/utils/commandExecutor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAe,EACf,IAAc,EACd,UAAwC;IAExC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QAElD,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;YACxC,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;SAClC,CAAC,CAAC;QAEH,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,UAAU,GAAG,KAAK,CAAC;QACvB,IAAI,kBAAkB,GAAG,CAAC,CAAC;QAE3B,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YACtC,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAE1B,0CAA0C;YAC1C,IAAI,UAAU,IAAI,MAAM,CAAC,MAAM,GAAG,kBAAkB,EAAE,CAAC;gBACrD,MAAM,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;gBACxD,kBAAkB,GAAG,MAAM,CAAC,MAAM,CAAC;gBACnC,UAAU,CAAC,UAAU,CAAC,CAAC;YACzB,CAAC;QACH,CAAC,CAAC,CAAC;QAGH,mBAAmB;QACnB,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YACtC,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC1B,gEAAgE;YAChE,IAAI,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,CAAC;gBAC1C,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;gBAC7E,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;gBAC7D,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;gBAC1D,MAAM,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC;gBAC3D,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;gBACpD,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC;gBAClE,MAAM,SAAS,GAAG;oBAChB,KAAK,EAAE;wBACL,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC;wBACtB,OAAO,EAAE,iCAAiC,KAAK,EAAE;wBACjD,OAAO,EAAE;4BACP,KAAK,EAAE,KAAK;4BACZ,MAAM,EAAE,MAAM;4BACd,UAAU,EAAE,6DAA6D;yBAC1E;qBACF;iBACF,CAAC;gBACF,MAAM,CAAC,KAAK,CAAC,uBAAuB,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;YAC5E,CAAC;QACH,CAAC,CAAC,CAAC;QACH,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACjC,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,UAAU,GAAG,IAAI,CAAC;gBAClB,MAAM,CAAC,KAAK,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;gBACtC,MAAM,CAAC,IAAI,KAAK,CAAC,4BAA4B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YACjE,CAAC;QACH,CAAC,CAAC,CAAC;QACH,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAChC,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,UAAU,GAAG,IAAI,CAAC;gBAClB,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;oBACf,MAAM,CAAC,eAAe,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;oBACvD,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;gBACzB,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,eAAe,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;oBACxC,MAAM,CAAC,KAAK,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC;oBAC9C,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,EAAE,IAAI,eAAe,CAAC;oBACtD,MAAM,CACJ,IAAI,KAAK,CAAC,iCAAiC,IAAI,KAAK,YAAY,EAAE,CAAC,CACpE,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function executeGeminiCLI(prompt: string, model?: string, sandbox?: boolean, changeMode?: boolean, onProgress?: (newOutput: string) => void): Promise<string>;
2
+ export declare function processChangeModeOutput(rawResult: string, chunkIndex?: number, chunkCacheKey?: string, prompt?: string): Promise<string>;
3
+ //# sourceMappingURL=geminiExecutor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geminiExecutor.d.ts","sourceRoot":"","sources":["../../src/utils/geminiExecutor.ts"],"names":[],"mappings":"AAcA,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,OAAO,EACjB,UAAU,CAAC,EAAE,OAAO,EACpB,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,GACvC,OAAO,CAAC,MAAM,CAAC,CAgHjB;AAED,wBAAsB,uBAAuB,CAC3C,SAAS,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,MAAM,EACnB,aAAa,CAAC,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,CA8DjB"}
@@ -0,0 +1,170 @@
1
+ import { executeCommand } from './commandExecutor.js';
2
+ import { Logger } from './logger.js';
3
+ import { ERROR_MESSAGES, STATUS_MESSAGES, MODELS, CLI } from '../constants.js';
4
+ import { parseChangeModeOutput, validateChangeModeEdits } from './changeModeParser.js';
5
+ import { formatChangeModeResponse, summarizeChangeModeEdits } from './changeModeTranslator.js';
6
+ import { chunkChangeModeEdits } from './changeModeChunker.js';
7
+ import { cacheChunks, getChunks } from './chunkCache.js';
8
+ export async function executeGeminiCLI(prompt, model, sandbox, changeMode, onProgress) {
9
+ let prompt_processed = prompt;
10
+ if (changeMode) {
11
+ prompt_processed = prompt.replace(/file:(\S+)/g, '@$1');
12
+ const changeModeInstructions = `
13
+ [CHANGEMODE INSTRUCTIONS]
14
+ You are generating code modifications that will be processed by an automated system. The output format is critical because it enables programmatic application of changes without human intervention.
15
+
16
+ INSTRUCTIONS:
17
+ 1. Analyze each provided file thoroughly
18
+ 2. Identify locations requiring changes based on the user request
19
+ 3. For each change, output in the exact format specified
20
+ 4. The OLD section must be EXACTLY what appears in the file (copy-paste exact match)
21
+ 5. Provide complete, directly replacing code blocks
22
+ 6. Verify line numbers are accurate
23
+
24
+ CRITICAL REQUIREMENTS:
25
+ 1. Output edits in the EXACT format specified below - no deviations
26
+ 2. The OLD string MUST be findable with Ctrl+F - it must be a unique, exact match
27
+ 3. Include enough surrounding lines to make the OLD string unique
28
+ 4. If a string appears multiple times (like </div>), include enough context lines above and below to make it unique
29
+ 5. Copy the OLD content EXACTLY as it appears - including all whitespace, indentation, line breaks
30
+ 6. Never use partial lines - always include complete lines from start to finish
31
+
32
+ OUTPUT FORMAT (follow exactly):
33
+ **FILE: [filename]:[line_number]**
34
+ \`\`\`
35
+ OLD:
36
+ [exact code to be replaced - must match file content precisely]
37
+ NEW:
38
+ [new code to insert - complete and functional]
39
+ \`\`\`
40
+
41
+ EXAMPLE 1 - Simple unique match:
42
+ **FILE: src/utils/helper.js:100**
43
+ \`\`\`
44
+ OLD:
45
+ function getMessage() {
46
+ return "Hello World";
47
+ }
48
+ NEW:
49
+ function getMessage() {
50
+ return "Hello Universe!";
51
+ }
52
+ \`\`\`
53
+
54
+ EXAMPLE 2 - Common tag needing context:
55
+ **FILE: index.html:245**
56
+ \`\`\`
57
+ OLD:
58
+ </div>
59
+ </div>
60
+ </section>
61
+ NEW:
62
+ </div>
63
+ </footer>
64
+ </section>
65
+ \`\`\`
66
+
67
+ IMPORTANT: The OLD section must be an EXACT copy from the file that can be found with Ctrl+F!
68
+
69
+ USER REQUEST:
70
+ ${prompt_processed}
71
+ `;
72
+ prompt_processed = changeModeInstructions;
73
+ }
74
+ const args = [];
75
+ if (model) {
76
+ args.push(CLI.FLAGS.MODEL, model);
77
+ }
78
+ if (sandbox) {
79
+ args.push(CLI.FLAGS.SANDBOX);
80
+ }
81
+ // Ensure @ symbols work cross-platform by wrapping in quotes if needed
82
+ const finalPrompt = prompt_processed.includes('@') && !prompt_processed.startsWith('"')
83
+ ? `"${prompt_processed}"`
84
+ : prompt_processed;
85
+ args.push(CLI.FLAGS.PROMPT, finalPrompt);
86
+ try {
87
+ return await executeCommand(CLI.COMMANDS.GEMINI, args, onProgress);
88
+ }
89
+ catch (error) {
90
+ const errorMessage = error instanceof Error ? error.message : String(error);
91
+ if (errorMessage.includes(ERROR_MESSAGES.QUOTA_EXCEEDED) && model !== MODELS.FLASH) {
92
+ Logger.warn(`${ERROR_MESSAGES.QUOTA_EXCEEDED}. Falling back to ${MODELS.FLASH}.`);
93
+ await sendStatusMessage(STATUS_MESSAGES.FLASH_RETRY);
94
+ const fallbackArgs = [];
95
+ fallbackArgs.push(CLI.FLAGS.MODEL, MODELS.FLASH);
96
+ if (sandbox) {
97
+ fallbackArgs.push(CLI.FLAGS.SANDBOX);
98
+ }
99
+ // Same @ symbol handling for fallback
100
+ const fallbackPrompt = prompt_processed.includes('@') && !prompt_processed.startsWith('"')
101
+ ? `"${prompt_processed}"`
102
+ : prompt_processed;
103
+ fallbackArgs.push(CLI.FLAGS.PROMPT, fallbackPrompt);
104
+ try {
105
+ const result = await executeCommand(CLI.COMMANDS.GEMINI, fallbackArgs, onProgress);
106
+ Logger.warn(`Successfully executed with ${MODELS.FLASH} fallback.`);
107
+ await sendStatusMessage(STATUS_MESSAGES.FLASH_SUCCESS);
108
+ return result;
109
+ }
110
+ catch (fallbackError) {
111
+ const fallbackErrorMessage = fallbackError instanceof Error ? fallbackError.message : String(fallbackError);
112
+ throw new Error(`${MODELS.PRO} quota exceeded, ${MODELS.FLASH} fallback also failed: ${fallbackErrorMessage}`);
113
+ }
114
+ }
115
+ else {
116
+ throw error;
117
+ }
118
+ }
119
+ }
120
+ export async function processChangeModeOutput(rawResult, chunkIndex, chunkCacheKey, prompt) {
121
+ // Check for cached chunks first
122
+ if (chunkIndex && chunkCacheKey) {
123
+ const cachedChunks = getChunks(chunkCacheKey);
124
+ if (cachedChunks && chunkIndex > 0 && chunkIndex <= cachedChunks.length) {
125
+ Logger.debug(`Using cached chunk ${chunkIndex} of ${cachedChunks.length}`);
126
+ const chunk = cachedChunks[chunkIndex - 1];
127
+ let result = formatChangeModeResponse(chunk.edits, { current: chunkIndex, total: cachedChunks.length, cacheKey: chunkCacheKey });
128
+ // Add summary for first chunk only
129
+ if (chunkIndex === 1 && chunk.edits.length > 5) {
130
+ const allEdits = cachedChunks.flatMap(c => c.edits);
131
+ result = summarizeChangeModeEdits(allEdits) + '\n\n' + result;
132
+ }
133
+ return result;
134
+ }
135
+ Logger.debug(`Cache miss or invalid chunk index, processing new result`);
136
+ }
137
+ // Parse OLD/NEW format
138
+ const edits = parseChangeModeOutput(rawResult);
139
+ if (edits.length === 0) {
140
+ return `No edits found in Gemini's response. Please ensure Gemini uses the OLD/NEW format. \n\n+ ${rawResult}`;
141
+ }
142
+ // Validate edits
143
+ const validation = validateChangeModeEdits(edits);
144
+ if (!validation.valid) {
145
+ return `Edit validation failed:\n${validation.errors.join('\n')}`;
146
+ }
147
+ const chunks = chunkChangeModeEdits(edits);
148
+ // Cache if multiple chunks and we have the original prompt
149
+ let cacheKey;
150
+ if (chunks.length > 1 && prompt) {
151
+ cacheKey = cacheChunks(prompt, chunks);
152
+ Logger.debug(`Cached ${chunks.length} chunks with key: ${cacheKey}`);
153
+ }
154
+ // Return requested chunk or first chunk
155
+ const returnChunkIndex = (chunkIndex && chunkIndex > 0 && chunkIndex <= chunks.length) ? chunkIndex : 1;
156
+ const returnChunk = chunks[returnChunkIndex - 1];
157
+ // Format the response
158
+ let result = formatChangeModeResponse(returnChunk.edits, chunks.length > 1 ? { current: returnChunkIndex, total: chunks.length, cacheKey } : undefined);
159
+ // Add summary if helpful (only for first chunk)
160
+ if (returnChunkIndex === 1 && edits.length > 5) {
161
+ result = summarizeChangeModeEdits(edits, chunks.length > 1) + '\n\n' + result;
162
+ }
163
+ Logger.debug(`ChangeMode: Parsed ${edits.length} edits, ${chunks.length} chunks, returning chunk ${returnChunkIndex}`);
164
+ return result;
165
+ }
166
+ // Placeholder
167
+ async function sendStatusMessage(message) {
168
+ Logger.debug(`Status: ${message}`);
169
+ }
170
+ //# sourceMappingURL=geminiExecutor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geminiExecutor.js","sourceRoot":"","sources":["../../src/utils/geminiExecutor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ export interface GitState {
2
+ branch: string;
3
+ commitHash: string;
4
+ workingTreeClean: boolean;
5
+ hasUncommittedChanges: boolean;
6
+ timestamp: number;
7
+ }
8
+ /**
9
+ * Gets the current git state of the repository
10
+ * Executes git commands in parallel for better performance
11
+ * @returns GitState object with branch, commit, and status info
12
+ */
13
+ export declare function getCurrentGitState(): Promise<GitState>;
14
+ /**
15
+ * Generates a session ID from git state
16
+ * Format: review-{branch}-{shortHash}
17
+ * @param gitState The git state to generate ID from
18
+ * @returns Session ID string
19
+ */
20
+ export declare function generateSessionId(gitState: GitState): string;
21
+ /**
22
+ * Checks if a session can continue based on git state comparison
23
+ * @param currentGitState Current git state
24
+ * @param sessionGitState Git state from existing session
25
+ * @returns Object indicating if continuation is allowed and reason if not
26
+ */
27
+ export declare function detectSessionContinuation(currentGitState: GitState, sessionGitState: GitState): {
28
+ canContinue: boolean;
29
+ reason?: string;
30
+ };
31
+ //# sourceMappingURL=gitStateDetector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitStateDetector.d.ts","sourceRoot":"","sources":["../../src/utils/gitStateDetector.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,QAAQ,CAAC,CAsB5D;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAK5D;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,eAAe,EAAE,QAAQ,EACzB,eAAe,EAAE,QAAQ,GACxB;IAAE,WAAW,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAsB3C"}
@@ -0,0 +1,67 @@
1
+ import { executeCommand } from './commandExecutor.js';
2
+ import { Logger } from './logger.js';
3
+ /**
4
+ * Gets the current git state of the repository
5
+ * Executes git commands in parallel for better performance
6
+ * @returns GitState object with branch, commit, and status info
7
+ */
8
+ export async function getCurrentGitState() {
9
+ try {
10
+ // Execute git commands in parallel for better performance
11
+ const [branch, commitHash, statusOutput] = await Promise.all([
12
+ executeCommand('git', ['rev-parse', '--abbrev-ref', 'HEAD']),
13
+ executeCommand('git', ['rev-parse', 'HEAD']),
14
+ executeCommand('git', ['status', '--porcelain'])
15
+ ]);
16
+ const workingTreeClean = statusOutput.trim() === '';
17
+ return {
18
+ branch: branch.trim(),
19
+ commitHash: commitHash.trim(),
20
+ workingTreeClean,
21
+ hasUncommittedChanges: !workingTreeClean,
22
+ timestamp: Date.now()
23
+ };
24
+ }
25
+ catch (error) {
26
+ Logger.error(`Failed to get git state: ${error}`);
27
+ throw new Error(`Git state detection failed. Ensure you're in a git repository: ${error}`);
28
+ }
29
+ }
30
+ /**
31
+ * Generates a session ID from git state
32
+ * Format: review-{branch}-{shortHash}
33
+ * @param gitState The git state to generate ID from
34
+ * @returns Session ID string
35
+ */
36
+ export function generateSessionId(gitState) {
37
+ const shortHash = gitState.commitHash.slice(0, 8);
38
+ // Sanitize branch name for filesystem safety
39
+ const safeBranch = gitState.branch.replace(/[^a-zA-Z0-9-_]/g, '-');
40
+ return `review-${safeBranch}-${shortHash}`;
41
+ }
42
+ /**
43
+ * Checks if a session can continue based on git state comparison
44
+ * @param currentGitState Current git state
45
+ * @param sessionGitState Git state from existing session
46
+ * @returns Object indicating if continuation is allowed and reason if not
47
+ */
48
+ export function detectSessionContinuation(currentGitState, sessionGitState) {
49
+ // Same branch and commit = auto-continue
50
+ if (currentGitState.branch === sessionGitState.branch &&
51
+ currentGitState.commitHash === sessionGitState.commitHash) {
52
+ return { canContinue: true };
53
+ }
54
+ // Different commit on same branch = warn but allow
55
+ if (currentGitState.branch === sessionGitState.branch) {
56
+ return {
57
+ canContinue: false,
58
+ reason: `Git state changed: commit ${sessionGitState.commitHash.slice(0, 8)} → ${currentGitState.commitHash.slice(0, 8)}`
59
+ };
60
+ }
61
+ // Different branch = don't auto-continue
62
+ return {
63
+ canContinue: false,
64
+ reason: `Branch changed: ${sessionGitState.branch} → ${currentGitState.branch}`
65
+ };
66
+ }
67
+ //# sourceMappingURL=gitStateDetector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitStateDetector.js","sourceRoot":"","sources":["../../src/utils/gitStateDetector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAUrC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,IAAI,CAAC;QACH,0DAA0D;QAC1D,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,YAAY,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAC3D,cAAc,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC;YAC5D,cAAc,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;YAC5C,cAAc,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;SACjD,CAAC,CAAC;QAEH,MAAM,gBAAgB,GAAG,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;QAEpD,OAAO;YACL,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE;YACrB,UAAU,EAAE,UAAU,CAAC,IAAI,EAAE;YAC7B,gBAAgB;YAChB,qBAAqB,EAAE,CAAC,gBAAgB;YACxC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,4BAA4B,KAAK,EAAE,CAAC,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,kEAAkE,KAAK,EAAE,CAAC,CAAC;IAC7F,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAkB;IAClD,MAAM,SAAS,GAAG,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAClD,6CAA6C;IAC7C,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;IACnE,OAAO,UAAU,UAAU,IAAI,SAAS,EAAE,CAAC;AAC7C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CACvC,eAAyB,EACzB,eAAyB;IAEzB,yCAAyC;IACzC,IACE,eAAe,CAAC,MAAM,KAAK,eAAe,CAAC,MAAM;QACjD,eAAe,CAAC,UAAU,KAAK,eAAe,CAAC,UAAU,EACzD,CAAC;QACD,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;IAC/B,CAAC;IAED,mDAAmD;IACnD,IAAI,eAAe,CAAC,MAAM,KAAK,eAAe,CAAC,MAAM,EAAE,CAAC;QACtD,OAAO;YACL,WAAW,EAAE,KAAK;YAClB,MAAM,EAAE,6BAA6B,eAAe,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,eAAe,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;SAC1H,CAAC;IACJ,CAAC;IAED,yCAAyC;IACzC,OAAO;QACL,WAAW,EAAE,KAAK;QAClB,MAAM,EAAE,mBAAmB,eAAe,CAAC,MAAM,MAAM,eAAe,CAAC,MAAM,EAAE;KAChF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ export declare class Logger {
2
+ private static formatMessage;
3
+ static log(message: string, ...args: any[]): void;
4
+ static warn(message: string, ...args: any[]): void;
5
+ static error(message: string, ...args: any[]): void;
6
+ static debug(message: string, ...args: any[]): void;
7
+ static toolInvocation(toolName: string, args: any): void;
8
+ static toolParsedArgs(prompt: string, model?: string, sandbox?: boolean, changeMode?: boolean): void;
9
+ static commandExecution(command: string, args: string[], startTime: number): void;
10
+ private static _commandStartTimes;
11
+ static commandComplete(startTime: number, exitCode: number | null, outputLength?: number): void;
12
+ }
13
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAGA,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAC,aAAa;IAI5B,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAIjD,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAIlD,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAInD,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAInD,MAAM,CAAC,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,IAAI;IAIxD,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,OAAO,GAAG,IAAI;IAIpG,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAQjF,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAA6E;IAE9G,MAAM,CAAC,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI;CAUhG"}
@@ -0,0 +1,42 @@
1
+ // WIP
2
+ import { LOG_PREFIX } from "../constants.js";
3
+ export class Logger {
4
+ static formatMessage(message) {
5
+ return `${LOG_PREFIX} ${message}` + "\n";
6
+ }
7
+ static log(message, ...args) {
8
+ console.warn(this.formatMessage(message), ...args);
9
+ }
10
+ static warn(message, ...args) {
11
+ console.warn(this.formatMessage(message), ...args);
12
+ }
13
+ static error(message, ...args) {
14
+ console.error(this.formatMessage(message), ...args);
15
+ }
16
+ static debug(message, ...args) {
17
+ console.warn(this.formatMessage(message), ...args);
18
+ }
19
+ static toolInvocation(toolName, args) {
20
+ this.warn("Raw:", JSON.stringify(args, null, 2));
21
+ }
22
+ static toolParsedArgs(prompt, model, sandbox, changeMode) {
23
+ this.warn(`Parsed prompt: "${prompt}"\nchangeMode: ${changeMode || false}`);
24
+ }
25
+ static commandExecution(command, args, startTime) {
26
+ this.warn(`[${startTime}] Starting: ${command} ${args.map((arg) => `"${arg}"`).join(" ")}`);
27
+ // Store command execution start for timing analysis
28
+ this._commandStartTimes.set(startTime, { command, args, startTime });
29
+ }
30
+ // Track command start times for duration calculation
31
+ static _commandStartTimes = new Map();
32
+ static commandComplete(startTime, exitCode, outputLength) {
33
+ const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
34
+ this.warn(`[${elapsed}s] Process finished with exit code: ${exitCode}`);
35
+ if (outputLength !== undefined) {
36
+ this.warn(`Response: ${outputLength} chars`);
37
+ }
38
+ // Clean up command tracking
39
+ this._commandStartTimes.delete(startTime);
40
+ }
41
+ }
42
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,MAAM;AACN,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,MAAM,OAAO,MAAM;IACT,MAAM,CAAC,aAAa,CAAC,OAAe;QAC1C,OAAO,GAAG,UAAU,IAAI,OAAO,EAAE,GAAG,IAAI,CAAC;IAC3C,CAAC;IAED,MAAM,CAAC,GAAG,CAAC,OAAe,EAAE,GAAG,IAAW;QACxC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IACrD,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,OAAe,EAAE,GAAG,IAAW;QACzC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IACrD,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,OAAe,EAAE,GAAG,IAAW;QAC1C,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IACtD,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,OAAe,EAAE,GAAG,IAAW;QAC1C,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IACrD,CAAC;IAED,MAAM,CAAC,cAAc,CAAC,QAAgB,EAAE,IAAS;QAC/C,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,CAAC,cAAc,CAAC,MAAc,EAAE,KAAc,EAAE,OAAiB,EAAE,UAAoB;QAC3F,IAAI,CAAC,IAAI,CAAC,mBAAmB,MAAM,kBAAkB,UAAU,IAAI,KAAK,EAAE,CAAC,CAAC;IAC9E,CAAC;IAED,MAAM,CAAC,gBAAgB,CAAC,OAAe,EAAE,IAAc,EAAE,SAAiB;QACxE,IAAI,CAAC,IAAI,CAAC,IAAI,SAAS,eAAe,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAE5F,oDAAoD;QACpD,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;IACvE,CAAC;IAED,qDAAqD;IAC7C,MAAM,CAAC,kBAAkB,GAAG,IAAI,GAAG,EAAkE,CAAC;IAE9G,MAAM,CAAC,eAAe,CAAC,SAAiB,EAAE,QAAuB,EAAE,YAAqB;QACtF,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC7D,IAAI,CAAC,IAAI,CAAC,IAAI,OAAO,uCAAuC,QAAQ,EAAE,CAAC,CAAC;QACxE,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YAC/B,IAAI,CAAC,IAAI,CAAC,aAAa,YAAY,QAAQ,CAAC,CAAC;QAC/C,CAAC;QAED,4BAA4B;QAC5B,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC5C,CAAC"}