@gitsense/gsc-utils 0.2.19 → 0.2.21
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 +118 -5
- package/dist/gsc-utils.esm.js +118 -5
- package/package.json +1 -1
- package/src/ContextUtils.js +9 -5
- package/src/GSToolBlockUtils.js +109 -0
- package/src/MessageUtils.js +1 -1
package/dist/gsc-utils.cjs.js
CHANGED
|
@@ -375,7 +375,7 @@ function getMessageContentType$1(messageContent) {
|
|
|
375
375
|
return 'file-content-context';
|
|
376
376
|
} else if (trimmedContent.startsWith('## OVERVIEW')) {
|
|
377
377
|
return 'overview-context';
|
|
378
|
-
} else if (trimmedContent.startsWith('## Context
|
|
378
|
+
} else if (trimmedContent.startsWith('## Context Overview\n\nThis context overview')) {
|
|
379
379
|
return 'context-items-overview';
|
|
380
380
|
} else if (trimmedContent.match(ANALYZE_MESSAGE_REGEXP)) {
|
|
381
381
|
return 'analyze-message';
|
|
@@ -8845,11 +8845,120 @@ function replaceToolBlock(markdownContent, toolName, newToolData, CodeBlockUtils
|
|
|
8845
8845
|
return updatedMarkdown;
|
|
8846
8846
|
}
|
|
8847
8847
|
|
|
8848
|
+
/**
|
|
8849
|
+
* Detects an unfenced GitSense Chat Tool block within a given message string,
|
|
8850
|
+
* validates its JSON content, and returns a properly formatted fenced block
|
|
8851
|
+
* along with its original position.
|
|
8852
|
+
*
|
|
8853
|
+
* This function is designed to be forgiving, looking for the marker line
|
|
8854
|
+
* "# GitSense Chat Tool" followed by JSON content, even if not enclosed
|
|
8855
|
+
* in Markdown code fences.
|
|
8856
|
+
*
|
|
8857
|
+
* @param {string} messageContent - The full message content string.
|
|
8858
|
+
* @returns {{
|
|
8859
|
+
* found: boolean,
|
|
8860
|
+
* formattedToolBlock?: string,
|
|
8861
|
+
* originalUnfencedContent?: string,
|
|
8862
|
+
* startIndex?: number,
|
|
8863
|
+
* endIndex?: number,
|
|
8864
|
+
* parsedToolData?: object
|
|
8865
|
+
* }} An object indicating if an unfenced tool block was found, its formatted version,
|
|
8866
|
+
* its original content, start/end indices, and the parsed tool data.
|
|
8867
|
+
*/
|
|
8868
|
+
function detectAndFormatUnfencedToolBlock(messageContent) {
|
|
8869
|
+
const marker = '# GitSense Chat Tool';
|
|
8870
|
+
const lines = messageContent.split('\n');
|
|
8871
|
+
let markerLineIndex = -1;
|
|
8872
|
+
|
|
8873
|
+
// 1. Find the marker line
|
|
8874
|
+
for (let i = 0; i < lines.length; i++) {
|
|
8875
|
+
if (lines[i].trim().startsWith(marker)) {
|
|
8876
|
+
markerLineIndex = i;
|
|
8877
|
+
break;
|
|
8878
|
+
}
|
|
8879
|
+
}
|
|
8880
|
+
|
|
8881
|
+
if (markerLineIndex === -1) {
|
|
8882
|
+
return { found: false };
|
|
8883
|
+
}
|
|
8884
|
+
|
|
8885
|
+
// 2. Extract potential JSON content following the marker
|
|
8886
|
+
let jsonStartLineIndex = -1;
|
|
8887
|
+
let jsonEndLineIndex = -1;
|
|
8888
|
+
let braceCount = 0;
|
|
8889
|
+
let inJsonBlock = false;
|
|
8890
|
+
|
|
8891
|
+
for (let i = markerLineIndex + 1; i < lines.length; i++) {
|
|
8892
|
+
const trimmedLine = lines[i].trim();
|
|
8893
|
+
|
|
8894
|
+
if (!inJsonBlock) {
|
|
8895
|
+
if (trimmedLine.length === 0 || trimmedLine.startsWith('#')) { // Skip empty lines or comments
|
|
8896
|
+
continue;
|
|
8897
|
+
}
|
|
8898
|
+
if (trimmedLine.startsWith('{')) {
|
|
8899
|
+
jsonStartLineIndex = i;
|
|
8900
|
+
inJsonBlock = true;
|
|
8901
|
+
} else {
|
|
8902
|
+
return { found: false }; // Found something after marker but not JSON
|
|
8903
|
+
}
|
|
8904
|
+
}
|
|
8905
|
+
|
|
8906
|
+
if (inJsonBlock) {
|
|
8907
|
+
for (const char of trimmedLine) {
|
|
8908
|
+
if (char === '{') braceCount++;
|
|
8909
|
+
else if (char === '}') braceCount--;
|
|
8910
|
+
}
|
|
8911
|
+
if (braceCount === 0 && trimmedLine.endsWith('}')) {
|
|
8912
|
+
jsonEndLineIndex = i;
|
|
8913
|
+
break; // Found the end of the JSON block
|
|
8914
|
+
}
|
|
8915
|
+
}
|
|
8916
|
+
}
|
|
8917
|
+
|
|
8918
|
+
if (jsonStartLineIndex === -1 || jsonEndLineIndex === -1) {
|
|
8919
|
+
return { found: false }; // JSON block not properly formed or not found
|
|
8920
|
+
}
|
|
8921
|
+
|
|
8922
|
+
// Extract the raw unfenced content including the marker and JSON
|
|
8923
|
+
const originalUnfencedContentLines = lines.slice(markerLineIndex, jsonEndLineIndex + 1);
|
|
8924
|
+
const originalUnfencedContent = originalUnfencedContentLines.join('\n');
|
|
8925
|
+
|
|
8926
|
+
// 3. Validate the extracted content using parseToolBlock
|
|
8927
|
+
let parsedToolData = null;
|
|
8928
|
+
try {
|
|
8929
|
+
parsedToolData = parseToolBlock$1(originalUnfencedContent);
|
|
8930
|
+
} catch (error) {
|
|
8931
|
+
console.warn("detectAndFormatUnfencedToolBlock: Failed to parse unfenced tool block JSON:", error.message);
|
|
8932
|
+
return { found: false }; // Invalid JSON structure
|
|
8933
|
+
}
|
|
8934
|
+
|
|
8935
|
+
if (!parsedToolData) {
|
|
8936
|
+
return { found: false };
|
|
8937
|
+
}
|
|
8938
|
+
|
|
8939
|
+
// 4. Format the validated tool data into a fenced block
|
|
8940
|
+
const formattedToolBlock = `\`\`\`txt\n${formatToolBlock(parsedToolData)}\n\`\`\``;
|
|
8941
|
+
|
|
8942
|
+
// Calculate start and end indices in the original message string
|
|
8943
|
+
const startIndex = messageContent.indexOf(originalUnfencedContent);
|
|
8944
|
+
const endIndex = startIndex + originalUnfencedContent.length;
|
|
8945
|
+
|
|
8946
|
+
return {
|
|
8947
|
+
found: true,
|
|
8948
|
+
formattedToolBlock,
|
|
8949
|
+
originalUnfencedContent,
|
|
8950
|
+
startIndex,
|
|
8951
|
+
endIndex,
|
|
8952
|
+
parsedToolData
|
|
8953
|
+
};
|
|
8954
|
+
}
|
|
8955
|
+
|
|
8848
8956
|
var GSToolBlockUtils$3 = {
|
|
8849
8957
|
isToolBlock: isToolBlock$1,
|
|
8850
8958
|
parseToolBlock: parseToolBlock$1,
|
|
8851
8959
|
formatToolBlock,
|
|
8852
8960
|
replaceToolBlock,
|
|
8961
|
+
detectAndFormatUnfencedToolBlock,
|
|
8853
8962
|
};
|
|
8854
8963
|
|
|
8855
8964
|
/*
|
|
@@ -10519,13 +10628,13 @@ var CodeBlockUtils$5 = {
|
|
|
10519
10628
|
|
|
10520
10629
|
/*
|
|
10521
10630
|
* Component: ContextUtils
|
|
10522
|
-
* Block-UUID:
|
|
10523
|
-
* Parent-UUID:
|
|
10524
|
-
* Version: 1.
|
|
10631
|
+
* Block-UUID: c018b1f9-2291-4bc9-9c4b-ab53a5db745e
|
|
10632
|
+
* Parent-UUID: c199efe3-003c-4226-af3c-d460392a6569
|
|
10633
|
+
* Version: 1.2.0
|
|
10525
10634
|
* Description: Provides utility functions for parsing context message sections to extract file details and code blocks, and for formatting content for LLM context.
|
|
10526
10635
|
* Language: JavaScript
|
|
10527
10636
|
* Created-at: 2025-05-09T01:36:20.107Z
|
|
10528
|
-
* Authors: Gemini 2.5 Flash Thinking (v1.0.0), Gemini 2.5 Flash (v1.1.0)
|
|
10637
|
+
* Authors: Gemini 2.5 Flash Thinking (v1.0.0), Gemini 2.5 Flash (v1.1.0), Qwen 3 Coder 480B - Cerebras (v1.2.0)
|
|
10529
10638
|
*/
|
|
10530
10639
|
|
|
10531
10640
|
const CodeBlockUtils$4 = CodeBlockUtils$5;
|
|
@@ -10792,10 +10901,14 @@ function formatContextContent$1(items, contentType, contentOption) {
|
|
|
10792
10901
|
// Header based on content type
|
|
10793
10902
|
if (contentType === 'overview') {
|
|
10794
10903
|
result += `## OVERVIEW - ${contentOption.toUpperCase()}\n`;
|
|
10904
|
+
result += '\n';
|
|
10795
10905
|
} else {
|
|
10796
10906
|
result += `## FILE CONTENT - ${contentOption.toUpperCase()}\n`;
|
|
10907
|
+
result += '\n';
|
|
10797
10908
|
}
|
|
10798
10909
|
|
|
10910
|
+
result += 'The following files are provided as context for your request. Use this information to understand the project\'s structure and content. This is a data payload for context; please do not mirror this format in your response.\n';
|
|
10911
|
+
result += '\n';
|
|
10799
10912
|
// Summary of items
|
|
10800
10913
|
result += _createContextSummary(items, contentType);
|
|
10801
10914
|
result += "\n---Start of Context---\n\n";
|
package/dist/gsc-utils.esm.js
CHANGED
|
@@ -373,7 +373,7 @@ function getMessageContentType$1(messageContent) {
|
|
|
373
373
|
return 'file-content-context';
|
|
374
374
|
} else if (trimmedContent.startsWith('## OVERVIEW')) {
|
|
375
375
|
return 'overview-context';
|
|
376
|
-
} else if (trimmedContent.startsWith('## Context
|
|
376
|
+
} else if (trimmedContent.startsWith('## Context Overview\n\nThis context overview')) {
|
|
377
377
|
return 'context-items-overview';
|
|
378
378
|
} else if (trimmedContent.match(ANALYZE_MESSAGE_REGEXP)) {
|
|
379
379
|
return 'analyze-message';
|
|
@@ -8843,11 +8843,120 @@ function replaceToolBlock(markdownContent, toolName, newToolData, CodeBlockUtils
|
|
|
8843
8843
|
return updatedMarkdown;
|
|
8844
8844
|
}
|
|
8845
8845
|
|
|
8846
|
+
/**
|
|
8847
|
+
* Detects an unfenced GitSense Chat Tool block within a given message string,
|
|
8848
|
+
* validates its JSON content, and returns a properly formatted fenced block
|
|
8849
|
+
* along with its original position.
|
|
8850
|
+
*
|
|
8851
|
+
* This function is designed to be forgiving, looking for the marker line
|
|
8852
|
+
* "# GitSense Chat Tool" followed by JSON content, even if not enclosed
|
|
8853
|
+
* in Markdown code fences.
|
|
8854
|
+
*
|
|
8855
|
+
* @param {string} messageContent - The full message content string.
|
|
8856
|
+
* @returns {{
|
|
8857
|
+
* found: boolean,
|
|
8858
|
+
* formattedToolBlock?: string,
|
|
8859
|
+
* originalUnfencedContent?: string,
|
|
8860
|
+
* startIndex?: number,
|
|
8861
|
+
* endIndex?: number,
|
|
8862
|
+
* parsedToolData?: object
|
|
8863
|
+
* }} An object indicating if an unfenced tool block was found, its formatted version,
|
|
8864
|
+
* its original content, start/end indices, and the parsed tool data.
|
|
8865
|
+
*/
|
|
8866
|
+
function detectAndFormatUnfencedToolBlock(messageContent) {
|
|
8867
|
+
const marker = '# GitSense Chat Tool';
|
|
8868
|
+
const lines = messageContent.split('\n');
|
|
8869
|
+
let markerLineIndex = -1;
|
|
8870
|
+
|
|
8871
|
+
// 1. Find the marker line
|
|
8872
|
+
for (let i = 0; i < lines.length; i++) {
|
|
8873
|
+
if (lines[i].trim().startsWith(marker)) {
|
|
8874
|
+
markerLineIndex = i;
|
|
8875
|
+
break;
|
|
8876
|
+
}
|
|
8877
|
+
}
|
|
8878
|
+
|
|
8879
|
+
if (markerLineIndex === -1) {
|
|
8880
|
+
return { found: false };
|
|
8881
|
+
}
|
|
8882
|
+
|
|
8883
|
+
// 2. Extract potential JSON content following the marker
|
|
8884
|
+
let jsonStartLineIndex = -1;
|
|
8885
|
+
let jsonEndLineIndex = -1;
|
|
8886
|
+
let braceCount = 0;
|
|
8887
|
+
let inJsonBlock = false;
|
|
8888
|
+
|
|
8889
|
+
for (let i = markerLineIndex + 1; i < lines.length; i++) {
|
|
8890
|
+
const trimmedLine = lines[i].trim();
|
|
8891
|
+
|
|
8892
|
+
if (!inJsonBlock) {
|
|
8893
|
+
if (trimmedLine.length === 0 || trimmedLine.startsWith('#')) { // Skip empty lines or comments
|
|
8894
|
+
continue;
|
|
8895
|
+
}
|
|
8896
|
+
if (trimmedLine.startsWith('{')) {
|
|
8897
|
+
jsonStartLineIndex = i;
|
|
8898
|
+
inJsonBlock = true;
|
|
8899
|
+
} else {
|
|
8900
|
+
return { found: false }; // Found something after marker but not JSON
|
|
8901
|
+
}
|
|
8902
|
+
}
|
|
8903
|
+
|
|
8904
|
+
if (inJsonBlock) {
|
|
8905
|
+
for (const char of trimmedLine) {
|
|
8906
|
+
if (char === '{') braceCount++;
|
|
8907
|
+
else if (char === '}') braceCount--;
|
|
8908
|
+
}
|
|
8909
|
+
if (braceCount === 0 && trimmedLine.endsWith('}')) {
|
|
8910
|
+
jsonEndLineIndex = i;
|
|
8911
|
+
break; // Found the end of the JSON block
|
|
8912
|
+
}
|
|
8913
|
+
}
|
|
8914
|
+
}
|
|
8915
|
+
|
|
8916
|
+
if (jsonStartLineIndex === -1 || jsonEndLineIndex === -1) {
|
|
8917
|
+
return { found: false }; // JSON block not properly formed or not found
|
|
8918
|
+
}
|
|
8919
|
+
|
|
8920
|
+
// Extract the raw unfenced content including the marker and JSON
|
|
8921
|
+
const originalUnfencedContentLines = lines.slice(markerLineIndex, jsonEndLineIndex + 1);
|
|
8922
|
+
const originalUnfencedContent = originalUnfencedContentLines.join('\n');
|
|
8923
|
+
|
|
8924
|
+
// 3. Validate the extracted content using parseToolBlock
|
|
8925
|
+
let parsedToolData = null;
|
|
8926
|
+
try {
|
|
8927
|
+
parsedToolData = parseToolBlock$1(originalUnfencedContent);
|
|
8928
|
+
} catch (error) {
|
|
8929
|
+
console.warn("detectAndFormatUnfencedToolBlock: Failed to parse unfenced tool block JSON:", error.message);
|
|
8930
|
+
return { found: false }; // Invalid JSON structure
|
|
8931
|
+
}
|
|
8932
|
+
|
|
8933
|
+
if (!parsedToolData) {
|
|
8934
|
+
return { found: false };
|
|
8935
|
+
}
|
|
8936
|
+
|
|
8937
|
+
// 4. Format the validated tool data into a fenced block
|
|
8938
|
+
const formattedToolBlock = `\`\`\`txt\n${formatToolBlock(parsedToolData)}\n\`\`\``;
|
|
8939
|
+
|
|
8940
|
+
// Calculate start and end indices in the original message string
|
|
8941
|
+
const startIndex = messageContent.indexOf(originalUnfencedContent);
|
|
8942
|
+
const endIndex = startIndex + originalUnfencedContent.length;
|
|
8943
|
+
|
|
8944
|
+
return {
|
|
8945
|
+
found: true,
|
|
8946
|
+
formattedToolBlock,
|
|
8947
|
+
originalUnfencedContent,
|
|
8948
|
+
startIndex,
|
|
8949
|
+
endIndex,
|
|
8950
|
+
parsedToolData
|
|
8951
|
+
};
|
|
8952
|
+
}
|
|
8953
|
+
|
|
8846
8954
|
var GSToolBlockUtils$3 = {
|
|
8847
8955
|
isToolBlock: isToolBlock$1,
|
|
8848
8956
|
parseToolBlock: parseToolBlock$1,
|
|
8849
8957
|
formatToolBlock,
|
|
8850
8958
|
replaceToolBlock,
|
|
8959
|
+
detectAndFormatUnfencedToolBlock,
|
|
8851
8960
|
};
|
|
8852
8961
|
|
|
8853
8962
|
/*
|
|
@@ -10517,13 +10626,13 @@ var CodeBlockUtils$5 = {
|
|
|
10517
10626
|
|
|
10518
10627
|
/*
|
|
10519
10628
|
* Component: ContextUtils
|
|
10520
|
-
* Block-UUID:
|
|
10521
|
-
* Parent-UUID:
|
|
10522
|
-
* Version: 1.
|
|
10629
|
+
* Block-UUID: c018b1f9-2291-4bc9-9c4b-ab53a5db745e
|
|
10630
|
+
* Parent-UUID: c199efe3-003c-4226-af3c-d460392a6569
|
|
10631
|
+
* Version: 1.2.0
|
|
10523
10632
|
* Description: Provides utility functions for parsing context message sections to extract file details and code blocks, and for formatting content for LLM context.
|
|
10524
10633
|
* Language: JavaScript
|
|
10525
10634
|
* Created-at: 2025-05-09T01:36:20.107Z
|
|
10526
|
-
* Authors: Gemini 2.5 Flash Thinking (v1.0.0), Gemini 2.5 Flash (v1.1.0)
|
|
10635
|
+
* Authors: Gemini 2.5 Flash Thinking (v1.0.0), Gemini 2.5 Flash (v1.1.0), Qwen 3 Coder 480B - Cerebras (v1.2.0)
|
|
10527
10636
|
*/
|
|
10528
10637
|
|
|
10529
10638
|
const CodeBlockUtils$4 = CodeBlockUtils$5;
|
|
@@ -10790,10 +10899,14 @@ function formatContextContent$1(items, contentType, contentOption) {
|
|
|
10790
10899
|
// Header based on content type
|
|
10791
10900
|
if (contentType === 'overview') {
|
|
10792
10901
|
result += `## OVERVIEW - ${contentOption.toUpperCase()}\n`;
|
|
10902
|
+
result += '\n';
|
|
10793
10903
|
} else {
|
|
10794
10904
|
result += `## FILE CONTENT - ${contentOption.toUpperCase()}\n`;
|
|
10905
|
+
result += '\n';
|
|
10795
10906
|
}
|
|
10796
10907
|
|
|
10908
|
+
result += 'The following files are provided as context for your request. Use this information to understand the project\'s structure and content. This is a data payload for context; please do not mirror this format in your response.\n';
|
|
10909
|
+
result += '\n';
|
|
10797
10910
|
// Summary of items
|
|
10798
10911
|
result += _createContextSummary(items, contentType);
|
|
10799
10912
|
result += "\n---Start of Context---\n\n";
|
package/package.json
CHANGED
package/src/ContextUtils.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Component: ContextUtils
|
|
3
|
-
* Block-UUID:
|
|
4
|
-
* Parent-UUID:
|
|
5
|
-
* Version: 1.
|
|
3
|
+
* Block-UUID: c018b1f9-2291-4bc9-9c4b-ab53a5db745e
|
|
4
|
+
* Parent-UUID: c199efe3-003c-4226-af3c-d460392a6569
|
|
5
|
+
* Version: 1.2.0
|
|
6
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), Gemini 2.5 Flash (v1.1.0)
|
|
9
|
+
* Authors: Gemini 2.5 Flash Thinking (v1.0.0), Gemini 2.5 Flash (v1.1.0), Qwen 3 Coder 480B - Cerebras (v1.2.0)
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
|
|
@@ -273,12 +273,15 @@ function formatContextContent(items, contentType, contentOption) {
|
|
|
273
273
|
|
|
274
274
|
// Header based on content type
|
|
275
275
|
if (contentType === 'overview') {
|
|
276
|
-
const label = contentOption === "long" ? "comprehensive" : "short";
|
|
277
276
|
result += `## OVERVIEW - ${contentOption.toUpperCase()}\n`;
|
|
277
|
+
result += '\n';
|
|
278
278
|
} else {
|
|
279
279
|
result += `## FILE CONTENT - ${contentOption.toUpperCase()}\n`;
|
|
280
|
+
result += '\n';
|
|
280
281
|
}
|
|
281
282
|
|
|
283
|
+
result += 'The following files are provided as context for your request. Use this information to understand the project\'s structure and content. This is a data payload for context; please do not mirror this format in your response.\n';
|
|
284
|
+
result += '\n';
|
|
282
285
|
// Summary of items
|
|
283
286
|
result += _createContextSummary(items, contentType);
|
|
284
287
|
result += "\n---Start of Context---\n\n";
|
|
@@ -336,3 +339,4 @@ module.exports = {
|
|
|
336
339
|
extractContextItemsOverviewTableRows,
|
|
337
340
|
formatContextContent,
|
|
338
341
|
};
|
|
342
|
+
|
package/src/GSToolBlockUtils.js
CHANGED
|
@@ -162,9 +162,118 @@ function replaceToolBlock(markdownContent, toolName, newToolData, CodeBlockUtils
|
|
|
162
162
|
return updatedMarkdown;
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
+
/**
|
|
166
|
+
* Detects an unfenced GitSense Chat Tool block within a given message string,
|
|
167
|
+
* validates its JSON content, and returns a properly formatted fenced block
|
|
168
|
+
* along with its original position.
|
|
169
|
+
*
|
|
170
|
+
* This function is designed to be forgiving, looking for the marker line
|
|
171
|
+
* "# GitSense Chat Tool" followed by JSON content, even if not enclosed
|
|
172
|
+
* in Markdown code fences.
|
|
173
|
+
*
|
|
174
|
+
* @param {string} messageContent - The full message content string.
|
|
175
|
+
* @returns {{
|
|
176
|
+
* found: boolean,
|
|
177
|
+
* formattedToolBlock?: string,
|
|
178
|
+
* originalUnfencedContent?: string,
|
|
179
|
+
* startIndex?: number,
|
|
180
|
+
* endIndex?: number,
|
|
181
|
+
* parsedToolData?: object
|
|
182
|
+
* }} An object indicating if an unfenced tool block was found, its formatted version,
|
|
183
|
+
* its original content, start/end indices, and the parsed tool data.
|
|
184
|
+
*/
|
|
185
|
+
function detectAndFormatUnfencedToolBlock(messageContent) {
|
|
186
|
+
const marker = '# GitSense Chat Tool';
|
|
187
|
+
const lines = messageContent.split('\n');
|
|
188
|
+
let markerLineIndex = -1;
|
|
189
|
+
|
|
190
|
+
// 1. Find the marker line
|
|
191
|
+
for (let i = 0; i < lines.length; i++) {
|
|
192
|
+
if (lines[i].trim().startsWith(marker)) {
|
|
193
|
+
markerLineIndex = i;
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (markerLineIndex === -1) {
|
|
199
|
+
return { found: false };
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// 2. Extract potential JSON content following the marker
|
|
203
|
+
let jsonStartLineIndex = -1;
|
|
204
|
+
let jsonEndLineIndex = -1;
|
|
205
|
+
let braceCount = 0;
|
|
206
|
+
let inJsonBlock = false;
|
|
207
|
+
|
|
208
|
+
for (let i = markerLineIndex + 1; i < lines.length; i++) {
|
|
209
|
+
const trimmedLine = lines[i].trim();
|
|
210
|
+
|
|
211
|
+
if (!inJsonBlock) {
|
|
212
|
+
if (trimmedLine.length === 0 || trimmedLine.startsWith('#')) { // Skip empty lines or comments
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
if (trimmedLine.startsWith('{')) {
|
|
216
|
+
jsonStartLineIndex = i;
|
|
217
|
+
inJsonBlock = true;
|
|
218
|
+
} else {
|
|
219
|
+
return { found: false }; // Found something after marker but not JSON
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (inJsonBlock) {
|
|
224
|
+
for (const char of trimmedLine) {
|
|
225
|
+
if (char === '{') braceCount++;
|
|
226
|
+
else if (char === '}') braceCount--;
|
|
227
|
+
}
|
|
228
|
+
if (braceCount === 0 && trimmedLine.endsWith('}')) {
|
|
229
|
+
jsonEndLineIndex = i;
|
|
230
|
+
break; // Found the end of the JSON block
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (jsonStartLineIndex === -1 || jsonEndLineIndex === -1) {
|
|
236
|
+
return { found: false }; // JSON block not properly formed or not found
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Extract the raw unfenced content including the marker and JSON
|
|
240
|
+
const originalUnfencedContentLines = lines.slice(markerLineIndex, jsonEndLineIndex + 1);
|
|
241
|
+
const originalUnfencedContent = originalUnfencedContentLines.join('\n');
|
|
242
|
+
|
|
243
|
+
// 3. Validate the extracted content using parseToolBlock
|
|
244
|
+
let parsedToolData = null;
|
|
245
|
+
try {
|
|
246
|
+
parsedToolData = parseToolBlock(originalUnfencedContent);
|
|
247
|
+
} catch (error) {
|
|
248
|
+
console.warn("detectAndFormatUnfencedToolBlock: Failed to parse unfenced tool block JSON:", error.message);
|
|
249
|
+
return { found: false }; // Invalid JSON structure
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (!parsedToolData) {
|
|
253
|
+
return { found: false };
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// 4. Format the validated tool data into a fenced block
|
|
257
|
+
const formattedToolBlock = `\`\`\`txt\n${formatToolBlock(parsedToolData)}\n\`\`\``;
|
|
258
|
+
|
|
259
|
+
// Calculate start and end indices in the original message string
|
|
260
|
+
const startIndex = messageContent.indexOf(originalUnfencedContent);
|
|
261
|
+
const endIndex = startIndex + originalUnfencedContent.length;
|
|
262
|
+
|
|
263
|
+
return {
|
|
264
|
+
found: true,
|
|
265
|
+
formattedToolBlock,
|
|
266
|
+
originalUnfencedContent,
|
|
267
|
+
startIndex,
|
|
268
|
+
endIndex,
|
|
269
|
+
parsedToolData
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
|
|
165
273
|
module.exports = {
|
|
166
274
|
isToolBlock,
|
|
167
275
|
parseToolBlock,
|
|
168
276
|
formatToolBlock,
|
|
169
277
|
replaceToolBlock,
|
|
278
|
+
detectAndFormatUnfencedToolBlock,
|
|
170
279
|
}
|
package/src/MessageUtils.js
CHANGED
|
@@ -367,7 +367,7 @@ function getMessageContentType(messageContent) {
|
|
|
367
367
|
return 'file-content-context';
|
|
368
368
|
} else if (trimmedContent.startsWith('## OVERVIEW')) {
|
|
369
369
|
return 'overview-context';
|
|
370
|
-
} else if (trimmedContent.startsWith('## Context
|
|
370
|
+
} else if (trimmedContent.startsWith('## Context Overview\n\nThis context overview')) {
|
|
371
371
|
return 'context-items-overview';
|
|
372
372
|
} else if (trimmedContent.match(ANALYZE_MESSAGE_REGEXP)) {
|
|
373
373
|
return 'analyze-message';
|