@open330/oac 2026.2.5

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 (56) hide show
  1. package/CHANGELOG.md +115 -0
  2. package/LICENSE +21 -0
  3. package/README.md +597 -0
  4. package/dist/budget/index.d.ts +117 -0
  5. package/dist/budget/index.js +23 -0
  6. package/dist/budget/index.js.map +1 -0
  7. package/dist/chunk-4IUL7ECC.js +3152 -0
  8. package/dist/chunk-4IUL7ECC.js.map +1 -0
  9. package/dist/chunk-5GAUWC3L.js +469 -0
  10. package/dist/chunk-5GAUWC3L.js.map +1 -0
  11. package/dist/chunk-6A37SKAJ.js +58 -0
  12. package/dist/chunk-6A37SKAJ.js.map +1 -0
  13. package/dist/chunk-7C7SC4TZ.js +358 -0
  14. package/dist/chunk-7C7SC4TZ.js.map +1 -0
  15. package/dist/chunk-CJAJ4MBO.js +475 -0
  16. package/dist/chunk-CJAJ4MBO.js.map +1 -0
  17. package/dist/chunk-LQC5DLT7.js +317 -0
  18. package/dist/chunk-LQC5DLT7.js.map +1 -0
  19. package/dist/chunk-OTPXGXO7.js +2368 -0
  20. package/dist/chunk-OTPXGXO7.js.map +1 -0
  21. package/dist/chunk-QPVNC7S4.js +1833 -0
  22. package/dist/chunk-QPVNC7S4.js.map +1 -0
  23. package/dist/cli/cli.d.ts +13 -0
  24. package/dist/cli/cli.js +16 -0
  25. package/dist/cli/cli.js.map +1 -0
  26. package/dist/cli/index.d.ts +1 -0
  27. package/dist/cli/index.js +22 -0
  28. package/dist/cli/index.js.map +1 -0
  29. package/dist/completion/index.d.ts +91 -0
  30. package/dist/completion/index.js +587 -0
  31. package/dist/completion/index.js.map +1 -0
  32. package/dist/config-DequKoFA.d.ts +1468 -0
  33. package/dist/core/index.d.ts +64 -0
  34. package/dist/core/index.js +87 -0
  35. package/dist/core/index.js.map +1 -0
  36. package/dist/dashboard/index.d.ts +14 -0
  37. package/dist/dashboard/index.js +1253 -0
  38. package/dist/dashboard/index.js.map +1 -0
  39. package/dist/discovery/index.d.ts +285 -0
  40. package/dist/discovery/index.js +50 -0
  41. package/dist/discovery/index.js.map +1 -0
  42. package/dist/event-bus-KiuR6e3P.d.ts +91 -0
  43. package/dist/execution/index.d.ts +215 -0
  44. package/dist/execution/index.js +27 -0
  45. package/dist/execution/index.js.map +1 -0
  46. package/dist/repo/index.d.ts +33 -0
  47. package/dist/repo/index.js +19 -0
  48. package/dist/repo/index.js.map +1 -0
  49. package/dist/tracking/index.d.ts +357 -0
  50. package/dist/tracking/index.js +15 -0
  51. package/dist/tracking/index.js.map +1 -0
  52. package/dist/types-CYCwgojB.d.ts +34 -0
  53. package/dist/types-Ck7IucqK.d.ts +195 -0
  54. package/docs/config-reference.md +271 -0
  55. package/docs/multi-agent-support-technical-spec.md +312 -0
  56. package/package.json +82 -0
@@ -0,0 +1,587 @@
1
+ import {
2
+ OacError,
3
+ completionError,
4
+ executionError
5
+ } from "../chunk-7C7SC4TZ.js";
6
+ import {
7
+ truncate
8
+ } from "../chunk-6A37SKAJ.js";
9
+
10
+ // src/completion/github-pr.ts
11
+ import { simpleGit } from "simple-git";
12
+ async function createPR(params, octokit) {
13
+ const { repo, task, result, branchName, baseBranch } = params;
14
+ const pushedSha = await pushBranch(repo, branchName);
15
+ const body = await buildPrBody(params);
16
+ try {
17
+ const created = await octokit.pulls.create({
18
+ owner: repo.owner,
19
+ repo: repo.name,
20
+ title: `[OAC] ${task.title}`,
21
+ body,
22
+ head: branchName,
23
+ base: baseBranch,
24
+ draft: false
25
+ });
26
+ await addLabels(octokit, repo, created.data.number, ["oac-contribution", task.source]);
27
+ return {
28
+ number: created.data.number,
29
+ url: created.data.html_url,
30
+ sha: created.data.head.sha || pushedSha
31
+ };
32
+ } catch (error) {
33
+ throw completionError(
34
+ "PR_CREATION_FAILED",
35
+ `Failed to create PR for "${repo.fullName}" on branch "${branchName}".`,
36
+ {
37
+ cause: error,
38
+ context: {
39
+ repo: repo.fullName,
40
+ branchName,
41
+ baseBranch,
42
+ taskId: task.id
43
+ }
44
+ }
45
+ );
46
+ }
47
+ }
48
+ async function pushBranch(repo, branchName) {
49
+ const git = simpleGit(resolveGitPath(repo));
50
+ const headSha = (await git.revparse(["HEAD"])).trim();
51
+ try {
52
+ const remoteSha = await readRemoteBranchSha(git, branchName);
53
+ if (remoteSha !== headSha) {
54
+ await git.push("origin", branchName);
55
+ }
56
+ } catch (error) {
57
+ try {
58
+ await git.raw(["push", "--set-upstream", "origin", branchName]);
59
+ } catch (retryError) {
60
+ throw completionError(
61
+ "PR_PUSH_REJECTED",
62
+ `Failed to push branch "${branchName}" for "${repo.fullName}".`,
63
+ {
64
+ cause: retryError,
65
+ context: {
66
+ repo: repo.fullName,
67
+ branchName,
68
+ headSha,
69
+ initialError: error instanceof Error ? error.message : "unknown push error"
70
+ }
71
+ }
72
+ );
73
+ }
74
+ }
75
+ return headSha;
76
+ }
77
+ async function buildPrBody(params) {
78
+ const { repo, task, result, baseBranch, branchName } = params;
79
+ const diffStats = await resolveDiffStats(repo, baseBranch, branchName);
80
+ const linkedIssue = task.linkedIssue ? `
81
+ Fixes #${task.linkedIssue.number}
82
+ ` : "\n";
83
+ const agentLabel = resolveAgentLabel(task.metadata);
84
+ const durationText = formatDurationSeconds(result.duration);
85
+ const summaryText = task.description.trim().length > 0 ? task.description.trim() : `Automated contribution for task "${task.title}".`;
86
+ const filesChanged = result.filesChanged.length || diffStats.filesChanged;
87
+ const filesPreview = renderFilesPreview(result.filesChanged);
88
+ return [
89
+ "## Summary",
90
+ "",
91
+ summaryText,
92
+ "",
93
+ "## Changes",
94
+ "",
95
+ filesPreview,
96
+ "",
97
+ `- **Files changed:** ${filesChanged}`,
98
+ `- **Lines added:** ${diffStats.linesAdded}`,
99
+ `- **Lines removed:** ${diffStats.linesRemoved}`,
100
+ "",
101
+ "## Context",
102
+ "",
103
+ `- **Task source:** ${task.source}`,
104
+ `- **Agent:** ${agentLabel}`,
105
+ `- **Tokens used:** ${result.totalTokensUsed}`,
106
+ `- **Execution time:** ${durationText}`,
107
+ linkedIssue.trimEnd(),
108
+ "",
109
+ "---",
110
+ "*This PR was automatically generated by OAC.*"
111
+ ].join("\n");
112
+ }
113
+ async function resolveDiffStats(repo, baseBranch, branchName) {
114
+ const git = simpleGit(resolveGitPath(repo));
115
+ const ranges = [
116
+ [`origin/${baseBranch}...${branchName}`],
117
+ [`${baseBranch}...${branchName}`],
118
+ ["HEAD"],
119
+ []
120
+ ];
121
+ for (const range of ranges) {
122
+ try {
123
+ const summary = await git.diffSummary(range);
124
+ return {
125
+ filesChanged: summary.changed,
126
+ linesAdded: summary.insertions,
127
+ linesRemoved: summary.deletions
128
+ };
129
+ } catch {
130
+ }
131
+ }
132
+ return {
133
+ filesChanged: 0,
134
+ linesAdded: 0,
135
+ linesRemoved: 0
136
+ };
137
+ }
138
+ async function addLabels(octokit, repo, prNumber, labels) {
139
+ const uniqueLabels = [...new Set(labels.map((label) => label.trim()).filter(Boolean))];
140
+ if (uniqueLabels.length === 0) {
141
+ return;
142
+ }
143
+ try {
144
+ await octokit.issues.addLabels({
145
+ owner: repo.owner,
146
+ repo: repo.name,
147
+ issue_number: prNumber,
148
+ labels: uniqueLabels
149
+ });
150
+ } catch {
151
+ }
152
+ }
153
+ function resolveGitPath(repo) {
154
+ return repo.worktreePath.trim().length > 0 ? repo.worktreePath : repo.localPath;
155
+ }
156
+ async function readRemoteBranchSha(git, branchName) {
157
+ const remoteHeads = await git.listRemote(["--heads", "origin", branchName]);
158
+ const firstLine = remoteHeads.split("\n").map((line) => line.trim()).find((line) => line.length > 0);
159
+ if (!firstLine) {
160
+ return void 0;
161
+ }
162
+ const [sha] = firstLine.split(/\s+/);
163
+ return sha;
164
+ }
165
+ function resolveAgentLabel(metadata) {
166
+ const fromAgent = readMetadataString(metadata, ["agent", "agentName", "provider"]);
167
+ return fromAgent ?? "unknown";
168
+ }
169
+ function readMetadataString(metadata, keys) {
170
+ for (const key of keys) {
171
+ const value = metadata[key];
172
+ if (typeof value === "string" && value.trim().length > 0) {
173
+ return value.trim();
174
+ }
175
+ }
176
+ return void 0;
177
+ }
178
+ function renderFilesPreview(files) {
179
+ if (files.length === 0) {
180
+ return "- No file list was reported by the execution step.";
181
+ }
182
+ const preview = files.slice(0, 15).map((path) => `- \`${path}\``);
183
+ if (files.length > 15) {
184
+ preview.push(`- ...and ${files.length - 15} more file(s)`);
185
+ }
186
+ return preview.join("\n");
187
+ }
188
+ function formatDurationSeconds(duration) {
189
+ if (!Number.isFinite(duration) || duration <= 0) {
190
+ return "0s";
191
+ }
192
+ const seconds = duration > 1e3 ? duration / 1e3 : duration;
193
+ if (seconds >= 100) {
194
+ return `${Math.round(seconds)}s`;
195
+ }
196
+ return `${seconds.toFixed(1)}s`;
197
+ }
198
+
199
+ // src/completion/issue-linker.ts
200
+ async function linkIssueToePR(repo, task, pr, octokit) {
201
+ if (!task.linkedIssue) {
202
+ return;
203
+ }
204
+ const issueNumber = task.linkedIssue.number;
205
+ try {
206
+ const issue = await octokit.issues.get({
207
+ owner: repo.owner,
208
+ repo: repo.name,
209
+ issue_number: issueNumber
210
+ });
211
+ if (issue.data.state === "closed") {
212
+ return;
213
+ }
214
+ await octokit.issues.createComment({
215
+ owner: repo.owner,
216
+ repo: repo.name,
217
+ issue_number: issueNumber,
218
+ body: `OAC opened a PR for this issue: ${pr.url}`
219
+ });
220
+ } catch (error) {
221
+ if (isNonBlockingIssueError(error)) {
222
+ return;
223
+ }
224
+ throw completionError(
225
+ "PR_CREATION_FAILED",
226
+ `Failed to link issue #${issueNumber} to PR #${pr.number}.`,
227
+ {
228
+ cause: error,
229
+ context: {
230
+ repo: repo.fullName,
231
+ issueNumber,
232
+ prNumber: pr.number
233
+ }
234
+ }
235
+ );
236
+ }
237
+ }
238
+ var linkIssueToPR = linkIssueToePR;
239
+ function isNonBlockingIssueError(error) {
240
+ if (!isStatusError(error)) {
241
+ return false;
242
+ }
243
+ return error.status === 404 || error.status === 410 || error.status === 422;
244
+ }
245
+ function isStatusError(error) {
246
+ return typeof error === "object" && error !== null && "status" in error;
247
+ }
248
+
249
+ // src/completion/diff-validator.ts
250
+ import { basename } from "path";
251
+ import { simpleGit as simpleGit2 } from "simple-git";
252
+ var DEFAULT_MAX_DIFF_LINES = 500;
253
+ var DEFAULT_FORBIDDEN_PATTERNS = [
254
+ /eval\s*\(/,
255
+ /new\s+Function\s*\(/,
256
+ /child_process/,
257
+ /\bexecSync\s*\(/,
258
+ /\bspawnSync\s*\(/
259
+ ];
260
+ var DEFAULT_PROTECTED_FILES = [".env*", "*.pem", "*.key"];
261
+ async function validateDiff(repoPath, config) {
262
+ const git = simpleGit2(repoPath);
263
+ const settings = resolveValidationConfig(config);
264
+ const warnings = [];
265
+ const errors = [];
266
+ const [diffSummary, changedFiles, patch] = await Promise.all([
267
+ readDiffSummary(git),
268
+ readChangedFiles(git),
269
+ readPatch(git)
270
+ ]);
271
+ const totalLinesChanged = diffSummary.insertions + diffSummary.deletions;
272
+ if (totalLinesChanged > settings.maxDiffLines) {
273
+ errors.push(
274
+ `Diff too large: ${totalLinesChanged} changed lines exceeds maxDiffLines=${settings.maxDiffLines}.`
275
+ );
276
+ } else if (totalLinesChanged > Math.floor(settings.maxDiffLines * 0.8)) {
277
+ warnings.push(
278
+ `Diff is near the maximum size (${totalLinesChanged}/${settings.maxDiffLines} changed lines).`
279
+ );
280
+ }
281
+ if (totalLinesChanged === 0) {
282
+ warnings.push("No changed lines detected in the current diff.");
283
+ }
284
+ const protectedFileHits = changedFiles.filter(
285
+ (path) => settings.protectedFiles.some((pattern) => matchesGlob(path, pattern))
286
+ );
287
+ if (protectedFileHits.length > 0) {
288
+ errors.push(`Protected files were modified: ${protectedFileHits.join(", ")}.`);
289
+ }
290
+ const forbiddenHits = findForbiddenPatternHits(patch, settings.forbiddenPatterns);
291
+ errors.push(...forbiddenHits);
292
+ return {
293
+ valid: errors.length === 0,
294
+ warnings,
295
+ errors
296
+ };
297
+ }
298
+ async function readDiffSummary(git) {
299
+ try {
300
+ return await git.diffSummary(["HEAD"]);
301
+ } catch {
302
+ return git.diffSummary();
303
+ }
304
+ }
305
+ async function readChangedFiles(git) {
306
+ const withHead = await tryGitDiff(git, ["--name-only", "HEAD"]);
307
+ const output = withHead ?? await git.diff(["--name-only"]);
308
+ return output.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
309
+ }
310
+ async function readPatch(git) {
311
+ const withHead = await tryGitDiff(git, ["--no-color", "--unified=0", "HEAD"]);
312
+ if (withHead !== void 0) {
313
+ return withHead;
314
+ }
315
+ return git.diff(["--no-color", "--unified=0"]);
316
+ }
317
+ async function tryGitDiff(git, args) {
318
+ try {
319
+ return await git.diff(args);
320
+ } catch {
321
+ return void 0;
322
+ }
323
+ }
324
+ function resolveValidationConfig(config) {
325
+ const diffConfig = isOacConfig(config) ? void 0 : config;
326
+ const maxDiffLines = isOacConfig(config) ? config.execution.validation.maxDiffLines : diffConfig?.maxDiffLines;
327
+ return {
328
+ maxDiffLines: typeof maxDiffLines === "number" && maxDiffLines > 0 ? Math.floor(maxDiffLines) : DEFAULT_MAX_DIFF_LINES,
329
+ forbiddenPatterns: Array.isArray(diffConfig?.forbiddenPatterns) && diffConfig.forbiddenPatterns.length > 0 ? diffConfig.forbiddenPatterns : DEFAULT_FORBIDDEN_PATTERNS,
330
+ protectedFiles: Array.isArray(diffConfig?.protectedFiles) && diffConfig.protectedFiles.length > 0 ? diffConfig.protectedFiles : DEFAULT_PROTECTED_FILES
331
+ };
332
+ }
333
+ function isOacConfig(value) {
334
+ return typeof value === "object" && value !== null && "execution" in value && typeof value.execution === "object";
335
+ }
336
+ function findForbiddenPatternHits(diffPatch, patterns) {
337
+ const hits = /* @__PURE__ */ new Set();
338
+ let currentFile = "(unknown)";
339
+ for (const line of diffPatch.split("\n")) {
340
+ if (line.startsWith("+++ b/")) {
341
+ currentFile = line.slice("+++ b/".length).trim();
342
+ continue;
343
+ }
344
+ if (!line.startsWith("+") || line.startsWith("+++")) {
345
+ continue;
346
+ }
347
+ const addedLine = line.slice(1);
348
+ for (const pattern of patterns) {
349
+ if (patternMatches(pattern, addedLine)) {
350
+ const preview = truncate(addedLine.trim(), 120);
351
+ hits.add(`Forbidden pattern "${pattern}" found in ${currentFile}: "${preview}".`);
352
+ }
353
+ }
354
+ }
355
+ return [...hits];
356
+ }
357
+ function patternMatches(pattern, input) {
358
+ const normalizedFlags = pattern.flags.replaceAll("g", "");
359
+ const matcher = new RegExp(pattern.source, normalizedFlags);
360
+ return matcher.test(input);
361
+ }
362
+ function matchesGlob(path, pattern) {
363
+ const regex = globToRegex(pattern);
364
+ const filename = basename(path);
365
+ return regex.test(path) || regex.test(filename);
366
+ }
367
+ function globToRegex(glob) {
368
+ const escaped = glob.replaceAll(/[-/\\^$+?.()|[\]{}]/g, "\\$&").replaceAll("*", ".*");
369
+ return new RegExp(`^${escaped}$`);
370
+ }
371
+
372
+ // src/completion/handler.ts
373
+ var CompletionHandler = class {
374
+ octokit;
375
+ eventBus;
376
+ providers;
377
+ diffValidationConfig;
378
+ constructor(options) {
379
+ this.octokit = options.octokit;
380
+ this.eventBus = options.eventBus;
381
+ this.providers = options.providers ?? [];
382
+ this.diffValidationConfig = options.diffValidationConfig;
383
+ }
384
+ async handle(params) {
385
+ return this.complete(params);
386
+ }
387
+ async complete(params) {
388
+ const warnings = [];
389
+ const externalTaskRef = this.resolveExternalTaskRef(params.task, params.externalTaskRef);
390
+ try {
391
+ this.emitProgress(params.jobId, params.result.totalTokensUsed, "completion:validateDiff");
392
+ const validation = await validateDiff(
393
+ resolveRepoPath(params.repo),
394
+ params.diffValidationConfig ?? this.diffValidationConfig
395
+ );
396
+ this.handleValidationResult(validation);
397
+ warnings.push(...validation.warnings);
398
+ warnings.push(...await this.notifyStarted(externalTaskRef));
399
+ this.emitProgress(params.jobId, params.result.totalTokensUsed, "completion:pushBranch");
400
+ await pushBranch(params.repo, params.branchName);
401
+ this.emitProgress(params.jobId, params.result.totalTokensUsed, "completion:createPR");
402
+ const pr = await createPR(params, this.octokit);
403
+ this.eventBus.emit("pr:created", { jobId: params.jobId, prUrl: pr.url });
404
+ this.emitProgress(params.jobId, params.result.totalTokensUsed, "completion:linkIssue");
405
+ const linkIssueWarning = await this.tryLinkIssue(params.repo, params.task, pr);
406
+ if (linkIssueWarning) {
407
+ warnings.push(linkIssueWarning);
408
+ }
409
+ this.emitProgress(params.jobId, params.result.totalTokensUsed, "completion:notifyWebhooks");
410
+ warnings.push(...await this.notifyPRCreated(externalTaskRef, pr));
411
+ const completionResult = buildCompletionResult(params, pr, warnings);
412
+ warnings.push(...await this.notifyCompleted(externalTaskRef, completionResult));
413
+ return completionResult;
414
+ } catch (error) {
415
+ const normalizedError = this.normalizePipelineError(error, params);
416
+ this.eventBus.emit("execution:failed", {
417
+ jobId: params.jobId,
418
+ error: normalizedError
419
+ });
420
+ await this.notifyFailed(externalTaskRef, normalizedError.message);
421
+ throw normalizedError;
422
+ }
423
+ }
424
+ emitProgress(jobId, tokensUsed, stage) {
425
+ this.eventBus.emit("execution:progress", {
426
+ jobId,
427
+ tokensUsed,
428
+ stage
429
+ });
430
+ }
431
+ handleValidationResult(validation) {
432
+ if (validation.valid) {
433
+ return;
434
+ }
435
+ const hasForbiddenPattern = validation.errors.some(
436
+ (message) => message.toLowerCase().includes("forbidden pattern")
437
+ );
438
+ const errorCode = hasForbiddenPattern ? "VALIDATION_FORBIDDEN_PATTERN" : "VALIDATION_DIFF_TOO_LARGE";
439
+ throw executionError(errorCode, "Diff validation failed.", {
440
+ context: {
441
+ errors: validation.errors,
442
+ warnings: validation.warnings
443
+ }
444
+ });
445
+ }
446
+ async tryLinkIssue(repo, task, pr) {
447
+ try {
448
+ await linkIssueToePR(repo, task, pr, this.octokit);
449
+ return void 0;
450
+ } catch (error) {
451
+ return `Issue linking warning: ${toErrorMessage(error)}`;
452
+ }
453
+ }
454
+ async notifyStarted(ref) {
455
+ return this.notifyProviders(
456
+ ref,
457
+ "notifyStarted",
458
+ (provider, taskRef) => provider.notifyStarted(taskRef)
459
+ );
460
+ }
461
+ async notifyPRCreated(ref, pr) {
462
+ return this.notifyProviders(
463
+ ref,
464
+ "notifyPRCreated",
465
+ (provider, taskRef) => provider.notifyPRCreated(taskRef, pr.url)
466
+ );
467
+ }
468
+ async notifyCompleted(ref, result) {
469
+ return this.notifyProviders(
470
+ ref,
471
+ "notifyCompleted",
472
+ (provider, taskRef) => provider.notifyCompleted(taskRef, result)
473
+ );
474
+ }
475
+ async notifyFailed(ref, message) {
476
+ await this.notifyProviders(
477
+ ref,
478
+ "notifyFailed",
479
+ (provider, taskRef) => provider.notifyFailed(taskRef, message)
480
+ );
481
+ }
482
+ async notifyProviders(ref, operationName, operation) {
483
+ if (!ref) {
484
+ return [];
485
+ }
486
+ const selectedProviders = this.providers.filter((provider) => provider.id === ref.provider);
487
+ if (selectedProviders.length === 0) {
488
+ return [];
489
+ }
490
+ const results = await Promise.allSettled(
491
+ selectedProviders.map(async (provider) => {
492
+ const isReachable = await provider.ping();
493
+ if (!isReachable) {
494
+ throw new Error(`Provider "${provider.id}" is unreachable.`);
495
+ }
496
+ await operation(provider, ref);
497
+ })
498
+ );
499
+ const warnings = [];
500
+ for (let index = 0; index < results.length; index += 1) {
501
+ const result = results[index];
502
+ if (result.status === "fulfilled") {
503
+ continue;
504
+ }
505
+ warnings.push(
506
+ `${operationName} failed for provider "${selectedProviders[index].id}": ${toErrorMessage(result.reason)}`
507
+ );
508
+ }
509
+ return warnings;
510
+ }
511
+ resolveExternalTaskRef(task, providedRef) {
512
+ if (providedRef) {
513
+ return providedRef;
514
+ }
515
+ if (task.linkedIssue) {
516
+ return {
517
+ provider: "github",
518
+ externalId: `#${task.linkedIssue.number}`,
519
+ url: task.linkedIssue.url
520
+ };
521
+ }
522
+ const metadata = task.metadata;
523
+ const provider = readMetadataString2(metadata, "externalProvider");
524
+ const externalId = readMetadataString2(metadata, "externalId");
525
+ const url = readMetadataString2(metadata, "externalUrl");
526
+ if (!provider || !externalId) {
527
+ return void 0;
528
+ }
529
+ return { provider, externalId, url };
530
+ }
531
+ normalizePipelineError(error, params) {
532
+ if (error instanceof OacError) {
533
+ return error;
534
+ }
535
+ return completionError(
536
+ "PR_CREATION_FAILED",
537
+ `Completion pipeline failed for task "${params.task.id}" in "${params.repo.fullName}": ${toErrorMessage(
538
+ error
539
+ )}`,
540
+ {
541
+ cause: error,
542
+ context: {
543
+ jobId: params.jobId,
544
+ taskId: params.task.id,
545
+ repo: params.repo.fullName,
546
+ branchName: params.branchName
547
+ }
548
+ }
549
+ );
550
+ }
551
+ };
552
+ function buildCompletionResult(params, pr, warnings) {
553
+ const filesChanged = params.result.filesChanged.length;
554
+ const warningSuffix = warnings.length > 0 ? ` Completed with ${warnings.length} warning(s).` : "";
555
+ return {
556
+ prUrl: pr.url,
557
+ commitSha: pr.sha,
558
+ summary: `Created PR #${pr.number} for "${params.task.title}".${warningSuffix}`,
559
+ filesChanged,
560
+ tokensUsed: params.result.totalTokensUsed
561
+ };
562
+ }
563
+ function resolveRepoPath(repo) {
564
+ return repo.worktreePath.trim().length > 0 ? repo.worktreePath : repo.localPath;
565
+ }
566
+ function readMetadataString2(metadata, key) {
567
+ const value = metadata[key];
568
+ if (typeof value === "string" && value.trim().length > 0) {
569
+ return value.trim();
570
+ }
571
+ return void 0;
572
+ }
573
+ function toErrorMessage(error) {
574
+ if (error instanceof Error && error.message.trim().length > 0) {
575
+ return error.message.trim();
576
+ }
577
+ return "Unknown error";
578
+ }
579
+ export {
580
+ CompletionHandler,
581
+ createPR,
582
+ linkIssueToPR,
583
+ linkIssueToePR,
584
+ pushBranch,
585
+ validateDiff
586
+ };
587
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/completion/github-pr.ts","../../src/completion/issue-linker.ts","../../src/completion/diff-validator.ts","../../src/completion/handler.ts"],"sourcesContent":["import type { Octokit } from \"@octokit/rest\";\nimport { type SimpleGit, simpleGit } from \"simple-git\";\nimport { type ResolvedRepo, completionError } from \"../core/index.js\";\n\nimport type { CreatedPR, PRCreationParams } from \"./types.js\";\n\ninterface PRDiffStats {\n filesChanged: number;\n linesAdded: number;\n linesRemoved: number;\n}\n\nexport async function createPR(params: PRCreationParams, octokit: Octokit): Promise<CreatedPR> {\n const { repo, task, result, branchName, baseBranch } = params;\n const pushedSha = await pushBranch(repo, branchName);\n const body = await buildPrBody(params);\n\n try {\n const created = await octokit.pulls.create({\n owner: repo.owner,\n repo: repo.name,\n title: `[OAC] ${task.title}`,\n body,\n head: branchName,\n base: baseBranch,\n draft: false,\n });\n\n await addLabels(octokit, repo, created.data.number, [\"oac-contribution\", task.source]);\n\n return {\n number: created.data.number,\n url: created.data.html_url,\n sha: created.data.head.sha || pushedSha,\n };\n } catch (error) {\n throw completionError(\n \"PR_CREATION_FAILED\",\n `Failed to create PR for \"${repo.fullName}\" on branch \"${branchName}\".`,\n {\n cause: error,\n context: {\n repo: repo.fullName,\n branchName,\n baseBranch,\n taskId: task.id,\n },\n },\n );\n }\n}\n\nexport async function pushBranch(repo: ResolvedRepo, branchName: string): Promise<string> {\n const git = simpleGit(resolveGitPath(repo));\n const headSha = (await git.revparse([\"HEAD\"])).trim();\n\n try {\n const remoteSha = await readRemoteBranchSha(git, branchName);\n if (remoteSha !== headSha) {\n await git.push(\"origin\", branchName);\n }\n } catch (error) {\n try {\n await git.raw([\"push\", \"--set-upstream\", \"origin\", branchName]);\n } catch (retryError) {\n throw completionError(\n \"PR_PUSH_REJECTED\",\n `Failed to push branch \"${branchName}\" for \"${repo.fullName}\".`,\n {\n cause: retryError,\n context: {\n repo: repo.fullName,\n branchName,\n headSha,\n initialError: error instanceof Error ? error.message : \"unknown push error\",\n },\n },\n );\n }\n }\n\n return headSha;\n}\n\nasync function buildPrBody(params: PRCreationParams): Promise<string> {\n const { repo, task, result, baseBranch, branchName } = params;\n const diffStats = await resolveDiffStats(repo, baseBranch, branchName);\n const linkedIssue = task.linkedIssue ? `\\nFixes #${task.linkedIssue.number}\\n` : \"\\n\";\n const agentLabel = resolveAgentLabel(task.metadata);\n const durationText = formatDurationSeconds(result.duration);\n const summaryText =\n task.description.trim().length > 0\n ? task.description.trim()\n : `Automated contribution for task \"${task.title}\".`;\n const filesChanged = result.filesChanged.length || diffStats.filesChanged;\n const filesPreview = renderFilesPreview(result.filesChanged);\n\n return [\n \"## Summary\",\n \"\",\n summaryText,\n \"\",\n \"## Changes\",\n \"\",\n filesPreview,\n \"\",\n `- **Files changed:** ${filesChanged}`,\n `- **Lines added:** ${diffStats.linesAdded}`,\n `- **Lines removed:** ${diffStats.linesRemoved}`,\n \"\",\n \"## Context\",\n \"\",\n `- **Task source:** ${task.source}`,\n `- **Agent:** ${agentLabel}`,\n `- **Tokens used:** ${result.totalTokensUsed}`,\n `- **Execution time:** ${durationText}`,\n linkedIssue.trimEnd(),\n \"\",\n \"---\",\n \"*This PR was automatically generated by OAC.*\",\n ].join(\"\\n\");\n}\n\nasync function resolveDiffStats(\n repo: ResolvedRepo,\n baseBranch: string,\n branchName: string,\n): Promise<PRDiffStats> {\n const git = simpleGit(resolveGitPath(repo));\n const ranges = [\n [`origin/${baseBranch}...${branchName}`],\n [`${baseBranch}...${branchName}`],\n [\"HEAD\"],\n [],\n ] as string[][];\n\n for (const range of ranges) {\n try {\n const summary = await git.diffSummary(range);\n return {\n filesChanged: summary.changed,\n linesAdded: summary.insertions,\n linesRemoved: summary.deletions,\n };\n } catch {} // best-effort: diff stats are optional\n }\n\n return {\n filesChanged: 0,\n linesAdded: 0,\n linesRemoved: 0,\n };\n}\n\nasync function addLabels(\n octokit: Octokit,\n repo: ResolvedRepo,\n prNumber: number,\n labels: string[],\n): Promise<void> {\n const uniqueLabels = [...new Set(labels.map((label) => label.trim()).filter(Boolean))];\n if (uniqueLabels.length === 0) {\n return;\n }\n\n try {\n await octokit.issues.addLabels({\n owner: repo.owner,\n repo: repo.name,\n issue_number: prNumber,\n labels: uniqueLabels,\n });\n } catch {\n // Labeling failure should not block PR creation.\n }\n}\n\nfunction resolveGitPath(repo: ResolvedRepo): string {\n return repo.worktreePath.trim().length > 0 ? repo.worktreePath : repo.localPath;\n}\n\nasync function readRemoteBranchSha(\n git: SimpleGit,\n branchName: string,\n): Promise<string | undefined> {\n const remoteHeads = await git.listRemote([\"--heads\", \"origin\", branchName]);\n const firstLine = remoteHeads\n .split(\"\\n\")\n .map((line) => line.trim())\n .find((line) => line.length > 0);\n\n if (!firstLine) {\n return undefined;\n }\n\n const [sha] = firstLine.split(/\\s+/);\n return sha;\n}\n\nfunction resolveAgentLabel(metadata: Record<string, unknown>): string {\n const fromAgent = readMetadataString(metadata, [\"agent\", \"agentName\", \"provider\"]);\n return fromAgent ?? \"unknown\";\n}\n\nfunction readMetadataString(metadata: Record<string, unknown>, keys: string[]): string | undefined {\n for (const key of keys) {\n const value = metadata[key];\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value.trim();\n }\n }\n return undefined;\n}\n\nfunction renderFilesPreview(files: string[]): string {\n if (files.length === 0) {\n return \"- No file list was reported by the execution step.\";\n }\n\n const preview = files.slice(0, 15).map((path) => `- \\`${path}\\``);\n if (files.length > 15) {\n preview.push(`- ...and ${files.length - 15} more file(s)`);\n }\n\n return preview.join(\"\\n\");\n}\n\nfunction formatDurationSeconds(duration: number): string {\n if (!Number.isFinite(duration) || duration <= 0) {\n return \"0s\";\n }\n\n const seconds = duration > 1_000 ? duration / 1_000 : duration;\n if (seconds >= 100) {\n return `${Math.round(seconds)}s`;\n }\n\n return `${seconds.toFixed(1)}s`;\n}\n","import type { Octokit } from \"@octokit/rest\";\nimport { type ResolvedRepo, type Task, completionError } from \"../core/index.js\";\n\nimport type { CreatedPR } from \"./types.js\";\n\nexport async function linkIssueToePR(\n repo: ResolvedRepo,\n task: Task,\n pr: CreatedPR,\n octokit: Octokit,\n): Promise<void> {\n if (!task.linkedIssue) {\n return;\n }\n\n const issueNumber = task.linkedIssue.number;\n\n try {\n const issue = await octokit.issues.get({\n owner: repo.owner,\n repo: repo.name,\n issue_number: issueNumber,\n });\n\n if (issue.data.state === \"closed\") {\n return;\n }\n\n await octokit.issues.createComment({\n owner: repo.owner,\n repo: repo.name,\n issue_number: issueNumber,\n body: `OAC opened a PR for this issue: ${pr.url}`,\n });\n } catch (error) {\n if (isNonBlockingIssueError(error)) {\n return;\n }\n\n throw completionError(\n \"PR_CREATION_FAILED\",\n `Failed to link issue #${issueNumber} to PR #${pr.number}.`,\n {\n cause: error,\n context: {\n repo: repo.fullName,\n issueNumber,\n prNumber: pr.number,\n },\n },\n );\n }\n}\n\nexport const linkIssueToPR = linkIssueToePR;\n\nfunction isNonBlockingIssueError(error: unknown): boolean {\n if (!isStatusError(error)) {\n return false;\n }\n\n return error.status === 404 || error.status === 410 || error.status === 422;\n}\n\nfunction isStatusError(error: unknown): error is { status?: number } {\n return typeof error === \"object\" && error !== null && \"status\" in error;\n}\n","import { basename } from \"node:path\";\n\nimport { type SimpleGit, simpleGit } from \"simple-git\";\nimport type { OacConfig } from \"../core/index.js\";\nimport { truncate } from \"../core/utils.js\";\n\nconst DEFAULT_MAX_DIFF_LINES = 500;\nconst DEFAULT_FORBIDDEN_PATTERNS: RegExp[] = [\n /eval\\s*\\(/,\n /new\\s+Function\\s*\\(/,\n /child_process/,\n /\\bexecSync\\s*\\(/,\n /\\bspawnSync\\s*\\(/,\n];\nconst DEFAULT_PROTECTED_FILES = [\".env*\", \"*.pem\", \"*.key\"];\n\ninterface ResolvedValidationConfig {\n maxDiffLines: number;\n forbiddenPatterns: RegExp[];\n protectedFiles: string[];\n}\n\nexport interface DiffValidationConfig {\n maxDiffLines?: number;\n forbiddenPatterns?: RegExp[];\n protectedFiles?: string[];\n}\n\nexport interface ValidationResult {\n valid: boolean;\n warnings: string[];\n errors: string[];\n}\n\nexport async function validateDiff(\n repoPath: string,\n config?: DiffValidationConfig | OacConfig,\n): Promise<ValidationResult> {\n const git = simpleGit(repoPath);\n const settings = resolveValidationConfig(config);\n const warnings: string[] = [];\n const errors: string[] = [];\n\n const [diffSummary, changedFiles, patch] = await Promise.all([\n readDiffSummary(git),\n readChangedFiles(git),\n readPatch(git),\n ]);\n\n const totalLinesChanged = diffSummary.insertions + diffSummary.deletions;\n if (totalLinesChanged > settings.maxDiffLines) {\n errors.push(\n `Diff too large: ${totalLinesChanged} changed lines exceeds maxDiffLines=${settings.maxDiffLines}.`,\n );\n } else if (totalLinesChanged > Math.floor(settings.maxDiffLines * 0.8)) {\n warnings.push(\n `Diff is near the maximum size (${totalLinesChanged}/${settings.maxDiffLines} changed lines).`,\n );\n }\n\n if (totalLinesChanged === 0) {\n warnings.push(\"No changed lines detected in the current diff.\");\n }\n\n const protectedFileHits = changedFiles.filter((path) =>\n settings.protectedFiles.some((pattern) => matchesGlob(path, pattern)),\n );\n if (protectedFileHits.length > 0) {\n errors.push(`Protected files were modified: ${protectedFileHits.join(\", \")}.`);\n }\n\n const forbiddenHits = findForbiddenPatternHits(patch, settings.forbiddenPatterns);\n errors.push(...forbiddenHits);\n\n return {\n valid: errors.length === 0,\n warnings,\n errors,\n };\n}\n\nasync function readDiffSummary(git: SimpleGit) {\n try {\n return await git.diffSummary([\"HEAD\"]);\n } catch {\n return git.diffSummary();\n }\n}\n\nasync function readChangedFiles(git: SimpleGit): Promise<string[]> {\n const withHead = await tryGitDiff(git, [\"--name-only\", \"HEAD\"]);\n const output = withHead ?? (await git.diff([\"--name-only\"]));\n\n return output\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.length > 0);\n}\n\nasync function readPatch(git: SimpleGit): Promise<string> {\n const withHead = await tryGitDiff(git, [\"--no-color\", \"--unified=0\", \"HEAD\"]);\n if (withHead !== undefined) {\n return withHead;\n }\n return git.diff([\"--no-color\", \"--unified=0\"]);\n}\n\nasync function tryGitDiff(git: SimpleGit, args: string[]): Promise<string | undefined> {\n try {\n return await git.diff(args);\n } catch {\n return undefined;\n }\n}\n\nfunction resolveValidationConfig(\n config?: DiffValidationConfig | OacConfig,\n): ResolvedValidationConfig {\n const diffConfig = isOacConfig(config) ? undefined : config;\n const maxDiffLines = isOacConfig(config)\n ? config.execution.validation.maxDiffLines\n : diffConfig?.maxDiffLines;\n\n return {\n maxDiffLines:\n typeof maxDiffLines === \"number\" && maxDiffLines > 0\n ? Math.floor(maxDiffLines)\n : DEFAULT_MAX_DIFF_LINES,\n forbiddenPatterns:\n Array.isArray(diffConfig?.forbiddenPatterns) && diffConfig.forbiddenPatterns.length > 0\n ? diffConfig.forbiddenPatterns\n : DEFAULT_FORBIDDEN_PATTERNS,\n protectedFiles:\n Array.isArray(diffConfig?.protectedFiles) && diffConfig.protectedFiles.length > 0\n ? diffConfig.protectedFiles\n : DEFAULT_PROTECTED_FILES,\n };\n}\n\nfunction isOacConfig(value: DiffValidationConfig | OacConfig | undefined): value is OacConfig {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"execution\" in value &&\n typeof (value as { execution?: unknown }).execution === \"object\"\n );\n}\n\nfunction findForbiddenPatternHits(diffPatch: string, patterns: RegExp[]): string[] {\n const hits = new Set<string>();\n let currentFile = \"(unknown)\";\n\n for (const line of diffPatch.split(\"\\n\")) {\n if (line.startsWith(\"+++ b/\")) {\n currentFile = line.slice(\"+++ b/\".length).trim();\n continue;\n }\n\n if (!line.startsWith(\"+\") || line.startsWith(\"+++\")) {\n continue;\n }\n\n const addedLine = line.slice(1);\n for (const pattern of patterns) {\n if (patternMatches(pattern, addedLine)) {\n const preview = truncate(addedLine.trim(), 120);\n hits.add(`Forbidden pattern \"${pattern}\" found in ${currentFile}: \"${preview}\".`);\n }\n }\n }\n\n return [...hits];\n}\n\nfunction patternMatches(pattern: RegExp, input: string): boolean {\n const normalizedFlags = pattern.flags.replaceAll(\"g\", \"\");\n const matcher = new RegExp(pattern.source, normalizedFlags);\n return matcher.test(input);\n}\n\nfunction matchesGlob(path: string, pattern: string): boolean {\n const regex = globToRegex(pattern);\n const filename = basename(path);\n return regex.test(path) || regex.test(filename);\n}\n\nfunction globToRegex(glob: string): RegExp {\n const escaped = glob.replaceAll(/[-/\\\\^$+?.()|[\\]{}]/g, \"\\\\$&\").replaceAll(\"*\", \".*\");\n return new RegExp(`^${escaped}$`);\n}\n\n\n","import type { Octokit } from \"@octokit/rest\";\nimport {\n type OacConfig,\n OacError,\n type OacEventBus,\n type ResolvedRepo,\n type Task,\n completionError,\n executionError,\n} from \"../core/index.js\";\n\nimport {\n type DiffValidationConfig,\n type ValidationResult,\n validateDiff,\n} from \"./diff-validator.js\";\nimport { createPR, pushBranch } from \"./github-pr.js\";\nimport { linkIssueToePR } from \"./issue-linker.js\";\nimport type {\n CompletionResult,\n CreatedPR,\n ExternalTaskRef,\n PRCreationParams,\n ProjectManagementProvider,\n} from \"./types.js\";\n\nexport interface CompletionHandlerOptions {\n octokit: Octokit;\n eventBus: OacEventBus;\n providers?: ProjectManagementProvider[];\n diffValidationConfig?: DiffValidationConfig | OacConfig;\n}\n\nexport interface CompletionHandlerParams extends PRCreationParams {\n jobId: string;\n externalTaskRef?: ExternalTaskRef;\n diffValidationConfig?: DiffValidationConfig | OacConfig;\n}\n\nexport class CompletionHandler {\n private readonly octokit: Octokit;\n private readonly eventBus: OacEventBus;\n private readonly providers: ProjectManagementProvider[];\n private readonly diffValidationConfig?: DiffValidationConfig | OacConfig;\n\n public constructor(options: CompletionHandlerOptions) {\n this.octokit = options.octokit;\n this.eventBus = options.eventBus;\n this.providers = options.providers ?? [];\n this.diffValidationConfig = options.diffValidationConfig;\n }\n\n public async handle(params: CompletionHandlerParams): Promise<CompletionResult> {\n return this.complete(params);\n }\n\n public async complete(params: CompletionHandlerParams): Promise<CompletionResult> {\n const warnings: string[] = [];\n const externalTaskRef = this.resolveExternalTaskRef(params.task, params.externalTaskRef);\n\n try {\n this.emitProgress(params.jobId, params.result.totalTokensUsed, \"completion:validateDiff\");\n const validation = await validateDiff(\n resolveRepoPath(params.repo),\n params.diffValidationConfig ?? this.diffValidationConfig,\n );\n this.handleValidationResult(validation);\n warnings.push(...validation.warnings);\n\n warnings.push(...(await this.notifyStarted(externalTaskRef)));\n\n this.emitProgress(params.jobId, params.result.totalTokensUsed, \"completion:pushBranch\");\n await pushBranch(params.repo, params.branchName);\n\n this.emitProgress(params.jobId, params.result.totalTokensUsed, \"completion:createPR\");\n const pr = await createPR(params, this.octokit);\n this.eventBus.emit(\"pr:created\", { jobId: params.jobId, prUrl: pr.url });\n\n this.emitProgress(params.jobId, params.result.totalTokensUsed, \"completion:linkIssue\");\n const linkIssueWarning = await this.tryLinkIssue(params.repo, params.task, pr);\n if (linkIssueWarning) {\n warnings.push(linkIssueWarning);\n }\n\n this.emitProgress(params.jobId, params.result.totalTokensUsed, \"completion:notifyWebhooks\");\n warnings.push(...(await this.notifyPRCreated(externalTaskRef, pr)));\n\n const completionResult = buildCompletionResult(params, pr, warnings);\n warnings.push(...(await this.notifyCompleted(externalTaskRef, completionResult)));\n\n return completionResult;\n } catch (error) {\n const normalizedError = this.normalizePipelineError(error, params);\n this.eventBus.emit(\"execution:failed\", {\n jobId: params.jobId,\n error: normalizedError,\n });\n await this.notifyFailed(externalTaskRef, normalizedError.message);\n throw normalizedError;\n }\n }\n\n private emitProgress(jobId: string, tokensUsed: number, stage: string): void {\n this.eventBus.emit(\"execution:progress\", {\n jobId,\n tokensUsed,\n stage,\n });\n }\n\n private handleValidationResult(validation: ValidationResult): void {\n if (validation.valid) {\n return;\n }\n\n const hasForbiddenPattern = validation.errors.some((message) =>\n message.toLowerCase().includes(\"forbidden pattern\"),\n );\n const errorCode = hasForbiddenPattern\n ? \"VALIDATION_FORBIDDEN_PATTERN\"\n : \"VALIDATION_DIFF_TOO_LARGE\";\n\n throw executionError(errorCode, \"Diff validation failed.\", {\n context: {\n errors: validation.errors,\n warnings: validation.warnings,\n },\n });\n }\n\n private async tryLinkIssue(\n repo: ResolvedRepo,\n task: Task,\n pr: CreatedPR,\n ): Promise<string | undefined> {\n try {\n await linkIssueToePR(repo, task, pr, this.octokit);\n return undefined;\n } catch (error) {\n return `Issue linking warning: ${toErrorMessage(error)}`;\n }\n }\n\n private async notifyStarted(ref: ExternalTaskRef | undefined): Promise<string[]> {\n return this.notifyProviders(ref, \"notifyStarted\", (provider, taskRef) =>\n provider.notifyStarted(taskRef),\n );\n }\n\n private async notifyPRCreated(\n ref: ExternalTaskRef | undefined,\n pr: CreatedPR,\n ): Promise<string[]> {\n return this.notifyProviders(ref, \"notifyPRCreated\", (provider, taskRef) =>\n provider.notifyPRCreated(taskRef, pr.url),\n );\n }\n\n private async notifyCompleted(\n ref: ExternalTaskRef | undefined,\n result: CompletionResult,\n ): Promise<string[]> {\n return this.notifyProviders(ref, \"notifyCompleted\", (provider, taskRef) =>\n provider.notifyCompleted(taskRef, result),\n );\n }\n\n private async notifyFailed(ref: ExternalTaskRef | undefined, message: string): Promise<void> {\n await this.notifyProviders(ref, \"notifyFailed\", (provider, taskRef) =>\n provider.notifyFailed(taskRef, message),\n );\n }\n\n private async notifyProviders(\n ref: ExternalTaskRef | undefined,\n operationName: string,\n operation: (provider: ProjectManagementProvider, taskRef: ExternalTaskRef) => Promise<void>,\n ): Promise<string[]> {\n if (!ref) {\n return [];\n }\n\n const selectedProviders = this.providers.filter((provider) => provider.id === ref.provider);\n if (selectedProviders.length === 0) {\n return [];\n }\n\n const results = await Promise.allSettled(\n selectedProviders.map(async (provider) => {\n const isReachable = await provider.ping();\n if (!isReachable) {\n throw new Error(`Provider \"${provider.id}\" is unreachable.`);\n }\n await operation(provider, ref);\n }),\n );\n\n const warnings: string[] = [];\n for (let index = 0; index < results.length; index += 1) {\n const result = results[index];\n if (result.status === \"fulfilled\") {\n continue;\n }\n\n warnings.push(\n `${operationName} failed for provider \"${\n selectedProviders[index].id\n }\": ${toErrorMessage(result.reason)}`,\n );\n }\n\n return warnings;\n }\n\n private resolveExternalTaskRef(\n task: Task,\n providedRef?: ExternalTaskRef,\n ): ExternalTaskRef | undefined {\n if (providedRef) {\n return providedRef;\n }\n\n if (task.linkedIssue) {\n return {\n provider: \"github\",\n externalId: `#${task.linkedIssue.number}`,\n url: task.linkedIssue.url,\n };\n }\n\n const metadata = task.metadata as Record<string, unknown>;\n const provider = readMetadataString(metadata, \"externalProvider\");\n const externalId = readMetadataString(metadata, \"externalId\");\n const url = readMetadataString(metadata, \"externalUrl\");\n\n if (!provider || !externalId) {\n return undefined;\n }\n\n return { provider, externalId, url };\n }\n\n private normalizePipelineError(error: unknown, params: CompletionHandlerParams): OacError {\n if (error instanceof OacError) {\n return error;\n }\n\n return completionError(\n \"PR_CREATION_FAILED\",\n `Completion pipeline failed for task \"${params.task.id}\" in \"${params.repo.fullName}\": ${toErrorMessage(\n error,\n )}`,\n {\n cause: error,\n context: {\n jobId: params.jobId,\n taskId: params.task.id,\n repo: params.repo.fullName,\n branchName: params.branchName,\n },\n },\n );\n }\n}\n\nfunction buildCompletionResult(\n params: CompletionHandlerParams,\n pr: CreatedPR,\n warnings: string[],\n): CompletionResult {\n const filesChanged = params.result.filesChanged.length;\n const warningSuffix = warnings.length > 0 ? ` Completed with ${warnings.length} warning(s).` : \"\";\n\n return {\n prUrl: pr.url,\n commitSha: pr.sha,\n summary: `Created PR #${pr.number} for \"${params.task.title}\".${warningSuffix}`,\n filesChanged,\n tokensUsed: params.result.totalTokensUsed,\n };\n}\n\nfunction resolveRepoPath(repo: ResolvedRepo): string {\n return repo.worktreePath.trim().length > 0 ? repo.worktreePath : repo.localPath;\n}\n\nfunction readMetadataString(metadata: Record<string, unknown>, key: string): string | undefined {\n const value = metadata[key];\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value.trim();\n }\n return undefined;\n}\n\nfunction toErrorMessage(error: unknown): string {\n if (error instanceof Error && error.message.trim().length > 0) {\n return error.message.trim();\n }\n return \"Unknown error\";\n}\n"],"mappings":"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","names":["simpleGit","simpleGit","readMetadataString"]}