@ipul-labs/forge 1.22.0 → 1.35.1
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/LICENSE +21 -0
- package/README.md +153 -78
- package/dist/apple-touch-icon.png +0 -0
- package/dist/assets/index-CNvSOdpC.js +27 -0
- package/dist/assets/index-CSH1OQYQ.css +1 -0
- package/dist/boot-check.js +98 -0
- package/dist/favicon.svg +8 -0
- package/dist/icon-192.png +0 -0
- package/dist/icon-512.png +0 -0
- package/dist/icon.svg +12 -0
- package/dist/index.html +33 -0
- package/dist/manifest.webmanifest +18 -0
- package/dist/theme-init.js +11 -0
- package/lib/bin/cli/analyze.d.ts.map +1 -1
- package/lib/bin/cli/analyze.js +3 -44
- package/lib/bin/cli/analyze.js.map +1 -1
- package/lib/bin/cli/apply.d.ts.map +1 -1
- package/lib/bin/cli/apply.js +2 -20
- package/lib/bin/cli/apply.js.map +1 -1
- package/lib/bin/cli/cifix.d.ts.map +1 -1
- package/lib/bin/cli/cifix.js +4 -28
- package/lib/bin/cli/cifix.js.map +1 -1
- package/lib/bin/cli/close.d.ts.map +1 -1
- package/lib/bin/cli/close.js +2 -33
- package/lib/bin/cli/close.js.map +1 -1
- package/lib/bin/cli/createIssue.d.ts.map +1 -1
- package/lib/bin/cli/createIssue.js +3 -12
- package/lib/bin/cli/createIssue.js.map +1 -1
- package/lib/bin/cli/doctor.d.ts.map +1 -1
- package/lib/bin/cli/doctor.js +3 -4
- package/lib/bin/cli/doctor.js.map +1 -1
- package/lib/bin/cli/init.js +1 -10
- package/lib/bin/cli/init.js.map +1 -1
- package/lib/bin/cli/issue.d.ts.map +1 -1
- package/lib/bin/cli/issue.js +3 -12
- package/lib/bin/cli/issue.js.map +1 -1
- package/lib/bin/cli/issues.d.ts.map +1 -1
- package/lib/bin/cli/issues.js +3 -12
- package/lib/bin/cli/issues.js.map +1 -1
- package/lib/bin/cli/merge.d.ts.map +1 -1
- package/lib/bin/cli/merge.js +4 -20
- package/lib/bin/cli/merge.js.map +1 -1
- package/lib/bin/cli/refine.d.ts.map +1 -1
- package/lib/bin/cli/refine.js +2 -26
- package/lib/bin/cli/refine.js.map +1 -1
- package/lib/bin/cli/repl.d.ts.map +1 -1
- package/lib/bin/cli/repl.js +4 -13
- package/lib/bin/cli/repl.js.map +1 -1
- package/lib/bin/cli/repos.d.ts.map +1 -1
- package/lib/bin/cli/repos.js +1 -11
- package/lib/bin/cli/repos.js.map +1 -1
- package/lib/bin/cli/resetPassword.d.ts +21 -0
- package/lib/bin/cli/resetPassword.d.ts.map +1 -0
- package/lib/bin/cli/resetPassword.js +69 -0
- package/lib/bin/cli/resetPassword.js.map +1 -0
- package/lib/bin/cli/resolution.d.ts.map +1 -1
- package/lib/bin/cli/resolution.js +2 -19
- package/lib/bin/cli/resolution.js.map +1 -1
- package/lib/bin/cli/serverClient.d.ts +2 -0
- package/lib/bin/cli/serverClient.d.ts.map +1 -1
- package/lib/bin/cli/serverClient.js +8 -4
- package/lib/bin/cli/serverClient.js.map +1 -1
- package/lib/bin/cli/session.d.ts.map +1 -1
- package/lib/bin/cli/session.js.map +1 -1
- package/lib/bin/cli/sessionStore.d.ts +1 -1
- package/lib/bin/cli/sessionStore.js +2 -2
- package/lib/bin/cli/sessionStore.js.map +1 -1
- package/lib/bin/cli/ship.d.ts.map +1 -1
- package/lib/bin/cli/ship.js +15 -23
- package/lib/bin/cli/ship.js.map +1 -1
- package/lib/bin/cli/update.d.ts.map +1 -1
- package/lib/bin/cli/update.js +34 -28
- package/lib/bin/cli/update.js.map +1 -1
- package/lib/bin/cli/updatePlan.d.ts +30 -0
- package/lib/bin/cli/updatePlan.d.ts.map +1 -0
- package/lib/bin/cli/updatePlan.js +50 -0
- package/lib/bin/cli/updatePlan.js.map +1 -0
- package/lib/bin/cli/utils.d.ts +3 -0
- package/lib/bin/cli/utils.d.ts.map +1 -1
- package/lib/bin/cli/utils.js +7 -23
- package/lib/bin/cli/utils.js.map +1 -1
- package/lib/bin/cli/validate.d.ts.map +1 -1
- package/lib/bin/cli/validate.js +3 -25
- package/lib/bin/cli/validate.js.map +1 -1
- package/lib/bin/cli/watch.d.ts.map +1 -1
- package/lib/bin/cli/watch.js +3 -12
- package/lib/bin/cli/watch.js.map +1 -1
- package/lib/bin/forge-agent.js +10 -22
- package/lib/bin/forge-agent.js.map +1 -1
- package/lib/server/app.d.ts +24 -0
- package/lib/server/app.d.ts.map +1 -0
- package/lib/server/app.js +58 -0
- package/lib/server/app.js.map +1 -0
- package/lib/server/forge/analyses/analysisStore.d.ts +53 -0
- package/lib/server/forge/analyses/analysisStore.d.ts.map +1 -0
- package/lib/server/forge/analyses/analysisStore.js +77 -0
- package/lib/server/forge/analyses/analysisStore.js.map +1 -0
- package/lib/server/forge/auth/apiTokens.d.ts +34 -0
- package/lib/server/forge/auth/apiTokens.d.ts.map +1 -0
- package/lib/server/forge/auth/apiTokens.js +44 -0
- package/lib/server/forge/auth/apiTokens.js.map +1 -0
- package/lib/server/forge/auth/auditLog.d.ts +36 -0
- package/lib/server/forge/auth/auditLog.d.ts.map +1 -0
- package/lib/server/forge/auth/auditLog.js +56 -0
- package/lib/server/forge/auth/auditLog.js.map +1 -0
- package/lib/server/forge/auth/authConfig.d.ts +13 -0
- package/lib/server/forge/auth/authConfig.d.ts.map +1 -0
- package/lib/server/forge/auth/authConfig.js +37 -0
- package/lib/server/forge/auth/authConfig.js.map +1 -0
- package/lib/server/forge/auth/createAuth.d.ts +130 -0
- package/lib/server/forge/auth/createAuth.d.ts.map +1 -0
- package/lib/server/forge/auth/createAuth.js +387 -0
- package/lib/server/forge/auth/createAuth.js.map +1 -0
- package/lib/server/forge/auth/middleware.d.ts +10 -0
- package/lib/server/forge/auth/middleware.d.ts.map +1 -0
- package/lib/server/forge/auth/middleware.js +22 -0
- package/lib/server/forge/auth/middleware.js.map +1 -0
- package/lib/server/forge/auth/oidc.d.ts +38 -0
- package/lib/server/forge/auth/oidc.d.ts.map +1 -0
- package/lib/server/forge/auth/oidc.js +63 -0
- package/lib/server/forge/auth/oidc.js.map +1 -0
- package/lib/server/forge/auth/passwords.d.ts +7 -0
- package/lib/server/forge/auth/passwords.d.ts.map +1 -0
- package/lib/server/forge/auth/passwords.js +28 -0
- package/lib/server/forge/auth/passwords.js.map +1 -0
- package/lib/server/forge/auth/resetPassword.d.ts +14 -0
- package/lib/server/forge/auth/resetPassword.d.ts.map +1 -0
- package/lib/server/forge/auth/resetPassword.js +29 -0
- package/lib/server/forge/auth/resetPassword.js.map +1 -0
- package/lib/server/forge/auth/roles.d.ts +7 -0
- package/lib/server/forge/auth/roles.d.ts.map +1 -0
- package/lib/server/forge/auth/roles.js +15 -0
- package/lib/server/forge/auth/roles.js.map +1 -0
- package/lib/server/forge/auth/sessions.d.ts +27 -0
- package/lib/server/forge/auth/sessions.d.ts.map +1 -0
- package/lib/server/forge/auth/sessions.js +37 -0
- package/lib/server/forge/auth/sessions.js.map +1 -0
- package/lib/server/forge/auth/testHarness.d.ts +104 -0
- package/lib/server/forge/auth/testHarness.d.ts.map +1 -0
- package/lib/server/forge/auth/testHarness.js +53 -0
- package/lib/server/forge/auth/testHarness.js.map +1 -0
- package/lib/server/forge/auth/tokenHash.d.ts +3 -0
- package/lib/server/forge/auth/tokenHash.d.ts.map +1 -0
- package/lib/server/forge/auth/tokenHash.js +4 -0
- package/lib/server/forge/auth/tokenHash.js.map +1 -0
- package/lib/server/forge/auth/users.d.ts +51 -0
- package/lib/server/forge/auth/users.d.ts.map +1 -0
- package/lib/server/forge/auth/users.js +118 -0
- package/lib/server/forge/auth/users.js.map +1 -0
- package/lib/server/forge/core/ForgeAgent.d.ts +43 -1
- package/lib/server/forge/core/ForgeAgent.d.ts.map +1 -1
- package/lib/server/forge/core/ForgeAgent.js +209 -61
- package/lib/server/forge/core/ForgeAgent.js.map +1 -1
- package/lib/server/forge/core/agentClient.d.ts +7 -23
- package/lib/server/forge/core/agentClient.d.ts.map +1 -1
- package/lib/server/forge/core/agentClient.js +10 -25
- package/lib/server/forge/core/agentClient.js.map +1 -1
- package/lib/server/forge/core/claudeClient.d.ts +24 -1
- package/lib/server/forge/core/claudeClient.d.ts.map +1 -1
- package/lib/server/forge/core/claudeClient.js +25 -7
- package/lib/server/forge/core/claudeClient.js.map +1 -1
- package/lib/server/forge/core/configStore.d.ts +11 -1
- package/lib/server/forge/core/configStore.d.ts.map +1 -1
- package/lib/server/forge/core/configStore.js +33 -2
- package/lib/server/forge/core/configStore.js.map +1 -1
- package/lib/server/forge/core/dependencyPaths.d.ts +19 -0
- package/lib/server/forge/core/dependencyPaths.d.ts.map +1 -0
- package/lib/server/forge/core/dependencyPaths.js +32 -0
- package/lib/server/forge/core/dependencyPaths.js.map +1 -0
- package/lib/server/forge/core/evidence.d.ts +43 -0
- package/lib/server/forge/core/evidence.d.ts.map +1 -0
- package/lib/server/forge/core/evidence.js +108 -0
- package/lib/server/forge/core/evidence.js.map +1 -0
- package/lib/server/forge/core/jobs.d.ts +2 -0
- package/lib/server/forge/core/jobs.d.ts.map +1 -1
- package/lib/server/forge/core/jobs.js +8 -0
- package/lib/server/forge/core/jobs.js.map +1 -1
- package/lib/server/forge/core/localRepo.d.ts +31 -10
- package/lib/server/forge/core/localRepo.d.ts.map +1 -1
- package/lib/server/forge/core/localRepo.js +48 -82
- package/lib/server/forge/core/localRepo.js.map +1 -1
- package/lib/server/forge/core/prompts.d.ts +3 -1
- package/lib/server/forge/core/prompts.d.ts.map +1 -1
- package/lib/server/forge/core/prompts.js +14 -5
- package/lib/server/forge/core/prompts.js.map +1 -1
- package/lib/server/forge/core/providers/azuredevops.d.ts +4 -2
- package/lib/server/forge/core/providers/azuredevops.d.ts.map +1 -1
- package/lib/server/forge/core/providers/azuredevops.js +12 -2
- package/lib/server/forge/core/providers/azuredevops.js.map +1 -1
- package/lib/server/forge/core/providers/base.d.ts +29 -4
- package/lib/server/forge/core/providers/base.d.ts.map +1 -1
- package/lib/server/forge/core/providers/base.js +21 -3
- package/lib/server/forge/core/providers/base.js.map +1 -1
- package/lib/server/forge/core/providers/github.d.ts +7 -7
- package/lib/server/forge/core/providers/github.d.ts.map +1 -1
- package/lib/server/forge/core/providers/github.js +13 -4
- package/lib/server/forge/core/providers/github.js.map +1 -1
- package/lib/server/forge/core/providers/gitlab.d.ts +20 -3
- package/lib/server/forge/core/providers/gitlab.d.ts.map +1 -1
- package/lib/server/forge/core/providers/gitlab.js +65 -5
- package/lib/server/forge/core/providers/gitlab.js.map +1 -1
- package/lib/server/forge/core/providers/types.d.ts +20 -0
- package/lib/server/forge/core/providers/types.d.ts.map +1 -1
- package/lib/server/forge/core/secretBox.d.ts +17 -0
- package/lib/server/forge/core/secretBox.d.ts.map +1 -0
- package/lib/server/forge/core/secretBox.js +74 -0
- package/lib/server/forge/core/secretBox.js.map +1 -0
- package/lib/server/forge/core/types.d.ts +7 -1
- package/lib/server/forge/core/types.d.ts.map +1 -1
- package/lib/server/forge/core/validator/clone.d.ts +5 -4
- package/lib/server/forge/core/validator/clone.d.ts.map +1 -1
- package/lib/server/forge/core/validator/clone.js +6 -86
- package/lib/server/forge/core/validator/clone.js.map +1 -1
- package/lib/server/forge/core/validator/cmd.d.ts.map +1 -1
- package/lib/server/forge/core/validator/cmd.js +4 -1
- package/lib/server/forge/core/validator/cmd.js.map +1 -1
- package/lib/server/forge/core/validator/projectType.d.ts.map +1 -1
- package/lib/server/forge/core/validator/projectType.js +2 -1
- package/lib/server/forge/core/validator/projectType.js.map +1 -1
- package/lib/server/forge/core/validator/runners/node.d.ts.map +1 -1
- package/lib/server/forge/core/validator/runners/node.js +6 -2
- package/lib/server/forge/core/validator/runners/node.js.map +1 -1
- package/lib/server/forge/core/validator.d.ts.map +1 -1
- package/lib/server/forge/core/validator.js +28 -22
- package/lib/server/forge/core/validator.js.map +1 -1
- package/lib/server/forge/core/workspaces.d.ts +70 -0
- package/lib/server/forge/core/workspaces.d.ts.map +1 -0
- package/lib/server/forge/core/workspaces.js +348 -0
- package/lib/server/forge/core/workspaces.js.map +1 -0
- package/lib/server/forge/db/database.d.ts +22 -0
- package/lib/server/forge/db/database.d.ts.map +1 -0
- package/lib/server/forge/db/database.js +71 -0
- package/lib/server/forge/db/database.js.map +1 -0
- package/lib/server/forge/db/migrations.d.ts +11 -0
- package/lib/server/forge/db/migrations.d.ts.map +1 -0
- package/lib/server/forge/db/migrations.js +87 -0
- package/lib/server/forge/db/migrations.js.map +1 -0
- package/lib/server/forge/routes.d.ts.map +1 -1
- package/lib/server/forge/routes.js +413 -163
- package/lib/server/forge/routes.js.map +1 -1
- package/lib/server/forge/sse.d.ts +10 -0
- package/lib/server/forge/sse.d.ts.map +1 -0
- package/lib/server/forge/sse.js +22 -0
- package/lib/server/forge/sse.js.map +1 -0
- package/lib/server/spa.d.ts +12 -0
- package/lib/server/spa.d.ts.map +1 -0
- package/lib/server/spa.js +23 -0
- package/lib/server/spa.js.map +1 -0
- package/lib/server.js +9 -24
- package/lib/server.js.map +1 -1
- package/lib/shared/events.d.ts +3 -0
- package/lib/shared/events.d.ts.map +1 -1
- package/lib/shared/events.js +3 -0
- package/lib/shared/events.js.map +1 -1
- package/lib/shared/packageRoot.d.ts +11 -0
- package/lib/shared/packageRoot.d.ts.map +1 -0
- package/lib/shared/packageRoot.js +23 -0
- package/lib/shared/packageRoot.js.map +1 -0
- package/lib/shared/project.d.ts +3 -0
- package/lib/shared/project.d.ts.map +1 -0
- package/lib/shared/project.js +3 -0
- package/lib/shared/project.js.map +1 -0
- package/package.json +23 -10
- package/lib/bin/cli/improve.d.ts +0 -2
- package/lib/bin/cli/improve.d.ts.map +0 -1
- package/lib/bin/cli/improve.js +0 -189
- package/lib/bin/cli/improve.js.map +0 -1
- package/lib/bin/cli/stats.d.ts +0 -2
- package/lib/bin/cli/stats.d.ts.map +0 -1
- package/lib/bin/cli/stats.js +0 -78
- package/lib/bin/cli/stats.js.map +0 -1
- package/lib/server/forge/core/k8s.d.ts +0 -18
- package/lib/server/forge/core/k8s.d.ts.map +0 -1
- package/lib/server/forge/core/k8s.js +0 -49
- package/lib/server/forge/core/k8s.js.map +0 -1
- package/lib/server/forge/core/openclawClient.d.ts +0 -61
- package/lib/server/forge/core/openclawClient.d.ts.map +0 -1
- package/lib/server/forge/core/openclawClient.js +0 -111
- package/lib/server/forge/core/openclawClient.js.map +0 -1
- package/lib/server/forge/core/quotaClient.d.ts +0 -48
- package/lib/server/forge/core/quotaClient.d.ts.map +0 -1
- package/lib/server/forge/core/quotaClient.js +0 -88
- package/lib/server/forge/core/quotaClient.js.map +0 -1
- package/lib/server/forge/core/selfImprove.d.ts +0 -43
- package/lib/server/forge/core/selfImprove.d.ts.map +0 -1
- package/lib/server/forge/core/selfImprove.js +0 -372
- package/lib/server/forge/core/selfImprove.js.map +0 -1
- package/lib/server/forge/core/telemetry.d.ts +0 -100
- package/lib/server/forge/core/telemetry.d.ts.map +0 -1
- package/lib/server/forge/core/telemetry.js +0 -273
- package/lib/server/forge/core/telemetry.js.map +0 -1
- package/scripts/fix-shebang.cjs +0 -11
- package/scripts/inject-readme.cjs +0 -23
- package/scripts/local-rollout.sh +0 -134
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ForgeAgent.d.ts","sourceRoot":"","sources":["../../../../server/forge/core/ForgeAgent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;
|
|
1
|
+
{"version":3,"file":"ForgeAgent.d.ts","sourceRoot":"","sources":["../../../../server/forge/core/ForgeAgent.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,14 +20,20 @@
|
|
|
20
20
|
* - `applyFix` groups by repo and creates one branch + MR per repo.
|
|
21
21
|
*/
|
|
22
22
|
import { randomUUID } from "node:crypto";
|
|
23
|
+
import { FORGE_PROJECT_URL } from "../../../shared/project.js";
|
|
23
24
|
import { checkResolution, identifyRelevantFiles, proposeFix, proposeFixAgentic, refineOrAsk } from "./agentClient.js";
|
|
24
25
|
import { AGENT_MODE, resolveAgentMode } from "./agentMode.js";
|
|
25
26
|
import { branchNameFor } from "./branchName.js";
|
|
27
|
+
import { AgentTimeoutError } from "./claudeClient.js";
|
|
26
28
|
import * as configStore from "./configStore.js";
|
|
27
|
-
import {
|
|
29
|
+
import { collectEvidence, prepareEvidenceDir, renderEvidence } from "./evidence.js";
|
|
30
|
+
import { acquireWorkingTree, captureChanges, overlayChanges } from "./localRepo.js";
|
|
28
31
|
import { classifyIssue } from "./prompts.js";
|
|
29
32
|
import { createProvider } from "./providers/index.js";
|
|
30
33
|
import { reattributeChanges } from "./validator/attribute.js";
|
|
34
|
+
// An agent editing a real checkout for a multi-part ticket regularly needs
|
|
35
|
+
// more than the CLI's 10-minute default.
|
|
36
|
+
const AGENTIC_TIMEOUT_MS = 30 * 60_000;
|
|
31
37
|
/**
|
|
32
38
|
* Whether Refine should give the model real Read/Glob/Grep access to a local
|
|
33
39
|
* checkout of the primary repo. Primary control is the Settings UI flag
|
|
@@ -117,6 +123,14 @@ function parseAgenticSummary(text) {
|
|
|
117
123
|
const explanation = text.replace(match[0], "").trim();
|
|
118
124
|
return { title: title || undefined, explanation };
|
|
119
125
|
}
|
|
126
|
+
/** Whether two change sets touch the same files with the same content. */
|
|
127
|
+
function sameChanges(a, b) {
|
|
128
|
+
if (a.length !== b.length)
|
|
129
|
+
return false;
|
|
130
|
+
const key = (c) => `${c.file}\0${c.action}\0${c.action === "delete" ? "" : c.proposed ?? ""}`;
|
|
131
|
+
const seen = new Set(a.map(key));
|
|
132
|
+
return b.every((c) => seen.has(key(c)));
|
|
133
|
+
}
|
|
120
134
|
/**
|
|
121
135
|
* Builds a conventional-commit subject line from the analysis. Prefers
|
|
122
136
|
* `analysis.mrTitle` (the model's own commit-style summary), falling back to
|
|
@@ -232,7 +246,7 @@ export class ForgeAgent {
|
|
|
232
246
|
return p;
|
|
233
247
|
}
|
|
234
248
|
get _agentLabel() {
|
|
235
|
-
return
|
|
249
|
+
return "Claude";
|
|
236
250
|
}
|
|
237
251
|
get _isMultiRepo() {
|
|
238
252
|
return this.allRepos.length > 1;
|
|
@@ -358,8 +372,6 @@ export class ForgeAgent {
|
|
|
358
372
|
* structured analysis happened instead.
|
|
359
373
|
*/
|
|
360
374
|
_agenticUnavailableReason() {
|
|
361
|
-
if (this.agent === "openclaw")
|
|
362
|
-
return "the openclaw backend has no agentic mode";
|
|
363
375
|
if (this._isMultiRepo)
|
|
364
376
|
return "multi-repo changes aren't supported in agentic mode yet";
|
|
365
377
|
if (!supportsLocalClone(this.primaryProject))
|
|
@@ -379,29 +391,76 @@ export class ForgeAgent {
|
|
|
379
391
|
const issue = await this.provider.getIssue(issueIid);
|
|
380
392
|
const branchName = branchNameFor(issueIid, { issue });
|
|
381
393
|
emit({ type: "progress", step: "scan_repo", message: `Preparing a checkout of ${repo}...` });
|
|
382
|
-
const
|
|
394
|
+
const lease = await acquireWorkingTree(repo, branchName, (m) => emit({ type: "log", message: m }));
|
|
395
|
+
try {
|
|
396
|
+
return await this._runAgentic(lease.dir, issue, repo, emit, model, ciContext, userPrompt, { signal });
|
|
397
|
+
}
|
|
398
|
+
finally {
|
|
399
|
+
lease.release();
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
async _runAgentic(dir, issue, repo, emit, model, ciContext, userPrompt, { signal }) {
|
|
403
|
+
const { result, usage } = await this._executeAgentic(dir, issue, repo, emit, model, { signal, ciContext, userPrompt });
|
|
404
|
+
emit({ type: "result", data: result });
|
|
405
|
+
if (usage)
|
|
406
|
+
emit(usage);
|
|
407
|
+
return result;
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Runs the agent in `dir` and reads back what it did: the captured changes,
|
|
411
|
+
* its summary and any evidence. Callers decide what to emit.
|
|
412
|
+
*/
|
|
413
|
+
async _executeAgentic(dir, issue, repo, emit, model, { signal, ciContext, userPrompt, feedback, baseline = [] }) {
|
|
414
|
+
await prepareEvidenceDir(dir);
|
|
383
415
|
emit({ type: "progress", step: "generate_fix", message: `Running ${this._agentLabel} as an agent in ${repo}...` });
|
|
384
416
|
const defaults = configStore.get().defaults;
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
417
|
+
let agentic = null;
|
|
418
|
+
let timedOut = null;
|
|
419
|
+
try {
|
|
420
|
+
agentic = await proposeFixAgentic({
|
|
421
|
+
issue,
|
|
422
|
+
cwd: dir,
|
|
423
|
+
model,
|
|
424
|
+
promptRules: defaults?.promptRules || "",
|
|
425
|
+
userPrompt,
|
|
426
|
+
ciContext,
|
|
427
|
+
feedback,
|
|
428
|
+
onEvent: emit,
|
|
429
|
+
signal,
|
|
430
|
+
timeout: defaults?.cliTimeout ?? AGENTIC_TIMEOUT_MS,
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
catch (err) {
|
|
434
|
+
// Out of time isn't nothing done: the edits are in the checkout. Keep
|
|
435
|
+
// them as a partial result (below) instead of losing the run.
|
|
436
|
+
if (!(err instanceof AgentTimeoutError))
|
|
437
|
+
throw err;
|
|
438
|
+
timedOut = err;
|
|
439
|
+
}
|
|
396
440
|
emit({ type: "progress", step: "fetch_files", message: "Capturing changes from the working tree..." });
|
|
397
|
-
const changes = await captureChanges({
|
|
441
|
+
const changes = await captureChanges({
|
|
442
|
+
dir,
|
|
443
|
+
repo,
|
|
444
|
+
onSkip: (file, reason) => emit({ type: "log", message: `Left out ${file} (${reason}): Forge never commits symlinks or dependency folders.` }),
|
|
445
|
+
});
|
|
446
|
+
const edited = !sameChanges(changes, baseline);
|
|
447
|
+
if (timedOut && !edited)
|
|
448
|
+
throw timedOut;
|
|
398
449
|
emit({
|
|
399
450
|
type: "log",
|
|
400
|
-
message:
|
|
401
|
-
?
|
|
402
|
-
|
|
451
|
+
message: !edited
|
|
452
|
+
? baseline.length
|
|
453
|
+
? "The agent left the proposed changes as they were."
|
|
454
|
+
: "No file changes were captured — the agent reported done without editing the tree."
|
|
455
|
+
: `Captured ${changes.length} change(s): ${changes.map((c) => `${c.file} (${c.action})`).join(", ")}`,
|
|
403
456
|
});
|
|
404
|
-
const
|
|
457
|
+
const evidence = await this._attachEvidence(dir, emit);
|
|
458
|
+
const { title, explanation } = agentic
|
|
459
|
+
? parseAgenticSummary(agentic.text)
|
|
460
|
+
: {
|
|
461
|
+
title: undefined,
|
|
462
|
+
explanation: `The agent ran out of time after ${timedOut.minutes} minutes, before it finished. These are the changes it had made so far: review them, then refine to finish the rest.`,
|
|
463
|
+
};
|
|
405
464
|
const result = {
|
|
406
465
|
issue,
|
|
407
466
|
mrTitle: title,
|
|
@@ -410,18 +469,85 @@ export class ForgeAgent {
|
|
|
410
469
|
changes,
|
|
411
470
|
removals: [],
|
|
412
471
|
repos: [repo],
|
|
472
|
+
...(evidence ? { evidence } : {}),
|
|
413
473
|
};
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
474
|
+
const usage = agentic
|
|
475
|
+
? {
|
|
476
|
+
type: "usage",
|
|
477
|
+
cost: agentic.cost,
|
|
478
|
+
serviceTier: agentic.serviceTier,
|
|
479
|
+
inputTokens: agentic.inputTokens,
|
|
480
|
+
outputTokens: agentic.outputTokens,
|
|
481
|
+
cacheCreationTokens: agentic.cacheCreationTokens,
|
|
482
|
+
cacheReadTokens: agentic.cacheReadTokens,
|
|
483
|
+
}
|
|
484
|
+
: null;
|
|
485
|
+
return { result, usage, edited };
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Agentic refine: overlays the current proposal on the issue's worktree and
|
|
489
|
+
* runs the reviewer's follow-up as a full agent, so asks like "check it in
|
|
490
|
+
* Playwright" can run things instead of hitting the read-only refine's
|
|
491
|
+
* Read/Glob/Grep wall. A run that leaves the tree untouched and gathers no
|
|
492
|
+
* evidence comes back as an answer, so a question doesn't replace the
|
|
493
|
+
* proposal (and its validation) with an identical one.
|
|
494
|
+
*/
|
|
495
|
+
async _refineAgentic(issue, previousChanges, feedback, emit, model, { signal }) {
|
|
496
|
+
const repo = this.primaryProject;
|
|
497
|
+
const log = (message) => emit({ type: "log", message });
|
|
498
|
+
emit({ type: "progress", step: "prepare_repo", message: `Preparing a checkout of ${repo}...` });
|
|
499
|
+
const lease = await acquireWorkingTree(repo, branchNameFor(issue.iid, { issue }), log);
|
|
500
|
+
try {
|
|
501
|
+
const baseline = (previousChanges ?? []).filter((c) => (c.repo ?? repo) === repo);
|
|
502
|
+
if (baseline.length)
|
|
503
|
+
await overlayChanges(lease.dir, baseline, log);
|
|
504
|
+
const { result, usage, edited } = await this._executeAgentic(lease.dir, issue, repo, emit, model, { signal, feedback, baseline });
|
|
505
|
+
if (!edited && !result.evidence) {
|
|
506
|
+
const text = result.explanation || "(no answer produced)";
|
|
507
|
+
log("Refine made no code changes — responding without changing the proposal.");
|
|
508
|
+
emit({ type: "answer", text });
|
|
509
|
+
if (usage)
|
|
510
|
+
emit(usage);
|
|
511
|
+
return { kind: "answer", answer: text };
|
|
512
|
+
}
|
|
513
|
+
emit({ type: "result", data: result });
|
|
514
|
+
if (usage)
|
|
515
|
+
emit(usage);
|
|
516
|
+
return result;
|
|
517
|
+
}
|
|
518
|
+
finally {
|
|
519
|
+
lease.release();
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Uploads whatever the agent left in the evidence folder and returns the
|
|
524
|
+
* markdown for the MR. A failed upload is logged, never fatal — the change
|
|
525
|
+
* itself is what matters.
|
|
526
|
+
*/
|
|
527
|
+
async _attachEvidence(dir, emit) {
|
|
528
|
+
const { notes, images, skipped } = await collectEvidence(dir);
|
|
529
|
+
for (const name of skipped) {
|
|
530
|
+
emit({ type: "log", message: `Evidence: skipped ${name} (over the size or count limit).` });
|
|
531
|
+
}
|
|
532
|
+
const uploads = [];
|
|
533
|
+
for (const image of images) {
|
|
534
|
+
try {
|
|
535
|
+
const uploaded = await this.provider.uploadFile(image);
|
|
536
|
+
if (!uploaded) {
|
|
537
|
+
emit({ type: "log", message: `Evidence: ${this.primaryProject} doesn't support uploads; screenshots stay out of the MR.` });
|
|
538
|
+
break;
|
|
539
|
+
}
|
|
540
|
+
uploads.push({ name: image.name, url: uploaded.url });
|
|
541
|
+
}
|
|
542
|
+
catch (err) {
|
|
543
|
+
emit({ type: "log", message: `Evidence: couldn't upload ${image.name}: ${err.message}` });
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
if (notes || uploads.length) {
|
|
547
|
+
const shots = uploads.length === 1 ? "1 screenshot" : `${uploads.length} screenshots`;
|
|
548
|
+
emit({ type: "log", message: `Evidence: attached ${notes ? "the write-up and " : ""}${shots} to the MR description.` });
|
|
549
|
+
}
|
|
550
|
+
return renderEvidence({ notes, uploads });
|
|
425
551
|
}
|
|
426
552
|
// ─── Analyze ───────────────────────────────────────────────────────────────
|
|
427
553
|
/**
|
|
@@ -472,7 +598,7 @@ export class ForgeAgent {
|
|
|
472
598
|
}
|
|
473
599
|
// Step 3 — identify relevant files (Claude pass 1)
|
|
474
600
|
emit({ type: "progress", step: "identify_files", message: msgs.identify_files });
|
|
475
|
-
const ident = await identifyRelevantFiles(issue, repoTrees, model,
|
|
601
|
+
const ident = await identifyRelevantFiles(issue, repoTrees, model, { signal });
|
|
476
602
|
const { files: rawFiles, reasoning = "", cost: cost1 = 0, serviceTier, inputTokens: it1 = 0, outputTokens: ot1 = 0, cacheCreationTokens: cc1 = 0, cacheReadTokens: cr1 = 0, } = ident;
|
|
477
603
|
const issueKind = classifyIssue(issue);
|
|
478
604
|
emit({ type: "log", message: `Issue classified as: ${issueKind}` });
|
|
@@ -499,7 +625,7 @@ export class ForgeAgent {
|
|
|
499
625
|
// Step 5 — propose fix (pass 2)
|
|
500
626
|
emit({ type: "progress", step: "generate_fix", message: msgs.generate_fix });
|
|
501
627
|
const promptRules = configStore.get().defaults?.promptRules || "";
|
|
502
|
-
const propose = await proposeFix(issue, fileContents, { ciContext, userPrompt, previousChanges, repos: this.allRepos, promptRules }, model,
|
|
628
|
+
const propose = await proposeFix(issue, fileContents, { ciContext, userPrompt, previousChanges, repos: this.allRepos, promptRules }, model, { signal });
|
|
503
629
|
const { title: mrTitle, explanation, changes, removals = [], cost: cost2 = 0, inputTokens: it2 = 0, outputTokens: ot2 = 0, cacheCreationTokens: cc2 = 0, cacheReadTokens: cr2 = 0, rateLimit: rl2 = null, } = propose;
|
|
504
630
|
const enrichedChanges = this._normalizeChanges(changes ?? [], fileContents);
|
|
505
631
|
emit({
|
|
@@ -548,11 +674,22 @@ export class ForgeAgent {
|
|
|
548
674
|
// a multi-turn session. CI-fix refines route through proposeFix (stateless)
|
|
549
675
|
// and OpenClaw has no session API. Generate a fresh UUID for turn 1 so we
|
|
550
676
|
// own the id from the start and can --resume it on turn 2+.
|
|
551
|
-
const useSession =
|
|
677
|
+
const useSession = !ciContext;
|
|
552
678
|
const resumeSession = Boolean(useSession && claudeSessionId);
|
|
553
679
|
const sessionId = useSession ? (claudeSessionId || randomUUID()) : null;
|
|
554
680
|
emit({ type: "progress", step: "fetch_issue", message: `Fetching issue #${issueIid}...` });
|
|
555
681
|
const issue = await this.provider.getIssue(issueIid);
|
|
682
|
+
// Agentic mode: reviewer follow-ups get the same full agent as the
|
|
683
|
+
// analysis. CI-fix refines stay on the targeted proposeFix path below.
|
|
684
|
+
if (!ciContext && resolveAgentMode({ requested: opts.agentMode, configured: configStore.get().defaults?.agentMode }) === AGENT_MODE.agentic) {
|
|
685
|
+
const reason = this._agenticUnavailableReason();
|
|
686
|
+
if (reason) {
|
|
687
|
+
emit({ type: "log", message: `Agentic refine unavailable (${reason}); refining with read-only repo access.` });
|
|
688
|
+
}
|
|
689
|
+
else {
|
|
690
|
+
return this._refineAgentic(issue, previousChanges, feedback, emit, model, { signal });
|
|
691
|
+
}
|
|
692
|
+
}
|
|
556
693
|
// Pull the unique (repo, path) pairs from the previous changes.
|
|
557
694
|
const uniq = new Map();
|
|
558
695
|
for (const c of previousChanges ?? []) {
|
|
@@ -575,7 +712,7 @@ export class ForgeAgent {
|
|
|
575
712
|
if (ciContext) {
|
|
576
713
|
emit({ type: "progress", step: "generate_fix", message: `Fixing CI failure with ${this._agentLabel}...` });
|
|
577
714
|
const ciRefineRules = configStore.get().defaults?.promptRules || "";
|
|
578
|
-
const propose = await proposeFix(issue, fileContents, { feedback, previousChanges, ciContext, repos: this.allRepos, promptRules: ciRefineRules }, model,
|
|
715
|
+
const propose = await proposeFix(issue, fileContents, { feedback, previousChanges, ciContext, repos: this.allRepos, promptRules: ciRefineRules }, model, { signal });
|
|
579
716
|
return this._emitRefineResult(propose, fileContents, issue, emit, "ci-fix");
|
|
580
717
|
}
|
|
581
718
|
// Give the refine model access to the full primary repo: prepare a local
|
|
@@ -584,15 +721,16 @@ export class ForgeAgent {
|
|
|
584
721
|
// when using a non-Claude agent, or when the primary repo isn't GitLab
|
|
585
722
|
// (validator/localRepo are GitLab-only for now).
|
|
586
723
|
let repoCwd = null;
|
|
724
|
+
let repoLease = null;
|
|
587
725
|
let repoTrees = null;
|
|
588
726
|
const canUseLocalClone = refineRepoAccessEnabled()
|
|
589
|
-
&& this.agent !== "openclaw"
|
|
590
727
|
&& supportsLocalClone(this.primaryProject);
|
|
591
728
|
if (canUseLocalClone) {
|
|
592
729
|
try {
|
|
593
730
|
emit({ type: "progress", step: "prepare_repo", message: `Preparing local checkout of ${this.primaryProject}...` });
|
|
594
731
|
const branchName = branchNameFor(issue.iid, { issue });
|
|
595
|
-
|
|
732
|
+
repoLease = await acquireWorkingTree(this.primaryProject, branchName, (msg) => emit({ type: "log", message: msg }));
|
|
733
|
+
const dir = repoLease.dir;
|
|
596
734
|
const primaryChanges = (previousChanges ?? []).filter((c) => (c.repo ?? this.primaryProject) === this.primaryProject);
|
|
597
735
|
if (primaryChanges.length) {
|
|
598
736
|
await overlayChanges(dir, primaryChanges, (msg) => emit({ type: "log", message: msg }));
|
|
@@ -603,6 +741,8 @@ export class ForgeAgent {
|
|
|
603
741
|
catch (err) {
|
|
604
742
|
const message = err instanceof Error ? err.message : String(err);
|
|
605
743
|
emit({ type: "log", message: `Could not prepare local checkout (${message}); falling back to file-tree mode.` });
|
|
744
|
+
repoLease?.release();
|
|
745
|
+
repoLease = null;
|
|
606
746
|
repoCwd = null;
|
|
607
747
|
}
|
|
608
748
|
}
|
|
@@ -629,29 +769,35 @@ export class ForgeAgent {
|
|
|
629
769
|
repoAccessMode: repoCwd ? "tools" : "tree",
|
|
630
770
|
promptRules: refinePromptRules,
|
|
631
771
|
...(sid ? { sessionId: sid, resumeSession: resume } : {}),
|
|
632
|
-
}, model,
|
|
772
|
+
}, model, (evt) => emit(evt), { signal });
|
|
633
773
|
let activeSessionId = sessionId;
|
|
634
774
|
let response;
|
|
635
775
|
try {
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
catch (err) {
|
|
639
|
-
// Resume failures (session pruned by the CLI, format drift after an
|
|
640
|
-
// upgrade, crashed half-turn leaving the session unreadable) should
|
|
641
|
-
// not kill the user's refine. Regenerate the session, tell the
|
|
642
|
-
// frontend to adopt the new id, and retry once with the full prompt.
|
|
643
|
-
if (resumeSession && isLikelyResumeFailure(err)) {
|
|
644
|
-
const fresh = randomUUID();
|
|
645
|
-
const errMsg = err instanceof Error ? err.message : String(err);
|
|
646
|
-
emit({ type: "log", message: `Could not resume Claude session ${activeSessionId} (${errMsg}). Starting fresh session ${fresh}.` });
|
|
647
|
-
activeSessionId = fresh;
|
|
648
|
-
emit({ type: "session", sessionId: fresh, resumed: false });
|
|
649
|
-
response = await callRefine(fresh, false);
|
|
776
|
+
try {
|
|
777
|
+
response = await callRefine(activeSessionId, resumeSession);
|
|
650
778
|
}
|
|
651
|
-
|
|
652
|
-
|
|
779
|
+
catch (err) {
|
|
780
|
+
// Resume failures (session pruned by the CLI, format drift after an
|
|
781
|
+
// upgrade, crashed half-turn leaving the session unreadable) should
|
|
782
|
+
// not kill the user's refine. Regenerate the session, tell the
|
|
783
|
+
// frontend to adopt the new id, and retry once with the full prompt.
|
|
784
|
+
if (resumeSession && isLikelyResumeFailure(err)) {
|
|
785
|
+
const fresh = randomUUID();
|
|
786
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
787
|
+
emit({ type: "log", message: `Could not resume Claude session ${activeSessionId} (${errMsg}). Starting fresh session ${fresh}.` });
|
|
788
|
+
activeSessionId = fresh;
|
|
789
|
+
emit({ type: "session", sessionId: fresh, resumed: false });
|
|
790
|
+
response = await callRefine(fresh, false);
|
|
791
|
+
}
|
|
792
|
+
else {
|
|
793
|
+
throw err;
|
|
794
|
+
}
|
|
653
795
|
}
|
|
654
796
|
}
|
|
797
|
+
finally {
|
|
798
|
+
// The session only reads the checkout while it runs.
|
|
799
|
+
repoLease?.release();
|
|
800
|
+
}
|
|
655
801
|
// CLI sometimes forks on resume and returns a different session id than
|
|
656
802
|
// the one we passed. Re-emit so the frontend persists the authoritative
|
|
657
803
|
// id — otherwise next refine would --resume a stale handle.
|
|
@@ -729,7 +875,7 @@ export class ForgeAgent {
|
|
|
729
875
|
const repoTrees = await this._fetchAllTrees(emit);
|
|
730
876
|
emit({ type: "progress", step: "identify_files", message: "Identifying files from CI failure..." });
|
|
731
877
|
const ciIssue = { ...issue, description: `CI pipeline failure:\n\n${ciContext}` };
|
|
732
|
-
const ident = await identifyRelevantFiles(ciIssue, repoTrees, model,
|
|
878
|
+
const ident = await identifyRelevantFiles(ciIssue, repoTrees, model, { signal });
|
|
733
879
|
const { files: rawFiles, cost: cost1 = 0, serviceTier, inputTokens: it1 = 0, outputTokens: ot1 = 0, cacheCreationTokens: cc1 = 0, cacheReadTokens: cr1 = 0, } = ident;
|
|
734
880
|
const { valid } = this._validateSelections(this._normalizeFileSelections(rawFiles), repoTrees);
|
|
735
881
|
const capped = this._capSelections(valid, "fix");
|
|
@@ -741,7 +887,7 @@ export class ForgeAgent {
|
|
|
741
887
|
const fileContents = await this._fetchFiles(capped, emit);
|
|
742
888
|
emit({ type: "progress", step: "generate_fix", message: `Fixing CI failure with ${this._agentLabel}...` });
|
|
743
889
|
const ciPromptRules = configStore.get().defaults?.promptRules || "";
|
|
744
|
-
const propose = await proposeFix(issue, fileContents, { ciContext, repos: this.allRepos, promptRules: ciPromptRules }, model,
|
|
890
|
+
const propose = await proposeFix(issue, fileContents, { ciContext, repos: this.allRepos, promptRules: ciPromptRules }, model, { signal });
|
|
745
891
|
const { title: mrTitle, explanation, changes, cost: cost2 = 0, inputTokens: it2 = 0, outputTokens: ot2 = 0, cacheCreationTokens: cc2 = 0, cacheReadTokens: cr2 = 0, rateLimit: rl2 = null, } = propose;
|
|
746
892
|
const enrichedChanges = this._normalizeChanges(changes ?? [], fileContents);
|
|
747
893
|
emit({
|
|
@@ -781,7 +927,7 @@ export class ForgeAgent {
|
|
|
781
927
|
this.provider.getIssue(issueIid),
|
|
782
928
|
provider.getMRDiffs(mrIid),
|
|
783
929
|
]);
|
|
784
|
-
return checkResolution(issue, diffs, undefined,
|
|
930
|
+
return checkResolution(issue, diffs, undefined, {});
|
|
785
931
|
}
|
|
786
932
|
// ─── Apply ─────────────────────────────────────────────────────────────────
|
|
787
933
|
/**
|
|
@@ -1026,6 +1172,8 @@ _Opened by Forge._`;
|
|
|
1026
1172
|
isPrimary,
|
|
1027
1173
|
repo,
|
|
1028
1174
|
priorApplications,
|
|
1175
|
+
// Evidence comes from the primary repo's checkout.
|
|
1176
|
+
evidence: isPrimary ? analysis.evidence : undefined,
|
|
1029
1177
|
});
|
|
1030
1178
|
const mr = await this._ensureMR(provider, {
|
|
1031
1179
|
sourceBranch: branchName,
|
|
@@ -1086,7 +1234,7 @@ _Opened by Forge._`;
|
|
|
1086
1234
|
return repo.split("/").pop() || repo;
|
|
1087
1235
|
}
|
|
1088
1236
|
_buildMRDescription(issue, explanation, changes, opts = {}) {
|
|
1089
|
-
const { isPrimary = true, repo = this.primaryProject, priorApplications = [] } = opts;
|
|
1237
|
+
const { isPrimary = true, repo = this.primaryProject, priorApplications = [], evidence } = opts;
|
|
1090
1238
|
const changeList = changes
|
|
1091
1239
|
.map((c) => `- **${c.file}** (${c.action}): ${c.summary}`)
|
|
1092
1240
|
.join("\n");
|
|
@@ -1120,12 +1268,12 @@ ${changeList}
|
|
|
1120
1268
|
|
|
1121
1269
|
## 🧪 Testing
|
|
1122
1270
|
|
|
1123
|
-
- ⏳ Automated CI pipeline
|
|
1271
|
+
${evidence?.trim() ? `${evidence.trim()}\n\n` : ""}- ⏳ Automated CI pipeline
|
|
1124
1272
|
- ⏳ Manual review of diff before merge
|
|
1125
1273
|
|
|
1126
1274
|
---
|
|
1127
1275
|
|
|
1128
|
-
_Generated by [Forge](
|
|
1276
|
+
_Generated by [Forge](${FORGE_PROJECT_URL})_`;
|
|
1129
1277
|
}
|
|
1130
1278
|
}
|
|
1131
1279
|
//# sourceMappingURL=ForgeAgent.js.map
|