pullfrog 0.1.9 → 0.1.11
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 +246 -86
- package/dist/index.js +245 -85
- package/dist/internal.js +19 -0
- package/dist/models.d.ts +20 -8
- 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);
|
|
@@ -98926,7 +98926,7 @@ var require_fast_content_type_parse = __commonJS({
|
|
|
98926
98926
|
// main.ts
|
|
98927
98927
|
import { existsSync as existsSync7, readdirSync } 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];
|
|
@@ -108021,6 +108021,25 @@ var providers = {
|
|
|
108021
108021
|
}
|
|
108022
108022
|
}
|
|
108023
108023
|
}),
|
|
108024
|
+
vertex: provider({
|
|
108025
|
+
displayName: "Google Vertex AI",
|
|
108026
|
+
envVars: [
|
|
108027
|
+
"VERTEX_SERVICE_ACCOUNT_JSON",
|
|
108028
|
+
"GOOGLE_CLOUD_PROJECT",
|
|
108029
|
+
"VERTEX_LOCATION",
|
|
108030
|
+
"VERTEX_MODEL_ID"
|
|
108031
|
+
],
|
|
108032
|
+
models: {
|
|
108033
|
+
// single routing entry — the actual Vertex AI model ID is read from
|
|
108034
|
+
// VERTEX_MODEL_ID at run time. see ModelRouting docs for why we don't
|
|
108035
|
+
// catalog individual Vertex models.
|
|
108036
|
+
byok: {
|
|
108037
|
+
displayName: "Google Vertex AI",
|
|
108038
|
+
resolve: "vertex",
|
|
108039
|
+
routing: "vertex"
|
|
108040
|
+
}
|
|
108041
|
+
}
|
|
108042
|
+
}),
|
|
108024
108043
|
openrouter: provider({
|
|
108025
108044
|
displayName: "OpenRouter",
|
|
108026
108045
|
envVars: ["OPENROUTER_API_KEY"],
|
|
@@ -108184,9 +108203,13 @@ function resolveCliModel(slug2) {
|
|
|
108184
108203
|
return resolveDisplayAlias(slug2)?.resolve;
|
|
108185
108204
|
}
|
|
108186
108205
|
var BEDROCK_MODEL_ID_ENV = "BEDROCK_MODEL_ID";
|
|
108206
|
+
var VERTEX_MODEL_ID_ENV = "VERTEX_MODEL_ID";
|
|
108187
108207
|
function isBedrockAnthropicId(bedrockModelId) {
|
|
108188
108208
|
return bedrockModelId.toLowerCase().split(/[./:]/).includes("anthropic");
|
|
108189
108209
|
}
|
|
108210
|
+
function isVertexAnthropicId(vertexModelId) {
|
|
108211
|
+
return /^claude-/i.test(vertexModelId.trim());
|
|
108212
|
+
}
|
|
108190
108213
|
|
|
108191
108214
|
// utils/buildPullfrogFooter.ts
|
|
108192
108215
|
var PULLFROG_DIVIDER = "<!-- PULLFROG_DIVIDER_DO_NOT_REMOVE_PLZ -->";
|
|
@@ -142469,7 +142492,7 @@ var import_semver = __toESM(require_semver2(), 1);
|
|
|
142469
142492
|
// package.json
|
|
142470
142493
|
var package_default = {
|
|
142471
142494
|
name: "pullfrog",
|
|
142472
|
-
version: "0.1.
|
|
142495
|
+
version: "0.1.11",
|
|
142473
142496
|
type: "module",
|
|
142474
142497
|
bin: {
|
|
142475
142498
|
pullfrog: "dist/cli.mjs",
|
|
@@ -147065,8 +147088,8 @@ function initToolState(params) {
|
|
|
147065
147088
|
|
|
147066
147089
|
// agents/claude.ts
|
|
147067
147090
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
147068
|
-
import { mkdirSync as
|
|
147069
|
-
import { join as
|
|
147091
|
+
import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync8 } from "node:fs";
|
|
147092
|
+
import { join as join11 } from "node:path";
|
|
147070
147093
|
import { performance as performance6 } from "node:perf_hooks";
|
|
147071
147094
|
|
|
147072
147095
|
// utils/install.ts
|
|
@@ -147367,6 +147390,70 @@ var ThinkingTimer = class {
|
|
|
147367
147390
|
}
|
|
147368
147391
|
};
|
|
147369
147392
|
|
|
147393
|
+
// utils/vertex.ts
|
|
147394
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
147395
|
+
import { mkdirSync as mkdirSync4, rmSync, writeFileSync as writeFileSync7 } from "node:fs";
|
|
147396
|
+
import { homedir } from "node:os";
|
|
147397
|
+
import { join as join10 } from "node:path";
|
|
147398
|
+
var VERTEX_SERVICE_ACCOUNT_JSON_ENV = "VERTEX_SERVICE_ACCOUNT_JSON";
|
|
147399
|
+
var GOOGLE_APPLICATION_CREDENTIALS_ENV = "GOOGLE_APPLICATION_CREDENTIALS";
|
|
147400
|
+
var GOOGLE_CLOUD_PROJECT_ENV = "GOOGLE_CLOUD_PROJECT";
|
|
147401
|
+
var VERTEX_LOCATION_ENV = "VERTEX_LOCATION";
|
|
147402
|
+
function hasEnvVar(name) {
|
|
147403
|
+
const value2 = process.env[name];
|
|
147404
|
+
return typeof value2 === "string" && value2.length > 0;
|
|
147405
|
+
}
|
|
147406
|
+
function isVertexRoute(model) {
|
|
147407
|
+
const vertexId = process.env[VERTEX_MODEL_ID_ENV]?.trim();
|
|
147408
|
+
return model !== void 0 && vertexId !== void 0 && vertexId === model;
|
|
147409
|
+
}
|
|
147410
|
+
function readProjectIdFromVertexServiceAccountJson() {
|
|
147411
|
+
const blob = process.env[VERTEX_SERVICE_ACCOUNT_JSON_ENV];
|
|
147412
|
+
if (!blob) return void 0;
|
|
147413
|
+
try {
|
|
147414
|
+
const parsed2 = JSON.parse(blob);
|
|
147415
|
+
if (!parsed2 || typeof parsed2 !== "object" || !("project_id" in parsed2)) {
|
|
147416
|
+
return void 0;
|
|
147417
|
+
}
|
|
147418
|
+
const projectId = parsed2.project_id;
|
|
147419
|
+
return typeof projectId === "string" && projectId.length > 0 ? projectId : void 0;
|
|
147420
|
+
} catch {
|
|
147421
|
+
return void 0;
|
|
147422
|
+
}
|
|
147423
|
+
}
|
|
147424
|
+
function createSecretDir() {
|
|
147425
|
+
const base = process.env.PULLFROG_SECRET_HOME || process.env.HOME || homedir();
|
|
147426
|
+
const secretDir = join10(base, ".pullfrog", "secrets", randomUUID3());
|
|
147427
|
+
mkdirSync4(secretDir, { recursive: true, mode: 448 });
|
|
147428
|
+
return secretDir;
|
|
147429
|
+
}
|
|
147430
|
+
function materializeVertexCredentials(params) {
|
|
147431
|
+
if (!isVertexRoute(params.model)) return void 0;
|
|
147432
|
+
const blob = process.env[VERTEX_SERVICE_ACCOUNT_JSON_ENV];
|
|
147433
|
+
if (!blob) return void 0;
|
|
147434
|
+
const secretDir = createSecretDir();
|
|
147435
|
+
const credentialsPath = join10(secretDir, "vertex-sa.json");
|
|
147436
|
+
writeFileSync7(credentialsPath, blob, { mode: 384 });
|
|
147437
|
+
process.env[GOOGLE_APPLICATION_CREDENTIALS_ENV] = credentialsPath;
|
|
147438
|
+
const projectId = readProjectIdFromVertexServiceAccountJson();
|
|
147439
|
+
if (projectId && !hasEnvVar(GOOGLE_CLOUD_PROJECT_ENV)) {
|
|
147440
|
+
process.env[GOOGLE_CLOUD_PROJECT_ENV] = projectId;
|
|
147441
|
+
}
|
|
147442
|
+
return { credentialsPath, secretDir };
|
|
147443
|
+
}
|
|
147444
|
+
function cleanupVertexCredentials(credentials) {
|
|
147445
|
+
if (!credentials) return;
|
|
147446
|
+
rmSync(credentials.secretDir, { recursive: true, force: true });
|
|
147447
|
+
}
|
|
147448
|
+
function applyClaudeVertexEnv(env2) {
|
|
147449
|
+
env2.CLAUDE_CODE_USE_VERTEX = "1";
|
|
147450
|
+
env2.ANTHROPIC_VERTEX_PROJECT_ID ??= env2[GOOGLE_CLOUD_PROJECT_ENV];
|
|
147451
|
+
env2.CLOUD_ML_REGION ??= env2[VERTEX_LOCATION_ENV];
|
|
147452
|
+
}
|
|
147453
|
+
function resolveVertexOpenCodeModel(model) {
|
|
147454
|
+
return isVertexRoute(model) && model ? `google-vertex/${model}` : void 0;
|
|
147455
|
+
}
|
|
147456
|
+
|
|
147370
147457
|
// agents/postRun.ts
|
|
147371
147458
|
import { readFile } from "node:fs/promises";
|
|
147372
147459
|
function getUnsubmittedReview(toolState) {
|
|
@@ -147670,10 +147757,10 @@ async function installClaudeCli() {
|
|
|
147670
147757
|
});
|
|
147671
147758
|
}
|
|
147672
147759
|
function writeMcpConfig(ctx) {
|
|
147673
|
-
const configDir =
|
|
147674
|
-
|
|
147675
|
-
const configPath =
|
|
147676
|
-
|
|
147760
|
+
const configDir = join11(ctx.tmpdir, ".claude");
|
|
147761
|
+
mkdirSync5(configDir, { recursive: true });
|
|
147762
|
+
const configPath = join11(configDir, "mcp.json");
|
|
147763
|
+
writeFileSync8(
|
|
147677
147764
|
configPath,
|
|
147678
147765
|
JSON.stringify({
|
|
147679
147766
|
mcpServers: {
|
|
@@ -148055,34 +148142,48 @@ ${stderrContext}`
|
|
|
148055
148142
|
var MANAGED_SETTINGS_DIR = "/etc/claude-code";
|
|
148056
148143
|
var MANAGED_SETTINGS_PATH = `${MANAGED_SETTINGS_DIR}/managed-settings.json`;
|
|
148057
148144
|
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
|
-
|
|
148145
|
+
function buildManagedSettings(ctx) {
|
|
148146
|
+
const secretDenyPaths = ctx.secretDenyPaths ?? [];
|
|
148147
|
+
const toolDeny = secretDenyPaths.flatMap((path3) => [
|
|
148148
|
+
`Read(${path3}/**)`,
|
|
148149
|
+
`Read(/${path3}/**)`,
|
|
148150
|
+
`Grep(${path3}/**)`,
|
|
148151
|
+
`Grep(/${path3}/**)`,
|
|
148152
|
+
`Edit(${path3}/**)`,
|
|
148153
|
+
`Edit(/${path3}/**)`,
|
|
148154
|
+
`Glob(${path3}/**)`,
|
|
148155
|
+
`Glob(/${path3}/**)`
|
|
148156
|
+
]);
|
|
148157
|
+
return {
|
|
148158
|
+
allowManagedPermissionRulesOnly: true,
|
|
148159
|
+
allowManagedHooksOnly: true,
|
|
148160
|
+
permissions: {
|
|
148161
|
+
deny: [
|
|
148162
|
+
"Read(//proc/**)",
|
|
148163
|
+
"Read(//sys/**)",
|
|
148164
|
+
"Grep(//proc/**)",
|
|
148165
|
+
"Grep(//sys/**)",
|
|
148166
|
+
"Edit(//proc/**)",
|
|
148167
|
+
"Edit(//sys/**)",
|
|
148168
|
+
"Glob(//proc/**)",
|
|
148169
|
+
"Glob(//sys/**)",
|
|
148170
|
+
`Read(${CODEX_AUTH_DENY_PATH})`,
|
|
148171
|
+
`Grep(${CODEX_AUTH_DENY_PATH})`,
|
|
148172
|
+
`Edit(${CODEX_AUTH_DENY_PATH})`,
|
|
148173
|
+
`Glob(${CODEX_AUTH_DENY_PATH})`,
|
|
148174
|
+
...toolDeny
|
|
148175
|
+
]
|
|
148176
|
+
},
|
|
148177
|
+
sandbox: {
|
|
148178
|
+
filesystem: {
|
|
148179
|
+
denyRead: ["/proc", "/sys", CODEX_AUTH_DENY_PATH, ...secretDenyPaths]
|
|
148180
|
+
}
|
|
148080
148181
|
}
|
|
148081
|
-
}
|
|
148082
|
-
}
|
|
148083
|
-
function installManagedSettings() {
|
|
148182
|
+
};
|
|
148183
|
+
}
|
|
148184
|
+
function installManagedSettings(ctx) {
|
|
148084
148185
|
if (process.env.CI !== "true") return;
|
|
148085
|
-
const content = JSON.stringify(
|
|
148186
|
+
const content = JSON.stringify(buildManagedSettings(ctx), null, 2);
|
|
148086
148187
|
try {
|
|
148087
148188
|
execFileSync3("sudo", ["mkdir", "-p", MANAGED_SETTINGS_DIR]);
|
|
148088
148189
|
execFileSync3("sudo", ["tee", MANAGED_SETTINGS_PATH], {
|
|
@@ -148102,12 +148203,14 @@ var claude = agent({
|
|
|
148102
148203
|
const specifier = ctx.payload.proxyModel ?? ctx.resolvedModel;
|
|
148103
148204
|
const bedrockModelId = process.env[BEDROCK_MODEL_ID_ENV]?.trim();
|
|
148104
148205
|
const isBedrockRoute = specifier !== void 0 && bedrockModelId !== void 0 && bedrockModelId === specifier && isBedrockAnthropicId(specifier);
|
|
148105
|
-
const
|
|
148206
|
+
const vertexModelId = process.env[VERTEX_MODEL_ID_ENV]?.trim();
|
|
148207
|
+
const isVertexRoute2 = specifier !== void 0 && vertexModelId !== void 0 && vertexModelId === specifier && isVertexAnthropicId(specifier);
|
|
148208
|
+
const model = !specifier ? void 0 : isBedrockRoute ? specifier : isVertexRoute2 ? void 0 : stripProviderPrefix(specifier);
|
|
148106
148209
|
const homeEnv = {
|
|
148107
148210
|
HOME: ctx.tmpdir,
|
|
148108
|
-
XDG_CONFIG_HOME:
|
|
148211
|
+
XDG_CONFIG_HOME: join11(ctx.tmpdir, ".config")
|
|
148109
148212
|
};
|
|
148110
|
-
|
|
148213
|
+
mkdirSync5(join11(homeEnv.XDG_CONFIG_HOME, "claude"), { recursive: true });
|
|
148111
148214
|
const agentBrowserVersion = getDevDependencyVersion("agent-browser");
|
|
148112
148215
|
addSkill({
|
|
148113
148216
|
ref: `vercel-labs/agent-browser@v${agentBrowserVersion}`,
|
|
@@ -148118,7 +148221,7 @@ var claude = agent({
|
|
|
148118
148221
|
installBundledSkills({ home: homeEnv.HOME });
|
|
148119
148222
|
const mcpConfigPath = writeMcpConfig(ctx);
|
|
148120
148223
|
const effort = resolveEffort(model);
|
|
148121
|
-
installManagedSettings();
|
|
148224
|
+
installManagedSettings(ctx);
|
|
148122
148225
|
const baseArgs = [
|
|
148123
148226
|
cliPath,
|
|
148124
148227
|
"--output-format",
|
|
@@ -148146,6 +148249,10 @@ var claude = agent({
|
|
|
148146
148249
|
if (isBedrockRoute) {
|
|
148147
148250
|
env2.CLAUDE_CODE_USE_BEDROCK = "1";
|
|
148148
148251
|
}
|
|
148252
|
+
if (isVertexRoute2) {
|
|
148253
|
+
applyClaudeVertexEnv(env2);
|
|
148254
|
+
env2.ANTHROPIC_MODEL = specifier;
|
|
148255
|
+
}
|
|
148149
148256
|
if (env2.CLAUDE_CODE_OAUTH_TOKEN && !isBedrockRoute && env2.ANTHROPIC_API_KEY) {
|
|
148150
148257
|
log.debug(
|
|
148151
148258
|
"\xBB CLAUDE_CODE_OAUTH_TOKEN present \u2014 stripping ANTHROPIC_API_KEY from Claude Code env so the OAuth subscription is used"
|
|
@@ -148187,8 +148294,8 @@ var claude = agent({
|
|
|
148187
148294
|
|
|
148188
148295
|
// agents/opencode_v2.ts
|
|
148189
148296
|
var core2 = __toESM(require_core(), 1);
|
|
148190
|
-
import { mkdirSync as
|
|
148191
|
-
import { join as
|
|
148297
|
+
import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync10 } from "node:fs";
|
|
148298
|
+
import { join as join13 } from "node:path";
|
|
148192
148299
|
import { performance as performance7 } from "node:perf_hooks";
|
|
148193
148300
|
|
|
148194
148301
|
// utils/agentHangReport.ts
|
|
@@ -148287,9 +148394,9 @@ function formatBillingExhaustedBody(diagnostic) {
|
|
|
148287
148394
|
}
|
|
148288
148395
|
|
|
148289
148396
|
// utils/codexHome.ts
|
|
148290
|
-
import { mkdirSync as
|
|
148291
|
-
import { homedir } from "node:os";
|
|
148292
|
-
import { join as
|
|
148397
|
+
import { mkdirSync as mkdirSync6, writeFileSync as writeFileSync9 } from "node:fs";
|
|
148398
|
+
import { homedir as homedir2 } from "node:os";
|
|
148399
|
+
import { join as join12 } from "node:path";
|
|
148293
148400
|
var CODEX_AUTH_ENV = "CODEX_AUTH_JSON";
|
|
148294
148401
|
function installCodexAuth() {
|
|
148295
148402
|
const raw2 = process.env[CODEX_AUTH_ENV];
|
|
@@ -148299,9 +148406,9 @@ function installCodexAuth() {
|
|
|
148299
148406
|
log.warning(`\xBB ${CODEX_AUTH_ENV} present but malformed; ignoring`);
|
|
148300
148407
|
return null;
|
|
148301
148408
|
}
|
|
148302
|
-
const xdgDataHome =
|
|
148303
|
-
const opencodeDir =
|
|
148304
|
-
const authPath =
|
|
148409
|
+
const xdgDataHome = join12(homedir2(), ".local", "share");
|
|
148410
|
+
const opencodeDir = join12(xdgDataHome, "opencode");
|
|
148411
|
+
const authPath = join12(opencodeDir, "auth.json");
|
|
148305
148412
|
const opencodeAuth = {
|
|
148306
148413
|
openai: {
|
|
148307
148414
|
type: "oauth",
|
|
@@ -148314,8 +148421,8 @@ function installCodexAuth() {
|
|
|
148314
148421
|
...blob.tokens.account_id ? { accountId: blob.tokens.account_id } : {}
|
|
148315
148422
|
}
|
|
148316
148423
|
};
|
|
148317
|
-
|
|
148318
|
-
|
|
148424
|
+
mkdirSync6(opencodeDir, { recursive: true });
|
|
148425
|
+
writeFileSync9(authPath, `${JSON.stringify(opencodeAuth, null, 2)}
|
|
148319
148426
|
`, { mode: 384 });
|
|
148320
148427
|
log.info(`\xBB installed Codex auth at ${authPath}`);
|
|
148321
148428
|
return { authPath, xdgDataHome, originalRefresh: blob.tokens.refresh_token };
|
|
@@ -148971,16 +149078,17 @@ var opencode = agent({
|
|
|
148971
149078
|
const rawModel = ctx.payload.proxyModel ?? ctx.resolvedModel ?? autoSelectModel(cliPath);
|
|
148972
149079
|
const bedrockModelId = process.env[BEDROCK_MODEL_ID_ENV]?.trim();
|
|
148973
149080
|
const isBedrockRoute = rawModel !== void 0 && bedrockModelId !== void 0 && bedrockModelId === rawModel;
|
|
148974
|
-
const
|
|
149081
|
+
const vertexModel = resolveVertexOpenCodeModel(rawModel);
|
|
149082
|
+
const model = vertexModel ?? (isBedrockRoute ? `amazon-bedrock/${rawModel}` : rawModel);
|
|
148975
149083
|
const homeEnv = {
|
|
148976
149084
|
HOME: ctx.tmpdir,
|
|
148977
|
-
XDG_CONFIG_HOME:
|
|
149085
|
+
XDG_CONFIG_HOME: join13(ctx.tmpdir, ".config")
|
|
148978
149086
|
};
|
|
148979
|
-
|
|
148980
|
-
const opencodePluginDir =
|
|
148981
|
-
|
|
148982
|
-
|
|
148983
|
-
|
|
149087
|
+
mkdirSync7(join13(homeEnv.XDG_CONFIG_HOME, "opencode"), { recursive: true });
|
|
149088
|
+
const opencodePluginDir = join13(homeEnv.XDG_CONFIG_HOME, "opencode", "plugin");
|
|
149089
|
+
mkdirSync7(opencodePluginDir, { recursive: true });
|
|
149090
|
+
writeFileSync10(
|
|
149091
|
+
join13(opencodePluginDir, PULLFROG_OPENCODE_PLUGIN_FILENAME),
|
|
148984
149092
|
PULLFROG_OPENCODE_PLUGIN_SOURCE
|
|
148985
149093
|
);
|
|
148986
149094
|
const agentBrowserVersion = getDevDependencyVersion("agent-browser");
|
|
@@ -149050,15 +149158,18 @@ var opencode = agent({
|
|
|
149050
149158
|
var agents = { claude, opencode };
|
|
149051
149159
|
|
|
149052
149160
|
// utils/agent.ts
|
|
149053
|
-
function
|
|
149161
|
+
function hasEnvVar2(name) {
|
|
149054
149162
|
const val = process.env[name];
|
|
149055
149163
|
return typeof val === "string" && val.length > 0;
|
|
149056
149164
|
}
|
|
149057
149165
|
function hasClaudeCodeAuth() {
|
|
149058
|
-
return
|
|
149166
|
+
return hasEnvVar2("CLAUDE_CODE_OAUTH_TOKEN") || hasEnvVar2("ANTHROPIC_API_KEY");
|
|
149059
149167
|
}
|
|
149060
149168
|
function hasBedrockAuth() {
|
|
149061
|
-
return
|
|
149169
|
+
return hasEnvVar2("AWS_BEARER_TOKEN_BEDROCK") || hasEnvVar2("AWS_ACCESS_KEY_ID") && hasEnvVar2("AWS_SECRET_ACCESS_KEY");
|
|
149170
|
+
}
|
|
149171
|
+
function hasVertexAuth() {
|
|
149172
|
+
return hasEnvVar2(VERTEX_SERVICE_ACCOUNT_JSON_ENV);
|
|
149062
149173
|
}
|
|
149063
149174
|
function resolveSlug(slug2) {
|
|
149064
149175
|
const alias = resolveDisplayAlias(slug2);
|
|
@@ -149066,11 +149177,20 @@ function resolveSlug(slug2) {
|
|
|
149066
149177
|
const bedrockId = process.env[BEDROCK_MODEL_ID_ENV]?.trim();
|
|
149067
149178
|
if (!bedrockId) {
|
|
149068
149179
|
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
|
|
149180
|
+
`${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
149181
|
);
|
|
149071
149182
|
}
|
|
149072
149183
|
return bedrockId;
|
|
149073
149184
|
}
|
|
149185
|
+
if (alias?.routing === "vertex") {
|
|
149186
|
+
const vertexId = process.env[VERTEX_MODEL_ID_ENV]?.trim();
|
|
149187
|
+
if (!vertexId) {
|
|
149188
|
+
throw new Error(
|
|
149189
|
+
`${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.`
|
|
149190
|
+
);
|
|
149191
|
+
}
|
|
149192
|
+
return vertexId;
|
|
149193
|
+
}
|
|
149074
149194
|
return resolveCliModel(slug2);
|
|
149075
149195
|
}
|
|
149076
149196
|
function resolveModel(ctx) {
|
|
@@ -149098,6 +149218,9 @@ function resolveAgent(ctx) {
|
|
|
149098
149218
|
if (ctx.model && hasBedrockAuth() && process.env[BEDROCK_MODEL_ID_ENV]?.trim() === ctx.model) {
|
|
149099
149219
|
return isBedrockAnthropicId(ctx.model) ? agents.claude : agents.opencode;
|
|
149100
149220
|
}
|
|
149221
|
+
if (ctx.model && hasVertexAuth() && process.env[VERTEX_MODEL_ID_ENV]?.trim() === ctx.model) {
|
|
149222
|
+
return isVertexAnthropicId(ctx.model) ? agents.claude : agents.opencode;
|
|
149223
|
+
}
|
|
149101
149224
|
if (ctx.model) {
|
|
149102
149225
|
try {
|
|
149103
149226
|
const provider2 = getModelProvider(ctx.model);
|
|
@@ -149138,26 +149261,51 @@ add the missing secret(s) to your GitHub repository at ${githubSecretsUrl}, then
|
|
|
149138
149261
|
|
|
149139
149262
|
for full setup instructions, see https://docs.pullfrog.com/bedrock`;
|
|
149140
149263
|
}
|
|
149141
|
-
function
|
|
149264
|
+
function buildVertexSetupError(params) {
|
|
149265
|
+
const githubSecretsUrl = `https://github.com/${params.owner}/${params.name}/settings/secrets/actions`;
|
|
149266
|
+
return `Google Vertex AI model selected but required configuration is missing: ${params.missing.join(", ")}.
|
|
149267
|
+
|
|
149268
|
+
add the missing secret(s) to your GitHub repository at ${githubSecretsUrl}, then reference them in your workflow's \`env:\` block:
|
|
149269
|
+
|
|
149270
|
+
${VERTEX_SERVICE_ACCOUNT_JSON_ENV}: \${{ secrets.${VERTEX_SERVICE_ACCOUNT_JSON_ENV} }}
|
|
149271
|
+
${GOOGLE_CLOUD_PROJECT_ENV}: my-project
|
|
149272
|
+
${VERTEX_LOCATION_ENV}: global
|
|
149273
|
+
${VERTEX_MODEL_ID_ENV}: <vertex-model-id>
|
|
149274
|
+
|
|
149275
|
+
for full setup instructions, see https://docs.pullfrog.com/vertex`;
|
|
149276
|
+
}
|
|
149277
|
+
function hasEnvVar3(name) {
|
|
149142
149278
|
const value2 = process.env[name];
|
|
149143
149279
|
return typeof value2 === "string" && value2.length > 0;
|
|
149144
149280
|
}
|
|
149145
149281
|
function hasProviderKey(model) {
|
|
149146
149282
|
const requiredVars = getModelEnvVars(model);
|
|
149147
149283
|
if (requiredVars.length === 0) return true;
|
|
149148
|
-
return requiredVars.some((v) =>
|
|
149284
|
+
return requiredVars.some((v) => hasEnvVar3(v));
|
|
149149
149285
|
}
|
|
149150
149286
|
function validateBedrockSetup(params) {
|
|
149151
|
-
const hasAuth =
|
|
149287
|
+
const hasAuth = hasEnvVar3("AWS_BEARER_TOKEN_BEDROCK") || hasEnvVar3("AWS_ACCESS_KEY_ID") && hasEnvVar3("AWS_SECRET_ACCESS_KEY");
|
|
149152
149288
|
const missing = [];
|
|
149153
149289
|
if (!hasAuth)
|
|
149154
149290
|
missing.push("AWS_BEARER_TOKEN_BEDROCK (or AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY)");
|
|
149155
|
-
if (!
|
|
149156
|
-
if (!
|
|
149291
|
+
if (!hasEnvVar3("AWS_REGION")) missing.push("AWS_REGION");
|
|
149292
|
+
if (!hasEnvVar3(BEDROCK_MODEL_ID_ENV)) missing.push(BEDROCK_MODEL_ID_ENV);
|
|
149157
149293
|
if (missing.length > 0) {
|
|
149158
149294
|
throw new Error(buildBedrockSetupError({ owner: params.owner, name: params.name, missing }));
|
|
149159
149295
|
}
|
|
149160
149296
|
}
|
|
149297
|
+
function validateVertexSetup(params) {
|
|
149298
|
+
const hasAuth = hasEnvVar3(VERTEX_SERVICE_ACCOUNT_JSON_ENV);
|
|
149299
|
+
const hasProject = hasEnvVar3(GOOGLE_CLOUD_PROJECT_ENV) || readProjectIdFromVertexServiceAccountJson() !== void 0;
|
|
149300
|
+
const missing = [];
|
|
149301
|
+
if (!hasAuth) missing.push(VERTEX_SERVICE_ACCOUNT_JSON_ENV);
|
|
149302
|
+
if (!hasProject) missing.push(GOOGLE_CLOUD_PROJECT_ENV);
|
|
149303
|
+
if (!hasEnvVar3(VERTEX_LOCATION_ENV)) missing.push(VERTEX_LOCATION_ENV);
|
|
149304
|
+
if (!hasEnvVar3(VERTEX_MODEL_ID_ENV)) missing.push(VERTEX_MODEL_ID_ENV);
|
|
149305
|
+
if (missing.length > 0) {
|
|
149306
|
+
throw new Error(buildVertexSetupError({ owner: params.owner, name: params.name, missing }));
|
|
149307
|
+
}
|
|
149308
|
+
}
|
|
149161
149309
|
function validateAgentApiKey(params) {
|
|
149162
149310
|
if (params.model) {
|
|
149163
149311
|
const alias = resolveDisplayAlias(params.model);
|
|
@@ -149165,16 +149313,24 @@ function validateAgentApiKey(params) {
|
|
|
149165
149313
|
validateBedrockSetup({ owner: params.owner, name: params.name });
|
|
149166
149314
|
return;
|
|
149167
149315
|
}
|
|
149316
|
+
if (alias?.routing === "vertex") {
|
|
149317
|
+
validateVertexSetup({ owner: params.owner, name: params.name });
|
|
149318
|
+
return;
|
|
149319
|
+
}
|
|
149168
149320
|
if (!params.model.includes("/")) {
|
|
149321
|
+
if (process.env[VERTEX_MODEL_ID_ENV]?.trim() === params.model) {
|
|
149322
|
+
validateVertexSetup({ owner: params.owner, name: params.name });
|
|
149323
|
+
return;
|
|
149324
|
+
}
|
|
149169
149325
|
validateBedrockSetup({ owner: params.owner, name: params.name });
|
|
149170
149326
|
return;
|
|
149171
149327
|
}
|
|
149172
149328
|
const requiredVars = getModelEnvVars(params.model);
|
|
149173
149329
|
if (requiredVars.length === 0) return;
|
|
149174
|
-
if (requiredVars.some((v) =>
|
|
149330
|
+
if (requiredVars.some((v) => hasEnvVar3(v))) return;
|
|
149175
149331
|
throw new Error(buildMissingApiKeyError({ owner: params.owner, name: params.name }));
|
|
149176
149332
|
}
|
|
149177
|
-
const hasAnyKey = [...knownApiKeys].some((k) =>
|
|
149333
|
+
const hasAnyKey = [...knownApiKeys].some((k) => hasEnvVar3(k));
|
|
149178
149334
|
if (!hasAnyKey) {
|
|
149179
149335
|
throw new Error(buildMissingApiKeyError({ owner: params.owner, name: params.name }));
|
|
149180
149336
|
}
|
|
@@ -149309,10 +149465,10 @@ function selectFallbackModelIfNeeded(input) {
|
|
|
149309
149465
|
}
|
|
149310
149466
|
|
|
149311
149467
|
// utils/gitAuthServer.ts
|
|
149312
|
-
import { randomUUID as
|
|
149313
|
-
import { writeFileSync as
|
|
149468
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
149469
|
+
import { writeFileSync as writeFileSync11 } from "node:fs";
|
|
149314
149470
|
import { createServer as createServer2 } from "node:http";
|
|
149315
|
-
import { join as
|
|
149471
|
+
import { join as join14 } from "node:path";
|
|
149316
149472
|
var CODE_TTL_MS = 5 * 60 * 1e3;
|
|
149317
149473
|
var TAMPER_WINDOW_MS = 6e4;
|
|
149318
149474
|
function revokeGitHubToken(token) {
|
|
@@ -149372,7 +149528,7 @@ async function startGitAuthServer(tmpdir3) {
|
|
|
149372
149528
|
const port = rawAddr.port;
|
|
149373
149529
|
log.debug(`git auth server listening on 127.0.0.1:${port}`);
|
|
149374
149530
|
function register4(token) {
|
|
149375
|
-
const code =
|
|
149531
|
+
const code = randomUUID4();
|
|
149376
149532
|
const timeout = setTimeout(() => {
|
|
149377
149533
|
codes.delete(code);
|
|
149378
149534
|
log.debug(`git auth code expired: ${code.slice(0, 8)}...`);
|
|
@@ -149382,9 +149538,9 @@ async function startGitAuthServer(tmpdir3) {
|
|
|
149382
149538
|
return code;
|
|
149383
149539
|
}
|
|
149384
149540
|
function writeAskpassScript(code) {
|
|
149385
|
-
const scriptId =
|
|
149541
|
+
const scriptId = randomUUID4();
|
|
149386
149542
|
const scriptName = `askpass-${scriptId}.js`;
|
|
149387
|
-
const scriptPath =
|
|
149543
|
+
const scriptPath = join14(tmpdir3, scriptName);
|
|
149388
149544
|
const content = [
|
|
149389
149545
|
`#!/usr/bin/env node`,
|
|
149390
149546
|
`var a=process.argv[2]||"";`,
|
|
@@ -149399,7 +149555,7 @@ async function startGitAuthServer(tmpdir3) {
|
|
|
149399
149555
|
`try{require("fs").unlinkSync("${scriptPath.replace(/\\/g, "\\\\")}")}catch(e){}`,
|
|
149400
149556
|
`})}).on("error",function(){process.exit(1)})}`
|
|
149401
149557
|
].join("\n");
|
|
149402
|
-
|
|
149558
|
+
writeFileSync11(scriptPath, content, { mode: 448 });
|
|
149403
149559
|
return scriptPath;
|
|
149404
149560
|
}
|
|
149405
149561
|
async function close() {
|
|
@@ -149423,7 +149579,7 @@ async function startGitAuthServer(tmpdir3) {
|
|
|
149423
149579
|
var core3 = __toESM(require_core(), 1);
|
|
149424
149580
|
import { createSign } from "node:crypto";
|
|
149425
149581
|
import { rename, writeFile } from "node:fs/promises";
|
|
149426
|
-
import { dirname as dirname3, join as
|
|
149582
|
+
import { dirname as dirname3, join as join15 } from "node:path";
|
|
149427
149583
|
|
|
149428
149584
|
// node_modules/.pnpm/@octokit+plugin-throttling@11.0.3_@octokit+core@7.0.5/node_modules/@octokit/plugin-throttling/dist-bundle/index.js
|
|
149429
149585
|
var import_light = __toESM(require_light(), 1);
|
|
@@ -153281,7 +153437,7 @@ function getGitHubUsageSummary() {
|
|
|
153281
153437
|
}
|
|
153282
153438
|
async function writeGitHubUsageSummaryToFile(path3) {
|
|
153283
153439
|
const summary2 = getGitHubUsageSummary();
|
|
153284
|
-
const tmpPath =
|
|
153440
|
+
const tmpPath = join15(dirname3(path3), `.usage-summary-${process.pid}.tmp`);
|
|
153285
153441
|
await writeFile(tmpPath, JSON.stringify(summary2));
|
|
153286
153442
|
await rename(tmpPath, path3);
|
|
153287
153443
|
}
|
|
@@ -153681,7 +153837,7 @@ function resolveInstructions(ctx) {
|
|
|
153681
153837
|
|
|
153682
153838
|
// utils/learnings.ts
|
|
153683
153839
|
import { mkdir, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
|
|
153684
|
-
import { dirname as dirname4, join as
|
|
153840
|
+
import { dirname as dirname4, join as join16 } from "node:path";
|
|
153685
153841
|
|
|
153686
153842
|
// utils/learningsTruncate.ts
|
|
153687
153843
|
var MAX_LEARNINGS_LENGTH = 1e5;
|
|
@@ -153698,7 +153854,7 @@ function truncateAtLineBoundary(body, cap) {
|
|
|
153698
153854
|
// utils/learnings.ts
|
|
153699
153855
|
var LEARNINGS_FILE_NAME = "pullfrog-learnings.md";
|
|
153700
153856
|
function learningsFilePath(tmpdir3) {
|
|
153701
|
-
return
|
|
153857
|
+
return join16(tmpdir3, LEARNINGS_FILE_NAME);
|
|
153702
153858
|
}
|
|
153703
153859
|
async function seedLearningsFile(params) {
|
|
153704
153860
|
const path3 = learningsFilePath(params.tmpdir);
|
|
@@ -154378,7 +154534,7 @@ async function runProxyResolution(ctx) {
|
|
|
154378
154534
|
|
|
154379
154535
|
// utils/prSummary.ts
|
|
154380
154536
|
import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile3 } from "node:fs/promises";
|
|
154381
|
-
import { dirname as dirname5, join as
|
|
154537
|
+
import { dirname as dirname5, join as join17 } from "node:path";
|
|
154382
154538
|
var SUMMARY_FILE_NAME = "pullfrog-summary.md";
|
|
154383
154539
|
var SUMMARY_SCAFFOLD = `# PR summary
|
|
154384
154540
|
|
|
@@ -154388,7 +154544,7 @@ var SUMMARY_SCAFFOLD = `# PR summary
|
|
|
154388
154544
|
var MIN_SNAPSHOT_LENGTH = 60;
|
|
154389
154545
|
var MAX_SNAPSHOT_LENGTH = 32768;
|
|
154390
154546
|
function summaryFilePath(tmpdir3) {
|
|
154391
|
-
return
|
|
154547
|
+
return join17(tmpdir3, SUMMARY_FILE_NAME);
|
|
154392
154548
|
}
|
|
154393
154549
|
async function seedSummaryFile(params) {
|
|
154394
154550
|
const path3 = summaryFilePath(params.tmpdir);
|
|
@@ -154812,9 +154968,9 @@ function logRunStartup(ctx) {
|
|
|
154812
154968
|
import { execFileSync as execFileSync5, execSync as execSync3 } from "node:child_process";
|
|
154813
154969
|
import { mkdtempSync } from "node:fs";
|
|
154814
154970
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
154815
|
-
import { join as
|
|
154971
|
+
import { join as join18 } from "node:path";
|
|
154816
154972
|
function createTempDirectory() {
|
|
154817
|
-
const sharedTempDir = mkdtempSync(
|
|
154973
|
+
const sharedTempDir = mkdtempSync(join18(tmpdir2(), "pullfrog-"));
|
|
154818
154974
|
process.env.PULLFROG_TEMP_DIR = sharedTempDir;
|
|
154819
154975
|
log.info(`\xBB created temp dir at ${sharedTempDir}`);
|
|
154820
154976
|
return sharedTempDir;
|
|
@@ -155146,6 +155302,7 @@ async function main() {
|
|
|
155146
155302
|
let toolContext;
|
|
155147
155303
|
let progressCallbackDisabled = false;
|
|
155148
155304
|
let todoTracker;
|
|
155305
|
+
let vertexCredentials;
|
|
155149
155306
|
try {
|
|
155150
155307
|
var _stack = [];
|
|
155151
155308
|
try {
|
|
@@ -155180,6 +155337,7 @@ async function main() {
|
|
|
155180
155337
|
);
|
|
155181
155338
|
toolState.modelFallback = { from: fallback.from };
|
|
155182
155339
|
}
|
|
155340
|
+
vertexCredentials = materializeVertexCredentials({ model: resolvedModel });
|
|
155183
155341
|
const agent2 = resolveAgent({ model: resolvedModel });
|
|
155184
155342
|
toolState.model = payload.proxyModel ?? resolvedModel ?? effectiveSlug;
|
|
155185
155343
|
validateAgentApiKey({
|
|
@@ -155291,7 +155449,7 @@ ${instructions.user}` : null,
|
|
|
155291
155449
|
log.info(instructions.full);
|
|
155292
155450
|
});
|
|
155293
155451
|
if (agentId === "opencode") {
|
|
155294
|
-
const pluginDir =
|
|
155452
|
+
const pluginDir = join19(process.cwd(), ".opencode", "plugin");
|
|
155295
155453
|
const hasPlugins = existsSync7(pluginDir) && readdirSync(pluginDir).some((f) => /\.[jt]sx?$/.test(f));
|
|
155296
155454
|
if (hasPlugins && toolState.dependencyInstallation?.promise) {
|
|
155297
155455
|
log.info(
|
|
@@ -155347,6 +155505,7 @@ ${instructions.user}` : null,
|
|
|
155347
155505
|
resolvedModel,
|
|
155348
155506
|
mcpServerUrl: mcpHttpServer.url,
|
|
155349
155507
|
tmpdir: tmpdir3,
|
|
155508
|
+
secretDenyPaths: vertexCredentials ? [vertexCredentials.secretDir] : [],
|
|
155350
155509
|
instructions,
|
|
155351
155510
|
todoTracker,
|
|
155352
155511
|
stopScript: runContext.repoSettings.stopScript,
|
|
@@ -155450,6 +155609,7 @@ ${instructions.user}` : null,
|
|
|
155450
155609
|
await patchWorkflowRunFields(toolContext, patch);
|
|
155451
155610
|
}
|
|
155452
155611
|
}
|
|
155612
|
+
cleanupVertexCredentials(vertexCredentials);
|
|
155453
155613
|
}
|
|
155454
155614
|
} catch (_2) {
|
|
155455
155615
|
var _error2 = _2, _hasError2 = true;
|
package/dist/internal.js
CHANGED
|
@@ -291,6 +291,25 @@ var providers = {
|
|
|
291
291
|
}
|
|
292
292
|
}
|
|
293
293
|
}),
|
|
294
|
+
vertex: provider({
|
|
295
|
+
displayName: "Google Vertex AI",
|
|
296
|
+
envVars: [
|
|
297
|
+
"VERTEX_SERVICE_ACCOUNT_JSON",
|
|
298
|
+
"GOOGLE_CLOUD_PROJECT",
|
|
299
|
+
"VERTEX_LOCATION",
|
|
300
|
+
"VERTEX_MODEL_ID"
|
|
301
|
+
],
|
|
302
|
+
models: {
|
|
303
|
+
// single routing entry — the actual Vertex AI model ID is read from
|
|
304
|
+
// VERTEX_MODEL_ID at run time. see ModelRouting docs for why we don't
|
|
305
|
+
// catalog individual Vertex models.
|
|
306
|
+
byok: {
|
|
307
|
+
displayName: "Google Vertex AI",
|
|
308
|
+
resolve: "vertex",
|
|
309
|
+
routing: "vertex"
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}),
|
|
294
313
|
openrouter: provider({
|
|
295
314
|
displayName: "OpenRouter",
|
|
296
315
|
envVars: ["OPENROUTER_API_KEY"],
|