smart-commit-copilot-cli 0.1.6 → 0.1.8

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.
Files changed (95) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/README.md +46 -4
  3. package/docs/configuration.md +99 -7
  4. package/docs/contracts.md +68 -2
  5. package/docs/getting-started.md +4 -1
  6. package/docs/publish.md +1 -1
  7. package/docs/releases/0.1.7-draft.md +55 -0
  8. package/docs/releases/0.1.8-draft.md +80 -0
  9. package/docs/roadmap.md +1 -1
  10. package/docs/verification.md +1 -0
  11. package/examples/config/smart-commit.json +32 -5
  12. package/out/cliApp.js +53 -6
  13. package/out/cliApp.js.map +1 -1
  14. package/out/commands/bridge.js +189 -6
  15. package/out/commands/bridge.js.map +1 -1
  16. package/out/commands/pullRequest.js +176 -0
  17. package/out/commands/pullRequest.js.map +1 -0
  18. package/out/commitMessage/index.js +2 -1
  19. package/out/commitMessage/index.js.map +1 -1
  20. package/out/commitMessage/prompt.js +58 -10
  21. package/out/commitMessage/prompt.js.map +1 -1
  22. package/out/commitMessage/protocol.js +168 -16
  23. package/out/commitMessage/protocol.js.map +1 -1
  24. package/out/config/cliArgs.js +114 -0
  25. package/out/config/cliArgs.js.map +1 -1
  26. package/out/config/constants.js +10 -1
  27. package/out/config/constants.js.map +1 -1
  28. package/out/config/env.js +90 -0
  29. package/out/config/env.js.map +1 -1
  30. package/out/config/file.js +113 -0
  31. package/out/config/file.js.map +1 -1
  32. package/out/config/legacySmartCommit.js +118 -9
  33. package/out/config/legacySmartCommit.js.map +1 -1
  34. package/out/config/merge.js +18 -0
  35. package/out/config/merge.js.map +1 -1
  36. package/out/config/schema.js +79 -7
  37. package/out/config/schema.js.map +1 -1
  38. package/out/contracts.js +174 -7
  39. package/out/contracts.js.map +1 -1
  40. package/out/git.js +108 -2
  41. package/out/git.js.map +1 -1
  42. package/out/output.js +4 -0
  43. package/out/output.js.map +1 -1
  44. package/out/pullRequest/api.js +528 -0
  45. package/out/pullRequest/api.js.map +1 -0
  46. package/out/pullRequest/client.js +17 -0
  47. package/out/pullRequest/client.js.map +1 -0
  48. package/out/pullRequest/config.js +18 -0
  49. package/out/pullRequest/config.js.map +1 -0
  50. package/out/pullRequest/contentPrompt.js +116 -0
  51. package/out/pullRequest/contentPrompt.js.map +1 -0
  52. package/out/pullRequest/contentService.js +77 -0
  53. package/out/pullRequest/contentService.js.map +1 -0
  54. package/out/pullRequest/index.js +25 -0
  55. package/out/pullRequest/index.js.map +1 -0
  56. package/out/pullRequest/platform.js +101 -0
  57. package/out/pullRequest/platform.js.map +1 -0
  58. package/out/pullRequest/redact.js +15 -0
  59. package/out/pullRequest/redact.js.map +1 -0
  60. package/out/pullRequest/workflow.js +153 -0
  61. package/out/pullRequest/workflow.js.map +1 -0
  62. package/out/renderOutput.js +31 -1
  63. package/out/renderOutput.js.map +1 -1
  64. package/out/reporting/aggregate.js +1 -1
  65. package/out/reporting/aggregate.js.map +1 -1
  66. package/out/reporting/mockProvider.js +5 -1
  67. package/out/reporting/mockProvider.js.map +1 -1
  68. package/out/reporting/openaiProvider.js +5 -1
  69. package/out/reporting/openaiProvider.js.map +1 -1
  70. package/out/reporting/prompt.js +145 -20
  71. package/out/reporting/prompt.js.map +1 -1
  72. package/out/reporting/render.js +24 -22
  73. package/out/reporting/render.js.map +1 -1
  74. package/out/reporting/timeWindow.js +101 -36
  75. package/out/reporting/timeWindow.js.map +1 -1
  76. package/out/reporting/types.js +3 -0
  77. package/out/reporting/types.js.map +1 -1
  78. package/out/review/mockProvider.js +25 -1
  79. package/out/review/mockProvider.js.map +1 -1
  80. package/out/stagedChangeSummary/index.js +53 -0
  81. package/out/stagedChangeSummary/index.js.map +1 -0
  82. package/out/stagedChangeSummary/mockProvider.js +24 -0
  83. package/out/stagedChangeSummary/mockProvider.js.map +1 -0
  84. package/out/stagedChangeSummary/openaiProvider.js +19 -0
  85. package/out/stagedChangeSummary/openaiProvider.js.map +1 -0
  86. package/out/stagedChangeSummary/prompt.js +138 -0
  87. package/out/stagedChangeSummary/prompt.js.map +1 -0
  88. package/out/stagedChangeSummary/provider.js +3 -0
  89. package/out/stagedChangeSummary/provider.js.map +1 -0
  90. package/out/stagedChangeSummary/render.js +74 -0
  91. package/out/stagedChangeSummary/render.js.map +1 -0
  92. package/package.json +1 -1
  93. package/src/git-commit-message-skills/conventional/SKILL.md +3 -3
  94. package/src/git-commit-message-skills/gitmoji/SKILL.md +3 -3
  95. package/src/git-commit-message-skills/semantic/SKILL.md +3 -3
@@ -0,0 +1,176 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.EXIT_CODE_RUNTIME_ERROR = exports.EXIT_CODE_CONFIG_ERROR = exports.EXIT_CODE_SUCCESS = void 0;
37
+ exports.runPullRequestCreateCommand = runPullRequestCreateCommand;
38
+ const fs = __importStar(require("node:fs"));
39
+ const path = __importStar(require("node:path"));
40
+ const config_1 = require("../config");
41
+ const contracts_1 = require("../contracts");
42
+ const git_1 = require("../git");
43
+ const output_1 = require("../output");
44
+ const pullRequest_1 = require("../pullRequest");
45
+ const redact_1 = require("../pullRequest/redact");
46
+ exports.EXIT_CODE_SUCCESS = 0;
47
+ exports.EXIT_CODE_CONFIG_ERROR = 3;
48
+ exports.EXIT_CODE_RUNTIME_ERROR = 4;
49
+ class PullRequestConfigError extends Error {
50
+ constructor(message) {
51
+ super(message);
52
+ this.name = "PullRequestConfigError";
53
+ }
54
+ }
55
+ async function runPullRequestCreateCommand(argv, env = process.env) {
56
+ const dryRun = argv.includes("--dry-run");
57
+ const configArgv = argv.filter((token) => token !== "--dry-run");
58
+ const fallbackConfig = (0, output_1.redactCliConfig)((0, config_1.resolveCliConfig)({
59
+ argv: [],
60
+ env: {},
61
+ validate: false,
62
+ requireConnection: false
63
+ }).config);
64
+ let resolved;
65
+ try {
66
+ resolved = (0, config_1.resolveCliConfig)({
67
+ argv: configArgv,
68
+ env,
69
+ validate: true,
70
+ requireConnection: true
71
+ });
72
+ validatePullRequestCommandConfig(resolved.config);
73
+ }
74
+ catch (error) {
75
+ return buildErrorResult("CONFIG_ERROR", error instanceof Error ? error.message : String(error), null, dryRun, fallbackConfig);
76
+ }
77
+ try {
78
+ const repositoryPath = await resolveRepositoryPath(resolved.runtime.repositoryPath);
79
+ const result = await (0, pullRequest_1.createPullRequestFromCurrentBranch)({
80
+ repositoryPath,
81
+ config: resolved.config,
82
+ client: (0, pullRequest_1.createOpenAICompatiblePullRequestContentClient)(resolved.config),
83
+ dryRun
84
+ });
85
+ return {
86
+ exitCode: exports.EXIT_CODE_SUCCESS,
87
+ payload: {
88
+ schemaVersion: contracts_1.SMART_COMMIT_CLI_SCHEMA_VERSION,
89
+ status: result.status,
90
+ command: "pull-request create",
91
+ repositoryPath,
92
+ platform: result.platform,
93
+ sourceBranch: result.sourceBranch,
94
+ targetBranch: result.targetBranch,
95
+ title: result.title,
96
+ url: result.url,
97
+ warnings: result.warnings,
98
+ dryRun,
99
+ config: (0, output_1.redactCliConfig)(resolved.config),
100
+ summary: buildSummary(result.status, result.url)
101
+ }
102
+ };
103
+ }
104
+ catch (error) {
105
+ const code = error instanceof PullRequestConfigError ? "CONFIG_ERROR" : "RUNTIME_ERROR";
106
+ const message = redactPullRequestError(resolved.config, error instanceof Error ? error.message : String(error));
107
+ return buildErrorResult(code, message, resolved, dryRun, (0, output_1.redactCliConfig)(resolved.config));
108
+ }
109
+ }
110
+ function redactPullRequestError(config, message) {
111
+ return (0, redact_1.redactSensitiveText)(message, [config.pullRequest.authToken]);
112
+ }
113
+ function validatePullRequestCommandConfig(config) {
114
+ (0, config_1.validateCliConfig)(config, { requireConnection: true });
115
+ if (!config.pullRequest.targetBranch.trim()) {
116
+ throw new PullRequestConfigError("--target-branch or pullRequest.targetBranch is required.");
117
+ }
118
+ if (!config.pullRequest.authToken.trim()) {
119
+ throw new PullRequestConfigError("--auth-token or SMART_COMMIT_PULL_REQUEST_AUTH_TOKEN is required.");
120
+ }
121
+ }
122
+ function buildErrorResult(code, message, resolved, dryRun, config) {
123
+ return {
124
+ exitCode: code === "CONFIG_ERROR" ? exports.EXIT_CODE_CONFIG_ERROR : exports.EXIT_CODE_RUNTIME_ERROR,
125
+ payload: {
126
+ schemaVersion: contracts_1.SMART_COMMIT_CLI_SCHEMA_VERSION,
127
+ status: "error",
128
+ command: "pull-request create",
129
+ repositoryPath: resolved?.runtime.repositoryPath ? path.resolve(resolved.runtime.repositoryPath) : null,
130
+ platform: null,
131
+ sourceBranch: null,
132
+ targetBranch: resolved?.config.pullRequest.targetBranch || null,
133
+ title: null,
134
+ url: null,
135
+ warnings: [],
136
+ dryRun,
137
+ config,
138
+ summary: message,
139
+ error: { code, message }
140
+ }
141
+ };
142
+ }
143
+ function buildSummary(status, url) {
144
+ if (status === "created") {
145
+ return `Created pull request / merge request: ${url ?? "(no url returned)"}`;
146
+ }
147
+ if (status === "existing") {
148
+ return `Pull request / merge request already exists: ${url ?? "(no url returned)"}`;
149
+ }
150
+ if (status === "ready") {
151
+ return "Pull request / merge request content is ready; dry-run did not create it.";
152
+ }
153
+ return "Pull request / merge request creation failed.";
154
+ }
155
+ async function resolveRepositoryPath(repositoryPath) {
156
+ if (!repositoryPath) {
157
+ throw new PullRequestConfigError("--repo is required for pull-request create.");
158
+ }
159
+ const resolved = path.resolve(repositoryPath);
160
+ if (!fs.existsSync(resolved)) {
161
+ throw new PullRequestConfigError(`Repository path not found: ${repositoryPath}`);
162
+ }
163
+ if (!fs.statSync(resolved).isDirectory()) {
164
+ throw new PullRequestConfigError(`Repository path must be a directory: ${repositoryPath}`);
165
+ }
166
+ try {
167
+ return await (0, git_1.resolveGitRepositoryRoot)(resolved);
168
+ }
169
+ catch (error) {
170
+ if (error instanceof git_1.GitExecutionError) {
171
+ throw new PullRequestConfigError(`Repository path is not inside a Git repository: ${repositoryPath}`);
172
+ }
173
+ throw error;
174
+ }
175
+ }
176
+ //# sourceMappingURL=pullRequest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pullRequest.js","sourceRoot":"","sources":["../../src/commands/pullRequest.ts"],"names":[],"mappings":"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"}
@@ -74,6 +74,7 @@ function buildGenerationInput(input, userDraft) {
74
74
  diff: input.diff,
75
75
  changedFiles: input.changedFiles,
76
76
  language: input.config.commitMessage.language,
77
+ structure: input.config.commitMessage.structure,
77
78
  protocol: input.config.commitMessage.validation.protocol,
78
79
  ...(userDraft ? { userDraft } : {})
79
80
  };
@@ -107,7 +108,7 @@ function tryValidateGeneratedCommitMessage(rawCommitMessage, config, branchName)
107
108
  return {
108
109
  ok: true,
109
110
  message: (0, protocol_1.validateAndFinalizeCommitMessage)({
110
- rawCommitMessage: (0, protocol_1.normalizeCommitMessage)(rawCommitMessage),
111
+ rawCommitMessage,
111
112
  config,
112
113
  branchName
113
114
  })
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commitMessage/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commitMessage/index.ts"],"names":[],"mappings":"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"}
@@ -4,11 +4,12 @@ exports.buildCommitMessageMessages = buildCommitMessageMessages;
4
4
  exports.buildCommitMessageRepairMessages = buildCommitMessageRepairMessages;
5
5
  function buildCommitMessageMessages(input, options = {}) {
6
6
  const protocolLabel = formatCommitMessageProtocolLabel(input.protocol);
7
+ const structure = input.structure ?? "subjectOnly";
7
8
  return [
8
9
  {
9
10
  role: "system",
10
11
  content: [
11
- "You generate a single-line git commit message.",
12
+ buildCommitMessageSystemIntro(structure),
12
13
  "You must obey the requested commit message language.",
13
14
  protocolLabel === null
14
15
  ? "No built-in commit-message protocol is enforced."
@@ -24,8 +25,9 @@ function buildCommitMessageMessages(input, options = {}) {
24
25
  `Repository: ${input.repositoryPath}`,
25
26
  `Branch: ${input.branchName ?? "(unknown)"}`,
26
27
  `Language: ${input.language}`,
28
+ `Commit message structure: ${structure}`,
27
29
  `Commit message protocol: ${protocolLabel ?? "none"}`,
28
- ...(buildCommitMessageOutputRules(input.protocol)),
30
+ ...(buildCommitMessageOutputRules(input.protocol, structure)),
29
31
  `Changed files (${input.changedFiles.length}):`,
30
32
  ...input.changedFiles.map((file) => `- ${file}`),
31
33
  "",
@@ -44,15 +46,16 @@ function buildCommitMessageMessages(input, options = {}) {
44
46
  }
45
47
  function buildCommitMessageRepairMessages(input, options = {}) {
46
48
  const protocolLabel = formatCommitMessageProtocolLabel(input.generationInput.protocol);
49
+ const structure = input.generationInput.structure ?? "subjectOnly";
47
50
  return [
48
51
  {
49
52
  role: "system",
50
53
  content: [
51
- "You are repairing an invalid single-line git commit message.",
54
+ buildCommitMessageRepairSystemIntro(structure),
52
55
  "You must obey the requested commit message language.",
53
56
  protocolLabel === null
54
57
  ? "No built-in commit-message protocol is enforced."
55
- : `You must repair it into a valid ${protocolLabel} subject.`,
58
+ : `You must repair the subject into valid ${protocolLabel} format.`,
56
59
  "Return plain text only.",
57
60
  "Do not return explanations or JSON.",
58
61
  ...(options.promptAugmentation?.length ? ["", ...options.promptAugmentation] : [])
@@ -64,8 +67,9 @@ function buildCommitMessageRepairMessages(input, options = {}) {
64
67
  `Repository: ${input.generationInput.repositoryPath}`,
65
68
  `Branch: ${input.generationInput.branchName ?? "(unknown)"}`,
66
69
  `Language: ${input.generationInput.language}`,
70
+ `Commit message structure: ${structure}`,
67
71
  `Commit message protocol: ${protocolLabel ?? "none"}`,
68
- ...(buildCommitMessageOutputRules(input.generationInput.protocol)),
72
+ ...(buildCommitMessageOutputRules(input.generationInput.protocol, structure)),
69
73
  "",
70
74
  "Invalid previous response:",
71
75
  input.invalidResponse,
@@ -76,17 +80,18 @@ function buildCommitMessageRepairMessages(input, options = {}) {
76
80
  }
77
81
  ];
78
82
  }
79
- function buildCommitMessageOutputRules(protocol) {
83
+ function buildCommitMessageOutputRules(protocol, structure) {
84
+ const structureRules = buildCommitMessageStructureRules(structure);
80
85
  if (protocol === "gitmoji") {
81
- return ["Output rule: return a single-line Gitmoji subject only."];
86
+ return [...structureRules, "Protocol rule: the subject must be a single-line Gitmoji subject."];
82
87
  }
83
88
  if (protocol === "semantic") {
84
- return ["Output rule: return a single-line Semantic Commits subject only."];
89
+ return [...structureRules, "Protocol rule: the subject must be a single-line Semantic Commits subject."];
85
90
  }
86
91
  if (protocol === "conventional") {
87
- return ["Output rule: return a single-line Conventional Commits subject only."];
92
+ return [...structureRules, "Protocol rule: the subject must be a single-line Conventional Commits subject."];
88
93
  }
89
- return ["Output rule: return a single-line git commit subject only."];
94
+ return [...structureRules, "Protocol rule: no built-in subject protocol is enforced."];
90
95
  }
91
96
  function formatCommitMessageProtocolLabel(protocol) {
92
97
  if (protocol === "gitmoji") {
@@ -100,4 +105,47 @@ function formatCommitMessageProtocolLabel(protocol) {
100
105
  }
101
106
  return null;
102
107
  }
108
+ function buildCommitMessageSystemIntro(structure) {
109
+ if (structure === "subjectOnly") {
110
+ return "You generate a single-line git commit message.";
111
+ }
112
+ if (structure === "subjectBody") {
113
+ return "You generate a git commit message with a subject and optional body.";
114
+ }
115
+ return "You generate a git commit message with a subject, optional body, and optional footer.";
116
+ }
117
+ function buildCommitMessageRepairSystemIntro(structure) {
118
+ if (structure === "subjectOnly") {
119
+ return "You are repairing an invalid single-line git commit message.";
120
+ }
121
+ if (structure === "subjectBody") {
122
+ return "You are repairing an invalid git commit message with a subject and optional body.";
123
+ }
124
+ return "You are repairing an invalid git commit message with a subject, optional body, and optional footer.";
125
+ }
126
+ function buildCommitMessageStructureRules(structure) {
127
+ if (structure === "subjectOnly") {
128
+ return [
129
+ "Output rule: return exactly one git commit subject line only.",
130
+ "If the staged diff is ambiguous, choose the single best subject and return only that one line."
131
+ ];
132
+ }
133
+ if (structure === "subjectBody") {
134
+ return [
135
+ "Output rule: return a git commit message with this maximum structure: subject plus optional body.",
136
+ "The subject must be the first line.",
137
+ "Body is optional; if the staged diff is simple, return only the subject.",
138
+ "If you include a body, separate it from the subject with one blank line.",
139
+ "Do not include footer or trailer lines."
140
+ ];
141
+ }
142
+ return [
143
+ "Output rule: return a git commit message with this maximum structure: subject plus optional body plus optional footer.",
144
+ "The subject must be the first line.",
145
+ "Body and footer are optional; if the staged diff is simple, return only the subject.",
146
+ "If you include body or footer content, separate each section with one blank line.",
147
+ "Include footer/trailer lines only when there is explicit evidence for them, such as breaking changes, issue references, co-authors, or sign-offs.",
148
+ "Footer/trailer lines must use Git trailer or Conventional Commits footer style, such as `Refs: #123`, `Signed-off-by: Name <email>`, or `BREAKING CHANGE: description`."
149
+ ];
150
+ }
103
151
  //# sourceMappingURL=prompt.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/commitMessage/prompt.ts"],"names":[],"mappings":";;AAYA,gEA0CC;AAED,4EAqCC;AAjFD,SAAgB,0BAA0B,CACxC,KAAmC,EACnC,UAAsD,EAAE;IAExD,MAAM,aAAa,GAAG,gCAAgC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACvE,OAAO;QACL;YACE,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE;gBACP,gDAAgD;gBAChD,sDAAsD;gBACtD,aAAa,KAAK,IAAI;oBACpB,CAAC,CAAC,kDAAkD;oBACpD,CAAC,CAAC,2DAA2D,aAAa,GAAG;gBAC/E,yBAAyB;gBACzB,yDAAyD;gBACzD,GAAG,CAAC,OAAO,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;aACnF,CAAC,IAAI,CAAC,GAAG,CAAC;SACZ;QACD;YACE,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE;gBACP,eAAe,KAAK,CAAC,cAAc,EAAE;gBACrC,WAAW,KAAK,CAAC,UAAU,IAAI,WAAW,EAAE;gBAC5C,aAAa,KAAK,CAAC,QAAQ,EAAE;gBAC7B,4BAA4B,aAAa,IAAI,MAAM,EAAE;gBACrD,GAAG,CAAC,6BAA6B,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBAClD,kBAAkB,KAAK,CAAC,YAAY,CAAC,MAAM,IAAI;gBAC/C,GAAG,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC;gBAChD,EAAE;gBACF,GAAG,CAAC,KAAK,CAAC,SAAS;oBACjB,CAAC,CAAC;wBACE,aAAa;wBACb,KAAK,CAAC,SAAS;wBACf,EAAE;qBACH;oBACH,CAAC,CAAC,EAAE,CAAC;gBACP,cAAc;gBACd,KAAK,CAAC,IAAI;aACX,CAAC,IAAI,CAAC,IAAI,CAAC;SACb;KACF,CAAC;AACJ,CAAC;AAED,SAAgB,gCAAgC,CAAC,KAIhD,EAAE,UAAsD,EAAE;IACzD,MAAM,aAAa,GAAG,gCAAgC,CAAC,KAAK,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;IACvF,OAAO;QACL;YACE,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE;gBACP,8DAA8D;gBAC9D,sDAAsD;gBACtD,aAAa,KAAK,IAAI;oBACpB,CAAC,CAAC,kDAAkD;oBACpD,CAAC,CAAC,mCAAmC,aAAa,WAAW;gBAC/D,yBAAyB;gBACzB,qCAAqC;gBACrC,GAAG,CAAC,OAAO,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;aACnF,CAAC,IAAI,CAAC,GAAG,CAAC;SACZ;QACD;YACE,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE;gBACP,eAAe,KAAK,CAAC,eAAe,CAAC,cAAc,EAAE;gBACrD,WAAW,KAAK,CAAC,eAAe,CAAC,UAAU,IAAI,WAAW,EAAE;gBAC5D,aAAa,KAAK,CAAC,eAAe,CAAC,QAAQ,EAAE;gBAC7C,4BAA4B,aAAa,IAAI,MAAM,EAAE;gBACrD,GAAG,CAAC,6BAA6B,CAAC,KAAK,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;gBAClE,EAAE;gBACF,4BAA4B;gBAC5B,KAAK,CAAC,eAAe;gBACrB,EAAE;gBACF,gBAAgB;gBAChB,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC;aAC7C,CAAC,IAAI,CAAC,IAAI,CAAC;SACb;KACF,CAAC;AACJ,CAAC;AAED,SAAS,6BAA6B,CACpC,QAAkD;IAElD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,CAAC,yDAAyD,CAAC,CAAC;IACrE,CAAC;IAED,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;QAC5B,OAAO,CAAC,kEAAkE,CAAC,CAAC;IAC9E,CAAC;IAED,IAAI,QAAQ,KAAK,cAAc,EAAE,CAAC;QAChC,OAAO,CAAC,sEAAsE,CAAC,CAAC;IAClF,CAAC;IAED,OAAO,CAAC,4DAA4D,CAAC,CAAC;AACxE,CAAC;AAED,SAAS,gCAAgC,CACvC,QAAkD;IAElD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;QAC5B,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IAED,IAAI,QAAQ,KAAK,cAAc,EAAE,CAAC;QAChC,OAAO,sBAAsB,CAAC;IAChC,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/commitMessage/prompt.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CommitMessageFlowError = void 0;
4
4
  exports.normalizeCommitMessage = normalizeCommitMessage;
5
+ exports.normalizeCommitMessageForStructure = normalizeCommitMessageForStructure;
5
6
  exports.ensureTicketIdFromBranchIfMissing = ensureTicketIdFromBranchIfMissing;
6
7
  exports.validateAndFinalizeCommitMessage = validateAndFinalizeCommitMessage;
7
8
  exports.validateLanguageText = validateLanguageText;
@@ -22,6 +23,7 @@ const conventionalTypes = new Set([
22
23
  ]);
23
24
  const typedCommitSubjectPattern = /^([a-z]+)(\([^)]+\))?(!)?: (.+)$/;
24
25
  const gitmojiSubjectPattern = /^\S+\s+(.+)$/u;
26
+ const footerLinePattern = /^(?:BREAKING CHANGE|[A-Za-z0-9-]+):\s+\S.*$/;
25
27
  const cjkPattern = /[\u3400-\u9fff]/;
26
28
  const japaneseKanaPattern = /[\u3040-\u30FF\u31F0-\u31FF\uFF66-\uFF9D]/;
27
29
  const japanesePattern = /[\u3040-\u30FF\u31F0-\u31FF\u3400-\u9fff\uFF66-\uFF9D]/;
@@ -39,7 +41,12 @@ const ticketLikeIdPatterns = [
39
41
  const leadingTicketLikeIdPattern = /^(?:[A-Z][A-Z0-9]+-\d+|#\d+|(?:task|bugfix|bug|issue|story|feature|hotfix|ticket)-\d+)\s+/i;
40
42
  const branchTicketLikeIdPattern = /[A-Za-z][A-Za-z0-9]+-\d+/g;
41
43
  const outputLanguageDefinitions = {
42
- zh: {
44
+ "zh-cn": {
45
+ validationMode: "script",
46
+ requiredPattern: cjkPattern,
47
+ requiredDescription: "Chinese text"
48
+ },
49
+ "zh-tw": {
43
50
  validationMode: "script",
44
51
  requiredPattern: cjkPattern,
45
52
  requiredDescription: "Chinese text"
@@ -111,36 +118,54 @@ function normalizeCommitMessage(raw) {
111
118
  .split("\n")[0]
112
119
  .trim();
113
120
  }
121
+ function normalizeCommitMessageForStructure(raw, structure) {
122
+ const sections = parseCommitMessageSections(raw);
123
+ return structure === "subjectOnly" ? sections.subject : sections.normalized;
124
+ }
114
125
  function ensureTicketIdFromBranchIfMissing(commitMessage, branchName) {
115
126
  const subject = normalizeCommitMessage(commitMessage);
116
127
  if (!subject || !branchName?.trim()) {
117
- return subject;
128
+ return normalizeCommitMessageForStructure(commitMessage, "subjectBodyFooter");
118
129
  }
119
130
  if (containsTicketLikeId(subject)) {
120
- return subject;
131
+ return normalizeCommitMessageForStructure(commitMessage, "subjectBodyFooter");
121
132
  }
122
133
  const ticket = extractTicketLikeIdFromBranch(branchName);
123
134
  if (!ticket) {
124
- return subject;
135
+ return normalizeCommitMessageForStructure(commitMessage, "subjectBodyFooter");
125
136
  }
137
+ let updatedSubject;
126
138
  const typedMatch = subject.match(typedCommitSubjectPattern);
127
139
  if (typedMatch) {
128
140
  const type = typedMatch[1] ?? "";
129
141
  const scope = typedMatch[2] ?? "";
130
142
  const breaking = typedMatch[3] ?? "";
131
143
  const summary = (typedMatch[4] ?? "").trim();
132
- return `${type}${scope}${breaking}: ${ticket} ${summary}`;
144
+ updatedSubject = `${type}${scope}${breaking}: ${ticket} ${summary}`;
133
145
  }
134
- const gitmojiMatch = subject.match(gitmojiSubjectPattern);
135
- if (gitmojiMatch) {
136
- const emoji = subject.split(/\s+/u)[0] ?? "";
137
- const summary = gitmojiMatch[1]?.trim() ?? "";
138
- return `${emoji} ${ticket} ${summary}`.trim();
146
+ else {
147
+ const gitmojiMatch = subject.match(gitmojiSubjectPattern);
148
+ if (gitmojiMatch) {
149
+ const emoji = subject.split(/\s+/u)[0] ?? "";
150
+ const summary = gitmojiMatch[1]?.trim() ?? "";
151
+ updatedSubject = `${emoji} ${ticket} ${summary}`.trim();
152
+ }
153
+ else {
154
+ updatedSubject = `${ticket} ${subject}`;
155
+ }
139
156
  }
140
- return `${ticket} ${subject}`;
157
+ return replaceCommitMessageSubject(commitMessage, updatedSubject);
141
158
  }
142
159
  function validateAndFinalizeCommitMessage(input) {
143
- let commitMessage = normalizeCommitMessage(input.rawCommitMessage);
160
+ const structure = input.config.commitMessage.structure;
161
+ const structureIssues = validateCommitMessageStructure(input.rawCommitMessage, structure);
162
+ if (structureIssues.length > 0) {
163
+ if (structureIssues.includes("response must not be empty")) {
164
+ throw new CommitMessageFlowError("COMMIT_MESSAGE_REQUIRED", "Commit message must not be empty.");
165
+ }
166
+ throw new CommitMessageFlowError("COMMIT_MESSAGE_INVALID", `Commit message validation failed: ${structureIssues.join("; ")}`);
167
+ }
168
+ let commitMessage = normalizeCommitMessageForStructure(input.rawCommitMessage, structure);
144
169
  if (!commitMessage) {
145
170
  throw new CommitMessageFlowError("COMMIT_MESSAGE_REQUIRED", "Commit message must not be empty.");
146
171
  }
@@ -149,16 +174,17 @@ function validateAndFinalizeCommitMessage(input) {
149
174
  }
150
175
  const issues = [];
151
176
  const protocol = input.config.commitMessage.validation.protocol;
177
+ const subject = normalizeCommitMessage(commitMessage);
152
178
  if (protocol !== "none") {
153
- issues.push(...validateCommitMessageProtocol(commitMessage, input.config.commitMessage.language, protocol));
179
+ issues.push(...validateCommitMessageProtocol(subject, input.config.commitMessage.language, protocol));
154
180
  }
155
- if (input.config.commitMessage.validation.requireTicketIdInMessage && !containsTicketLikeId(commitMessage)) {
181
+ if (input.config.commitMessage.validation.requireTicketIdInMessage && !containsTicketLikeId(subject)) {
156
182
  issues.push("commit message must contain a ticket-like ID");
157
183
  }
158
184
  if (input.config.commitMessage.validation.pattern) {
159
185
  const regex = new RegExp(input.config.commitMessage.validation.pattern);
160
- if (!regex.test(commitMessage)) {
161
- issues.push("commit message does not match the configured validation pattern");
186
+ if (!regex.test(subject)) {
187
+ issues.push("commit message subject does not match the configured validation pattern");
162
188
  }
163
189
  }
164
190
  if (issues.length > 0) {
@@ -196,6 +222,34 @@ function containsTicketLikeId(raw) {
196
222
  const subject = normalizeCommitMessage(raw);
197
223
  return subject.length > 0 && ticketLikeIdPatterns.some((pattern) => pattern.test(subject));
198
224
  }
225
+ function validateCommitMessageStructure(raw, structure) {
226
+ const issues = [];
227
+ const trimmed = raw.trim();
228
+ if (!trimmed) {
229
+ return ["response must not be empty"];
230
+ }
231
+ if (trimmed.includes("```")) {
232
+ issues.push("response must not use markdown code fences");
233
+ }
234
+ const sections = parseCommitMessageSections(raw);
235
+ issues.push(...sections.issues);
236
+ if (!sections.subject) {
237
+ issues.push("response must contain a non-empty subject after normalization");
238
+ }
239
+ if (structure === "subjectOnly") {
240
+ const nonEmptyLines = trimmed
241
+ .split(/\r?\n/)
242
+ .map((line) => line.trim())
243
+ .filter((line) => line.length > 0);
244
+ if (nonEmptyLines.length !== 1) {
245
+ issues.push("response must contain exactly one non-empty line");
246
+ }
247
+ }
248
+ if (structure === "subjectBody" && sections.hasFooter) {
249
+ issues.push("response must not include a footer when commitMessage.structure is subjectBody");
250
+ }
251
+ return issues;
252
+ }
199
253
  function validateCommitMessageProtocol(commitMessage, language, protocol) {
200
254
  if (protocol === "gitmoji") {
201
255
  return validateGitmojiSubject(commitMessage, language);
@@ -237,4 +291,102 @@ function validateGitmojiSubject(subject, language) {
237
291
  const summaryWithoutLeadingTicket = summary.replace(leadingTicketLikeIdPattern, "").trim() || summary;
238
292
  return validateLanguageText(summaryWithoutLeadingTicket, language, "summary");
239
293
  }
294
+ function parseCommitMessageSections(raw) {
295
+ const trimmed = raw.trim();
296
+ if (!trimmed) {
297
+ return {
298
+ subject: "",
299
+ body: "",
300
+ footer: "",
301
+ hasFooter: false,
302
+ normalized: "",
303
+ issues: []
304
+ };
305
+ }
306
+ const lines = trimmed.split(/\r?\n/).map((line) => line.trimEnd());
307
+ const subjectIndex = lines.findIndex((line) => line.trim().length > 0);
308
+ if (subjectIndex === -1) {
309
+ return {
310
+ subject: "",
311
+ body: "",
312
+ footer: "",
313
+ hasFooter: false,
314
+ normalized: "",
315
+ issues: []
316
+ };
317
+ }
318
+ const subject = normalizeCommitMessage(lines[subjectIndex] ?? "");
319
+ const linesAfterSubject = lines.slice(subjectIndex + 1);
320
+ const hasContentAfterSubject = linesAfterSubject.some((line) => line.trim().length > 0);
321
+ const issues = [];
322
+ if (!hasContentAfterSubject) {
323
+ return {
324
+ subject,
325
+ body: "",
326
+ footer: "",
327
+ hasFooter: false,
328
+ normalized: subject,
329
+ issues
330
+ };
331
+ }
332
+ if ((linesAfterSubject[0] ?? "").trim().length > 0) {
333
+ issues.push("body or footer must be separated from the subject by a blank line");
334
+ }
335
+ const contentLines = trimBlankLines(linesAfterSubject);
336
+ const paragraphs = splitParagraphs(contentLines);
337
+ const footerParagraph = paragraphs.length > 0 && isFooterParagraph(paragraphs[paragraphs.length - 1] ?? [])
338
+ ? paragraphs[paragraphs.length - 1]
339
+ : undefined;
340
+ const bodyParagraphs = footerParagraph ? paragraphs.slice(0, -1) : paragraphs;
341
+ const body = bodyParagraphs
342
+ .map((paragraph) => paragraph.join("\n").trim())
343
+ .filter(Boolean)
344
+ .join("\n\n");
345
+ const footer = footerParagraph ? footerParagraph.join("\n").trim() : "";
346
+ const normalized = [subject, body, footer].filter((section) => section.length > 0).join("\n\n");
347
+ return {
348
+ subject,
349
+ body,
350
+ footer,
351
+ hasFooter: footer.length > 0,
352
+ normalized,
353
+ issues
354
+ };
355
+ }
356
+ function replaceCommitMessageSubject(raw, subject) {
357
+ const sections = parseCommitMessageSections(raw);
358
+ return [subject, sections.body, sections.footer].filter((section) => section.length > 0).join("\n\n");
359
+ }
360
+ function trimBlankLines(lines) {
361
+ let start = 0;
362
+ let end = lines.length;
363
+ while (start < end && lines[start]?.trim().length === 0) {
364
+ start += 1;
365
+ }
366
+ while (end > start && lines[end - 1]?.trim().length === 0) {
367
+ end -= 1;
368
+ }
369
+ return lines.slice(start, end);
370
+ }
371
+ function splitParagraphs(lines) {
372
+ const paragraphs = [];
373
+ let current = [];
374
+ for (const line of lines) {
375
+ if (line.trim().length === 0) {
376
+ if (current.length > 0) {
377
+ paragraphs.push(current);
378
+ current = [];
379
+ }
380
+ continue;
381
+ }
382
+ current.push(line);
383
+ }
384
+ if (current.length > 0) {
385
+ paragraphs.push(current);
386
+ }
387
+ return paragraphs;
388
+ }
389
+ function isFooterParagraph(lines) {
390
+ return lines.length > 0 && lines.every((line) => footerLinePattern.test(line.trim()));
391
+ }
240
392
  //# sourceMappingURL=protocol.js.map