@gitsense/gsc-utils 0.2.35 → 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.
@@ -9964,7 +9964,7 @@ function fixTextCodeBlocks$2(text) {
9964
9964
  const [fieldPart, valuePart] = line.split(':').map(p => p.trim());
9965
9965
 
9966
9966
  // Skip if N/A or contains unexpected characters
9967
- if (valuePart === 'N/A' || valuePart.match(/\(/)) {
9967
+ if (valuePart === 'N/A' || !valuePart.match(/\w-/)) {
9968
9968
  return line;
9969
9969
  }
9970
9970
  // Validate UUID
@@ -11003,7 +11003,7 @@ const { formatWithLineNumbers: formatWithLineNumbers$1, formatBlockWithLineNumbe
11003
11003
  const { getLineage: getLineage$1 } = lineageTracer;
11004
11004
 
11005
11005
  // Export all imported items
11006
- var CodeBlockUtils$7 = {
11006
+ var CodeBlockUtils$8 = {
11007
11007
  // Constants
11008
11008
  COMMENT_STYLES: COMMENT_STYLES$1,
11009
11009
 
@@ -11063,6 +11063,302 @@ var CodeBlockUtils$7 = {
11063
11063
  removeLineNumbers: removeLineNumbers$1,
11064
11064
  };
11065
11065
 
11066
+ /**
11067
+ * Component: Date Utilities
11068
+ * Block-UUID: fef3b0f4-8055-4690-9336-e68a9cc33a61
11069
+ * Parent-UUID: 716e5ce9-84df-4f12-89e7-4a28e4a39a81
11070
+ * Version: 1.0.0
11071
+ * Description: Date formatting and manipulation utilities for GitSense Chat
11072
+ * Language: JavaScript
11073
+ * Created-at: 2025-10-11T23:26:20.815Z
11074
+ * Authors: Claude-3.5-Sonnet (v1.0.0), Qwen 3 Coder 480B - Cerebras (v1.0.0)
11075
+ */
11076
+
11077
+ /**
11078
+ * Ensures a date string has a timezone indicator
11079
+ * @param {string} dateString - Date string in format "YYYY-MM-DD(T| )HH:mm:ss.SSS"
11080
+ * @returns {string} Date string with 'Z' timezone indicator if not present
11081
+ */
11082
+ function normalizeDateTime$1(dateString) {
11083
+ return dateString.includes('Z') ? dateString : dateString + 'Z';
11084
+ }
11085
+
11086
+ /**
11087
+ * Calculates the time difference between now and a given date
11088
+ * @param {string} dateString - Date string to compare against current time
11089
+ * @returns {number} Difference in seconds
11090
+ */
11091
+ function getTimeDifference$1(dateString) {
11092
+ const now = new Date();
11093
+ const date = new Date(normalizeDateTime$1(dateString));
11094
+ return Math.floor((now - date) / 1000);
11095
+ }
11096
+
11097
+ /**
11098
+ * Formats a time difference in seconds to a human-readable string
11099
+ * @param {number} diff - Time difference in seconds
11100
+ * @returns {string} Formatted string (e.g., "5s ago", "2m ago", "3h ago", "2d ago")
11101
+ */
11102
+ function formatTimeDifference$1(diff) {
11103
+ if (diff < 60) {
11104
+ return `${diff}s ago`;
11105
+ } else if (diff < 3600) {
11106
+ const minutes = Math.floor(diff / 60);
11107
+ return `${minutes}m ago`;
11108
+ } else if (diff < 86400) {
11109
+ const hours = Math.floor(diff / 3600);
11110
+ return `${hours}h ago`;
11111
+ } else {
11112
+ const days = Math.floor(diff / 86400);
11113
+ return `${days}d ago`;
11114
+ }
11115
+ }
11116
+
11117
+ /**
11118
+ * Formats a date string into a relative time string
11119
+ * @param {string} dateString - Date string to format
11120
+ * @returns {string} Formatted relative time string
11121
+ */
11122
+ function formatAge$1(dateString) {
11123
+ if (!dateString) {
11124
+ return 'N/A';
11125
+ }
11126
+
11127
+ try {
11128
+ const diff = getTimeDifference$1(dateString);
11129
+ return formatTimeDifference$1(diff);
11130
+ } catch (error) {
11131
+ console.error('Error formatting date:', error);
11132
+ return 'Invalid date';
11133
+ }
11134
+ }
11135
+
11136
+ /**
11137
+ * Validates a date string format
11138
+ * @param {string} dateString - Date string to validate
11139
+ * @returns {boolean} True if date string is valid
11140
+ */
11141
+ function isValidDateString$1(dateString) {
11142
+ if (!dateString) return false;
11143
+
11144
+ const pattern = /^\d{4}-\d{2}-\d{2}(T| )\d{2}:\d{2}:\d{2}\.\d{3}Z?$/;
11145
+ if (!pattern.test(dateString)) return false;
11146
+
11147
+ const date = new Date(normalizeDateTime$1(dateString));
11148
+ return date instanceof Date && !isNaN(date);
11149
+ }
11150
+
11151
+ /**
11152
+ * Compares two date strings
11153
+ * @param {string} dateA - First date string
11154
+ * @param {string} dateB - Second date string
11155
+ * @returns {number} -1 if dateA is earlier, 0 if equal, 1 if dateA is later
11156
+ */
11157
+ function compareDates$1(dateA, dateB) {
11158
+ if (!isValidDateString$1(dateA) || !isValidDateString$1(dateB)) {
11159
+ throw new Error(`Invalid date string format. A: ${dateA} B: ${dateB})`);
11160
+ }
11161
+
11162
+ const timeA = new Date(normalizeDateTime$1(dateA)).getTime();
11163
+ const timeB = new Date(normalizeDateTime$1(dateB)).getTime();
11164
+
11165
+ if (timeA < timeB) return -1;
11166
+ if (timeA > timeB) return 1;
11167
+ return 0;
11168
+ }
11169
+
11170
+ var DateUtils$1 = {
11171
+ formatAge: formatAge$1,
11172
+ isValidDateString: isValidDateString$1,
11173
+ compareDates: compareDates$1,
11174
+ normalizeDateTime: normalizeDateTime$1,
11175
+ getTimeDifference: getTimeDifference$1,
11176
+ formatTimeDifference: formatTimeDifference$1
11177
+ };
11178
+
11179
+ /**
11180
+ * Component: CLI Contract Utilities
11181
+ * Block-UUID: a57b72a0-0d95-44a2-8f3f-ab6ee84b3197
11182
+ * Parent-UUID: 9050e244-793a-4dc6-8571-b96f38927f69
11183
+ * Version: 1.1.0
11184
+ * Description: Utilities for parsing GitSense Chat CLI contract messages and determining save modes for code blocks.
11185
+ * Language: JavaScript
11186
+ * Created-at: 2026-02-27T02:26:15.078Z
11187
+ * Authors: GLM-4.7 (v1.0.0), GLM-4.7 (v1.1.0)
11188
+ */
11189
+
11190
+ const CodeBlockUtils$7 = CodeBlockUtils$8;
11191
+
11192
+ /**
11193
+ * Parses a contract message object to extract the contract data.
11194
+ * Handles cases where data might be in 'content' (as JSON string) or 'metadata'.
11195
+ *
11196
+ * @param {Object} message - The chat message object.
11197
+ * @returns {Object|null} The parsed contract data object or null if invalid.
11198
+ */
11199
+ function parseContractMessage(message) {
11200
+ if (!message) {
11201
+ return null;
11202
+ }
11203
+
11204
+ // We expect the message type to be 'gsc-cli-contract'
11205
+ if (message.type !== 'gsc-cli-contract') {
11206
+ return null;
11207
+ }
11208
+
11209
+ const content = message.message || '';
11210
+ const lines = content.split('\n');
11211
+
11212
+ const contractData = {};
11213
+ let inTable = false;
11214
+ let foundHeader = false;
11215
+
11216
+ for (let i = 0; i < lines.length; i++) {
11217
+ const line = lines[i].trim();
11218
+
11219
+ // Check for the CLI Contract header
11220
+ if (line.startsWith('### CLI Contract')) {
11221
+ foundHeader = true;
11222
+ continue;
11223
+ }
11224
+
11225
+ // If we haven't found the header yet, keep looking
11226
+ if (!foundHeader) {
11227
+ continue;
11228
+ }
11229
+
11230
+ // Check for table separator (e.g., | :--- | :--- |)
11231
+ if (line.includes('---')) {
11232
+ inTable = true;
11233
+ continue;
11234
+ }
11235
+
11236
+ // Parse table rows
11237
+ if (inTable && line.startsWith('|')) {
11238
+ // Remove leading/trailing pipes and split by pipe
11239
+ const parts = line.substring(1, line.length - 1).split('|').map(p => p.trim());
11240
+
11241
+ if (parts.length >= 2) {
11242
+ const key = parts[0].replace(/\*\*/g, '').toLowerCase(); // Remove bold markdown and normalize
11243
+ const value = parts[1];
11244
+
11245
+ if (key === 'uuid') contractData.uuid = value;
11246
+ else if (key === 'expires at') contractData.expiresAt = value;
11247
+ else if (key === 'status') contractData.status = value;
11248
+ else if (key === 'description') contractData.description = value;
11249
+ }
11250
+ }
11251
+ }
11252
+
11253
+ return contractData;
11254
+ }
11255
+
11256
+ /**
11257
+ * Checks if a message is a contract message.
11258
+ *
11259
+ * @param {Object} message - The chat message object.
11260
+ * @returns {boolean} True if the message is a contract message.
11261
+ */
11262
+ function isContractMessage(message) {
11263
+ return message && message.type === 'gsc-cli-contract';
11264
+ }
11265
+
11266
+ /**
11267
+ * Determines if a contract is currently active based on its expiration time.
11268
+ *
11269
+ * @param {Object} contractData - The contract data object (must contain expiresAt).
11270
+ * @returns {boolean} True if the contract is active, false otherwise.
11271
+ */
11272
+ function isContractActive(contractData) {
11273
+ if (!contractData || !contractData.expiresAt) {
11274
+ return false;
11275
+ }
11276
+
11277
+ const now = Date.now();
11278
+ const expiresAt = new Date(contractData.expiresAt).getTime();
11279
+
11280
+ return now < expiresAt;
11281
+ }
11282
+
11283
+ /**
11284
+ * Determines the save mode (update vs new-file) based on the code content.
11285
+ * Parses the code block header to check for a Parent-UUID.
11286
+ *
11287
+ * @param {string} rawCodeContent - The full content of the code block (including header).
11288
+ * @returns {Object} An object { mode: 'update'|'new-file', metadata: Object }.
11289
+ */
11290
+ function determineSaveMode(rawCodeContent) {
11291
+ const { blocks } = CodeBlockUtils$7.processCodeBlocks(rawCodeContent, { silent: true });
11292
+
11293
+ if (!blocks || blocks.length === 0) {
11294
+ return { mode: 'unknown', metadata: null };
11295
+ }
11296
+
11297
+ const block = blocks[0];
11298
+ const header = block.header || {};
11299
+ const parentUUID = header['Parent-UUID'];
11300
+
11301
+ let mode = 'new-file';
11302
+
11303
+ // If Parent-UUID exists and is not N/A, it's an update
11304
+ if (parentUUID && parentUUID !== 'N/A') {
11305
+ mode = 'update';
11306
+ }
11307
+
11308
+ return {
11309
+ mode,
11310
+ metadata: {
11311
+ blockUUID: header['Block-UUID'],
11312
+ parentUUID: parentUUID,
11313
+ language: block.language
11314
+ }
11315
+ };
11316
+ }
11317
+
11318
+ /**
11319
+ * Extracts key metadata from a code block content.
11320
+ *
11321
+ * @param {string} rawCodeContent - The full content of the code block.
11322
+ * @returns {Object|null} Metadata object or null if parsing fails.
11323
+ */
11324
+ function extractCodeMetadata(rawCodeContent) {
11325
+ const result = determineSaveMode(rawCodeContent);
11326
+ return result.metadata;
11327
+ }
11328
+
11329
+ /**
11330
+ * Formats the remaining time until expiration.
11331
+ *
11332
+ * @param {string|Date} expiresAt - The expiration timestamp.
11333
+ * @returns {string} Formatted string (e.g., "45m", "2h", "1d").
11334
+ */
11335
+ function formatTimeRemaining(expiresAt) {
11336
+ const now = Date.now();
11337
+ const expiry = new Date(expiresAt).getTime();
11338
+ const diffMs = expiry - now;
11339
+
11340
+ if (diffMs <= 0) return 'Expired';
11341
+
11342
+ const diffMins = Math.floor(diffMs / 60000);
11343
+
11344
+ if (diffMins < 60) return `${diffMins}m`;
11345
+
11346
+ const diffHours = Math.floor(diffMins / 60);
11347
+ if (diffHours < 24) return `${diffHours}h`;
11348
+
11349
+ const diffDays = Math.floor(diffHours / 24);
11350
+ return `${diffDays}d`;
11351
+ }
11352
+
11353
+ var CLIContractUtils$1 = {
11354
+ parseContractMessage,
11355
+ isContractMessage,
11356
+ isContractActive,
11357
+ determineSaveMode,
11358
+ extractCodeMetadata,
11359
+ formatTimeRemaining
11360
+ };
11361
+
11066
11362
  /*
11067
11363
  * Component: ContextUtils
11068
11364
  * Block-UUID: 534c348d-a11f-4de6-ad15-f33068d51fb8
@@ -11074,7 +11370,7 @@ var CodeBlockUtils$7 = {
11074
11370
  * 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)
11075
11371
  */
11076
11372
 
11077
- const CodeBlockUtils$6 = CodeBlockUtils$7;
11373
+ const CodeBlockUtils$6 = CodeBlockUtils$8;
11078
11374
  const MessageUtils$2 = MessageUtils$3;
11079
11375
 
11080
11376
  /**
@@ -11534,7 +11830,7 @@ var constants = {
11534
11830
  * Authors: Gemini 2.5 Flash (v1.0.0)
11535
11831
  */
11536
11832
 
11537
- const CodeBlockUtils$5 = CodeBlockUtils$7;
11833
+ const CodeBlockUtils$5 = CodeBlockUtils$8;
11538
11834
  const GSToolBlockUtils$1 = GSToolBlockUtils$3;
11539
11835
  const JsonUtils$1 = JsonUtils$2;
11540
11836
  const { ANALYZE_HEADER_PREFIX } = constants;
@@ -11844,7 +12140,7 @@ const fs$7 = require$$0.promises;
11844
12140
  const path$5 = require$$1;
11845
12141
  const { getAnalyzerInstructionsContent: getAnalyzerInstructionsContent$2 } = instructionLoader;
11846
12142
  const { preprocessJsonForValidation: preprocessJsonForValidation$4 } = jsonParser;
11847
- const CodeBlockUtils$4 = CodeBlockUtils$7;
12143
+ const CodeBlockUtils$4 = CodeBlockUtils$8;
11848
12144
 
11849
12145
  /**
11850
12146
  * Reads and parses the config.json file in a directory.
@@ -12151,7 +12447,7 @@ var saver = {
12151
12447
 
12152
12448
  const fs$5 = require$$0.promises;
12153
12449
  const path$3 = require$$1;
12154
- const CodeBlockUtils$3 = CodeBlockUtils$7;
12450
+ const CodeBlockUtils$3 = CodeBlockUtils$8;
12155
12451
  const { preprocessJsonForValidation: preprocessJsonForValidation$3 } = jsonParser;
12156
12452
 
12157
12453
  /**
@@ -12629,7 +12925,7 @@ var defaultPromptLoader = {
12629
12925
 
12630
12926
  const fs$2 = require$$0.promises;
12631
12927
  const path = require$$1;
12632
- const CodeBlockUtils$2 = CodeBlockUtils$7;
12928
+ const CodeBlockUtils$2 = CodeBlockUtils$8;
12633
12929
  const { preprocessJsonForValidation: preprocessJsonForValidation$2 } = jsonParser;
12634
12930
  const { isValidDirName: isValidDirName$1 } = discovery;
12635
12931
  const { readConfig } = discovery;
@@ -12815,7 +13111,7 @@ var updater = {
12815
13111
  */
12816
13112
 
12817
13113
  require$$0.promises;
12818
- const CodeBlockUtils$1 = CodeBlockUtils$7;
13114
+ const CodeBlockUtils$1 = CodeBlockUtils$8;
12819
13115
  const { preprocessJsonForValidation: preprocessJsonForValidation$1 } = jsonParser;
12820
13116
  const { isValidDirName } = discovery;
12821
13117
  const { saveConfiguration: saveConfiguration$1 } = saver;
@@ -13022,119 +13318,6 @@ var LLMUtils$1 = {
13022
13318
  estimateTokens: estimateTokens$1,
13023
13319
  };
13024
13320
 
13025
- /**
13026
- * Component: Date Utilities
13027
- * Block-UUID: fef3b0f4-8055-4690-9336-e68a9cc33a61
13028
- * Parent-UUID: 716e5ce9-84df-4f12-89e7-4a28e4a39a81
13029
- * Version: 1.0.0
13030
- * Description: Date formatting and manipulation utilities for GitSense Chat
13031
- * Language: JavaScript
13032
- * Created-at: 2025-10-11T23:26:20.815Z
13033
- * Authors: Claude-3.5-Sonnet (v1.0.0), Qwen 3 Coder 480B - Cerebras (v1.0.0)
13034
- */
13035
-
13036
- /**
13037
- * Ensures a date string has a timezone indicator
13038
- * @param {string} dateString - Date string in format "YYYY-MM-DD(T| )HH:mm:ss.SSS"
13039
- * @returns {string} Date string with 'Z' timezone indicator if not present
13040
- */
13041
- function normalizeDateTime$1(dateString) {
13042
- return dateString.includes('Z') ? dateString : dateString + 'Z';
13043
- }
13044
-
13045
- /**
13046
- * Calculates the time difference between now and a given date
13047
- * @param {string} dateString - Date string to compare against current time
13048
- * @returns {number} Difference in seconds
13049
- */
13050
- function getTimeDifference$1(dateString) {
13051
- const now = new Date();
13052
- const date = new Date(normalizeDateTime$1(dateString));
13053
- return Math.floor((now - date) / 1000);
13054
- }
13055
-
13056
- /**
13057
- * Formats a time difference in seconds to a human-readable string
13058
- * @param {number} diff - Time difference in seconds
13059
- * @returns {string} Formatted string (e.g., "5s ago", "2m ago", "3h ago", "2d ago")
13060
- */
13061
- function formatTimeDifference$1(diff) {
13062
- if (diff < 60) {
13063
- return `${diff}s ago`;
13064
- } else if (diff < 3600) {
13065
- const minutes = Math.floor(diff / 60);
13066
- return `${minutes}m ago`;
13067
- } else if (diff < 86400) {
13068
- const hours = Math.floor(diff / 3600);
13069
- return `${hours}h ago`;
13070
- } else {
13071
- const days = Math.floor(diff / 86400);
13072
- return `${days}d ago`;
13073
- }
13074
- }
13075
-
13076
- /**
13077
- * Formats a date string into a relative time string
13078
- * @param {string} dateString - Date string to format
13079
- * @returns {string} Formatted relative time string
13080
- */
13081
- function formatAge$1(dateString) {
13082
- if (!dateString) {
13083
- return 'N/A';
13084
- }
13085
-
13086
- try {
13087
- const diff = getTimeDifference$1(dateString);
13088
- return formatTimeDifference$1(diff);
13089
- } catch (error) {
13090
- console.error('Error formatting date:', error);
13091
- return 'Invalid date';
13092
- }
13093
- }
13094
-
13095
- /**
13096
- * Validates a date string format
13097
- * @param {string} dateString - Date string to validate
13098
- * @returns {boolean} True if date string is valid
13099
- */
13100
- function isValidDateString$1(dateString) {
13101
- if (!dateString) return false;
13102
-
13103
- const pattern = /^\d{4}-\d{2}-\d{2}(T| )\d{2}:\d{2}:\d{2}\.\d{3}Z?$/;
13104
- if (!pattern.test(dateString)) return false;
13105
-
13106
- const date = new Date(normalizeDateTime$1(dateString));
13107
- return date instanceof Date && !isNaN(date);
13108
- }
13109
-
13110
- /**
13111
- * Compares two date strings
13112
- * @param {string} dateA - First date string
13113
- * @param {string} dateB - Second date string
13114
- * @returns {number} -1 if dateA is earlier, 0 if equal, 1 if dateA is later
13115
- */
13116
- function compareDates$1(dateA, dateB) {
13117
- if (!isValidDateString$1(dateA) || !isValidDateString$1(dateB)) {
13118
- throw new Error(`Invalid date string format. A: ${dateA} B: ${dateB})`);
13119
- }
13120
-
13121
- const timeA = new Date(normalizeDateTime$1(dateA)).getTime();
13122
- const timeB = new Date(normalizeDateTime$1(dateB)).getTime();
13123
-
13124
- if (timeA < timeB) return -1;
13125
- if (timeA > timeB) return 1;
13126
- return 0;
13127
- }
13128
-
13129
- var DateUtils$1 = {
13130
- formatAge: formatAge$1,
13131
- isValidDateString: isValidDateString$1,
13132
- compareDates: compareDates$1,
13133
- normalizeDateTime: normalizeDateTime$1,
13134
- getTimeDifference: getTimeDifference$1,
13135
- formatTimeDifference: formatTimeDifference$1
13136
- };
13137
-
13138
13321
  /**
13139
13322
  * Component: Formatter Utilities
13140
13323
  * Block-UUID: 8512c809-87b0-4f90-af9d-b3dca204c4de
@@ -13345,6 +13528,9 @@ const h$1 = {
13345
13528
  createArticle: (params) => {
13346
13529
  return createElement("article", params);
13347
13530
  },
13531
+ createBlockquote: (params) => {
13532
+ return createElement("blockquote", params);
13533
+ },
13348
13534
  createBr: () => {
13349
13535
  return createElement("br");
13350
13536
  },
@@ -26377,15 +26563,16 @@ var CompactChatUtils$1 = {
26377
26563
  * Component: GitSenseChatUtils
26378
26564
  * Block-UUID: c1b6c4d3-7959-4eb6-8022-6cd7aa59240d
26379
26565
  * Parent-UUID: 1793b3a8-4881-4306-bfdf-673eef503679
26380
- * Version: 2.7.0
26381
- * 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.
26566
+ * Version: 2.8.0
26567
+ * 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.
26382
26568
  * Language: JavaScript
26383
26569
  * Created-at: 2025-10-17T17:13:04.663Z
26384
- * 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)
26570
+ * 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)
26385
26571
  */
26386
26572
 
26387
26573
  const ChatUtils = ChatUtils$2;
26388
- const CodeBlockUtils = CodeBlockUtils$7;
26574
+ const CLIContractUtils = CLIContractUtils$1;
26575
+ const CodeBlockUtils = CodeBlockUtils$8;
26389
26576
  const ContextUtils = ContextUtils$2;
26390
26577
  const MessageUtils = MessageUtils$3;
26391
26578
  const AnalysisBlockUtils = AnalysisBlockUtils$3;
@@ -26801,6 +26988,7 @@ var GitSenseChatUtils_1 = {
26801
26988
  GSToolBlockUtils,
26802
26989
  JsonUtils,
26803
26990
  ConfigUtils,
26991
+ CLIContractUtils,
26804
26992
  DateUtils,
26805
26993
  LanguageNameUtils,
26806
26994
  FormatterUtils,
@@ -26951,6 +27139,14 @@ var GitSenseChatUtils_1 = {
26951
27139
  parseTableRow,
26952
27140
  parseSize,
26953
27141
  parseTokens,
27142
+
27143
+ // Contract Utilities (from CLIContractUtils)
27144
+ parseContractMessage: CLIContractUtils.parseContractMessage,
27145
+ isContractMessage: CLIContractUtils.isContractMessage,
27146
+ isContractActive: CLIContractUtils.isContractActive,
27147
+ determineSaveMode: CLIContractUtils.determineSaveMode,
27148
+ extractCodeMetadata: CLIContractUtils.extractCodeMetadata,
27149
+ formatTimeRemaining: CLIContractUtils.formatTimeRemaining,
26954
27150
  };
26955
27151
 
26956
27152
  var GitSenseChatUtils$1 = /*@__PURE__*/getDefaultExportFromCjs(GitSenseChatUtils_1);
@@ -9962,7 +9962,7 @@ function fixTextCodeBlocks$2(text) {
9962
9962
  const [fieldPart, valuePart] = line.split(':').map(p => p.trim());
9963
9963
 
9964
9964
  // Skip if N/A or contains unexpected characters
9965
- if (valuePart === 'N/A' || valuePart.match(/\(/)) {
9965
+ if (valuePart === 'N/A' || !valuePart.match(/\w-/)) {
9966
9966
  return line;
9967
9967
  }
9968
9968
  // Validate UUID
@@ -11001,7 +11001,7 @@ const { formatWithLineNumbers: formatWithLineNumbers$1, formatBlockWithLineNumbe
11001
11001
  const { getLineage: getLineage$1 } = lineageTracer;
11002
11002
 
11003
11003
  // Export all imported items
11004
- var CodeBlockUtils$7 = {
11004
+ var CodeBlockUtils$8 = {
11005
11005
  // Constants
11006
11006
  COMMENT_STYLES: COMMENT_STYLES$1,
11007
11007
 
@@ -11061,6 +11061,302 @@ var CodeBlockUtils$7 = {
11061
11061
  removeLineNumbers: removeLineNumbers$1,
11062
11062
  };
11063
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
+
11064
11360
  /*
11065
11361
  * Component: ContextUtils
11066
11362
  * Block-UUID: 534c348d-a11f-4de6-ad15-f33068d51fb8
@@ -11072,7 +11368,7 @@ var CodeBlockUtils$7 = {
11072
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)
11073
11369
  */
11074
11370
 
11075
- const CodeBlockUtils$6 = CodeBlockUtils$7;
11371
+ const CodeBlockUtils$6 = CodeBlockUtils$8;
11076
11372
  const MessageUtils$2 = MessageUtils$3;
11077
11373
 
11078
11374
  /**
@@ -11532,7 +11828,7 @@ var constants = {
11532
11828
  * Authors: Gemini 2.5 Flash (v1.0.0)
11533
11829
  */
11534
11830
 
11535
- const CodeBlockUtils$5 = CodeBlockUtils$7;
11831
+ const CodeBlockUtils$5 = CodeBlockUtils$8;
11536
11832
  const GSToolBlockUtils$1 = GSToolBlockUtils$3;
11537
11833
  const JsonUtils$1 = JsonUtils$2;
11538
11834
  const { ANALYZE_HEADER_PREFIX } = constants;
@@ -11842,7 +12138,7 @@ const fs$7 = require$$0.promises;
11842
12138
  const path$5 = require$$1;
11843
12139
  const { getAnalyzerInstructionsContent: getAnalyzerInstructionsContent$2 } = instructionLoader;
11844
12140
  const { preprocessJsonForValidation: preprocessJsonForValidation$4 } = jsonParser;
11845
- const CodeBlockUtils$4 = CodeBlockUtils$7;
12141
+ const CodeBlockUtils$4 = CodeBlockUtils$8;
11846
12142
 
11847
12143
  /**
11848
12144
  * Reads and parses the config.json file in a directory.
@@ -12149,7 +12445,7 @@ var saver = {
12149
12445
 
12150
12446
  const fs$5 = require$$0.promises;
12151
12447
  const path$3 = require$$1;
12152
- const CodeBlockUtils$3 = CodeBlockUtils$7;
12448
+ const CodeBlockUtils$3 = CodeBlockUtils$8;
12153
12449
  const { preprocessJsonForValidation: preprocessJsonForValidation$3 } = jsonParser;
12154
12450
 
12155
12451
  /**
@@ -12627,7 +12923,7 @@ var defaultPromptLoader = {
12627
12923
 
12628
12924
  const fs$2 = require$$0.promises;
12629
12925
  const path = require$$1;
12630
- const CodeBlockUtils$2 = CodeBlockUtils$7;
12926
+ const CodeBlockUtils$2 = CodeBlockUtils$8;
12631
12927
  const { preprocessJsonForValidation: preprocessJsonForValidation$2 } = jsonParser;
12632
12928
  const { isValidDirName: isValidDirName$1 } = discovery;
12633
12929
  const { readConfig } = discovery;
@@ -12813,7 +13109,7 @@ var updater = {
12813
13109
  */
12814
13110
 
12815
13111
  require$$0.promises;
12816
- const CodeBlockUtils$1 = CodeBlockUtils$7;
13112
+ const CodeBlockUtils$1 = CodeBlockUtils$8;
12817
13113
  const { preprocessJsonForValidation: preprocessJsonForValidation$1 } = jsonParser;
12818
13114
  const { isValidDirName } = discovery;
12819
13115
  const { saveConfiguration: saveConfiguration$1 } = saver;
@@ -13020,119 +13316,6 @@ var LLMUtils$1 = {
13020
13316
  estimateTokens: estimateTokens$1,
13021
13317
  };
13022
13318
 
13023
- /**
13024
- * Component: Date Utilities
13025
- * Block-UUID: fef3b0f4-8055-4690-9336-e68a9cc33a61
13026
- * Parent-UUID: 716e5ce9-84df-4f12-89e7-4a28e4a39a81
13027
- * Version: 1.0.0
13028
- * Description: Date formatting and manipulation utilities for GitSense Chat
13029
- * Language: JavaScript
13030
- * Created-at: 2025-10-11T23:26:20.815Z
13031
- * Authors: Claude-3.5-Sonnet (v1.0.0), Qwen 3 Coder 480B - Cerebras (v1.0.0)
13032
- */
13033
-
13034
- /**
13035
- * Ensures a date string has a timezone indicator
13036
- * @param {string} dateString - Date string in format "YYYY-MM-DD(T| )HH:mm:ss.SSS"
13037
- * @returns {string} Date string with 'Z' timezone indicator if not present
13038
- */
13039
- function normalizeDateTime$1(dateString) {
13040
- return dateString.includes('Z') ? dateString : dateString + 'Z';
13041
- }
13042
-
13043
- /**
13044
- * Calculates the time difference between now and a given date
13045
- * @param {string} dateString - Date string to compare against current time
13046
- * @returns {number} Difference in seconds
13047
- */
13048
- function getTimeDifference$1(dateString) {
13049
- const now = new Date();
13050
- const date = new Date(normalizeDateTime$1(dateString));
13051
- return Math.floor((now - date) / 1000);
13052
- }
13053
-
13054
- /**
13055
- * Formats a time difference in seconds to a human-readable string
13056
- * @param {number} diff - Time difference in seconds
13057
- * @returns {string} Formatted string (e.g., "5s ago", "2m ago", "3h ago", "2d ago")
13058
- */
13059
- function formatTimeDifference$1(diff) {
13060
- if (diff < 60) {
13061
- return `${diff}s ago`;
13062
- } else if (diff < 3600) {
13063
- const minutes = Math.floor(diff / 60);
13064
- return `${minutes}m ago`;
13065
- } else if (diff < 86400) {
13066
- const hours = Math.floor(diff / 3600);
13067
- return `${hours}h ago`;
13068
- } else {
13069
- const days = Math.floor(diff / 86400);
13070
- return `${days}d ago`;
13071
- }
13072
- }
13073
-
13074
- /**
13075
- * Formats a date string into a relative time string
13076
- * @param {string} dateString - Date string to format
13077
- * @returns {string} Formatted relative time string
13078
- */
13079
- function formatAge$1(dateString) {
13080
- if (!dateString) {
13081
- return 'N/A';
13082
- }
13083
-
13084
- try {
13085
- const diff = getTimeDifference$1(dateString);
13086
- return formatTimeDifference$1(diff);
13087
- } catch (error) {
13088
- console.error('Error formatting date:', error);
13089
- return 'Invalid date';
13090
- }
13091
- }
13092
-
13093
- /**
13094
- * Validates a date string format
13095
- * @param {string} dateString - Date string to validate
13096
- * @returns {boolean} True if date string is valid
13097
- */
13098
- function isValidDateString$1(dateString) {
13099
- if (!dateString) return false;
13100
-
13101
- const pattern = /^\d{4}-\d{2}-\d{2}(T| )\d{2}:\d{2}:\d{2}\.\d{3}Z?$/;
13102
- if (!pattern.test(dateString)) return false;
13103
-
13104
- const date = new Date(normalizeDateTime$1(dateString));
13105
- return date instanceof Date && !isNaN(date);
13106
- }
13107
-
13108
- /**
13109
- * Compares two date strings
13110
- * @param {string} dateA - First date string
13111
- * @param {string} dateB - Second date string
13112
- * @returns {number} -1 if dateA is earlier, 0 if equal, 1 if dateA is later
13113
- */
13114
- function compareDates$1(dateA, dateB) {
13115
- if (!isValidDateString$1(dateA) || !isValidDateString$1(dateB)) {
13116
- throw new Error(`Invalid date string format. A: ${dateA} B: ${dateB})`);
13117
- }
13118
-
13119
- const timeA = new Date(normalizeDateTime$1(dateA)).getTime();
13120
- const timeB = new Date(normalizeDateTime$1(dateB)).getTime();
13121
-
13122
- if (timeA < timeB) return -1;
13123
- if (timeA > timeB) return 1;
13124
- return 0;
13125
- }
13126
-
13127
- var DateUtils$1 = {
13128
- formatAge: formatAge$1,
13129
- isValidDateString: isValidDateString$1,
13130
- compareDates: compareDates$1,
13131
- normalizeDateTime: normalizeDateTime$1,
13132
- getTimeDifference: getTimeDifference$1,
13133
- formatTimeDifference: formatTimeDifference$1
13134
- };
13135
-
13136
13319
  /**
13137
13320
  * Component: Formatter Utilities
13138
13321
  * Block-UUID: 8512c809-87b0-4f90-af9d-b3dca204c4de
@@ -13343,6 +13526,9 @@ const h$1 = {
13343
13526
  createArticle: (params) => {
13344
13527
  return createElement("article", params);
13345
13528
  },
13529
+ createBlockquote: (params) => {
13530
+ return createElement("blockquote", params);
13531
+ },
13346
13532
  createBr: () => {
13347
13533
  return createElement("br");
13348
13534
  },
@@ -26375,15 +26561,16 @@ var CompactChatUtils$1 = {
26375
26561
  * Component: GitSenseChatUtils
26376
26562
  * Block-UUID: c1b6c4d3-7959-4eb6-8022-6cd7aa59240d
26377
26563
  * Parent-UUID: 1793b3a8-4881-4306-bfdf-673eef503679
26378
- * Version: 2.7.0
26379
- * 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.
26380
26566
  * Language: JavaScript
26381
26567
  * Created-at: 2025-10-17T17:13:04.663Z
26382
- * 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)
26383
26569
  */
26384
26570
 
26385
26571
  const ChatUtils = ChatUtils$2;
26386
- const CodeBlockUtils = CodeBlockUtils$7;
26572
+ const CLIContractUtils = CLIContractUtils$1;
26573
+ const CodeBlockUtils = CodeBlockUtils$8;
26387
26574
  const ContextUtils = ContextUtils$2;
26388
26575
  const MessageUtils = MessageUtils$3;
26389
26576
  const AnalysisBlockUtils = AnalysisBlockUtils$3;
@@ -26799,6 +26986,7 @@ var GitSenseChatUtils_1 = {
26799
26986
  GSToolBlockUtils,
26800
26987
  JsonUtils,
26801
26988
  ConfigUtils,
26989
+ CLIContractUtils,
26802
26990
  DateUtils,
26803
26991
  LanguageNameUtils,
26804
26992
  FormatterUtils,
@@ -26949,6 +27137,14 @@ var GitSenseChatUtils_1 = {
26949
27137
  parseTableRow,
26950
27138
  parseSize,
26951
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,
26952
27148
  };
26953
27149
 
26954
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.35",
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",
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Component: CLI Contract Utilities
3
+ * Block-UUID: a57b72a0-0d95-44a2-8f3f-ab6ee84b3197
4
+ * Parent-UUID: 9050e244-793a-4dc6-8571-b96f38927f69
5
+ * Version: 1.1.0
6
+ * Description: Utilities for parsing GitSense Chat CLI contract messages and determining save modes for code blocks.
7
+ * Language: JavaScript
8
+ * Created-at: 2026-02-27T02:26:15.078Z
9
+ * Authors: GLM-4.7 (v1.0.0), GLM-4.7 (v1.1.0)
10
+ */
11
+
12
+
13
+ const CodeBlockUtils = require('./CodeBlockUtils');
14
+ const DateUtils = require('./DateUtils');
15
+
16
+ /**
17
+ * Parses a contract message object to extract the contract data.
18
+ * Handles cases where data might be in 'content' (as JSON string) or 'metadata'.
19
+ *
20
+ * @param {Object} message - The chat message object.
21
+ * @returns {Object|null} The parsed contract data object or null if invalid.
22
+ */
23
+ function parseContractMessage(message) {
24
+ if (!message) {
25
+ return null;
26
+ }
27
+
28
+ // We expect the message type to be 'gsc-cli-contract'
29
+ if (message.type !== 'gsc-cli-contract') {
30
+ return null;
31
+ }
32
+
33
+ const content = message.message || '';
34
+ const lines = content.split('\n');
35
+
36
+ const contractData = {};
37
+ let inTable = false;
38
+ let foundHeader = false;
39
+
40
+ for (let i = 0; i < lines.length; i++) {
41
+ const line = lines[i].trim();
42
+
43
+ // Check for the CLI Contract header
44
+ if (line.startsWith('### CLI Contract')) {
45
+ foundHeader = true;
46
+ continue;
47
+ }
48
+
49
+ // If we haven't found the header yet, keep looking
50
+ if (!foundHeader) {
51
+ continue;
52
+ }
53
+
54
+ // Check for table separator (e.g., | :--- | :--- |)
55
+ if (line.includes('---')) {
56
+ inTable = true;
57
+ continue;
58
+ }
59
+
60
+ // Parse table rows
61
+ if (inTable && line.startsWith('|')) {
62
+ // Remove leading/trailing pipes and split by pipe
63
+ const parts = line.substring(1, line.length - 1).split('|').map(p => p.trim());
64
+
65
+ if (parts.length >= 2) {
66
+ const key = parts[0].replace(/\*\*/g, '').toLowerCase(); // Remove bold markdown and normalize
67
+ const value = parts[1];
68
+
69
+ if (key === 'uuid') contractData.uuid = value;
70
+ else if (key === 'expires at') contractData.expiresAt = value;
71
+ else if (key === 'status') contractData.status = value;
72
+ else if (key === 'description') contractData.description = value;
73
+ }
74
+ }
75
+ }
76
+
77
+ return contractData;
78
+ }
79
+
80
+ /**
81
+ * Checks if a message is a contract message.
82
+ *
83
+ * @param {Object} message - The chat message object.
84
+ * @returns {boolean} True if the message is a contract message.
85
+ */
86
+ function isContractMessage(message) {
87
+ return message && message.type === 'gsc-cli-contract';
88
+ }
89
+
90
+ /**
91
+ * Determines if a contract is currently active based on its expiration time.
92
+ *
93
+ * @param {Object} contractData - The contract data object (must contain expiresAt).
94
+ * @returns {boolean} True if the contract is active, false otherwise.
95
+ */
96
+ function isContractActive(contractData) {
97
+ if (!contractData || !contractData.expiresAt) {
98
+ return false;
99
+ }
100
+
101
+ const now = Date.now();
102
+ const expiresAt = new Date(contractData.expiresAt).getTime();
103
+
104
+ return now < expiresAt;
105
+ }
106
+
107
+ /**
108
+ * Determines the save mode (update vs new-file) based on the code content.
109
+ * Parses the code block header to check for a Parent-UUID.
110
+ *
111
+ * @param {string} rawCodeContent - The full content of the code block (including header).
112
+ * @returns {Object} An object { mode: 'update'|'new-file', metadata: Object }.
113
+ */
114
+ function determineSaveMode(rawCodeContent) {
115
+ const { blocks } = CodeBlockUtils.processCodeBlocks(rawCodeContent, { silent: true });
116
+
117
+ if (!blocks || blocks.length === 0) {
118
+ return { mode: 'unknown', metadata: null };
119
+ }
120
+
121
+ const block = blocks[0];
122
+ const header = block.header || {};
123
+ const parentUUID = header['Parent-UUID'];
124
+
125
+ let mode = 'new-file';
126
+
127
+ // If Parent-UUID exists and is not N/A, it's an update
128
+ if (parentUUID && parentUUID !== 'N/A') {
129
+ mode = 'update';
130
+ }
131
+
132
+ return {
133
+ mode,
134
+ metadata: {
135
+ blockUUID: header['Block-UUID'],
136
+ parentUUID: parentUUID,
137
+ language: block.language
138
+ }
139
+ };
140
+ }
141
+
142
+ /**
143
+ * Extracts key metadata from a code block content.
144
+ *
145
+ * @param {string} rawCodeContent - The full content of the code block.
146
+ * @returns {Object|null} Metadata object or null if parsing fails.
147
+ */
148
+ function extractCodeMetadata(rawCodeContent) {
149
+ const result = determineSaveMode(rawCodeContent);
150
+ return result.metadata;
151
+ }
152
+
153
+ /**
154
+ * Formats the remaining time until expiration.
155
+ *
156
+ * @param {string|Date} expiresAt - The expiration timestamp.
157
+ * @returns {string} Formatted string (e.g., "45m", "2h", "1d").
158
+ */
159
+ function formatTimeRemaining(expiresAt) {
160
+ const now = Date.now();
161
+ const expiry = new Date(expiresAt).getTime();
162
+ const diffMs = expiry - now;
163
+
164
+ if (diffMs <= 0) return 'Expired';
165
+
166
+ const diffMins = Math.floor(diffMs / 60000);
167
+
168
+ if (diffMins < 60) return `${diffMins}m`;
169
+
170
+ const diffHours = Math.floor(diffMins / 60);
171
+ if (diffHours < 24) return `${diffHours}h`;
172
+
173
+ const diffDays = Math.floor(diffHours / 24);
174
+ return `${diffDays}d`;
175
+ }
176
+
177
+ module.exports = {
178
+ parseContractMessage,
179
+ isContractMessage,
180
+ isContractActive,
181
+ determineSaveMode,
182
+ extractCodeMetadata,
183
+ formatTimeRemaining
184
+ };
@@ -502,7 +502,7 @@ function fixTextCodeBlocks(text) {
502
502
  const [fieldPart, valuePart] = line.split(':').map(p => p.trim());
503
503
 
504
504
  // Skip if N/A or contains unexpected characters
505
- if (valuePart === 'N/A' || valuePart.match(/\(/)) {
505
+ if (valuePart === 'N/A' || !valuePart.match(/\w-/)) {
506
506
  return line;
507
507
  }
508
508
  // Validate UUID
package/src/DomUtils.js CHANGED
@@ -154,6 +154,9 @@ const h = {
154
154
  createArticle: (params) => {
155
155
  return createElement("article", params);
156
156
  },
157
+ createBlockquote: (params) => {
158
+ return createElement("blockquote", params);
159
+ },
157
160
  createBr: () => {
158
161
  return createElement("br");
159
162
  },
@@ -2,15 +2,16 @@
2
2
  * Component: GitSenseChatUtils
3
3
  * Block-UUID: c1b6c4d3-7959-4eb6-8022-6cd7aa59240d
4
4
  * Parent-UUID: 1793b3a8-4881-4306-bfdf-673eef503679
5
- * Version: 2.7.0
6
- * Description: Interface class for GitSense Chat utilities providing a unified API for code block parsing (markdown), extraction, and patch operations. Integrates functionalities from CodeBlockUtils and PatchUtils modules, and now includes ConfigUtils, EnvUtils, ObjectUtils, MetaRawResultUtils, and CompactChatUtils.
5
+ * Version: 2.8.0
6
+ * Description: Interface class for GitSense Chat utilities providing a unified API for code block parsing (markdown), extraction, and patch operations. Integrates functionalities from CodeBlockUtils and PatchUtils modules, and now includes ConfigUtils, EnvUtils, ObjectUtils, MetaRawResultUtils, CompactChatUtils, and CLIContractUtils.
7
7
  * Language: JavaScript
8
8
  * Created-at: 2025-10-17T17:13:04.663Z
9
- * Authors: Claude 3.7 Sonnet (v1.0.0), Gemini 2.5 Pro (v2.0.0), Gemini 2.5 Pro (v2.1.0), Gemini 2.5 Pro (v2.1.1), Gemini 2.5 Flash (v2.1.2), Gemini 2.5 Flash (v2.1.3), Gemini 2.5 Flash (v2.1.4), 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)
9
+ * Authors: Claude 3.7 Sonnet (v1.0.0), Gemini 2.5 Pro (v2.0.0), Gemini 2.5 Pro (v2.1.0), Gemini 2.5 Pro (v2.1.1), Gemini 2.5 Flash (v2.1.2), Gemini 2.5 Flash (v2.1.3), Gemini 2.5 Flash (v2.1.4), 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)
10
10
  */
11
11
 
12
12
 
13
13
  const ChatUtils = require('./ChatUtils');
14
+ const CLIContractUtils = require('./CLIContractUtils');
14
15
  const CodeBlockUtils = require('./CodeBlockUtils');
15
16
  const ContextUtils = require('./ContextUtils');
16
17
  const MessageUtils = require('./MessageUtils');
@@ -427,6 +428,7 @@ module.exports = {
427
428
  GSToolBlockUtils,
428
429
  JsonUtils,
429
430
  ConfigUtils,
431
+ CLIContractUtils,
430
432
  DateUtils,
431
433
  LanguageNameUtils,
432
434
  FormatterUtils,
@@ -577,4 +579,12 @@ module.exports = {
577
579
  parseTableRow,
578
580
  parseSize,
579
581
  parseTokens,
582
+
583
+ // Contract Utilities (from CLIContractUtils)
584
+ parseContractMessage: CLIContractUtils.parseContractMessage,
585
+ isContractMessage: CLIContractUtils.isContractMessage,
586
+ isContractActive: CLIContractUtils.isContractActive,
587
+ determineSaveMode: CLIContractUtils.determineSaveMode,
588
+ extractCodeMetadata: CLIContractUtils.extractCodeMetadata,
589
+ formatTimeRemaining: CLIContractUtils.formatTimeRemaining,
580
590
  };