@xn-intenton-z2a/agentic-lib 7.4.8 → 7.4.9
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.
- package/{src → .github}/agents/agent-apply-fix.md +10 -0
- package/{src → .github}/agents/agent-director.md +10 -0
- package/{src → .github}/agents/agent-discovery.md +8 -0
- package/{src → .github}/agents/agent-discussion-bot.md +9 -0
- package/{src → .github}/agents/agent-issue-resolution.md +12 -0
- package/{src → .github}/agents/agent-iterate.md +8 -0
- package/{src → .github}/agents/agent-maintain-features.md +8 -0
- package/{src → .github}/agents/agent-maintain-library.md +7 -0
- package/{src → .github}/agents/agent-review-issue.md +8 -0
- package/{src → .github}/agents/agent-supervisor.md +9 -0
- package/.github/workflows/agentic-lib-test.yml +4 -2
- package/.github/workflows/agentic-lib-workflow.yml +70 -26
- package/README.md +5 -7
- package/agentic-lib.toml +16 -38
- package/bin/agentic-lib.js +49 -60
- package/package.json +3 -4
- package/src/actions/agentic-step/action.yml +1 -1
- package/src/actions/agentic-step/copilot.js +0 -5
- package/src/actions/agentic-step/index.js +8 -1
- package/src/actions/agentic-step/logging.js +14 -2
- package/src/actions/agentic-step/tasks/direct.js +86 -65
- package/src/actions/agentic-step/tasks/discussions.js +198 -264
- package/src/actions/agentic-step/tasks/enhance-issue.js +84 -33
- package/src/actions/agentic-step/tasks/fix-code.js +111 -57
- package/src/actions/agentic-step/tasks/maintain-features.js +69 -52
- package/src/actions/agentic-step/tasks/maintain-library.js +57 -19
- package/src/actions/agentic-step/tasks/resolve-issue.js +43 -18
- package/src/actions/agentic-step/tasks/review-issue.js +117 -117
- package/src/actions/agentic-step/tasks/supervise.js +140 -151
- package/src/actions/agentic-step/tasks/transform.js +106 -258
- package/src/copilot/agents.js +2 -2
- package/src/copilot/config.js +2 -18
- package/src/copilot/{hybrid-session.js → copilot-session.js} +39 -7
- package/src/copilot/github-tools.js +514 -0
- package/src/copilot/guards.js +1 -1
- package/src/copilot/session.js +0 -141
- package/src/copilot/tools.js +4 -0
- package/src/iterate.js +1 -1
- package/src/scripts/push-to-logs.sh +1 -1
- package/src/seeds/zero-SCREENSHOT_INDEX.png +0 -0
- package/src/seeds/zero-package.json +1 -1
- package/src/agents/agentic-lib.yml +0 -66
- package/src/copilot/context.js +0 -457
- package/src/mcp/server.js +0 -830
- /package/{src → .github}/agents/agent-ready-issue.md +0 -0
|
@@ -2,18 +2,35 @@
|
|
|
2
2
|
// Copyright (C) 2025-2026 Polycode Limited
|
|
3
3
|
// tasks/enhance-issue.js — Add testable acceptance criteria to issues
|
|
4
4
|
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// Supports batch mode: when no issueNumber is provided, enhances up to 3 issues.
|
|
5
|
+
// Uses runCopilotSession with lean prompts: the model reads features and docs
|
|
6
|
+
// via tools to enhance issues with acceptance criteria.
|
|
8
7
|
|
|
9
8
|
import * as core from "@actions/core";
|
|
9
|
+
import { existsSync, readdirSync } from "fs";
|
|
10
10
|
import { isIssueResolved } from "../safety.js";
|
|
11
|
-
import {
|
|
11
|
+
import { readOptionalFile, extractNarrative, NARRATIVE_INSTRUCTION } from "../copilot.js";
|
|
12
|
+
import { runCopilotSession } from "../../../copilot/copilot-session.js";
|
|
13
|
+
import { createGitHubTools } from "../../../copilot/github-tools.js";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Build a file listing summary (names only).
|
|
17
|
+
*/
|
|
18
|
+
function listFiles(dirPath, extension) {
|
|
19
|
+
if (!dirPath || !existsSync(dirPath)) return [];
|
|
20
|
+
try {
|
|
21
|
+
return readdirSync(dirPath, { recursive: true })
|
|
22
|
+
.filter((f) => String(f).endsWith(extension))
|
|
23
|
+
.map((f) => String(f))
|
|
24
|
+
.slice(0, 20);
|
|
25
|
+
} catch {
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
}
|
|
12
29
|
|
|
13
30
|
/**
|
|
14
31
|
* Enhance a single GitHub issue with testable acceptance criteria.
|
|
15
32
|
*/
|
|
16
|
-
async function enhanceSingleIssue({ octokit, repo, config, issueNumber, instructions, model, tuning: t }) {
|
|
33
|
+
async function enhanceSingleIssue({ octokit, repo, config, issueNumber, instructions, model, tuning: t, logFilePath, screenshotFilePath }) {
|
|
17
34
|
if (await isIssueResolved(octokit, repo, issueNumber)) {
|
|
18
35
|
return { outcome: "nop", details: `Issue #${issueNumber} already resolved` };
|
|
19
36
|
}
|
|
@@ -28,10 +45,13 @@ async function enhanceSingleIssue({ octokit, repo, config, issueNumber, instruct
|
|
|
28
45
|
}
|
|
29
46
|
|
|
30
47
|
const contributing = readOptionalFile(config.paths.contributing.path);
|
|
31
|
-
const
|
|
48
|
+
const featureFiles = listFiles(config.paths.features.path, ".md");
|
|
32
49
|
|
|
33
50
|
const agentInstructions = instructions || "Enhance this issue with clear, testable acceptance criteria.";
|
|
34
51
|
|
|
52
|
+
// Shared mutable state to capture the enhanced body
|
|
53
|
+
const enhanceResult = { body: "" };
|
|
54
|
+
|
|
35
55
|
const prompt = [
|
|
36
56
|
"## Instructions",
|
|
37
57
|
agentInstructions,
|
|
@@ -39,39 +59,71 @@ async function enhanceSingleIssue({ octokit, repo, config, issueNumber, instruct
|
|
|
39
59
|
`## Issue #${issueNumber}: ${issue.title}`,
|
|
40
60
|
issue.body || "(no description)",
|
|
41
61
|
"",
|
|
42
|
-
contributing ? `## Contributing Guidelines\n${contributing.substring(0,
|
|
43
|
-
|
|
44
|
-
config.configToml ? `## Configuration (agentic-lib.toml)\n\`\`\`toml\n${config.configToml}\n\`\`\`` : "",
|
|
45
|
-
config.packageJson ? `## Dependencies (package.json)\n\`\`\`json\n${config.packageJson}\n\`\`\`` : "",
|
|
62
|
+
contributing ? `## Contributing Guidelines\n${contributing.substring(0, 2000)}` : "",
|
|
63
|
+
featureFiles.length > 0 ? `## Feature Files (read with read_file for details)\n${featureFiles.join(", ")}` : "",
|
|
46
64
|
"",
|
|
47
65
|
"## Your Task",
|
|
66
|
+
"Read relevant feature files if needed using read_file.",
|
|
48
67
|
"Write an enhanced version of this issue body that includes:",
|
|
49
68
|
"1. Clear problem statement or feature description",
|
|
50
69
|
"2. Testable acceptance criteria (Given/When/Then or checkbox format)",
|
|
51
70
|
"3. Implementation hints if applicable",
|
|
52
71
|
"",
|
|
53
|
-
"
|
|
72
|
+
"**Call report_enhanced_body exactly once** with the improved issue body.",
|
|
54
73
|
].join("\n");
|
|
55
74
|
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
75
|
+
const systemPrompt =
|
|
76
|
+
"You are a requirements analyst. Enhance GitHub issues with clear, testable acceptance criteria." +
|
|
77
|
+
NARRATIVE_INSTRUCTION;
|
|
78
|
+
|
|
79
|
+
const createTools = (defineTool, _wp, logger) => {
|
|
80
|
+
const ghTools = createGitHubTools(octokit, repo, defineTool, logger);
|
|
81
|
+
|
|
82
|
+
const reportEnhancedBody = defineTool("report_enhanced_body", {
|
|
83
|
+
description: "Report the enhanced issue body with testable acceptance criteria. Call this exactly once.",
|
|
84
|
+
parameters: {
|
|
85
|
+
type: "object",
|
|
86
|
+
properties: {
|
|
87
|
+
enhanced_body: { type: "string", description: "The complete enhanced issue body text" },
|
|
88
|
+
},
|
|
89
|
+
required: ["enhanced_body"],
|
|
90
|
+
},
|
|
91
|
+
handler: async ({ enhanced_body }) => {
|
|
92
|
+
enhanceResult.body = enhanced_body;
|
|
93
|
+
return { textResultForLlm: "Enhanced body recorded." };
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
return [...ghTools, reportEnhancedBody];
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const attachments = [];
|
|
101
|
+
if (logFilePath) attachments.push({ type: "file", path: logFilePath });
|
|
102
|
+
if (screenshotFilePath) attachments.push({ type: "file", path: screenshotFilePath });
|
|
103
|
+
|
|
104
|
+
const result = await runCopilotSession({
|
|
105
|
+
workspacePath: process.cwd(),
|
|
63
106
|
model,
|
|
64
|
-
systemMessage: "You are a requirements analyst. Enhance GitHub issues with clear, testable acceptance criteria.",
|
|
65
|
-
prompt,
|
|
66
|
-
writablePaths: [],
|
|
67
107
|
tuning: t,
|
|
108
|
+
agentPrompt: systemPrompt,
|
|
109
|
+
userPrompt: prompt,
|
|
110
|
+
writablePaths: [],
|
|
111
|
+
createTools,
|
|
112
|
+
attachments,
|
|
113
|
+
excludedTools: ["write_file", "run_command", "run_tests", "dispatch_workflow", "close_issue", "label_issue", "post_discussion_comment"],
|
|
114
|
+
logger: { info: core.info, warning: core.warning, error: core.error, debug: core.debug },
|
|
68
115
|
});
|
|
69
116
|
|
|
70
|
-
|
|
117
|
+
const tokensUsed = result.tokensIn + result.tokensOut;
|
|
118
|
+
|
|
119
|
+
// Fall back to agent message if report_enhanced_body wasn't called
|
|
120
|
+
const enhancedBody = enhanceResult.body || (result.agentMessage || "").trim();
|
|
121
|
+
|
|
122
|
+
if (enhancedBody) {
|
|
71
123
|
await octokit.rest.issues.update({
|
|
72
124
|
...repo,
|
|
73
125
|
issue_number: Number(issueNumber),
|
|
74
|
-
body: enhancedBody
|
|
126
|
+
body: enhancedBody,
|
|
75
127
|
});
|
|
76
128
|
await octokit.rest.issues.addLabels({
|
|
77
129
|
...repo,
|
|
@@ -86,7 +138,6 @@ async function enhanceSingleIssue({ octokit, repo, config, issueNumber, instruct
|
|
|
86
138
|
"",
|
|
87
139
|
`**Task:** enhance-issue`,
|
|
88
140
|
`**Model:** ${model}`,
|
|
89
|
-
`**Features referenced:** ${features.length}`,
|
|
90
141
|
"",
|
|
91
142
|
"The issue body has been updated. The `ready` label has been added to indicate it is ready for implementation.",
|
|
92
143
|
].join("\n"),
|
|
@@ -97,12 +148,12 @@ async function enhanceSingleIssue({ octokit, repo, config, issueNumber, instruct
|
|
|
97
148
|
return {
|
|
98
149
|
outcome: "issue-enhanced",
|
|
99
150
|
tokensUsed,
|
|
100
|
-
inputTokens,
|
|
101
|
-
outputTokens,
|
|
102
|
-
cost,
|
|
151
|
+
inputTokens: result.tokensIn,
|
|
152
|
+
outputTokens: result.tokensOut,
|
|
153
|
+
cost: 0,
|
|
103
154
|
model,
|
|
104
155
|
details: `Enhanced issue #${issueNumber} with acceptance criteria`,
|
|
105
|
-
narrative: `Enhanced issue #${issueNumber} with testable acceptance criteria.`,
|
|
156
|
+
narrative: result.narrative || `Enhanced issue #${issueNumber} with testable acceptance criteria.`,
|
|
106
157
|
};
|
|
107
158
|
}
|
|
108
159
|
|
|
@@ -114,12 +165,12 @@ async function enhanceSingleIssue({ octokit, repo, config, issueNumber, instruct
|
|
|
114
165
|
* @returns {Promise<Object>} Result with outcome, tokensUsed, model
|
|
115
166
|
*/
|
|
116
167
|
export async function enhanceIssue(context) {
|
|
117
|
-
const { octokit, repo, config, issueNumber, instructions, model } = context;
|
|
168
|
+
const { octokit, repo, config, issueNumber, instructions, model, logFilePath, screenshotFilePath } = context;
|
|
118
169
|
const t = config.tuning || {};
|
|
119
170
|
|
|
120
171
|
// Single issue mode
|
|
121
172
|
if (issueNumber) {
|
|
122
|
-
return enhanceSingleIssue({ octokit, repo, config, issueNumber, instructions, model, tuning: t });
|
|
173
|
+
return enhanceSingleIssue({ octokit, repo, config, issueNumber, instructions, model, tuning: t, logFilePath, screenshotFilePath });
|
|
123
174
|
}
|
|
124
175
|
|
|
125
176
|
// Batch mode: find up to 3 unready automated issues
|
|
@@ -141,7 +192,6 @@ export async function enhanceIssue(context) {
|
|
|
141
192
|
let totalTokens = 0;
|
|
142
193
|
let totalInputTokens = 0;
|
|
143
194
|
let totalOutputTokens = 0;
|
|
144
|
-
let totalCost = 0;
|
|
145
195
|
|
|
146
196
|
for (const issue of unready) {
|
|
147
197
|
core.info(`Batch enhancing issue #${issue.number} (${results.length + 1}/${unready.length})`);
|
|
@@ -153,12 +203,13 @@ export async function enhanceIssue(context) {
|
|
|
153
203
|
instructions,
|
|
154
204
|
model,
|
|
155
205
|
tuning: t,
|
|
206
|
+
logFilePath,
|
|
207
|
+
screenshotFilePath,
|
|
156
208
|
});
|
|
157
209
|
results.push(result);
|
|
158
210
|
totalTokens += result.tokensUsed || 0;
|
|
159
211
|
totalInputTokens += result.inputTokens || 0;
|
|
160
212
|
totalOutputTokens += result.outputTokens || 0;
|
|
161
|
-
totalCost += result.cost || 0;
|
|
162
213
|
}
|
|
163
214
|
|
|
164
215
|
const enhanced = results.filter((r) => r.outcome === "issue-enhanced").length;
|
|
@@ -168,7 +219,7 @@ export async function enhanceIssue(context) {
|
|
|
168
219
|
tokensUsed: totalTokens,
|
|
169
220
|
inputTokens: totalInputTokens,
|
|
170
221
|
outputTokens: totalOutputTokens,
|
|
171
|
-
cost:
|
|
222
|
+
cost: 0,
|
|
172
223
|
model,
|
|
173
224
|
details: `Batch enhanced ${enhanced}/${results.length} issues. ${results
|
|
174
225
|
.map((r) => r.details)
|
|
@@ -2,14 +2,15 @@
|
|
|
2
2
|
// Copyright (C) 2025-2026 Polycode Limited
|
|
3
3
|
// tasks/fix-code.js — Fix failing tests or resolve merge conflicts on a PR
|
|
4
4
|
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// Failing checks: analyzes test output, generates code fixes.
|
|
5
|
+
// Uses runCopilotSession with lean prompts: the model reads files, analyzes
|
|
6
|
+
// failures, writes fixes, and runs tests via tools.
|
|
8
7
|
|
|
9
8
|
import * as core from "@actions/core";
|
|
10
9
|
import { readFileSync } from "fs";
|
|
11
10
|
import { execSync } from "child_process";
|
|
12
|
-
import {
|
|
11
|
+
import { formatPathsSection, extractNarrative, NARRATIVE_INSTRUCTION } from "../copilot.js";
|
|
12
|
+
import { runCopilotSession } from "../../../copilot/copilot-session.js";
|
|
13
|
+
import { createGitHubTools, createGitTools } from "../../../copilot/github-tools.js";
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* Extract run_id from a check run's details_url.
|
|
@@ -40,13 +41,8 @@ function fetchRunLog(runId) {
|
|
|
40
41
|
|
|
41
42
|
/**
|
|
42
43
|
* Resolve merge conflicts on a PR using the Copilot SDK.
|
|
43
|
-
* Called when the workflow has started a `git merge origin/main` that left
|
|
44
|
-
* conflict markers in non-trivial files (listed in NON_TRIVIAL_FILES env var).
|
|
45
|
-
*
|
|
46
|
-
* @param {Object} params
|
|
47
|
-
* @returns {Promise<Object>} Result with outcome, tokensUsed, model
|
|
48
44
|
*/
|
|
49
|
-
async function resolveConflicts({ config, pr, prNumber, instructions, model, writablePaths, testCommand }) {
|
|
45
|
+
async function resolveConflicts({ config, pr, prNumber, instructions, model, writablePaths, testCommand, octokit, repo, logFilePath, screenshotFilePath }) {
|
|
50
46
|
const nonTrivialEnv = process.env.NON_TRIVIAL_FILES || "";
|
|
51
47
|
const conflictedPaths = nonTrivialEnv
|
|
52
48
|
.split("\n")
|
|
@@ -70,7 +66,6 @@ async function resolveConflicts({ config, pr, prNumber, instructions, model, wri
|
|
|
70
66
|
});
|
|
71
67
|
|
|
72
68
|
const agentInstructions = instructions || "Resolve the merge conflicts while preserving the PR's intended changes.";
|
|
73
|
-
const readOnlyPaths = config.readOnlyPaths;
|
|
74
69
|
|
|
75
70
|
const prompt = [
|
|
76
71
|
"## Instructions",
|
|
@@ -89,42 +84,60 @@ async function resolveConflicts({ config, pr, prNumber, instructions, model, wri
|
|
|
89
84
|
`## Conflicted Files (${conflicts.length})`,
|
|
90
85
|
...conflicts.map((f) => `### ${f.name}\n\`\`\`\n${f.content}\n\`\`\``),
|
|
91
86
|
"",
|
|
92
|
-
formatPathsSection(writablePaths, readOnlyPaths, config),
|
|
87
|
+
formatPathsSection(writablePaths, config.readOnlyPaths, config),
|
|
93
88
|
"",
|
|
94
89
|
"## Constraints",
|
|
95
90
|
"- Remove ALL conflict markers (<<<<<<, =======, >>>>>>>)",
|
|
96
91
|
"- Preserve the PR's feature/fix intent",
|
|
97
|
-
`- Run \`${testCommand}\` to validate your resolution`,
|
|
92
|
+
`- Run \`${testCommand}\` via run_tests to validate your resolution`,
|
|
98
93
|
].join("\n");
|
|
99
94
|
|
|
100
95
|
const t = config.tuning || {};
|
|
101
|
-
const
|
|
96
|
+
const systemPrompt =
|
|
97
|
+
`You are resolving git merge conflicts on PR #${prNumber}. Write resolved versions of each conflicted file, removing all conflict markers. Preserve the PR's feature intent while incorporating main's updates.` +
|
|
98
|
+
NARRATIVE_INSTRUCTION;
|
|
99
|
+
|
|
100
|
+
const createTools = (defineTool, _wp, logger) => {
|
|
101
|
+
const ghTools = createGitHubTools(octokit, repo, defineTool, logger);
|
|
102
|
+
const gitTools = createGitTools(defineTool, logger);
|
|
103
|
+
return [...ghTools, ...gitTools];
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const attachments = [];
|
|
107
|
+
if (logFilePath) attachments.push({ type: "file", path: logFilePath });
|
|
108
|
+
if (screenshotFilePath) attachments.push({ type: "file", path: screenshotFilePath });
|
|
109
|
+
|
|
110
|
+
const result = await runCopilotSession({
|
|
111
|
+
workspacePath: process.cwd(),
|
|
102
112
|
model,
|
|
103
|
-
systemMessage: `You are resolving git merge conflicts on PR #${prNumber}. Write resolved versions of each conflicted file, removing all conflict markers. Preserve the PR's feature intent while incorporating main's updates.` + NARRATIVE_INSTRUCTION,
|
|
104
|
-
prompt,
|
|
105
|
-
writablePaths,
|
|
106
113
|
tuning: t,
|
|
114
|
+
agentPrompt: systemPrompt,
|
|
115
|
+
userPrompt: prompt,
|
|
116
|
+
writablePaths,
|
|
117
|
+
createTools,
|
|
118
|
+
attachments,
|
|
119
|
+
excludedTools: ["dispatch_workflow", "close_issue", "label_issue", "post_discussion_comment"],
|
|
120
|
+
logger: { info: core.info, warning: core.warning, error: core.error, debug: core.debug },
|
|
107
121
|
});
|
|
108
122
|
|
|
109
|
-
core.info(`Conflict resolution completed (${
|
|
123
|
+
core.info(`Conflict resolution completed (${result.tokensIn + result.tokensOut} tokens)`);
|
|
110
124
|
|
|
111
125
|
return {
|
|
112
126
|
outcome: "conflicts-resolved",
|
|
113
|
-
tokensUsed,
|
|
114
|
-
inputTokens,
|
|
115
|
-
outputTokens,
|
|
116
|
-
cost,
|
|
127
|
+
tokensUsed: result.tokensIn + result.tokensOut,
|
|
128
|
+
inputTokens: result.tokensIn,
|
|
129
|
+
outputTokens: result.tokensOut,
|
|
130
|
+
cost: 0,
|
|
117
131
|
model,
|
|
118
132
|
details: `Resolved ${conflicts.length} conflicted file(s) on PR #${prNumber}`,
|
|
119
|
-
narrative: extractNarrative(
|
|
133
|
+
narrative: result.narrative || extractNarrative(result.agentMessage, `Resolved ${conflicts.length} merge conflict(s) on PR #${prNumber}.`),
|
|
120
134
|
};
|
|
121
135
|
}
|
|
122
136
|
|
|
123
137
|
/**
|
|
124
138
|
* Fix a broken main branch build.
|
|
125
|
-
* Called when no PR is involved — just a failing workflow run on main.
|
|
126
139
|
*/
|
|
127
|
-
async function fixMainBuild({ config, runId, instructions, model, writablePaths, testCommand }) {
|
|
140
|
+
async function fixMainBuild({ config, runId, instructions, model, writablePaths, testCommand, octokit, repo, logFilePath, screenshotFilePath }) {
|
|
128
141
|
const logContent = fetchRunLog(runId);
|
|
129
142
|
if (!logContent) {
|
|
130
143
|
core.info(`Could not fetch log for run ${runId}. Returning nop.`);
|
|
@@ -132,7 +145,6 @@ async function fixMainBuild({ config, runId, instructions, model, writablePaths,
|
|
|
132
145
|
}
|
|
133
146
|
|
|
134
147
|
const agentInstructions = instructions || "Fix the failing tests by modifying the source code.";
|
|
135
|
-
const readOnlyPaths = config.readOnlyPaths;
|
|
136
148
|
|
|
137
149
|
const prompt = [
|
|
138
150
|
"## Instructions",
|
|
@@ -145,34 +157,57 @@ async function fixMainBuild({ config, runId, instructions, model, writablePaths,
|
|
|
145
157
|
"## Failed Run Log",
|
|
146
158
|
logContent,
|
|
147
159
|
"",
|
|
148
|
-
|
|
160
|
+
"## Your Task",
|
|
161
|
+
"Use read_file to read the relevant source and test files.",
|
|
162
|
+
"Make minimal changes to fix the failing tests, then run run_tests to verify.",
|
|
163
|
+
"",
|
|
164
|
+
formatPathsSection(writablePaths, config.readOnlyPaths, config),
|
|
149
165
|
"",
|
|
150
166
|
"## Constraints",
|
|
151
|
-
`- Run \`${testCommand}\` to validate your fixes`,
|
|
167
|
+
`- Run \`${testCommand}\` via run_tests to validate your fixes`,
|
|
152
168
|
"- Make minimal changes to fix the failing tests",
|
|
153
169
|
"- Do not introduce new features — focus on making the build green",
|
|
154
170
|
].join("\n");
|
|
155
171
|
|
|
156
172
|
const t = config.tuning || {};
|
|
157
|
-
const
|
|
173
|
+
const systemPrompt =
|
|
174
|
+
`You are an autonomous coding agent fixing a broken build on the main branch. The test/build workflow has failed. Analyze the error log and make minimal, targeted changes to fix it.` +
|
|
175
|
+
NARRATIVE_INSTRUCTION;
|
|
176
|
+
|
|
177
|
+
const createTools = (defineTool, _wp, logger) => {
|
|
178
|
+
const ghTools = createGitHubTools(octokit, repo, defineTool, logger);
|
|
179
|
+
const gitTools = createGitTools(defineTool, logger);
|
|
180
|
+
return [...ghTools, ...gitTools];
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
const attachments = [];
|
|
184
|
+
if (logFilePath) attachments.push({ type: "file", path: logFilePath });
|
|
185
|
+
if (screenshotFilePath) attachments.push({ type: "file", path: screenshotFilePath });
|
|
186
|
+
|
|
187
|
+
const result = await runCopilotSession({
|
|
188
|
+
workspacePath: process.cwd(),
|
|
158
189
|
model,
|
|
159
|
-
systemMessage: `You are an autonomous coding agent fixing a broken build on the main branch. The test/build workflow has failed. Analyze the error log and make minimal, targeted changes to fix it.` + NARRATIVE_INSTRUCTION,
|
|
160
|
-
prompt,
|
|
161
|
-
writablePaths,
|
|
162
190
|
tuning: t,
|
|
191
|
+
agentPrompt: systemPrompt,
|
|
192
|
+
userPrompt: prompt,
|
|
193
|
+
writablePaths,
|
|
194
|
+
createTools,
|
|
195
|
+
attachments,
|
|
196
|
+
excludedTools: ["dispatch_workflow", "close_issue", "label_issue", "post_discussion_comment"],
|
|
197
|
+
logger: { info: core.info, warning: core.warning, error: core.error, debug: core.debug },
|
|
163
198
|
});
|
|
164
199
|
|
|
165
|
-
core.info(`Main build fix completed (${
|
|
200
|
+
core.info(`Main build fix completed (${result.tokensIn + result.tokensOut} tokens)`);
|
|
166
201
|
|
|
167
202
|
return {
|
|
168
203
|
outcome: "fix-applied",
|
|
169
|
-
tokensUsed,
|
|
170
|
-
inputTokens,
|
|
171
|
-
outputTokens,
|
|
172
|
-
cost,
|
|
204
|
+
tokensUsed: result.tokensIn + result.tokensOut,
|
|
205
|
+
inputTokens: result.tokensIn,
|
|
206
|
+
outputTokens: result.tokensOut,
|
|
207
|
+
cost: 0,
|
|
173
208
|
model,
|
|
174
209
|
details: `Applied fix for broken main build (run ${runId})`,
|
|
175
|
-
narrative: extractNarrative(
|
|
210
|
+
narrative: result.narrative || extractNarrative(result.agentMessage, `Fixed broken main build (run ${runId}).`),
|
|
176
211
|
};
|
|
177
212
|
}
|
|
178
213
|
|
|
@@ -180,19 +215,16 @@ async function fixMainBuild({ config, runId, instructions, model, writablePaths,
|
|
|
180
215
|
* Fix failing code or resolve merge conflicts on a pull request,
|
|
181
216
|
* or fix a broken build on main.
|
|
182
217
|
*
|
|
183
|
-
* Priority: main build fix (if FIX_RUN_ID env is set),
|
|
184
|
-
* then conflicts (if NON_TRIVIAL_FILES env is set), then failing checks.
|
|
185
|
-
*
|
|
186
218
|
* @param {Object} context - Task context from index.js
|
|
187
219
|
* @returns {Promise<Object>} Result with outcome, tokensUsed, model
|
|
188
220
|
*/
|
|
189
221
|
export async function fixCode(context) {
|
|
190
|
-
const { octokit, repo, config, prNumber, instructions, writablePaths, testCommand, model } = context;
|
|
222
|
+
const { octokit, repo, config, prNumber, instructions, writablePaths, testCommand, model, logFilePath, screenshotFilePath } = context;
|
|
191
223
|
|
|
192
224
|
// Fix main build (no PR involved)
|
|
193
225
|
const fixRunId = process.env.FIX_RUN_ID || "";
|
|
194
226
|
if (fixRunId && !prNumber) {
|
|
195
|
-
return fixMainBuild({ config, runId: fixRunId, instructions, model, writablePaths, testCommand });
|
|
227
|
+
return fixMainBuild({ config, runId: fixRunId, instructions, model, writablePaths, testCommand, octokit, repo, logFilePath, screenshotFilePath });
|
|
196
228
|
}
|
|
197
229
|
|
|
198
230
|
if (!prNumber) {
|
|
@@ -204,7 +236,7 @@ export async function fixCode(context) {
|
|
|
204
236
|
|
|
205
237
|
// If we have non-trivial conflict files from the workflow's Tier 1 step, resolve them
|
|
206
238
|
if (process.env.NON_TRIVIAL_FILES) {
|
|
207
|
-
return resolveConflicts({ config, pr, prNumber, instructions, model, writablePaths, testCommand });
|
|
239
|
+
return resolveConflicts({ config, pr, prNumber, instructions, model, writablePaths, testCommand, octokit, repo, logFilePath, screenshotFilePath });
|
|
208
240
|
}
|
|
209
241
|
|
|
210
242
|
// Otherwise, check for failing checks
|
|
@@ -230,7 +262,6 @@ export async function fixCode(context) {
|
|
|
230
262
|
.join("\n\n");
|
|
231
263
|
|
|
232
264
|
const agentInstructions = instructions || "Fix the failing tests by modifying the source code.";
|
|
233
|
-
const readOnlyPaths = config.readOnlyPaths;
|
|
234
265
|
|
|
235
266
|
const prompt = [
|
|
236
267
|
"## Instructions",
|
|
@@ -243,32 +274,55 @@ export async function fixCode(context) {
|
|
|
243
274
|
"## Failing Checks",
|
|
244
275
|
failureDetails,
|
|
245
276
|
"",
|
|
246
|
-
|
|
277
|
+
"## Your Task",
|
|
278
|
+
"Use read_file to read the relevant source and test files.",
|
|
279
|
+
"Make minimal changes to fix the failures, then run run_tests to verify.",
|
|
280
|
+
"",
|
|
281
|
+
formatPathsSection(writablePaths, config.readOnlyPaths, config),
|
|
247
282
|
"",
|
|
248
283
|
"## Constraints",
|
|
249
|
-
`- Run \`${testCommand}\` to validate your fixes`,
|
|
284
|
+
`- Run \`${testCommand}\` via run_tests to validate your fixes`,
|
|
250
285
|
"- Make minimal changes to fix the failing tests",
|
|
251
286
|
].join("\n");
|
|
252
287
|
|
|
253
288
|
const t = config.tuning || {};
|
|
254
|
-
const
|
|
289
|
+
const systemPrompt =
|
|
290
|
+
`You are an autonomous coding agent fixing failing tests on PR #${prNumber}. Make minimal, targeted changes to fix the test failures.` +
|
|
291
|
+
NARRATIVE_INSTRUCTION;
|
|
292
|
+
|
|
293
|
+
const createTools = (defineTool, _wp, logger) => {
|
|
294
|
+
const ghTools = createGitHubTools(octokit, repo, defineTool, logger);
|
|
295
|
+
const gitTools = createGitTools(defineTool, logger);
|
|
296
|
+
return [...ghTools, ...gitTools];
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
const attachments = [];
|
|
300
|
+
if (logFilePath) attachments.push({ type: "file", path: logFilePath });
|
|
301
|
+
if (screenshotFilePath) attachments.push({ type: "file", path: screenshotFilePath });
|
|
302
|
+
|
|
303
|
+
const result = await runCopilotSession({
|
|
304
|
+
workspacePath: process.cwd(),
|
|
255
305
|
model,
|
|
256
|
-
systemMessage: `You are an autonomous coding agent fixing failing tests on PR #${prNumber}. Make minimal, targeted changes to fix the test failures.` + NARRATIVE_INSTRUCTION,
|
|
257
|
-
prompt,
|
|
258
|
-
writablePaths,
|
|
259
306
|
tuning: t,
|
|
307
|
+
agentPrompt: systemPrompt,
|
|
308
|
+
userPrompt: prompt,
|
|
309
|
+
writablePaths,
|
|
310
|
+
createTools,
|
|
311
|
+
attachments,
|
|
312
|
+
excludedTools: ["dispatch_workflow", "close_issue", "label_issue", "post_discussion_comment"],
|
|
313
|
+
logger: { info: core.info, warning: core.warning, error: core.error, debug: core.debug },
|
|
260
314
|
});
|
|
261
315
|
|
|
262
|
-
core.info(`
|
|
316
|
+
core.info(`Fix response received (${result.tokensIn + result.tokensOut} tokens)`);
|
|
263
317
|
|
|
264
318
|
return {
|
|
265
319
|
outcome: "fix-applied",
|
|
266
|
-
tokensUsed,
|
|
267
|
-
inputTokens,
|
|
268
|
-
outputTokens,
|
|
269
|
-
cost,
|
|
320
|
+
tokensUsed: result.tokensIn + result.tokensOut,
|
|
321
|
+
inputTokens: result.tokensIn,
|
|
322
|
+
outputTokens: result.tokensOut,
|
|
323
|
+
cost: 0,
|
|
270
324
|
model,
|
|
271
325
|
details: `Applied fix for ${failedChecks.length} failing check(s) on PR #${prNumber}`,
|
|
272
|
-
narrative: extractNarrative(
|
|
326
|
+
narrative: result.narrative || extractNarrative(result.agentMessage, `Fixed ${failedChecks.length} failing check(s) on PR #${prNumber}.`),
|
|
273
327
|
};
|
|
274
328
|
}
|