@gitsense/gsc-utils 0.2.34 → 0.2.36

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.
@@ -1424,7 +1424,10 @@ function parseOverviewMetadata$1(content) {
1424
1424
  const lines = content.split('\n');
1425
1425
 
1426
1426
  // Regex to capture "Field Name" and "Value" from lines like '* **Field Name: ** Value'
1427
- const fieldRegex = /^\*\s+\*\*([\w\s.-]+):\*\*\s+(.*)$/;
1427
+ const fieldRegex1 = /^\*\s+\*\*([\w\s.-]+):\*\*\s+(.*)$/;
1428
+ const fieldRegex2 = /^\*\s+\*\*([\w\s.-]+)\*\*:\s+(.*)$/;
1429
+ const fieldRegex3 = /^.*?(Chat ID|Path).*:\s*(\d+)$/m;
1430
+
1428
1431
  let foundList = false;
1429
1432
  let currentKey = null; // For potential multi-line handling in the future
1430
1433
 
@@ -1440,7 +1443,7 @@ function parseOverviewMetadata$1(content) {
1440
1443
  break;
1441
1444
  }
1442
1445
 
1443
- const match = trimmedLine.match(fieldRegex);
1446
+ const match = trimmedLine.match(fieldRegex1) || trimmedLine.match(fieldRegex2) || trimmedLine.match(fieldRegex3);
1444
1447
 
1445
1448
  if (match) {
1446
1449
  foundList = true;
@@ -9959,7 +9962,7 @@ function fixTextCodeBlocks$2(text) {
9959
9962
  const [fieldPart, valuePart] = line.split(':').map(p => p.trim());
9960
9963
 
9961
9964
  // Skip if N/A or contains unexpected characters
9962
- if (valuePart === 'N/A' || valuePart.match(/\(/)) {
9965
+ if (valuePart === 'N/A' || !valuePart.match(/\w-/)) {
9963
9966
  return line;
9964
9967
  }
9965
9968
  // Validate UUID
@@ -10998,7 +11001,7 @@ const { formatWithLineNumbers: formatWithLineNumbers$1, formatBlockWithLineNumbe
10998
11001
  const { getLineage: getLineage$1 } = lineageTracer;
10999
11002
 
11000
11003
  // Export all imported items
11001
- var CodeBlockUtils$7 = {
11004
+ var CodeBlockUtils$8 = {
11002
11005
  // Constants
11003
11006
  COMMENT_STYLES: COMMENT_STYLES$1,
11004
11007
 
@@ -11058,6 +11061,302 @@ var CodeBlockUtils$7 = {
11058
11061
  removeLineNumbers: removeLineNumbers$1,
11059
11062
  };
11060
11063
 
11064
+ /**
11065
+ * Component: Date Utilities
11066
+ * Block-UUID: fef3b0f4-8055-4690-9336-e68a9cc33a61
11067
+ * Parent-UUID: 716e5ce9-84df-4f12-89e7-4a28e4a39a81
11068
+ * Version: 1.0.0
11069
+ * Description: Date formatting and manipulation utilities for GitSense Chat
11070
+ * Language: JavaScript
11071
+ * Created-at: 2025-10-11T23:26:20.815Z
11072
+ * Authors: Claude-3.5-Sonnet (v1.0.0), Qwen 3 Coder 480B - Cerebras (v1.0.0)
11073
+ */
11074
+
11075
+ /**
11076
+ * Ensures a date string has a timezone indicator
11077
+ * @param {string} dateString - Date string in format "YYYY-MM-DD(T| )HH:mm:ss.SSS"
11078
+ * @returns {string} Date string with 'Z' timezone indicator if not present
11079
+ */
11080
+ function normalizeDateTime$1(dateString) {
11081
+ return dateString.includes('Z') ? dateString : dateString + 'Z';
11082
+ }
11083
+
11084
+ /**
11085
+ * Calculates the time difference between now and a given date
11086
+ * @param {string} dateString - Date string to compare against current time
11087
+ * @returns {number} Difference in seconds
11088
+ */
11089
+ function getTimeDifference$1(dateString) {
11090
+ const now = new Date();
11091
+ const date = new Date(normalizeDateTime$1(dateString));
11092
+ return Math.floor((now - date) / 1000);
11093
+ }
11094
+
11095
+ /**
11096
+ * Formats a time difference in seconds to a human-readable string
11097
+ * @param {number} diff - Time difference in seconds
11098
+ * @returns {string} Formatted string (e.g., "5s ago", "2m ago", "3h ago", "2d ago")
11099
+ */
11100
+ function formatTimeDifference$1(diff) {
11101
+ if (diff < 60) {
11102
+ return `${diff}s ago`;
11103
+ } else if (diff < 3600) {
11104
+ const minutes = Math.floor(diff / 60);
11105
+ return `${minutes}m ago`;
11106
+ } else if (diff < 86400) {
11107
+ const hours = Math.floor(diff / 3600);
11108
+ return `${hours}h ago`;
11109
+ } else {
11110
+ const days = Math.floor(diff / 86400);
11111
+ return `${days}d ago`;
11112
+ }
11113
+ }
11114
+
11115
+ /**
11116
+ * Formats a date string into a relative time string
11117
+ * @param {string} dateString - Date string to format
11118
+ * @returns {string} Formatted relative time string
11119
+ */
11120
+ function formatAge$1(dateString) {
11121
+ if (!dateString) {
11122
+ return 'N/A';
11123
+ }
11124
+
11125
+ try {
11126
+ const diff = getTimeDifference$1(dateString);
11127
+ return formatTimeDifference$1(diff);
11128
+ } catch (error) {
11129
+ console.error('Error formatting date:', error);
11130
+ return 'Invalid date';
11131
+ }
11132
+ }
11133
+
11134
+ /**
11135
+ * Validates a date string format
11136
+ * @param {string} dateString - Date string to validate
11137
+ * @returns {boolean} True if date string is valid
11138
+ */
11139
+ function isValidDateString$1(dateString) {
11140
+ if (!dateString) return false;
11141
+
11142
+ const pattern = /^\d{4}-\d{2}-\d{2}(T| )\d{2}:\d{2}:\d{2}\.\d{3}Z?$/;
11143
+ if (!pattern.test(dateString)) return false;
11144
+
11145
+ const date = new Date(normalizeDateTime$1(dateString));
11146
+ return date instanceof Date && !isNaN(date);
11147
+ }
11148
+
11149
+ /**
11150
+ * Compares two date strings
11151
+ * @param {string} dateA - First date string
11152
+ * @param {string} dateB - Second date string
11153
+ * @returns {number} -1 if dateA is earlier, 0 if equal, 1 if dateA is later
11154
+ */
11155
+ function compareDates$1(dateA, dateB) {
11156
+ if (!isValidDateString$1(dateA) || !isValidDateString$1(dateB)) {
11157
+ throw new Error(`Invalid date string format. A: ${dateA} B: ${dateB})`);
11158
+ }
11159
+
11160
+ const timeA = new Date(normalizeDateTime$1(dateA)).getTime();
11161
+ const timeB = new Date(normalizeDateTime$1(dateB)).getTime();
11162
+
11163
+ if (timeA < timeB) return -1;
11164
+ if (timeA > timeB) return 1;
11165
+ return 0;
11166
+ }
11167
+
11168
+ var DateUtils$1 = {
11169
+ formatAge: formatAge$1,
11170
+ isValidDateString: isValidDateString$1,
11171
+ compareDates: compareDates$1,
11172
+ normalizeDateTime: normalizeDateTime$1,
11173
+ getTimeDifference: getTimeDifference$1,
11174
+ formatTimeDifference: formatTimeDifference$1
11175
+ };
11176
+
11177
+ /**
11178
+ * Component: CLI Contract Utilities
11179
+ * Block-UUID: a57b72a0-0d95-44a2-8f3f-ab6ee84b3197
11180
+ * Parent-UUID: 9050e244-793a-4dc6-8571-b96f38927f69
11181
+ * Version: 1.1.0
11182
+ * Description: Utilities for parsing GitSense Chat CLI contract messages and determining save modes for code blocks.
11183
+ * Language: JavaScript
11184
+ * Created-at: 2026-02-27T02:26:15.078Z
11185
+ * Authors: GLM-4.7 (v1.0.0), GLM-4.7 (v1.1.0)
11186
+ */
11187
+
11188
+ const CodeBlockUtils$7 = CodeBlockUtils$8;
11189
+
11190
+ /**
11191
+ * Parses a contract message object to extract the contract data.
11192
+ * Handles cases where data might be in 'content' (as JSON string) or 'metadata'.
11193
+ *
11194
+ * @param {Object} message - The chat message object.
11195
+ * @returns {Object|null} The parsed contract data object or null if invalid.
11196
+ */
11197
+ function parseContractMessage(message) {
11198
+ if (!message) {
11199
+ return null;
11200
+ }
11201
+
11202
+ // We expect the message type to be 'gsc-cli-contract'
11203
+ if (message.type !== 'gsc-cli-contract') {
11204
+ return null;
11205
+ }
11206
+
11207
+ const content = message.message || '';
11208
+ const lines = content.split('\n');
11209
+
11210
+ const contractData = {};
11211
+ let inTable = false;
11212
+ let foundHeader = false;
11213
+
11214
+ for (let i = 0; i < lines.length; i++) {
11215
+ const line = lines[i].trim();
11216
+
11217
+ // Check for the CLI Contract header
11218
+ if (line.startsWith('### CLI Contract')) {
11219
+ foundHeader = true;
11220
+ continue;
11221
+ }
11222
+
11223
+ // If we haven't found the header yet, keep looking
11224
+ if (!foundHeader) {
11225
+ continue;
11226
+ }
11227
+
11228
+ // Check for table separator (e.g., | :--- | :--- |)
11229
+ if (line.includes('---')) {
11230
+ inTable = true;
11231
+ continue;
11232
+ }
11233
+
11234
+ // Parse table rows
11235
+ if (inTable && line.startsWith('|')) {
11236
+ // Remove leading/trailing pipes and split by pipe
11237
+ const parts = line.substring(1, line.length - 1).split('|').map(p => p.trim());
11238
+
11239
+ if (parts.length >= 2) {
11240
+ const key = parts[0].replace(/\*\*/g, '').toLowerCase(); // Remove bold markdown and normalize
11241
+ const value = parts[1];
11242
+
11243
+ if (key === 'uuid') contractData.uuid = value;
11244
+ else if (key === 'expires at') contractData.expiresAt = value;
11245
+ else if (key === 'status') contractData.status = value;
11246
+ else if (key === 'description') contractData.description = value;
11247
+ }
11248
+ }
11249
+ }
11250
+
11251
+ return contractData;
11252
+ }
11253
+
11254
+ /**
11255
+ * Checks if a message is a contract message.
11256
+ *
11257
+ * @param {Object} message - The chat message object.
11258
+ * @returns {boolean} True if the message is a contract message.
11259
+ */
11260
+ function isContractMessage(message) {
11261
+ return message && message.type === 'gsc-cli-contract';
11262
+ }
11263
+
11264
+ /**
11265
+ * Determines if a contract is currently active based on its expiration time.
11266
+ *
11267
+ * @param {Object} contractData - The contract data object (must contain expiresAt).
11268
+ * @returns {boolean} True if the contract is active, false otherwise.
11269
+ */
11270
+ function isContractActive(contractData) {
11271
+ if (!contractData || !contractData.expiresAt) {
11272
+ return false;
11273
+ }
11274
+
11275
+ const now = Date.now();
11276
+ const expiresAt = new Date(contractData.expiresAt).getTime();
11277
+
11278
+ return now < expiresAt;
11279
+ }
11280
+
11281
+ /**
11282
+ * Determines the save mode (update vs new-file) based on the code content.
11283
+ * Parses the code block header to check for a Parent-UUID.
11284
+ *
11285
+ * @param {string} rawCodeContent - The full content of the code block (including header).
11286
+ * @returns {Object} An object { mode: 'update'|'new-file', metadata: Object }.
11287
+ */
11288
+ function determineSaveMode(rawCodeContent) {
11289
+ const { blocks } = CodeBlockUtils$7.processCodeBlocks(rawCodeContent, { silent: true });
11290
+
11291
+ if (!blocks || blocks.length === 0) {
11292
+ return { mode: 'unknown', metadata: null };
11293
+ }
11294
+
11295
+ const block = blocks[0];
11296
+ const header = block.header || {};
11297
+ const parentUUID = header['Parent-UUID'];
11298
+
11299
+ let mode = 'new-file';
11300
+
11301
+ // If Parent-UUID exists and is not N/A, it's an update
11302
+ if (parentUUID && parentUUID !== 'N/A') {
11303
+ mode = 'update';
11304
+ }
11305
+
11306
+ return {
11307
+ mode,
11308
+ metadata: {
11309
+ blockUUID: header['Block-UUID'],
11310
+ parentUUID: parentUUID,
11311
+ language: block.language
11312
+ }
11313
+ };
11314
+ }
11315
+
11316
+ /**
11317
+ * Extracts key metadata from a code block content.
11318
+ *
11319
+ * @param {string} rawCodeContent - The full content of the code block.
11320
+ * @returns {Object|null} Metadata object or null if parsing fails.
11321
+ */
11322
+ function extractCodeMetadata(rawCodeContent) {
11323
+ const result = determineSaveMode(rawCodeContent);
11324
+ return result.metadata;
11325
+ }
11326
+
11327
+ /**
11328
+ * Formats the remaining time until expiration.
11329
+ *
11330
+ * @param {string|Date} expiresAt - The expiration timestamp.
11331
+ * @returns {string} Formatted string (e.g., "45m", "2h", "1d").
11332
+ */
11333
+ function formatTimeRemaining(expiresAt) {
11334
+ const now = Date.now();
11335
+ const expiry = new Date(expiresAt).getTime();
11336
+ const diffMs = expiry - now;
11337
+
11338
+ if (diffMs <= 0) return 'Expired';
11339
+
11340
+ const diffMins = Math.floor(diffMs / 60000);
11341
+
11342
+ if (diffMins < 60) return `${diffMins}m`;
11343
+
11344
+ const diffHours = Math.floor(diffMins / 60);
11345
+ if (diffHours < 24) return `${diffHours}h`;
11346
+
11347
+ const diffDays = Math.floor(diffHours / 24);
11348
+ return `${diffDays}d`;
11349
+ }
11350
+
11351
+ var CLIContractUtils$1 = {
11352
+ parseContractMessage,
11353
+ isContractMessage,
11354
+ isContractActive,
11355
+ determineSaveMode,
11356
+ extractCodeMetadata,
11357
+ formatTimeRemaining
11358
+ };
11359
+
11061
11360
  /*
11062
11361
  * Component: ContextUtils
11063
11362
  * Block-UUID: 534c348d-a11f-4de6-ad15-f33068d51fb8
@@ -11069,7 +11368,7 @@ var CodeBlockUtils$7 = {
11069
11368
  * 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), Qwen 3 Coder 480B - Cerebras (v1.4.0)
11070
11369
  */
11071
11370
 
11072
- const CodeBlockUtils$6 = CodeBlockUtils$7;
11371
+ const CodeBlockUtils$6 = CodeBlockUtils$8;
11073
11372
  const MessageUtils$2 = MessageUtils$3;
11074
11373
 
11075
11374
  /**
@@ -11529,7 +11828,7 @@ var constants = {
11529
11828
  * Authors: Gemini 2.5 Flash (v1.0.0)
11530
11829
  */
11531
11830
 
11532
- const CodeBlockUtils$5 = CodeBlockUtils$7;
11831
+ const CodeBlockUtils$5 = CodeBlockUtils$8;
11533
11832
  const GSToolBlockUtils$1 = GSToolBlockUtils$3;
11534
11833
  const JsonUtils$1 = JsonUtils$2;
11535
11834
  const { ANALYZE_HEADER_PREFIX } = constants;
@@ -11839,7 +12138,7 @@ const fs$7 = require$$0.promises;
11839
12138
  const path$5 = require$$1;
11840
12139
  const { getAnalyzerInstructionsContent: getAnalyzerInstructionsContent$2 } = instructionLoader;
11841
12140
  const { preprocessJsonForValidation: preprocessJsonForValidation$4 } = jsonParser;
11842
- const CodeBlockUtils$4 = CodeBlockUtils$7;
12141
+ const CodeBlockUtils$4 = CodeBlockUtils$8;
11843
12142
 
11844
12143
  /**
11845
12144
  * Reads and parses the config.json file in a directory.
@@ -12135,18 +12434,18 @@ var saver = {
12135
12434
 
12136
12435
  /**
12137
12436
  * Component: AnalyzerUtils Schema Loader
12138
- * Block-UUID: bf25c501-f9e1-4e5b-ad22-9ed24ba50787
12139
- * Parent-UUID: 66208fdc-2c80-4264-8500-06d5f4db103a
12140
- * Version: 1.4.1
12437
+ * Block-UUID: 20ac37ba-6ff7-462e-9e08-3204df118b03
12438
+ * Parent-UUID: bf25c501-f9e1-4e5b-ad22-9ed24ba50787
12439
+ * Version: 1.5.0
12141
12440
  * Description: Provides utility functions for retrieving and deducing JSON schemas for analyzers.
12142
12441
  * Language: JavaScript
12143
- * Created-at: 2025-11-23T05:40:43.016Z
12144
- * Authors: Gemini 2.5 Flash (v1.0.0), Gemini 2.5 Pro (v1.1.0), Claude Haiku 4.5 (v1.2.0), Claude Haiku 4.5 (v1.3.0), Qwen 3 Coder 480B - Cerebras (v1.4.0), GLM-4.6 (v1.4.1)
12442
+ * Created-at: 2026-02-15T06:21:20.089Z
12443
+ * Authors: Gemini 2.5 Flash (v1.0.0), Gemini 2.5 Pro (v1.1.0), Claude Haiku 4.5 (v1.2.0), Claude Haiku 4.5 (v1.3.0), Qwen 3 Coder 480B - Cerebras (v1.4.0), GLM-4.6 (v1.4.1), GLM-4.7 (v1.5.0)
12145
12444
  */
12146
12445
 
12147
12446
  const fs$5 = require$$0.promises;
12148
12447
  const path$3 = require$$1;
12149
- const CodeBlockUtils$3 = CodeBlockUtils$7;
12448
+ const CodeBlockUtils$3 = CodeBlockUtils$8;
12150
12449
  const { preprocessJsonForValidation: preprocessJsonForValidation$3 } = jsonParser;
12151
12450
 
12152
12451
  /**
@@ -12161,35 +12460,39 @@ const { preprocessJsonForValidation: preprocessJsonForValidation$3 } = jsonParse
12161
12460
  function parseMetadataDefinitions(markdownContent) {
12162
12461
  const definitions = new Map();
12163
12462
 
12164
- // Match the "### Custom Metadata Definitions" section until the next code block or section
12165
- const sectionRegex = /### Custom Metadata Definitions\s*([\s\S]*?)(?=```|\n##|\n---)/;
12166
- const match = markdownContent.match(sectionRegex);
12167
-
12168
- if (!match || !match[1]) {
12169
- return definitions;
12170
- }
12171
-
12172
- const definitionBlock = match[1];
12463
+ // Match both "### Fixed Metadata Definitions" and "### Custom Metadata Definitions" sections
12464
+ const sectionHeaders = ['### Fixed Metadata Definitions', '### Custom Metadata Definitions'];
12173
12465
 
12174
- // Regex to match both formats:
12175
- // Format 1: * `fieldName` (type): description
12176
- // Format 2: * fieldName (type): description
12177
- // Capture groups:
12178
- // Group 1: backtick-wrapped field name (if present)
12179
- // Group 2: non-backtick field name (if present)
12180
- // Group 3: field type
12181
- // Group 4: description
12182
- const lineRegex = /^\s*\*\s+(?:`([^`]+)`|([a-zA-Z0-9_-]+))\s+\(([^)]+)\):\s*(.+)/gm;
12466
+ for (const sectionHeader of sectionHeaders) {
12467
+ const sectionRegex = new RegExp(`${sectionHeader}\\s*([\\s\\S]*?)(?=\`\`\\|\\n##|\\n---)`);
12468
+ const match = markdownContent.match(sectionRegex);
12183
12469
 
12184
- let lineMatch;
12185
- while ((lineMatch = lineRegex.exec(definitionBlock)) !== null) {
12186
- // Extract field name from either group 1 (backtick-wrapped) or group 2 (plain)
12187
- const fieldName = (lineMatch[1] || lineMatch[2]).trim();
12188
- const fieldType = lineMatch[3].trim();
12189
- const description = lineMatch[4].trim();
12470
+ if (!match || !match[1]) {
12471
+ continue;
12472
+ }
12190
12473
 
12191
- if (fieldName && fieldType && description) {
12192
- definitions.set(fieldName, { type: fieldType, description });
12474
+ const definitionBlock = match[1];
12475
+
12476
+ // Regex to match both formats:
12477
+ // Format 1: * `fieldName` (type): description
12478
+ // Format 2: * fieldName (type): description
12479
+ // Capture groups:
12480
+ // Group 1: backtick-wrapped field name (if present)
12481
+ // Group 2: non-backtick field name (if present)
12482
+ // Group 3: field type
12483
+ // Group 4: description
12484
+ const lineRegex = /^\s*\*\s+(?:`([^`]+)`|([a-zA-Z0-9_-]+))\s+\(([^)]+)\):\s*(.+)/gm;
12485
+
12486
+ let lineMatch;
12487
+ while ((lineMatch = lineRegex.exec(definitionBlock)) !== null) {
12488
+ // Extract field name from either group 1 (backtick-wrapped) or group 2 (plain)
12489
+ const fieldName = (lineMatch[1] || lineMatch[2]).trim();
12490
+ const fieldType = lineMatch[3].trim();
12491
+ const description = lineMatch[4].trim();
12492
+
12493
+ if (fieldName && fieldType && description) {
12494
+ definitions.set(fieldName, { type: fieldType, description });
12495
+ }
12193
12496
  }
12194
12497
  }
12195
12498
 
@@ -12620,7 +12923,7 @@ var defaultPromptLoader = {
12620
12923
 
12621
12924
  const fs$2 = require$$0.promises;
12622
12925
  const path = require$$1;
12623
- const CodeBlockUtils$2 = CodeBlockUtils$7;
12926
+ const CodeBlockUtils$2 = CodeBlockUtils$8;
12624
12927
  const { preprocessJsonForValidation: preprocessJsonForValidation$2 } = jsonParser;
12625
12928
  const { isValidDirName: isValidDirName$1 } = discovery;
12626
12929
  const { readConfig } = discovery;
@@ -12806,7 +13109,7 @@ var updater = {
12806
13109
  */
12807
13110
 
12808
13111
  require$$0.promises;
12809
- const CodeBlockUtils$1 = CodeBlockUtils$7;
13112
+ const CodeBlockUtils$1 = CodeBlockUtils$8;
12810
13113
  const { preprocessJsonForValidation: preprocessJsonForValidation$1 } = jsonParser;
12811
13114
  const { isValidDirName } = discovery;
12812
13115
  const { saveConfiguration: saveConfiguration$1 } = saver;
@@ -13013,119 +13316,6 @@ var LLMUtils$1 = {
13013
13316
  estimateTokens: estimateTokens$1,
13014
13317
  };
13015
13318
 
13016
- /**
13017
- * Component: Date Utilities
13018
- * Block-UUID: fef3b0f4-8055-4690-9336-e68a9cc33a61
13019
- * Parent-UUID: 716e5ce9-84df-4f12-89e7-4a28e4a39a81
13020
- * Version: 1.0.0
13021
- * Description: Date formatting and manipulation utilities for GitSense Chat
13022
- * Language: JavaScript
13023
- * Created-at: 2025-10-11T23:26:20.815Z
13024
- * Authors: Claude-3.5-Sonnet (v1.0.0), Qwen 3 Coder 480B - Cerebras (v1.0.0)
13025
- */
13026
-
13027
- /**
13028
- * Ensures a date string has a timezone indicator
13029
- * @param {string} dateString - Date string in format "YYYY-MM-DD(T| )HH:mm:ss.SSS"
13030
- * @returns {string} Date string with 'Z' timezone indicator if not present
13031
- */
13032
- function normalizeDateTime$1(dateString) {
13033
- return dateString.includes('Z') ? dateString : dateString + 'Z';
13034
- }
13035
-
13036
- /**
13037
- * Calculates the time difference between now and a given date
13038
- * @param {string} dateString - Date string to compare against current time
13039
- * @returns {number} Difference in seconds
13040
- */
13041
- function getTimeDifference$1(dateString) {
13042
- const now = new Date();
13043
- const date = new Date(normalizeDateTime$1(dateString));
13044
- return Math.floor((now - date) / 1000);
13045
- }
13046
-
13047
- /**
13048
- * Formats a time difference in seconds to a human-readable string
13049
- * @param {number} diff - Time difference in seconds
13050
- * @returns {string} Formatted string (e.g., "5s ago", "2m ago", "3h ago", "2d ago")
13051
- */
13052
- function formatTimeDifference$1(diff) {
13053
- if (diff < 60) {
13054
- return `${diff}s ago`;
13055
- } else if (diff < 3600) {
13056
- const minutes = Math.floor(diff / 60);
13057
- return `${minutes}m ago`;
13058
- } else if (diff < 86400) {
13059
- const hours = Math.floor(diff / 3600);
13060
- return `${hours}h ago`;
13061
- } else {
13062
- const days = Math.floor(diff / 86400);
13063
- return `${days}d ago`;
13064
- }
13065
- }
13066
-
13067
- /**
13068
- * Formats a date string into a relative time string
13069
- * @param {string} dateString - Date string to format
13070
- * @returns {string} Formatted relative time string
13071
- */
13072
- function formatAge$1(dateString) {
13073
- if (!dateString) {
13074
- return 'N/A';
13075
- }
13076
-
13077
- try {
13078
- const diff = getTimeDifference$1(dateString);
13079
- return formatTimeDifference$1(diff);
13080
- } catch (error) {
13081
- console.error('Error formatting date:', error);
13082
- return 'Invalid date';
13083
- }
13084
- }
13085
-
13086
- /**
13087
- * Validates a date string format
13088
- * @param {string} dateString - Date string to validate
13089
- * @returns {boolean} True if date string is valid
13090
- */
13091
- function isValidDateString$1(dateString) {
13092
- if (!dateString) return false;
13093
-
13094
- const pattern = /^\d{4}-\d{2}-\d{2}(T| )\d{2}:\d{2}:\d{2}\.\d{3}Z?$/;
13095
- if (!pattern.test(dateString)) return false;
13096
-
13097
- const date = new Date(normalizeDateTime$1(dateString));
13098
- return date instanceof Date && !isNaN(date);
13099
- }
13100
-
13101
- /**
13102
- * Compares two date strings
13103
- * @param {string} dateA - First date string
13104
- * @param {string} dateB - Second date string
13105
- * @returns {number} -1 if dateA is earlier, 0 if equal, 1 if dateA is later
13106
- */
13107
- function compareDates$1(dateA, dateB) {
13108
- if (!isValidDateString$1(dateA) || !isValidDateString$1(dateB)) {
13109
- throw new Error(`Invalid date string format. A: ${dateA} B: ${dateB})`);
13110
- }
13111
-
13112
- const timeA = new Date(normalizeDateTime$1(dateA)).getTime();
13113
- const timeB = new Date(normalizeDateTime$1(dateB)).getTime();
13114
-
13115
- if (timeA < timeB) return -1;
13116
- if (timeA > timeB) return 1;
13117
- return 0;
13118
- }
13119
-
13120
- var DateUtils$1 = {
13121
- formatAge: formatAge$1,
13122
- isValidDateString: isValidDateString$1,
13123
- compareDates: compareDates$1,
13124
- normalizeDateTime: normalizeDateTime$1,
13125
- getTimeDifference: getTimeDifference$1,
13126
- formatTimeDifference: formatTimeDifference$1
13127
- };
13128
-
13129
13319
  /**
13130
13320
  * Component: Formatter Utilities
13131
13321
  * Block-UUID: 8512c809-87b0-4f90-af9d-b3dca204c4de
@@ -13336,6 +13526,9 @@ const h$1 = {
13336
13526
  createArticle: (params) => {
13337
13527
  return createElement("article", params);
13338
13528
  },
13529
+ createBlockquote: (params) => {
13530
+ return createElement("blockquote", params);
13531
+ },
13339
13532
  createBr: () => {
13340
13533
  return createElement("br");
13341
13534
  },
@@ -26368,15 +26561,16 @@ var CompactChatUtils$1 = {
26368
26561
  * Component: GitSenseChatUtils
26369
26562
  * Block-UUID: c1b6c4d3-7959-4eb6-8022-6cd7aa59240d
26370
26563
  * Parent-UUID: 1793b3a8-4881-4306-bfdf-673eef503679
26371
- * Version: 2.7.0
26372
- * 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, EnvUtils, ObjectUtils, MetaRawResultUtils, and CompactChatUtils.
26564
+ * Version: 2.8.0
26565
+ * 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, EnvUtils, ObjectUtils, MetaRawResultUtils, CompactChatUtils, and CLIContractUtils.
26373
26566
  * Language: JavaScript
26374
26567
  * Created-at: 2025-10-17T17:13:04.663Z
26375
- * 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), Qwen 3 Coder 480B - Cerebras (v2.2.0), Qwen 3 Coder 480B - Cerebras (v2.2.1), Claude Haiku 4.5 (v2.3.0), Qwen 3 Coder 480B - Cerebras (v2.4.0), Qwen 3 Coder 480B - Cerebras (v2.5.0), GLM-4.6 (v2.6.0), GLM-4.6 (v2.7.0)
26568
+ * 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), Qwen 3 Coder 480B - Cerebras (v2.2.0), Qwen 3 Coder 480B - Cerebras (v2.2.1), Claude Haiku 4.5 (v2.3.0), Qwen 3 Coder 480B - Cerebras (v2.4.0), Qwen 3 Coder 480B - Cerebras (v2.5.0), GLM-4.6 (v2.6.0), GLM-4.6 (v2.7.0), GLM-4.7 (v2.8.0)
26376
26569
  */
26377
26570
 
26378
26571
  const ChatUtils = ChatUtils$2;
26379
- const CodeBlockUtils = CodeBlockUtils$7;
26572
+ const CLIContractUtils = CLIContractUtils$1;
26573
+ const CodeBlockUtils = CodeBlockUtils$8;
26380
26574
  const ContextUtils = ContextUtils$2;
26381
26575
  const MessageUtils = MessageUtils$3;
26382
26576
  const AnalysisBlockUtils = AnalysisBlockUtils$3;
@@ -26792,6 +26986,7 @@ var GitSenseChatUtils_1 = {
26792
26986
  GSToolBlockUtils,
26793
26987
  JsonUtils,
26794
26988
  ConfigUtils,
26989
+ CLIContractUtils,
26795
26990
  DateUtils,
26796
26991
  LanguageNameUtils,
26797
26992
  FormatterUtils,
@@ -26942,6 +27137,14 @@ var GitSenseChatUtils_1 = {
26942
27137
  parseTableRow,
26943
27138
  parseSize,
26944
27139
  parseTokens,
27140
+
27141
+ // Contract Utilities (from CLIContractUtils)
27142
+ parseContractMessage: CLIContractUtils.parseContractMessage,
27143
+ isContractMessage: CLIContractUtils.isContractMessage,
27144
+ isContractActive: CLIContractUtils.isContractActive,
27145
+ determineSaveMode: CLIContractUtils.determineSaveMode,
27146
+ extractCodeMetadata: CLIContractUtils.extractCodeMetadata,
27147
+ formatTimeRemaining: CLIContractUtils.formatTimeRemaining,
26945
27148
  };
26946
27149
 
26947
27150
  var GitSenseChatUtils$1 = /*@__PURE__*/getDefaultExportFromCjs(GitSenseChatUtils_1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitsense/gsc-utils",
3
- "version": "0.2.34",
3
+ "version": "0.2.36",
4
4
  "description": "Utilities for GitSense Chat (GSC)",
5
5
  "main": "dist/gsc-utils.cjs.js",
6
6
  "module": "dist/gsc-utils.esm.js",
@@ -60,7 +60,10 @@ function parseOverviewMetadata(content) {
60
60
  const lines = content.split('\n');
61
61
 
62
62
  // Regex to capture "Field Name" and "Value" from lines like '* **Field Name: ** Value'
63
- const fieldRegex = /^\*\s+\*\*([\w\s.-]+):\*\*\s+(.*)$/;
63
+ const fieldRegex1 = /^\*\s+\*\*([\w\s.-]+):\*\*\s+(.*)$/;
64
+ const fieldRegex2 = /^\*\s+\*\*([\w\s.-]+)\*\*:\s+(.*)$/;
65
+ const fieldRegex3 = /^.*?(Chat ID|Path).*:\s*(\d+)$/m;
66
+
64
67
  let foundList = false;
65
68
  let currentKey = null; // For potential multi-line handling in the future
66
69
 
@@ -76,7 +79,7 @@ function parseOverviewMetadata(content) {
76
79
  break;
77
80
  }
78
81
 
79
- const match = trimmedLine.match(fieldRegex);
82
+ const match = trimmedLine.match(fieldRegex1) || trimmedLine.match(fieldRegex2) || trimmedLine.match(fieldRegex3)
80
83
 
81
84
  if (match) {
82
85
  foundList = true;