pullfrog 0.1.10 → 0.1.12
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/dist/agents/shared.d.ts +2 -0
- package/dist/cli.mjs +558 -252
- package/dist/external.d.ts +1 -1
- package/dist/index.js +557 -251
- package/dist/internal/index.d.ts +1 -1
- package/dist/internal.js +57 -2
- package/dist/mcp/checkout.d.ts +1 -1
- package/dist/models.d.ts +21 -8
- package/dist/toolState.d.ts +7 -0
- package/dist/utils/byokFallback.d.ts +2 -3
- package/dist/utils/codexHome.d.ts +0 -8
- package/dist/utils/runLifecycle.d.ts +7 -4
- package/dist/utils/setup.d.ts +44 -0
- package/dist/utils/vertex.d.ts +16 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -97475,14 +97475,14 @@ var require_turndown_cjs = __commonJS({
|
|
|
97475
97475
|
} else if (node2.nodeType === 1) {
|
|
97476
97476
|
replacement = replacementForNode.call(self2, node2);
|
|
97477
97477
|
}
|
|
97478
|
-
return
|
|
97478
|
+
return join20(output, replacement);
|
|
97479
97479
|
}, "");
|
|
97480
97480
|
}
|
|
97481
97481
|
function postProcess(output) {
|
|
97482
97482
|
var self2 = this;
|
|
97483
97483
|
this.rules.forEach(function(rule) {
|
|
97484
97484
|
if (typeof rule.append === "function") {
|
|
97485
|
-
output =
|
|
97485
|
+
output = join20(output, rule.append(self2.options));
|
|
97486
97486
|
}
|
|
97487
97487
|
});
|
|
97488
97488
|
return output.replace(/^[\t\r\n]+/, "").replace(/[\t\r\n\s]+$/, "");
|
|
@@ -97494,7 +97494,7 @@ var require_turndown_cjs = __commonJS({
|
|
|
97494
97494
|
if (whitespace.leading || whitespace.trailing) content = content.trim();
|
|
97495
97495
|
return whitespace.leading + rule.replacement(content, node2, this.options) + whitespace.trailing;
|
|
97496
97496
|
}
|
|
97497
|
-
function
|
|
97497
|
+
function join20(output, replacement) {
|
|
97498
97498
|
var s1 = trimTrailingNewlines(output);
|
|
97499
97499
|
var s2 = trimLeadingNewlines(replacement);
|
|
97500
97500
|
var nls = Math.max(output.length - s1.length, replacement.length - s2.length);
|
|
@@ -98924,9 +98924,9 @@ var require_fast_content_type_parse = __commonJS({
|
|
|
98924
98924
|
});
|
|
98925
98925
|
|
|
98926
98926
|
// main.ts
|
|
98927
|
-
import { existsSync as existsSync7, readdirSync } from "node:fs";
|
|
98927
|
+
import { existsSync as existsSync7, readdirSync as readdirSync2 } from "node:fs";
|
|
98928
98928
|
import { readFile as readFile4 } from "node:fs/promises";
|
|
98929
|
-
import { join as
|
|
98929
|
+
import { join as join19 } from "node:path";
|
|
98930
98930
|
|
|
98931
98931
|
// node_modules/.pnpm/@ark+util@0.56.0/node_modules/@ark/util/out/arrays.js
|
|
98932
98932
|
var liftArray = (data) => Array.isArray(data) ? data : [data];
|
|
@@ -107987,6 +107987,11 @@ var providers = {
|
|
|
107987
107987
|
resolve: "opencode/kimi-k2.6",
|
|
107988
107988
|
openRouterResolve: "openrouter/moonshotai/kimi-k2.6"
|
|
107989
107989
|
},
|
|
107990
|
+
"minimax-m2.5": {
|
|
107991
|
+
displayName: "MiniMax M2.5",
|
|
107992
|
+
resolve: "opencode/minimax-m2.5",
|
|
107993
|
+
openRouterResolve: "openrouter/minimax/minimax-m2.5"
|
|
107994
|
+
},
|
|
107990
107995
|
"gpt-5-nano": {
|
|
107991
107996
|
displayName: "GPT Nano",
|
|
107992
107997
|
resolve: "opencode/gpt-5-nano",
|
|
@@ -108003,7 +108008,9 @@ var providers = {
|
|
|
108003
108008
|
displayName: "MiniMax M2.5",
|
|
108004
108009
|
resolve: "opencode/minimax-m2.5-free",
|
|
108005
108010
|
envVars: [],
|
|
108006
|
-
isFree: true
|
|
108011
|
+
isFree: true,
|
|
108012
|
+
fallback: "opencode/big-pickle",
|
|
108013
|
+
hidden: true
|
|
108007
108014
|
}
|
|
108008
108015
|
}
|
|
108009
108016
|
}),
|
|
@@ -108021,6 +108028,25 @@ var providers = {
|
|
|
108021
108028
|
}
|
|
108022
108029
|
}
|
|
108023
108030
|
}),
|
|
108031
|
+
vertex: provider({
|
|
108032
|
+
displayName: "Google Vertex AI",
|
|
108033
|
+
envVars: [
|
|
108034
|
+
"VERTEX_SERVICE_ACCOUNT_JSON",
|
|
108035
|
+
"GOOGLE_CLOUD_PROJECT",
|
|
108036
|
+
"VERTEX_LOCATION",
|
|
108037
|
+
"VERTEX_MODEL_ID"
|
|
108038
|
+
],
|
|
108039
|
+
models: {
|
|
108040
|
+
// single routing entry — the actual Vertex AI model ID is read from
|
|
108041
|
+
// VERTEX_MODEL_ID at run time. see ModelRouting docs for why we don't
|
|
108042
|
+
// catalog individual Vertex models.
|
|
108043
|
+
byok: {
|
|
108044
|
+
displayName: "Google Vertex AI",
|
|
108045
|
+
resolve: "vertex",
|
|
108046
|
+
routing: "vertex"
|
|
108047
|
+
}
|
|
108048
|
+
}
|
|
108049
|
+
}),
|
|
108024
108050
|
openrouter: provider({
|
|
108025
108051
|
displayName: "OpenRouter",
|
|
108026
108052
|
envVars: ["OPENROUTER_API_KEY"],
|
|
@@ -108122,6 +108148,11 @@ var providers = {
|
|
|
108122
108148
|
displayName: "Kimi K2",
|
|
108123
108149
|
resolve: "openrouter/moonshotai/kimi-k2.6",
|
|
108124
108150
|
openRouterResolve: "openrouter/moonshotai/kimi-k2.6"
|
|
108151
|
+
},
|
|
108152
|
+
"minimax-m2.5": {
|
|
108153
|
+
displayName: "MiniMax M2.5",
|
|
108154
|
+
resolve: "openrouter/minimax/minimax-m2.5",
|
|
108155
|
+
openRouterResolve: "openrouter/minimax/minimax-m2.5"
|
|
108125
108156
|
}
|
|
108126
108157
|
}
|
|
108127
108158
|
})
|
|
@@ -108166,6 +108197,11 @@ var modelAliases = Object.entries(providers).flatMap(
|
|
|
108166
108197
|
hidden: def.hidden ?? false
|
|
108167
108198
|
}))
|
|
108168
108199
|
);
|
|
108200
|
+
var defaultProxyAlias = modelAliases.find((a) => a.slug === "moonshotai/kimi-k2");
|
|
108201
|
+
if (!defaultProxyAlias?.openRouterResolve) {
|
|
108202
|
+
throw new Error("DEFAULT_PROXY_MODEL: moonshotai/kimi-k2 missing openRouterResolve");
|
|
108203
|
+
}
|
|
108204
|
+
var DEFAULT_PROXY_MODEL = defaultProxyAlias.openRouterResolve;
|
|
108169
108205
|
var MAX_FALLBACK_DEPTH = 10;
|
|
108170
108206
|
function resolveDisplayAlias(slug2) {
|
|
108171
108207
|
let current = slug2;
|
|
@@ -108184,9 +108220,13 @@ function resolveCliModel(slug2) {
|
|
|
108184
108220
|
return resolveDisplayAlias(slug2)?.resolve;
|
|
108185
108221
|
}
|
|
108186
108222
|
var BEDROCK_MODEL_ID_ENV = "BEDROCK_MODEL_ID";
|
|
108223
|
+
var VERTEX_MODEL_ID_ENV = "VERTEX_MODEL_ID";
|
|
108187
108224
|
function isBedrockAnthropicId(bedrockModelId) {
|
|
108188
108225
|
return bedrockModelId.toLowerCase().split(/[./:]/).includes("anthropic");
|
|
108189
108226
|
}
|
|
108227
|
+
function isVertexAnthropicId(vertexModelId) {
|
|
108228
|
+
return /^claude-/i.test(vertexModelId.trim());
|
|
108229
|
+
}
|
|
108190
108230
|
|
|
108191
108231
|
// utils/buildPullfrogFooter.ts
|
|
108192
108232
|
var PULLFROG_DIVIDER = "<!-- PULLFROG_DIVIDER_DO_NOT_REMOVE_PLZ -->";
|
|
@@ -142469,7 +142509,7 @@ var import_semver = __toESM(require_semver2(), 1);
|
|
|
142469
142509
|
// package.json
|
|
142470
142510
|
var package_default = {
|
|
142471
142511
|
name: "pullfrog",
|
|
142472
|
-
version: "0.1.
|
|
142512
|
+
version: "0.1.12",
|
|
142473
142513
|
type: "module",
|
|
142474
142514
|
bin: {
|
|
142475
142515
|
pullfrog: "dist/cli.mjs",
|
|
@@ -142667,8 +142707,8 @@ function closeBrowserDaemon(toolState) {
|
|
|
142667
142707
|
|
|
142668
142708
|
// mcp/checkout.ts
|
|
142669
142709
|
import { createHash as createHash2 } from "node:crypto";
|
|
142670
|
-
import { statSync, unlinkSync as
|
|
142671
|
-
import { join as
|
|
142710
|
+
import { statSync, unlinkSync as unlinkSync3, writeFileSync } from "node:fs";
|
|
142711
|
+
import { join as join4 } from "node:path";
|
|
142672
142712
|
|
|
142673
142713
|
// utils/diffCoverage.ts
|
|
142674
142714
|
import { isAbsolute, normalize as normalize2, resolve } from "node:path";
|
|
@@ -144180,6 +144220,183 @@ async function reportReviewNodeId(ctx, params) {
|
|
|
144180
144220
|
await patchWorkflowRunFields(ctx, { reviewNodeId: params.nodeId });
|
|
144181
144221
|
}
|
|
144182
144222
|
|
|
144223
|
+
// utils/setup.ts
|
|
144224
|
+
import { execFileSync as execFileSync3, execSync as execSync2 } from "node:child_process";
|
|
144225
|
+
import { mkdtempSync, readdirSync, realpathSync as realpathSync2, unlinkSync as unlinkSync2 } from "node:fs";
|
|
144226
|
+
import { tmpdir } from "node:os";
|
|
144227
|
+
import { join as join3 } from "node:path";
|
|
144228
|
+
function createTempDirectory() {
|
|
144229
|
+
const sharedTempDir = mkdtempSync(join3(tmpdir(), "pullfrog-"));
|
|
144230
|
+
process.env.PULLFROG_TEMP_DIR = sharedTempDir;
|
|
144231
|
+
log.info(`\xBB created temp dir at ${sharedTempDir}`);
|
|
144232
|
+
return sharedTempDir;
|
|
144233
|
+
}
|
|
144234
|
+
function wipeRunnerLeakSurface() {
|
|
144235
|
+
const runnerTemp = process.env.RUNNER_TEMP;
|
|
144236
|
+
if (!runnerTemp) return;
|
|
144237
|
+
const preserve = /* @__PURE__ */ new Set();
|
|
144238
|
+
for (const envVar of [
|
|
144239
|
+
"GITHUB_OUTPUT",
|
|
144240
|
+
"GITHUB_ENV",
|
|
144241
|
+
"GITHUB_PATH",
|
|
144242
|
+
"GITHUB_STATE",
|
|
144243
|
+
"GITHUB_STEP_SUMMARY"
|
|
144244
|
+
]) {
|
|
144245
|
+
const path3 = process.env[envVar];
|
|
144246
|
+
if (!path3) continue;
|
|
144247
|
+
try {
|
|
144248
|
+
preserve.add(realpathSync2(path3));
|
|
144249
|
+
} catch {
|
|
144250
|
+
preserve.add(path3);
|
|
144251
|
+
}
|
|
144252
|
+
}
|
|
144253
|
+
const wiped = [];
|
|
144254
|
+
const tryUnlink = (path3) => {
|
|
144255
|
+
let resolved = path3;
|
|
144256
|
+
try {
|
|
144257
|
+
resolved = realpathSync2(path3);
|
|
144258
|
+
} catch {
|
|
144259
|
+
}
|
|
144260
|
+
if (preserve.has(resolved) || preserve.has(path3)) return;
|
|
144261
|
+
try {
|
|
144262
|
+
unlinkSync2(path3);
|
|
144263
|
+
wiped.push(path3);
|
|
144264
|
+
} catch {
|
|
144265
|
+
}
|
|
144266
|
+
};
|
|
144267
|
+
const listDir = (dir) => {
|
|
144268
|
+
try {
|
|
144269
|
+
return readdirSync(dir);
|
|
144270
|
+
} catch {
|
|
144271
|
+
return [];
|
|
144272
|
+
}
|
|
144273
|
+
};
|
|
144274
|
+
const fileCommandsDir = join3(runnerTemp, "_runner_file_commands");
|
|
144275
|
+
for (const entry of listDir(fileCommandsDir)) {
|
|
144276
|
+
tryUnlink(join3(fileCommandsDir, entry));
|
|
144277
|
+
}
|
|
144278
|
+
for (const entry of listDir(runnerTemp)) {
|
|
144279
|
+
if (entry.endsWith(".sh") || /^git-credentials-.*\.config$/.test(entry)) {
|
|
144280
|
+
tryUnlink(join3(runnerTemp, entry));
|
|
144281
|
+
}
|
|
144282
|
+
}
|
|
144283
|
+
if (wiped.length > 0) {
|
|
144284
|
+
log.info(`\xBB wiped ${wiped.length} leak-surface file(s) from $RUNNER_TEMP`);
|
|
144285
|
+
log.debug(`\xBB wiped paths: ${wiped.join(", ")}`);
|
|
144286
|
+
}
|
|
144287
|
+
}
|
|
144288
|
+
function envScopedToRepo() {
|
|
144289
|
+
const scoped = { ...process.env };
|
|
144290
|
+
for (const key of Object.keys(scoped)) {
|
|
144291
|
+
if (key.startsWith("GIT_")) delete scoped[key];
|
|
144292
|
+
}
|
|
144293
|
+
return scoped;
|
|
144294
|
+
}
|
|
144295
|
+
function removeIncludeIfEntries(repoDir) {
|
|
144296
|
+
const env2 = envScopedToRepo();
|
|
144297
|
+
let configOutput;
|
|
144298
|
+
try {
|
|
144299
|
+
configOutput = execSync2("git config --local --get-regexp -z ^includeif\\.", {
|
|
144300
|
+
cwd: repoDir,
|
|
144301
|
+
encoding: "utf-8",
|
|
144302
|
+
stdio: "pipe",
|
|
144303
|
+
env: env2
|
|
144304
|
+
});
|
|
144305
|
+
} catch {
|
|
144306
|
+
log.debug("\xBB no includeIf credential entries to remove");
|
|
144307
|
+
return;
|
|
144308
|
+
}
|
|
144309
|
+
const seen = /* @__PURE__ */ new Set();
|
|
144310
|
+
for (const entry of configOutput.split("\0")) {
|
|
144311
|
+
if (!entry) continue;
|
|
144312
|
+
const nl = entry.indexOf("\n");
|
|
144313
|
+
const key = nl === -1 ? entry : entry.slice(0, nl);
|
|
144314
|
+
if (!key || seen.has(key)) continue;
|
|
144315
|
+
seen.add(key);
|
|
144316
|
+
try {
|
|
144317
|
+
execFileSync3("git", ["config", "--local", "--unset-all", key], {
|
|
144318
|
+
cwd: repoDir,
|
|
144319
|
+
stdio: "pipe",
|
|
144320
|
+
env: env2
|
|
144321
|
+
});
|
|
144322
|
+
} catch (error49) {
|
|
144323
|
+
log.debug(
|
|
144324
|
+
`\xBB failed to unset ${key}: ${error49 instanceof Error ? error49.message : String(error49)}`
|
|
144325
|
+
);
|
|
144326
|
+
}
|
|
144327
|
+
}
|
|
144328
|
+
if (seen.size > 0)
|
|
144329
|
+
log.info(
|
|
144330
|
+
`\xBB removed ${seen.size} includeIf credential ${seen.size === 1 ? "entry" : "entries"}`
|
|
144331
|
+
);
|
|
144332
|
+
}
|
|
144333
|
+
async function setupGit(params) {
|
|
144334
|
+
const repoDir = process.cwd();
|
|
144335
|
+
log.info("\xBB setting up git configuration...");
|
|
144336
|
+
try {
|
|
144337
|
+
let currentEmail = "";
|
|
144338
|
+
try {
|
|
144339
|
+
currentEmail = execSync2("git config user.email", {
|
|
144340
|
+
cwd: repoDir,
|
|
144341
|
+
stdio: "pipe",
|
|
144342
|
+
encoding: "utf-8"
|
|
144343
|
+
}).trim();
|
|
144344
|
+
} catch {
|
|
144345
|
+
}
|
|
144346
|
+
const shouldSetDefaults = !currentEmail || currentEmail === "github-actions[bot]@users.noreply.github.com";
|
|
144347
|
+
if (shouldSetDefaults) {
|
|
144348
|
+
execSync2('git config --local user.email "226033991+pullfrog[bot]@users.noreply.github.com"', {
|
|
144349
|
+
cwd: repoDir,
|
|
144350
|
+
stdio: "pipe"
|
|
144351
|
+
});
|
|
144352
|
+
execSync2('git config --local user.name "pullfrog[bot]"', {
|
|
144353
|
+
cwd: repoDir,
|
|
144354
|
+
stdio: "pipe"
|
|
144355
|
+
});
|
|
144356
|
+
log.debug("\xBB git user configured (using defaults)");
|
|
144357
|
+
} else {
|
|
144358
|
+
log.debug(`\xBB git user already configured (${currentEmail}), skipping`);
|
|
144359
|
+
}
|
|
144360
|
+
if (params.shell === "disabled") {
|
|
144361
|
+
execSync2("git config --local core.hooksPath /dev/null", {
|
|
144362
|
+
cwd: repoDir,
|
|
144363
|
+
stdio: "pipe"
|
|
144364
|
+
});
|
|
144365
|
+
log.debug("\xBB git hooks disabled (shell=disabled)");
|
|
144366
|
+
}
|
|
144367
|
+
} catch (error49) {
|
|
144368
|
+
log.info(`Failed to set git config: ${error49 instanceof Error ? error49.message : String(error49)}`);
|
|
144369
|
+
}
|
|
144370
|
+
try {
|
|
144371
|
+
execSync2("git config --local --unset-all http.https://github.com/.extraheader", {
|
|
144372
|
+
cwd: repoDir,
|
|
144373
|
+
stdio: "pipe"
|
|
144374
|
+
});
|
|
144375
|
+
log.info("\xBB removed existing authentication headers");
|
|
144376
|
+
} catch {
|
|
144377
|
+
log.debug("\xBB no existing authentication headers to remove");
|
|
144378
|
+
}
|
|
144379
|
+
removeIncludeIfEntries(repoDir);
|
|
144380
|
+
const originUrl = `https://github.com/${params.owner}/${params.name}.git`;
|
|
144381
|
+
$("git", ["remote", "set-url", "origin", originUrl], { cwd: repoDir });
|
|
144382
|
+
params.toolState.pushUrl = originUrl;
|
|
144383
|
+
$("git", ["config", "--local", "credential.helper", ""], { cwd: repoDir });
|
|
144384
|
+
params.toolState.initialHead = captureInitialHead(repoDir);
|
|
144385
|
+
log.info("\xBB git authentication configured");
|
|
144386
|
+
}
|
|
144387
|
+
function captureInitialHead(repoDir) {
|
|
144388
|
+
try {
|
|
144389
|
+
const name = $("git", ["symbolic-ref", "--short", "HEAD"], {
|
|
144390
|
+
cwd: repoDir,
|
|
144391
|
+
log: false
|
|
144392
|
+
}).trim();
|
|
144393
|
+
if (name) return { kind: "branch", name };
|
|
144394
|
+
} catch {
|
|
144395
|
+
}
|
|
144396
|
+
const sha = $("git", ["rev-parse", "HEAD"], { cwd: repoDir, log: false }).trim();
|
|
144397
|
+
return { kind: "detached", sha };
|
|
144398
|
+
}
|
|
144399
|
+
|
|
144183
144400
|
// mcp/checkout.ts
|
|
144184
144401
|
function formatFilesWithLineNumbers(files) {
|
|
144185
144402
|
const output = [];
|
|
@@ -144354,7 +144571,7 @@ function cleanupStaleGitLocks() {
|
|
|
144354
144571
|
}
|
|
144355
144572
|
if (now - mtimeMs < STALE_LOCK_AGE_MS) continue;
|
|
144356
144573
|
try {
|
|
144357
|
-
|
|
144574
|
+
unlinkSync3(relPath);
|
|
144358
144575
|
log.warning(`\xBB removed stale ${relPath} from prior run`);
|
|
144359
144576
|
} catch (e) {
|
|
144360
144577
|
log.debug(
|
|
@@ -144513,6 +144730,15 @@ async function checkoutPrBranch(pr, params) {
|
|
|
144513
144730
|
return { hookWarning: postCheckoutHook.warning };
|
|
144514
144731
|
}
|
|
144515
144732
|
var inFlightCheckouts = /* @__PURE__ */ new Map();
|
|
144733
|
+
function headsEqual(a, b) {
|
|
144734
|
+
if (a.kind === "branch" && b.kind === "branch") return a.name === b.name;
|
|
144735
|
+
if (a.kind === "detached" && b.kind === "detached") return a.sha === b.sha;
|
|
144736
|
+
return false;
|
|
144737
|
+
}
|
|
144738
|
+
function describeHead(h) {
|
|
144739
|
+
if (h.kind === "branch") return `branch \`${h.name}\``;
|
|
144740
|
+
return `detached HEAD \`${h.sha}\``;
|
|
144741
|
+
}
|
|
144516
144742
|
function CheckoutPrTool(ctx) {
|
|
144517
144743
|
const runCheckout = async (pull_number) => {
|
|
144518
144744
|
const prResponse = await ctx.octokit.rest.pulls.get({
|
|
@@ -144559,7 +144785,7 @@ function CheckoutPrTool(ctx) {
|
|
|
144559
144785
|
headSha: ctx.toolState.checkoutSha
|
|
144560
144786
|
});
|
|
144561
144787
|
if (incremental) {
|
|
144562
|
-
incrementalDiffPath =
|
|
144788
|
+
incrementalDiffPath = join4(
|
|
144563
144789
|
tempDir,
|
|
144564
144790
|
`pr-${pull_number}-${beforeShort}-${headShort}-incremental.diff`
|
|
144565
144791
|
);
|
|
@@ -144573,7 +144799,7 @@ function CheckoutPrTool(ctx) {
|
|
|
144573
144799
|
const diffPreview = formatResult.content.split("\n").slice(0, 100).join("\n");
|
|
144574
144800
|
log.debug(`formatted diff preview (first 100 lines):
|
|
144575
144801
|
${diffPreview}`);
|
|
144576
|
-
const diffPath =
|
|
144802
|
+
const diffPath = join4(tempDir, `pr-${pull_number}-${headShort}.diff`);
|
|
144577
144803
|
writeFileSync(diffPath, formatResult.content);
|
|
144578
144804
|
log.debug(`wrote diff to ${diffPath} (${formatResult.content.length} bytes)`);
|
|
144579
144805
|
ctx.toolState.diffCoverage = createDiffCoverageState({
|
|
@@ -144640,7 +144866,8 @@ ${diffPreview}`);
|
|
|
144640
144866
|
};
|
|
144641
144867
|
return tool({
|
|
144642
144868
|
name: "checkout_pr",
|
|
144643
|
-
|
|
144869
|
+
timeoutMs: 6e5,
|
|
144870
|
+
description: "Checkout a pull request branch locally. This fetches the PR branch and sets up push configuration for fork PRs. Returns diffPath pointing to the formatted diff file. Example: `checkout_pr({ pull_number: 1234 })`. Large repos can take several minutes \u2014 wait for the call to finish; do not treat a slow response as failure. If you see `MCP error -32001: Request timed out`, retry the same call without touching git lock files first \u2014 that error is a client-side abort. If the retry then reports `.git/shallow.lock: File exists` or `.git/index.lock: File exists`, remove those lock files via the shell tool and retry again.",
|
|
144644
144871
|
parameters: CheckoutPr,
|
|
144645
144872
|
execute: execute(async ({ pull_number }) => {
|
|
144646
144873
|
const inFlight = inFlightCheckouts.get(pull_number);
|
|
@@ -144648,13 +144875,23 @@ ${diffPreview}`);
|
|
|
144648
144875
|
log.info(`\xBB checkout_pr({pull_number:${pull_number}}) already in flight \u2014 sharing result`);
|
|
144649
144876
|
return inFlight;
|
|
144650
144877
|
}
|
|
144651
|
-
const
|
|
144652
|
-
if (
|
|
144653
|
-
|
|
144654
|
-
|
|
144655
|
-
throw new Error(
|
|
144656
|
-
`cannot checkout PR #${pull_number} while the working tree has uncommitted changes. commit, push, or discard them before switching. dirty paths:
|
|
144878
|
+
const dirty = $("git", ["status", "--porcelain"], { log: false }).trim();
|
|
144879
|
+
if (dirty) {
|
|
144880
|
+
throw new Error(
|
|
144881
|
+
`cannot checkout PR #${pull_number} while the working tree has uncommitted changes. commit (then push if needed), or discard with \`git restore --staged --worktree .\` / \`git clean -fd\` before retrying. this refusal is unconditional \u2014 even re-checking-out the PR you're already on is refused, because shared-working-tree subagents make carry-forward edits unsafe. dirty paths:
|
|
144657
144882
|
${dirty}`
|
|
144883
|
+
);
|
|
144884
|
+
}
|
|
144885
|
+
const initialHead = ctx.toolState.initialHead;
|
|
144886
|
+
if (initialHead) {
|
|
144887
|
+
const currentHead = captureInitialHead(process.cwd());
|
|
144888
|
+
const targetBranch = `pr-${pull_number}`;
|
|
144889
|
+
const onTarget = currentHead.kind === "branch" && currentHead.name === targetBranch;
|
|
144890
|
+
const onInitial = headsEqual(currentHead, initialHead);
|
|
144891
|
+
if (!onTarget && !onInitial) {
|
|
144892
|
+
const recoverCmd = initialHead.kind === "branch" ? `git checkout ${initialHead.name}` : `git checkout ${initialHead.sha}`;
|
|
144893
|
+
throw new Error(
|
|
144894
|
+
`cannot checkout PR #${pull_number} from ${describeHead(currentHead)}. the only sanctioned HEAD positions for checkout_pr are the run-entry HEAD (${describeHead(initialHead)}) or the target PR's branch (\`${targetBranch}\`, idempotent re-checkout). recover with \`${recoverCmd}\` first \u2014 if that would carry uncommitted work along, commit or discard it (\`git restore --staged --worktree .\` / \`git clean -fd\`) before switching. routing around this via the \`git\` tool's \`checkout\`/\`switch\` subcommands is not sanctioned: this guard exists to prevent the shared-working-tree cross-PR clobber pattern from the zed-industries/cloud (2026-05-18) incident.`
|
|
144658
144895
|
);
|
|
144659
144896
|
}
|
|
144660
144897
|
}
|
|
@@ -144671,7 +144908,7 @@ ${dirty}`
|
|
|
144671
144908
|
|
|
144672
144909
|
// mcp/checkSuite.ts
|
|
144673
144910
|
import { mkdirSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
144674
|
-
import { join as
|
|
144911
|
+
import { join as join5 } from "node:path";
|
|
144675
144912
|
var GetCheckSuiteLogs = type({
|
|
144676
144913
|
check_suite_id: type.number.describe("the id from check_suite.id")
|
|
144677
144914
|
});
|
|
@@ -144767,7 +145004,7 @@ function GetCheckSuiteLogsTool(ctx) {
|
|
|
144767
145004
|
if (!tempDir) {
|
|
144768
145005
|
throw new Error("PULLFROG_TEMP_DIR not set");
|
|
144769
145006
|
}
|
|
144770
|
-
const logsDir =
|
|
145007
|
+
const logsDir = join5(tempDir, "ci-logs");
|
|
144771
145008
|
mkdirSync(logsDir, { recursive: true });
|
|
144772
145009
|
const jobResults = [];
|
|
144773
145010
|
for (const run of failedRuns) {
|
|
@@ -144794,7 +145031,7 @@ function GetCheckSuiteLogsTool(ctx) {
|
|
|
144794
145031
|
);
|
|
144795
145032
|
}
|
|
144796
145033
|
const logsText = await logsResult.text();
|
|
144797
|
-
const logPath =
|
|
145034
|
+
const logPath = join5(logsDir, `job-${job.id}.log`);
|
|
144798
145035
|
writeFileSync2(logPath, logsText);
|
|
144799
145036
|
const analysis = analyzeLog(logsText, 80);
|
|
144800
145037
|
const failedSteps = job.steps?.filter((s) => s.conclusion === "failure").map((s) => `Step ${s.number}: ${s.name}`) ?? [];
|
|
@@ -144844,7 +145081,7 @@ function GetCheckSuiteLogsTool(ctx) {
|
|
|
144844
145081
|
|
|
144845
145082
|
// mcp/commitInfo.ts
|
|
144846
145083
|
import { writeFileSync as writeFileSync3 } from "node:fs";
|
|
144847
|
-
import { join as
|
|
145084
|
+
import { join as join6 } from "node:path";
|
|
144848
145085
|
var CommitInfo = type({
|
|
144849
145086
|
sha: type.string.describe("the commit SHA (full or abbreviated) to fetch")
|
|
144850
145087
|
});
|
|
@@ -144868,7 +145105,7 @@ function CommitInfoTool(ctx) {
|
|
|
144868
145105
|
"PULLFROG_TEMP_DIR not set - get_commit_info must run in pullfrog action context"
|
|
144869
145106
|
);
|
|
144870
145107
|
}
|
|
144871
|
-
const diffFile =
|
|
145108
|
+
const diffFile = join6(tempDir, `commit-${sha.slice(0, 7)}.diff`);
|
|
144872
145109
|
writeFileSync3(diffFile, formatResult.content);
|
|
144873
145110
|
log.debug(`wrote commit diff to ${diffFile} (${formatResult.content.length} bytes)`);
|
|
144874
145111
|
return {
|
|
@@ -145326,7 +145563,7 @@ function PullRequestInfoTool(ctx) {
|
|
|
145326
145563
|
|
|
145327
145564
|
// mcp/reviewComments.ts
|
|
145328
145565
|
import { writeFileSync as writeFileSync4 } from "node:fs";
|
|
145329
|
-
import { join as
|
|
145566
|
+
import { join as join7 } from "node:path";
|
|
145330
145567
|
var REVIEW_THREADS_QUERY = `
|
|
145331
145568
|
query ($owner: String!, $name: String!, $prNumber: Int!) {
|
|
145332
145569
|
repository(owner: $owner, name: $name) {
|
|
@@ -145718,7 +145955,7 @@ function GetReviewCommentsTool(ctx) {
|
|
|
145718
145955
|
throw new Error("PULLFROG_TEMP_DIR not set");
|
|
145719
145956
|
}
|
|
145720
145957
|
const filename = `review-${params.review_id}-threads.md`;
|
|
145721
|
-
const commentsPath =
|
|
145958
|
+
const commentsPath = join7(tempDir, filename);
|
|
145722
145959
|
writeFileSync4(commentsPath, formatted.content);
|
|
145723
145960
|
log.debug(`wrote ${threadBlocks.length} threads to ${commentsPath}`);
|
|
145724
145961
|
return {
|
|
@@ -145947,7 +146184,7 @@ import { spawn as spawn2, spawnSync as spawnSync3 } from "node:child_process";
|
|
|
145947
146184
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
145948
146185
|
import { closeSync, openSync, writeFileSync as writeFileSync5 } from "node:fs";
|
|
145949
146186
|
import { userInfo } from "node:os";
|
|
145950
|
-
import { join as
|
|
146187
|
+
import { join as join8 } from "node:path";
|
|
145951
146188
|
import { setTimeout as sleep2 } from "node:timers/promises";
|
|
145952
146189
|
var ShellParams = type({
|
|
145953
146190
|
command: "string",
|
|
@@ -146080,7 +146317,7 @@ function getTempDir() {
|
|
|
146080
146317
|
var MAX_OUTPUT_CHARS = 5e3;
|
|
146081
146318
|
function capOutput(output) {
|
|
146082
146319
|
if (output.length <= MAX_OUTPUT_CHARS) return output;
|
|
146083
|
-
const fullPath =
|
|
146320
|
+
const fullPath = join8(getTempDir(), `shell-${randomUUID2().slice(0, 8)}.log`);
|
|
146084
146321
|
writeFileSync5(fullPath, output);
|
|
146085
146322
|
const elided = output.length - MAX_OUTPUT_CHARS;
|
|
146086
146323
|
return `... [${elided} chars truncated; full output saved to ${fullPath}] ...
|
|
@@ -146095,6 +146332,7 @@ function isGitCommand(command) {
|
|
|
146095
146332
|
function ShellTool(ctx) {
|
|
146096
146333
|
return tool({
|
|
146097
146334
|
name: "shell",
|
|
146335
|
+
timeoutMs: 12e4,
|
|
146098
146336
|
description: `Execute shell commands securely. Environment is filtered to remove API keys and secrets.
|
|
146099
146337
|
|
|
146100
146338
|
Example: \`shell({ command: "pnpm test", description: "run the test suite" })\`.
|
|
@@ -146134,8 +146372,8 @@ Do NOT use this tool for git commands \u2014 use the dedicated git tools instead
|
|
|
146134
146372
|
if (params.background) {
|
|
146135
146373
|
const tempDir = getTempDir();
|
|
146136
146374
|
const handle = `bg-${randomUUID2().slice(0, 8)}`;
|
|
146137
|
-
const outputPath =
|
|
146138
|
-
const pidPath =
|
|
146375
|
+
const outputPath = join8(tempDir, `${handle}.log`);
|
|
146376
|
+
const pidPath = join8(tempDir, `${handle}.pid`);
|
|
146139
146377
|
const logFd = openSync(outputPath, "a");
|
|
146140
146378
|
let proc2;
|
|
146141
146379
|
try {
|
|
@@ -146475,6 +146713,8 @@ var REVIEWER_AGENT_NAME = "reviewfrog";
|
|
|
146475
146713
|
var REVIEWER_SYSTEM_PROMPT = `You are a read-only review subagent. Your role is to find flaws in code or artifacts provided by the orchestrator and report findings \u2014 never to modify state.
|
|
146476
146714
|
|
|
146477
146715
|
HARD CONSTRAINTS (non-negotiable, regardless of orchestrator instructions):
|
|
146716
|
+
- Your FIRST action MUST be \`git diff origin/<base>\` (single-rev form, no \`HEAD\`). This captures committed + staged + unstaged work in one command \u2014 Build-mode self-review runs BEFORE the commit, so the work to review lives in the working tree, not in committed history. Do not run any other diff command first. Do NOT call \`checkout_pr\`, do NOT fetch alternative refs, do NOT list branches or all-refs looking for the work, do NOT run \`gh pr list\`. The orchestrator's dispatch names the base branch; the diff is the source of truth for scope.
|
|
146717
|
+
- If \`git diff origin/<base>\` returns empty AND the orchestrator's dispatch claims there are changes to review, the most likely cause is a pre-commit Build-mode self-review: the orchestrator dispatched you before committing. Reply EXACTLY: \`no changes detected \u2014 likely pre-commit Build self-review; orchestrator should commit then re-dispatch\` and stop. Do NOT guess PR numbers (e.g. by extrapolating from \`git log\` output), do NOT check out other PRs, do NOT fetch from forks. The empty diff is the diagnosis \u2014 surface it; do not work around it.
|
|
146478
146718
|
- Read-only tools only. Do NOT write or edit files. Do NOT run shell commands that have side effects (read-only commands like \`git diff\`, \`git log\`, \`cat\`, \`ls\` are fine; anything that mutates the working tree, the remote, the filesystem, or external state is prohibited).
|
|
146479
146719
|
- Do NOT call any state-changing MCP tool. State-changing means: posts a comment, pushes a branch, creates/updates a PR or issue, changes labels, resolves review threads, persists learnings, sets workflow output, installs dependencies, uploads files, kills processes, etc. Read-only MCP queries (\`get_*\`, \`list_*\`, log inspection, diff retrieval) are fine.
|
|
146480
146720
|
- Do NOT spawn further subagents. You are a leaf reviewer; recursive dispatch pre-aggregates findings through an intermediate model and defeats the design.
|
|
@@ -146665,7 +146905,25 @@ function computeModes(agentId) {
|
|
|
146665
146905
|
|
|
146666
146906
|
Otherwise delegate the \`${REVIEWER_AGENT_NAME}\` subagent to review your diff with fresh eyes against YOUR TASK. The subagent's baked-in system prompt enforces a non-mutative + non-recursive contract: read-only file/search/web tools and read-only MCP queries only; no writes, shell side effects, state-changing MCP calls, or nested subagent dispatch. Enforcement is prose-only \u2014 restate the constraint in your dispatch instructions and do not relax it.
|
|
146667
146907
|
|
|
146668
|
-
|
|
146908
|
+
Compose your \`${REVIEWER_AGENT_NAME}\` dispatch prompt using this template verbatim, substituting the \`<...>\` placeholders. The preamble aligns the orchestrator side of the dispatch contract with the reviewer's baked-in system prompt \u2014 both ends say the same thing about where the work lives and what to do on an empty diff.
|
|
146909
|
+
|
|
146910
|
+
\`\`\`
|
|
146911
|
+
## What you're reviewing
|
|
146912
|
+
This is a PRE-COMMIT Build-mode self-review. The work to review lives in the working tree (uncommitted), NOT in committed history.
|
|
146913
|
+
|
|
146914
|
+
Branch: <branch> (off <base>)
|
|
146915
|
+
Canonical diff command: git diff origin/<base>
|
|
146916
|
+
|
|
146917
|
+
If that command returns empty, treat it as "no changes \u2014 nothing to review" and stop per your system prompt. Do not search for the work elsewhere.
|
|
146918
|
+
|
|
146919
|
+
## Your task
|
|
146920
|
+
<YOUR TASK content>
|
|
146921
|
+
|
|
146922
|
+
## Build-phase failures
|
|
146923
|
+
<tight summary \u2014 what broke, root cause, the fix \u2014 or "no build-phase failures">
|
|
146924
|
+
\`\`\`
|
|
146925
|
+
|
|
146926
|
+
Follow the template with the diff content (\`git diff origin/<base-branch>\`, single-rev form \u2014 \`main...HEAD\` and \`--cached\` both miss the uncommitted edits self-review runs on) and your task brief. Instruct the subagent to flag bugs, logic errors, missing edge cases, gaps between request and diff, and unintended changes.
|
|
146669
146927
|
|
|
146670
146928
|
Delegation + research discipline (distilled from \`/anneal\` canonical \u2014 these are codified learnings from many review rounds, not theoretical best practices):
|
|
146671
146929
|
- Do NOT summarize what you implemented \u2014 that biases the subagent toward validating the shape of your solution rather than questioning it.
|
|
@@ -147064,21 +147322,21 @@ function initToolState(params) {
|
|
|
147064
147322
|
}
|
|
147065
147323
|
|
|
147066
147324
|
// agents/claude.ts
|
|
147067
|
-
import { execFileSync as
|
|
147068
|
-
import { mkdirSync as
|
|
147069
|
-
import { join as
|
|
147325
|
+
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
147326
|
+
import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync8 } from "node:fs";
|
|
147327
|
+
import { join as join12 } from "node:path";
|
|
147070
147328
|
import { performance as performance6 } from "node:perf_hooks";
|
|
147071
147329
|
|
|
147072
147330
|
// utils/install.ts
|
|
147073
147331
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
147074
147332
|
import { chmodSync, createWriteStream, existsSync as existsSync5, mkdirSync as mkdirSync2 } from "node:fs";
|
|
147075
|
-
import { join as
|
|
147333
|
+
import { join as join9 } from "node:path";
|
|
147076
147334
|
import { pipeline } from "node:stream/promises";
|
|
147077
147335
|
async function installFromNpmTarball(params) {
|
|
147078
147336
|
const tempDir = process.env.PULLFROG_TEMP_DIR;
|
|
147079
147337
|
if (!tempDir) throw new Error("PULLFROG_TEMP_DIR is not set");
|
|
147080
|
-
const extractedDir =
|
|
147081
|
-
const cliPath =
|
|
147338
|
+
const extractedDir = join9(tempDir, "package");
|
|
147339
|
+
const cliPath = join9(extractedDir, params.executablePath);
|
|
147082
147340
|
if (existsSync5(cliPath)) {
|
|
147083
147341
|
log.debug(`\xBB using cached binary at ${cliPath}`);
|
|
147084
147342
|
return cliPath;
|
|
@@ -147103,7 +147361,7 @@ async function installFromNpmTarball(params) {
|
|
|
147103
147361
|
}
|
|
147104
147362
|
}
|
|
147105
147363
|
log.debug(`\xBB installing ${params.packageName}@${resolvedVersion}...`);
|
|
147106
|
-
const tarballPath =
|
|
147364
|
+
const tarballPath = join9(tempDir, "package.tgz");
|
|
147107
147365
|
const npmRegistry = process.env.NPM_REGISTRY || "https://registry.npmjs.org";
|
|
147108
147366
|
let tarballUrl;
|
|
147109
147367
|
if (params.packageName.startsWith("@")) {
|
|
@@ -147242,16 +147500,16 @@ function isRouterKeylimitExhaustedError(text) {
|
|
|
147242
147500
|
// utils/skills.ts
|
|
147243
147501
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
147244
147502
|
import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync6 } from "node:fs";
|
|
147245
|
-
import { tmpdir } from "node:os";
|
|
147246
|
-
import { dirname as dirname2, join as
|
|
147503
|
+
import { tmpdir as tmpdir2 } from "node:os";
|
|
147504
|
+
import { dirname as dirname2, join as join10 } from "node:path";
|
|
147247
147505
|
import { fileURLToPath } from "node:url";
|
|
147248
147506
|
var skillsVersion = getDevDependencyVersion("skills");
|
|
147249
147507
|
var BUNDLED_SKILL_NAMES = ["git-archaeology"];
|
|
147250
147508
|
function resolveSkillPath(name) {
|
|
147251
147509
|
const here = dirname2(fileURLToPath(import.meta.url));
|
|
147252
147510
|
const candidates = [
|
|
147253
|
-
|
|
147254
|
-
|
|
147511
|
+
join10(here, "..", "skills", name, "SKILL.md"),
|
|
147512
|
+
join10(here, "skills", name, "SKILL.md")
|
|
147255
147513
|
];
|
|
147256
147514
|
for (const candidate of candidates) {
|
|
147257
147515
|
if (existsSync6(candidate)) return candidate;
|
|
@@ -147263,9 +147521,9 @@ function installBundledSkills(params) {
|
|
|
147263
147521
|
for (const name of BUNDLED_SKILL_NAMES) {
|
|
147264
147522
|
const content = readFileSync4(resolveSkillPath(name), "utf8");
|
|
147265
147523
|
for (const targetDir of SKILL_TARGET_DIRS) {
|
|
147266
|
-
const skillDir =
|
|
147524
|
+
const skillDir = join10(params.home, targetDir, name);
|
|
147267
147525
|
mkdirSync3(skillDir, { recursive: true });
|
|
147268
|
-
writeFileSync6(
|
|
147526
|
+
writeFileSync6(join10(skillDir, "SKILL.md"), content);
|
|
147269
147527
|
}
|
|
147270
147528
|
}
|
|
147271
147529
|
log.success(`installed bundled skills: ${BUNDLED_SKILL_NAMES.join(", ")}`);
|
|
@@ -147286,7 +147544,7 @@ function addSkill(params) {
|
|
|
147286
147544
|
"-y"
|
|
147287
147545
|
],
|
|
147288
147546
|
{
|
|
147289
|
-
cwd:
|
|
147547
|
+
cwd: tmpdir2(),
|
|
147290
147548
|
env: { ...process.env, ...params.env },
|
|
147291
147549
|
stdio: "pipe",
|
|
147292
147550
|
timeout: 3e4
|
|
@@ -147367,6 +147625,71 @@ var ThinkingTimer = class {
|
|
|
147367
147625
|
}
|
|
147368
147626
|
};
|
|
147369
147627
|
|
|
147628
|
+
// utils/vertex.ts
|
|
147629
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
147630
|
+
import { mkdirSync as mkdirSync4, rmSync, writeFileSync as writeFileSync7 } from "node:fs";
|
|
147631
|
+
import { homedir } from "node:os";
|
|
147632
|
+
import { join as join11 } from "node:path";
|
|
147633
|
+
var VERTEX_SERVICE_ACCOUNT_JSON_ENV = "VERTEX_SERVICE_ACCOUNT_JSON";
|
|
147634
|
+
var GOOGLE_APPLICATION_CREDENTIALS_ENV = "GOOGLE_APPLICATION_CREDENTIALS";
|
|
147635
|
+
var GOOGLE_CLOUD_PROJECT_ENV = "GOOGLE_CLOUD_PROJECT";
|
|
147636
|
+
var VERTEX_LOCATION_ENV = "VERTEX_LOCATION";
|
|
147637
|
+
function hasEnvVar(name) {
|
|
147638
|
+
const value2 = process.env[name];
|
|
147639
|
+
return typeof value2 === "string" && value2.length > 0;
|
|
147640
|
+
}
|
|
147641
|
+
function isVertexRoute(model) {
|
|
147642
|
+
const vertexId = process.env[VERTEX_MODEL_ID_ENV]?.trim();
|
|
147643
|
+
return model !== void 0 && vertexId !== void 0 && vertexId === model;
|
|
147644
|
+
}
|
|
147645
|
+
function readProjectIdFromVertexServiceAccountJson() {
|
|
147646
|
+
const blob = process.env[VERTEX_SERVICE_ACCOUNT_JSON_ENV];
|
|
147647
|
+
if (!blob) return void 0;
|
|
147648
|
+
try {
|
|
147649
|
+
const parsed2 = JSON.parse(blob);
|
|
147650
|
+
if (!parsed2 || typeof parsed2 !== "object" || !("project_id" in parsed2)) {
|
|
147651
|
+
return void 0;
|
|
147652
|
+
}
|
|
147653
|
+
const projectId = parsed2.project_id;
|
|
147654
|
+
return typeof projectId === "string" && projectId.length > 0 ? projectId : void 0;
|
|
147655
|
+
} catch {
|
|
147656
|
+
return void 0;
|
|
147657
|
+
}
|
|
147658
|
+
}
|
|
147659
|
+
function createSecretDir() {
|
|
147660
|
+
const base = process.env.PULLFROG_SECRET_HOME || process.env.HOME || homedir();
|
|
147661
|
+
const secretDir = join11(base, ".pullfrog", "secrets", randomUUID3());
|
|
147662
|
+
mkdirSync4(secretDir, { recursive: true, mode: 448 });
|
|
147663
|
+
return secretDir;
|
|
147664
|
+
}
|
|
147665
|
+
function materializeVertexCredentials(params) {
|
|
147666
|
+
if (!isVertexRoute(params.model)) return void 0;
|
|
147667
|
+
const blob = process.env[VERTEX_SERVICE_ACCOUNT_JSON_ENV];
|
|
147668
|
+
if (!blob) return void 0;
|
|
147669
|
+
const secretDir = createSecretDir();
|
|
147670
|
+
const credentialsPath = join11(secretDir, "vertex-sa.json");
|
|
147671
|
+
writeFileSync7(credentialsPath, blob, { mode: 384 });
|
|
147672
|
+
process.env[GOOGLE_APPLICATION_CREDENTIALS_ENV] = credentialsPath;
|
|
147673
|
+
const projectId = readProjectIdFromVertexServiceAccountJson();
|
|
147674
|
+
if (projectId && !hasEnvVar(GOOGLE_CLOUD_PROJECT_ENV)) {
|
|
147675
|
+
process.env[GOOGLE_CLOUD_PROJECT_ENV] = projectId;
|
|
147676
|
+
}
|
|
147677
|
+
return { credentialsPath, secretDir };
|
|
147678
|
+
}
|
|
147679
|
+
function cleanupVertexCredentials(credentials) {
|
|
147680
|
+
if (!credentials) return;
|
|
147681
|
+
rmSync(credentials.secretDir, { recursive: true, force: true });
|
|
147682
|
+
delete process.env[GOOGLE_APPLICATION_CREDENTIALS_ENV];
|
|
147683
|
+
}
|
|
147684
|
+
function applyClaudeVertexEnv(env2) {
|
|
147685
|
+
env2.CLAUDE_CODE_USE_VERTEX = "1";
|
|
147686
|
+
env2.ANTHROPIC_VERTEX_PROJECT_ID ??= env2[GOOGLE_CLOUD_PROJECT_ENV];
|
|
147687
|
+
env2.CLOUD_ML_REGION ??= env2[VERTEX_LOCATION_ENV];
|
|
147688
|
+
}
|
|
147689
|
+
function resolveVertexOpenCodeModel(model) {
|
|
147690
|
+
return isVertexRoute(model) && model ? `google-vertex/${model}` : void 0;
|
|
147691
|
+
}
|
|
147692
|
+
|
|
147370
147693
|
// agents/postRun.ts
|
|
147371
147694
|
import { readFile } from "node:fs/promises";
|
|
147372
147695
|
function getUnsubmittedReview(toolState) {
|
|
@@ -147670,10 +147993,10 @@ async function installClaudeCli() {
|
|
|
147670
147993
|
});
|
|
147671
147994
|
}
|
|
147672
147995
|
function writeMcpConfig(ctx) {
|
|
147673
|
-
const configDir =
|
|
147674
|
-
|
|
147675
|
-
const configPath =
|
|
147676
|
-
|
|
147996
|
+
const configDir = join12(ctx.tmpdir, ".claude");
|
|
147997
|
+
mkdirSync5(configDir, { recursive: true });
|
|
147998
|
+
const configPath = join12(configDir, "mcp.json");
|
|
147999
|
+
writeFileSync8(
|
|
147677
148000
|
configPath,
|
|
147678
148001
|
JSON.stringify({
|
|
147679
148002
|
mcpServers: {
|
|
@@ -148055,37 +148378,51 @@ ${stderrContext}`
|
|
|
148055
148378
|
var MANAGED_SETTINGS_DIR = "/etc/claude-code";
|
|
148056
148379
|
var MANAGED_SETTINGS_PATH = `${MANAGED_SETTINGS_DIR}/managed-settings.json`;
|
|
148057
148380
|
var CODEX_AUTH_DENY_PATH = "~/.local/share/opencode/auth.json";
|
|
148058
|
-
|
|
148059
|
-
|
|
148060
|
-
|
|
148061
|
-
|
|
148062
|
-
|
|
148063
|
-
|
|
148064
|
-
|
|
148065
|
-
|
|
148066
|
-
|
|
148067
|
-
|
|
148068
|
-
|
|
148069
|
-
|
|
148070
|
-
|
|
148071
|
-
|
|
148072
|
-
|
|
148073
|
-
|
|
148074
|
-
|
|
148075
|
-
|
|
148076
|
-
|
|
148077
|
-
|
|
148078
|
-
|
|
148079
|
-
|
|
148381
|
+
function buildManagedSettings(ctx) {
|
|
148382
|
+
const secretDenyPaths = ctx.secretDenyPaths ?? [];
|
|
148383
|
+
const toolDeny = secretDenyPaths.flatMap((path3) => [
|
|
148384
|
+
`Read(${path3}/**)`,
|
|
148385
|
+
`Read(/${path3}/**)`,
|
|
148386
|
+
`Grep(${path3}/**)`,
|
|
148387
|
+
`Grep(/${path3}/**)`,
|
|
148388
|
+
`Edit(${path3}/**)`,
|
|
148389
|
+
`Edit(/${path3}/**)`,
|
|
148390
|
+
`Glob(${path3}/**)`,
|
|
148391
|
+
`Glob(/${path3}/**)`
|
|
148392
|
+
]);
|
|
148393
|
+
return {
|
|
148394
|
+
allowManagedPermissionRulesOnly: true,
|
|
148395
|
+
allowManagedHooksOnly: true,
|
|
148396
|
+
permissions: {
|
|
148397
|
+
deny: [
|
|
148398
|
+
"Read(//proc/**)",
|
|
148399
|
+
"Read(//sys/**)",
|
|
148400
|
+
"Grep(//proc/**)",
|
|
148401
|
+
"Grep(//sys/**)",
|
|
148402
|
+
"Edit(//proc/**)",
|
|
148403
|
+
"Edit(//sys/**)",
|
|
148404
|
+
"Glob(//proc/**)",
|
|
148405
|
+
"Glob(//sys/**)",
|
|
148406
|
+
`Read(${CODEX_AUTH_DENY_PATH})`,
|
|
148407
|
+
`Grep(${CODEX_AUTH_DENY_PATH})`,
|
|
148408
|
+
`Edit(${CODEX_AUTH_DENY_PATH})`,
|
|
148409
|
+
`Glob(${CODEX_AUTH_DENY_PATH})`,
|
|
148410
|
+
...toolDeny
|
|
148411
|
+
]
|
|
148412
|
+
},
|
|
148413
|
+
sandbox: {
|
|
148414
|
+
filesystem: {
|
|
148415
|
+
denyRead: ["/proc", "/sys", CODEX_AUTH_DENY_PATH, ...secretDenyPaths]
|
|
148416
|
+
}
|
|
148080
148417
|
}
|
|
148081
|
-
}
|
|
148082
|
-
}
|
|
148083
|
-
function installManagedSettings() {
|
|
148418
|
+
};
|
|
148419
|
+
}
|
|
148420
|
+
function installManagedSettings(ctx) {
|
|
148084
148421
|
if (process.env.CI !== "true") return;
|
|
148085
|
-
const content = JSON.stringify(
|
|
148422
|
+
const content = JSON.stringify(buildManagedSettings(ctx), null, 2);
|
|
148086
148423
|
try {
|
|
148087
|
-
|
|
148088
|
-
|
|
148424
|
+
execFileSync4("sudo", ["mkdir", "-p", MANAGED_SETTINGS_DIR]);
|
|
148425
|
+
execFileSync4("sudo", ["tee", MANAGED_SETTINGS_PATH], {
|
|
148089
148426
|
input: content,
|
|
148090
148427
|
stdio: ["pipe", "ignore", "pipe"]
|
|
148091
148428
|
});
|
|
@@ -148102,23 +148439,25 @@ var claude = agent({
|
|
|
148102
148439
|
const specifier = ctx.payload.proxyModel ?? ctx.resolvedModel;
|
|
148103
148440
|
const bedrockModelId = process.env[BEDROCK_MODEL_ID_ENV]?.trim();
|
|
148104
148441
|
const isBedrockRoute = specifier !== void 0 && bedrockModelId !== void 0 && bedrockModelId === specifier && isBedrockAnthropicId(specifier);
|
|
148105
|
-
const
|
|
148442
|
+
const vertexModelId = process.env[VERTEX_MODEL_ID_ENV]?.trim();
|
|
148443
|
+
const isVertexRoute2 = specifier !== void 0 && vertexModelId !== void 0 && vertexModelId === specifier && isVertexAnthropicId(specifier);
|
|
148444
|
+
const model = !specifier ? void 0 : isBedrockRoute ? specifier : isVertexRoute2 ? void 0 : stripProviderPrefix(specifier);
|
|
148106
148445
|
const homeEnv = {
|
|
148107
148446
|
HOME: ctx.tmpdir,
|
|
148108
|
-
XDG_CONFIG_HOME:
|
|
148447
|
+
XDG_CONFIG_HOME: join12(ctx.tmpdir, ".config")
|
|
148109
148448
|
};
|
|
148110
|
-
|
|
148449
|
+
mkdirSync5(join12(homeEnv.XDG_CONFIG_HOME, "claude"), { recursive: true });
|
|
148111
148450
|
const agentBrowserVersion = getDevDependencyVersion("agent-browser");
|
|
148112
148451
|
addSkill({
|
|
148113
148452
|
ref: `vercel-labs/agent-browser@v${agentBrowserVersion}`,
|
|
148114
148453
|
skill: "agent-browser",
|
|
148115
148454
|
env: homeEnv,
|
|
148116
|
-
agent: "claude"
|
|
148455
|
+
agent: "claude-code"
|
|
148117
148456
|
});
|
|
148118
148457
|
installBundledSkills({ home: homeEnv.HOME });
|
|
148119
148458
|
const mcpConfigPath = writeMcpConfig(ctx);
|
|
148120
148459
|
const effort = resolveEffort(model);
|
|
148121
|
-
installManagedSettings();
|
|
148460
|
+
installManagedSettings(ctx);
|
|
148122
148461
|
const baseArgs = [
|
|
148123
148462
|
cliPath,
|
|
148124
148463
|
"--output-format",
|
|
@@ -148146,6 +148485,10 @@ var claude = agent({
|
|
|
148146
148485
|
if (isBedrockRoute) {
|
|
148147
148486
|
env2.CLAUDE_CODE_USE_BEDROCK = "1";
|
|
148148
148487
|
}
|
|
148488
|
+
if (isVertexRoute2) {
|
|
148489
|
+
applyClaudeVertexEnv(env2);
|
|
148490
|
+
env2.ANTHROPIC_MODEL = specifier;
|
|
148491
|
+
}
|
|
148149
148492
|
if (env2.CLAUDE_CODE_OAUTH_TOKEN && !isBedrockRoute && env2.ANTHROPIC_API_KEY) {
|
|
148150
148493
|
log.debug(
|
|
148151
148494
|
"\xBB CLAUDE_CODE_OAUTH_TOKEN present \u2014 stripping ANTHROPIC_API_KEY from Claude Code env so the OAuth subscription is used"
|
|
@@ -148187,8 +148530,8 @@ var claude = agent({
|
|
|
148187
148530
|
|
|
148188
148531
|
// agents/opencode_v2.ts
|
|
148189
148532
|
var core2 = __toESM(require_core(), 1);
|
|
148190
|
-
import { mkdirSync as
|
|
148191
|
-
import { join as
|
|
148533
|
+
import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync10 } from "node:fs";
|
|
148534
|
+
import { join as join14 } from "node:path";
|
|
148192
148535
|
import { performance as performance7 } from "node:perf_hooks";
|
|
148193
148536
|
|
|
148194
148537
|
// utils/agentHangReport.ts
|
|
@@ -148287,9 +148630,9 @@ function formatBillingExhaustedBody(diagnostic) {
|
|
|
148287
148630
|
}
|
|
148288
148631
|
|
|
148289
148632
|
// utils/codexHome.ts
|
|
148290
|
-
import { mkdirSync as
|
|
148291
|
-
import { homedir } from "node:os";
|
|
148292
|
-
import { join as
|
|
148633
|
+
import { mkdirSync as mkdirSync6, writeFileSync as writeFileSync9 } from "node:fs";
|
|
148634
|
+
import { homedir as homedir2 } from "node:os";
|
|
148635
|
+
import { join as join13 } from "node:path";
|
|
148293
148636
|
var CODEX_AUTH_ENV = "CODEX_AUTH_JSON";
|
|
148294
148637
|
function installCodexAuth() {
|
|
148295
148638
|
const raw2 = process.env[CODEX_AUTH_ENV];
|
|
@@ -148299,9 +148642,9 @@ function installCodexAuth() {
|
|
|
148299
148642
|
log.warning(`\xBB ${CODEX_AUTH_ENV} present but malformed; ignoring`);
|
|
148300
148643
|
return null;
|
|
148301
148644
|
}
|
|
148302
|
-
const xdgDataHome =
|
|
148303
|
-
const opencodeDir =
|
|
148304
|
-
const authPath =
|
|
148645
|
+
const xdgDataHome = join13(homedir2(), ".local", "share");
|
|
148646
|
+
const opencodeDir = join13(xdgDataHome, "opencode");
|
|
148647
|
+
const authPath = join13(opencodeDir, "auth.json");
|
|
148305
148648
|
const opencodeAuth = {
|
|
148306
148649
|
openai: {
|
|
148307
148650
|
type: "oauth",
|
|
@@ -148314,8 +148657,8 @@ function installCodexAuth() {
|
|
|
148314
148657
|
...blob.tokens.account_id ? { accountId: blob.tokens.account_id } : {}
|
|
148315
148658
|
}
|
|
148316
148659
|
};
|
|
148317
|
-
|
|
148318
|
-
|
|
148660
|
+
mkdirSync6(opencodeDir, { recursive: true });
|
|
148661
|
+
writeFileSync9(authPath, `${JSON.stringify(opencodeAuth, null, 2)}
|
|
148319
148662
|
`, { mode: 384 });
|
|
148320
148663
|
log.info(`\xBB installed Codex auth at ${authPath}`);
|
|
148321
148664
|
return { authPath, xdgDataHome, originalRefresh: blob.tokens.refresh_token };
|
|
@@ -148429,7 +148772,7 @@ export default async function pullfrogEventsPlugin() {
|
|
|
148429
148772
|
`;
|
|
148430
148773
|
|
|
148431
148774
|
// agents/opencodeShared.ts
|
|
148432
|
-
import { execFileSync as
|
|
148775
|
+
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
148433
148776
|
|
|
148434
148777
|
// agents/subagentModels.ts
|
|
148435
148778
|
function deriveSubagentModels(orchestratorSpec) {
|
|
@@ -148478,7 +148821,7 @@ async function installOpencodeCli(params) {
|
|
|
148478
148821
|
var AUTO_SELECT_WARNING = "select a model explicitly in the Pullfrog console (https://pullfrog.com/console) to avoid this.";
|
|
148479
148822
|
function getOpenCodeModels(cliPath) {
|
|
148480
148823
|
try {
|
|
148481
|
-
const output =
|
|
148824
|
+
const output = execFileSync5(cliPath, ["models"], {
|
|
148482
148825
|
encoding: "utf-8",
|
|
148483
148826
|
timeout: 3e4,
|
|
148484
148827
|
env: process.env
|
|
@@ -148971,16 +149314,17 @@ var opencode = agent({
|
|
|
148971
149314
|
const rawModel = ctx.payload.proxyModel ?? ctx.resolvedModel ?? autoSelectModel(cliPath);
|
|
148972
149315
|
const bedrockModelId = process.env[BEDROCK_MODEL_ID_ENV]?.trim();
|
|
148973
149316
|
const isBedrockRoute = rawModel !== void 0 && bedrockModelId !== void 0 && bedrockModelId === rawModel;
|
|
148974
|
-
const
|
|
149317
|
+
const vertexModel = resolveVertexOpenCodeModel(rawModel);
|
|
149318
|
+
const model = vertexModel ?? (isBedrockRoute ? `amazon-bedrock/${rawModel}` : rawModel);
|
|
148975
149319
|
const homeEnv = {
|
|
148976
149320
|
HOME: ctx.tmpdir,
|
|
148977
|
-
XDG_CONFIG_HOME:
|
|
149321
|
+
XDG_CONFIG_HOME: join14(ctx.tmpdir, ".config")
|
|
148978
149322
|
};
|
|
148979
|
-
|
|
148980
|
-
const opencodePluginDir =
|
|
148981
|
-
|
|
148982
|
-
|
|
148983
|
-
|
|
149323
|
+
mkdirSync7(join14(homeEnv.XDG_CONFIG_HOME, "opencode"), { recursive: true });
|
|
149324
|
+
const opencodePluginDir = join14(homeEnv.XDG_CONFIG_HOME, "opencode", "plugin");
|
|
149325
|
+
mkdirSync7(opencodePluginDir, { recursive: true });
|
|
149326
|
+
writeFileSync10(
|
|
149327
|
+
join14(opencodePluginDir, PULLFROG_OPENCODE_PLUGIN_FILENAME),
|
|
148984
149328
|
PULLFROG_OPENCODE_PLUGIN_SOURCE
|
|
148985
149329
|
);
|
|
148986
149330
|
const agentBrowserVersion = getDevDependencyVersion("agent-browser");
|
|
@@ -149050,15 +149394,18 @@ var opencode = agent({
|
|
|
149050
149394
|
var agents = { claude, opencode };
|
|
149051
149395
|
|
|
149052
149396
|
// utils/agent.ts
|
|
149053
|
-
function
|
|
149397
|
+
function hasEnvVar2(name) {
|
|
149054
149398
|
const val = process.env[name];
|
|
149055
149399
|
return typeof val === "string" && val.length > 0;
|
|
149056
149400
|
}
|
|
149057
149401
|
function hasClaudeCodeAuth() {
|
|
149058
|
-
return
|
|
149402
|
+
return hasEnvVar2("CLAUDE_CODE_OAUTH_TOKEN") || hasEnvVar2("ANTHROPIC_API_KEY");
|
|
149059
149403
|
}
|
|
149060
149404
|
function hasBedrockAuth() {
|
|
149061
|
-
return
|
|
149405
|
+
return hasEnvVar2("AWS_BEARER_TOKEN_BEDROCK") || hasEnvVar2("AWS_ACCESS_KEY_ID") && hasEnvVar2("AWS_SECRET_ACCESS_KEY");
|
|
149406
|
+
}
|
|
149407
|
+
function hasVertexAuth() {
|
|
149408
|
+
return hasEnvVar2(VERTEX_SERVICE_ACCOUNT_JSON_ENV);
|
|
149062
149409
|
}
|
|
149063
149410
|
function resolveSlug(slug2) {
|
|
149064
149411
|
const alias = resolveDisplayAlias(slug2);
|
|
@@ -149066,11 +149413,20 @@ function resolveSlug(slug2) {
|
|
|
149066
149413
|
const bedrockId = process.env[BEDROCK_MODEL_ID_ENV]?.trim();
|
|
149067
149414
|
if (!bedrockId) {
|
|
149068
149415
|
throw new Error(
|
|
149069
|
-
`${BEDROCK_MODEL_ID_ENV} env var is required when the model is set to "${slug2}". set it to an AWS Bedrock model ID
|
|
149416
|
+
`${BEDROCK_MODEL_ID_ENV} env var is required when the model is set to "${slug2}". set it to an AWS Bedrock model ID from the Bedrock console. see https://docs.pullfrog.com/bedrock for setup.`
|
|
149070
149417
|
);
|
|
149071
149418
|
}
|
|
149072
149419
|
return bedrockId;
|
|
149073
149420
|
}
|
|
149421
|
+
if (alias?.routing === "vertex") {
|
|
149422
|
+
const vertexId = process.env[VERTEX_MODEL_ID_ENV]?.trim();
|
|
149423
|
+
if (!vertexId) {
|
|
149424
|
+
throw new Error(
|
|
149425
|
+
`${VERTEX_MODEL_ID_ENV} env var is required when the model is set to "${slug2}". set it to a Google Vertex AI model ID from Model Garden. see https://docs.pullfrog.com/vertex for setup.`
|
|
149426
|
+
);
|
|
149427
|
+
}
|
|
149428
|
+
return vertexId;
|
|
149429
|
+
}
|
|
149074
149430
|
return resolveCliModel(slug2);
|
|
149075
149431
|
}
|
|
149076
149432
|
function resolveModel(ctx) {
|
|
@@ -149098,6 +149454,9 @@ function resolveAgent(ctx) {
|
|
|
149098
149454
|
if (ctx.model && hasBedrockAuth() && process.env[BEDROCK_MODEL_ID_ENV]?.trim() === ctx.model) {
|
|
149099
149455
|
return isBedrockAnthropicId(ctx.model) ? agents.claude : agents.opencode;
|
|
149100
149456
|
}
|
|
149457
|
+
if (ctx.model && hasVertexAuth() && process.env[VERTEX_MODEL_ID_ENV]?.trim() === ctx.model) {
|
|
149458
|
+
return isVertexAnthropicId(ctx.model) ? agents.claude : agents.opencode;
|
|
149459
|
+
}
|
|
149101
149460
|
if (ctx.model) {
|
|
149102
149461
|
try {
|
|
149103
149462
|
const provider2 = getModelProvider(ctx.model);
|
|
@@ -149138,26 +149497,51 @@ add the missing secret(s) to your GitHub repository at ${githubSecretsUrl}, then
|
|
|
149138
149497
|
|
|
149139
149498
|
for full setup instructions, see https://docs.pullfrog.com/bedrock`;
|
|
149140
149499
|
}
|
|
149141
|
-
function
|
|
149500
|
+
function buildVertexSetupError(params) {
|
|
149501
|
+
const githubSecretsUrl = `https://github.com/${params.owner}/${params.name}/settings/secrets/actions`;
|
|
149502
|
+
return `Google Vertex AI model selected but required configuration is missing: ${params.missing.join(", ")}.
|
|
149503
|
+
|
|
149504
|
+
add the missing secret(s) to your GitHub repository at ${githubSecretsUrl}, then reference them in your workflow's \`env:\` block:
|
|
149505
|
+
|
|
149506
|
+
${VERTEX_SERVICE_ACCOUNT_JSON_ENV}: \${{ secrets.${VERTEX_SERVICE_ACCOUNT_JSON_ENV} }}
|
|
149507
|
+
${GOOGLE_CLOUD_PROJECT_ENV}: my-project
|
|
149508
|
+
${VERTEX_LOCATION_ENV}: global
|
|
149509
|
+
${VERTEX_MODEL_ID_ENV}: <vertex-model-id>
|
|
149510
|
+
|
|
149511
|
+
for full setup instructions, see https://docs.pullfrog.com/vertex`;
|
|
149512
|
+
}
|
|
149513
|
+
function hasEnvVar3(name) {
|
|
149142
149514
|
const value2 = process.env[name];
|
|
149143
149515
|
return typeof value2 === "string" && value2.length > 0;
|
|
149144
149516
|
}
|
|
149145
149517
|
function hasProviderKey(model) {
|
|
149146
149518
|
const requiredVars = getModelEnvVars(model);
|
|
149147
149519
|
if (requiredVars.length === 0) return true;
|
|
149148
|
-
return requiredVars.some((v) =>
|
|
149520
|
+
return requiredVars.some((v) => hasEnvVar3(v));
|
|
149149
149521
|
}
|
|
149150
149522
|
function validateBedrockSetup(params) {
|
|
149151
|
-
const hasAuth =
|
|
149523
|
+
const hasAuth = hasEnvVar3("AWS_BEARER_TOKEN_BEDROCK") || hasEnvVar3("AWS_ACCESS_KEY_ID") && hasEnvVar3("AWS_SECRET_ACCESS_KEY");
|
|
149152
149524
|
const missing = [];
|
|
149153
149525
|
if (!hasAuth)
|
|
149154
149526
|
missing.push("AWS_BEARER_TOKEN_BEDROCK (or AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY)");
|
|
149155
|
-
if (!
|
|
149156
|
-
if (!
|
|
149527
|
+
if (!hasEnvVar3("AWS_REGION")) missing.push("AWS_REGION");
|
|
149528
|
+
if (!hasEnvVar3(BEDROCK_MODEL_ID_ENV)) missing.push(BEDROCK_MODEL_ID_ENV);
|
|
149157
149529
|
if (missing.length > 0) {
|
|
149158
149530
|
throw new Error(buildBedrockSetupError({ owner: params.owner, name: params.name, missing }));
|
|
149159
149531
|
}
|
|
149160
149532
|
}
|
|
149533
|
+
function validateVertexSetup(params) {
|
|
149534
|
+
const hasAuth = hasEnvVar3(VERTEX_SERVICE_ACCOUNT_JSON_ENV);
|
|
149535
|
+
const hasProject = hasEnvVar3(GOOGLE_CLOUD_PROJECT_ENV) || readProjectIdFromVertexServiceAccountJson() !== void 0;
|
|
149536
|
+
const missing = [];
|
|
149537
|
+
if (!hasAuth) missing.push(VERTEX_SERVICE_ACCOUNT_JSON_ENV);
|
|
149538
|
+
if (!hasProject) missing.push(GOOGLE_CLOUD_PROJECT_ENV);
|
|
149539
|
+
if (!hasEnvVar3(VERTEX_LOCATION_ENV)) missing.push(VERTEX_LOCATION_ENV);
|
|
149540
|
+
if (!hasEnvVar3(VERTEX_MODEL_ID_ENV)) missing.push(VERTEX_MODEL_ID_ENV);
|
|
149541
|
+
if (missing.length > 0) {
|
|
149542
|
+
throw new Error(buildVertexSetupError({ owner: params.owner, name: params.name, missing }));
|
|
149543
|
+
}
|
|
149544
|
+
}
|
|
149161
149545
|
function validateAgentApiKey(params) {
|
|
149162
149546
|
if (params.model) {
|
|
149163
149547
|
const alias = resolveDisplayAlias(params.model);
|
|
@@ -149165,16 +149549,24 @@ function validateAgentApiKey(params) {
|
|
|
149165
149549
|
validateBedrockSetup({ owner: params.owner, name: params.name });
|
|
149166
149550
|
return;
|
|
149167
149551
|
}
|
|
149552
|
+
if (alias?.routing === "vertex") {
|
|
149553
|
+
validateVertexSetup({ owner: params.owner, name: params.name });
|
|
149554
|
+
return;
|
|
149555
|
+
}
|
|
149168
149556
|
if (!params.model.includes("/")) {
|
|
149557
|
+
if (process.env[VERTEX_MODEL_ID_ENV]?.trim() === params.model) {
|
|
149558
|
+
validateVertexSetup({ owner: params.owner, name: params.name });
|
|
149559
|
+
return;
|
|
149560
|
+
}
|
|
149169
149561
|
validateBedrockSetup({ owner: params.owner, name: params.name });
|
|
149170
149562
|
return;
|
|
149171
149563
|
}
|
|
149172
149564
|
const requiredVars = getModelEnvVars(params.model);
|
|
149173
149565
|
if (requiredVars.length === 0) return;
|
|
149174
|
-
if (requiredVars.some((v) =>
|
|
149566
|
+
if (requiredVars.some((v) => hasEnvVar3(v))) return;
|
|
149175
149567
|
throw new Error(buildMissingApiKeyError({ owner: params.owner, name: params.name }));
|
|
149176
149568
|
}
|
|
149177
|
-
const hasAnyKey = [...knownApiKeys].some((k) =>
|
|
149569
|
+
const hasAnyKey = [...knownApiKeys].some((k) => hasEnvVar3(k));
|
|
149178
149570
|
if (!hasAnyKey) {
|
|
149179
149571
|
throw new Error(buildMissingApiKeyError({ owner: params.owner, name: params.name }));
|
|
149180
149572
|
}
|
|
@@ -149294,7 +149686,7 @@ async function fetchBodyHtml(ctx) {
|
|
|
149294
149686
|
}
|
|
149295
149687
|
|
|
149296
149688
|
// utils/byokFallback.ts
|
|
149297
|
-
var FREE_FALLBACK_SLUG = "opencode/
|
|
149689
|
+
var FREE_FALLBACK_SLUG = "opencode/big-pickle";
|
|
149298
149690
|
function selectFallbackModelIfNeeded(input) {
|
|
149299
149691
|
if (input.proxyModel) return { fallback: false };
|
|
149300
149692
|
if (!input.resolvedModel) return { fallback: false };
|
|
@@ -149309,10 +149701,10 @@ function selectFallbackModelIfNeeded(input) {
|
|
|
149309
149701
|
}
|
|
149310
149702
|
|
|
149311
149703
|
// utils/gitAuthServer.ts
|
|
149312
|
-
import { randomUUID as
|
|
149313
|
-
import { writeFileSync as
|
|
149704
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
149705
|
+
import { writeFileSync as writeFileSync11 } from "node:fs";
|
|
149314
149706
|
import { createServer as createServer2 } from "node:http";
|
|
149315
|
-
import { join as
|
|
149707
|
+
import { join as join15 } from "node:path";
|
|
149316
149708
|
var CODE_TTL_MS = 5 * 60 * 1e3;
|
|
149317
149709
|
var TAMPER_WINDOW_MS = 6e4;
|
|
149318
149710
|
function revokeGitHubToken(token) {
|
|
@@ -149372,7 +149764,7 @@ async function startGitAuthServer(tmpdir3) {
|
|
|
149372
149764
|
const port = rawAddr.port;
|
|
149373
149765
|
log.debug(`git auth server listening on 127.0.0.1:${port}`);
|
|
149374
149766
|
function register4(token) {
|
|
149375
|
-
const code =
|
|
149767
|
+
const code = randomUUID4();
|
|
149376
149768
|
const timeout = setTimeout(() => {
|
|
149377
149769
|
codes.delete(code);
|
|
149378
149770
|
log.debug(`git auth code expired: ${code.slice(0, 8)}...`);
|
|
@@ -149382,9 +149774,9 @@ async function startGitAuthServer(tmpdir3) {
|
|
|
149382
149774
|
return code;
|
|
149383
149775
|
}
|
|
149384
149776
|
function writeAskpassScript(code) {
|
|
149385
|
-
const scriptId =
|
|
149777
|
+
const scriptId = randomUUID4();
|
|
149386
149778
|
const scriptName = `askpass-${scriptId}.js`;
|
|
149387
|
-
const scriptPath =
|
|
149779
|
+
const scriptPath = join15(tmpdir3, scriptName);
|
|
149388
149780
|
const content = [
|
|
149389
149781
|
`#!/usr/bin/env node`,
|
|
149390
149782
|
`var a=process.argv[2]||"";`,
|
|
@@ -149399,7 +149791,7 @@ async function startGitAuthServer(tmpdir3) {
|
|
|
149399
149791
|
`try{require("fs").unlinkSync("${scriptPath.replace(/\\/g, "\\\\")}")}catch(e){}`,
|
|
149400
149792
|
`})}).on("error",function(){process.exit(1)})}`
|
|
149401
149793
|
].join("\n");
|
|
149402
|
-
|
|
149794
|
+
writeFileSync11(scriptPath, content, { mode: 448 });
|
|
149403
149795
|
return scriptPath;
|
|
149404
149796
|
}
|
|
149405
149797
|
async function close() {
|
|
@@ -149423,7 +149815,7 @@ async function startGitAuthServer(tmpdir3) {
|
|
|
149423
149815
|
var core3 = __toESM(require_core(), 1);
|
|
149424
149816
|
import { createSign } from "node:crypto";
|
|
149425
149817
|
import { rename, writeFile } from "node:fs/promises";
|
|
149426
|
-
import { dirname as dirname3, join as
|
|
149818
|
+
import { dirname as dirname3, join as join16 } from "node:path";
|
|
149427
149819
|
|
|
149428
149820
|
// node_modules/.pnpm/@octokit+plugin-throttling@11.0.3_@octokit+core@7.0.5/node_modules/@octokit/plugin-throttling/dist-bundle/index.js
|
|
149429
149821
|
var import_light = __toESM(require_light(), 1);
|
|
@@ -153281,7 +153673,7 @@ function getGitHubUsageSummary() {
|
|
|
153281
153673
|
}
|
|
153282
153674
|
async function writeGitHubUsageSummaryToFile(path3) {
|
|
153283
153675
|
const summary2 = getGitHubUsageSummary();
|
|
153284
|
-
const tmpPath =
|
|
153676
|
+
const tmpPath = join16(dirname3(path3), `.usage-summary-${process.pid}.tmp`);
|
|
153285
153677
|
await writeFile(tmpPath, JSON.stringify(summary2));
|
|
153286
153678
|
await rename(tmpPath, path3);
|
|
153287
153679
|
}
|
|
@@ -153332,7 +153724,7 @@ function createOctokit(token) {
|
|
|
153332
153724
|
}
|
|
153333
153725
|
|
|
153334
153726
|
// utils/instructions.ts
|
|
153335
|
-
import { execSync as
|
|
153727
|
+
import { execSync as execSync3 } from "node:child_process";
|
|
153336
153728
|
function buildRuntimeContext(ctx) {
|
|
153337
153729
|
const {
|
|
153338
153730
|
"~pullfrog": _,
|
|
@@ -153344,7 +153736,7 @@ function buildRuntimeContext(ctx) {
|
|
|
153344
153736
|
} = ctx.payload;
|
|
153345
153737
|
let gitStatus;
|
|
153346
153738
|
try {
|
|
153347
|
-
gitStatus =
|
|
153739
|
+
gitStatus = execSync3("git status --short", { encoding: "utf-8", stdio: "pipe" }).trim() || "(clean)";
|
|
153348
153740
|
} catch {
|
|
153349
153741
|
}
|
|
153350
153742
|
const data = {
|
|
@@ -153681,7 +154073,7 @@ function resolveInstructions(ctx) {
|
|
|
153681
154073
|
|
|
153682
154074
|
// utils/learnings.ts
|
|
153683
154075
|
import { mkdir, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
|
|
153684
|
-
import { dirname as dirname4, join as
|
|
154076
|
+
import { dirname as dirname4, join as join17 } from "node:path";
|
|
153685
154077
|
|
|
153686
154078
|
// utils/learningsTruncate.ts
|
|
153687
154079
|
var MAX_LEARNINGS_LENGTH = 1e5;
|
|
@@ -153698,7 +154090,7 @@ function truncateAtLineBoundary(body, cap) {
|
|
|
153698
154090
|
// utils/learnings.ts
|
|
153699
154091
|
var LEARNINGS_FILE_NAME = "pullfrog-learnings.md";
|
|
153700
154092
|
function learningsFilePath(tmpdir3) {
|
|
153701
|
-
return
|
|
154093
|
+
return join17(tmpdir3, LEARNINGS_FILE_NAME);
|
|
153702
154094
|
}
|
|
153703
154095
|
async function seedLearningsFile(params) {
|
|
153704
154096
|
const path3 = learningsFilePath(params.tmpdir);
|
|
@@ -154378,7 +154770,7 @@ async function runProxyResolution(ctx) {
|
|
|
154378
154770
|
|
|
154379
154771
|
// utils/prSummary.ts
|
|
154380
154772
|
import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile3 } from "node:fs/promises";
|
|
154381
|
-
import { dirname as dirname5, join as
|
|
154773
|
+
import { dirname as dirname5, join as join18 } from "node:path";
|
|
154382
154774
|
var SUMMARY_FILE_NAME = "pullfrog-summary.md";
|
|
154383
154775
|
var SUMMARY_SCAFFOLD = `# PR summary
|
|
154384
154776
|
|
|
@@ -154388,7 +154780,7 @@ var SUMMARY_SCAFFOLD = `# PR summary
|
|
|
154388
154780
|
var MIN_SNAPSHOT_LENGTH = 60;
|
|
154389
154781
|
var MAX_SNAPSHOT_LENGTH = 32768;
|
|
154390
154782
|
function summaryFilePath(tmpdir3) {
|
|
154391
|
-
return
|
|
154783
|
+
return join18(tmpdir3, SUMMARY_FILE_NAME);
|
|
154392
154784
|
}
|
|
154393
154785
|
async function seedSummaryFile(params) {
|
|
154394
154786
|
const path3 = summaryFilePath(params.tmpdir);
|
|
@@ -154582,6 +154974,16 @@ async function resolveRunContextData(params) {
|
|
|
154582
154974
|
}
|
|
154583
154975
|
|
|
154584
154976
|
// utils/runErrorRenderer.ts
|
|
154977
|
+
function isProviderModelNotFoundError(message) {
|
|
154978
|
+
return message.includes("ProviderModelNotFoundError");
|
|
154979
|
+
}
|
|
154980
|
+
function formatProviderModelNotFoundSummary(input) {
|
|
154981
|
+
return `Pullfrog's free fallback model is no longer available in OpenCode's catalog. Add an API key for your configured model in the Pullfrog console for \`${input.owner}/${input.name}\`, or contact support if this persists.
|
|
154982
|
+
|
|
154983
|
+
\`\`\`
|
|
154984
|
+
${input.raw}
|
|
154985
|
+
\`\`\``;
|
|
154986
|
+
}
|
|
154585
154987
|
function renderRunError(input) {
|
|
154586
154988
|
const billingError = isRouterKeylimitExhaustedError(input.errorMessage) ? new BillingError(input.errorMessage, { code: "router_keylimit_exhausted" }) : null;
|
|
154587
154989
|
if (billingError) {
|
|
@@ -154603,6 +155005,14 @@ function renderRunError(input) {
|
|
|
154603
155005
|
if (apiKeyErrorSummary) {
|
|
154604
155006
|
return { summary: apiKeyErrorSummary, comment: apiKeyErrorSummary };
|
|
154605
155007
|
}
|
|
155008
|
+
if (isProviderModelNotFoundError(input.errorMessage)) {
|
|
155009
|
+
const body = formatProviderModelNotFoundSummary({
|
|
155010
|
+
owner: input.repo.owner,
|
|
155011
|
+
name: input.repo.name,
|
|
155012
|
+
raw: input.errorMessage
|
|
155013
|
+
});
|
|
155014
|
+
return { summary: body, comment: body };
|
|
155015
|
+
}
|
|
154606
155016
|
if (hangBody) {
|
|
154607
155017
|
return {
|
|
154608
155018
|
summary: `### \u274C Pullfrog failed
|
|
@@ -154704,16 +155114,17 @@ async function persistRunArtifacts(toolContext) {
|
|
|
154704
155114
|
}
|
|
154705
155115
|
async function finalizeSuccessRun(input) {
|
|
154706
155116
|
await persistRunArtifacts(input.toolContext);
|
|
154707
|
-
|
|
154708
|
-
|
|
154709
|
-
|
|
154710
|
-
|
|
154711
|
-
|
|
154712
|
-
|
|
154713
|
-
|
|
154714
|
-
|
|
154715
|
-
|
|
154716
|
-
|
|
155117
|
+
const rendered = !input.result.success ? renderRunError({
|
|
155118
|
+
errorMessage: input.result.error || "agent run failed",
|
|
155119
|
+
repo: input.repo,
|
|
155120
|
+
agentDiagnostic: input.toolState.agentDiagnostic
|
|
155121
|
+
}) : null;
|
|
155122
|
+
if (rendered && input.toolState.progressComment) {
|
|
155123
|
+
await reportErrorToComment({ toolState: input.toolState, error: rendered.comment }).catch(
|
|
155124
|
+
(error49) => {
|
|
155125
|
+
log.debug(`failure error report failed: ${error49}`);
|
|
155126
|
+
}
|
|
155127
|
+
);
|
|
154717
155128
|
}
|
|
154718
155129
|
if (input.result.success && input.toolState.progressComment && !input.toolState.finalSummaryWritten) {
|
|
154719
155130
|
await deleteProgressComment(input.toolContext).catch((error49) => {
|
|
@@ -154723,7 +155134,7 @@ async function finalizeSuccessRun(input) {
|
|
|
154723
155134
|
try {
|
|
154724
155135
|
const usageSummary = formatUsageSummary(input.toolState.usageEntries);
|
|
154725
155136
|
const body = input.toolState.lastProgressBody || input.result.output;
|
|
154726
|
-
const parts = [body, usageSummary].filter(Boolean);
|
|
155137
|
+
const parts = [rendered?.summary, body, usageSummary].filter(Boolean);
|
|
154727
155138
|
if (parts.length > 0) {
|
|
154728
155139
|
await writeSummary(parts.join("\n\n"));
|
|
154729
155140
|
}
|
|
@@ -154808,116 +155219,6 @@ function logRunStartup(ctx) {
|
|
|
154808
155219
|
log.info(`\xBB timeout: ${resolveTimeoutForLog(ctx.payload.timeout)}`);
|
|
154809
155220
|
}
|
|
154810
155221
|
|
|
154811
|
-
// utils/setup.ts
|
|
154812
|
-
import { execFileSync as execFileSync5, execSync as execSync3 } from "node:child_process";
|
|
154813
|
-
import { mkdtempSync } from "node:fs";
|
|
154814
|
-
import { tmpdir as tmpdir2 } from "node:os";
|
|
154815
|
-
import { join as join17 } from "node:path";
|
|
154816
|
-
function createTempDirectory() {
|
|
154817
|
-
const sharedTempDir = mkdtempSync(join17(tmpdir2(), "pullfrog-"));
|
|
154818
|
-
process.env.PULLFROG_TEMP_DIR = sharedTempDir;
|
|
154819
|
-
log.info(`\xBB created temp dir at ${sharedTempDir}`);
|
|
154820
|
-
return sharedTempDir;
|
|
154821
|
-
}
|
|
154822
|
-
function envScopedToRepo() {
|
|
154823
|
-
const scoped = { ...process.env };
|
|
154824
|
-
for (const key of Object.keys(scoped)) {
|
|
154825
|
-
if (key.startsWith("GIT_")) delete scoped[key];
|
|
154826
|
-
}
|
|
154827
|
-
return scoped;
|
|
154828
|
-
}
|
|
154829
|
-
function removeIncludeIfEntries(repoDir) {
|
|
154830
|
-
const env2 = envScopedToRepo();
|
|
154831
|
-
let configOutput;
|
|
154832
|
-
try {
|
|
154833
|
-
configOutput = execSync3("git config --local --get-regexp -z ^includeif\\.", {
|
|
154834
|
-
cwd: repoDir,
|
|
154835
|
-
encoding: "utf-8",
|
|
154836
|
-
stdio: "pipe",
|
|
154837
|
-
env: env2
|
|
154838
|
-
});
|
|
154839
|
-
} catch {
|
|
154840
|
-
log.debug("\xBB no includeIf credential entries to remove");
|
|
154841
|
-
return;
|
|
154842
|
-
}
|
|
154843
|
-
const seen = /* @__PURE__ */ new Set();
|
|
154844
|
-
for (const entry of configOutput.split("\0")) {
|
|
154845
|
-
if (!entry) continue;
|
|
154846
|
-
const nl = entry.indexOf("\n");
|
|
154847
|
-
const key = nl === -1 ? entry : entry.slice(0, nl);
|
|
154848
|
-
if (!key || seen.has(key)) continue;
|
|
154849
|
-
seen.add(key);
|
|
154850
|
-
try {
|
|
154851
|
-
execFileSync5("git", ["config", "--local", "--unset-all", key], {
|
|
154852
|
-
cwd: repoDir,
|
|
154853
|
-
stdio: "pipe",
|
|
154854
|
-
env: env2
|
|
154855
|
-
});
|
|
154856
|
-
} catch (error49) {
|
|
154857
|
-
log.debug(
|
|
154858
|
-
`\xBB failed to unset ${key}: ${error49 instanceof Error ? error49.message : String(error49)}`
|
|
154859
|
-
);
|
|
154860
|
-
}
|
|
154861
|
-
}
|
|
154862
|
-
if (seen.size > 0)
|
|
154863
|
-
log.info(
|
|
154864
|
-
`\xBB removed ${seen.size} includeIf credential ${seen.size === 1 ? "entry" : "entries"}`
|
|
154865
|
-
);
|
|
154866
|
-
}
|
|
154867
|
-
async function setupGit(params) {
|
|
154868
|
-
const repoDir = process.cwd();
|
|
154869
|
-
log.info("\xBB setting up git configuration...");
|
|
154870
|
-
try {
|
|
154871
|
-
let currentEmail = "";
|
|
154872
|
-
try {
|
|
154873
|
-
currentEmail = execSync3("git config user.email", {
|
|
154874
|
-
cwd: repoDir,
|
|
154875
|
-
stdio: "pipe",
|
|
154876
|
-
encoding: "utf-8"
|
|
154877
|
-
}).trim();
|
|
154878
|
-
} catch {
|
|
154879
|
-
}
|
|
154880
|
-
const shouldSetDefaults = !currentEmail || currentEmail === "github-actions[bot]@users.noreply.github.com";
|
|
154881
|
-
if (shouldSetDefaults) {
|
|
154882
|
-
execSync3('git config --local user.email "226033991+pullfrog[bot]@users.noreply.github.com"', {
|
|
154883
|
-
cwd: repoDir,
|
|
154884
|
-
stdio: "pipe"
|
|
154885
|
-
});
|
|
154886
|
-
execSync3('git config --local user.name "pullfrog[bot]"', {
|
|
154887
|
-
cwd: repoDir,
|
|
154888
|
-
stdio: "pipe"
|
|
154889
|
-
});
|
|
154890
|
-
log.debug("\xBB git user configured (using defaults)");
|
|
154891
|
-
} else {
|
|
154892
|
-
log.debug(`\xBB git user already configured (${currentEmail}), skipping`);
|
|
154893
|
-
}
|
|
154894
|
-
if (params.shell === "disabled") {
|
|
154895
|
-
execSync3("git config --local core.hooksPath /dev/null", {
|
|
154896
|
-
cwd: repoDir,
|
|
154897
|
-
stdio: "pipe"
|
|
154898
|
-
});
|
|
154899
|
-
log.debug("\xBB git hooks disabled (shell=disabled)");
|
|
154900
|
-
}
|
|
154901
|
-
} catch (error49) {
|
|
154902
|
-
log.info(`Failed to set git config: ${error49 instanceof Error ? error49.message : String(error49)}`);
|
|
154903
|
-
}
|
|
154904
|
-
try {
|
|
154905
|
-
execSync3("git config --local --unset-all http.https://github.com/.extraheader", {
|
|
154906
|
-
cwd: repoDir,
|
|
154907
|
-
stdio: "pipe"
|
|
154908
|
-
});
|
|
154909
|
-
log.info("\xBB removed existing authentication headers");
|
|
154910
|
-
} catch {
|
|
154911
|
-
log.debug("\xBB no existing authentication headers to remove");
|
|
154912
|
-
}
|
|
154913
|
-
removeIncludeIfEntries(repoDir);
|
|
154914
|
-
const originUrl = `https://github.com/${params.owner}/${params.name}.git`;
|
|
154915
|
-
$("git", ["remote", "set-url", "origin", originUrl], { cwd: repoDir });
|
|
154916
|
-
params.toolState.pushUrl = originUrl;
|
|
154917
|
-
$("git", ["config", "--local", "credential.helper", ""], { cwd: repoDir });
|
|
154918
|
-
log.info("\xBB git authentication configured");
|
|
154919
|
-
}
|
|
154920
|
-
|
|
154921
155222
|
// utils/todoTracking.ts
|
|
154922
155223
|
function isValidTodoStatus(value2) {
|
|
154923
155224
|
return value2 === "pending" || value2 === "in_progress" || value2 === "completed" || value2 === "cancelled";
|
|
@@ -155125,6 +155426,7 @@ async function main() {
|
|
|
155125
155426
|
toolState.beforeSha = payload.event.before_sha;
|
|
155126
155427
|
}
|
|
155127
155428
|
const tokenRef = __using(_stack2, await resolveTokens({ push: payload.push }), true);
|
|
155429
|
+
wipeRunnerLeakSurface();
|
|
155128
155430
|
const oidcCredentials = process.env.ACTIONS_ID_TOKEN_REQUEST_URL && process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN ? {
|
|
155129
155431
|
requestUrl: process.env.ACTIONS_ID_TOKEN_REQUEST_URL,
|
|
155130
155432
|
requestToken: process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN
|
|
@@ -155146,6 +155448,7 @@ async function main() {
|
|
|
155146
155448
|
let toolContext;
|
|
155147
155449
|
let progressCallbackDisabled = false;
|
|
155148
155450
|
let todoTracker;
|
|
155451
|
+
let vertexCredentials;
|
|
155149
155452
|
try {
|
|
155150
155453
|
var _stack = [];
|
|
155151
155454
|
try {
|
|
@@ -155180,6 +155483,7 @@ async function main() {
|
|
|
155180
155483
|
);
|
|
155181
155484
|
toolState.modelFallback = { from: fallback.from };
|
|
155182
155485
|
}
|
|
155486
|
+
vertexCredentials = materializeVertexCredentials({ model: resolvedModel });
|
|
155183
155487
|
const agent2 = resolveAgent({ model: resolvedModel });
|
|
155184
155488
|
toolState.model = payload.proxyModel ?? resolvedModel ?? effectiveSlug;
|
|
155185
155489
|
validateAgentApiKey({
|
|
@@ -155291,8 +155595,8 @@ ${instructions.user}` : null,
|
|
|
155291
155595
|
log.info(instructions.full);
|
|
155292
155596
|
});
|
|
155293
155597
|
if (agentId === "opencode") {
|
|
155294
|
-
const pluginDir =
|
|
155295
|
-
const hasPlugins = existsSync7(pluginDir) &&
|
|
155598
|
+
const pluginDir = join19(process.cwd(), ".opencode", "plugin");
|
|
155599
|
+
const hasPlugins = existsSync7(pluginDir) && readdirSync2(pluginDir).some((f) => /\.[jt]sx?$/.test(f));
|
|
155296
155600
|
if (hasPlugins && toolState.dependencyInstallation?.promise) {
|
|
155297
155601
|
log.info(
|
|
155298
155602
|
"\xBB .opencode/plugin/ detected \u2014 awaiting dependency installation before agent start"
|
|
@@ -155347,6 +155651,7 @@ ${instructions.user}` : null,
|
|
|
155347
155651
|
resolvedModel,
|
|
155348
155652
|
mcpServerUrl: mcpHttpServer.url,
|
|
155349
155653
|
tmpdir: tmpdir3,
|
|
155654
|
+
secretDenyPaths: vertexCredentials ? [vertexCredentials.secretDir] : [],
|
|
155350
155655
|
instructions,
|
|
155351
155656
|
todoTracker,
|
|
155352
155657
|
stopScript: runContext.repoSettings.stopScript,
|
|
@@ -155450,6 +155755,7 @@ ${instructions.user}` : null,
|
|
|
155450
155755
|
await patchWorkflowRunFields(toolContext, patch);
|
|
155451
155756
|
}
|
|
155452
155757
|
}
|
|
155758
|
+
cleanupVertexCredentials(vertexCredentials);
|
|
155453
155759
|
}
|
|
155454
155760
|
} catch (_2) {
|
|
155455
155761
|
var _error2 = _2, _hasError2 = true;
|