@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.
@@ -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 Items Overview\n\nThis section provides')) {
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: c199efe3-003c-4226-af3c-d460392a6569
10523
- * Parent-UUID: N/A
10524
- * Version: 1.1.0
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";
@@ -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 Items Overview\n\nThis section provides')) {
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: c199efe3-003c-4226-af3c-d460392a6569
10521
- * Parent-UUID: N/A
10522
- * Version: 1.1.0
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitsense/gsc-utils",
3
- "version": "0.2.19",
3
+ "version": "0.2.21",
4
4
  "description": "Utilities for GitSense Chat (GSC)",
5
5
  "main": "dist/gsc-utils.cjs.js",
6
6
  "module": "dist/gsc-utils.esm.js",
@@ -1,12 +1,12 @@
1
1
  /*
2
2
  * Component: ContextUtils
3
- * Block-UUID: c199efe3-003c-4226-af3c-d460392a6569
4
- * Parent-UUID: N/A
5
- * Version: 1.1.0
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
+
@@ -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
  }
@@ -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 Items Overview\n\nThis section provides')) {
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';