@gitsense/gsc-utils 0.2.21 → 0.2.23

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.
@@ -6810,7 +6810,9 @@ function createPatchFromCodeBlocks(CodeBlockUtils, sourceCodeBlockText, targetCo
6810
6810
  const targetContent = targetContentTemp.join('\n\n');
6811
6811
 
6812
6812
  // Get the number of lines in the header + two blank lines
6813
- const sourceHeaderLineCount = sourceHeaderText.split('\n').length;
6813
+ // Note, before the code block header format was solidified, we use to include 'Updated-at' but no more so
6814
+ // we need to filter it out from the source header
6815
+ const sourceHeaderLineCount = sourceHeaderText.split('\n').filter(line => !line.includes('Updated-at')).length;
6814
6816
  const targetHeaderLineCount = targetHeaderText.split('\n').length;
6815
6817
 
6816
6818
  // To keep things simple we are going to require the source and target header line count to be the same.
@@ -6818,7 +6820,7 @@ function createPatchFromCodeBlocks(CodeBlockUtils, sourceCodeBlockText, targetCo
6818
6820
  if (sourceHeaderLineCount !== targetHeaderLineCount) {
6819
6821
  // Some LLMs will not generate a Parent-UUID for the first version so we won't make this
6820
6822
  // fatal if the sourceHeader does not have a Parent-UUID
6821
- if (sourceHeaderLineCount.includes('Parent-UUID')) {
6823
+ if (sourceHeaderText.includes('Parent-UUID')) {
6822
6824
  throw new Error('Source and target header line count must be the same');
6823
6825
  }
6824
6826
  }
@@ -10628,13 +10630,13 @@ var CodeBlockUtils$5 = {
10628
10630
 
10629
10631
  /*
10630
10632
  * Component: ContextUtils
10631
- * Block-UUID: c018b1f9-2291-4bc9-9c4b-ab53a5db745e
10632
- * Parent-UUID: c199efe3-003c-4226-af3c-d460392a6569
10633
- * Version: 1.2.0
10633
+ * Block-UUID: a0b71292-b1cc-401a-8ce2-544a047b0fef
10634
+ * Parent-UUID: c018b1f9-2291-4bc9-9c4b-ab53a5db745e
10635
+ * Version: 1.3.0
10634
10636
  * Description: Provides utility functions for parsing context message sections to extract file details and code blocks, and for formatting content for LLM context.
10635
10637
  * Language: JavaScript
10636
10638
  * Created-at: 2025-05-09T01:36:20.107Z
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)
10639
+ * Authors: Gemini 2.5 Flash Thinking (v1.0.0), Gemini 2.5 Flash (v1.1.0), Qwen 3 Coder 480B - Cerebras (v1.2.0), Qwen 3 Coder 480B - Cerebras (v1.3.0)
10638
10640
  */
10639
10641
 
10640
10642
  const CodeBlockUtils$4 = CodeBlockUtils$5;
@@ -10815,12 +10817,26 @@ function extractContextSections$1(messageContent) {
10815
10817
  const [summary, items] = messageContent.split(/\n---Start of Context---\n\n/);
10816
10818
  const sections = items.split(/\n---End of Item---\n/);
10817
10819
 
10820
+ // Determine the origin of the context based on the message header
10821
+ let contextOrigin = 'unknown'; // Default value if not determinable
10822
+ if (messageContent.includes("## FILE CONTENT - WORKING DIRECTORY")) {
10823
+ contextOrigin = 'working-directory';
10824
+ } else if (messageContent.includes("## FILE CONTENT - IMPORTED")) {
10825
+ contextOrigin = 'imported';
10826
+ } else if (messageContent.includes("## OVERVIEW - IMPORTED")) {
10827
+ // Handle the overview case as well, though it uses 'file content' type
10828
+ contextOrigin = 'imported';
10829
+ }
10830
+
10818
10831
  // Process sections starting from the first potential path delimiter.
10819
10832
  for (let i = 0; i < sections.length; i++) {
10820
10833
  const contextSection = parseContextSection$1(sections[i]);
10821
10834
 
10822
10835
  if (contextSection) {
10823
10836
  contextSections.push(contextSection);
10837
+ // Attach the determined context origin to the section
10838
+ // This provides information on how the context was introduced
10839
+ contextSection.contextOrigin = contextOrigin;
10824
10840
  }
10825
10841
  }
10826
10842
 
@@ -10841,6 +10857,7 @@ function extractContextItemsOverviewTableRows$1(messageContent) {
10841
10857
  return null;
10842
10858
  }
10843
10859
 
10860
+ // Map the column number to the type
10844
10861
  const col2Field = {
10845
10862
  1: 'chatId',
10846
10863
  2: 'type', // file, tree, etc.
@@ -12038,6 +12055,174 @@ var LLMUtils$1 = {
12038
12055
  estimateTokens: estimateTokens$1,
12039
12056
  };
12040
12057
 
12058
+ /**
12059
+ * Component: Date Utilities
12060
+ * Block-UUID: fef3b0f4-8055-4690-9336-e68a9cc33a61
12061
+ * Parent-UUID: 716e5ce9-84df-4f12-89e7-4a28e4a39a81
12062
+ * Version: 1.0.0
12063
+ * Description: Date formatting and manipulation utilities for GitSense Chat
12064
+ * Language: JavaScript
12065
+ * Created-at: 2025-10-11T23:26:20.815Z
12066
+ * Authors: Claude-3.5-Sonnet (v1.0.0), Qwen 3 Coder 480B - Cerebras (v1.0.0)
12067
+ */
12068
+
12069
+ /**
12070
+ * Ensures a date string has a timezone indicator
12071
+ * @param {string} dateString - Date string in format "YYYY-MM-DD(T| )HH:mm:ss.SSS"
12072
+ * @returns {string} Date string with 'Z' timezone indicator if not present
12073
+ */
12074
+ function normalizeDateTime(dateString) {
12075
+ return dateString.includes('Z') ? dateString : dateString + 'Z';
12076
+ }
12077
+
12078
+ /**
12079
+ * Calculates the time difference between now and a given date
12080
+ * @param {string} dateString - Date string to compare against current time
12081
+ * @returns {number} Difference in seconds
12082
+ */
12083
+ function getTimeDifference(dateString) {
12084
+ const now = new Date();
12085
+ const date = new Date(normalizeDateTime(dateString));
12086
+ return Math.floor((now - date) / 1000);
12087
+ }
12088
+
12089
+ /**
12090
+ * Formats a time difference in seconds to a human-readable string
12091
+ * @param {number} diff - Time difference in seconds
12092
+ * @returns {string} Formatted string (e.g., "5s ago", "2m ago", "3h ago", "2d ago")
12093
+ */
12094
+ function formatTimeDifference(diff) {
12095
+ if (diff < 60) {
12096
+ return `${diff}s ago`;
12097
+ } else if (diff < 3600) {
12098
+ const minutes = Math.floor(diff / 60);
12099
+ return `${minutes}m ago`;
12100
+ } else if (diff < 86400) {
12101
+ const hours = Math.floor(diff / 3600);
12102
+ return `${hours}h ago`;
12103
+ } else {
12104
+ const days = Math.floor(diff / 86400);
12105
+ return `${days}d ago`;
12106
+ }
12107
+ }
12108
+
12109
+ /**
12110
+ * Formats a date string into a relative time string
12111
+ * @param {string} dateString - Date string to format
12112
+ * @returns {string} Formatted relative time string
12113
+ */
12114
+ function formatAge$1(dateString) {
12115
+ if (!dateString) {
12116
+ return 'N/A';
12117
+ }
12118
+
12119
+ try {
12120
+ const diff = getTimeDifference(dateString);
12121
+ return formatTimeDifference(diff);
12122
+ } catch (error) {
12123
+ console.error('Error formatting date:', error);
12124
+ return 'Invalid date';
12125
+ }
12126
+ }
12127
+
12128
+ /**
12129
+ * Validates a date string format
12130
+ * @param {string} dateString - Date string to validate
12131
+ * @returns {boolean} True if date string is valid
12132
+ */
12133
+ function isValidDateString$1(dateString) {
12134
+ if (!dateString) return false;
12135
+
12136
+ const pattern = /^\d{4}-\d{2}-\d{2}(T| )\d{2}:\d{2}:\d{2}\.\d{3}Z?$/;
12137
+ if (!pattern.test(dateString)) return false;
12138
+
12139
+ const date = new Date(normalizeDateTime(dateString));
12140
+ return date instanceof Date && !isNaN(date);
12141
+ }
12142
+
12143
+ /**
12144
+ * Compares two date strings
12145
+ * @param {string} dateA - First date string
12146
+ * @param {string} dateB - Second date string
12147
+ * @returns {number} -1 if dateA is earlier, 0 if equal, 1 if dateA is later
12148
+ */
12149
+ function compareDates$1(dateA, dateB) {
12150
+ if (!isValidDateString$1(dateA) || !isValidDateString$1(dateB)) {
12151
+ throw new Error(`Invalid date string format. A: ${dateA} B: ${dateB})`);
12152
+ }
12153
+
12154
+ const timeA = new Date(normalizeDateTime(dateA)).getTime();
12155
+ const timeB = new Date(normalizeDateTime(dateB)).getTime();
12156
+
12157
+ if (timeA < timeB) return -1;
12158
+ if (timeA > timeB) return 1;
12159
+ return 0;
12160
+ }
12161
+
12162
+ var DateUtils$1 = {
12163
+ formatAge: formatAge$1,
12164
+ isValidDateString: isValidDateString$1,
12165
+ compareDates: compareDates$1,
12166
+ normalizeDateTime,
12167
+ getTimeDifference,
12168
+ formatTimeDifference
12169
+ };
12170
+
12171
+ /**
12172
+ * Component: Formatter Utilities
12173
+ * Block-UUID: 9b1e07bf-e92c-43c1-9ac0-5dacdb7ae618
12174
+ * Parent-UUID: 9c07d12f-5a05-4402-99d2-85d872d7b2f7
12175
+ * Version: 1.0.0
12176
+ * Description: Utility functions for formatting content in GitSense Chat
12177
+ * Language: JavaScript
12178
+ * Created-at: 2025-10-11T23:27:15.420Z
12179
+ * Authors: Claude 3.7 Sonnet (v1.0.0), Claude 3.7 Sonnet (v1.1.0), Gemini 2.5 Flash Thinking (v1.2.0), Gemini 2.5 Flash Thinking (v1.3.0), Qwen 3 Coder 480B - Cerebras (v1.4.0), Qwen 3 Coder 480B - Cerebras (v1.5.0), Qwen 3 Coder 480B - Cerebras (v1.0.0)
12180
+ */
12181
+
12182
+ /**
12183
+ * Formats bytes into human-readable string (KB, MB, GB)
12184
+ * @param {number} bytes - Number of bytes
12185
+ * @returns {string} Formatted size string
12186
+ */
12187
+ function formatBytes$1(bytes) {
12188
+ if (typeof bytes !== 'number' || isNaN(bytes)) return '0 bytes';
12189
+ if (bytes === 0) return '0 bytes';
12190
+
12191
+ const k = 1024;
12192
+ const sizes = ['bytes', 'KB', 'MB', 'GB'];
12193
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
12194
+
12195
+ // Special case for bytes (no decimal)
12196
+ if (i === 0) return `${bytes} ${sizes[i]}`;
12197
+
12198
+ const value = bytes / Math.pow(k, i);
12199
+ // Show no decimal if whole number
12200
+ const decimalPlaces = value % 1 === 0 ? 0 : 1;
12201
+ return `${value.toFixed(decimalPlaces)} ${sizes[i]}`;
12202
+ }
12203
+
12204
+ /**
12205
+ * Formats token count into human-readable string (k, m, b)
12206
+ * @param {number} count - Number of tokens
12207
+ * @returns {string} Formatted token string
12208
+ */
12209
+ function formatTokens$1(count) {
12210
+ if (typeof count !== 'number' || isNaN(count)) return '0';
12211
+ if (count === 0) return '0';
12212
+
12213
+ if (count < 1000) return `${count}`;
12214
+ if (count < 1000000) return `${(count/1000).toFixed(count >= 10000 ? 1 : 0)}k`;
12215
+ if (count < 1000000000) return `${(count/1000000).toFixed(1)}m`;
12216
+
12217
+ // For billions
12218
+ return `${(count/1000000000).toFixed(1)}b`;
12219
+ }
12220
+
12221
+ var FormatterUtils$1 = {
12222
+ formatBytes: formatBytes$1,
12223
+ formatTokens: formatTokens$1
12224
+ };
12225
+
12041
12226
  /*
12042
12227
  * Component: Config Utilities
12043
12228
  * Block-UUID: 65b39008-da68-462e-bcac-27db873c9ddc
@@ -12236,13 +12421,13 @@ var EnvUtils$1 = {
12236
12421
 
12237
12422
  /*
12238
12423
  * Component: GitSenseChatUtils
12239
- * Block-UUID: 5e8d1a9c-0b3f-4e1a-8c7d-9f0b2e1d3a4b
12240
- * Parent-UUID: 7a9b1c8e-f1a4-4b2d-9e8f-6f7a0b1c2d3f
12241
- * Version: 2.1.4
12424
+ * Block-UUID: d7cdbb94-f335-4f85-bdc4-0dd3ae95127e
12425
+ * Parent-UUID: 5e8d1a9c-0b3f-4e1a-8c7d-9f0b2e1d3a4b
12426
+ * Version: 2.1.5
12242
12427
  * 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.
12243
12428
  * Language: JavaScript
12244
12429
  * Created-at: 2025-04-15T16:04:26.780Z
12245
- * 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)
12430
+ * 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), Qwen 3 Coder 480B - Cerebras (v2.1.5)
12246
12431
  */
12247
12432
 
12248
12433
  const ChatUtils = ChatUtils$1;
@@ -12255,6 +12440,8 @@ const PatchUtils = PatchUtils$2;
12255
12440
  const GSToolBlockUtils = GSToolBlockUtils$3;
12256
12441
  const LLMUtils = LLMUtils$1;
12257
12442
  const JsonUtils = JsonUtils$2;
12443
+ const DateUtils = DateUtils$1;
12444
+ const FormatterUtils = FormatterUtils$1;
12258
12445
  const ConfigUtils = ConfigUtils$1;
12259
12446
  const EnvUtils = EnvUtils$1;
12260
12447
 
@@ -12359,6 +12546,11 @@ const {
12359
12546
  getApiKey
12360
12547
  } = EnvUtils;
12361
12548
 
12549
+ const {
12550
+ formatBytes,
12551
+ formatTokens,
12552
+ } = FormatterUtils;
12553
+
12362
12554
  const {
12363
12555
  parseContextSection,
12364
12556
  extractContextSections,
@@ -12573,6 +12765,15 @@ class GitSenseChatUtils {
12573
12765
  // Export the main class, the aggregated CodeBlockUtils, PatchUtils,
12574
12766
  // and individual functions for backward compatibility or direct use.
12575
12767
  var GitSenseChatUtils_1 = {
12768
+ // New Utility Modules
12769
+ DateUtils,
12770
+ FormatterUtils,
12771
+
12772
+ // Date Utility Functions
12773
+ formatAge: DateUtils.formatAge,
12774
+ compareDates: DateUtils.compareDates,
12775
+ isValidDateString: DateUtils.isValidDateString,
12776
+
12576
12777
  // Main class
12577
12778
  GitSenseChatUtils,
12578
12779
 
@@ -12588,6 +12789,9 @@ var GitSenseChatUtils_1 = {
12588
12789
  GSToolBlockUtils,
12589
12790
  JsonUtils,
12590
12791
  ConfigUtils,
12792
+ DateUtils,
12793
+ FormatterUtils,
12794
+
12591
12795
  EnvUtils,
12592
12796
 
12593
12797
  // --- Individual Function Exports (sourced correctly) ---
@@ -12662,6 +12866,16 @@ var GitSenseChatUtils_1 = {
12662
12866
  // LLM Utils
12663
12867
  estimateTokens,
12664
12868
 
12869
+ // Date Utils
12870
+ formatAge,
12871
+ compareDates,
12872
+ isValidDateString,
12873
+
12874
+ // Formatter Utils
12875
+ formatBytes,
12876
+ formatTokens,
12877
+ formatOverviewTable,
12878
+
12665
12879
  // GS Tool Block
12666
12880
  isToolBlock,
12667
12881
  parseToolBlock,
@@ -6808,7 +6808,9 @@ function createPatchFromCodeBlocks(CodeBlockUtils, sourceCodeBlockText, targetCo
6808
6808
  const targetContent = targetContentTemp.join('\n\n');
6809
6809
 
6810
6810
  // Get the number of lines in the header + two blank lines
6811
- const sourceHeaderLineCount = sourceHeaderText.split('\n').length;
6811
+ // Note, before the code block header format was solidified, we use to include 'Updated-at' but no more so
6812
+ // we need to filter it out from the source header
6813
+ const sourceHeaderLineCount = sourceHeaderText.split('\n').filter(line => !line.includes('Updated-at')).length;
6812
6814
  const targetHeaderLineCount = targetHeaderText.split('\n').length;
6813
6815
 
6814
6816
  // To keep things simple we are going to require the source and target header line count to be the same.
@@ -6816,7 +6818,7 @@ function createPatchFromCodeBlocks(CodeBlockUtils, sourceCodeBlockText, targetCo
6816
6818
  if (sourceHeaderLineCount !== targetHeaderLineCount) {
6817
6819
  // Some LLMs will not generate a Parent-UUID for the first version so we won't make this
6818
6820
  // fatal if the sourceHeader does not have a Parent-UUID
6819
- if (sourceHeaderLineCount.includes('Parent-UUID')) {
6821
+ if (sourceHeaderText.includes('Parent-UUID')) {
6820
6822
  throw new Error('Source and target header line count must be the same');
6821
6823
  }
6822
6824
  }
@@ -10626,13 +10628,13 @@ var CodeBlockUtils$5 = {
10626
10628
 
10627
10629
  /*
10628
10630
  * Component: ContextUtils
10629
- * Block-UUID: c018b1f9-2291-4bc9-9c4b-ab53a5db745e
10630
- * Parent-UUID: c199efe3-003c-4226-af3c-d460392a6569
10631
- * Version: 1.2.0
10631
+ * Block-UUID: a0b71292-b1cc-401a-8ce2-544a047b0fef
10632
+ * Parent-UUID: c018b1f9-2291-4bc9-9c4b-ab53a5db745e
10633
+ * Version: 1.3.0
10632
10634
  * Description: Provides utility functions for parsing context message sections to extract file details and code blocks, and for formatting content for LLM context.
10633
10635
  * Language: JavaScript
10634
10636
  * Created-at: 2025-05-09T01:36:20.107Z
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)
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), Qwen 3 Coder 480B - Cerebras (v1.3.0)
10636
10638
  */
10637
10639
 
10638
10640
  const CodeBlockUtils$4 = CodeBlockUtils$5;
@@ -10813,12 +10815,26 @@ function extractContextSections$1(messageContent) {
10813
10815
  const [summary, items] = messageContent.split(/\n---Start of Context---\n\n/);
10814
10816
  const sections = items.split(/\n---End of Item---\n/);
10815
10817
 
10818
+ // Determine the origin of the context based on the message header
10819
+ let contextOrigin = 'unknown'; // Default value if not determinable
10820
+ if (messageContent.includes("## FILE CONTENT - WORKING DIRECTORY")) {
10821
+ contextOrigin = 'working-directory';
10822
+ } else if (messageContent.includes("## FILE CONTENT - IMPORTED")) {
10823
+ contextOrigin = 'imported';
10824
+ } else if (messageContent.includes("## OVERVIEW - IMPORTED")) {
10825
+ // Handle the overview case as well, though it uses 'file content' type
10826
+ contextOrigin = 'imported';
10827
+ }
10828
+
10816
10829
  // Process sections starting from the first potential path delimiter.
10817
10830
  for (let i = 0; i < sections.length; i++) {
10818
10831
  const contextSection = parseContextSection$1(sections[i]);
10819
10832
 
10820
10833
  if (contextSection) {
10821
10834
  contextSections.push(contextSection);
10835
+ // Attach the determined context origin to the section
10836
+ // This provides information on how the context was introduced
10837
+ contextSection.contextOrigin = contextOrigin;
10822
10838
  }
10823
10839
  }
10824
10840
 
@@ -10839,6 +10855,7 @@ function extractContextItemsOverviewTableRows$1(messageContent) {
10839
10855
  return null;
10840
10856
  }
10841
10857
 
10858
+ // Map the column number to the type
10842
10859
  const col2Field = {
10843
10860
  1: 'chatId',
10844
10861
  2: 'type', // file, tree, etc.
@@ -12036,6 +12053,174 @@ var LLMUtils$1 = {
12036
12053
  estimateTokens: estimateTokens$1,
12037
12054
  };
12038
12055
 
12056
+ /**
12057
+ * Component: Date Utilities
12058
+ * Block-UUID: fef3b0f4-8055-4690-9336-e68a9cc33a61
12059
+ * Parent-UUID: 716e5ce9-84df-4f12-89e7-4a28e4a39a81
12060
+ * Version: 1.0.0
12061
+ * Description: Date formatting and manipulation utilities for GitSense Chat
12062
+ * Language: JavaScript
12063
+ * Created-at: 2025-10-11T23:26:20.815Z
12064
+ * Authors: Claude-3.5-Sonnet (v1.0.0), Qwen 3 Coder 480B - Cerebras (v1.0.0)
12065
+ */
12066
+
12067
+ /**
12068
+ * Ensures a date string has a timezone indicator
12069
+ * @param {string} dateString - Date string in format "YYYY-MM-DD(T| )HH:mm:ss.SSS"
12070
+ * @returns {string} Date string with 'Z' timezone indicator if not present
12071
+ */
12072
+ function normalizeDateTime(dateString) {
12073
+ return dateString.includes('Z') ? dateString : dateString + 'Z';
12074
+ }
12075
+
12076
+ /**
12077
+ * Calculates the time difference between now and a given date
12078
+ * @param {string} dateString - Date string to compare against current time
12079
+ * @returns {number} Difference in seconds
12080
+ */
12081
+ function getTimeDifference(dateString) {
12082
+ const now = new Date();
12083
+ const date = new Date(normalizeDateTime(dateString));
12084
+ return Math.floor((now - date) / 1000);
12085
+ }
12086
+
12087
+ /**
12088
+ * Formats a time difference in seconds to a human-readable string
12089
+ * @param {number} diff - Time difference in seconds
12090
+ * @returns {string} Formatted string (e.g., "5s ago", "2m ago", "3h ago", "2d ago")
12091
+ */
12092
+ function formatTimeDifference(diff) {
12093
+ if (diff < 60) {
12094
+ return `${diff}s ago`;
12095
+ } else if (diff < 3600) {
12096
+ const minutes = Math.floor(diff / 60);
12097
+ return `${minutes}m ago`;
12098
+ } else if (diff < 86400) {
12099
+ const hours = Math.floor(diff / 3600);
12100
+ return `${hours}h ago`;
12101
+ } else {
12102
+ const days = Math.floor(diff / 86400);
12103
+ return `${days}d ago`;
12104
+ }
12105
+ }
12106
+
12107
+ /**
12108
+ * Formats a date string into a relative time string
12109
+ * @param {string} dateString - Date string to format
12110
+ * @returns {string} Formatted relative time string
12111
+ */
12112
+ function formatAge$1(dateString) {
12113
+ if (!dateString) {
12114
+ return 'N/A';
12115
+ }
12116
+
12117
+ try {
12118
+ const diff = getTimeDifference(dateString);
12119
+ return formatTimeDifference(diff);
12120
+ } catch (error) {
12121
+ console.error('Error formatting date:', error);
12122
+ return 'Invalid date';
12123
+ }
12124
+ }
12125
+
12126
+ /**
12127
+ * Validates a date string format
12128
+ * @param {string} dateString - Date string to validate
12129
+ * @returns {boolean} True if date string is valid
12130
+ */
12131
+ function isValidDateString$1(dateString) {
12132
+ if (!dateString) return false;
12133
+
12134
+ const pattern = /^\d{4}-\d{2}-\d{2}(T| )\d{2}:\d{2}:\d{2}\.\d{3}Z?$/;
12135
+ if (!pattern.test(dateString)) return false;
12136
+
12137
+ const date = new Date(normalizeDateTime(dateString));
12138
+ return date instanceof Date && !isNaN(date);
12139
+ }
12140
+
12141
+ /**
12142
+ * Compares two date strings
12143
+ * @param {string} dateA - First date string
12144
+ * @param {string} dateB - Second date string
12145
+ * @returns {number} -1 if dateA is earlier, 0 if equal, 1 if dateA is later
12146
+ */
12147
+ function compareDates$1(dateA, dateB) {
12148
+ if (!isValidDateString$1(dateA) || !isValidDateString$1(dateB)) {
12149
+ throw new Error(`Invalid date string format. A: ${dateA} B: ${dateB})`);
12150
+ }
12151
+
12152
+ const timeA = new Date(normalizeDateTime(dateA)).getTime();
12153
+ const timeB = new Date(normalizeDateTime(dateB)).getTime();
12154
+
12155
+ if (timeA < timeB) return -1;
12156
+ if (timeA > timeB) return 1;
12157
+ return 0;
12158
+ }
12159
+
12160
+ var DateUtils$1 = {
12161
+ formatAge: formatAge$1,
12162
+ isValidDateString: isValidDateString$1,
12163
+ compareDates: compareDates$1,
12164
+ normalizeDateTime,
12165
+ getTimeDifference,
12166
+ formatTimeDifference
12167
+ };
12168
+
12169
+ /**
12170
+ * Component: Formatter Utilities
12171
+ * Block-UUID: 9b1e07bf-e92c-43c1-9ac0-5dacdb7ae618
12172
+ * Parent-UUID: 9c07d12f-5a05-4402-99d2-85d872d7b2f7
12173
+ * Version: 1.0.0
12174
+ * Description: Utility functions for formatting content in GitSense Chat
12175
+ * Language: JavaScript
12176
+ * Created-at: 2025-10-11T23:27:15.420Z
12177
+ * Authors: Claude 3.7 Sonnet (v1.0.0), Claude 3.7 Sonnet (v1.1.0), Gemini 2.5 Flash Thinking (v1.2.0), Gemini 2.5 Flash Thinking (v1.3.0), Qwen 3 Coder 480B - Cerebras (v1.4.0), Qwen 3 Coder 480B - Cerebras (v1.5.0), Qwen 3 Coder 480B - Cerebras (v1.0.0)
12178
+ */
12179
+
12180
+ /**
12181
+ * Formats bytes into human-readable string (KB, MB, GB)
12182
+ * @param {number} bytes - Number of bytes
12183
+ * @returns {string} Formatted size string
12184
+ */
12185
+ function formatBytes$1(bytes) {
12186
+ if (typeof bytes !== 'number' || isNaN(bytes)) return '0 bytes';
12187
+ if (bytes === 0) return '0 bytes';
12188
+
12189
+ const k = 1024;
12190
+ const sizes = ['bytes', 'KB', 'MB', 'GB'];
12191
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
12192
+
12193
+ // Special case for bytes (no decimal)
12194
+ if (i === 0) return `${bytes} ${sizes[i]}`;
12195
+
12196
+ const value = bytes / Math.pow(k, i);
12197
+ // Show no decimal if whole number
12198
+ const decimalPlaces = value % 1 === 0 ? 0 : 1;
12199
+ return `${value.toFixed(decimalPlaces)} ${sizes[i]}`;
12200
+ }
12201
+
12202
+ /**
12203
+ * Formats token count into human-readable string (k, m, b)
12204
+ * @param {number} count - Number of tokens
12205
+ * @returns {string} Formatted token string
12206
+ */
12207
+ function formatTokens$1(count) {
12208
+ if (typeof count !== 'number' || isNaN(count)) return '0';
12209
+ if (count === 0) return '0';
12210
+
12211
+ if (count < 1000) return `${count}`;
12212
+ if (count < 1000000) return `${(count/1000).toFixed(count >= 10000 ? 1 : 0)}k`;
12213
+ if (count < 1000000000) return `${(count/1000000).toFixed(1)}m`;
12214
+
12215
+ // For billions
12216
+ return `${(count/1000000000).toFixed(1)}b`;
12217
+ }
12218
+
12219
+ var FormatterUtils$1 = {
12220
+ formatBytes: formatBytes$1,
12221
+ formatTokens: formatTokens$1
12222
+ };
12223
+
12039
12224
  /*
12040
12225
  * Component: Config Utilities
12041
12226
  * Block-UUID: 65b39008-da68-462e-bcac-27db873c9ddc
@@ -12234,13 +12419,13 @@ var EnvUtils$1 = {
12234
12419
 
12235
12420
  /*
12236
12421
  * Component: GitSenseChatUtils
12237
- * Block-UUID: 5e8d1a9c-0b3f-4e1a-8c7d-9f0b2e1d3a4b
12238
- * Parent-UUID: 7a9b1c8e-f1a4-4b2d-9e8f-6f7a0b1c2d3f
12239
- * Version: 2.1.4
12422
+ * Block-UUID: d7cdbb94-f335-4f85-bdc4-0dd3ae95127e
12423
+ * Parent-UUID: 5e8d1a9c-0b3f-4e1a-8c7d-9f0b2e1d3a4b
12424
+ * Version: 2.1.5
12240
12425
  * 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.
12241
12426
  * Language: JavaScript
12242
12427
  * Created-at: 2025-04-15T16:04:26.780Z
12243
- * 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)
12428
+ * 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), Qwen 3 Coder 480B - Cerebras (v2.1.5)
12244
12429
  */
12245
12430
 
12246
12431
  const ChatUtils = ChatUtils$1;
@@ -12253,6 +12438,8 @@ const PatchUtils = PatchUtils$2;
12253
12438
  const GSToolBlockUtils = GSToolBlockUtils$3;
12254
12439
  const LLMUtils = LLMUtils$1;
12255
12440
  const JsonUtils = JsonUtils$2;
12441
+ const DateUtils = DateUtils$1;
12442
+ const FormatterUtils = FormatterUtils$1;
12256
12443
  const ConfigUtils = ConfigUtils$1;
12257
12444
  const EnvUtils = EnvUtils$1;
12258
12445
 
@@ -12357,6 +12544,11 @@ const {
12357
12544
  getApiKey
12358
12545
  } = EnvUtils;
12359
12546
 
12547
+ const {
12548
+ formatBytes,
12549
+ formatTokens,
12550
+ } = FormatterUtils;
12551
+
12360
12552
  const {
12361
12553
  parseContextSection,
12362
12554
  extractContextSections,
@@ -12571,6 +12763,15 @@ class GitSenseChatUtils {
12571
12763
  // Export the main class, the aggregated CodeBlockUtils, PatchUtils,
12572
12764
  // and individual functions for backward compatibility or direct use.
12573
12765
  var GitSenseChatUtils_1 = {
12766
+ // New Utility Modules
12767
+ DateUtils,
12768
+ FormatterUtils,
12769
+
12770
+ // Date Utility Functions
12771
+ formatAge: DateUtils.formatAge,
12772
+ compareDates: DateUtils.compareDates,
12773
+ isValidDateString: DateUtils.isValidDateString,
12774
+
12574
12775
  // Main class
12575
12776
  GitSenseChatUtils,
12576
12777
 
@@ -12586,6 +12787,9 @@ var GitSenseChatUtils_1 = {
12586
12787
  GSToolBlockUtils,
12587
12788
  JsonUtils,
12588
12789
  ConfigUtils,
12790
+ DateUtils,
12791
+ FormatterUtils,
12792
+
12589
12793
  EnvUtils,
12590
12794
 
12591
12795
  // --- Individual Function Exports (sourced correctly) ---
@@ -12660,6 +12864,16 @@ var GitSenseChatUtils_1 = {
12660
12864
  // LLM Utils
12661
12865
  estimateTokens,
12662
12866
 
12867
+ // Date Utils
12868
+ formatAge,
12869
+ compareDates,
12870
+ isValidDateString,
12871
+
12872
+ // Formatter Utils
12873
+ formatBytes,
12874
+ formatTokens,
12875
+ formatOverviewTable,
12876
+
12663
12877
  // GS Tool Block
12664
12878
  isToolBlock,
12665
12879
  parseToolBlock,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitsense/gsc-utils",
3
- "version": "0.2.21",
3
+ "version": "0.2.23",
4
4
  "description": "Utilities for GitSense Chat (GSC)",
5
5
  "main": "dist/gsc-utils.cjs.js",
6
6
  "module": "dist/gsc-utils.esm.js",