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/cli.mjs
CHANGED
|
@@ -97748,14 +97748,14 @@ var require_turndown_cjs = __commonJS({
|
|
|
97748
97748
|
} else if (node2.nodeType === 1) {
|
|
97749
97749
|
replacement = replacementForNode.call(self2, node2);
|
|
97750
97750
|
}
|
|
97751
|
-
return
|
|
97751
|
+
return join21(output, replacement);
|
|
97752
97752
|
}, "");
|
|
97753
97753
|
}
|
|
97754
97754
|
function postProcess(output) {
|
|
97755
97755
|
var self2 = this;
|
|
97756
97756
|
this.rules.forEach(function(rule) {
|
|
97757
97757
|
if (typeof rule.append === "function") {
|
|
97758
|
-
output =
|
|
97758
|
+
output = join21(output, rule.append(self2.options));
|
|
97759
97759
|
}
|
|
97760
97760
|
});
|
|
97761
97761
|
return output.replace(/^[\t\r\n]+/, "").replace(/[\t\r\n\s]+$/, "");
|
|
@@ -97767,7 +97767,7 @@ var require_turndown_cjs = __commonJS({
|
|
|
97767
97767
|
if (whitespace.leading || whitespace.trailing) content = content.trim();
|
|
97768
97768
|
return whitespace.leading + rule.replacement(content, node2, this.options) + whitespace.trailing;
|
|
97769
97769
|
}
|
|
97770
|
-
function
|
|
97770
|
+
function join21(output, replacement) {
|
|
97771
97771
|
var s1 = trimTrailingNewlines(output);
|
|
97772
97772
|
var s2 = trimLeadingNewlines(replacement);
|
|
97773
97773
|
var nls = Math.max(output.length - s1.length, replacement.length - s2.length);
|
|
@@ -100664,9 +100664,9 @@ var import_arg2 = __toESM(require_arg(), 1);
|
|
|
100664
100664
|
import { dirname as dirname6 } from "node:path";
|
|
100665
100665
|
|
|
100666
100666
|
// main.ts
|
|
100667
|
-
import { existsSync as existsSync7, readdirSync } from "node:fs";
|
|
100667
|
+
import { existsSync as existsSync7, readdirSync as readdirSync2 } from "node:fs";
|
|
100668
100668
|
import { readFile as readFile4 } from "node:fs/promises";
|
|
100669
|
-
import { join as
|
|
100669
|
+
import { join as join20 } from "node:path";
|
|
100670
100670
|
|
|
100671
100671
|
// node_modules/.pnpm/@ark+util@0.56.0/node_modules/@ark/util/out/arrays.js
|
|
100672
100672
|
var liftArray = (data) => Array.isArray(data) ? data : [data];
|
|
@@ -109727,6 +109727,11 @@ var providers = {
|
|
|
109727
109727
|
resolve: "opencode/kimi-k2.6",
|
|
109728
109728
|
openRouterResolve: "openrouter/moonshotai/kimi-k2.6"
|
|
109729
109729
|
},
|
|
109730
|
+
"minimax-m2.5": {
|
|
109731
|
+
displayName: "MiniMax M2.5",
|
|
109732
|
+
resolve: "opencode/minimax-m2.5",
|
|
109733
|
+
openRouterResolve: "openrouter/minimax/minimax-m2.5"
|
|
109734
|
+
},
|
|
109730
109735
|
"gpt-5-nano": {
|
|
109731
109736
|
displayName: "GPT Nano",
|
|
109732
109737
|
resolve: "opencode/gpt-5-nano",
|
|
@@ -109743,7 +109748,9 @@ var providers = {
|
|
|
109743
109748
|
displayName: "MiniMax M2.5",
|
|
109744
109749
|
resolve: "opencode/minimax-m2.5-free",
|
|
109745
109750
|
envVars: [],
|
|
109746
|
-
isFree: true
|
|
109751
|
+
isFree: true,
|
|
109752
|
+
fallback: "opencode/big-pickle",
|
|
109753
|
+
hidden: true
|
|
109747
109754
|
}
|
|
109748
109755
|
}
|
|
109749
109756
|
}),
|
|
@@ -109761,6 +109768,25 @@ var providers = {
|
|
|
109761
109768
|
}
|
|
109762
109769
|
}
|
|
109763
109770
|
}),
|
|
109771
|
+
vertex: provider({
|
|
109772
|
+
displayName: "Google Vertex AI",
|
|
109773
|
+
envVars: [
|
|
109774
|
+
"VERTEX_SERVICE_ACCOUNT_JSON",
|
|
109775
|
+
"GOOGLE_CLOUD_PROJECT",
|
|
109776
|
+
"VERTEX_LOCATION",
|
|
109777
|
+
"VERTEX_MODEL_ID"
|
|
109778
|
+
],
|
|
109779
|
+
models: {
|
|
109780
|
+
// single routing entry — the actual Vertex AI model ID is read from
|
|
109781
|
+
// VERTEX_MODEL_ID at run time. see ModelRouting docs for why we don't
|
|
109782
|
+
// catalog individual Vertex models.
|
|
109783
|
+
byok: {
|
|
109784
|
+
displayName: "Google Vertex AI",
|
|
109785
|
+
resolve: "vertex",
|
|
109786
|
+
routing: "vertex"
|
|
109787
|
+
}
|
|
109788
|
+
}
|
|
109789
|
+
}),
|
|
109764
109790
|
openrouter: provider({
|
|
109765
109791
|
displayName: "OpenRouter",
|
|
109766
109792
|
envVars: ["OPENROUTER_API_KEY"],
|
|
@@ -109862,6 +109888,11 @@ var providers = {
|
|
|
109862
109888
|
displayName: "Kimi K2",
|
|
109863
109889
|
resolve: "openrouter/moonshotai/kimi-k2.6",
|
|
109864
109890
|
openRouterResolve: "openrouter/moonshotai/kimi-k2.6"
|
|
109891
|
+
},
|
|
109892
|
+
"minimax-m2.5": {
|
|
109893
|
+
displayName: "MiniMax M2.5",
|
|
109894
|
+
resolve: "openrouter/minimax/minimax-m2.5",
|
|
109895
|
+
openRouterResolve: "openrouter/minimax/minimax-m2.5"
|
|
109865
109896
|
}
|
|
109866
109897
|
}
|
|
109867
109898
|
})
|
|
@@ -109906,6 +109937,11 @@ var modelAliases = Object.entries(providers).flatMap(
|
|
|
109906
109937
|
hidden: def.hidden ?? false
|
|
109907
109938
|
}))
|
|
109908
109939
|
);
|
|
109940
|
+
var defaultProxyAlias = modelAliases.find((a) => a.slug === "moonshotai/kimi-k2");
|
|
109941
|
+
if (!defaultProxyAlias?.openRouterResolve) {
|
|
109942
|
+
throw new Error("DEFAULT_PROXY_MODEL: moonshotai/kimi-k2 missing openRouterResolve");
|
|
109943
|
+
}
|
|
109944
|
+
var DEFAULT_PROXY_MODEL = defaultProxyAlias.openRouterResolve;
|
|
109909
109945
|
var MAX_FALLBACK_DEPTH = 10;
|
|
109910
109946
|
function resolveDisplayAlias(slug2) {
|
|
109911
109947
|
let current = slug2;
|
|
@@ -109924,9 +109960,13 @@ function resolveCliModel(slug2) {
|
|
|
109924
109960
|
return resolveDisplayAlias(slug2)?.resolve;
|
|
109925
109961
|
}
|
|
109926
109962
|
var BEDROCK_MODEL_ID_ENV = "BEDROCK_MODEL_ID";
|
|
109963
|
+
var VERTEX_MODEL_ID_ENV = "VERTEX_MODEL_ID";
|
|
109927
109964
|
function isBedrockAnthropicId(bedrockModelId) {
|
|
109928
109965
|
return bedrockModelId.toLowerCase().split(/[./:]/).includes("anthropic");
|
|
109929
109966
|
}
|
|
109967
|
+
function isVertexAnthropicId(vertexModelId) {
|
|
109968
|
+
return /^claude-/i.test(vertexModelId.trim());
|
|
109969
|
+
}
|
|
109930
109970
|
|
|
109931
109971
|
// utils/buildPullfrogFooter.ts
|
|
109932
109972
|
var PULLFROG_DIVIDER = "<!-- PULLFROG_DIVIDER_DO_NOT_REMOVE_PLZ -->";
|
|
@@ -144209,7 +144249,7 @@ var import_semver = __toESM(require_semver2(), 1);
|
|
|
144209
144249
|
// package.json
|
|
144210
144250
|
var package_default = {
|
|
144211
144251
|
name: "pullfrog",
|
|
144212
|
-
version: "0.1.
|
|
144252
|
+
version: "0.1.12",
|
|
144213
144253
|
type: "module",
|
|
144214
144254
|
bin: {
|
|
144215
144255
|
pullfrog: "dist/cli.mjs",
|
|
@@ -144407,8 +144447,8 @@ function closeBrowserDaemon(toolState) {
|
|
|
144407
144447
|
|
|
144408
144448
|
// mcp/checkout.ts
|
|
144409
144449
|
import { createHash as createHash2 } from "node:crypto";
|
|
144410
|
-
import { statSync, unlinkSync as
|
|
144411
|
-
import { join as
|
|
144450
|
+
import { statSync, unlinkSync as unlinkSync3, writeFileSync as writeFileSync2 } from "node:fs";
|
|
144451
|
+
import { join as join5 } from "node:path";
|
|
144412
144452
|
|
|
144413
144453
|
// utils/diffCoverage.ts
|
|
144414
144454
|
import { isAbsolute, normalize as normalize2, resolve } from "node:path";
|
|
@@ -145920,6 +145960,183 @@ async function reportReviewNodeId(ctx, params) {
|
|
|
145920
145960
|
await patchWorkflowRunFields(ctx, { reviewNodeId: params.nodeId });
|
|
145921
145961
|
}
|
|
145922
145962
|
|
|
145963
|
+
// utils/setup.ts
|
|
145964
|
+
import { execFileSync as execFileSync4, execSync as execSync2 } from "node:child_process";
|
|
145965
|
+
import { mkdtempSync as mkdtempSync2, readdirSync, realpathSync as realpathSync2, unlinkSync as unlinkSync2 } from "node:fs";
|
|
145966
|
+
import { tmpdir as tmpdir2 } from "node:os";
|
|
145967
|
+
import { join as join4 } from "node:path";
|
|
145968
|
+
function createTempDirectory() {
|
|
145969
|
+
const sharedTempDir = mkdtempSync2(join4(tmpdir2(), "pullfrog-"));
|
|
145970
|
+
process.env.PULLFROG_TEMP_DIR = sharedTempDir;
|
|
145971
|
+
log.info(`\xBB created temp dir at ${sharedTempDir}`);
|
|
145972
|
+
return sharedTempDir;
|
|
145973
|
+
}
|
|
145974
|
+
function wipeRunnerLeakSurface() {
|
|
145975
|
+
const runnerTemp = process.env.RUNNER_TEMP;
|
|
145976
|
+
if (!runnerTemp) return;
|
|
145977
|
+
const preserve = /* @__PURE__ */ new Set();
|
|
145978
|
+
for (const envVar of [
|
|
145979
|
+
"GITHUB_OUTPUT",
|
|
145980
|
+
"GITHUB_ENV",
|
|
145981
|
+
"GITHUB_PATH",
|
|
145982
|
+
"GITHUB_STATE",
|
|
145983
|
+
"GITHUB_STEP_SUMMARY"
|
|
145984
|
+
]) {
|
|
145985
|
+
const path3 = process.env[envVar];
|
|
145986
|
+
if (!path3) continue;
|
|
145987
|
+
try {
|
|
145988
|
+
preserve.add(realpathSync2(path3));
|
|
145989
|
+
} catch {
|
|
145990
|
+
preserve.add(path3);
|
|
145991
|
+
}
|
|
145992
|
+
}
|
|
145993
|
+
const wiped = [];
|
|
145994
|
+
const tryUnlink = (path3) => {
|
|
145995
|
+
let resolved = path3;
|
|
145996
|
+
try {
|
|
145997
|
+
resolved = realpathSync2(path3);
|
|
145998
|
+
} catch {
|
|
145999
|
+
}
|
|
146000
|
+
if (preserve.has(resolved) || preserve.has(path3)) return;
|
|
146001
|
+
try {
|
|
146002
|
+
unlinkSync2(path3);
|
|
146003
|
+
wiped.push(path3);
|
|
146004
|
+
} catch {
|
|
146005
|
+
}
|
|
146006
|
+
};
|
|
146007
|
+
const listDir = (dir) => {
|
|
146008
|
+
try {
|
|
146009
|
+
return readdirSync(dir);
|
|
146010
|
+
} catch {
|
|
146011
|
+
return [];
|
|
146012
|
+
}
|
|
146013
|
+
};
|
|
146014
|
+
const fileCommandsDir = join4(runnerTemp, "_runner_file_commands");
|
|
146015
|
+
for (const entry of listDir(fileCommandsDir)) {
|
|
146016
|
+
tryUnlink(join4(fileCommandsDir, entry));
|
|
146017
|
+
}
|
|
146018
|
+
for (const entry of listDir(runnerTemp)) {
|
|
146019
|
+
if (entry.endsWith(".sh") || /^git-credentials-.*\.config$/.test(entry)) {
|
|
146020
|
+
tryUnlink(join4(runnerTemp, entry));
|
|
146021
|
+
}
|
|
146022
|
+
}
|
|
146023
|
+
if (wiped.length > 0) {
|
|
146024
|
+
log.info(`\xBB wiped ${wiped.length} leak-surface file(s) from $RUNNER_TEMP`);
|
|
146025
|
+
log.debug(`\xBB wiped paths: ${wiped.join(", ")}`);
|
|
146026
|
+
}
|
|
146027
|
+
}
|
|
146028
|
+
function envScopedToRepo() {
|
|
146029
|
+
const scoped = { ...process.env };
|
|
146030
|
+
for (const key of Object.keys(scoped)) {
|
|
146031
|
+
if (key.startsWith("GIT_")) delete scoped[key];
|
|
146032
|
+
}
|
|
146033
|
+
return scoped;
|
|
146034
|
+
}
|
|
146035
|
+
function removeIncludeIfEntries(repoDir) {
|
|
146036
|
+
const env2 = envScopedToRepo();
|
|
146037
|
+
let configOutput;
|
|
146038
|
+
try {
|
|
146039
|
+
configOutput = execSync2("git config --local --get-regexp -z ^includeif\\.", {
|
|
146040
|
+
cwd: repoDir,
|
|
146041
|
+
encoding: "utf-8",
|
|
146042
|
+
stdio: "pipe",
|
|
146043
|
+
env: env2
|
|
146044
|
+
});
|
|
146045
|
+
} catch {
|
|
146046
|
+
log.debug("\xBB no includeIf credential entries to remove");
|
|
146047
|
+
return;
|
|
146048
|
+
}
|
|
146049
|
+
const seen = /* @__PURE__ */ new Set();
|
|
146050
|
+
for (const entry of configOutput.split("\0")) {
|
|
146051
|
+
if (!entry) continue;
|
|
146052
|
+
const nl = entry.indexOf("\n");
|
|
146053
|
+
const key = nl === -1 ? entry : entry.slice(0, nl);
|
|
146054
|
+
if (!key || seen.has(key)) continue;
|
|
146055
|
+
seen.add(key);
|
|
146056
|
+
try {
|
|
146057
|
+
execFileSync4("git", ["config", "--local", "--unset-all", key], {
|
|
146058
|
+
cwd: repoDir,
|
|
146059
|
+
stdio: "pipe",
|
|
146060
|
+
env: env2
|
|
146061
|
+
});
|
|
146062
|
+
} catch (error49) {
|
|
146063
|
+
log.debug(
|
|
146064
|
+
`\xBB failed to unset ${key}: ${error49 instanceof Error ? error49.message : String(error49)}`
|
|
146065
|
+
);
|
|
146066
|
+
}
|
|
146067
|
+
}
|
|
146068
|
+
if (seen.size > 0)
|
|
146069
|
+
log.info(
|
|
146070
|
+
`\xBB removed ${seen.size} includeIf credential ${seen.size === 1 ? "entry" : "entries"}`
|
|
146071
|
+
);
|
|
146072
|
+
}
|
|
146073
|
+
async function setupGit(params) {
|
|
146074
|
+
const repoDir = process.cwd();
|
|
146075
|
+
log.info("\xBB setting up git configuration...");
|
|
146076
|
+
try {
|
|
146077
|
+
let currentEmail = "";
|
|
146078
|
+
try {
|
|
146079
|
+
currentEmail = execSync2("git config user.email", {
|
|
146080
|
+
cwd: repoDir,
|
|
146081
|
+
stdio: "pipe",
|
|
146082
|
+
encoding: "utf-8"
|
|
146083
|
+
}).trim();
|
|
146084
|
+
} catch {
|
|
146085
|
+
}
|
|
146086
|
+
const shouldSetDefaults = !currentEmail || currentEmail === "github-actions[bot]@users.noreply.github.com";
|
|
146087
|
+
if (shouldSetDefaults) {
|
|
146088
|
+
execSync2('git config --local user.email "226033991+pullfrog[bot]@users.noreply.github.com"', {
|
|
146089
|
+
cwd: repoDir,
|
|
146090
|
+
stdio: "pipe"
|
|
146091
|
+
});
|
|
146092
|
+
execSync2('git config --local user.name "pullfrog[bot]"', {
|
|
146093
|
+
cwd: repoDir,
|
|
146094
|
+
stdio: "pipe"
|
|
146095
|
+
});
|
|
146096
|
+
log.debug("\xBB git user configured (using defaults)");
|
|
146097
|
+
} else {
|
|
146098
|
+
log.debug(`\xBB git user already configured (${currentEmail}), skipping`);
|
|
146099
|
+
}
|
|
146100
|
+
if (params.shell === "disabled") {
|
|
146101
|
+
execSync2("git config --local core.hooksPath /dev/null", {
|
|
146102
|
+
cwd: repoDir,
|
|
146103
|
+
stdio: "pipe"
|
|
146104
|
+
});
|
|
146105
|
+
log.debug("\xBB git hooks disabled (shell=disabled)");
|
|
146106
|
+
}
|
|
146107
|
+
} catch (error49) {
|
|
146108
|
+
log.info(`Failed to set git config: ${error49 instanceof Error ? error49.message : String(error49)}`);
|
|
146109
|
+
}
|
|
146110
|
+
try {
|
|
146111
|
+
execSync2("git config --local --unset-all http.https://github.com/.extraheader", {
|
|
146112
|
+
cwd: repoDir,
|
|
146113
|
+
stdio: "pipe"
|
|
146114
|
+
});
|
|
146115
|
+
log.info("\xBB removed existing authentication headers");
|
|
146116
|
+
} catch {
|
|
146117
|
+
log.debug("\xBB no existing authentication headers to remove");
|
|
146118
|
+
}
|
|
146119
|
+
removeIncludeIfEntries(repoDir);
|
|
146120
|
+
const originUrl = `https://github.com/${params.owner}/${params.name}.git`;
|
|
146121
|
+
$2("git", ["remote", "set-url", "origin", originUrl], { cwd: repoDir });
|
|
146122
|
+
params.toolState.pushUrl = originUrl;
|
|
146123
|
+
$2("git", ["config", "--local", "credential.helper", ""], { cwd: repoDir });
|
|
146124
|
+
params.toolState.initialHead = captureInitialHead(repoDir);
|
|
146125
|
+
log.info("\xBB git authentication configured");
|
|
146126
|
+
}
|
|
146127
|
+
function captureInitialHead(repoDir) {
|
|
146128
|
+
try {
|
|
146129
|
+
const name = $2("git", ["symbolic-ref", "--short", "HEAD"], {
|
|
146130
|
+
cwd: repoDir,
|
|
146131
|
+
log: false
|
|
146132
|
+
}).trim();
|
|
146133
|
+
if (name) return { kind: "branch", name };
|
|
146134
|
+
} catch {
|
|
146135
|
+
}
|
|
146136
|
+
const sha = $2("git", ["rev-parse", "HEAD"], { cwd: repoDir, log: false }).trim();
|
|
146137
|
+
return { kind: "detached", sha };
|
|
146138
|
+
}
|
|
146139
|
+
|
|
145923
146140
|
// mcp/checkout.ts
|
|
145924
146141
|
function formatFilesWithLineNumbers(files) {
|
|
145925
146142
|
const output = [];
|
|
@@ -146094,7 +146311,7 @@ function cleanupStaleGitLocks() {
|
|
|
146094
146311
|
}
|
|
146095
146312
|
if (now - mtimeMs < STALE_LOCK_AGE_MS) continue;
|
|
146096
146313
|
try {
|
|
146097
|
-
|
|
146314
|
+
unlinkSync3(relPath);
|
|
146098
146315
|
log.warning(`\xBB removed stale ${relPath} from prior run`);
|
|
146099
146316
|
} catch (e) {
|
|
146100
146317
|
log.debug(
|
|
@@ -146253,6 +146470,15 @@ async function checkoutPrBranch(pr, params) {
|
|
|
146253
146470
|
return { hookWarning: postCheckoutHook.warning };
|
|
146254
146471
|
}
|
|
146255
146472
|
var inFlightCheckouts = /* @__PURE__ */ new Map();
|
|
146473
|
+
function headsEqual(a, b) {
|
|
146474
|
+
if (a.kind === "branch" && b.kind === "branch") return a.name === b.name;
|
|
146475
|
+
if (a.kind === "detached" && b.kind === "detached") return a.sha === b.sha;
|
|
146476
|
+
return false;
|
|
146477
|
+
}
|
|
146478
|
+
function describeHead(h) {
|
|
146479
|
+
if (h.kind === "branch") return `branch \`${h.name}\``;
|
|
146480
|
+
return `detached HEAD \`${h.sha}\``;
|
|
146481
|
+
}
|
|
146256
146482
|
function CheckoutPrTool(ctx) {
|
|
146257
146483
|
const runCheckout = async (pull_number) => {
|
|
146258
146484
|
const prResponse = await ctx.octokit.rest.pulls.get({
|
|
@@ -146299,7 +146525,7 @@ function CheckoutPrTool(ctx) {
|
|
|
146299
146525
|
headSha: ctx.toolState.checkoutSha
|
|
146300
146526
|
});
|
|
146301
146527
|
if (incremental) {
|
|
146302
|
-
incrementalDiffPath =
|
|
146528
|
+
incrementalDiffPath = join5(
|
|
146303
146529
|
tempDir,
|
|
146304
146530
|
`pr-${pull_number}-${beforeShort}-${headShort}-incremental.diff`
|
|
146305
146531
|
);
|
|
@@ -146313,7 +146539,7 @@ function CheckoutPrTool(ctx) {
|
|
|
146313
146539
|
const diffPreview = formatResult.content.split("\n").slice(0, 100).join("\n");
|
|
146314
146540
|
log.debug(`formatted diff preview (first 100 lines):
|
|
146315
146541
|
${diffPreview}`);
|
|
146316
|
-
const diffPath =
|
|
146542
|
+
const diffPath = join5(tempDir, `pr-${pull_number}-${headShort}.diff`);
|
|
146317
146543
|
writeFileSync2(diffPath, formatResult.content);
|
|
146318
146544
|
log.debug(`wrote diff to ${diffPath} (${formatResult.content.length} bytes)`);
|
|
146319
146545
|
ctx.toolState.diffCoverage = createDiffCoverageState({
|
|
@@ -146380,7 +146606,8 @@ ${diffPreview}`);
|
|
|
146380
146606
|
};
|
|
146381
146607
|
return tool({
|
|
146382
146608
|
name: "checkout_pr",
|
|
146383
|
-
|
|
146609
|
+
timeoutMs: 6e5,
|
|
146610
|
+
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.",
|
|
146384
146611
|
parameters: CheckoutPr,
|
|
146385
146612
|
execute: execute(async ({ pull_number }) => {
|
|
146386
146613
|
const inFlight = inFlightCheckouts.get(pull_number);
|
|
@@ -146388,13 +146615,23 @@ ${diffPreview}`);
|
|
|
146388
146615
|
log.info(`\xBB checkout_pr({pull_number:${pull_number}}) already in flight \u2014 sharing result`);
|
|
146389
146616
|
return inFlight;
|
|
146390
146617
|
}
|
|
146391
|
-
const
|
|
146392
|
-
if (
|
|
146393
|
-
|
|
146394
|
-
|
|
146395
|
-
throw new Error(
|
|
146396
|
-
`cannot checkout PR #${pull_number} while the working tree has uncommitted changes. commit, push, or discard them before switching. dirty paths:
|
|
146618
|
+
const dirty = $2("git", ["status", "--porcelain"], { log: false }).trim();
|
|
146619
|
+
if (dirty) {
|
|
146620
|
+
throw new Error(
|
|
146621
|
+
`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:
|
|
146397
146622
|
${dirty}`
|
|
146623
|
+
);
|
|
146624
|
+
}
|
|
146625
|
+
const initialHead = ctx.toolState.initialHead;
|
|
146626
|
+
if (initialHead) {
|
|
146627
|
+
const currentHead = captureInitialHead(process.cwd());
|
|
146628
|
+
const targetBranch = `pr-${pull_number}`;
|
|
146629
|
+
const onTarget = currentHead.kind === "branch" && currentHead.name === targetBranch;
|
|
146630
|
+
const onInitial = headsEqual(currentHead, initialHead);
|
|
146631
|
+
if (!onTarget && !onInitial) {
|
|
146632
|
+
const recoverCmd = initialHead.kind === "branch" ? `git checkout ${initialHead.name}` : `git checkout ${initialHead.sha}`;
|
|
146633
|
+
throw new Error(
|
|
146634
|
+
`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.`
|
|
146398
146635
|
);
|
|
146399
146636
|
}
|
|
146400
146637
|
}
|
|
@@ -146411,7 +146648,7 @@ ${dirty}`
|
|
|
146411
146648
|
|
|
146412
146649
|
// mcp/checkSuite.ts
|
|
146413
146650
|
import { mkdirSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
146414
|
-
import { join as
|
|
146651
|
+
import { join as join6 } from "node:path";
|
|
146415
146652
|
var GetCheckSuiteLogs = type({
|
|
146416
146653
|
check_suite_id: type.number.describe("the id from check_suite.id")
|
|
146417
146654
|
});
|
|
@@ -146507,7 +146744,7 @@ function GetCheckSuiteLogsTool(ctx) {
|
|
|
146507
146744
|
if (!tempDir) {
|
|
146508
146745
|
throw new Error("PULLFROG_TEMP_DIR not set");
|
|
146509
146746
|
}
|
|
146510
|
-
const logsDir =
|
|
146747
|
+
const logsDir = join6(tempDir, "ci-logs");
|
|
146511
146748
|
mkdirSync(logsDir, { recursive: true });
|
|
146512
146749
|
const jobResults = [];
|
|
146513
146750
|
for (const run4 of failedRuns) {
|
|
@@ -146534,7 +146771,7 @@ function GetCheckSuiteLogsTool(ctx) {
|
|
|
146534
146771
|
);
|
|
146535
146772
|
}
|
|
146536
146773
|
const logsText = await logsResult.text();
|
|
146537
|
-
const logPath =
|
|
146774
|
+
const logPath = join6(logsDir, `job-${job.id}.log`);
|
|
146538
146775
|
writeFileSync3(logPath, logsText);
|
|
146539
146776
|
const analysis = analyzeLog(logsText, 80);
|
|
146540
146777
|
const failedSteps = job.steps?.filter((s) => s.conclusion === "failure").map((s) => `Step ${s.number}: ${s.name}`) ?? [];
|
|
@@ -146584,7 +146821,7 @@ function GetCheckSuiteLogsTool(ctx) {
|
|
|
146584
146821
|
|
|
146585
146822
|
// mcp/commitInfo.ts
|
|
146586
146823
|
import { writeFileSync as writeFileSync4 } from "node:fs";
|
|
146587
|
-
import { join as
|
|
146824
|
+
import { join as join7 } from "node:path";
|
|
146588
146825
|
var CommitInfo = type({
|
|
146589
146826
|
sha: type.string.describe("the commit SHA (full or abbreviated) to fetch")
|
|
146590
146827
|
});
|
|
@@ -146608,7 +146845,7 @@ function CommitInfoTool(ctx) {
|
|
|
146608
146845
|
"PULLFROG_TEMP_DIR not set - get_commit_info must run in pullfrog action context"
|
|
146609
146846
|
);
|
|
146610
146847
|
}
|
|
146611
|
-
const diffFile =
|
|
146848
|
+
const diffFile = join7(tempDir, `commit-${sha.slice(0, 7)}.diff`);
|
|
146612
146849
|
writeFileSync4(diffFile, formatResult.content);
|
|
146613
146850
|
log.debug(`wrote commit diff to ${diffFile} (${formatResult.content.length} bytes)`);
|
|
146614
146851
|
return {
|
|
@@ -147066,7 +147303,7 @@ function PullRequestInfoTool(ctx) {
|
|
|
147066
147303
|
|
|
147067
147304
|
// mcp/reviewComments.ts
|
|
147068
147305
|
import { writeFileSync as writeFileSync5 } from "node:fs";
|
|
147069
|
-
import { join as
|
|
147306
|
+
import { join as join8 } from "node:path";
|
|
147070
147307
|
var REVIEW_THREADS_QUERY = `
|
|
147071
147308
|
query ($owner: String!, $name: String!, $prNumber: Int!) {
|
|
147072
147309
|
repository(owner: $owner, name: $name) {
|
|
@@ -147458,7 +147695,7 @@ function GetReviewCommentsTool(ctx) {
|
|
|
147458
147695
|
throw new Error("PULLFROG_TEMP_DIR not set");
|
|
147459
147696
|
}
|
|
147460
147697
|
const filename = `review-${params.review_id}-threads.md`;
|
|
147461
|
-
const commentsPath =
|
|
147698
|
+
const commentsPath = join8(tempDir, filename);
|
|
147462
147699
|
writeFileSync5(commentsPath, formatted.content);
|
|
147463
147700
|
log.debug(`wrote ${threadBlocks.length} threads to ${commentsPath}`);
|
|
147464
147701
|
return {
|
|
@@ -147687,7 +147924,7 @@ import { spawn as spawn4, spawnSync as spawnSync3 } from "node:child_process";
|
|
|
147687
147924
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
147688
147925
|
import { closeSync, openSync, writeFileSync as writeFileSync6 } from "node:fs";
|
|
147689
147926
|
import { userInfo } from "node:os";
|
|
147690
|
-
import { join as
|
|
147927
|
+
import { join as join9 } from "node:path";
|
|
147691
147928
|
import { setTimeout as sleep2 } from "node:timers/promises";
|
|
147692
147929
|
var ShellParams = type({
|
|
147693
147930
|
command: "string",
|
|
@@ -147820,7 +148057,7 @@ function getTempDir() {
|
|
|
147820
148057
|
var MAX_OUTPUT_CHARS = 5e3;
|
|
147821
148058
|
function capOutput(output) {
|
|
147822
148059
|
if (output.length <= MAX_OUTPUT_CHARS) return output;
|
|
147823
|
-
const fullPath =
|
|
148060
|
+
const fullPath = join9(getTempDir(), `shell-${randomUUID2().slice(0, 8)}.log`);
|
|
147824
148061
|
writeFileSync6(fullPath, output);
|
|
147825
148062
|
const elided = output.length - MAX_OUTPUT_CHARS;
|
|
147826
148063
|
return `... [${elided} chars truncated; full output saved to ${fullPath}] ...
|
|
@@ -147835,6 +148072,7 @@ function isGitCommand(command) {
|
|
|
147835
148072
|
function ShellTool(ctx) {
|
|
147836
148073
|
return tool({
|
|
147837
148074
|
name: "shell",
|
|
148075
|
+
timeoutMs: 12e4,
|
|
147838
148076
|
description: `Execute shell commands securely. Environment is filtered to remove API keys and secrets.
|
|
147839
148077
|
|
|
147840
148078
|
Example: \`shell({ command: "pnpm test", description: "run the test suite" })\`.
|
|
@@ -147874,8 +148112,8 @@ Do NOT use this tool for git commands \u2014 use the dedicated git tools instead
|
|
|
147874
148112
|
if (params.background) {
|
|
147875
148113
|
const tempDir = getTempDir();
|
|
147876
148114
|
const handle = `bg-${randomUUID2().slice(0, 8)}`;
|
|
147877
|
-
const outputPath =
|
|
147878
|
-
const pidPath =
|
|
148115
|
+
const outputPath = join9(tempDir, `${handle}.log`);
|
|
148116
|
+
const pidPath = join9(tempDir, `${handle}.pid`);
|
|
147879
148117
|
const logFd = openSync(outputPath, "a");
|
|
147880
148118
|
let proc2;
|
|
147881
148119
|
try {
|
|
@@ -148215,6 +148453,8 @@ var REVIEWER_AGENT_NAME = "reviewfrog";
|
|
|
148215
148453
|
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.
|
|
148216
148454
|
|
|
148217
148455
|
HARD CONSTRAINTS (non-negotiable, regardless of orchestrator instructions):
|
|
148456
|
+
- 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.
|
|
148457
|
+
- 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.
|
|
148218
148458
|
- 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).
|
|
148219
148459
|
- 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.
|
|
148220
148460
|
- Do NOT spawn further subagents. You are a leaf reviewer; recursive dispatch pre-aggregates findings through an intermediate model and defeats the design.
|
|
@@ -148405,7 +148645,25 @@ function computeModes(agentId) {
|
|
|
148405
148645
|
|
|
148406
148646
|
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.
|
|
148407
148647
|
|
|
148408
|
-
|
|
148648
|
+
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.
|
|
148649
|
+
|
|
148650
|
+
\`\`\`
|
|
148651
|
+
## What you're reviewing
|
|
148652
|
+
This is a PRE-COMMIT Build-mode self-review. The work to review lives in the working tree (uncommitted), NOT in committed history.
|
|
148653
|
+
|
|
148654
|
+
Branch: <branch> (off <base>)
|
|
148655
|
+
Canonical diff command: git diff origin/<base>
|
|
148656
|
+
|
|
148657
|
+
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.
|
|
148658
|
+
|
|
148659
|
+
## Your task
|
|
148660
|
+
<YOUR TASK content>
|
|
148661
|
+
|
|
148662
|
+
## Build-phase failures
|
|
148663
|
+
<tight summary \u2014 what broke, root cause, the fix \u2014 or "no build-phase failures">
|
|
148664
|
+
\`\`\`
|
|
148665
|
+
|
|
148666
|
+
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.
|
|
148409
148667
|
|
|
148410
148668
|
Delegation + research discipline (distilled from \`/anneal\` canonical \u2014 these are codified learnings from many review rounds, not theoretical best practices):
|
|
148411
148669
|
- Do NOT summarize what you implemented \u2014 that biases the subagent toward validating the shape of your solution rather than questioning it.
|
|
@@ -148804,21 +149062,21 @@ function initToolState(params) {
|
|
|
148804
149062
|
}
|
|
148805
149063
|
|
|
148806
149064
|
// agents/claude.ts
|
|
148807
|
-
import { execFileSync as
|
|
148808
|
-
import { mkdirSync as
|
|
148809
|
-
import { join as
|
|
149065
|
+
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
149066
|
+
import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync9 } from "node:fs";
|
|
149067
|
+
import { join as join13 } from "node:path";
|
|
148810
149068
|
import { performance as performance6 } from "node:perf_hooks";
|
|
148811
149069
|
|
|
148812
149070
|
// utils/install.ts
|
|
148813
149071
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
148814
149072
|
import { chmodSync, createWriteStream, existsSync as existsSync5, mkdirSync as mkdirSync2 } from "node:fs";
|
|
148815
|
-
import { join as
|
|
149073
|
+
import { join as join10 } from "node:path";
|
|
148816
149074
|
import { pipeline } from "node:stream/promises";
|
|
148817
149075
|
async function installFromNpmTarball(params) {
|
|
148818
149076
|
const tempDir = process.env.PULLFROG_TEMP_DIR;
|
|
148819
149077
|
if (!tempDir) throw new Error("PULLFROG_TEMP_DIR is not set");
|
|
148820
|
-
const extractedDir =
|
|
148821
|
-
const cliPath =
|
|
149078
|
+
const extractedDir = join10(tempDir, "package");
|
|
149079
|
+
const cliPath = join10(extractedDir, params.executablePath);
|
|
148822
149080
|
if (existsSync5(cliPath)) {
|
|
148823
149081
|
log.debug(`\xBB using cached binary at ${cliPath}`);
|
|
148824
149082
|
return cliPath;
|
|
@@ -148843,7 +149101,7 @@ async function installFromNpmTarball(params) {
|
|
|
148843
149101
|
}
|
|
148844
149102
|
}
|
|
148845
149103
|
log.debug(`\xBB installing ${params.packageName}@${resolvedVersion}...`);
|
|
148846
|
-
const tarballPath =
|
|
149104
|
+
const tarballPath = join10(tempDir, "package.tgz");
|
|
148847
149105
|
const npmRegistry = process.env.NPM_REGISTRY || "https://registry.npmjs.org";
|
|
148848
149106
|
let tarballUrl;
|
|
148849
149107
|
if (params.packageName.startsWith("@")) {
|
|
@@ -148982,16 +149240,16 @@ function isRouterKeylimitExhaustedError(text) {
|
|
|
148982
149240
|
// utils/skills.ts
|
|
148983
149241
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
148984
149242
|
import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync7 } from "node:fs";
|
|
148985
|
-
import { tmpdir as
|
|
148986
|
-
import { dirname as dirname2, join as
|
|
149243
|
+
import { tmpdir as tmpdir3 } from "node:os";
|
|
149244
|
+
import { dirname as dirname2, join as join11 } from "node:path";
|
|
148987
149245
|
import { fileURLToPath } from "node:url";
|
|
148988
149246
|
var skillsVersion = getDevDependencyVersion("skills");
|
|
148989
149247
|
var BUNDLED_SKILL_NAMES = ["git-archaeology"];
|
|
148990
149248
|
function resolveSkillPath(name) {
|
|
148991
149249
|
const here = dirname2(fileURLToPath(import.meta.url));
|
|
148992
149250
|
const candidates = [
|
|
148993
|
-
|
|
148994
|
-
|
|
149251
|
+
join11(here, "..", "skills", name, "SKILL.md"),
|
|
149252
|
+
join11(here, "skills", name, "SKILL.md")
|
|
148995
149253
|
];
|
|
148996
149254
|
for (const candidate of candidates) {
|
|
148997
149255
|
if (existsSync6(candidate)) return candidate;
|
|
@@ -149003,9 +149261,9 @@ function installBundledSkills(params) {
|
|
|
149003
149261
|
for (const name of BUNDLED_SKILL_NAMES) {
|
|
149004
149262
|
const content = readFileSync5(resolveSkillPath(name), "utf8");
|
|
149005
149263
|
for (const targetDir of SKILL_TARGET_DIRS) {
|
|
149006
|
-
const skillDir =
|
|
149264
|
+
const skillDir = join11(params.home, targetDir, name);
|
|
149007
149265
|
mkdirSync3(skillDir, { recursive: true });
|
|
149008
|
-
writeFileSync7(
|
|
149266
|
+
writeFileSync7(join11(skillDir, "SKILL.md"), content);
|
|
149009
149267
|
}
|
|
149010
149268
|
}
|
|
149011
149269
|
log.success(`installed bundled skills: ${BUNDLED_SKILL_NAMES.join(", ")}`);
|
|
@@ -149026,7 +149284,7 @@ function addSkill(params) {
|
|
|
149026
149284
|
"-y"
|
|
149027
149285
|
],
|
|
149028
149286
|
{
|
|
149029
|
-
cwd:
|
|
149287
|
+
cwd: tmpdir3(),
|
|
149030
149288
|
env: { ...process.env, ...params.env },
|
|
149031
149289
|
stdio: "pipe",
|
|
149032
149290
|
timeout: 3e4
|
|
@@ -149107,6 +149365,71 @@ var ThinkingTimer = class {
|
|
|
149107
149365
|
}
|
|
149108
149366
|
};
|
|
149109
149367
|
|
|
149368
|
+
// utils/vertex.ts
|
|
149369
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
149370
|
+
import { mkdirSync as mkdirSync4, rmSync as rmSync2, writeFileSync as writeFileSync8 } from "node:fs";
|
|
149371
|
+
import { homedir } from "node:os";
|
|
149372
|
+
import { join as join12 } from "node:path";
|
|
149373
|
+
var VERTEX_SERVICE_ACCOUNT_JSON_ENV = "VERTEX_SERVICE_ACCOUNT_JSON";
|
|
149374
|
+
var GOOGLE_APPLICATION_CREDENTIALS_ENV = "GOOGLE_APPLICATION_CREDENTIALS";
|
|
149375
|
+
var GOOGLE_CLOUD_PROJECT_ENV = "GOOGLE_CLOUD_PROJECT";
|
|
149376
|
+
var VERTEX_LOCATION_ENV = "VERTEX_LOCATION";
|
|
149377
|
+
function hasEnvVar(name) {
|
|
149378
|
+
const value2 = process.env[name];
|
|
149379
|
+
return typeof value2 === "string" && value2.length > 0;
|
|
149380
|
+
}
|
|
149381
|
+
function isVertexRoute(model) {
|
|
149382
|
+
const vertexId = process.env[VERTEX_MODEL_ID_ENV]?.trim();
|
|
149383
|
+
return model !== void 0 && vertexId !== void 0 && vertexId === model;
|
|
149384
|
+
}
|
|
149385
|
+
function readProjectIdFromVertexServiceAccountJson() {
|
|
149386
|
+
const blob = process.env[VERTEX_SERVICE_ACCOUNT_JSON_ENV];
|
|
149387
|
+
if (!blob) return void 0;
|
|
149388
|
+
try {
|
|
149389
|
+
const parsed2 = JSON.parse(blob);
|
|
149390
|
+
if (!parsed2 || typeof parsed2 !== "object" || !("project_id" in parsed2)) {
|
|
149391
|
+
return void 0;
|
|
149392
|
+
}
|
|
149393
|
+
const projectId = parsed2.project_id;
|
|
149394
|
+
return typeof projectId === "string" && projectId.length > 0 ? projectId : void 0;
|
|
149395
|
+
} catch {
|
|
149396
|
+
return void 0;
|
|
149397
|
+
}
|
|
149398
|
+
}
|
|
149399
|
+
function createSecretDir() {
|
|
149400
|
+
const base = process.env.PULLFROG_SECRET_HOME || process.env.HOME || homedir();
|
|
149401
|
+
const secretDir = join12(base, ".pullfrog", "secrets", randomUUID3());
|
|
149402
|
+
mkdirSync4(secretDir, { recursive: true, mode: 448 });
|
|
149403
|
+
return secretDir;
|
|
149404
|
+
}
|
|
149405
|
+
function materializeVertexCredentials(params) {
|
|
149406
|
+
if (!isVertexRoute(params.model)) return void 0;
|
|
149407
|
+
const blob = process.env[VERTEX_SERVICE_ACCOUNT_JSON_ENV];
|
|
149408
|
+
if (!blob) return void 0;
|
|
149409
|
+
const secretDir = createSecretDir();
|
|
149410
|
+
const credentialsPath = join12(secretDir, "vertex-sa.json");
|
|
149411
|
+
writeFileSync8(credentialsPath, blob, { mode: 384 });
|
|
149412
|
+
process.env[GOOGLE_APPLICATION_CREDENTIALS_ENV] = credentialsPath;
|
|
149413
|
+
const projectId = readProjectIdFromVertexServiceAccountJson();
|
|
149414
|
+
if (projectId && !hasEnvVar(GOOGLE_CLOUD_PROJECT_ENV)) {
|
|
149415
|
+
process.env[GOOGLE_CLOUD_PROJECT_ENV] = projectId;
|
|
149416
|
+
}
|
|
149417
|
+
return { credentialsPath, secretDir };
|
|
149418
|
+
}
|
|
149419
|
+
function cleanupVertexCredentials(credentials) {
|
|
149420
|
+
if (!credentials) return;
|
|
149421
|
+
rmSync2(credentials.secretDir, { recursive: true, force: true });
|
|
149422
|
+
delete process.env[GOOGLE_APPLICATION_CREDENTIALS_ENV];
|
|
149423
|
+
}
|
|
149424
|
+
function applyClaudeVertexEnv(env2) {
|
|
149425
|
+
env2.CLAUDE_CODE_USE_VERTEX = "1";
|
|
149426
|
+
env2.ANTHROPIC_VERTEX_PROJECT_ID ??= env2[GOOGLE_CLOUD_PROJECT_ENV];
|
|
149427
|
+
env2.CLOUD_ML_REGION ??= env2[VERTEX_LOCATION_ENV];
|
|
149428
|
+
}
|
|
149429
|
+
function resolveVertexOpenCodeModel(model) {
|
|
149430
|
+
return isVertexRoute(model) && model ? `google-vertex/${model}` : void 0;
|
|
149431
|
+
}
|
|
149432
|
+
|
|
149110
149433
|
// agents/postRun.ts
|
|
149111
149434
|
import { readFile } from "node:fs/promises";
|
|
149112
149435
|
function getUnsubmittedReview(toolState) {
|
|
@@ -149410,10 +149733,10 @@ async function installClaudeCli() {
|
|
|
149410
149733
|
});
|
|
149411
149734
|
}
|
|
149412
149735
|
function writeMcpConfig(ctx) {
|
|
149413
|
-
const configDir =
|
|
149414
|
-
|
|
149415
|
-
const configPath =
|
|
149416
|
-
|
|
149736
|
+
const configDir = join13(ctx.tmpdir, ".claude");
|
|
149737
|
+
mkdirSync5(configDir, { recursive: true });
|
|
149738
|
+
const configPath = join13(configDir, "mcp.json");
|
|
149739
|
+
writeFileSync9(
|
|
149417
149740
|
configPath,
|
|
149418
149741
|
JSON.stringify({
|
|
149419
149742
|
mcpServers: {
|
|
@@ -149795,37 +150118,51 @@ ${stderrContext}`
|
|
|
149795
150118
|
var MANAGED_SETTINGS_DIR = "/etc/claude-code";
|
|
149796
150119
|
var MANAGED_SETTINGS_PATH = `${MANAGED_SETTINGS_DIR}/managed-settings.json`;
|
|
149797
150120
|
var CODEX_AUTH_DENY_PATH = "~/.local/share/opencode/auth.json";
|
|
149798
|
-
|
|
149799
|
-
|
|
149800
|
-
|
|
149801
|
-
|
|
149802
|
-
|
|
149803
|
-
|
|
149804
|
-
|
|
149805
|
-
|
|
149806
|
-
|
|
149807
|
-
|
|
149808
|
-
|
|
149809
|
-
|
|
149810
|
-
|
|
149811
|
-
|
|
149812
|
-
|
|
149813
|
-
|
|
149814
|
-
|
|
149815
|
-
|
|
149816
|
-
|
|
149817
|
-
|
|
149818
|
-
|
|
149819
|
-
|
|
150121
|
+
function buildManagedSettings(ctx) {
|
|
150122
|
+
const secretDenyPaths = ctx.secretDenyPaths ?? [];
|
|
150123
|
+
const toolDeny = secretDenyPaths.flatMap((path3) => [
|
|
150124
|
+
`Read(${path3}/**)`,
|
|
150125
|
+
`Read(/${path3}/**)`,
|
|
150126
|
+
`Grep(${path3}/**)`,
|
|
150127
|
+
`Grep(/${path3}/**)`,
|
|
150128
|
+
`Edit(${path3}/**)`,
|
|
150129
|
+
`Edit(/${path3}/**)`,
|
|
150130
|
+
`Glob(${path3}/**)`,
|
|
150131
|
+
`Glob(/${path3}/**)`
|
|
150132
|
+
]);
|
|
150133
|
+
return {
|
|
150134
|
+
allowManagedPermissionRulesOnly: true,
|
|
150135
|
+
allowManagedHooksOnly: true,
|
|
150136
|
+
permissions: {
|
|
150137
|
+
deny: [
|
|
150138
|
+
"Read(//proc/**)",
|
|
150139
|
+
"Read(//sys/**)",
|
|
150140
|
+
"Grep(//proc/**)",
|
|
150141
|
+
"Grep(//sys/**)",
|
|
150142
|
+
"Edit(//proc/**)",
|
|
150143
|
+
"Edit(//sys/**)",
|
|
150144
|
+
"Glob(//proc/**)",
|
|
150145
|
+
"Glob(//sys/**)",
|
|
150146
|
+
`Read(${CODEX_AUTH_DENY_PATH})`,
|
|
150147
|
+
`Grep(${CODEX_AUTH_DENY_PATH})`,
|
|
150148
|
+
`Edit(${CODEX_AUTH_DENY_PATH})`,
|
|
150149
|
+
`Glob(${CODEX_AUTH_DENY_PATH})`,
|
|
150150
|
+
...toolDeny
|
|
150151
|
+
]
|
|
150152
|
+
},
|
|
150153
|
+
sandbox: {
|
|
150154
|
+
filesystem: {
|
|
150155
|
+
denyRead: ["/proc", "/sys", CODEX_AUTH_DENY_PATH, ...secretDenyPaths]
|
|
150156
|
+
}
|
|
149820
150157
|
}
|
|
149821
|
-
}
|
|
149822
|
-
}
|
|
149823
|
-
function installManagedSettings() {
|
|
150158
|
+
};
|
|
150159
|
+
}
|
|
150160
|
+
function installManagedSettings(ctx) {
|
|
149824
150161
|
if (process.env.CI !== "true") return;
|
|
149825
|
-
const content = JSON.stringify(
|
|
150162
|
+
const content = JSON.stringify(buildManagedSettings(ctx), null, 2);
|
|
149826
150163
|
try {
|
|
149827
|
-
|
|
149828
|
-
|
|
150164
|
+
execFileSync5("sudo", ["mkdir", "-p", MANAGED_SETTINGS_DIR]);
|
|
150165
|
+
execFileSync5("sudo", ["tee", MANAGED_SETTINGS_PATH], {
|
|
149829
150166
|
input: content,
|
|
149830
150167
|
stdio: ["pipe", "ignore", "pipe"]
|
|
149831
150168
|
});
|
|
@@ -149842,23 +150179,25 @@ var claude = agent({
|
|
|
149842
150179
|
const specifier = ctx.payload.proxyModel ?? ctx.resolvedModel;
|
|
149843
150180
|
const bedrockModelId = process.env[BEDROCK_MODEL_ID_ENV]?.trim();
|
|
149844
150181
|
const isBedrockRoute = specifier !== void 0 && bedrockModelId !== void 0 && bedrockModelId === specifier && isBedrockAnthropicId(specifier);
|
|
149845
|
-
const
|
|
150182
|
+
const vertexModelId = process.env[VERTEX_MODEL_ID_ENV]?.trim();
|
|
150183
|
+
const isVertexRoute2 = specifier !== void 0 && vertexModelId !== void 0 && vertexModelId === specifier && isVertexAnthropicId(specifier);
|
|
150184
|
+
const model = !specifier ? void 0 : isBedrockRoute ? specifier : isVertexRoute2 ? void 0 : stripProviderPrefix(specifier);
|
|
149846
150185
|
const homeEnv = {
|
|
149847
150186
|
HOME: ctx.tmpdir,
|
|
149848
|
-
XDG_CONFIG_HOME:
|
|
150187
|
+
XDG_CONFIG_HOME: join13(ctx.tmpdir, ".config")
|
|
149849
150188
|
};
|
|
149850
|
-
|
|
150189
|
+
mkdirSync5(join13(homeEnv.XDG_CONFIG_HOME, "claude"), { recursive: true });
|
|
149851
150190
|
const agentBrowserVersion = getDevDependencyVersion("agent-browser");
|
|
149852
150191
|
addSkill({
|
|
149853
150192
|
ref: `vercel-labs/agent-browser@v${agentBrowserVersion}`,
|
|
149854
150193
|
skill: "agent-browser",
|
|
149855
150194
|
env: homeEnv,
|
|
149856
|
-
agent: "claude"
|
|
150195
|
+
agent: "claude-code"
|
|
149857
150196
|
});
|
|
149858
150197
|
installBundledSkills({ home: homeEnv.HOME });
|
|
149859
150198
|
const mcpConfigPath = writeMcpConfig(ctx);
|
|
149860
150199
|
const effort = resolveEffort(model);
|
|
149861
|
-
installManagedSettings();
|
|
150200
|
+
installManagedSettings(ctx);
|
|
149862
150201
|
const baseArgs = [
|
|
149863
150202
|
cliPath,
|
|
149864
150203
|
"--output-format",
|
|
@@ -149886,6 +150225,10 @@ var claude = agent({
|
|
|
149886
150225
|
if (isBedrockRoute) {
|
|
149887
150226
|
env2.CLAUDE_CODE_USE_BEDROCK = "1";
|
|
149888
150227
|
}
|
|
150228
|
+
if (isVertexRoute2) {
|
|
150229
|
+
applyClaudeVertexEnv(env2);
|
|
150230
|
+
env2.ANTHROPIC_MODEL = specifier;
|
|
150231
|
+
}
|
|
149889
150232
|
if (env2.CLAUDE_CODE_OAUTH_TOKEN && !isBedrockRoute && env2.ANTHROPIC_API_KEY) {
|
|
149890
150233
|
log.debug(
|
|
149891
150234
|
"\xBB CLAUDE_CODE_OAUTH_TOKEN present \u2014 stripping ANTHROPIC_API_KEY from Claude Code env so the OAuth subscription is used"
|
|
@@ -149927,8 +150270,8 @@ var claude = agent({
|
|
|
149927
150270
|
|
|
149928
150271
|
// agents/opencode_v2.ts
|
|
149929
150272
|
var core2 = __toESM(require_core(), 1);
|
|
149930
|
-
import { mkdirSync as
|
|
149931
|
-
import { join as
|
|
150273
|
+
import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync11 } from "node:fs";
|
|
150274
|
+
import { join as join15 } from "node:path";
|
|
149932
150275
|
import { performance as performance7 } from "node:perf_hooks";
|
|
149933
150276
|
|
|
149934
150277
|
// utils/agentHangReport.ts
|
|
@@ -150027,9 +150370,9 @@ function formatBillingExhaustedBody(diagnostic) {
|
|
|
150027
150370
|
}
|
|
150028
150371
|
|
|
150029
150372
|
// utils/codexHome.ts
|
|
150030
|
-
import { mkdirSync as
|
|
150031
|
-
import { homedir } from "node:os";
|
|
150032
|
-
import { join as
|
|
150373
|
+
import { mkdirSync as mkdirSync6, writeFileSync as writeFileSync10 } from "node:fs";
|
|
150374
|
+
import { homedir as homedir2 } from "node:os";
|
|
150375
|
+
import { join as join14 } from "node:path";
|
|
150033
150376
|
var CODEX_AUTH_ENV = "CODEX_AUTH_JSON";
|
|
150034
150377
|
function installCodexAuth() {
|
|
150035
150378
|
const raw2 = process.env[CODEX_AUTH_ENV];
|
|
@@ -150039,9 +150382,9 @@ function installCodexAuth() {
|
|
|
150039
150382
|
log.warning(`\xBB ${CODEX_AUTH_ENV} present but malformed; ignoring`);
|
|
150040
150383
|
return null;
|
|
150041
150384
|
}
|
|
150042
|
-
const xdgDataHome =
|
|
150043
|
-
const opencodeDir =
|
|
150044
|
-
const authPath =
|
|
150385
|
+
const xdgDataHome = join14(homedir2(), ".local", "share");
|
|
150386
|
+
const opencodeDir = join14(xdgDataHome, "opencode");
|
|
150387
|
+
const authPath = join14(opencodeDir, "auth.json");
|
|
150045
150388
|
const opencodeAuth = {
|
|
150046
150389
|
openai: {
|
|
150047
150390
|
type: "oauth",
|
|
@@ -150054,8 +150397,8 @@ function installCodexAuth() {
|
|
|
150054
150397
|
...blob.tokens.account_id ? { accountId: blob.tokens.account_id } : {}
|
|
150055
150398
|
}
|
|
150056
150399
|
};
|
|
150057
|
-
|
|
150058
|
-
|
|
150400
|
+
mkdirSync6(opencodeDir, { recursive: true });
|
|
150401
|
+
writeFileSync10(authPath, `${JSON.stringify(opencodeAuth, null, 2)}
|
|
150059
150402
|
`, { mode: 384 });
|
|
150060
150403
|
log.info(`\xBB installed Codex auth at ${authPath}`);
|
|
150061
150404
|
return { authPath, xdgDataHome, originalRefresh: blob.tokens.refresh_token };
|
|
@@ -150169,7 +150512,7 @@ export default async function pullfrogEventsPlugin() {
|
|
|
150169
150512
|
`;
|
|
150170
150513
|
|
|
150171
150514
|
// agents/opencodeShared.ts
|
|
150172
|
-
import { execFileSync as
|
|
150515
|
+
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
150173
150516
|
|
|
150174
150517
|
// agents/subagentModels.ts
|
|
150175
150518
|
function deriveSubagentModels(orchestratorSpec) {
|
|
@@ -150218,7 +150561,7 @@ async function installOpencodeCli(params) {
|
|
|
150218
150561
|
var AUTO_SELECT_WARNING = "select a model explicitly in the Pullfrog console (https://pullfrog.com/console) to avoid this.";
|
|
150219
150562
|
function getOpenCodeModels(cliPath) {
|
|
150220
150563
|
try {
|
|
150221
|
-
const output =
|
|
150564
|
+
const output = execFileSync6(cliPath, ["models"], {
|
|
150222
150565
|
encoding: "utf-8",
|
|
150223
150566
|
timeout: 3e4,
|
|
150224
150567
|
env: process.env
|
|
@@ -150711,16 +151054,17 @@ var opencode = agent({
|
|
|
150711
151054
|
const rawModel = ctx.payload.proxyModel ?? ctx.resolvedModel ?? autoSelectModel(cliPath);
|
|
150712
151055
|
const bedrockModelId = process.env[BEDROCK_MODEL_ID_ENV]?.trim();
|
|
150713
151056
|
const isBedrockRoute = rawModel !== void 0 && bedrockModelId !== void 0 && bedrockModelId === rawModel;
|
|
150714
|
-
const
|
|
151057
|
+
const vertexModel = resolveVertexOpenCodeModel(rawModel);
|
|
151058
|
+
const model = vertexModel ?? (isBedrockRoute ? `amazon-bedrock/${rawModel}` : rawModel);
|
|
150715
151059
|
const homeEnv = {
|
|
150716
151060
|
HOME: ctx.tmpdir,
|
|
150717
|
-
XDG_CONFIG_HOME:
|
|
151061
|
+
XDG_CONFIG_HOME: join15(ctx.tmpdir, ".config")
|
|
150718
151062
|
};
|
|
150719
|
-
|
|
150720
|
-
const opencodePluginDir =
|
|
150721
|
-
|
|
150722
|
-
|
|
150723
|
-
|
|
151063
|
+
mkdirSync7(join15(homeEnv.XDG_CONFIG_HOME, "opencode"), { recursive: true });
|
|
151064
|
+
const opencodePluginDir = join15(homeEnv.XDG_CONFIG_HOME, "opencode", "plugin");
|
|
151065
|
+
mkdirSync7(opencodePluginDir, { recursive: true });
|
|
151066
|
+
writeFileSync11(
|
|
151067
|
+
join15(opencodePluginDir, PULLFROG_OPENCODE_PLUGIN_FILENAME),
|
|
150724
151068
|
PULLFROG_OPENCODE_PLUGIN_SOURCE
|
|
150725
151069
|
);
|
|
150726
151070
|
const agentBrowserVersion = getDevDependencyVersion("agent-browser");
|
|
@@ -150790,15 +151134,18 @@ var opencode = agent({
|
|
|
150790
151134
|
var agents = { claude, opencode };
|
|
150791
151135
|
|
|
150792
151136
|
// utils/agent.ts
|
|
150793
|
-
function
|
|
151137
|
+
function hasEnvVar2(name) {
|
|
150794
151138
|
const val = process.env[name];
|
|
150795
151139
|
return typeof val === "string" && val.length > 0;
|
|
150796
151140
|
}
|
|
150797
151141
|
function hasClaudeCodeAuth() {
|
|
150798
|
-
return
|
|
151142
|
+
return hasEnvVar2("CLAUDE_CODE_OAUTH_TOKEN") || hasEnvVar2("ANTHROPIC_API_KEY");
|
|
150799
151143
|
}
|
|
150800
151144
|
function hasBedrockAuth() {
|
|
150801
|
-
return
|
|
151145
|
+
return hasEnvVar2("AWS_BEARER_TOKEN_BEDROCK") || hasEnvVar2("AWS_ACCESS_KEY_ID") && hasEnvVar2("AWS_SECRET_ACCESS_KEY");
|
|
151146
|
+
}
|
|
151147
|
+
function hasVertexAuth() {
|
|
151148
|
+
return hasEnvVar2(VERTEX_SERVICE_ACCOUNT_JSON_ENV);
|
|
150802
151149
|
}
|
|
150803
151150
|
function resolveSlug(slug2) {
|
|
150804
151151
|
const alias = resolveDisplayAlias(slug2);
|
|
@@ -150806,11 +151153,20 @@ function resolveSlug(slug2) {
|
|
|
150806
151153
|
const bedrockId = process.env[BEDROCK_MODEL_ID_ENV]?.trim();
|
|
150807
151154
|
if (!bedrockId) {
|
|
150808
151155
|
throw new Error(
|
|
150809
|
-
`${BEDROCK_MODEL_ID_ENV} env var is required when the model is set to "${slug2}". set it to an AWS Bedrock model ID
|
|
151156
|
+
`${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.`
|
|
150810
151157
|
);
|
|
150811
151158
|
}
|
|
150812
151159
|
return bedrockId;
|
|
150813
151160
|
}
|
|
151161
|
+
if (alias?.routing === "vertex") {
|
|
151162
|
+
const vertexId = process.env[VERTEX_MODEL_ID_ENV]?.trim();
|
|
151163
|
+
if (!vertexId) {
|
|
151164
|
+
throw new Error(
|
|
151165
|
+
`${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.`
|
|
151166
|
+
);
|
|
151167
|
+
}
|
|
151168
|
+
return vertexId;
|
|
151169
|
+
}
|
|
150814
151170
|
return resolveCliModel(slug2);
|
|
150815
151171
|
}
|
|
150816
151172
|
function resolveModel(ctx) {
|
|
@@ -150838,6 +151194,9 @@ function resolveAgent(ctx) {
|
|
|
150838
151194
|
if (ctx.model && hasBedrockAuth() && process.env[BEDROCK_MODEL_ID_ENV]?.trim() === ctx.model) {
|
|
150839
151195
|
return isBedrockAnthropicId(ctx.model) ? agents.claude : agents.opencode;
|
|
150840
151196
|
}
|
|
151197
|
+
if (ctx.model && hasVertexAuth() && process.env[VERTEX_MODEL_ID_ENV]?.trim() === ctx.model) {
|
|
151198
|
+
return isVertexAnthropicId(ctx.model) ? agents.claude : agents.opencode;
|
|
151199
|
+
}
|
|
150841
151200
|
if (ctx.model) {
|
|
150842
151201
|
try {
|
|
150843
151202
|
const provider2 = getModelProvider(ctx.model);
|
|
@@ -150878,26 +151237,51 @@ add the missing secret(s) to your GitHub repository at ${githubSecretsUrl}, then
|
|
|
150878
151237
|
|
|
150879
151238
|
for full setup instructions, see https://docs.pullfrog.com/bedrock`;
|
|
150880
151239
|
}
|
|
150881
|
-
function
|
|
151240
|
+
function buildVertexSetupError(params) {
|
|
151241
|
+
const githubSecretsUrl = `https://github.com/${params.owner}/${params.name}/settings/secrets/actions`;
|
|
151242
|
+
return `Google Vertex AI model selected but required configuration is missing: ${params.missing.join(", ")}.
|
|
151243
|
+
|
|
151244
|
+
add the missing secret(s) to your GitHub repository at ${githubSecretsUrl}, then reference them in your workflow's \`env:\` block:
|
|
151245
|
+
|
|
151246
|
+
${VERTEX_SERVICE_ACCOUNT_JSON_ENV}: \${{ secrets.${VERTEX_SERVICE_ACCOUNT_JSON_ENV} }}
|
|
151247
|
+
${GOOGLE_CLOUD_PROJECT_ENV}: my-project
|
|
151248
|
+
${VERTEX_LOCATION_ENV}: global
|
|
151249
|
+
${VERTEX_MODEL_ID_ENV}: <vertex-model-id>
|
|
151250
|
+
|
|
151251
|
+
for full setup instructions, see https://docs.pullfrog.com/vertex`;
|
|
151252
|
+
}
|
|
151253
|
+
function hasEnvVar3(name) {
|
|
150882
151254
|
const value2 = process.env[name];
|
|
150883
151255
|
return typeof value2 === "string" && value2.length > 0;
|
|
150884
151256
|
}
|
|
150885
151257
|
function hasProviderKey(model) {
|
|
150886
151258
|
const requiredVars = getModelEnvVars(model);
|
|
150887
151259
|
if (requiredVars.length === 0) return true;
|
|
150888
|
-
return requiredVars.some((v) =>
|
|
151260
|
+
return requiredVars.some((v) => hasEnvVar3(v));
|
|
150889
151261
|
}
|
|
150890
151262
|
function validateBedrockSetup(params) {
|
|
150891
|
-
const hasAuth =
|
|
151263
|
+
const hasAuth = hasEnvVar3("AWS_BEARER_TOKEN_BEDROCK") || hasEnvVar3("AWS_ACCESS_KEY_ID") && hasEnvVar3("AWS_SECRET_ACCESS_KEY");
|
|
150892
151264
|
const missing = [];
|
|
150893
151265
|
if (!hasAuth)
|
|
150894
151266
|
missing.push("AWS_BEARER_TOKEN_BEDROCK (or AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY)");
|
|
150895
|
-
if (!
|
|
150896
|
-
if (!
|
|
151267
|
+
if (!hasEnvVar3("AWS_REGION")) missing.push("AWS_REGION");
|
|
151268
|
+
if (!hasEnvVar3(BEDROCK_MODEL_ID_ENV)) missing.push(BEDROCK_MODEL_ID_ENV);
|
|
150897
151269
|
if (missing.length > 0) {
|
|
150898
151270
|
throw new Error(buildBedrockSetupError({ owner: params.owner, name: params.name, missing }));
|
|
150899
151271
|
}
|
|
150900
151272
|
}
|
|
151273
|
+
function validateVertexSetup(params) {
|
|
151274
|
+
const hasAuth = hasEnvVar3(VERTEX_SERVICE_ACCOUNT_JSON_ENV);
|
|
151275
|
+
const hasProject = hasEnvVar3(GOOGLE_CLOUD_PROJECT_ENV) || readProjectIdFromVertexServiceAccountJson() !== void 0;
|
|
151276
|
+
const missing = [];
|
|
151277
|
+
if (!hasAuth) missing.push(VERTEX_SERVICE_ACCOUNT_JSON_ENV);
|
|
151278
|
+
if (!hasProject) missing.push(GOOGLE_CLOUD_PROJECT_ENV);
|
|
151279
|
+
if (!hasEnvVar3(VERTEX_LOCATION_ENV)) missing.push(VERTEX_LOCATION_ENV);
|
|
151280
|
+
if (!hasEnvVar3(VERTEX_MODEL_ID_ENV)) missing.push(VERTEX_MODEL_ID_ENV);
|
|
151281
|
+
if (missing.length > 0) {
|
|
151282
|
+
throw new Error(buildVertexSetupError({ owner: params.owner, name: params.name, missing }));
|
|
151283
|
+
}
|
|
151284
|
+
}
|
|
150901
151285
|
function validateAgentApiKey(params) {
|
|
150902
151286
|
if (params.model) {
|
|
150903
151287
|
const alias = resolveDisplayAlias(params.model);
|
|
@@ -150905,16 +151289,24 @@ function validateAgentApiKey(params) {
|
|
|
150905
151289
|
validateBedrockSetup({ owner: params.owner, name: params.name });
|
|
150906
151290
|
return;
|
|
150907
151291
|
}
|
|
151292
|
+
if (alias?.routing === "vertex") {
|
|
151293
|
+
validateVertexSetup({ owner: params.owner, name: params.name });
|
|
151294
|
+
return;
|
|
151295
|
+
}
|
|
150908
151296
|
if (!params.model.includes("/")) {
|
|
151297
|
+
if (process.env[VERTEX_MODEL_ID_ENV]?.trim() === params.model) {
|
|
151298
|
+
validateVertexSetup({ owner: params.owner, name: params.name });
|
|
151299
|
+
return;
|
|
151300
|
+
}
|
|
150909
151301
|
validateBedrockSetup({ owner: params.owner, name: params.name });
|
|
150910
151302
|
return;
|
|
150911
151303
|
}
|
|
150912
151304
|
const requiredVars = getModelEnvVars(params.model);
|
|
150913
151305
|
if (requiredVars.length === 0) return;
|
|
150914
|
-
if (requiredVars.some((v) =>
|
|
151306
|
+
if (requiredVars.some((v) => hasEnvVar3(v))) return;
|
|
150915
151307
|
throw new Error(buildMissingApiKeyError({ owner: params.owner, name: params.name }));
|
|
150916
151308
|
}
|
|
150917
|
-
const hasAnyKey = [...knownApiKeys].some((k) =>
|
|
151309
|
+
const hasAnyKey = [...knownApiKeys].some((k) => hasEnvVar3(k));
|
|
150918
151310
|
if (!hasAnyKey) {
|
|
150919
151311
|
throw new Error(buildMissingApiKeyError({ owner: params.owner, name: params.name }));
|
|
150920
151312
|
}
|
|
@@ -151034,7 +151426,7 @@ async function fetchBodyHtml(ctx) {
|
|
|
151034
151426
|
}
|
|
151035
151427
|
|
|
151036
151428
|
// utils/byokFallback.ts
|
|
151037
|
-
var FREE_FALLBACK_SLUG = "opencode/
|
|
151429
|
+
var FREE_FALLBACK_SLUG = "opencode/big-pickle";
|
|
151038
151430
|
function selectFallbackModelIfNeeded(input) {
|
|
151039
151431
|
if (input.proxyModel) return { fallback: false };
|
|
151040
151432
|
if (!input.resolvedModel) return { fallback: false };
|
|
@@ -151049,10 +151441,10 @@ function selectFallbackModelIfNeeded(input) {
|
|
|
151049
151441
|
}
|
|
151050
151442
|
|
|
151051
151443
|
// utils/gitAuthServer.ts
|
|
151052
|
-
import { randomUUID as
|
|
151053
|
-
import { writeFileSync as
|
|
151444
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
151445
|
+
import { writeFileSync as writeFileSync12 } from "node:fs";
|
|
151054
151446
|
import { createServer as createServer2 } from "node:http";
|
|
151055
|
-
import { join as
|
|
151447
|
+
import { join as join16 } from "node:path";
|
|
151056
151448
|
var CODE_TTL_MS = 5 * 60 * 1e3;
|
|
151057
151449
|
var TAMPER_WINDOW_MS = 6e4;
|
|
151058
151450
|
function revokeGitHubToken(token) {
|
|
@@ -151112,7 +151504,7 @@ async function startGitAuthServer(tmpdir4) {
|
|
|
151112
151504
|
const port = rawAddr.port;
|
|
151113
151505
|
log.debug(`git auth server listening on 127.0.0.1:${port}`);
|
|
151114
151506
|
function register4(token) {
|
|
151115
|
-
const code =
|
|
151507
|
+
const code = randomUUID4();
|
|
151116
151508
|
const timeout = setTimeout(() => {
|
|
151117
151509
|
codes.delete(code);
|
|
151118
151510
|
log.debug(`git auth code expired: ${code.slice(0, 8)}...`);
|
|
@@ -151122,9 +151514,9 @@ async function startGitAuthServer(tmpdir4) {
|
|
|
151122
151514
|
return code;
|
|
151123
151515
|
}
|
|
151124
151516
|
function writeAskpassScript(code) {
|
|
151125
|
-
const scriptId =
|
|
151517
|
+
const scriptId = randomUUID4();
|
|
151126
151518
|
const scriptName = `askpass-${scriptId}.js`;
|
|
151127
|
-
const scriptPath =
|
|
151519
|
+
const scriptPath = join16(tmpdir4, scriptName);
|
|
151128
151520
|
const content = [
|
|
151129
151521
|
`#!/usr/bin/env node`,
|
|
151130
151522
|
`var a=process.argv[2]||"";`,
|
|
@@ -151139,7 +151531,7 @@ async function startGitAuthServer(tmpdir4) {
|
|
|
151139
151531
|
`try{require("fs").unlinkSync("${scriptPath.replace(/\\/g, "\\\\")}")}catch(e){}`,
|
|
151140
151532
|
`})}).on("error",function(){process.exit(1)})}`
|
|
151141
151533
|
].join("\n");
|
|
151142
|
-
|
|
151534
|
+
writeFileSync12(scriptPath, content, { mode: 448 });
|
|
151143
151535
|
return scriptPath;
|
|
151144
151536
|
}
|
|
151145
151537
|
async function close() {
|
|
@@ -151163,7 +151555,7 @@ async function startGitAuthServer(tmpdir4) {
|
|
|
151163
151555
|
var core3 = __toESM(require_core(), 1);
|
|
151164
151556
|
import { createSign } from "node:crypto";
|
|
151165
151557
|
import { rename, writeFile } from "node:fs/promises";
|
|
151166
|
-
import { dirname as dirname3, join as
|
|
151558
|
+
import { dirname as dirname3, join as join17 } from "node:path";
|
|
151167
151559
|
|
|
151168
151560
|
// node_modules/.pnpm/@octokit+plugin-throttling@11.0.3_@octokit+core@7.0.5/node_modules/@octokit/plugin-throttling/dist-bundle/index.js
|
|
151169
151561
|
var import_light = __toESM(require_light(), 1);
|
|
@@ -155021,7 +155413,7 @@ function getGitHubUsageSummary() {
|
|
|
155021
155413
|
}
|
|
155022
155414
|
async function writeGitHubUsageSummaryToFile(path3) {
|
|
155023
155415
|
const summary2 = getGitHubUsageSummary();
|
|
155024
|
-
const tmpPath =
|
|
155416
|
+
const tmpPath = join17(dirname3(path3), `.usage-summary-${process.pid}.tmp`);
|
|
155025
155417
|
await writeFile(tmpPath, JSON.stringify(summary2));
|
|
155026
155418
|
await rename(tmpPath, path3);
|
|
155027
155419
|
}
|
|
@@ -155072,7 +155464,7 @@ function createOctokit(token) {
|
|
|
155072
155464
|
}
|
|
155073
155465
|
|
|
155074
155466
|
// utils/instructions.ts
|
|
155075
|
-
import { execSync as
|
|
155467
|
+
import { execSync as execSync3 } from "node:child_process";
|
|
155076
155468
|
function buildRuntimeContext(ctx) {
|
|
155077
155469
|
const {
|
|
155078
155470
|
"~pullfrog": _2,
|
|
@@ -155084,7 +155476,7 @@ function buildRuntimeContext(ctx) {
|
|
|
155084
155476
|
} = ctx.payload;
|
|
155085
155477
|
let gitStatus;
|
|
155086
155478
|
try {
|
|
155087
|
-
gitStatus =
|
|
155479
|
+
gitStatus = execSync3("git status --short", { encoding: "utf-8", stdio: "pipe" }).trim() || "(clean)";
|
|
155088
155480
|
} catch {
|
|
155089
155481
|
}
|
|
155090
155482
|
const data = {
|
|
@@ -155421,7 +155813,7 @@ function resolveInstructions(ctx) {
|
|
|
155421
155813
|
|
|
155422
155814
|
// utils/learnings.ts
|
|
155423
155815
|
import { mkdir, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
|
|
155424
|
-
import { dirname as dirname4, join as
|
|
155816
|
+
import { dirname as dirname4, join as join18 } from "node:path";
|
|
155425
155817
|
|
|
155426
155818
|
// utils/learningsTruncate.ts
|
|
155427
155819
|
var MAX_LEARNINGS_LENGTH = 1e5;
|
|
@@ -155438,7 +155830,7 @@ function truncateAtLineBoundary(body, cap) {
|
|
|
155438
155830
|
// utils/learnings.ts
|
|
155439
155831
|
var LEARNINGS_FILE_NAME = "pullfrog-learnings.md";
|
|
155440
155832
|
function learningsFilePath(tmpdir4) {
|
|
155441
|
-
return
|
|
155833
|
+
return join18(tmpdir4, LEARNINGS_FILE_NAME);
|
|
155442
155834
|
}
|
|
155443
155835
|
async function seedLearningsFile(params) {
|
|
155444
155836
|
const path3 = learningsFilePath(params.tmpdir);
|
|
@@ -156118,7 +156510,7 @@ async function runProxyResolution(ctx) {
|
|
|
156118
156510
|
|
|
156119
156511
|
// utils/prSummary.ts
|
|
156120
156512
|
import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile3 } from "node:fs/promises";
|
|
156121
|
-
import { dirname as dirname5, join as
|
|
156513
|
+
import { dirname as dirname5, join as join19 } from "node:path";
|
|
156122
156514
|
var SUMMARY_FILE_NAME = "pullfrog-summary.md";
|
|
156123
156515
|
var SUMMARY_SCAFFOLD = `# PR summary
|
|
156124
156516
|
|
|
@@ -156128,7 +156520,7 @@ var SUMMARY_SCAFFOLD = `# PR summary
|
|
|
156128
156520
|
var MIN_SNAPSHOT_LENGTH = 60;
|
|
156129
156521
|
var MAX_SNAPSHOT_LENGTH = 32768;
|
|
156130
156522
|
function summaryFilePath(tmpdir4) {
|
|
156131
|
-
return
|
|
156523
|
+
return join19(tmpdir4, SUMMARY_FILE_NAME);
|
|
156132
156524
|
}
|
|
156133
156525
|
async function seedSummaryFile(params) {
|
|
156134
156526
|
const path3 = summaryFilePath(params.tmpdir);
|
|
@@ -156322,6 +156714,16 @@ async function resolveRunContextData(params) {
|
|
|
156322
156714
|
}
|
|
156323
156715
|
|
|
156324
156716
|
// utils/runErrorRenderer.ts
|
|
156717
|
+
function isProviderModelNotFoundError(message) {
|
|
156718
|
+
return message.includes("ProviderModelNotFoundError");
|
|
156719
|
+
}
|
|
156720
|
+
function formatProviderModelNotFoundSummary(input) {
|
|
156721
|
+
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.
|
|
156722
|
+
|
|
156723
|
+
\`\`\`
|
|
156724
|
+
${input.raw}
|
|
156725
|
+
\`\`\``;
|
|
156726
|
+
}
|
|
156325
156727
|
function renderRunError(input) {
|
|
156326
156728
|
const billingError = isRouterKeylimitExhaustedError(input.errorMessage) ? new BillingError(input.errorMessage, { code: "router_keylimit_exhausted" }) : null;
|
|
156327
156729
|
if (billingError) {
|
|
@@ -156343,6 +156745,14 @@ function renderRunError(input) {
|
|
|
156343
156745
|
if (apiKeyErrorSummary) {
|
|
156344
156746
|
return { summary: apiKeyErrorSummary, comment: apiKeyErrorSummary };
|
|
156345
156747
|
}
|
|
156748
|
+
if (isProviderModelNotFoundError(input.errorMessage)) {
|
|
156749
|
+
const body = formatProviderModelNotFoundSummary({
|
|
156750
|
+
owner: input.repo.owner,
|
|
156751
|
+
name: input.repo.name,
|
|
156752
|
+
raw: input.errorMessage
|
|
156753
|
+
});
|
|
156754
|
+
return { summary: body, comment: body };
|
|
156755
|
+
}
|
|
156346
156756
|
if (hangBody) {
|
|
156347
156757
|
return {
|
|
156348
156758
|
summary: `### \u274C Pullfrog failed
|
|
@@ -156444,16 +156854,17 @@ async function persistRunArtifacts(toolContext) {
|
|
|
156444
156854
|
}
|
|
156445
156855
|
async function finalizeSuccessRun(input) {
|
|
156446
156856
|
await persistRunArtifacts(input.toolContext);
|
|
156447
|
-
|
|
156448
|
-
|
|
156449
|
-
|
|
156450
|
-
|
|
156451
|
-
|
|
156452
|
-
|
|
156453
|
-
|
|
156454
|
-
|
|
156455
|
-
|
|
156456
|
-
|
|
156857
|
+
const rendered = !input.result.success ? renderRunError({
|
|
156858
|
+
errorMessage: input.result.error || "agent run failed",
|
|
156859
|
+
repo: input.repo,
|
|
156860
|
+
agentDiagnostic: input.toolState.agentDiagnostic
|
|
156861
|
+
}) : null;
|
|
156862
|
+
if (rendered && input.toolState.progressComment) {
|
|
156863
|
+
await reportErrorToComment({ toolState: input.toolState, error: rendered.comment }).catch(
|
|
156864
|
+
(error49) => {
|
|
156865
|
+
log.debug(`failure error report failed: ${error49}`);
|
|
156866
|
+
}
|
|
156867
|
+
);
|
|
156457
156868
|
}
|
|
156458
156869
|
if (input.result.success && input.toolState.progressComment && !input.toolState.finalSummaryWritten) {
|
|
156459
156870
|
await deleteProgressComment(input.toolContext).catch((error49) => {
|
|
@@ -156463,7 +156874,7 @@ async function finalizeSuccessRun(input) {
|
|
|
156463
156874
|
try {
|
|
156464
156875
|
const usageSummary = formatUsageSummary(input.toolState.usageEntries);
|
|
156465
156876
|
const body = input.toolState.lastProgressBody || input.result.output;
|
|
156466
|
-
const parts = [body, usageSummary].filter(Boolean);
|
|
156877
|
+
const parts = [rendered?.summary, body, usageSummary].filter(Boolean);
|
|
156467
156878
|
if (parts.length > 0) {
|
|
156468
156879
|
await writeSummary(parts.join("\n\n"));
|
|
156469
156880
|
}
|
|
@@ -156548,116 +156959,6 @@ function logRunStartup(ctx) {
|
|
|
156548
156959
|
log.info(`\xBB timeout: ${resolveTimeoutForLog(ctx.payload.timeout)}`);
|
|
156549
156960
|
}
|
|
156550
156961
|
|
|
156551
|
-
// utils/setup.ts
|
|
156552
|
-
import { execFileSync as execFileSync6, execSync as execSync3 } from "node:child_process";
|
|
156553
|
-
import { mkdtempSync as mkdtempSync2 } from "node:fs";
|
|
156554
|
-
import { tmpdir as tmpdir3 } from "node:os";
|
|
156555
|
-
import { join as join18 } from "node:path";
|
|
156556
|
-
function createTempDirectory() {
|
|
156557
|
-
const sharedTempDir = mkdtempSync2(join18(tmpdir3(), "pullfrog-"));
|
|
156558
|
-
process.env.PULLFROG_TEMP_DIR = sharedTempDir;
|
|
156559
|
-
log.info(`\xBB created temp dir at ${sharedTempDir}`);
|
|
156560
|
-
return sharedTempDir;
|
|
156561
|
-
}
|
|
156562
|
-
function envScopedToRepo() {
|
|
156563
|
-
const scoped = { ...process.env };
|
|
156564
|
-
for (const key of Object.keys(scoped)) {
|
|
156565
|
-
if (key.startsWith("GIT_")) delete scoped[key];
|
|
156566
|
-
}
|
|
156567
|
-
return scoped;
|
|
156568
|
-
}
|
|
156569
|
-
function removeIncludeIfEntries(repoDir) {
|
|
156570
|
-
const env2 = envScopedToRepo();
|
|
156571
|
-
let configOutput;
|
|
156572
|
-
try {
|
|
156573
|
-
configOutput = execSync3("git config --local --get-regexp -z ^includeif\\.", {
|
|
156574
|
-
cwd: repoDir,
|
|
156575
|
-
encoding: "utf-8",
|
|
156576
|
-
stdio: "pipe",
|
|
156577
|
-
env: env2
|
|
156578
|
-
});
|
|
156579
|
-
} catch {
|
|
156580
|
-
log.debug("\xBB no includeIf credential entries to remove");
|
|
156581
|
-
return;
|
|
156582
|
-
}
|
|
156583
|
-
const seen = /* @__PURE__ */ new Set();
|
|
156584
|
-
for (const entry of configOutput.split("\0")) {
|
|
156585
|
-
if (!entry) continue;
|
|
156586
|
-
const nl = entry.indexOf("\n");
|
|
156587
|
-
const key = nl === -1 ? entry : entry.slice(0, nl);
|
|
156588
|
-
if (!key || seen.has(key)) continue;
|
|
156589
|
-
seen.add(key);
|
|
156590
|
-
try {
|
|
156591
|
-
execFileSync6("git", ["config", "--local", "--unset-all", key], {
|
|
156592
|
-
cwd: repoDir,
|
|
156593
|
-
stdio: "pipe",
|
|
156594
|
-
env: env2
|
|
156595
|
-
});
|
|
156596
|
-
} catch (error49) {
|
|
156597
|
-
log.debug(
|
|
156598
|
-
`\xBB failed to unset ${key}: ${error49 instanceof Error ? error49.message : String(error49)}`
|
|
156599
|
-
);
|
|
156600
|
-
}
|
|
156601
|
-
}
|
|
156602
|
-
if (seen.size > 0)
|
|
156603
|
-
log.info(
|
|
156604
|
-
`\xBB removed ${seen.size} includeIf credential ${seen.size === 1 ? "entry" : "entries"}`
|
|
156605
|
-
);
|
|
156606
|
-
}
|
|
156607
|
-
async function setupGit(params) {
|
|
156608
|
-
const repoDir = process.cwd();
|
|
156609
|
-
log.info("\xBB setting up git configuration...");
|
|
156610
|
-
try {
|
|
156611
|
-
let currentEmail = "";
|
|
156612
|
-
try {
|
|
156613
|
-
currentEmail = execSync3("git config user.email", {
|
|
156614
|
-
cwd: repoDir,
|
|
156615
|
-
stdio: "pipe",
|
|
156616
|
-
encoding: "utf-8"
|
|
156617
|
-
}).trim();
|
|
156618
|
-
} catch {
|
|
156619
|
-
}
|
|
156620
|
-
const shouldSetDefaults = !currentEmail || currentEmail === "github-actions[bot]@users.noreply.github.com";
|
|
156621
|
-
if (shouldSetDefaults) {
|
|
156622
|
-
execSync3('git config --local user.email "226033991+pullfrog[bot]@users.noreply.github.com"', {
|
|
156623
|
-
cwd: repoDir,
|
|
156624
|
-
stdio: "pipe"
|
|
156625
|
-
});
|
|
156626
|
-
execSync3('git config --local user.name "pullfrog[bot]"', {
|
|
156627
|
-
cwd: repoDir,
|
|
156628
|
-
stdio: "pipe"
|
|
156629
|
-
});
|
|
156630
|
-
log.debug("\xBB git user configured (using defaults)");
|
|
156631
|
-
} else {
|
|
156632
|
-
log.debug(`\xBB git user already configured (${currentEmail}), skipping`);
|
|
156633
|
-
}
|
|
156634
|
-
if (params.shell === "disabled") {
|
|
156635
|
-
execSync3("git config --local core.hooksPath /dev/null", {
|
|
156636
|
-
cwd: repoDir,
|
|
156637
|
-
stdio: "pipe"
|
|
156638
|
-
});
|
|
156639
|
-
log.debug("\xBB git hooks disabled (shell=disabled)");
|
|
156640
|
-
}
|
|
156641
|
-
} catch (error49) {
|
|
156642
|
-
log.info(`Failed to set git config: ${error49 instanceof Error ? error49.message : String(error49)}`);
|
|
156643
|
-
}
|
|
156644
|
-
try {
|
|
156645
|
-
execSync3("git config --local --unset-all http.https://github.com/.extraheader", {
|
|
156646
|
-
cwd: repoDir,
|
|
156647
|
-
stdio: "pipe"
|
|
156648
|
-
});
|
|
156649
|
-
log.info("\xBB removed existing authentication headers");
|
|
156650
|
-
} catch {
|
|
156651
|
-
log.debug("\xBB no existing authentication headers to remove");
|
|
156652
|
-
}
|
|
156653
|
-
removeIncludeIfEntries(repoDir);
|
|
156654
|
-
const originUrl = `https://github.com/${params.owner}/${params.name}.git`;
|
|
156655
|
-
$2("git", ["remote", "set-url", "origin", originUrl], { cwd: repoDir });
|
|
156656
|
-
params.toolState.pushUrl = originUrl;
|
|
156657
|
-
$2("git", ["config", "--local", "credential.helper", ""], { cwd: repoDir });
|
|
156658
|
-
log.info("\xBB git authentication configured");
|
|
156659
|
-
}
|
|
156660
|
-
|
|
156661
156962
|
// utils/todoTracking.ts
|
|
156662
156963
|
function isValidTodoStatus(value2) {
|
|
156663
156964
|
return value2 === "pending" || value2 === "in_progress" || value2 === "completed" || value2 === "cancelled";
|
|
@@ -156865,6 +157166,7 @@ async function main() {
|
|
|
156865
157166
|
toolState.beforeSha = payload.event.before_sha;
|
|
156866
157167
|
}
|
|
156867
157168
|
const tokenRef = __using(_stack2, await resolveTokens({ push: payload.push }), true);
|
|
157169
|
+
wipeRunnerLeakSurface();
|
|
156868
157170
|
const oidcCredentials = process.env.ACTIONS_ID_TOKEN_REQUEST_URL && process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN ? {
|
|
156869
157171
|
requestUrl: process.env.ACTIONS_ID_TOKEN_REQUEST_URL,
|
|
156870
157172
|
requestToken: process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN
|
|
@@ -156886,6 +157188,7 @@ async function main() {
|
|
|
156886
157188
|
let toolContext;
|
|
156887
157189
|
let progressCallbackDisabled = false;
|
|
156888
157190
|
let todoTracker;
|
|
157191
|
+
let vertexCredentials;
|
|
156889
157192
|
try {
|
|
156890
157193
|
var _stack = [];
|
|
156891
157194
|
try {
|
|
@@ -156920,6 +157223,7 @@ async function main() {
|
|
|
156920
157223
|
);
|
|
156921
157224
|
toolState.modelFallback = { from: fallback.from };
|
|
156922
157225
|
}
|
|
157226
|
+
vertexCredentials = materializeVertexCredentials({ model: resolvedModel });
|
|
156923
157227
|
const agent2 = resolveAgent({ model: resolvedModel });
|
|
156924
157228
|
toolState.model = payload.proxyModel ?? resolvedModel ?? effectiveSlug;
|
|
156925
157229
|
validateAgentApiKey({
|
|
@@ -157031,8 +157335,8 @@ ${instructions.user}` : null,
|
|
|
157031
157335
|
log.info(instructions.full);
|
|
157032
157336
|
});
|
|
157033
157337
|
if (agentId === "opencode") {
|
|
157034
|
-
const pluginDir =
|
|
157035
|
-
const hasPlugins = existsSync7(pluginDir) &&
|
|
157338
|
+
const pluginDir = join20(process.cwd(), ".opencode", "plugin");
|
|
157339
|
+
const hasPlugins = existsSync7(pluginDir) && readdirSync2(pluginDir).some((f) => /\.[jt]sx?$/.test(f));
|
|
157036
157340
|
if (hasPlugins && toolState.dependencyInstallation?.promise) {
|
|
157037
157341
|
log.info(
|
|
157038
157342
|
"\xBB .opencode/plugin/ detected \u2014 awaiting dependency installation before agent start"
|
|
@@ -157087,6 +157391,7 @@ ${instructions.user}` : null,
|
|
|
157087
157391
|
resolvedModel,
|
|
157088
157392
|
mcpServerUrl: mcpHttpServer.url,
|
|
157089
157393
|
tmpdir: tmpdir4,
|
|
157394
|
+
secretDenyPaths: vertexCredentials ? [vertexCredentials.secretDir] : [],
|
|
157090
157395
|
instructions,
|
|
157091
157396
|
todoTracker,
|
|
157092
157397
|
stopScript: runContext.repoSettings.stopScript,
|
|
@@ -157190,6 +157495,7 @@ ${instructions.user}` : null,
|
|
|
157190
157495
|
await patchWorkflowRunFields(toolContext, patch);
|
|
157191
157496
|
}
|
|
157192
157497
|
}
|
|
157498
|
+
cleanupVertexCredentials(vertexCredentials);
|
|
157193
157499
|
}
|
|
157194
157500
|
} catch (_3) {
|
|
157195
157501
|
var _error2 = _3, _hasError2 = true;
|
|
@@ -158078,7 +158384,7 @@ async function run2() {
|
|
|
158078
158384
|
}
|
|
158079
158385
|
|
|
158080
158386
|
// cli.ts
|
|
158081
|
-
var VERSION10 = "0.1.
|
|
158387
|
+
var VERSION10 = "0.1.12";
|
|
158082
158388
|
var bin = basename2(process.argv[1] || "");
|
|
158083
158389
|
var PROG = bin === "pf" || bin === "pullfrog" ? bin : "pullfrog";
|
|
158084
158390
|
var rawArgs = process.argv.slice(2);
|