@gitsense/gsc-utils 0.2.7 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/gsc-utils.cjs.js +316 -67
- package/dist/gsc-utils.esm.js +316 -67
- package/package.json +1 -1
- package/src/AnalyzerUtils/defaultPromptLoader.js +75 -0
- package/src/AnalyzerUtils/index.js +5 -2
- package/src/ContextUtils.js +163 -5
- package/src/GitSenseChatUtils.js +18 -4
package/package.json
CHANGED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Component: AnalyzerUtils Default Prompt Loader
|
|
3
|
+
* Block-UUID: 0b1c2d3e-4f5a-6b7c-8d9e-0f1a2b3c4d5f
|
|
4
|
+
* Parent-UUID: N/A
|
|
5
|
+
* Version: 1.0.0
|
|
6
|
+
* Description: Provides utility functions for loading shared, default prompt components (system and start messages).
|
|
7
|
+
* Language: JavaScript
|
|
8
|
+
* Created-at: 2025-08-29T03:30:28.771Z
|
|
9
|
+
* Authors: Gemini 2.5 Flash (v1.0.0)
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
const fs = require('fs').promises;
|
|
14
|
+
const path = require('path');
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Retrieves the raw Markdown content of the shared system message ('_shared/system/1.md').
|
|
18
|
+
*
|
|
19
|
+
* @param {string} analyzeMessagesBasePath - The absolute path to the base directory containing analyzer message files (e.g., 'messages/analyze').
|
|
20
|
+
* @returns {Promise<string|null>} A promise that resolves with the full Markdown content, or null if not found/invalid.
|
|
21
|
+
*/
|
|
22
|
+
async function getSystemMessageContent(analyzeMessagesBasePath) {
|
|
23
|
+
if (typeof analyzeMessagesBasePath !== 'string' || analyzeMessagesBasePath.trim() === '') {
|
|
24
|
+
console.error('Error: analyzeMessagesBasePath is required for getSystemMessageContent.');
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const systemMessageFilePath = path.join(analyzeMessagesBasePath, '_shared', 'system', '1.md');
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
const fileContent = await fs.readFile(systemMessageFilePath, 'utf8');
|
|
32
|
+
return fileContent;
|
|
33
|
+
} catch (error) {
|
|
34
|
+
if (error.code === 'ENOENT') {
|
|
35
|
+
console.warn(`Default system message file not found: ${systemMessageFilePath}.`);
|
|
36
|
+
return null;
|
|
37
|
+
} else {
|
|
38
|
+
console.error(`Error reading default system message file ${systemMessageFilePath}: ${error.message}`);
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Retrieves the raw Markdown content of the shared start message ('_shared/start/1.md').
|
|
46
|
+
*
|
|
47
|
+
* @param {string} analyzeMessagesBasePath - The absolute path to the base directory containing analyzer message files (e.g., 'messages/analyze').
|
|
48
|
+
* @returns {Promise<string|null>} A promise that resolves with the full Markdown content, or null if not found/invalid.
|
|
49
|
+
*/
|
|
50
|
+
async function getStartMessageContent(analyzeMessagesBasePath) {
|
|
51
|
+
if (typeof analyzeMessagesBasePath !== 'string' || analyzeMessagesBasePath.trim() === '') {
|
|
52
|
+
console.error('Error: analyzeMessagesBasePath is required for getStartMessageContent.');
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const startMessageFilePath = path.join(analyzeMessagesBasePath, '_shared', 'start', '1.md');
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
const fileContent = await fs.readFile(startMessageFilePath, 'utf8');
|
|
60
|
+
return fileContent;
|
|
61
|
+
} catch (error) {
|
|
62
|
+
if (error.code === 'ENOENT') {
|
|
63
|
+
console.warn(`Default start message file not found: ${startMessageFilePath}.`);
|
|
64
|
+
return null;
|
|
65
|
+
} else {
|
|
66
|
+
console.error(`Error reading default start message file ${startMessageFilePath}: ${error.message}`);
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
module.exports = {
|
|
73
|
+
getSystemMessageContent,
|
|
74
|
+
getStartMessageContent
|
|
75
|
+
};
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
* Component: AnalyzerUtils Index
|
|
3
3
|
* Block-UUID: b403b6a1-230b-4247-8cd6-2a3d068f4bbf
|
|
4
4
|
* Parent-UUID: N/A
|
|
5
|
-
* Version: 1.
|
|
5
|
+
* Version: 1.2.0
|
|
6
6
|
* Description: Aggregates and exports all utility functions from the AnalyzerUtils module.
|
|
7
7
|
* Language: JavaScript
|
|
8
8
|
* Created-at: 2025-08-28T15:56:40.319Z
|
|
9
|
-
* Authors: Gemini 2.5 Flash (v1.0.0), Gemini 2.5 Flash (v1.1.0)
|
|
9
|
+
* Authors: Gemini 2.5 Flash (v1.0.0), Gemini 2.5 Flash (v1.1.0), Gemini 2.5 Flash (v1.2.0)
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
|
|
@@ -18,6 +18,7 @@ const { saveConfiguration } = require('./saver');
|
|
|
18
18
|
const { getAnalyzerSchema } = require('./schemaLoader');
|
|
19
19
|
const { deleteAnalyzer } = require('./management');
|
|
20
20
|
const { getAnalyzerInstructionsContent } = require('./instructionLoader');
|
|
21
|
+
const { getSystemMessageContent, getStartMessageContent } = require('./defaultPromptLoader'); // NEW: Import default prompt loaders
|
|
21
22
|
|
|
22
23
|
module.exports = {
|
|
23
24
|
buildChatIdToPathMap,
|
|
@@ -28,4 +29,6 @@ module.exports = {
|
|
|
28
29
|
deleteAnalyzer,
|
|
29
30
|
getAnalyzerInstructionsContent,
|
|
30
31
|
saveConfiguration,
|
|
32
|
+
getSystemMessageContent,
|
|
33
|
+
getStartMessageContent
|
|
31
34
|
};
|
package/src/ContextUtils.js
CHANGED
|
@@ -1,18 +1,100 @@
|
|
|
1
|
-
|
|
1
|
+
/*
|
|
2
2
|
* Component: ContextUtils
|
|
3
3
|
* Block-UUID: c199efe3-003c-4226-af3c-d460392a6569
|
|
4
4
|
* Parent-UUID: N/A
|
|
5
|
-
* Version: 1.
|
|
6
|
-
* Description: Provides utility functions for parsing context message sections to extract file details and code blocks.
|
|
5
|
+
* Version: 1.1.0
|
|
6
|
+
* Description: Provides utility functions for parsing context message sections to extract file details and code blocks, and for formatting content for LLM context.
|
|
7
7
|
* Language: JavaScript
|
|
8
8
|
* Created-at: 2025-05-09T01:36:20.107Z
|
|
9
|
-
* Authors: Gemini 2.5 Flash Thinking (v1.0.0)
|
|
9
|
+
* Authors: Gemini 2.5 Flash Thinking (v1.0.0), Gemini 2.5 Flash (v1.1.0)
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
const CodeBlockUtils = require('./CodeBlockUtils');
|
|
14
14
|
const MessageUtils = require('./MessageUtils');
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Formats bytes into human-readable string (KB, MB, GB)
|
|
18
|
+
* @param {number} bytes - Number of bytes
|
|
19
|
+
* @returns {string} Formatted size string
|
|
20
|
+
*/
|
|
21
|
+
function _formatBytes(bytes) {
|
|
22
|
+
if (typeof bytes !== 'number' || isNaN(bytes)) return '0 bytes';
|
|
23
|
+
if (bytes === 0) return '0 bytes';
|
|
24
|
+
|
|
25
|
+
const k = 1024;
|
|
26
|
+
const sizes = ['bytes', 'KB', 'MB', 'GB'];
|
|
27
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
28
|
+
|
|
29
|
+
// Special case for bytes (no decimal)
|
|
30
|
+
if (i === 0) return `${bytes} ${sizes[i]}`;
|
|
31
|
+
|
|
32
|
+
const value = bytes / Math.pow(k, i);
|
|
33
|
+
// Show no decimal if whole number
|
|
34
|
+
const decimalPlaces = value % 1 === 0 ? 0 : 1;
|
|
35
|
+
return `${value.toFixed(decimalPlaces)} ${sizes[i]}`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Creates a summary of items for human readers
|
|
40
|
+
* @param {Array} items - Array of loaded items
|
|
41
|
+
* @param {string} contentType - Content type
|
|
42
|
+
* @returns {string} Human-readable summary
|
|
43
|
+
*/
|
|
44
|
+
function _createContextSummary(items, contentType) {
|
|
45
|
+
if (items.length === 0) return '';
|
|
46
|
+
|
|
47
|
+
// Group by files and trees
|
|
48
|
+
const files = items.filter(item => item.metadata?.type === 'git-blob');
|
|
49
|
+
const trees = items.filter(item => item.metadata?.type === 'git-tree' || item.metadata?.type === 'git-ref');
|
|
50
|
+
|
|
51
|
+
// Calculate total size and tokens
|
|
52
|
+
const totalSize = items.reduce((sum, item) => sum + (item.size || 0), 0);
|
|
53
|
+
const totalTokens = items.reduce((sum, item) => sum + (item.tokenCount || 0), 0);
|
|
54
|
+
|
|
55
|
+
let summary = contentType === 'file content'
|
|
56
|
+
? `\n**Summary:** ${items.length} file${items.length === 1 ? '' : 's'} (${_formatBytes(totalSize)}, ${totalTokens.toLocaleString()} tokens)\n\n`
|
|
57
|
+
: `\n**Summary:** ${files.length} file${files.length === 1 ? '' : 's'} - ${trees.length} tree${trees.length === 1 ? '' : 's'}\n\n`;
|
|
58
|
+
|
|
59
|
+
// Add brief description of first X files
|
|
60
|
+
const maxFiles = 10;
|
|
61
|
+
const displayItems = items.slice(0, maxFiles);
|
|
62
|
+
if (displayItems.length > 0) {
|
|
63
|
+
displayItems.forEach(item => {
|
|
64
|
+
if (item.tokenCount) {
|
|
65
|
+
summary += `- ${item.name} - ${_formatBytes(item.size)}, ${item.tokenCount.toLocaleString()} tokens\n`;
|
|
66
|
+
} else {
|
|
67
|
+
summary += `- ${item.name} - Not analyzed\n`;
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Add note if there are more files
|
|
72
|
+
if (items.length > maxFiles) {
|
|
73
|
+
summary += `- ... and ${items.length - maxFiles} more\n`;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return summary + "\n";
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Escapes backticks in code blocks to prevent premature termination of LLM-generated code blocks.
|
|
82
|
+
* @param {string} content - The content string to escape.
|
|
83
|
+
* @returns {{escapedContent: string, escapedLineNums: Array<number>}} Object with escaped content and line numbers of escaped lines.
|
|
84
|
+
*/
|
|
85
|
+
function _escapeCodeBlocks(content) {
|
|
86
|
+
const escapedLineNums = [];
|
|
87
|
+
const escapedLines = content.replace(/\n$/, '').split('\n').map((line, i) => {
|
|
88
|
+
if (line.trimStart().startsWith('```')) {
|
|
89
|
+
line = '\\' + line.trimStart();
|
|
90
|
+
escapedLineNums.push(i + 1);
|
|
91
|
+
}
|
|
92
|
+
return line;
|
|
93
|
+
});
|
|
94
|
+
return { escapedContent: escapedLines.join('\n'), escapedLineNums };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
16
98
|
/**
|
|
17
99
|
* Parses context details from a context message section.
|
|
18
100
|
* @param {string} sectionText - The text content of a single context section (starting from the file header).
|
|
@@ -173,8 +255,84 @@ function extractContextItemsOverviewTableRows(messageContent) {
|
|
|
173
255
|
return rows;
|
|
174
256
|
}
|
|
175
257
|
|
|
258
|
+
/**
|
|
259
|
+
* Formats content for context based on content type.
|
|
260
|
+
* This function is adapted from the original `formatContentForContext` in `formatterUtils.js`.
|
|
261
|
+
*
|
|
262
|
+
* @param {Array<Object>} items - Array of loaded items, each with `chatId`, `name`, `content`, `meta`, `repo` (from chatsApi.getBlobDetailsByChatIds).
|
|
263
|
+
* @param {string} contentType - Type of content ('file content' or 'overview'). For batch analysis, always 'file content'.
|
|
264
|
+
* @param {string} contentOption - Option for the content type. For batch analysis, always 'imported'.
|
|
265
|
+
* @returns {string} Formatted text for context.
|
|
266
|
+
*/
|
|
267
|
+
function formatContextContent(items, contentType, contentOption) {
|
|
268
|
+
if (items.length === 0) {
|
|
269
|
+
return 'No content loaded';
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
let result = '';
|
|
273
|
+
|
|
274
|
+
// Header based on content type
|
|
275
|
+
if (contentType === 'overview') {
|
|
276
|
+
const label = contentOption === "long" ? "comprehensive" : "short";
|
|
277
|
+
result += `## OVERVIEW - ${contentOption.toUpperCase()}\n`;
|
|
278
|
+
} else {
|
|
279
|
+
result += `## FILE CONTENT - ${contentOption.toUpperCase()}\n`;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Summary of items
|
|
283
|
+
result += _createContextSummary(items, contentType);
|
|
284
|
+
result += "\n---Start of Context---\n\n";
|
|
285
|
+
|
|
286
|
+
items.forEach((item, index) => {
|
|
287
|
+
// Ensure item has necessary properties, especially meta and repo
|
|
288
|
+
const itemMeta = item.meta || {};
|
|
289
|
+
const itemRepo = item.repo || {};
|
|
290
|
+
|
|
291
|
+
result += "#### `"+item.name+"`\n";
|
|
292
|
+
|
|
293
|
+
const { escapedContent, escapedLineNums } = _escapeCodeBlocks(item.content);
|
|
294
|
+
|
|
295
|
+
// Always include metadata for batch analysis context
|
|
296
|
+
result +=
|
|
297
|
+
`- Repo: ${itemRepo.fullName || 'N/A'}\n`+
|
|
298
|
+
`- Path: ${itemMeta.path || 'N/A'}\n`;
|
|
299
|
+
|
|
300
|
+
// Size and Tokens are specific to 'file content'
|
|
301
|
+
if (contentType === 'file content') {
|
|
302
|
+
result += `- Size: ${_formatBytes(itemMeta.size)}\n`;
|
|
303
|
+
result += `- Tokens: ${itemMeta.tokens?.content?.estimate || 'N/A'}\n`;
|
|
304
|
+
} else {
|
|
305
|
+
const type = itemMeta.type || 'unknown';
|
|
306
|
+
result += `- Type: ${type === 'git-blob' ? 'file' : type === 'git-tree' || type === 'git-ref' ? 'directory' : type }\n`;
|
|
307
|
+
result += `- Tokens: ${itemMeta.tokens?.analysis?.[contentOption.toLowerCase()]?.estimate || 'N/A'}\n`;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
result += `- Chat ID: ${item.chatId}\n`;
|
|
311
|
+
|
|
312
|
+
if (escapedLineNums.length) {
|
|
313
|
+
result += `- Escaped Lines: ${escapedLineNums.join(',')}\n`;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
result += '\n';
|
|
317
|
+
|
|
318
|
+
// The original formatterUtils had a special summary handling.
|
|
319
|
+
// For batch analysis, we want the full file content.
|
|
320
|
+
// The `if (!escapedContent.includes('Component: New Analyzer Chat') && escapedContent.match(summary))`
|
|
321
|
+
// logic is specific to the frontend's overview builder and should not be applied here.
|
|
322
|
+
result += "```"+(itemMeta.highlight || '')+"\n"+escapedContent+"\n```";
|
|
323
|
+
|
|
324
|
+
if (index !== items.length - 1) {
|
|
325
|
+
result += '\n---End of Item---\n';
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
return result;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
|
|
176
333
|
module.exports = {
|
|
177
334
|
parseContextSection,
|
|
178
335
|
extractContextSections,
|
|
179
|
-
extractContextItemsOverviewTableRows
|
|
336
|
+
extractContextItemsOverviewTableRows,
|
|
337
|
+
formatContextContent, // Export the new method
|
|
180
338
|
};
|
package/src/GitSenseChatUtils.js
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
* Component: GitSenseChatUtils
|
|
3
3
|
* Block-UUID: 5e8d1a9c-0b3f-4e1a-8c7d-9f0b2e1d3a4b
|
|
4
4
|
* Parent-UUID: 7a9b1c8e-f1a4-4b2d-9e8f-6f7a0b1c2d3f
|
|
5
|
-
* Version: 2.1.
|
|
5
|
+
* Version: 2.1.4
|
|
6
6
|
* Description: Interface class for GitSense Chat utilities providing a unified API for code block parsing (markdown), extraction, and patch operations. Integrates functionalities from CodeBlockUtils and PatchUtils modules, and now includes ConfigUtils and EnvUtils.
|
|
7
7
|
* Language: JavaScript
|
|
8
8
|
* Created-at: 2025-04-15T16:04:26.780Z
|
|
9
|
-
* Authors: Claude 3.7 Sonnet (v1.0.0), Gemini 2.5 Pro (v2.0.0), Gemini 2.5 Pro (v2.1.0), Gemini 2.5 Pro (v2.1.1), Gemini 2.5 Flash (v2.1.2), Gemini 2.5 Flash (v2.1.3)
|
|
9
|
+
* Authors: Claude 3.7 Sonnet (v1.0.0), Gemini 2.5 Pro (v2.0.0), Gemini 2.5 Pro (v2.1.0), Gemini 2.5 Pro (v2.1.1), Gemini 2.5 Flash (v2.1.2), Gemini 2.5 Flash (v2.1.3), Gemini 2.5 Flash (v2.1.4)
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
|
|
@@ -63,6 +63,8 @@ const {
|
|
|
63
63
|
getAnalyzerSchema,
|
|
64
64
|
deleteAnalyzer,
|
|
65
65
|
getAnalyzerInstructionsContent,
|
|
66
|
+
getSystemMessageContent,
|
|
67
|
+
getStartMessageContent,
|
|
66
68
|
saveAnalyzerConfiguration,
|
|
67
69
|
} = AnalyzerUtils;
|
|
68
70
|
|
|
@@ -122,6 +124,13 @@ const {
|
|
|
122
124
|
getApiKey
|
|
123
125
|
} = EnvUtils;
|
|
124
126
|
|
|
127
|
+
const {
|
|
128
|
+
parseContextSection,
|
|
129
|
+
extractContextSections,
|
|
130
|
+
extractContextItemsOverviewTableRows,
|
|
131
|
+
formatContextContent,
|
|
132
|
+
} = ContextUtils;
|
|
133
|
+
|
|
125
134
|
|
|
126
135
|
/**
|
|
127
136
|
* GitSenseChatUtils class provides a unified interface to code block and patch utilities.
|
|
@@ -398,6 +407,8 @@ module.exports = {
|
|
|
398
407
|
getAnalyzerSchema,
|
|
399
408
|
deleteAnalyzer,
|
|
400
409
|
getAnalyzerInstructionsContent,
|
|
410
|
+
getSystemMessageContent,
|
|
411
|
+
getStartMessageContent,
|
|
401
412
|
|
|
402
413
|
// ChatUtils
|
|
403
414
|
getChatMessages,
|
|
@@ -430,6 +441,9 @@ module.exports = {
|
|
|
430
441
|
loadEnv,
|
|
431
442
|
getApiKey,
|
|
432
443
|
|
|
433
|
-
//
|
|
434
|
-
|
|
444
|
+
// Context Utils
|
|
445
|
+
parseContextSection,
|
|
446
|
+
extractContextSections,
|
|
447
|
+
extractContextItemsOverviewTableRows,
|
|
448
|
+
formatContextContent,
|
|
435
449
|
};
|