git-coco 0.22.5 → 0.22.6

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.
@@ -47,7 +47,7 @@ import { pathToFileURL } from 'url';
47
47
  /**
48
48
  * Current build version from package.json
49
49
  */
50
- const BUILD_VERSION = "0.22.5";
50
+ const BUILD_VERSION = "0.22.6";
51
51
 
52
52
  const isInteractive = (config) => {
53
53
  return config?.mode === 'interactive' || !!config?.interactive;
@@ -7966,31 +7966,64 @@ async function executeChainWithSchema(schema, llm, prompt, variables, options =
7966
7966
  */
7967
7967
  function formatCommitMessage(result, options = {}) {
7968
7968
  const { append, ticketId, appendTicket } = options;
7969
- // If it's a string, check if it contains a JSON object
7969
+ // Helper function to construct the final message with appends
7970
+ const constructMessage = (title, body) => {
7971
+ const appendedText = append ? `\n\n${append}` : '';
7972
+ const ticketFooter = appendTicket && ticketId ? `\n\nPart of **${ticketId}**` : '';
7973
+ return `${title}\n\n${body}${appendedText}${ticketFooter}`;
7974
+ };
7975
+ // If it's a string, check if it contains a JSON object (including markdown code blocks)
7970
7976
  if (typeof result === 'string') {
7971
- try {
7972
- // Try to parse as JSON to see if it's a stringified object
7973
- const parsed = JSON.parse(result);
7974
- if (parsed && typeof parsed === 'object' && parsed.title && parsed.body) {
7975
- // It's a stringified JSON object, format it properly
7976
- const appendedText = append ? `\n\n${append}` : '';
7977
- const ticketFooter = appendTicket && ticketId ? `\n\nPart of **${ticketId}**` : '';
7978
- return `${parsed.title}\n\n${parsed.body}${appendedText}${ticketFooter}`;
7977
+ // Early return if string clearly doesn't contain JSON-like content
7978
+ if (!result.includes('{') && !result.includes('"title"')) {
7979
+ return result;
7980
+ }
7981
+ // Handle multiple markdown code block formats
7982
+ const codeBlockPatterns = [
7983
+ /```(?:json)?\s*(\{[\s\S]*?\})\s*```/, // Standard markdown blocks
7984
+ /`(\{[\s\S]*?\})`/, // Inline code blocks
7985
+ /^\s*(\{[\s\S]*\})\s*$/ // Raw JSON without blocks
7986
+ ];
7987
+ let jsonString = result;
7988
+ // Try each pattern to extract JSON
7989
+ for (const pattern of codeBlockPatterns) {
7990
+ const match = result.match(pattern);
7991
+ if (match && match[1]) {
7992
+ jsonString = match[1].trim();
7993
+ break;
7979
7994
  }
7980
7995
  }
7981
- catch {
7982
- // Not valid JSON, treat as regular string
7996
+ // Only attempt JSON parsing if we found potential JSON content
7997
+ if (jsonString !== result || jsonString.startsWith('{')) {
7998
+ try {
7999
+ // Try to parse as JSON to see if it's a stringified object
8000
+ const parsed = JSON.parse(jsonString);
8001
+ if (parsed &&
8002
+ typeof parsed === 'object' &&
8003
+ typeof parsed.title === 'string' &&
8004
+ typeof parsed.body === 'string' &&
8005
+ parsed.title.length > 0 &&
8006
+ parsed.body.length > 0) {
8007
+ // It's a valid stringified JSON object, format it properly
8008
+ return constructMessage(parsed.title, parsed.body);
8009
+ }
8010
+ }
8011
+ catch {
8012
+ // Not valid JSON, continue to fallback
8013
+ }
7983
8014
  }
8015
+ // If no JSON found and it's already formatted, return as-is
7984
8016
  return result;
7985
8017
  }
7986
8018
  // If it's already an object with title and body, format it
7987
- if (typeof result === 'object' && result !== null && 'title' in result && 'body' in result) {
8019
+ if (typeof result === 'object' && result !== null &&
8020
+ 'title' in result && 'body' in result) {
7988
8021
  const commitMsgObj = result;
7989
- const appendedText = append ? `\n\n${append}` : '';
7990
- const ticketFooter = appendTicket && ticketId ? `\n\nPart of **${ticketId}**` : '';
7991
- return `${commitMsgObj.title}\n\n${commitMsgObj.body}${appendedText}${ticketFooter}`;
8022
+ if (typeof commitMsgObj.title === 'string' && typeof commitMsgObj.body === 'string') {
8023
+ return constructMessage(commitMsgObj.title, commitMsgObj.body);
8024
+ }
7992
8025
  }
7993
- // Fallback - convert to string
8026
+ // Fallback - convert to string and return as-is
7994
8027
  return String(result);
7995
8028
  }
7996
8029
 
@@ -11579,11 +11612,13 @@ ${schema.description}
11579
11612
  });
11580
11613
  },
11581
11614
  });
11582
- // Construct the full commit message
11583
- const appendedText = argv.append ? `\n\n${argv.append}` : '';
11615
+ // Construct the full commit message using the utility function
11584
11616
  const ticketId = extractTicketIdFromBranchName(branchName);
11585
- const ticketFooter = argv.appendTicket && ticketId ? `\n\nPart of **${ticketId}**` : '';
11586
- const fullMessage = `${commitMsg.title}\n\n${commitMsg.body}${appendedText}${ticketFooter}`;
11617
+ const fullMessage = formatCommitMessage(commitMsg, {
11618
+ append: argv.append,
11619
+ ticketId: ticketId || undefined,
11620
+ appendTicket: argv.appendTicket,
11621
+ });
11587
11622
  // If commitlint validation is needed and not skipped, validate the message
11588
11623
  if ((USE_CONVENTIONAL_COMMITS || hasCommitLintConfig) && !shouldSkipCommitlintValidation) {
11589
11624
  const { validateCommitMessage, CommitlintValidationError } = await Promise.resolve().then(function () { return commitlintValidator; });
@@ -11666,13 +11701,8 @@ ${schema.description}
11666
11701
  logger.verbose(`Retrying commit message generation (attempt ${attempt}): ${error.message}`, { color: 'yellow' });
11667
11702
  },
11668
11703
  });
11669
- // Ensure we always return a properly formatted commit message string
11670
- const ticketId = extractTicketIdFromBranchName(branchName);
11671
- return formatCommitMessage(result, {
11672
- append: argv.append,
11673
- ticketId: ticketId || undefined,
11674
- appendTicket: argv.appendTicket,
11675
- });
11704
+ // Return the result which is already a properly formatted commit message string
11705
+ return result;
11676
11706
  },
11677
11707
  noResult: async () => {
11678
11708
  await noResult$2({ git, logger });
package/dist/index.js CHANGED
@@ -69,7 +69,7 @@ var readline__namespace = /*#__PURE__*/_interopNamespaceDefault(readline);
69
69
  /**
70
70
  * Current build version from package.json
71
71
  */
72
- const BUILD_VERSION = "0.22.5";
72
+ const BUILD_VERSION = "0.22.6";
73
73
 
74
74
  const isInteractive = (config) => {
75
75
  return config?.mode === 'interactive' || !!config?.interactive;
@@ -7988,31 +7988,64 @@ async function executeChainWithSchema(schema, llm, prompt, variables, options =
7988
7988
  */
7989
7989
  function formatCommitMessage(result, options = {}) {
7990
7990
  const { append, ticketId, appendTicket } = options;
7991
- // If it's a string, check if it contains a JSON object
7991
+ // Helper function to construct the final message with appends
7992
+ const constructMessage = (title, body) => {
7993
+ const appendedText = append ? `\n\n${append}` : '';
7994
+ const ticketFooter = appendTicket && ticketId ? `\n\nPart of **${ticketId}**` : '';
7995
+ return `${title}\n\n${body}${appendedText}${ticketFooter}`;
7996
+ };
7997
+ // If it's a string, check if it contains a JSON object (including markdown code blocks)
7992
7998
  if (typeof result === 'string') {
7993
- try {
7994
- // Try to parse as JSON to see if it's a stringified object
7995
- const parsed = JSON.parse(result);
7996
- if (parsed && typeof parsed === 'object' && parsed.title && parsed.body) {
7997
- // It's a stringified JSON object, format it properly
7998
- const appendedText = append ? `\n\n${append}` : '';
7999
- const ticketFooter = appendTicket && ticketId ? `\n\nPart of **${ticketId}**` : '';
8000
- return `${parsed.title}\n\n${parsed.body}${appendedText}${ticketFooter}`;
7999
+ // Early return if string clearly doesn't contain JSON-like content
8000
+ if (!result.includes('{') && !result.includes('"title"')) {
8001
+ return result;
8002
+ }
8003
+ // Handle multiple markdown code block formats
8004
+ const codeBlockPatterns = [
8005
+ /```(?:json)?\s*(\{[\s\S]*?\})\s*```/, // Standard markdown blocks
8006
+ /`(\{[\s\S]*?\})`/, // Inline code blocks
8007
+ /^\s*(\{[\s\S]*\})\s*$/ // Raw JSON without blocks
8008
+ ];
8009
+ let jsonString = result;
8010
+ // Try each pattern to extract JSON
8011
+ for (const pattern of codeBlockPatterns) {
8012
+ const match = result.match(pattern);
8013
+ if (match && match[1]) {
8014
+ jsonString = match[1].trim();
8015
+ break;
8001
8016
  }
8002
8017
  }
8003
- catch {
8004
- // Not valid JSON, treat as regular string
8018
+ // Only attempt JSON parsing if we found potential JSON content
8019
+ if (jsonString !== result || jsonString.startsWith('{')) {
8020
+ try {
8021
+ // Try to parse as JSON to see if it's a stringified object
8022
+ const parsed = JSON.parse(jsonString);
8023
+ if (parsed &&
8024
+ typeof parsed === 'object' &&
8025
+ typeof parsed.title === 'string' &&
8026
+ typeof parsed.body === 'string' &&
8027
+ parsed.title.length > 0 &&
8028
+ parsed.body.length > 0) {
8029
+ // It's a valid stringified JSON object, format it properly
8030
+ return constructMessage(parsed.title, parsed.body);
8031
+ }
8032
+ }
8033
+ catch {
8034
+ // Not valid JSON, continue to fallback
8035
+ }
8005
8036
  }
8037
+ // If no JSON found and it's already formatted, return as-is
8006
8038
  return result;
8007
8039
  }
8008
8040
  // If it's already an object with title and body, format it
8009
- if (typeof result === 'object' && result !== null && 'title' in result && 'body' in result) {
8041
+ if (typeof result === 'object' && result !== null &&
8042
+ 'title' in result && 'body' in result) {
8010
8043
  const commitMsgObj = result;
8011
- const appendedText = append ? `\n\n${append}` : '';
8012
- const ticketFooter = appendTicket && ticketId ? `\n\nPart of **${ticketId}**` : '';
8013
- return `${commitMsgObj.title}\n\n${commitMsgObj.body}${appendedText}${ticketFooter}`;
8044
+ if (typeof commitMsgObj.title === 'string' && typeof commitMsgObj.body === 'string') {
8045
+ return constructMessage(commitMsgObj.title, commitMsgObj.body);
8046
+ }
8014
8047
  }
8015
- // Fallback - convert to string
8048
+ // Fallback - convert to string and return as-is
8016
8049
  return String(result);
8017
8050
  }
8018
8051
 
@@ -11601,11 +11634,13 @@ ${schema.description}
11601
11634
  });
11602
11635
  },
11603
11636
  });
11604
- // Construct the full commit message
11605
- const appendedText = argv.append ? `\n\n${argv.append}` : '';
11637
+ // Construct the full commit message using the utility function
11606
11638
  const ticketId = extractTicketIdFromBranchName(branchName);
11607
- const ticketFooter = argv.appendTicket && ticketId ? `\n\nPart of **${ticketId}**` : '';
11608
- const fullMessage = `${commitMsg.title}\n\n${commitMsg.body}${appendedText}${ticketFooter}`;
11639
+ const fullMessage = formatCommitMessage(commitMsg, {
11640
+ append: argv.append,
11641
+ ticketId: ticketId || undefined,
11642
+ appendTicket: argv.appendTicket,
11643
+ });
11609
11644
  // If commitlint validation is needed and not skipped, validate the message
11610
11645
  if ((USE_CONVENTIONAL_COMMITS || hasCommitLintConfig) && !shouldSkipCommitlintValidation) {
11611
11646
  const { validateCommitMessage, CommitlintValidationError } = await Promise.resolve().then(function () { return commitlintValidator; });
@@ -11688,13 +11723,8 @@ ${schema.description}
11688
11723
  logger.verbose(`Retrying commit message generation (attempt ${attempt}): ${error.message}`, { color: 'yellow' });
11689
11724
  },
11690
11725
  });
11691
- // Ensure we always return a properly formatted commit message string
11692
- const ticketId = extractTicketIdFromBranchName(branchName);
11693
- return formatCommitMessage(result, {
11694
- append: argv.append,
11695
- ticketId: ticketId || undefined,
11696
- appendTicket: argv.appendTicket,
11697
- });
11726
+ // Return the result which is already a properly formatted commit message string
11727
+ return result;
11698
11728
  },
11699
11729
  noResult: async () => {
11700
11730
  await noResult$2({ git, logger });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "git-coco",
3
- "version": "0.22.5",
3
+ "version": "0.22.6",
4
4
  "description": "zero-effort git commits with coco.",
5
5
  "author": "gfargo <ghfargo@gmail.com>",
6
6
  "license": "MIT",