git-smart-flow 0.3.0

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 (190) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/LICENSE +21 -0
  3. package/README.md +130 -0
  4. package/bin/git-smart-flow.js +2 -0
  5. package/bin/gsf.js +2 -0
  6. package/bin/gsfc.js +3 -0
  7. package/bin/gsfm.js +3 -0
  8. package/bin/gsfp.js +3 -0
  9. package/bin/gsfpr.js +3 -0
  10. package/dist/cli.d.ts +2 -0
  11. package/dist/cli.js +214 -0
  12. package/dist/cli.js.map +1 -0
  13. package/dist/commands/aliases.d.ts +2 -0
  14. package/dist/commands/aliases.js +37 -0
  15. package/dist/commands/aliases.js.map +1 -0
  16. package/dist/commands/branch.d.ts +2 -0
  17. package/dist/commands/branch.js +414 -0
  18. package/dist/commands/branch.js.map +1 -0
  19. package/dist/commands/commit-message.d.ts +7 -0
  20. package/dist/commands/commit-message.js +95 -0
  21. package/dist/commands/commit-message.js.map +1 -0
  22. package/dist/commands/commit.d.ts +3 -0
  23. package/dist/commands/commit.js +597 -0
  24. package/dist/commands/commit.js.map +1 -0
  25. package/dist/commands/config.d.ts +2 -0
  26. package/dist/commands/config.js +88 -0
  27. package/dist/commands/config.js.map +1 -0
  28. package/dist/commands/doctor.d.ts +2 -0
  29. package/dist/commands/doctor.js +246 -0
  30. package/dist/commands/doctor.js.map +1 -0
  31. package/dist/commands/info.d.ts +2 -0
  32. package/dist/commands/info.js +155 -0
  33. package/dist/commands/info.js.map +1 -0
  34. package/dist/commands/install-hooks.d.ts +2 -0
  35. package/dist/commands/install-hooks.js +66 -0
  36. package/dist/commands/install-hooks.js.map +1 -0
  37. package/dist/commands/log.d.ts +2 -0
  38. package/dist/commands/log.js +101 -0
  39. package/dist/commands/log.js.map +1 -0
  40. package/dist/commands/menu.d.ts +2 -0
  41. package/dist/commands/menu.js +297 -0
  42. package/dist/commands/menu.js.map +1 -0
  43. package/dist/commands/merge.d.ts +6 -0
  44. package/dist/commands/merge.js +128 -0
  45. package/dist/commands/merge.js.map +1 -0
  46. package/dist/commands/pr.d.ts +2 -0
  47. package/dist/commands/pr.js +731 -0
  48. package/dist/commands/pr.js.map +1 -0
  49. package/dist/commands/push.d.ts +7 -0
  50. package/dist/commands/push.js +225 -0
  51. package/dist/commands/push.js.map +1 -0
  52. package/dist/commands/reflog.d.ts +2 -0
  53. package/dist/commands/reflog.js +162 -0
  54. package/dist/commands/reflog.js.map +1 -0
  55. package/dist/commands/repo-init.d.ts +2 -0
  56. package/dist/commands/repo-init.js +466 -0
  57. package/dist/commands/repo-init.js.map +1 -0
  58. package/dist/commands/revert.d.ts +7 -0
  59. package/dist/commands/revert.js +694 -0
  60. package/dist/commands/revert.js.map +1 -0
  61. package/dist/commands/setup.d.ts +2 -0
  62. package/dist/commands/setup.js +86 -0
  63. package/dist/commands/setup.js.map +1 -0
  64. package/dist/commands/stash.d.ts +2 -0
  65. package/dist/commands/stash.js +130 -0
  66. package/dist/commands/stash.js.map +1 -0
  67. package/dist/commands/sync.d.ts +2 -0
  68. package/dist/commands/sync.js +335 -0
  69. package/dist/commands/sync.js.map +1 -0
  70. package/dist/commands/tag.d.ts +2 -0
  71. package/dist/commands/tag.js +163 -0
  72. package/dist/commands/tag.js.map +1 -0
  73. package/dist/commands/validate.d.ts +2 -0
  74. package/dist/commands/validate.js +203 -0
  75. package/dist/commands/validate.js.map +1 -0
  76. package/dist/config/config.d.ts +10 -0
  77. package/dist/config/config.js +126 -0
  78. package/dist/config/config.js.map +1 -0
  79. package/dist/git/ai-context-builder.d.ts +11 -0
  80. package/dist/git/ai-context-builder.js +112 -0
  81. package/dist/git/ai-context-builder.js.map +1 -0
  82. package/dist/git/convention-detector.d.ts +3 -0
  83. package/dist/git/convention-detector.js +211 -0
  84. package/dist/git/convention-detector.js.map +1 -0
  85. package/dist/git/ensure-repo.d.ts +7 -0
  86. package/dist/git/ensure-repo.js +141 -0
  87. package/dist/git/ensure-repo.js.map +1 -0
  88. package/dist/git/gitignore.d.ts +8 -0
  89. package/dist/git/gitignore.js +261 -0
  90. package/dist/git/gitignore.js.map +1 -0
  91. package/dist/git/remote-setup.d.ts +2 -0
  92. package/dist/git/remote-setup.js +129 -0
  93. package/dist/git/remote-setup.js.map +1 -0
  94. package/dist/git/repo.d.ts +73 -0
  95. package/dist/git/repo.js +308 -0
  96. package/dist/git/repo.js.map +1 -0
  97. package/dist/git/validate.d.ts +36 -0
  98. package/dist/git/validate.js +113 -0
  99. package/dist/git/validate.js.map +1 -0
  100. package/dist/providers/base.provider.d.ts +10 -0
  101. package/dist/providers/base.provider.js +40 -0
  102. package/dist/providers/base.provider.js.map +1 -0
  103. package/dist/providers/claude.provider.d.ts +14 -0
  104. package/dist/providers/claude.provider.js +85 -0
  105. package/dist/providers/claude.provider.js.map +1 -0
  106. package/dist/providers/copilot.provider.d.ts +12 -0
  107. package/dist/providers/copilot.provider.js +88 -0
  108. package/dist/providers/copilot.provider.js.map +1 -0
  109. package/dist/providers/heuristic.provider.d.ts +9 -0
  110. package/dist/providers/heuristic.provider.js +163 -0
  111. package/dist/providers/heuristic.provider.js.map +1 -0
  112. package/dist/providers/ollama.provider.d.ts +14 -0
  113. package/dist/providers/ollama.provider.js +83 -0
  114. package/dist/providers/ollama.provider.js.map +1 -0
  115. package/dist/providers/openai.provider.d.ts +14 -0
  116. package/dist/providers/openai.provider.js +84 -0
  117. package/dist/providers/openai.provider.js.map +1 -0
  118. package/dist/providers/provider.factory.d.ts +5 -0
  119. package/dist/providers/provider.factory.js +51 -0
  120. package/dist/providers/provider.factory.js.map +1 -0
  121. package/dist/security/scanner.d.ts +13 -0
  122. package/dist/security/scanner.js +138 -0
  123. package/dist/security/scanner.js.map +1 -0
  124. package/dist/types/index.d.ts +146 -0
  125. package/dist/types/index.js +2 -0
  126. package/dist/types/index.js.map +1 -0
  127. package/dist/ux/components/BranchTree.d.ts +8 -0
  128. package/dist/ux/components/BranchTree.js +57 -0
  129. package/dist/ux/components/BranchTree.js.map +1 -0
  130. package/dist/ux/components/CommitProposal.d.ts +13 -0
  131. package/dist/ux/components/CommitProposal.js +127 -0
  132. package/dist/ux/components/CommitProposal.js.map +1 -0
  133. package/dist/ux/components/DiagnosticReport.d.ts +18 -0
  134. package/dist/ux/components/DiagnosticReport.js +19 -0
  135. package/dist/ux/components/DiagnosticReport.js.map +1 -0
  136. package/dist/ux/components/ErrorBox.d.ts +7 -0
  137. package/dist/ux/components/ErrorBox.js +9 -0
  138. package/dist/ux/components/ErrorBox.js.map +1 -0
  139. package/dist/ux/components/FileSelector.d.ts +14 -0
  140. package/dist/ux/components/FileSelector.js +87 -0
  141. package/dist/ux/components/FileSelector.js.map +1 -0
  142. package/dist/ux/components/Logo.d.ts +6 -0
  143. package/dist/ux/components/Logo.js +21 -0
  144. package/dist/ux/components/Logo.js.map +1 -0
  145. package/dist/ux/components/RepoContext.d.ts +8 -0
  146. package/dist/ux/components/RepoContext.js +17 -0
  147. package/dist/ux/components/RepoContext.js.map +1 -0
  148. package/dist/ux/components/SecurityAlert.d.ts +9 -0
  149. package/dist/ux/components/SecurityAlert.js +16 -0
  150. package/dist/ux/components/SecurityAlert.js.map +1 -0
  151. package/dist/ux/components/StatusDashboard.d.ts +14 -0
  152. package/dist/ux/components/StatusDashboard.js +36 -0
  153. package/dist/ux/components/StatusDashboard.js.map +1 -0
  154. package/dist/ux/components/SuccessBox.d.ts +7 -0
  155. package/dist/ux/components/SuccessBox.js +9 -0
  156. package/dist/ux/components/SuccessBox.js.map +1 -0
  157. package/dist/ux/components/ValidationReport.d.ts +16 -0
  158. package/dist/ux/components/ValidationReport.js +19 -0
  159. package/dist/ux/components/ValidationReport.js.map +1 -0
  160. package/dist/ux/components/WarningBox.d.ts +7 -0
  161. package/dist/ux/components/WarningBox.js +9 -0
  162. package/dist/ux/components/WarningBox.js.map +1 -0
  163. package/dist/ux/display.d.ts +21 -0
  164. package/dist/ux/display.js +96 -0
  165. package/dist/ux/display.js.map +1 -0
  166. package/dist/ux/hooks/useActivation.d.ts +8 -0
  167. package/dist/ux/hooks/useActivation.js +16 -0
  168. package/dist/ux/hooks/useActivation.js.map +1 -0
  169. package/dist/ux/hooks/useSpinner.d.ts +2 -0
  170. package/dist/ux/hooks/useSpinner.js +13 -0
  171. package/dist/ux/hooks/useSpinner.js.map +1 -0
  172. package/dist/ux/menu.d.ts +7 -0
  173. package/dist/ux/menu.js +56 -0
  174. package/dist/ux/menu.js.map +1 -0
  175. package/dist/ux/prompt.d.ts +7 -0
  176. package/dist/ux/prompt.js +361 -0
  177. package/dist/ux/prompt.js.map +1 -0
  178. package/dist/ux/renderer.d.ts +9 -0
  179. package/dist/ux/renderer.js +45 -0
  180. package/dist/ux/renderer.js.map +1 -0
  181. package/dist/ux/spinner.d.ts +6 -0
  182. package/dist/ux/spinner.js +42 -0
  183. package/dist/ux/spinner.js.map +1 -0
  184. package/dist/ux/statusbar.d.ts +2 -0
  185. package/dist/ux/statusbar.js +44 -0
  186. package/dist/ux/statusbar.js.map +1 -0
  187. package/dist/ux/theme.d.ts +37 -0
  188. package/dist/ux/theme.js +55 -0
  189. package/dist/ux/theme.js.map +1 -0
  190. package/package.json +125 -0
@@ -0,0 +1,308 @@
1
+ import { spawnSync } from 'child_process';
2
+ import { existsSync, statSync } from 'fs';
3
+ import { join } from 'path';
4
+ function git(args, cwd = process.cwd()) {
5
+ const result = spawnSync('git', args, { cwd, encoding: 'utf-8' });
6
+ if (result.error)
7
+ throw result.error;
8
+ return (result.stdout || '').trim();
9
+ }
10
+ function gitSafe(args, cwd = process.cwd()) {
11
+ try {
12
+ return git(args, cwd);
13
+ }
14
+ catch {
15
+ return null;
16
+ }
17
+ }
18
+ export function isGitRepo(cwd = process.cwd()) {
19
+ const result = spawnSync('git', ['rev-parse', '--is-inside-work-tree'], {
20
+ cwd,
21
+ encoding: 'utf-8',
22
+ });
23
+ return result.status === 0;
24
+ }
25
+ export function initRepo(cwd = process.cwd()) {
26
+ git(['init'], cwd);
27
+ }
28
+ export function hasCommits(cwd = process.cwd()) {
29
+ return spawnSync('git', ['rev-parse', 'HEAD'], { cwd, encoding: 'utf-8' }).status === 0;
30
+ }
31
+ export function unstageAll(cwd = process.cwd()) {
32
+ if (hasCommits(cwd)) {
33
+ // Reset index to HEAD, keeping working tree changes
34
+ spawnSync('git', ['reset', 'HEAD', '--', '.'], { cwd });
35
+ }
36
+ else {
37
+ // No commits yet — remove everything from index without touching files
38
+ spawnSync('git', ['rm', '--cached', '-r', '.'], { cwd });
39
+ }
40
+ }
41
+ export function setDefaultBranch(name, cwd = process.cwd()) {
42
+ // Rename the just-created branch (before any commits, git branch -m works)
43
+ spawnSync('git', ['symbolic-ref', 'HEAD', `refs/heads/${name}`], { cwd });
44
+ }
45
+ export function getGitUserConfig(cwd = process.cwd()) {
46
+ const name = gitSafe(['config', 'user.name'], cwd) ?? '';
47
+ const email = gitSafe(['config', 'user.email'], cwd) ?? '';
48
+ return { name, email };
49
+ }
50
+ export function setGitUserConfig(name, email, cwd = process.cwd()) {
51
+ git(['config', 'user.name', name], cwd);
52
+ git(['config', 'user.email', email], cwd);
53
+ }
54
+ export function listBranches(includeRemote = false, cwd = process.cwd()) {
55
+ const args = ['branch', '--format=%(refname:short)|%(HEAD)|%(upstream:short)'];
56
+ if (includeRemote)
57
+ args.push('-a');
58
+ const output = gitSafe(args, cwd) ?? '';
59
+ const current = getCurrentBranch(cwd);
60
+ const mergedOutput = gitSafe(['branch', '--merged'], cwd) ?? '';
61
+ const mergedBranches = new Set(mergedOutput.split('\n').map((b) => b.trim().replace(/^\*\s*/, '')));
62
+ return output
63
+ .split('\n')
64
+ .filter(Boolean)
65
+ .map((line) => {
66
+ const name = line.split('|')[0] ?? '';
67
+ const head = line.split('|')[1];
68
+ const cleanName = name.replace(/^remotes\//, '');
69
+ return {
70
+ name: cleanName,
71
+ current: head === '*' || cleanName === current,
72
+ remote: name.startsWith('remotes/'),
73
+ merged: mergedBranches.has(cleanName),
74
+ };
75
+ })
76
+ .filter((b) => !b.name.endsWith('/HEAD'));
77
+ }
78
+ export function createBranch(name, baseBranch, cwd = process.cwd()) {
79
+ if (baseBranch) {
80
+ git(['checkout', '-b', name, baseBranch], cwd);
81
+ }
82
+ else {
83
+ git(['checkout', '-b', name], cwd);
84
+ }
85
+ }
86
+ export function switchBranch(name, cwd = process.cwd()) {
87
+ git(['checkout', name], cwd);
88
+ }
89
+ export function deleteBranch(name, force = false, cwd = process.cwd()) {
90
+ git(['branch', force ? '-D' : '-d', name], cwd);
91
+ }
92
+ export function deleteRemoteBranch(remote, name, cwd = process.cwd()) {
93
+ git(['push', remote, '--delete', name], cwd);
94
+ }
95
+ export function renameBranch(newName, cwd = process.cwd()) {
96
+ git(['branch', '-m', newName], cwd);
97
+ }
98
+ export function branchExists(name, cwd = process.cwd()) {
99
+ const result = spawnSync('git', ['rev-parse', '--verify', name], { cwd, encoding: 'utf-8' });
100
+ return result.status === 0;
101
+ }
102
+ export function getRepoName(cwd = process.cwd()) {
103
+ const remote = gitSafe(['remote', 'get-url', 'origin'], cwd);
104
+ if (remote) {
105
+ const match = remote.match(/\/([^/]+?)(?:\.git)?$/);
106
+ if (match)
107
+ return match[1] ?? 'unknown';
108
+ }
109
+ const topLevel = gitSafe(['rev-parse', '--show-toplevel'], cwd);
110
+ if (topLevel)
111
+ return topLevel.split('/').pop() ?? 'unknown';
112
+ return 'unknown';
113
+ }
114
+ export function getCurrentBranch(cwd = process.cwd()) {
115
+ // symbolic-ref works even before the first commit (rev-parse returns "HEAD" then)
116
+ const symbolic = gitSafe(['symbolic-ref', '--short', 'HEAD'], cwd);
117
+ if (symbolic)
118
+ return symbolic;
119
+ return gitSafe(['rev-parse', '--abbrev-ref', 'HEAD'], cwd) ?? 'HEAD';
120
+ }
121
+ export function isProtectedBranch(branch, protectedBranches) {
122
+ return protectedBranches.includes(branch);
123
+ }
124
+ export function extractTicketFromBranch(branch, ticketPattern) {
125
+ let regex;
126
+ try {
127
+ regex = new RegExp(ticketPattern);
128
+ }
129
+ catch {
130
+ // Invalid pattern from user config — skip silently rather than crash.
131
+ return undefined;
132
+ }
133
+ const match = branch.match(regex);
134
+ return match ? match[0] : undefined;
135
+ }
136
+ export function getStagedFiles(cwd = process.cwd()) {
137
+ const output = gitSafe(['diff', '--cached', '--name-status'], cwd);
138
+ if (!output)
139
+ return [];
140
+ return output
141
+ .split('\n')
142
+ .filter(Boolean)
143
+ .map((line) => {
144
+ const parts = line.split('\t');
145
+ const statusChar = parts[0] ?? '';
146
+ const path = parts[parts.length - 1] ?? '';
147
+ return { path, status: parseStatus(statusChar.charAt(0)) };
148
+ });
149
+ }
150
+ export function getUnstagedFiles(cwd = process.cwd()) {
151
+ const output = gitSafe(['diff', '--name-only'], cwd);
152
+ if (!output)
153
+ return [];
154
+ return output.split('\n').filter(Boolean);
155
+ }
156
+ export function getUntrackedFiles(cwd = process.cwd()) {
157
+ const output = gitSafe(['ls-files', '--others', '--exclude-standard'], cwd);
158
+ if (!output)
159
+ return [];
160
+ return output.split('\n').filter(Boolean);
161
+ }
162
+ export function getStagedDiff(cwd = process.cwd()) {
163
+ return gitSafe(['diff', '--cached'], cwd) ?? '';
164
+ }
165
+ export function getLastCommit(cwd = process.cwd()) {
166
+ const out = gitSafe(['log', '-1', '--format=%h\x1f%s\x1f%an\x1f%ar'], cwd);
167
+ if (!out)
168
+ return null;
169
+ const [shortSha, message, author, ago] = out.split('\x1f');
170
+ return { shortSha: shortSha ?? '', message: message ?? '', author: author ?? '', ago: ago ?? '' };
171
+ }
172
+ export function fetchRemote(cwd = process.cwd()) {
173
+ const r = spawnSync('git', ['fetch'], { cwd, encoding: 'utf-8', timeout: 15000 });
174
+ return { ok: r.status === 0, output: ((r.stdout ?? '') + (r.stderr ?? '')).trim() };
175
+ }
176
+ export function getLastFetchTime(cwd = process.cwd()) {
177
+ try {
178
+ const p = join(cwd, '.git', 'FETCH_HEAD');
179
+ return existsSync(p) ? statSync(p).mtime : null;
180
+ }
181
+ catch {
182
+ return null;
183
+ }
184
+ }
185
+ export function getCommitsSinceBase(base, cwd = process.cwd()) {
186
+ const output = gitSafe(['log', `${base}..HEAD`, '--oneline'], cwd);
187
+ if (!output)
188
+ return [];
189
+ return output.split('\n').filter(Boolean);
190
+ }
191
+ export function getUpstream(cwd = process.cwd()) {
192
+ const upstream = gitSafe(['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{u}'], cwd);
193
+ return upstream ?? undefined;
194
+ }
195
+ export function getAheadBehindCount(upstream, cwd = process.cwd()) {
196
+ const output = gitSafe(['rev-list', '--left-right', '--count', `${upstream}...HEAD`], cwd);
197
+ if (!output)
198
+ return { ahead: 0, behind: 0 };
199
+ const [behind, ahead] = output.split('\t').map(Number);
200
+ return { ahead: ahead ?? 0, behind: behind ?? 0 };
201
+ }
202
+ export function hasMergeConflicts(cwd = process.cwd()) {
203
+ const output = gitSafe(['diff', '--name-only', '--diff-filter=U'], cwd);
204
+ return !!(output && output.trim().length > 0);
205
+ }
206
+ export function hasUncommittedChanges(cwd = process.cwd()) {
207
+ const output = gitSafe(['status', '--porcelain'], cwd);
208
+ return !!(output && output.trim().length > 0);
209
+ }
210
+ export function stageFile(filePath, cwd = process.cwd()) {
211
+ git(['add', filePath], cwd);
212
+ }
213
+ export function stageFiles(paths, cwd = process.cwd()) {
214
+ if (paths.length === 0)
215
+ return;
216
+ git(['add', '--', ...paths], cwd);
217
+ }
218
+ export function buildRepoContext(protectedBranches, ticketPattern, convention, cwd = process.cwd()) {
219
+ const branch = getCurrentBranch(cwd);
220
+ const upstream = getUpstream(cwd);
221
+ const staged = getStagedFiles(cwd);
222
+ const unstaged = getUnstagedFiles(cwd);
223
+ const untracked = getUntrackedFiles(cwd);
224
+ const { ahead, behind } = upstream ? getAheadBehindCount(upstream, cwd) : { ahead: 0, behind: 0 };
225
+ return {
226
+ name: getRepoName(cwd),
227
+ branch,
228
+ ticket: extractTicketFromBranch(branch, ticketPattern),
229
+ convention,
230
+ isMonorepo: false,
231
+ upstream,
232
+ hasUncommittedChanges: hasUncommittedChanges(cwd),
233
+ stagedFiles: staged,
234
+ unstagedFiles: unstaged,
235
+ untrackedFiles: untracked,
236
+ conflictsActive: hasMergeConflicts(cwd),
237
+ aheadCount: ahead,
238
+ behindCount: behind,
239
+ };
240
+ }
241
+ export function refExists(ref, cwd = process.cwd()) {
242
+ return gitSafe(['rev-parse', '--verify', ref], cwd) !== null;
243
+ }
244
+ export function stashSave(message, cwd = process.cwd()) {
245
+ git(['stash', 'push', '-m', message], cwd);
246
+ }
247
+ export function stashPop(cwd = process.cwd()) {
248
+ git(['stash', 'pop'], cwd);
249
+ }
250
+ export function stashList(cwd = process.cwd()) {
251
+ const out = gitSafe(['stash', 'list', '--format=%gd\x1f%s\x1f%ar'], cwd) ?? '';
252
+ if (!out)
253
+ return [];
254
+ return out
255
+ .split('\n')
256
+ .filter(Boolean)
257
+ .map((line, index) => {
258
+ const [ref, message, ago] = line.split('\x1f');
259
+ return {
260
+ index,
261
+ ref: ref ?? `stash@{${index}}`,
262
+ message: message ?? 'Sin título',
263
+ ago: ago ?? '',
264
+ };
265
+ });
266
+ }
267
+ export function stashApplyRef(ref, cwd = process.cwd()) {
268
+ git(['stash', 'apply', ref], cwd);
269
+ }
270
+ export function stashPopRef(ref, cwd = process.cwd()) {
271
+ git(['stash', 'pop', ref], cwd);
272
+ }
273
+ export function stashDropRef(ref, cwd = process.cwd()) {
274
+ git(['stash', 'drop', ref], cwd);
275
+ }
276
+ export function resetHard(ref, cwd = process.cwd()) {
277
+ git(['reset', '--hard', ref], cwd);
278
+ }
279
+ export function detectGhCli() {
280
+ const result = spawnSync('gh', ['auth', 'status'], { encoding: 'utf-8', stdio: 'pipe' });
281
+ return result.status === 0;
282
+ }
283
+ export function autoFetchIfStale(thresholdMinutes, cwd = process.cwd()) {
284
+ const lastFetch = getLastFetchTime(cwd);
285
+ if (!lastFetch) {
286
+ spawnSync('git', ['fetch', '--quiet', '--prune'], { cwd, stdio: 'pipe', timeout: 10000 });
287
+ return;
288
+ }
289
+ const ageMinutes = (Date.now() - lastFetch.getTime()) / 60000;
290
+ if (ageMinutes >= thresholdMinutes) {
291
+ spawnSync('git', ['fetch', '--quiet', '--prune'], { cwd, stdio: 'pipe', timeout: 10000 });
292
+ }
293
+ }
294
+ export function listRemotes(cwd = process.cwd()) {
295
+ const out = gitSafe(['remote'], cwd) ?? '';
296
+ return out.split('\n').filter(Boolean);
297
+ }
298
+ function parseStatus(char) {
299
+ const map = {
300
+ A: 'added',
301
+ M: 'modified',
302
+ D: 'deleted',
303
+ R: 'renamed',
304
+ C: 'copied',
305
+ };
306
+ return map[char] ?? 'unknown';
307
+ }
308
+ //# sourceMappingURL=repo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo.js","sourceRoot":"","sources":["../../src/git/repo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,SAAS,GAAG,CAAC,IAAc,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC9C,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IAClE,IAAI,MAAM,CAAC,KAAK;QAAE,MAAM,MAAM,CAAC,KAAK,CAAC;IACrC,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AACtC,CAAC;AAED,SAAS,OAAO,CAAC,IAAc,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAClD,IAAI,CAAC;QACH,OAAO,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC3C,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,uBAAuB,CAAC,EAAE;QACtE,GAAG;QACH,QAAQ,EAAE,OAAO;KAClB,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC1C,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC5C,OAAO,SAAS,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;AAC1F,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC5C,IAAI,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACpB,oDAAoD;QACpD,SAAS,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;IAC1D,CAAC;SAAM,CAAC;QACN,uEAAuE;QACvE,SAAS,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAChE,2EAA2E;IAC3E,SAAS,CAAC,KAAK,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,cAAc,IAAI,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAClD,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,QAAQ,EAAE,WAAW,CAAC,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;IACzD,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3D,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,KAAa,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC/E,GAAG,CAAC,CAAC,QAAQ,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;IACxC,GAAG,CAAC,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC;AAC5C,CAAC;AAWD,MAAM,UAAU,YAAY,CAAC,aAAa,GAAG,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IACrE,MAAM,IAAI,GAAG,CAAC,QAAQ,EAAE,qDAAqD,CAAC,CAAC;IAC/E,IAAI,aAAa;QAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;IACxC,MAAM,OAAO,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAEtC,MAAM,YAAY,GAAG,OAAO,CAAC,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;IAChE,MAAM,cAAc,GAAG,IAAI,GAAG,CAC5B,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CACpE,CAAC;IAEF,OAAO,MAAM;SACV,KAAK,CAAC,IAAI,CAAC;SACX,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACZ,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;QACjD,OAAO;YACL,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,IAAI,KAAK,GAAG,IAAI,SAAS,KAAK,OAAO;YAC9C,MAAM,EAAE,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;YACnC,MAAM,EAAE,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC;SACtC,CAAC;IACJ,CAAC,CAAC;SACD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,UAAmB,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IACjF,IAAI,UAAU,EAAE,CAAC;QACf,GAAG,CAAC,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC;IACjD,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;IACrC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC5D,GAAG,CAAC,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,KAAK,GAAG,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC3E,GAAG,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAc,EAAE,IAAY,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAClF,GAAG,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAe,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC/D,GAAG,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC5D,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IAC7F,OAAO,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC7C,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,GAAG,CAAC,CAAC;IAC7D,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;QACpD,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC;IAC1C,CAAC;IACD,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAAE,GAAG,CAAC,CAAC;IAChE,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,SAAS,CAAC;IAC5D,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAClD,kFAAkF;IAClF,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,cAAc,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;IACnE,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,OAAO,OAAO,CAAC,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAc,EAAE,iBAA2B;IAC3E,OAAO,iBAAiB,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,MAAc,EAAE,aAAqB;IAC3E,IAAI,KAAa,CAAC;IAClB,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,MAAM,CAAC,aAAa,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,sEAAsE;QACtE,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAClC,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAChD,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,MAAM,EAAE,UAAU,EAAE,eAAe,CAAC,EAAE,GAAG,CAAC,CAAC;IACnE,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IACvB,OAAO,MAAM;SACV,KAAK,CAAC,IAAI,CAAC;SACX,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACZ,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7D,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAClD,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE,GAAG,CAAC,CAAC;IACrD,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IACvB,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IACnD,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,UAAU,EAAE,UAAU,EAAE,oBAAoB,CAAC,EAAE,GAAG,CAAC,CAAC;IAC5E,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IACvB,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC/C,OAAO,OAAO,CAAC,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;AAClD,CAAC;AASD,MAAM,UAAU,aAAa,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC/C,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,iCAAiC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC3E,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3D,OAAO,EAAE,QAAQ,EAAE,QAAQ,IAAI,EAAE,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,IAAI,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,EAAE,CAAC;AACpG,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC7C,MAAM,CAAC,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IAClF,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;AACtF,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAClD,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QAC1C,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,IAAY,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IACnE,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,IAAI,QAAQ,EAAE,WAAW,CAAC,EAAE,GAAG,CAAC,CAAC;IACnE,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IACvB,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC7C,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,WAAW,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;IAC7F,OAAO,QAAQ,IAAI,SAAS,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,QAAgB,EAChB,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAEnB,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,UAAU,EAAE,cAAc,EAAE,SAAS,EAAE,GAAG,QAAQ,SAAS,CAAC,EAAE,GAAG,CAAC,CAAC;IAC3F,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;IAC5C,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACvD,OAAO,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC,EAAE,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IACnD,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,MAAM,EAAE,aAAa,EAAE,iBAAiB,CAAC,EAAE,GAAG,CAAC,CAAC;IACxE,OAAO,CAAC,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IACvD,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE,GAAG,CAAC,CAAC;IACvD,OAAO,CAAC,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,QAAgB,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC7D,GAAG,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,GAAG,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAe,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC7D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAC/B,GAAG,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,iBAA2B,EAC3B,aAAqB,EACrB,UAA4B,EAC5B,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAEnB,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,QAAQ,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,mBAAmB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;IAElG,OAAO;QACL,IAAI,EAAE,WAAW,CAAC,GAAG,CAAC;QACtB,MAAM;QACN,MAAM,EAAE,uBAAuB,CAAC,MAAM,EAAE,aAAa,CAAC;QACtD,UAAU;QACV,UAAU,EAAE,KAAK;QACjB,QAAQ;QACR,qBAAqB,EAAE,qBAAqB,CAAC,GAAG,CAAC;QACjD,WAAW,EAAE,MAAM;QACnB,aAAa,EAAE,QAAQ;QACvB,cAAc,EAAE,SAAS;QACzB,eAAe,EAAE,iBAAiB,CAAC,GAAG,CAAC;QACvC,UAAU,EAAE,KAAK;QACjB,WAAW,EAAE,MAAM;KACpB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAW,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IACxD,OAAO,OAAO,CAAC,CAAC,WAAW,EAAE,UAAU,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,OAAe,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC5D,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC1C,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC;AAC7B,CAAC;AASD,MAAM,UAAU,SAAS,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC3C,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,2BAA2B,CAAC,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;IAC/E,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IACpB,OAAO,GAAG;SACP,KAAK,CAAC,IAAI,CAAC;SACX,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QACnB,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC/C,OAAO;YACL,KAAK;YACL,GAAG,EAAE,GAAG,IAAI,UAAU,KAAK,GAAG;YAC9B,OAAO,EAAE,OAAO,IAAI,YAAY;YAChC,GAAG,EAAE,GAAG,IAAI,EAAE;SACf,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAW,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC5D,GAAG,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC1D,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC3D,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAW,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IACxD,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IACzF,OAAO,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,gBAAwB,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC5E,MAAM,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACxC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,SAAS,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAC1F,OAAO;IACT,CAAC;IACD,MAAM,UAAU,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,KAAK,CAAC;IAC9D,IAAI,UAAU,IAAI,gBAAgB,EAAE,CAAC;QACnC,SAAS,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IAC5F,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC7C,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3C,OAAO,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AACzC,CAAC;AAED,SAAS,WAAW,CAAC,IAAY;IAC/B,MAAM,GAAG,GAAyC;QAChD,CAAC,EAAE,OAAO;QACV,CAAC,EAAE,UAAU;QACb,CAAC,EAAE,SAAS;QACZ,CAAC,EAAE,SAAS;QACZ,CAAC,EAAE,QAAQ;KACZ,CAAC;IACF,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC;AAChC,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Input validation for Git operations.
3
+ *
4
+ * All user-supplied strings that flow into git commands must pass through
5
+ * these validators before reaching spawnSync. This prevents path traversal,
6
+ * shell metacharacter injection (even in array args), and unintended git
7
+ * flag injection (e.g. a branch name of "--upload-pack=evil").
8
+ */
9
+ export interface ValidationResult {
10
+ valid: boolean;
11
+ reason?: string;
12
+ }
13
+ /**
14
+ * Validates a git branch name against git's own rules plus injection guards.
15
+ * Reference: git-check-ref-format(1)
16
+ */
17
+ export declare function validateBranchName(name: string): ValidationResult;
18
+ /**
19
+ * Validates a git remote name (e.g. "origin", "upstream").
20
+ */
21
+ export declare function validateRemoteName(name: string): ValidationResult;
22
+ /**
23
+ * Validates a file path to be used in a git command.
24
+ * Prevents path traversal and null-byte injection.
25
+ */
26
+ export declare function validateFilePath(filePath: string): ValidationResult;
27
+ /**
28
+ * Validates a git ref (branch name, tag, or SHA).
29
+ */
30
+ export declare function validateRef(ref: string): ValidationResult;
31
+ /**
32
+ * Asserts a validation result and throws a descriptive Error on failure.
33
+ * Intended for use in command handlers before calling repo functions.
34
+ */
35
+ export declare function assertValid(result: ValidationResult, context: string): void;
36
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Input validation for Git operations.
3
+ *
4
+ * All user-supplied strings that flow into git commands must pass through
5
+ * these validators before reaching spawnSync. This prevents path traversal,
6
+ * shell metacharacter injection (even in array args), and unintended git
7
+ * flag injection (e.g. a branch name of "--upload-pack=evil").
8
+ */
9
+ const BRANCH_MAX_LENGTH = 250;
10
+ /**
11
+ * Validates a git branch name against git's own rules plus injection guards.
12
+ * Reference: git-check-ref-format(1)
13
+ */
14
+ export function validateBranchName(name) {
15
+ if (!name || name.trim().length === 0) {
16
+ return { valid: false, reason: 'Branch name cannot be empty' };
17
+ }
18
+ if (name.length > BRANCH_MAX_LENGTH) {
19
+ return { valid: false, reason: `Branch name exceeds ${BRANCH_MAX_LENGTH} characters` };
20
+ }
21
+ // Prevent flag injection: git treats args starting with "-" as options.
22
+ if (name.startsWith('-')) {
23
+ return { valid: false, reason: 'Branch name cannot start with a hyphen' };
24
+ }
25
+ const rules = [
26
+ { test: /\.\./, reason: 'Cannot contain consecutive dots (..)' },
27
+ { test: /^\./, reason: 'Cannot start with a dot' },
28
+ { test: /\.$/, reason: 'Cannot end with a dot' },
29
+ { test: /\s/, reason: 'Cannot contain whitespace' },
30
+ { test: /[~^:?*\[\\]/, reason: 'Contains invalid character (~^:?*[\\)' },
31
+ { test: /\.lock$/, reason: 'Cannot end with .lock' },
32
+ { test: /@\{/, reason: 'Cannot contain @{' },
33
+ { test: /\/$/, reason: 'Cannot end with /' },
34
+ { test: /\/\//, reason: 'Cannot contain consecutive slashes' },
35
+ { test: /\x00/, reason: 'Cannot contain null bytes' },
36
+ ];
37
+ for (const { test, reason } of rules) {
38
+ if (test.test(name))
39
+ return { valid: false, reason };
40
+ }
41
+ return { valid: true };
42
+ }
43
+ /**
44
+ * Validates a git remote name (e.g. "origin", "upstream").
45
+ */
46
+ export function validateRemoteName(name) {
47
+ if (!name || name.trim().length === 0) {
48
+ return { valid: false, reason: 'Remote name cannot be empty' };
49
+ }
50
+ if (name.startsWith('-')) {
51
+ return { valid: false, reason: 'Remote name cannot start with a hyphen' };
52
+ }
53
+ if (!/^[a-zA-Z0-9._-]+$/.test(name)) {
54
+ return { valid: false, reason: 'Remote name contains invalid characters' };
55
+ }
56
+ return { valid: true };
57
+ }
58
+ /**
59
+ * Validates a file path to be used in a git command.
60
+ * Prevents path traversal and null-byte injection.
61
+ */
62
+ export function validateFilePath(filePath) {
63
+ if (!filePath || filePath.trim().length === 0) {
64
+ return { valid: false, reason: 'File path cannot be empty' };
65
+ }
66
+ if (filePath.includes('\x00')) {
67
+ return { valid: false, reason: 'File path cannot contain null bytes' };
68
+ }
69
+ // Prevent traversal above the repo root via absolute paths or ..
70
+ if (filePath.startsWith('/') || filePath.startsWith('\\')) {
71
+ return { valid: false, reason: 'File path must be relative, not absolute' };
72
+ }
73
+ // Normalize and check for traversal
74
+ const normalized = filePath.replace(/\\/g, '/');
75
+ const parts = normalized.split('/');
76
+ let depth = 0;
77
+ for (const part of parts) {
78
+ if (part === '..') {
79
+ depth--;
80
+ if (depth < 0)
81
+ return { valid: false, reason: 'Path traversal above repo root detected' };
82
+ }
83
+ else if (part !== '.') {
84
+ depth++;
85
+ }
86
+ }
87
+ return { valid: true };
88
+ }
89
+ /**
90
+ * Validates a git ref (branch name, tag, or SHA).
91
+ */
92
+ export function validateRef(ref) {
93
+ if (!ref || ref.trim().length === 0) {
94
+ return { valid: false, reason: 'Ref cannot be empty' };
95
+ }
96
+ if (ref.startsWith('-')) {
97
+ return { valid: false, reason: 'Ref cannot start with a hyphen (flag injection risk)' };
98
+ }
99
+ if (ref.includes('\x00')) {
100
+ return { valid: false, reason: 'Ref cannot contain null bytes' };
101
+ }
102
+ return { valid: true };
103
+ }
104
+ /**
105
+ * Asserts a validation result and throws a descriptive Error on failure.
106
+ * Intended for use in command handlers before calling repo functions.
107
+ */
108
+ export function assertValid(result, context) {
109
+ if (!result.valid) {
110
+ throw new Error(`[git-smart-flow] ${context}: ${result.reason}`);
111
+ }
112
+ }
113
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/git/validate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { AIContext, AIProvider, PRProposal, ProviderName } from '../types/index.js';
2
+ export declare abstract class BaseProvider implements AIProvider {
3
+ abstract name: ProviderName;
4
+ abstract isAvailable(): Promise<boolean>;
5
+ abstract generateCommitMessage(context: AIContext): Promise<string>;
6
+ abstract generatePRDescription(context: AIContext): Promise<PRProposal>;
7
+ protected buildCommitPrompt(context: AIContext): string;
8
+ protected buildPRPrompt(context: AIContext): string;
9
+ }
10
+ //# sourceMappingURL=base.provider.d.ts.map
@@ -0,0 +1,40 @@
1
+ export class BaseProvider {
2
+ buildCommitPrompt(context) {
3
+ const { detectedCommitConvention: conv, changedFiles, localSummary, ticket, branch } = context;
4
+ const types = conv.allowedTypes.join(', ');
5
+ const scopeHint = conv.allowedScopes?.length
6
+ ? `\nAllowed scopes: ${conv.allowedScopes.join(', ')}`
7
+ : '';
8
+ const ticketHint = ticket ? `\nTicket: ${ticket}` : '';
9
+ const files = changedFiles.map((f) => ` - ${f.status}: ${f.path}`).join('\n');
10
+ const summary = localSummary.join('\n');
11
+ return [
12
+ `Generate a single-line commit message following the Conventional Commits spec.`,
13
+ `Format: <type>${conv.scopeRequired ? '(<scope>)' : '[(<scope>)]'}: <subject>`,
14
+ `Max length: ${conv.maxHeaderLength} characters`,
15
+ `Allowed types: ${types}${scopeHint}`,
16
+ ticketHint,
17
+ `Branch: ${branch}`,
18
+ `Changed files:\n${files}`,
19
+ `Summary:\n${summary}`,
20
+ `Output ONLY the commit message, nothing else.`,
21
+ ]
22
+ .filter(Boolean)
23
+ .join('\n');
24
+ }
25
+ buildPRPrompt(context) {
26
+ const { changedFiles, localSummary, ticket, branch } = context;
27
+ const files = changedFiles.map((f) => ` - ${f.status}: ${f.path}`).join('\n');
28
+ return [
29
+ `Generate a pull request title and description for the following changes.`,
30
+ `Branch: ${branch}`,
31
+ ticket ? `Ticket: ${ticket}` : '',
32
+ `Changed files:\n${files}`,
33
+ `Summary:\n${localSummary.join('\n')}`,
34
+ `Output a JSON object with fields: title (string), body (markdown string with sections: Context, Changes, Testing, Risks/Impact).`,
35
+ ]
36
+ .filter(Boolean)
37
+ .join('\n');
38
+ }
39
+ }
40
+ //# sourceMappingURL=base.provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.provider.js","sourceRoot":"","sources":["../../src/providers/base.provider.ts"],"names":[],"mappings":"AAEA,MAAM,OAAgB,YAAY;IAMtB,iBAAiB,CAAC,OAAkB;QAC5C,MAAM,EAAE,wBAAwB,EAAE,IAAI,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;QAC/F,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,EAAE,MAAM;YAC1C,CAAC,CAAC,qBAAqB,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YACtD,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,aAAa,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvD,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/E,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAExC,OAAO;YACL,gFAAgF;YAChF,iBAAiB,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,aAAa;YAC9E,eAAe,IAAI,CAAC,eAAe,aAAa;YAChD,kBAAkB,KAAK,GAAG,SAAS,EAAE;YACrC,UAAU;YACV,WAAW,MAAM,EAAE;YACnB,mBAAmB,KAAK,EAAE;YAC1B,aAAa,OAAO,EAAE;YACtB,+CAA+C;SAChD;aACE,MAAM,CAAC,OAAO,CAAC;aACf,IAAI,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC;IAES,aAAa,CAAC,OAAkB;QACxC,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;QAC/D,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAE/E,OAAO;YACL,0EAA0E;YAC1E,WAAW,MAAM,EAAE;YACnB,MAAM,CAAC,CAAC,CAAC,WAAW,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE;YACjC,mBAAmB,KAAK,EAAE;YAC1B,aAAa,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YACtC,kIAAkI;SACnI;aACE,MAAM,CAAC,OAAO,CAAC;aACf,IAAI,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC;CACF"}
@@ -0,0 +1,14 @@
1
+ import type { AIContext, PRProposal, ProviderName } from '../types/index.js';
2
+ import { BaseProvider } from './base.provider.js';
3
+ export declare class ClaudeProvider extends BaseProvider {
4
+ name: ProviderName;
5
+ private apiKey;
6
+ private model;
7
+ private fallback;
8
+ constructor(apiKey?: string, model?: string);
9
+ isAvailable(): Promise<boolean>;
10
+ generateCommitMessage(context: AIContext): Promise<string>;
11
+ generatePRDescription(context: AIContext): Promise<PRProposal>;
12
+ private messages;
13
+ }
14
+ //# sourceMappingURL=claude.provider.d.ts.map
@@ -0,0 +1,85 @@
1
+ import { BaseProvider } from './base.provider.js';
2
+ import { HeuristicProvider } from './heuristic.provider.js';
3
+ const ANTHROPIC_API_URL = 'https://api.anthropic.com/v1/messages';
4
+ const DEFAULT_MODEL = 'claude-haiku-4-5-20251001';
5
+ const API_VERSION = '2023-06-01';
6
+ export class ClaudeProvider extends BaseProvider {
7
+ name = 'claude';
8
+ apiKey;
9
+ model;
10
+ fallback = new HeuristicProvider();
11
+ constructor(apiKey, model) {
12
+ super();
13
+ this.apiKey = apiKey ?? process.env.ANTHROPIC_API_KEY ?? '';
14
+ this.model = model ?? DEFAULT_MODEL;
15
+ }
16
+ // eslint-disable-next-line @typescript-eslint/require-await
17
+ async isAvailable() {
18
+ return this.apiKey.length > 0;
19
+ }
20
+ async generateCommitMessage(context) {
21
+ if (!(await this.isAvailable()))
22
+ return this.fallback.generateCommitMessage(context);
23
+ try {
24
+ const prompt = this.buildCommitPrompt(context);
25
+ const response = await this.messages(prompt);
26
+ if (response)
27
+ return response.trim();
28
+ }
29
+ catch {
30
+ /* */
31
+ }
32
+ return this.fallback.generateCommitMessage(context);
33
+ }
34
+ async generatePRDescription(context) {
35
+ if (!(await this.isAvailable()))
36
+ return this.fallback.generatePRDescription(context);
37
+ try {
38
+ const prompt = this.buildPRPrompt(context);
39
+ const response = await this.messages(prompt);
40
+ if (response) {
41
+ const parsed = parsePRJSON(response);
42
+ if (parsed)
43
+ return parsed;
44
+ }
45
+ }
46
+ catch {
47
+ /* */
48
+ }
49
+ return this.fallback.generatePRDescription(context);
50
+ }
51
+ async messages(prompt) {
52
+ const res = await fetch(ANTHROPIC_API_URL, {
53
+ method: 'POST',
54
+ headers: {
55
+ 'Content-Type': 'application/json',
56
+ 'x-api-key': this.apiKey,
57
+ 'anthropic-version': API_VERSION,
58
+ },
59
+ body: JSON.stringify({
60
+ model: this.model,
61
+ max_tokens: 512,
62
+ messages: [{ role: 'user', content: prompt }],
63
+ }),
64
+ });
65
+ if (!res.ok)
66
+ return null;
67
+ const data = (await res.json());
68
+ return data.content?.find((c) => c.type === 'text')?.text ?? null;
69
+ }
70
+ }
71
+ function parsePRJSON(raw) {
72
+ try {
73
+ const match = raw.match(/\{[\s\S]+\}/);
74
+ if (!match)
75
+ return null;
76
+ const parsed = JSON.parse(match[0]);
77
+ if (parsed.title && parsed.body)
78
+ return { title: parsed.title, body: parsed.body };
79
+ }
80
+ catch {
81
+ /* */
82
+ }
83
+ return null;
84
+ }
85
+ //# sourceMappingURL=claude.provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.provider.js","sourceRoot":"","sources":["../../src/providers/claude.provider.ts"],"names":[],"mappings":"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"}