pullfrog 0.1.56 → 0.1.59
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/codex.d.ts +1 -0
- package/dist/agents/index.d.ts +1 -0
- package/dist/agents/opencodeShared.d.ts +24 -0
- package/dist/cli.mjs +1070 -396
- package/dist/external.d.ts +12 -4
- package/dist/index.js +1105 -427
- package/dist/internal.js +18 -0
- package/dist/models.d.ts +42 -1
- package/dist/utils/agent.d.ts +10 -0
- package/dist/utils/codexHome.d.ts +27 -0
- package/dist/utils/roleMirror.d.ts +14 -0
- package/dist/utils/runContext.d.ts +1 -0
- package/package.json +3 -1
package/dist/cli.mjs
CHANGED
|
@@ -3955,7 +3955,7 @@ var require_util2 = __commonJS({
|
|
|
3955
3955
|
"use strict";
|
|
3956
3956
|
var { redirectStatusSet, referrerPolicySet: referrerPolicyTokens, badPortsSet } = require_constants2();
|
|
3957
3957
|
var { getGlobalOrigin } = require_global();
|
|
3958
|
-
var { performance:
|
|
3958
|
+
var { performance: performance10 } = __require("perf_hooks");
|
|
3959
3959
|
var { isBlobLike, toUSVString, ReadableStreamFrom } = require_util();
|
|
3960
3960
|
var assert3 = __require("assert");
|
|
3961
3961
|
var { isUint8Array } = __require("util/types");
|
|
@@ -4118,7 +4118,7 @@ var require_util2 = __commonJS({
|
|
|
4118
4118
|
}
|
|
4119
4119
|
}
|
|
4120
4120
|
function coarsenedSharedCurrentTime(crossOriginIsolatedCapability) {
|
|
4121
|
-
return
|
|
4121
|
+
return performance10.now();
|
|
4122
4122
|
}
|
|
4123
4123
|
function createOpaqueTimingInfo(timingInfo) {
|
|
4124
4124
|
return {
|
|
@@ -20099,14 +20099,14 @@ Support boolean input list: \`true | True | TRUE | false | False | FALSE\``);
|
|
|
20099
20099
|
});
|
|
20100
20100
|
}
|
|
20101
20101
|
exports.group = group2;
|
|
20102
|
-
function
|
|
20102
|
+
function saveState4(name, value2) {
|
|
20103
20103
|
const filePath = process.env["GITHUB_STATE"] || "";
|
|
20104
20104
|
if (filePath) {
|
|
20105
20105
|
return (0, file_command_1.issueFileCommand)("STATE", (0, file_command_1.prepareKeyValueMessage)(name, value2));
|
|
20106
20106
|
}
|
|
20107
20107
|
(0, command_1.issueCommand)("save-state", { name }, (0, utils_1.toCommandValue)(value2));
|
|
20108
20108
|
}
|
|
20109
|
-
exports.saveState =
|
|
20109
|
+
exports.saveState = saveState4;
|
|
20110
20110
|
function getState2(name) {
|
|
20111
20111
|
return process.env[`STATE_${name}`] || "";
|
|
20112
20112
|
}
|
|
@@ -27894,11 +27894,11 @@ var require_mode = __commonJS({
|
|
|
27894
27894
|
var require_isexe = __commonJS({
|
|
27895
27895
|
"node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/index.js"(exports, module) {
|
|
27896
27896
|
var fs5 = __require("fs");
|
|
27897
|
-
var
|
|
27897
|
+
var core12;
|
|
27898
27898
|
if (process.platform === "win32" || global.TESTING_WINDOWS) {
|
|
27899
|
-
|
|
27899
|
+
core12 = require_windows();
|
|
27900
27900
|
} else {
|
|
27901
|
-
|
|
27901
|
+
core12 = require_mode();
|
|
27902
27902
|
}
|
|
27903
27903
|
module.exports = isexe;
|
|
27904
27904
|
isexe.sync = sync;
|
|
@@ -27921,7 +27921,7 @@ var require_isexe = __commonJS({
|
|
|
27921
27921
|
});
|
|
27922
27922
|
});
|
|
27923
27923
|
}
|
|
27924
|
-
|
|
27924
|
+
core12(path4, options || {}, function(er, is) {
|
|
27925
27925
|
if (er) {
|
|
27926
27926
|
if (er.code === "EACCES" || options && options.ignoreErrors) {
|
|
27927
27927
|
er = null;
|
|
@@ -27933,7 +27933,7 @@ var require_isexe = __commonJS({
|
|
|
27933
27933
|
}
|
|
27934
27934
|
function sync(path4, options) {
|
|
27935
27935
|
try {
|
|
27936
|
-
return
|
|
27936
|
+
return core12.sync(path4, options || {});
|
|
27937
27937
|
} catch (er) {
|
|
27938
27938
|
if (options && options.ignoreErrors || er.code === "EACCES") {
|
|
27939
27939
|
return false;
|
|
@@ -33299,7 +33299,7 @@ var require_util9 = __commonJS({
|
|
|
33299
33299
|
var { redirectStatusSet, referrerPolicyTokens, badPortsSet } = require_constants9();
|
|
33300
33300
|
var { getGlobalOrigin } = require_global3();
|
|
33301
33301
|
var { collectAnHTTPQuotedString, parseMIMEType } = require_data_url();
|
|
33302
|
-
var { performance:
|
|
33302
|
+
var { performance: performance10 } = __require("node:perf_hooks");
|
|
33303
33303
|
var { ReadableStreamFrom, isValidHTTPToken, normalizedMethodRecordsBase } = require_util8();
|
|
33304
33304
|
var assert3 = __require("node:assert");
|
|
33305
33305
|
var { isUint8Array } = __require("node:util/types");
|
|
@@ -33454,7 +33454,7 @@ var require_util9 = __commonJS({
|
|
|
33454
33454
|
};
|
|
33455
33455
|
}
|
|
33456
33456
|
function coarsenedSharedCurrentTime(crossOriginIsolatedCapability) {
|
|
33457
|
-
return coarsenTime(
|
|
33457
|
+
return coarsenTime(performance10.now(), crossOriginIsolatedCapability);
|
|
33458
33458
|
}
|
|
33459
33459
|
function createOpaqueTimingInfo(timingInfo) {
|
|
33460
33460
|
return {
|
|
@@ -76726,7 +76726,7 @@ var require_core3 = __commonJS({
|
|
|
76726
76726
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
76727
76727
|
var id_1 = require_id();
|
|
76728
76728
|
var ref_1 = require_ref();
|
|
76729
|
-
var
|
|
76729
|
+
var core12 = [
|
|
76730
76730
|
"$schema",
|
|
76731
76731
|
"$id",
|
|
76732
76732
|
"$defs",
|
|
@@ -76736,7 +76736,7 @@ var require_core3 = __commonJS({
|
|
|
76736
76736
|
id_1.default,
|
|
76737
76737
|
ref_1.default
|
|
76738
76738
|
];
|
|
76739
|
-
exports.default =
|
|
76739
|
+
exports.default = core12;
|
|
76740
76740
|
}
|
|
76741
76741
|
});
|
|
76742
76742
|
|
|
@@ -98607,14 +98607,14 @@ var require_turndown_cjs = __commonJS({
|
|
|
98607
98607
|
} else if (node2.nodeType === 1) {
|
|
98608
98608
|
replacement = replacementForNode.call(self2, node2);
|
|
98609
98609
|
}
|
|
98610
|
-
return
|
|
98610
|
+
return join29(output, replacement);
|
|
98611
98611
|
}, "");
|
|
98612
98612
|
}
|
|
98613
98613
|
function postProcess(output) {
|
|
98614
98614
|
var self2 = this;
|
|
98615
98615
|
this.rules.forEach(function(rule) {
|
|
98616
98616
|
if (typeof rule.append === "function") {
|
|
98617
|
-
output =
|
|
98617
|
+
output = join29(output, rule.append(self2.options));
|
|
98618
98618
|
}
|
|
98619
98619
|
});
|
|
98620
98620
|
return output.replace(/^[\t\r\n]+/, "").replace(/[\t\r\n\s]+$/, "");
|
|
@@ -98626,7 +98626,7 @@ var require_turndown_cjs = __commonJS({
|
|
|
98626
98626
|
if (whitespace.leading || whitespace.trailing) content = content.trim();
|
|
98627
98627
|
return whitespace.leading + rule.replacement(content, node2, this.options) + whitespace.trailing;
|
|
98628
98628
|
}
|
|
98629
|
-
function
|
|
98629
|
+
function join29(output, replacement) {
|
|
98630
98630
|
var s1 = trimTrailingNewlines(output);
|
|
98631
98631
|
var s2 = trimLeadingNewlines(replacement);
|
|
98632
98632
|
var nls = Math.max(output.length - s1.length, replacement.length - s2.length);
|
|
@@ -105306,14 +105306,14 @@ async function runClaudeAuth() {
|
|
|
105306
105306
|
}
|
|
105307
105307
|
|
|
105308
105308
|
// commands/gha.ts
|
|
105309
|
-
var
|
|
105309
|
+
var core11 = __toESM(require_core(), 1);
|
|
105310
105310
|
var import_arg2 = __toESM(require_arg(), 1);
|
|
105311
105311
|
import { dirname as dirname6 } from "node:path";
|
|
105312
105312
|
|
|
105313
105313
|
// main.ts
|
|
105314
|
-
import { existsSync as
|
|
105314
|
+
import { existsSync as existsSync9, readdirSync as readdirSync2 } from "node:fs";
|
|
105315
105315
|
import { readFile as readFile5 } from "node:fs/promises";
|
|
105316
|
-
import { join as
|
|
105316
|
+
import { join as join28 } from "node:path";
|
|
105317
105317
|
|
|
105318
105318
|
// node_modules/.pnpm/package-manager-detector@1.8.0/node_modules/package-manager-detector/dist/commands.mjs
|
|
105319
105319
|
function splitRunArgs(args2, valueFlags = []) {
|
|
@@ -106186,6 +106186,22 @@ var providers = {
|
|
|
106186
106186
|
}
|
|
106187
106187
|
}
|
|
106188
106188
|
}),
|
|
106189
|
+
azure: provider({
|
|
106190
|
+
displayName: "Azure OpenAI",
|
|
106191
|
+
// the resource name is half the endpoint URL and the deployment is the model
|
|
106192
|
+
// id, so both are as load-bearing as the key. only the key is sensitive.
|
|
106193
|
+
envVars: ["AZURE_API_KEY", "AZURE_RESOURCE_NAME", "AZURE_DEPLOYMENT"],
|
|
106194
|
+
models: {
|
|
106195
|
+
// single routing entry — the real model is the customer's deployment name,
|
|
106196
|
+
// read from AZURE_DEPLOYMENT at run time. see ModelRouting docs for why
|
|
106197
|
+
// Azure can't be cataloged even though models.dev lists it.
|
|
106198
|
+
byok: {
|
|
106199
|
+
displayName: "Azure OpenAI",
|
|
106200
|
+
resolve: "azure",
|
|
106201
|
+
routing: "azure"
|
|
106202
|
+
}
|
|
106203
|
+
}
|
|
106204
|
+
}),
|
|
106189
106205
|
"openai-compatible": provider({
|
|
106190
106206
|
// "Custom" is the picker group, "OpenAI-compatible" the entry under it, so the
|
|
106191
106207
|
// menu reads `Custom › OpenAI-compatible` and a second custom backend (a
|
|
@@ -106411,6 +106427,11 @@ function getModelEnvVars(slug2) {
|
|
|
106411
106427
|
}
|
|
106412
106428
|
return providerConfig.envVars.slice();
|
|
106413
106429
|
}
|
|
106430
|
+
function getModelManagedCredentials(slug2) {
|
|
106431
|
+
const parsed2 = parseModel(slug2);
|
|
106432
|
+
const providerConfig = providers[parsed2.provider];
|
|
106433
|
+
return providerConfig?.managedCredentials?.slice() ?? [];
|
|
106434
|
+
}
|
|
106414
106435
|
var modelAliases = Object.entries(providers).flatMap(
|
|
106415
106436
|
([providerKey, config3]) => Object.entries(config3.models).map(([modelId, def]) => ({
|
|
106416
106437
|
slug: `${providerKey}/${modelId}`,
|
|
@@ -106508,6 +106529,13 @@ function isOssAllowedModel(slug2) {
|
|
|
106508
106529
|
}
|
|
106509
106530
|
var BEDROCK_MODEL_ID_ENV = "BEDROCK_MODEL_ID";
|
|
106510
106531
|
var VERTEX_MODEL_ID_ENV = "VERTEX_MODEL_ID";
|
|
106532
|
+
var AZURE_PROVIDER = "azure";
|
|
106533
|
+
var AZURE_RESOURCE_NAME_ENV = "AZURE_RESOURCE_NAME";
|
|
106534
|
+
var AZURE_API_KEY_ENV = "AZURE_API_KEY";
|
|
106535
|
+
var AZURE_DEPLOYMENT_ENV = "AZURE_DEPLOYMENT";
|
|
106536
|
+
var AZURE_CONTEXT_ENV = "AZURE_CONTEXT";
|
|
106537
|
+
var AZURE_MAX_OUTPUT_ENV = "AZURE_MAX_OUTPUT";
|
|
106538
|
+
var AZURE_USE_CHAT_COMPLETIONS_ENV = "AZURE_USE_CHAT_COMPLETIONS";
|
|
106511
106539
|
var OPENAI_COMPATIBLE_PROVIDER = "openai-compatible";
|
|
106512
106540
|
var OPENAI_COMPATIBLE_BASE_URL_ENV = "OPENAI_COMPATIBLE_BASE_URL";
|
|
106513
106541
|
var OPENAI_COMPATIBLE_API_KEY_ENV = "OPENAI_COMPATIBLE_API_KEY";
|
|
@@ -106527,6 +106555,8 @@ function formatMcpToolRef(agentId, toolName) {
|
|
|
106527
106555
|
switch (agentId) {
|
|
106528
106556
|
case "claude":
|
|
106529
106557
|
return `mcp__${pullfrogMcpName}__${toolName}`;
|
|
106558
|
+
case "codex":
|
|
106559
|
+
return `${pullfrogMcpName}__${toolName}`;
|
|
106530
106560
|
case "opencode":
|
|
106531
106561
|
return `${pullfrogMcpName}_${toolName}`;
|
|
106532
106562
|
default:
|
|
@@ -106536,15 +106566,13 @@ function formatMcpToolRef(agentId, toolName) {
|
|
|
106536
106566
|
function extractMcpToolRefs(agentId, text) {
|
|
106537
106567
|
const prefix = formatMcpToolRef(agentId, "");
|
|
106538
106568
|
const escaped = prefix.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
106539
|
-
return [...text.matchAll(new RegExp(
|
|
106569
|
+
return [...text.matchAll(new RegExp(`(?<![A-Za-z0-9_])${escaped}([a-z0-9_]+)`, "g"))].map(
|
|
106570
|
+
(match3) => match3[1]
|
|
106571
|
+
);
|
|
106540
106572
|
}
|
|
106541
|
-
function
|
|
106573
|
+
function findDanglingPromptToolRefs(params) {
|
|
106542
106574
|
const registered = new Set(params.toolNames);
|
|
106543
|
-
|
|
106544
|
-
if (dangling.length === 0) return;
|
|
106545
|
-
throw new Error(
|
|
106546
|
-
`prompt advertises ${dangling.length} tool(s) the MCP server did not register: ${dangling.join(", ")}. registered: ${[...registered].sort().join(", ")}`
|
|
106547
|
-
);
|
|
106575
|
+
return [...new Set(extractMcpToolRefs(params.agentId, params.prompt))].filter((name) => !registered.has(name)).sort();
|
|
106548
106576
|
}
|
|
106549
106577
|
function hasSimilarIssues(params) {
|
|
106550
106578
|
return params.repoIntelligence && !!params.event.issue_number && !params.event.is_pr;
|
|
@@ -107030,7 +107058,8 @@ import { pipeline } from "node:stream/promises";
|
|
|
107030
107058
|
async function installFromNpmTarball(params) {
|
|
107031
107059
|
const tempDir = process.env.PULLFROG_TEMP_DIR;
|
|
107032
107060
|
if (!tempDir) throw new Error("PULLFROG_TEMP_DIR is not set");
|
|
107033
|
-
const
|
|
107061
|
+
const packageRoot = join2(tempDir, `npm-${params.packageName.replace(/[^a-z0-9]+/gi, "-")}`);
|
|
107062
|
+
const extractedDir = join2(packageRoot, "package");
|
|
107034
107063
|
const cliPath = join2(extractedDir, params.executablePath);
|
|
107035
107064
|
if (existsSync2(cliPath)) {
|
|
107036
107065
|
log2.debug(`\xBB using cached binary at ${cliPath}`);
|
|
@@ -107056,7 +107085,8 @@ async function installFromNpmTarball(params) {
|
|
|
107056
107085
|
}
|
|
107057
107086
|
}
|
|
107058
107087
|
log2.debug(`\xBB installing ${params.packageName}@${resolvedVersion}...`);
|
|
107059
|
-
|
|
107088
|
+
mkdirSync(packageRoot, { recursive: true });
|
|
107089
|
+
const tarballPath = join2(packageRoot, "package.tgz");
|
|
107060
107090
|
const npmRegistry = process.env.NPM_REGISTRY || "https://registry.npmjs.org";
|
|
107061
107091
|
let tarballUrl;
|
|
107062
107092
|
if (params.packageName.startsWith("@")) {
|
|
@@ -107076,7 +107106,7 @@ async function installFromNpmTarball(params) {
|
|
|
107076
107106
|
await pipeline(response.body, fileStream);
|
|
107077
107107
|
log2.debug(`\xBB downloaded tarball to ${tarballPath}`);
|
|
107078
107108
|
log2.debug(`\xBB extracting tarball...`);
|
|
107079
|
-
const extractResult = spawnSync("tar", ["-xzf", tarballPath, "-C",
|
|
107109
|
+
const extractResult = spawnSync("tar", ["-xzf", tarballPath, "-C", packageRoot], {
|
|
107080
107110
|
stdio: "pipe",
|
|
107081
107111
|
encoding: "utf-8"
|
|
107082
107112
|
});
|
|
@@ -107085,9 +107115,6 @@ async function installFromNpmTarball(params) {
|
|
|
107085
107115
|
`Failed to extract tarball: ${extractResult.stderr || extractResult.stdout || "Unknown error"}`
|
|
107086
107116
|
);
|
|
107087
107117
|
}
|
|
107088
|
-
if (!existsSync2(cliPath)) {
|
|
107089
|
-
throw new Error(`Executable not found in extracted package at ${cliPath}`);
|
|
107090
|
-
}
|
|
107091
107118
|
if (params.installDependencies) {
|
|
107092
107119
|
log2.debug(`\xBB installing dependencies for ${params.packageName}...`);
|
|
107093
107120
|
const installResult = spawnSync("npm", ["install", "--production"], {
|
|
@@ -107108,6 +107135,9 @@ async function installFromNpmTarball(params) {
|
|
|
107108
107135
|
}
|
|
107109
107136
|
log2.debug(`\xBB dependencies installed`);
|
|
107110
107137
|
}
|
|
107138
|
+
if (!existsSync2(cliPath)) {
|
|
107139
|
+
throw new Error(`Executable not found in extracted package at ${cliPath}`);
|
|
107140
|
+
}
|
|
107111
107141
|
chmodSync(cliPath, 493);
|
|
107112
107142
|
log2.debug(`\xBB ${params.packageName} installed at ${cliPath}`);
|
|
107113
107143
|
return cliPath;
|
|
@@ -107281,6 +107311,7 @@ function resolveRunAlias(ctx) {
|
|
|
107281
107311
|
}
|
|
107282
107312
|
const model = ctx.resolvedModel;
|
|
107283
107313
|
if (!model) return void 0;
|
|
107314
|
+
if (model.startsWith(`${AZURE_PROVIDER}/`)) return void 0;
|
|
107284
107315
|
return modelAliases.find((a2) => !a2.fallback && a2.resolve === model) ?? matchHostedAnthropicAlias(model);
|
|
107285
107316
|
}
|
|
107286
107317
|
function ossEffortFloor(ctx) {
|
|
@@ -107319,7 +107350,7 @@ var import_semver = __toESM(require_semver2(), 1);
|
|
|
107319
107350
|
// package.json
|
|
107320
107351
|
var package_default = {
|
|
107321
107352
|
name: "pullfrog",
|
|
107322
|
-
version: "0.1.
|
|
107353
|
+
version: "0.1.59",
|
|
107323
107354
|
type: "module",
|
|
107324
107355
|
bin: {
|
|
107325
107356
|
pullfrog: "dist/cli.mjs",
|
|
@@ -107351,6 +107382,8 @@ var package_default = {
|
|
|
107351
107382
|
"@clack/prompts": "^1.2.0",
|
|
107352
107383
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
107353
107384
|
"@opencode-ai/sdk": "1.18.5",
|
|
107385
|
+
"@openai/codex": "0.147.0",
|
|
107386
|
+
"@openai/codex-sdk": "0.147.0",
|
|
107354
107387
|
"@octokit/plugin-throttling": "^11.0.3",
|
|
107355
107388
|
"@octokit/rest": "^22.0.0",
|
|
107356
107389
|
"@octokit/webhooks-types": "^7.6.1",
|
|
@@ -109472,13 +109505,735 @@ var claude = agent({
|
|
|
109472
109505
|
}
|
|
109473
109506
|
});
|
|
109474
109507
|
|
|
109475
|
-
// agents/
|
|
109508
|
+
// agents/codex.ts
|
|
109476
109509
|
var core2 = __toESM(require_core(), 1);
|
|
109477
|
-
import {
|
|
109478
|
-
import { mkdirSync as mkdirSync6, writeFileSync as writeFileSync6 } from "node:fs";
|
|
109510
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync6, readFileSync as readFileSync3, writeFileSync as writeFileSync6 } from "node:fs";
|
|
109479
109511
|
import { join as join7 } from "node:path";
|
|
109480
109512
|
import { performance as performance6 } from "node:perf_hooks";
|
|
109481
109513
|
|
|
109514
|
+
// utils/codexHome.ts
|
|
109515
|
+
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
109516
|
+
import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync5 } from "node:fs";
|
|
109517
|
+
import { homedir as homedir2, userInfo } from "node:os";
|
|
109518
|
+
import { join as join6 } from "node:path";
|
|
109519
|
+
var CODEX_AUTH_ENV = "CODEX_AUTH_JSON";
|
|
109520
|
+
var PULLFROG_DATA_DIR = "/var/lib/pullfrog";
|
|
109521
|
+
function isRejectedChain(body) {
|
|
109522
|
+
if (!body.refresh_rejected_at) return false;
|
|
109523
|
+
log2.warning(
|
|
109524
|
+
`\xBB ${CODEX_AUTH_ENV} was rejected by OpenAI at ${body.refresh_rejected_at} and cannot be refreshed \u2014 re-run \`npx pullfrog auth codex\`. skipping it for this run.`
|
|
109525
|
+
);
|
|
109526
|
+
return true;
|
|
109527
|
+
}
|
|
109528
|
+
function installCodexAuth() {
|
|
109529
|
+
const raw2 = process.env[CODEX_AUTH_ENV];
|
|
109530
|
+
if (!raw2) return null;
|
|
109531
|
+
const body = parseCodexAuthBody(raw2);
|
|
109532
|
+
if (!body) {
|
|
109533
|
+
log2.warning(`\xBB ${CODEX_AUTH_ENV} present but malformed; ignoring`);
|
|
109534
|
+
return null;
|
|
109535
|
+
}
|
|
109536
|
+
if (isRejectedChain(body)) return null;
|
|
109537
|
+
const expiresMs = decodeJwtExpMs(body.tokens.access_token) ?? 0;
|
|
109538
|
+
const xdgDataHome = resolveDataHome();
|
|
109539
|
+
const opencodeDir = join6(xdgDataHome, "opencode");
|
|
109540
|
+
const authPath = join6(opencodeDir, "auth.json");
|
|
109541
|
+
const opencodeAuth = {
|
|
109542
|
+
openai: {
|
|
109543
|
+
type: "oauth",
|
|
109544
|
+
refresh: body.tokens.refresh_token,
|
|
109545
|
+
access: body.tokens.access_token,
|
|
109546
|
+
expires: expiresMs,
|
|
109547
|
+
...body.tokens.account_id ? { accountId: body.tokens.account_id } : {}
|
|
109548
|
+
}
|
|
109549
|
+
};
|
|
109550
|
+
mkdirSync5(opencodeDir, { recursive: true });
|
|
109551
|
+
writeFileSync5(authPath, `${JSON.stringify(opencodeAuth, null, 2)}
|
|
109552
|
+
`, { mode: 384 });
|
|
109553
|
+
process.env.XDG_DATA_HOME = xdgDataHome;
|
|
109554
|
+
log2.info(`\xBB installed Codex auth at ${authPath}`);
|
|
109555
|
+
return {
|
|
109556
|
+
authPath,
|
|
109557
|
+
xdgDataHome,
|
|
109558
|
+
originalRefresh: body.tokens.refresh_token,
|
|
109559
|
+
originalIdToken: body.tokens.id_token
|
|
109560
|
+
};
|
|
109561
|
+
}
|
|
109562
|
+
function installCodexHome() {
|
|
109563
|
+
const raw2 = process.env[CODEX_AUTH_ENV];
|
|
109564
|
+
if (!raw2) return null;
|
|
109565
|
+
const body = parseCodexAuthBody(raw2);
|
|
109566
|
+
if (!body) {
|
|
109567
|
+
log2.warning(`\xBB ${CODEX_AUTH_ENV} present but malformed; ignoring`);
|
|
109568
|
+
return null;
|
|
109569
|
+
}
|
|
109570
|
+
if (isRejectedChain(body)) return null;
|
|
109571
|
+
if (!body.tokens.id_token) {
|
|
109572
|
+
log2.warning(
|
|
109573
|
+
`\xBB ${CODEX_AUTH_ENV} carries no id_token \u2014 the codex CLI cannot load it. re-run \`npx pullfrog auth codex\` to mint a complete credential.`
|
|
109574
|
+
);
|
|
109575
|
+
return null;
|
|
109576
|
+
}
|
|
109577
|
+
const codexHome = join6(resolveDataHome(), "codex");
|
|
109578
|
+
const authPath = join6(codexHome, "auth.json");
|
|
109579
|
+
mkdirSync5(codexHome, { recursive: true });
|
|
109580
|
+
writeFileSync5(authPath, stringifyCodexAuthBody(body), { mode: 384 });
|
|
109581
|
+
log2.info(`\xBB installed Codex auth at ${authPath}`);
|
|
109582
|
+
return { codexHome, authPath, originalRefresh: body.tokens.refresh_token };
|
|
109583
|
+
}
|
|
109584
|
+
function resolveDataHome() {
|
|
109585
|
+
if (process.env.CI !== "true") return join6(homedir2(), ".local", "share");
|
|
109586
|
+
bootstrapPullfrogDataDir();
|
|
109587
|
+
return PULLFROG_DATA_DIR;
|
|
109588
|
+
}
|
|
109589
|
+
function bootstrapPullfrogDataDir() {
|
|
109590
|
+
const user = userInfo().username;
|
|
109591
|
+
let primaryGroup;
|
|
109592
|
+
try {
|
|
109593
|
+
primaryGroup = execFileSync4("id", ["-gn", user], { stdio: "pipe", encoding: "utf-8" }).trim();
|
|
109594
|
+
} catch {
|
|
109595
|
+
primaryGroup = user;
|
|
109596
|
+
}
|
|
109597
|
+
try {
|
|
109598
|
+
execFileSync4("sudo", ["-n", "mkdir", "-p", PULLFROG_DATA_DIR], { stdio: "pipe" });
|
|
109599
|
+
execFileSync4("sudo", ["-n", "chown", `${user}:${primaryGroup}`, PULLFROG_DATA_DIR], {
|
|
109600
|
+
stdio: "pipe"
|
|
109601
|
+
});
|
|
109602
|
+
execFileSync4("sudo", ["-n", "chmod", "700", PULLFROG_DATA_DIR], { stdio: "pipe" });
|
|
109603
|
+
} catch (err) {
|
|
109604
|
+
throw new Error(
|
|
109605
|
+
`failed to bootstrap ${PULLFROG_DATA_DIR} (required for codex auth in CI): ${err instanceof Error ? err.message : String(err)}. the MCP shell's mount-namespace sandbox cannot protect the auth file when it lives under $HOME, and silently falling back would contradict the "three independent layers" claim in wiki/codex-auth.md. passwordless sudo is required for codex auth on this runner \u2014 either configure it, or remove CODEX_AUTH_JSON from the run.`
|
|
109606
|
+
);
|
|
109607
|
+
}
|
|
109608
|
+
}
|
|
109609
|
+
|
|
109610
|
+
// utils/secrets.ts
|
|
109611
|
+
var SENSITIVE_PATTERNS = [
|
|
109612
|
+
/_KEY$/i,
|
|
109613
|
+
/_SECRET$/i,
|
|
109614
|
+
/_TOKEN$/i,
|
|
109615
|
+
/_PASSWORD$/i,
|
|
109616
|
+
/_CREDENTIAL$/i
|
|
109617
|
+
];
|
|
109618
|
+
function isSensitiveEnvName(key) {
|
|
109619
|
+
return SENSITIVE_PATTERNS.some((p) => p.test(key));
|
|
109620
|
+
}
|
|
109621
|
+
var SAFE_ENV_PREFIXES = ["GITHUB_", "RUNNER_", "JAVA_HOME_", "GOROOT_"];
|
|
109622
|
+
var SAFE_ENV_NAMES = /* @__PURE__ */ new Set([
|
|
109623
|
+
// system
|
|
109624
|
+
"CI",
|
|
109625
|
+
"HOME",
|
|
109626
|
+
"LANG",
|
|
109627
|
+
"LOGNAME",
|
|
109628
|
+
"PATH",
|
|
109629
|
+
"SHELL",
|
|
109630
|
+
"SHLVL",
|
|
109631
|
+
"TERM",
|
|
109632
|
+
"TMPDIR",
|
|
109633
|
+
"TZ",
|
|
109634
|
+
"USER",
|
|
109635
|
+
"XDG_CONFIG_HOME",
|
|
109636
|
+
"XDG_RUNTIME_DIR",
|
|
109637
|
+
"DEBIAN_FRONTEND",
|
|
109638
|
+
// runner image toolchain
|
|
109639
|
+
"ACCEPT_EULA",
|
|
109640
|
+
"AGENT_TOOLSDIRECTORY",
|
|
109641
|
+
"ANDROID_HOME",
|
|
109642
|
+
"ANDROID_NDK",
|
|
109643
|
+
"ANDROID_NDK_HOME",
|
|
109644
|
+
"ANDROID_NDK_LATEST_HOME",
|
|
109645
|
+
"ANDROID_NDK_ROOT",
|
|
109646
|
+
"ANDROID_SDK_ROOT",
|
|
109647
|
+
"ANT_HOME",
|
|
109648
|
+
"AZURE_EXTENSION_DIR",
|
|
109649
|
+
"BOOTSTRAP_HASKELL_NONINTERACTIVE",
|
|
109650
|
+
"CHROME_BIN",
|
|
109651
|
+
"CHROMEWEBDRIVER",
|
|
109652
|
+
"CONDA",
|
|
109653
|
+
"DOTNET_MULTILEVEL_LOOKUP",
|
|
109654
|
+
"DOTNET_NOLOGO",
|
|
109655
|
+
"DOTNET_SKIP_FIRST_TIME_EXPERIENCE",
|
|
109656
|
+
"EDGEWEBDRIVER",
|
|
109657
|
+
"GECKOWEBDRIVER",
|
|
109658
|
+
"GHCUP_INSTALL_BASE_PREFIX",
|
|
109659
|
+
"GRADLE_HOME",
|
|
109660
|
+
"JAVA_HOME",
|
|
109661
|
+
"HOMEBREW_CLEANUP_PERIODIC_FULL_DAYS",
|
|
109662
|
+
"HOMEBREW_NO_AUTO_UPDATE",
|
|
109663
|
+
"ImageOS",
|
|
109664
|
+
"ImageVersion",
|
|
109665
|
+
"NVM_DIR",
|
|
109666
|
+
"PIPX_BIN_DIR",
|
|
109667
|
+
"PIPX_HOME",
|
|
109668
|
+
"PSModulePath",
|
|
109669
|
+
"SELENIUM_JAR_PATH",
|
|
109670
|
+
"SGX_AESM_ADDR",
|
|
109671
|
+
"SWIFT_PATH",
|
|
109672
|
+
"VCPKG_INSTALLATION_ROOT"
|
|
109673
|
+
]);
|
|
109674
|
+
var _userAllowlist = null;
|
|
109675
|
+
function setEnvAllowlist(raw2) {
|
|
109676
|
+
const names = raw2.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
109677
|
+
_userAllowlist = new Set(names);
|
|
109678
|
+
}
|
|
109679
|
+
function isSafeEnvVar(key) {
|
|
109680
|
+
if (SAFE_ENV_NAMES.has(key)) return true;
|
|
109681
|
+
return SAFE_ENV_PREFIXES.some((p) => key.startsWith(p));
|
|
109682
|
+
}
|
|
109683
|
+
var WORKFLOW_COMMAND_ENV_NAMES = [
|
|
109684
|
+
"GITHUB_ENV",
|
|
109685
|
+
"GITHUB_PATH",
|
|
109686
|
+
"GITHUB_OUTPUT",
|
|
109687
|
+
"GITHUB_STATE",
|
|
109688
|
+
"GITHUB_STEP_SUMMARY",
|
|
109689
|
+
// dropping the five paths above but keeping RUNNER_TEMP would be theatre:
|
|
109690
|
+
// the file-command files live in `$RUNNER_TEMP/_runner_file_commands/`, so the
|
|
109691
|
+
// directory is one `ls` away. nothing in the install path reads it (only our
|
|
109692
|
+
// own leak-surface wipe in `setup.ts`, which runs in the parent), and package
|
|
109693
|
+
// managers use TMPDIR.
|
|
109694
|
+
"RUNNER_TEMP"
|
|
109695
|
+
];
|
|
109696
|
+
function filterEnvForUntrustedCode() {
|
|
109697
|
+
const env2 = filterEnv();
|
|
109698
|
+
for (const name of WORKFLOW_COMMAND_ENV_NAMES) delete env2[name];
|
|
109699
|
+
return env2;
|
|
109700
|
+
}
|
|
109701
|
+
function filterEnv() {
|
|
109702
|
+
const filtered = {};
|
|
109703
|
+
for (const [key, value2] of Object.entries(process.env)) {
|
|
109704
|
+
if (value2 === void 0) continue;
|
|
109705
|
+
const userAllowed = _userAllowlist?.has(key) ?? false;
|
|
109706
|
+
if (isSensitiveEnvName(key) && !userAllowed) continue;
|
|
109707
|
+
if (isSafeEnvVar(key) || userAllowed) {
|
|
109708
|
+
filtered[key] = value2;
|
|
109709
|
+
}
|
|
109710
|
+
}
|
|
109711
|
+
return filtered;
|
|
109712
|
+
}
|
|
109713
|
+
function resolveEnv(mode) {
|
|
109714
|
+
if (mode === "inherit") {
|
|
109715
|
+
return process.env;
|
|
109716
|
+
}
|
|
109717
|
+
if (mode === "restricted" || mode === void 0) {
|
|
109718
|
+
return filterEnv();
|
|
109719
|
+
}
|
|
109720
|
+
return { ...filterEnv(), ...mode };
|
|
109721
|
+
}
|
|
109722
|
+
|
|
109723
|
+
// agents/codex.ts
|
|
109724
|
+
var CODEX_TARGETS = {
|
|
109725
|
+
"linux-x64": "x86_64-unknown-linux-musl",
|
|
109726
|
+
"linux-arm64": "aarch64-unknown-linux-musl",
|
|
109727
|
+
"darwin-x64": "x86_64-apple-darwin",
|
|
109728
|
+
"darwin-arm64": "aarch64-apple-darwin",
|
|
109729
|
+
"win32-x64": "x86_64-pc-windows-msvc",
|
|
109730
|
+
"win32-arm64": "aarch64-pc-windows-msvc"
|
|
109731
|
+
};
|
|
109732
|
+
async function installCodexCli() {
|
|
109733
|
+
const target = CODEX_TARGETS[`${process.platform}-${process.arch}`];
|
|
109734
|
+
if (!target) {
|
|
109735
|
+
throw new Error(`the codex CLI ships no binary for ${process.platform}-${process.arch}`);
|
|
109736
|
+
}
|
|
109737
|
+
const binary = process.platform === "win32" ? "codex.exe" : "codex";
|
|
109738
|
+
return await installFromNpmTarball({
|
|
109739
|
+
packageName: "@openai/codex",
|
|
109740
|
+
version: getDevDependencyVersion("@openai/codex"),
|
|
109741
|
+
executablePath: `node_modules/@openai/codex-${process.platform}-${process.arch}/vendor/${target}/bin/${binary}`,
|
|
109742
|
+
installDependencies: true
|
|
109743
|
+
});
|
|
109744
|
+
}
|
|
109745
|
+
var CODEX_DISABLED_FEATURES = [
|
|
109746
|
+
// browser / desktop control — network reach and arbitrary JS
|
|
109747
|
+
"browser_use",
|
|
109748
|
+
"browser_use_external",
|
|
109749
|
+
"browser_use_full_cdp_access",
|
|
109750
|
+
"computer_use",
|
|
109751
|
+
"in_app_browser",
|
|
109752
|
+
// third-party code loaded into the agent process
|
|
109753
|
+
"plugins",
|
|
109754
|
+
"remote_plugin",
|
|
109755
|
+
"plugin_sharing",
|
|
109756
|
+
"skill_mcp_dependency_install",
|
|
109757
|
+
// lifecycle hooks run commands sourced from repo config, which a PR can edit
|
|
109758
|
+
"hooks",
|
|
109759
|
+
// connectors
|
|
109760
|
+
"apps",
|
|
109761
|
+
// ungated subagent fan-out (see the file header)
|
|
109762
|
+
"multi_agent",
|
|
109763
|
+
"multi_agent_v2"
|
|
109764
|
+
];
|
|
109765
|
+
var CODEX_SHELL_FEATURES = ["shell_tool", "unified_exec"];
|
|
109766
|
+
function tomlBool(entries, value2) {
|
|
109767
|
+
return entries.map((name) => `${name} = ${value2}`).join("\n");
|
|
109768
|
+
}
|
|
109769
|
+
function securityOverrideFlags(params) {
|
|
109770
|
+
const shellEnabled = params.ctx.payload.shell === "enabled";
|
|
109771
|
+
const features = [
|
|
109772
|
+
...CODEX_DISABLED_FEATURES.map((name) => `${name}=false`),
|
|
109773
|
+
...CODEX_SHELL_FEATURES.map((name) => `${name}=${shellEnabled}`)
|
|
109774
|
+
];
|
|
109775
|
+
return [
|
|
109776
|
+
"-c",
|
|
109777
|
+
`approval_policy=${JSON.stringify("never")}`,
|
|
109778
|
+
"-c",
|
|
109779
|
+
`sandbox_mode=${JSON.stringify(params.sandboxMode)}`,
|
|
109780
|
+
// the sandbox's EXTENT has to be locked too, not just its mode: a repo
|
|
109781
|
+
// setting `writable_roots = ["/"]` walked straight out of the checkout with
|
|
109782
|
+
// `sandbox_mode` already flag-locked (measured — apply_patch wrote a file
|
|
109783
|
+
// under $HOME).
|
|
109784
|
+
"-c",
|
|
109785
|
+
`sandbox_workspace_write.writable_roots=[${JSON.stringify(params.repoDir)}]`,
|
|
109786
|
+
"-c",
|
|
109787
|
+
"sandbox_workspace_write.network_access=true",
|
|
109788
|
+
// our own MCP server, for a third time in the same class: a repo pointing
|
|
109789
|
+
// `mcp_servers.pullfrog.url` at its own endpoint (measured — `codex mcp get`
|
|
109790
|
+
// reported the repo's URL) turns every pullfrog tool call into an
|
|
109791
|
+
// exfiltration channel, carrying diffs, file contents and cross-repo
|
|
109792
|
+
// learnings to whoever it names.
|
|
109793
|
+
"-c",
|
|
109794
|
+
`mcp_servers.${pullfrogMcpName}.url=${JSON.stringify(params.mcpServerUrl)}`,
|
|
109795
|
+
"-c",
|
|
109796
|
+
`mcp_servers.${pullfrogMcpName}.${APPROVAL_MODE_KEY}=${JSON.stringify("approve")}`,
|
|
109797
|
+
"-c",
|
|
109798
|
+
`mcp_servers.${pullfrogMcpName}.required=true`,
|
|
109799
|
+
"-c",
|
|
109800
|
+
`mcp_servers.${pullfrogMcpName}.tool_timeout_sec=660`,
|
|
109801
|
+
// `enabled` closes the silent-DoS variant: a repo setting it false would
|
|
109802
|
+
// otherwise strip every GitHub tool and leave the agent narrating failure.
|
|
109803
|
+
"-c",
|
|
109804
|
+
`mcp_servers.${pullfrogMcpName}.enabled=true`,
|
|
109805
|
+
// not a boundary, but the same override: a repo silently re-pointing the
|
|
109806
|
+
// model spends the account's money on a pick it never made, and makes the
|
|
109807
|
+
// "Using `…`" run footer a lie about what actually ran.
|
|
109808
|
+
...params.model ? ["-c", `model=${JSON.stringify(params.model)}`] : [],
|
|
109809
|
+
...params.effortRung ? ["-c", `model_reasoning_effort=${JSON.stringify(params.effortRung)}`] : [],
|
|
109810
|
+
...features.flatMap((entry) => ["-c", `features.${entry}`])
|
|
109811
|
+
];
|
|
109812
|
+
}
|
|
109813
|
+
var CODEX_EFFORTS = ["minimal", "low", "medium", "high", "xhigh"];
|
|
109814
|
+
function resolveCodexModel(ctx) {
|
|
109815
|
+
const specifier = ctx.payload.proxyModel ?? ctx.resolvedModel;
|
|
109816
|
+
if (!specifier) return void 0;
|
|
109817
|
+
try {
|
|
109818
|
+
if (getModelProvider(specifier) === "openai") return stripProviderPrefix(specifier);
|
|
109819
|
+
} catch {
|
|
109820
|
+
}
|
|
109821
|
+
log2.warning(`\xBB ${specifier} isn't an OpenAI model \u2014 running codex on its own default instead`);
|
|
109822
|
+
return void 0;
|
|
109823
|
+
}
|
|
109824
|
+
var APPROVAL_MODE_KEY = "default_tools_approval_mode";
|
|
109825
|
+
var APPROVE_TOOLS = `${APPROVAL_MODE_KEY} = "approve"`;
|
|
109826
|
+
function repoMcpApprovals(repoDir) {
|
|
109827
|
+
const path4 = join7(repoDir, ".codex", "config.toml");
|
|
109828
|
+
if (!existsSync4(path4)) return [];
|
|
109829
|
+
const out = [];
|
|
109830
|
+
let section = [];
|
|
109831
|
+
let isServerTable = false;
|
|
109832
|
+
function flush() {
|
|
109833
|
+
if (section.length === 0) return;
|
|
109834
|
+
const declared = section.some((line) => line.trimStart().startsWith(APPROVAL_MODE_KEY));
|
|
109835
|
+
if (isServerTable && !declared) section.splice(1, 0, APPROVE_TOOLS);
|
|
109836
|
+
out.push(...section, "");
|
|
109837
|
+
section = [];
|
|
109838
|
+
}
|
|
109839
|
+
for (const line of readFileSync3(path4, "utf8").split("\n")) {
|
|
109840
|
+
const header = line.trim().match(/^\[(?<key>[^\]]+)\]$/);
|
|
109841
|
+
if (!header?.groups) {
|
|
109842
|
+
if (section.length > 0) section.push(line);
|
|
109843
|
+
continue;
|
|
109844
|
+
}
|
|
109845
|
+
flush();
|
|
109846
|
+
const key = header.groups.key.trim();
|
|
109847
|
+
if (!key.startsWith("mcp_servers.")) continue;
|
|
109848
|
+
const name = key.slice("mcp_servers.".length).replace(/^"([^"]*)"/, "$1");
|
|
109849
|
+
if (name === pullfrogMcpName || name.startsWith(`${pullfrogMcpName}.`)) continue;
|
|
109850
|
+
isServerTable = !name.includes(".");
|
|
109851
|
+
section = [line.trim()];
|
|
109852
|
+
}
|
|
109853
|
+
flush();
|
|
109854
|
+
return out;
|
|
109855
|
+
}
|
|
109856
|
+
function warnIfNativeEditsUnavailable(ctx) {
|
|
109857
|
+
if (process.platform !== "linux" || ctx.payload.shell !== "disabled") return;
|
|
109858
|
+
log2.warning(
|
|
109859
|
+
"\xBB this run cannot change files: codex's native write tool depends on bubblewrap, which Ubuntu 24.04 blocks (https://github.com/openai/codex/issues/29908), and the MCP shell is disabled for this repo. read-only work is unaffected \u2014 set `shell: restricted` if the agent needs to edit anything."
|
|
109860
|
+
);
|
|
109861
|
+
}
|
|
109862
|
+
function writeCodexConfig(params) {
|
|
109863
|
+
const shellEnabled = params.ctx.payload.shell === "enabled";
|
|
109864
|
+
const sandboxMode = params.ctx.payload.push === "disabled" ? "read-only" : "workspace-write";
|
|
109865
|
+
const repoDir = process.cwd();
|
|
109866
|
+
const config3 = [
|
|
109867
|
+
"# written by pullfrog",
|
|
109868
|
+
// "never" keeps the run non-interactive WITHOUT
|
|
109869
|
+
// --dangerously-bypass-approvals-and-sandbox, which would also switch the
|
|
109870
|
+
// sandbox off and let the native apply_patch tool write anywhere.
|
|
109871
|
+
'approval_policy = "never"',
|
|
109872
|
+
`sandbox_mode = ${JSON.stringify(sandboxMode)}`,
|
|
109873
|
+
// matches opencode's `webfetch: "allow"` — research is part of the job and
|
|
109874
|
+
// neither harness gates it on a permission.
|
|
109875
|
+
'web_search = "live"',
|
|
109876
|
+
...params.model ? [`model = ${JSON.stringify(params.model)}`] : [],
|
|
109877
|
+
...params.effortRung ? [`model_reasoning_effort = ${JSON.stringify(params.effortRung)}`] : [],
|
|
109878
|
+
"",
|
|
109879
|
+
"[features]",
|
|
109880
|
+
tomlBool(CODEX_DISABLED_FEATURES, false),
|
|
109881
|
+
tomlBool(CODEX_SHELL_FEATURES, shellEnabled),
|
|
109882
|
+
"",
|
|
109883
|
+
"[sandbox_workspace_write]",
|
|
109884
|
+
"network_access = true",
|
|
109885
|
+
// the checkout, named explicitly rather than left to `workspace-write` to
|
|
109886
|
+
// imply. does NOT fix the Linux native-write failure — nothing here does;
|
|
109887
|
+
// see wiki/codex-agent.md "The Linux native-write blocker".
|
|
109888
|
+
`writable_roots = [${JSON.stringify(repoDir)}]`,
|
|
109889
|
+
"",
|
|
109890
|
+
`[mcp_servers.${pullfrogMcpName}]`,
|
|
109891
|
+
`url = ${JSON.stringify(params.ctx.mcpServerUrl)}`,
|
|
109892
|
+
// codex's default MCP approval mode PROMPTS for anything it can't read as
|
|
109893
|
+
// read-only, and a `codex exec` run has nobody to answer — the call comes
|
|
109894
|
+
// back "user cancelled MCP tool call" and the agent silently accomplishes
|
|
109895
|
+
// nothing. our own server is the trusted one; the boundary is what we
|
|
109896
|
+
// register, not a second confirmation.
|
|
109897
|
+
APPROVE_TOOLS,
|
|
109898
|
+
// a run whose GitHub tools never registered can't do its job, so fail loudly
|
|
109899
|
+
// rather than let the agent improvise without them.
|
|
109900
|
+
"required = true",
|
|
109901
|
+
// mirrors the opencode harness's 660s: `checkout_pr` runs a multi-minute
|
|
109902
|
+
// fetch on large repos and enforces its own 600s deadline, so a shorter
|
|
109903
|
+
// client abort turns a working checkout into a spurious tool error.
|
|
109904
|
+
"tool_timeout_sec = 660",
|
|
109905
|
+
"",
|
|
109906
|
+
...repoMcpApprovals(repoDir),
|
|
109907
|
+
// UNTRUSTED, deliberately, and this one line is the whole config-precedence
|
|
109908
|
+
// boundary. Codex loads `<repo>/.codex/config.toml` as a layer that
|
|
109909
|
+
// OUTRANKS ours (project 25 vs user 20), and its denylist strips none of
|
|
109910
|
+
// `sandbox_mode`, `approval_policy`, `features` or `mcp_servers` — so a
|
|
109911
|
+
// fork PR could ship a config re-enabling the native shell. Marking the
|
|
109912
|
+
// checkout untrusted makes that layer load `disabled`, closing the class
|
|
109913
|
+
// outright rather than key by key: `RawMcpServerConfig` alone has ~26
|
|
109914
|
+
// fields and enumeration can never finish.
|
|
109915
|
+
//
|
|
109916
|
+
// It costs nothing. `codex exec`'s only startup gate is a GIT-REPO check
|
|
109917
|
+
// (`exec/src/lib.rs:796` — `get_git_repo_root(...).is_none()`, whose error
|
|
109918
|
+
// text unhelpfully says "Not inside a trusted directory"), so an untrusted
|
|
109919
|
+
// checkout still runs. And the repo's own MCP servers survive, because
|
|
109920
|
+
// `repoMcpApprovals` above copies them into OUR layer — which is why that
|
|
109921
|
+
// copying exists at all.
|
|
109922
|
+
//
|
|
109923
|
+
// Measured both ways at 0.147.0: `trusted` → the repo's `model` won;
|
|
109924
|
+
// `untrusted` → it did not, and the run proceeded normally.
|
|
109925
|
+
`[projects.${JSON.stringify(repoDir)}]`,
|
|
109926
|
+
'trust_level = "untrusted"',
|
|
109927
|
+
""
|
|
109928
|
+
].join("\n");
|
|
109929
|
+
writeFileSync6(join7(params.codexHome, "config.toml"), config3, { mode: 384 });
|
|
109930
|
+
log2.info(`\xBB codex config: sandbox=${sandboxMode}, nativeShell=${shellEnabled}`);
|
|
109931
|
+
}
|
|
109932
|
+
function toTodoWriteInput(item) {
|
|
109933
|
+
return {
|
|
109934
|
+
todos: item.items.map((todo, index) => ({
|
|
109935
|
+
id: String(index),
|
|
109936
|
+
content: todo.text,
|
|
109937
|
+
status: todo.completed ? "completed" : "pending"
|
|
109938
|
+
}))
|
|
109939
|
+
};
|
|
109940
|
+
}
|
|
109941
|
+
async function runCodex2(params) {
|
|
109942
|
+
const startTime = performance6.now();
|
|
109943
|
+
const thinkingTimer = new ThinkingTimer();
|
|
109944
|
+
const output = new TailBuffer(DEFAULT_MAX_RETAINED_BYTES);
|
|
109945
|
+
const recentStderr = [];
|
|
109946
|
+
let eventCount = 0;
|
|
109947
|
+
let finalOutput = "";
|
|
109948
|
+
let threadId;
|
|
109949
|
+
let turnError = null;
|
|
109950
|
+
let lastProviderError = null;
|
|
109951
|
+
let stdoutBuffer = "";
|
|
109952
|
+
const tokens = { input: 0, cacheRead: 0, output: 0 };
|
|
109953
|
+
function buildUsage2() {
|
|
109954
|
+
if (tokens.input === 0 && tokens.output === 0) return void 0;
|
|
109955
|
+
return {
|
|
109956
|
+
agent: "codex",
|
|
109957
|
+
inputTokens: tokens.input,
|
|
109958
|
+
outputTokens: tokens.output,
|
|
109959
|
+
cacheReadTokens: tokens.cacheRead || void 0
|
|
109960
|
+
};
|
|
109961
|
+
}
|
|
109962
|
+
function onItem(item, phase) {
|
|
109963
|
+
switch (item.type) {
|
|
109964
|
+
case "agent_message":
|
|
109965
|
+
if (phase === "completed" && item.text.trim()) {
|
|
109966
|
+
finalOutput = item.text.trim();
|
|
109967
|
+
log2.box(finalOutput, { title: "Pullfrog" });
|
|
109968
|
+
}
|
|
109969
|
+
return;
|
|
109970
|
+
case "reasoning":
|
|
109971
|
+
if (phase === "completed" && item.text.trim()) {
|
|
109972
|
+
log2.box(item.text.trim(), { title: "Pullfrog" });
|
|
109973
|
+
}
|
|
109974
|
+
return;
|
|
109975
|
+
case "command_execution":
|
|
109976
|
+
if (phase === "started") {
|
|
109977
|
+
thinkingTimer.markToolCall();
|
|
109978
|
+
log2.toolCall({ toolName: "shell", input: { command: item.command } });
|
|
109979
|
+
return;
|
|
109980
|
+
}
|
|
109981
|
+
thinkingTimer.markToolResult();
|
|
109982
|
+
log2.startGroup("shell output");
|
|
109983
|
+
log2.info(item.aggregated_output || "");
|
|
109984
|
+
log2.endGroup();
|
|
109985
|
+
return;
|
|
109986
|
+
case "mcp_tool_call":
|
|
109987
|
+
if (phase === "started") {
|
|
109988
|
+
thinkingTimer.markToolCall();
|
|
109989
|
+
params.onToolUse?.({ toolName: item.tool, input: item.arguments });
|
|
109990
|
+
log2.toolCall({ toolName: `${item.server}__${item.tool}`, input: item.arguments });
|
|
109991
|
+
if (item.tool.includes("report_progress")) params.todoTracker?.cancel();
|
|
109992
|
+
return;
|
|
109993
|
+
}
|
|
109994
|
+
thinkingTimer.markToolResult();
|
|
109995
|
+
if (item.error) log2.info(`\xBB tool error: ${item.error.message}`);
|
|
109996
|
+
return;
|
|
109997
|
+
case "file_change":
|
|
109998
|
+
if (phase === "completed") {
|
|
109999
|
+
const paths = item.changes.map((c2) => `${c2.kind} ${c2.path}`).join(", ");
|
|
110000
|
+
log2.info(`\xBB apply_patch (${item.status}): ${paths}`);
|
|
110001
|
+
}
|
|
110002
|
+
return;
|
|
110003
|
+
case "web_search":
|
|
110004
|
+
if (phase === "started") log2.toolCall({ toolName: "web_search", input: item.query });
|
|
110005
|
+
return;
|
|
110006
|
+
case "todo_list":
|
|
110007
|
+
if (params.todoTracker?.enabled) params.todoTracker.update(toTodoWriteInput(item));
|
|
110008
|
+
return;
|
|
110009
|
+
case "error":
|
|
110010
|
+
log2.info(`\xBB ${item.message}`);
|
|
110011
|
+
return;
|
|
110012
|
+
default:
|
|
110013
|
+
item;
|
|
110014
|
+
}
|
|
110015
|
+
}
|
|
110016
|
+
function onEvent(event) {
|
|
110017
|
+
switch (event.type) {
|
|
110018
|
+
case "thread.started":
|
|
110019
|
+
threadId = event.thread_id;
|
|
110020
|
+
return;
|
|
110021
|
+
case "turn.completed":
|
|
110022
|
+
tokens.input += event.usage.input_tokens ?? 0;
|
|
110023
|
+
tokens.cacheRead += event.usage.cached_input_tokens ?? 0;
|
|
110024
|
+
tokens.output += event.usage.output_tokens ?? 0;
|
|
110025
|
+
return;
|
|
110026
|
+
case "turn.failed":
|
|
110027
|
+
turnError = event.error.message;
|
|
110028
|
+
log2.info(`\xBB turn failed: ${turnError}`);
|
|
110029
|
+
return;
|
|
110030
|
+
case "error":
|
|
110031
|
+
turnError = event.message;
|
|
110032
|
+
log2.info(`\xBB codex error: ${event.message}`);
|
|
110033
|
+
return;
|
|
110034
|
+
case "item.started":
|
|
110035
|
+
onItem(event.item, "started");
|
|
110036
|
+
return;
|
|
110037
|
+
case "item.completed":
|
|
110038
|
+
onItem(event.item, "completed");
|
|
110039
|
+
return;
|
|
110040
|
+
case "item.updated":
|
|
110041
|
+
if (event.item.type === "todo_list") onItem(event.item, "started");
|
|
110042
|
+
return;
|
|
110043
|
+
case "turn.started":
|
|
110044
|
+
return;
|
|
110045
|
+
default:
|
|
110046
|
+
event;
|
|
110047
|
+
}
|
|
110048
|
+
}
|
|
110049
|
+
try {
|
|
110050
|
+
const result = await spawn3({
|
|
110051
|
+
cmd: params.cliPath,
|
|
110052
|
+
args: params.args,
|
|
110053
|
+
cwd: params.cwd,
|
|
110054
|
+
env: params.env,
|
|
110055
|
+
activityTimeout: AGENT_ACTIVITY_TIMEOUT_MS,
|
|
110056
|
+
onActivityTimeout: params.onActivityTimeout,
|
|
110057
|
+
// stdin MUST be `ignore`: codex reads a piped stdin as an extra `<stdin>`
|
|
110058
|
+
// prompt block and blocks on EOF, so an inherited pipe hangs the run
|
|
110059
|
+
// before the first model call.
|
|
110060
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
110061
|
+
killGroup: true,
|
|
110062
|
+
retain: "none",
|
|
110063
|
+
onStdout: (chunk) => {
|
|
110064
|
+
output.append(chunk);
|
|
110065
|
+
markActivity();
|
|
110066
|
+
stdoutBuffer += chunk;
|
|
110067
|
+
const lines = stdoutBuffer.split("\n");
|
|
110068
|
+
stdoutBuffer = lines.pop() || "";
|
|
110069
|
+
for (const line of lines) {
|
|
110070
|
+
const trimmed = line.trim();
|
|
110071
|
+
if (!trimmed) continue;
|
|
110072
|
+
let event;
|
|
110073
|
+
try {
|
|
110074
|
+
event = JSON.parse(trimmed);
|
|
110075
|
+
} catch {
|
|
110076
|
+
log2.debug(`\xBB non-JSON stdout line: ${trimmed.substring(0, 200)}`);
|
|
110077
|
+
continue;
|
|
110078
|
+
}
|
|
110079
|
+
eventCount++;
|
|
110080
|
+
log2.debug(JSON.stringify(event, null, 2));
|
|
110081
|
+
const idleMs = getIdleMs();
|
|
110082
|
+
if (idleMs > 1e4) {
|
|
110083
|
+
log2.info(
|
|
110084
|
+
`\xBB no activity for ${(idleMs / 1e3).toFixed(1)}s (${eventCount} events processed so far)`
|
|
110085
|
+
);
|
|
110086
|
+
}
|
|
110087
|
+
markActivity();
|
|
110088
|
+
onEvent(event);
|
|
110089
|
+
}
|
|
110090
|
+
},
|
|
110091
|
+
onStderr: (chunk) => {
|
|
110092
|
+
const trimmed = chunk.trim();
|
|
110093
|
+
if (!trimmed) return;
|
|
110094
|
+
recentStderr.push(trimmed);
|
|
110095
|
+
if (recentStderr.length > MAX_STDERR_LINES) recentStderr.shift();
|
|
110096
|
+
const match3 = findProviderErrorMatch(trimmed);
|
|
110097
|
+
if (match3) {
|
|
110098
|
+
lastProviderError = match3.label;
|
|
110099
|
+
log2.info(`\xBB provider error detected (${match3.label}): ${match3.excerpt}`);
|
|
110100
|
+
} else {
|
|
110101
|
+
log2.debug(trimmed);
|
|
110102
|
+
}
|
|
110103
|
+
}
|
|
110104
|
+
});
|
|
110105
|
+
const duration4 = performance6.now() - startTime;
|
|
110106
|
+
log2.info(`\xBB codex completed in ${Math.round(duration4)}ms with exit code ${result.exitCode}`);
|
|
110107
|
+
const usage = buildUsage2();
|
|
110108
|
+
if (usage) {
|
|
110109
|
+
logTokenTable({
|
|
110110
|
+
input: tokens.input - tokens.cacheRead,
|
|
110111
|
+
cacheRead: tokens.cacheRead,
|
|
110112
|
+
cacheWrite: 0,
|
|
110113
|
+
output: tokens.output
|
|
110114
|
+
});
|
|
110115
|
+
}
|
|
110116
|
+
if (result.exitCode !== 0 || turnError) {
|
|
110117
|
+
const stderrSnapshot = recentStderr.join("\n");
|
|
110118
|
+
const error52 = turnError || stderrSnapshot || lastProviderError && `provider error: ${lastProviderError}` || `unknown error - no output from Codex CLI (exit ${result.exitCode})`;
|
|
110119
|
+
log2.error(`codex exited with code ${result.exitCode}: ${error52}`);
|
|
110120
|
+
return { success: false, output: finalOutput || output.toString(), error: error52, usage, threadId };
|
|
110121
|
+
}
|
|
110122
|
+
return { success: true, output: finalOutput || output.toString(), usage, threadId };
|
|
110123
|
+
} catch (error52) {
|
|
110124
|
+
const duration4 = performance6.now() - startTime;
|
|
110125
|
+
const message = error52 instanceof Error ? error52.message : String(error52);
|
|
110126
|
+
const isActivityTimeout = error52 instanceof SpawnTimeoutError && error52.code === SPAWN_ACTIVITY_TIMEOUT_CODE;
|
|
110127
|
+
const diagnosis = lastProviderError ? `likely cause: ${lastProviderError}` : eventCount === 0 ? "codex produced 0 stdout events - check if the API is reachable" : `${eventCount} events were processed before the hang`;
|
|
110128
|
+
log2.info(
|
|
110129
|
+
`\xBB codex ${isActivityTimeout ? "hung" : "failed"} after ${(duration4 / 1e3).toFixed(1)}s: ${message}`
|
|
110130
|
+
);
|
|
110131
|
+
log2.info(`\xBB diagnosis: ${diagnosis}`);
|
|
110132
|
+
if (recentStderr.length > 0) log2.info(`\xBB recent stderr:
|
|
110133
|
+
${recentStderr.join("\n")}`);
|
|
110134
|
+
return {
|
|
110135
|
+
success: false,
|
|
110136
|
+
output: finalOutput || output.toString(),
|
|
110137
|
+
error: `${message} [${diagnosis}]`,
|
|
110138
|
+
usage: buildUsage2(),
|
|
110139
|
+
threadId
|
|
110140
|
+
};
|
|
110141
|
+
}
|
|
110142
|
+
}
|
|
110143
|
+
var codex = agent({
|
|
110144
|
+
name: "codex",
|
|
110145
|
+
install: installCodexCli,
|
|
110146
|
+
run: async (ctx) => {
|
|
110147
|
+
const cliPath = await installCodexCli();
|
|
110148
|
+
warnIfNativeEditsUnavailable(ctx);
|
|
110149
|
+
const codexHomeAuth = installCodexHome();
|
|
110150
|
+
const codexHome = codexHomeAuth?.codexHome ?? join7(ctx.tmpdir, ".codex");
|
|
110151
|
+
mkdirSync6(codexHome, { recursive: true });
|
|
110152
|
+
const effort = resolveRunEffort(ctx);
|
|
110153
|
+
if (effort.rung && !CODEX_EFFORTS.includes(effort.rung)) {
|
|
110154
|
+
log2.warning(`\xBB effort ${effort.rung} not sent \u2014 codex doesn't accept that level`);
|
|
110155
|
+
}
|
|
110156
|
+
writeCodexConfig({
|
|
110157
|
+
ctx,
|
|
110158
|
+
codexHome,
|
|
110159
|
+
model: resolveCodexModel(ctx),
|
|
110160
|
+
effortRung: effort.rung && CODEX_EFFORTS.includes(effort.rung) ? effort.rung : void 0
|
|
110161
|
+
});
|
|
110162
|
+
if (codexHomeAuth) {
|
|
110163
|
+
core2.saveState(
|
|
110164
|
+
"codex_writeback",
|
|
110165
|
+
JSON.stringify({
|
|
110166
|
+
apiToken: ctx.apiToken,
|
|
110167
|
+
authPath: codexHomeAuth.authPath,
|
|
110168
|
+
originalRefresh: codexHomeAuth.originalRefresh
|
|
110169
|
+
})
|
|
110170
|
+
);
|
|
110171
|
+
}
|
|
110172
|
+
const baseEnv = ctx.payload.shell === "enabled" ? process.env : filterEnv();
|
|
110173
|
+
const env2 = {
|
|
110174
|
+
...baseEnv,
|
|
110175
|
+
CODEX_HOME: codexHome,
|
|
110176
|
+
PWD: process.cwd()
|
|
110177
|
+
};
|
|
110178
|
+
delete env2.CODEX_API_KEY;
|
|
110179
|
+
if (codexHomeAuth) {
|
|
110180
|
+
delete env2.OPENAI_API_KEY;
|
|
110181
|
+
} else if (process.env.OPENAI_API_KEY) {
|
|
110182
|
+
env2.CODEX_API_KEY = process.env.OPENAI_API_KEY;
|
|
110183
|
+
}
|
|
110184
|
+
const securityFlags = securityOverrideFlags({
|
|
110185
|
+
ctx,
|
|
110186
|
+
sandboxMode: ctx.payload.push === "disabled" ? "read-only" : "workspace-write",
|
|
110187
|
+
repoDir: process.cwd(),
|
|
110188
|
+
mcpServerUrl: ctx.mcpServerUrl,
|
|
110189
|
+
model: resolveCodexModel(ctx),
|
|
110190
|
+
effortRung: effort.rung && CODEX_EFFORTS.includes(effort.rung) ? effort.rung : void 0
|
|
110191
|
+
});
|
|
110192
|
+
const runnerArgs = { cliPath, cwd: process.cwd(), env: env2, todoTracker: ctx.todoTracker };
|
|
110193
|
+
const initial = await runCodex2({
|
|
110194
|
+
...runnerArgs,
|
|
110195
|
+
args: [...securityFlags, "exec", "--json", ctx.instructions.full],
|
|
110196
|
+
onActivityTimeout: ctx.onActivityTimeout,
|
|
110197
|
+
onToolUse: ctx.onToolUse
|
|
110198
|
+
});
|
|
110199
|
+
const result = await runPostRunRetryLoop({
|
|
110200
|
+
ctx,
|
|
110201
|
+
initialResult: initial,
|
|
110202
|
+
initialUsage: initial.usage,
|
|
110203
|
+
reflectionPrompt: buildReflectionPrompt(ctx.toolState),
|
|
110204
|
+
// a resume needs the thread codex recorded. without one there is nothing
|
|
110205
|
+
// to continue, and `resume --last` would be worse than not resuming: it
|
|
110206
|
+
// picks the newest recorded session in this cwd, which on a self-hosted
|
|
110207
|
+
// runner with a shared CODEX_HOME is somebody else's run.
|
|
110208
|
+
canResume: (r2) => r2.threadId !== void 0,
|
|
110209
|
+
resume: async (c2) => runCodex2({
|
|
110210
|
+
...runnerArgs,
|
|
110211
|
+
args: [
|
|
110212
|
+
...securityFlags,
|
|
110213
|
+
"exec",
|
|
110214
|
+
"resume",
|
|
110215
|
+
"--json",
|
|
110216
|
+
c2.previousResult.threadId ?? "",
|
|
110217
|
+
c2.prompt
|
|
110218
|
+
]
|
|
110219
|
+
})
|
|
110220
|
+
});
|
|
110221
|
+
if (result.success) {
|
|
110222
|
+
await ctx.todoTracker?.flush();
|
|
110223
|
+
} else {
|
|
110224
|
+
ctx.todoTracker?.cancel();
|
|
110225
|
+
}
|
|
110226
|
+
return result;
|
|
110227
|
+
}
|
|
110228
|
+
});
|
|
110229
|
+
|
|
110230
|
+
// agents/opencode.ts
|
|
110231
|
+
var core3 = __toESM(require_core(), 1);
|
|
110232
|
+
import { spawn as nodeSpawn2 } from "node:child_process";
|
|
110233
|
+
import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync7 } from "node:fs";
|
|
110234
|
+
import { join as join8 } from "node:path";
|
|
110235
|
+
import { performance as performance7 } from "node:perf_hooks";
|
|
110236
|
+
|
|
109482
110237
|
// node_modules/.pnpm/@opencode-ai+sdk@1.18.5/node_modules/@opencode-ai/sdk/dist/v2/gen/core/serverSentEvents.gen.js
|
|
109483
110238
|
var createSseClient = ({ onRequest, onSseError, onSseEvent, responseTransformer, responseValidator, sseDefaultRetryDelay, sseMaxRetryAttempts, sseMaxRetryDelay, sseSleepFn, url: url4, ...options }) => {
|
|
109484
110239
|
let lastEventId;
|
|
@@ -114885,71 +115640,6 @@ var import_cross_spawn = __toESM(require_cross_spawn(), 1);
|
|
|
114885
115640
|
// agents/opencode.ts
|
|
114886
115641
|
var import_undici = __toESM(require_undici2(), 1);
|
|
114887
115642
|
|
|
114888
|
-
// utils/codexHome.ts
|
|
114889
|
-
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
114890
|
-
import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync5 } from "node:fs";
|
|
114891
|
-
import { homedir as homedir2, userInfo } from "node:os";
|
|
114892
|
-
import { join as join6 } from "node:path";
|
|
114893
|
-
var CODEX_AUTH_ENV = "CODEX_AUTH_JSON";
|
|
114894
|
-
var PULLFROG_DATA_DIR = "/var/lib/pullfrog";
|
|
114895
|
-
function installCodexAuth() {
|
|
114896
|
-
const raw2 = process.env[CODEX_AUTH_ENV];
|
|
114897
|
-
if (!raw2) return null;
|
|
114898
|
-
const body = parseCodexAuthBody(raw2);
|
|
114899
|
-
if (!body) {
|
|
114900
|
-
log2.warning(`\xBB ${CODEX_AUTH_ENV} present but malformed; ignoring`);
|
|
114901
|
-
return null;
|
|
114902
|
-
}
|
|
114903
|
-
const expiresMs = decodeJwtExpMs(body.tokens.access_token) ?? 0;
|
|
114904
|
-
const xdgDataHome = resolveDataHome();
|
|
114905
|
-
const opencodeDir = join6(xdgDataHome, "opencode");
|
|
114906
|
-
const authPath = join6(opencodeDir, "auth.json");
|
|
114907
|
-
const opencodeAuth = {
|
|
114908
|
-
openai: {
|
|
114909
|
-
type: "oauth",
|
|
114910
|
-
refresh: body.tokens.refresh_token,
|
|
114911
|
-
access: body.tokens.access_token,
|
|
114912
|
-
expires: expiresMs,
|
|
114913
|
-
...body.tokens.account_id ? { accountId: body.tokens.account_id } : {}
|
|
114914
|
-
}
|
|
114915
|
-
};
|
|
114916
|
-
mkdirSync5(opencodeDir, { recursive: true });
|
|
114917
|
-
writeFileSync5(authPath, `${JSON.stringify(opencodeAuth, null, 2)}
|
|
114918
|
-
`, { mode: 384 });
|
|
114919
|
-
process.env.XDG_DATA_HOME = xdgDataHome;
|
|
114920
|
-
log2.info(`\xBB installed Codex auth at ${authPath}`);
|
|
114921
|
-
return {
|
|
114922
|
-
authPath,
|
|
114923
|
-
xdgDataHome,
|
|
114924
|
-
originalRefresh: body.tokens.refresh_token
|
|
114925
|
-
};
|
|
114926
|
-
}
|
|
114927
|
-
function resolveDataHome() {
|
|
114928
|
-
if (process.env.CI !== "true") return join6(homedir2(), ".local", "share");
|
|
114929
|
-
bootstrapPullfrogDataDir();
|
|
114930
|
-
return PULLFROG_DATA_DIR;
|
|
114931
|
-
}
|
|
114932
|
-
function bootstrapPullfrogDataDir() {
|
|
114933
|
-
const user = userInfo().username;
|
|
114934
|
-
let primaryGroup;
|
|
114935
|
-
try {
|
|
114936
|
-
primaryGroup = execFileSync4("id", ["-gn", user], { stdio: "pipe", encoding: "utf-8" }).trim();
|
|
114937
|
-
} catch {
|
|
114938
|
-
primaryGroup = user;
|
|
114939
|
-
}
|
|
114940
|
-
try {
|
|
114941
|
-
execFileSync4("sudo", ["-n", "mkdir", "-p", PULLFROG_DATA_DIR], { stdio: "pipe" });
|
|
114942
|
-
execFileSync4("sudo", ["-n", "chown", `${user}:${primaryGroup}`, PULLFROG_DATA_DIR], {
|
|
114943
|
-
stdio: "pipe"
|
|
114944
|
-
});
|
|
114945
|
-
execFileSync4("sudo", ["-n", "chmod", "700", PULLFROG_DATA_DIR], { stdio: "pipe" });
|
|
114946
|
-
} catch (err) {
|
|
114947
|
-
throw new Error(
|
|
114948
|
-
`failed to bootstrap ${PULLFROG_DATA_DIR} (required for codex auth in CI): ${err instanceof Error ? err.message : String(err)}. the MCP shell's mount-namespace sandbox cannot protect the auth file when it lives under $HOME, and silently falling back would contradict the "three independent layers" claim in wiki/codex-auth.md. passwordless sudo is required for codex auth on this runner \u2014 either configure it, or remove CODEX_AUTH_JSON from the run.`
|
|
114949
|
-
);
|
|
114950
|
-
}
|
|
114951
|
-
}
|
|
114952
|
-
|
|
114953
115643
|
// utils/worktree.ts
|
|
114954
115644
|
async function dirtyTrackedPaths(params = {}) {
|
|
114955
115645
|
const result = await spawn3({
|
|
@@ -115217,6 +115907,30 @@ function openAICompatibleProvider(model) {
|
|
|
115217
115907
|
}
|
|
115218
115908
|
};
|
|
115219
115909
|
}
|
|
115910
|
+
function azureProvider(model) {
|
|
115911
|
+
const prefix = `${AZURE_PROVIDER}/`;
|
|
115912
|
+
if (!model?.startsWith(prefix)) return {};
|
|
115913
|
+
const deployment = model.slice(prefix.length);
|
|
115914
|
+
return {
|
|
115915
|
+
[AZURE_PROVIDER]: {
|
|
115916
|
+
// always sent: opencode reads it as `Boolean(options?.useCompletionUrls)`,
|
|
115917
|
+
// so `false` and absent are the same, and the deep merge keeps the native
|
|
115918
|
+
// loader's `resourceName` either way.
|
|
115919
|
+
options: {
|
|
115920
|
+
useCompletionUrls: process.env[AZURE_USE_CHAT_COMPLETIONS_ENV]?.trim() === "true"
|
|
115921
|
+
},
|
|
115922
|
+
models: {
|
|
115923
|
+
[deployment]: {
|
|
115924
|
+
name: deployment,
|
|
115925
|
+
limit: {
|
|
115926
|
+
context: Number(process.env[AZURE_CONTEXT_ENV]),
|
|
115927
|
+
output: Number(process.env[AZURE_MAX_OUTPUT_ENV])
|
|
115928
|
+
}
|
|
115929
|
+
}
|
|
115930
|
+
}
|
|
115931
|
+
}
|
|
115932
|
+
};
|
|
115933
|
+
}
|
|
115220
115934
|
var KIMI_ENFORCERLESS_PROVIDERS = ["siliconflow", "together"];
|
|
115221
115935
|
function kimiOpenRouterProviderOverrides() {
|
|
115222
115936
|
return Object.fromEntries(
|
|
@@ -115308,7 +116022,8 @@ function buildSecurityConfig(ctx, model) {
|
|
|
115308
116022
|
// see opencodeShared.ts.
|
|
115309
116023
|
provider: {
|
|
115310
116024
|
openrouter: { models: kimiOpenRouterProviderOverrides() },
|
|
115311
|
-
...openAICompatibleProvider(model)
|
|
116025
|
+
...openAICompatibleProvider(model),
|
|
116026
|
+
...azureProvider(model)
|
|
115312
116027
|
}
|
|
115313
116028
|
};
|
|
115314
116029
|
if (model) {
|
|
@@ -115476,7 +116191,7 @@ function isModelOutput(ctx, part) {
|
|
|
115476
116191
|
}
|
|
115477
116192
|
async function dispatchEvent(ctx, event) {
|
|
115478
116193
|
if (event.type === "message.part.updated") {
|
|
115479
|
-
ctx.lastEventAt =
|
|
116194
|
+
ctx.lastEventAt = performance7.now();
|
|
115480
116195
|
if (isModelOutput(ctx, event.properties.part)) ctx.sawModelOutput = true;
|
|
115481
116196
|
await onPartUpdated(ctx, event.properties.part);
|
|
115482
116197
|
return;
|
|
@@ -115543,7 +116258,7 @@ async function onToolPart(ctx, part, label, isOrchestrator) {
|
|
|
115543
116258
|
if (toolName === "task" && status === "running" && isOrchestrator && !ctx.taskDispatchByCallID.has(toolId)) {
|
|
115544
116259
|
const input = part.state.input ?? {};
|
|
115545
116260
|
const dispatched = ctx.labeler.recordTaskDispatch(input);
|
|
115546
|
-
ctx.taskDispatchByCallID.set(toolId, { label: dispatched, startedAt:
|
|
116261
|
+
ctx.taskDispatchByCallID.set(toolId, { label: dispatched, startedAt: performance7.now() });
|
|
115547
116262
|
log2.info(
|
|
115548
116263
|
`\xBB dispatching subagent: ${dispatched}` + (input.subagent_type ? ` (subagent_type=${input.subagent_type})` : "")
|
|
115549
116264
|
);
|
|
@@ -115573,7 +116288,7 @@ function processTerminalToolPart(ctx, part, label, isOrchestrator) {
|
|
|
115573
116288
|
if (toolName === "task") {
|
|
115574
116289
|
const dispatch = ctx.taskDispatchByCallID.get(toolId);
|
|
115575
116290
|
if (dispatch) {
|
|
115576
|
-
const dur = ((
|
|
116291
|
+
const dur = ((performance7.now() - dispatch.startedAt) / 1e3).toFixed(1);
|
|
115577
116292
|
const outputStr = state.status === "completed" ? state.output : "";
|
|
115578
116293
|
const preview = typeof outputStr === "string" && outputStr.length > 120 ? `${outputStr.slice(0, 120)}\u2026` : outputStr;
|
|
115579
116294
|
log2.info(
|
|
@@ -115616,7 +116331,7 @@ function withLabel(label, message) {
|
|
|
115616
116331
|
return label === ORCHESTRATOR_LABEL ? message : formatWithLabel(label, message);
|
|
115617
116332
|
}
|
|
115618
116333
|
async function runPromptTurn(ctx, params) {
|
|
115619
|
-
const start =
|
|
116334
|
+
const start = performance7.now();
|
|
115620
116335
|
const turnStartMs = Date.now();
|
|
115621
116336
|
ctx.currentTurn = newTurn();
|
|
115622
116337
|
const turn = ctx.currentTurn;
|
|
@@ -115650,7 +116365,7 @@ async function runPromptTurn(ctx, params) {
|
|
|
115650
116365
|
} catch (err) {
|
|
115651
116366
|
networkError = err instanceof Error ? err.message : String(err);
|
|
115652
116367
|
}
|
|
115653
|
-
const durationMs =
|
|
116368
|
+
const durationMs = performance7.now() - start;
|
|
115654
116369
|
const aggregatedUsage = await aggregateTurnUsage(ctx, turnStartMs);
|
|
115655
116370
|
const usage = aggregatedUsage ?? buildUsage(turn, assistant);
|
|
115656
116371
|
const finalText = turn.finalText || extractTextFromParts(returnedParts) || "";
|
|
@@ -115804,7 +116519,7 @@ function startInnerActivityWatchdog(params) {
|
|
|
115804
116519
|
let fired = false;
|
|
115805
116520
|
const id = setInterval(() => {
|
|
115806
116521
|
if (fired) return;
|
|
115807
|
-
const idleMs =
|
|
116522
|
+
const idleMs = performance7.now() - params.ctx.lastEventAt;
|
|
115808
116523
|
const budgetMs = params.ctx.sawModelOutput ? params.timeoutMs : AGENT_FIRST_EVENT_TIMEOUT_MS;
|
|
115809
116524
|
if (idleMs <= budgetMs) return;
|
|
115810
116525
|
fired = true;
|
|
@@ -115843,12 +116558,12 @@ var opencode = agent({
|
|
|
115843
116558
|
const model = vertexModel ?? (isBedrockRoute ? `amazon-bedrock/${rawModel}` : rawModel);
|
|
115844
116559
|
const homeEnv = {
|
|
115845
116560
|
HOME: ctx.tmpdir,
|
|
115846
|
-
XDG_CONFIG_HOME:
|
|
116561
|
+
XDG_CONFIG_HOME: join8(ctx.tmpdir, ".config")
|
|
115847
116562
|
};
|
|
115848
|
-
const opencodePluginDir =
|
|
115849
|
-
|
|
115850
|
-
|
|
115851
|
-
|
|
116563
|
+
const opencodePluginDir = join8(homeEnv.XDG_CONFIG_HOME, "opencode", "plugin");
|
|
116564
|
+
mkdirSync7(opencodePluginDir, { recursive: true });
|
|
116565
|
+
writeFileSync7(
|
|
116566
|
+
join8(opencodePluginDir, PULLFROG_OPENCODE_GATE_PLUGIN_FILENAME),
|
|
115852
116567
|
buildOpencodeSubagentGateSource(ctx.subagentDeniedTools)
|
|
115853
116568
|
);
|
|
115854
116569
|
const agentBrowserVersion = getDevDependencyVersion("agent-browser");
|
|
@@ -115879,12 +116594,13 @@ var opencode = agent({
|
|
|
115879
116594
|
if (codexAuth) {
|
|
115880
116595
|
env2.XDG_DATA_HOME = codexAuth.xdgDataHome;
|
|
115881
116596
|
delete env2.OPENAI_API_KEY;
|
|
115882
|
-
|
|
116597
|
+
core3.saveState(
|
|
115883
116598
|
"codex_writeback",
|
|
115884
116599
|
JSON.stringify({
|
|
115885
116600
|
apiToken: ctx.apiToken,
|
|
115886
116601
|
authPath: codexAuth.authPath,
|
|
115887
|
-
originalRefresh: codexAuth.originalRefresh
|
|
116602
|
+
originalRefresh: codexAuth.originalRefresh,
|
|
116603
|
+
originalIdToken: codexAuth.originalIdToken
|
|
115888
116604
|
})
|
|
115889
116605
|
);
|
|
115890
116606
|
}
|
|
@@ -115938,7 +116654,7 @@ var opencode = agent({
|
|
|
115938
116654
|
onToolUse: ctx.onToolUse,
|
|
115939
116655
|
currentTurn: null,
|
|
115940
116656
|
eventCount: 0,
|
|
115941
|
-
lastEventAt:
|
|
116657
|
+
lastEventAt: performance7.now(),
|
|
115942
116658
|
sawModelOutput: false,
|
|
115943
116659
|
promptMessageID: void 0,
|
|
115944
116660
|
taskDispatchByCallID: /* @__PURE__ */ new Map(),
|
|
@@ -116048,7 +116764,7 @@ async function runTurnGuarded(ctx, fn2) {
|
|
|
116048
116764
|
}
|
|
116049
116765
|
|
|
116050
116766
|
// agents/index.ts
|
|
116051
|
-
var agents = { claude, opencode };
|
|
116767
|
+
var agents = { claude, codex, opencode };
|
|
116052
116768
|
|
|
116053
116769
|
// node_modules/.pnpm/@ark+util@0.56.0/node_modules/@ark/util/out/arrays.js
|
|
116054
116770
|
var liftArray = (data) => Array.isArray(data) ? data : [data];
|
|
@@ -136380,7 +137096,7 @@ var require_core$2 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
136380
137096
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
136381
137097
|
const id_1 = require_id2();
|
|
136382
137098
|
const ref_1 = require_ref2();
|
|
136383
|
-
const
|
|
137099
|
+
const core12 = [
|
|
136384
137100
|
"$schema",
|
|
136385
137101
|
"$id",
|
|
136386
137102
|
"$defs",
|
|
@@ -136390,7 +137106,7 @@ var require_core$2 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
136390
137106
|
id_1.default,
|
|
136391
137107
|
ref_1.default
|
|
136392
137108
|
];
|
|
136393
|
-
exports.default =
|
|
137109
|
+
exports.default = core12;
|
|
136394
137110
|
}));
|
|
136395
137111
|
var require_limitNumber2 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
136396
137112
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -138528,7 +139244,7 @@ var require_json_schema_2019_09 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
138528
139244
|
const metaSchema = require_schema$1();
|
|
138529
139245
|
const applicator = require_applicator$1();
|
|
138530
139246
|
const content = require_content$1();
|
|
138531
|
-
const
|
|
139247
|
+
const core12 = require_core$1();
|
|
138532
139248
|
const format2 = require_format3();
|
|
138533
139249
|
const metadata = require_meta_data$1();
|
|
138534
139250
|
const validation = require_validation$1();
|
|
@@ -138538,7 +139254,7 @@ var require_json_schema_2019_09 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
138538
139254
|
metaSchema,
|
|
138539
139255
|
applicator,
|
|
138540
139256
|
content,
|
|
138541
|
-
|
|
139257
|
+
core12,
|
|
138542
139258
|
with$data(this, format2),
|
|
138543
139259
|
metadata,
|
|
138544
139260
|
with$data(this, validation)
|
|
@@ -138978,7 +139694,7 @@ var require_json_schema_2020_12 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
138978
139694
|
const applicator = require_applicator2();
|
|
138979
139695
|
const unevaluated = require_unevaluated();
|
|
138980
139696
|
const content = require_content();
|
|
138981
|
-
const
|
|
139697
|
+
const core12 = require_core4();
|
|
138982
139698
|
const format2 = require_format_annotation();
|
|
138983
139699
|
const metadata = require_meta_data();
|
|
138984
139700
|
const validation = require_validation2();
|
|
@@ -138989,7 +139705,7 @@ var require_json_schema_2020_12 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
138989
139705
|
applicator,
|
|
138990
139706
|
unevaluated,
|
|
138991
139707
|
content,
|
|
138992
|
-
|
|
139708
|
+
core12,
|
|
138993
139709
|
with$data(this, format2),
|
|
138994
139710
|
metadata,
|
|
138995
139711
|
with$data(this, validation)
|
|
@@ -150431,7 +151147,7 @@ var require_core$22 = /* @__PURE__ */ __commonJSMin2(((exports) => {
|
|
|
150431
151147
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
150432
151148
|
const id_1 = require_id3();
|
|
150433
151149
|
const ref_1 = require_ref3();
|
|
150434
|
-
const
|
|
151150
|
+
const core12 = [
|
|
150435
151151
|
"$schema",
|
|
150436
151152
|
"$id",
|
|
150437
151153
|
"$defs",
|
|
@@ -150441,7 +151157,7 @@ var require_core$22 = /* @__PURE__ */ __commonJSMin2(((exports) => {
|
|
|
150441
151157
|
id_1.default,
|
|
150442
151158
|
ref_1.default
|
|
150443
151159
|
];
|
|
150444
|
-
exports.default =
|
|
151160
|
+
exports.default = core12;
|
|
150445
151161
|
}));
|
|
150446
151162
|
var require_limitNumber3 = /* @__PURE__ */ __commonJSMin2(((exports) => {
|
|
150447
151163
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -152579,7 +153295,7 @@ var require_json_schema_2019_092 = /* @__PURE__ */ __commonJSMin2(((exports) =>
|
|
|
152579
153295
|
const metaSchema = require_schema$12();
|
|
152580
153296
|
const applicator = require_applicator$12();
|
|
152581
153297
|
const content = require_content$12();
|
|
152582
|
-
const
|
|
153298
|
+
const core12 = require_core$12();
|
|
152583
153299
|
const format2 = require_format4();
|
|
152584
153300
|
const metadata = require_meta_data$12();
|
|
152585
153301
|
const validation = require_validation$12();
|
|
@@ -152589,7 +153305,7 @@ var require_json_schema_2019_092 = /* @__PURE__ */ __commonJSMin2(((exports) =>
|
|
|
152589
153305
|
metaSchema,
|
|
152590
153306
|
applicator,
|
|
152591
153307
|
content,
|
|
152592
|
-
|
|
153308
|
+
core12,
|
|
152593
153309
|
with$data(this, format2),
|
|
152594
153310
|
metadata,
|
|
152595
153311
|
with$data(this, validation)
|
|
@@ -153029,7 +153745,7 @@ var require_json_schema_2020_122 = /* @__PURE__ */ __commonJSMin2(((exports) =>
|
|
|
153029
153745
|
const applicator = require_applicator3();
|
|
153030
153746
|
const unevaluated = require_unevaluated2();
|
|
153031
153747
|
const content = require_content2();
|
|
153032
|
-
const
|
|
153748
|
+
const core12 = require_core5();
|
|
153033
153749
|
const format2 = require_format_annotation2();
|
|
153034
153750
|
const metadata = require_meta_data2();
|
|
153035
153751
|
const validation = require_validation3();
|
|
@@ -153040,7 +153756,7 @@ var require_json_schema_2020_122 = /* @__PURE__ */ __commonJSMin2(((exports) =>
|
|
|
153040
153756
|
applicator,
|
|
153041
153757
|
unevaluated,
|
|
153042
153758
|
content,
|
|
153043
|
-
|
|
153759
|
+
core12,
|
|
153044
153760
|
with$data(this, format2),
|
|
153045
153761
|
metadata,
|
|
153046
153762
|
with$data(this, validation)
|
|
@@ -173001,123 +173717,8 @@ var pbkdf2Async = promisify(pbkdf2);
|
|
|
173001
173717
|
|
|
173002
173718
|
// utils/browser.ts
|
|
173003
173719
|
import { execFileSync as execFileSync5, spawnSync as spawnSync4 } from "node:child_process";
|
|
173004
|
-
import { existsSync as
|
|
173720
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
173005
173721
|
import { dirname as dirname2 } from "node:path";
|
|
173006
|
-
|
|
173007
|
-
// utils/secrets.ts
|
|
173008
|
-
var SENSITIVE_PATTERNS = [
|
|
173009
|
-
/_KEY$/i,
|
|
173010
|
-
/_SECRET$/i,
|
|
173011
|
-
/_TOKEN$/i,
|
|
173012
|
-
/_PASSWORD$/i,
|
|
173013
|
-
/_CREDENTIAL$/i
|
|
173014
|
-
];
|
|
173015
|
-
function isSensitiveEnvName(key) {
|
|
173016
|
-
return SENSITIVE_PATTERNS.some((p) => p.test(key));
|
|
173017
|
-
}
|
|
173018
|
-
var SAFE_ENV_PREFIXES = ["GITHUB_", "RUNNER_", "JAVA_HOME_", "GOROOT_"];
|
|
173019
|
-
var SAFE_ENV_NAMES = /* @__PURE__ */ new Set([
|
|
173020
|
-
// system
|
|
173021
|
-
"CI",
|
|
173022
|
-
"HOME",
|
|
173023
|
-
"LANG",
|
|
173024
|
-
"LOGNAME",
|
|
173025
|
-
"PATH",
|
|
173026
|
-
"SHELL",
|
|
173027
|
-
"SHLVL",
|
|
173028
|
-
"TERM",
|
|
173029
|
-
"TMPDIR",
|
|
173030
|
-
"TZ",
|
|
173031
|
-
"USER",
|
|
173032
|
-
"XDG_CONFIG_HOME",
|
|
173033
|
-
"XDG_RUNTIME_DIR",
|
|
173034
|
-
"DEBIAN_FRONTEND",
|
|
173035
|
-
// runner image toolchain
|
|
173036
|
-
"ACCEPT_EULA",
|
|
173037
|
-
"AGENT_TOOLSDIRECTORY",
|
|
173038
|
-
"ANDROID_HOME",
|
|
173039
|
-
"ANDROID_NDK",
|
|
173040
|
-
"ANDROID_NDK_HOME",
|
|
173041
|
-
"ANDROID_NDK_LATEST_HOME",
|
|
173042
|
-
"ANDROID_NDK_ROOT",
|
|
173043
|
-
"ANDROID_SDK_ROOT",
|
|
173044
|
-
"ANT_HOME",
|
|
173045
|
-
"AZURE_EXTENSION_DIR",
|
|
173046
|
-
"BOOTSTRAP_HASKELL_NONINTERACTIVE",
|
|
173047
|
-
"CHROME_BIN",
|
|
173048
|
-
"CHROMEWEBDRIVER",
|
|
173049
|
-
"CONDA",
|
|
173050
|
-
"DOTNET_MULTILEVEL_LOOKUP",
|
|
173051
|
-
"DOTNET_NOLOGO",
|
|
173052
|
-
"DOTNET_SKIP_FIRST_TIME_EXPERIENCE",
|
|
173053
|
-
"EDGEWEBDRIVER",
|
|
173054
|
-
"GECKOWEBDRIVER",
|
|
173055
|
-
"GHCUP_INSTALL_BASE_PREFIX",
|
|
173056
|
-
"GRADLE_HOME",
|
|
173057
|
-
"JAVA_HOME",
|
|
173058
|
-
"HOMEBREW_CLEANUP_PERIODIC_FULL_DAYS",
|
|
173059
|
-
"HOMEBREW_NO_AUTO_UPDATE",
|
|
173060
|
-
"ImageOS",
|
|
173061
|
-
"ImageVersion",
|
|
173062
|
-
"NVM_DIR",
|
|
173063
|
-
"PIPX_BIN_DIR",
|
|
173064
|
-
"PIPX_HOME",
|
|
173065
|
-
"PSModulePath",
|
|
173066
|
-
"SELENIUM_JAR_PATH",
|
|
173067
|
-
"SGX_AESM_ADDR",
|
|
173068
|
-
"SWIFT_PATH",
|
|
173069
|
-
"VCPKG_INSTALLATION_ROOT"
|
|
173070
|
-
]);
|
|
173071
|
-
var _userAllowlist = null;
|
|
173072
|
-
function setEnvAllowlist(raw2) {
|
|
173073
|
-
const names = raw2.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
173074
|
-
_userAllowlist = new Set(names);
|
|
173075
|
-
}
|
|
173076
|
-
function isSafeEnvVar(key) {
|
|
173077
|
-
if (SAFE_ENV_NAMES.has(key)) return true;
|
|
173078
|
-
return SAFE_ENV_PREFIXES.some((p) => key.startsWith(p));
|
|
173079
|
-
}
|
|
173080
|
-
var WORKFLOW_COMMAND_ENV_NAMES = [
|
|
173081
|
-
"GITHUB_ENV",
|
|
173082
|
-
"GITHUB_PATH",
|
|
173083
|
-
"GITHUB_OUTPUT",
|
|
173084
|
-
"GITHUB_STATE",
|
|
173085
|
-
"GITHUB_STEP_SUMMARY",
|
|
173086
|
-
// dropping the five paths above but keeping RUNNER_TEMP would be theatre:
|
|
173087
|
-
// the file-command files live in `$RUNNER_TEMP/_runner_file_commands/`, so the
|
|
173088
|
-
// directory is one `ls` away. nothing in the install path reads it (only our
|
|
173089
|
-
// own leak-surface wipe in `setup.ts`, which runs in the parent), and package
|
|
173090
|
-
// managers use TMPDIR.
|
|
173091
|
-
"RUNNER_TEMP"
|
|
173092
|
-
];
|
|
173093
|
-
function filterEnvForUntrustedCode() {
|
|
173094
|
-
const env2 = filterEnv();
|
|
173095
|
-
for (const name of WORKFLOW_COMMAND_ENV_NAMES) delete env2[name];
|
|
173096
|
-
return env2;
|
|
173097
|
-
}
|
|
173098
|
-
function filterEnv() {
|
|
173099
|
-
const filtered = {};
|
|
173100
|
-
for (const [key, value2] of Object.entries(process.env)) {
|
|
173101
|
-
if (value2 === void 0) continue;
|
|
173102
|
-
const userAllowed = _userAllowlist?.has(key) ?? false;
|
|
173103
|
-
if (isSensitiveEnvName(key) && !userAllowed) continue;
|
|
173104
|
-
if (isSafeEnvVar(key) || userAllowed) {
|
|
173105
|
-
filtered[key] = value2;
|
|
173106
|
-
}
|
|
173107
|
-
}
|
|
173108
|
-
return filtered;
|
|
173109
|
-
}
|
|
173110
|
-
function resolveEnv(mode) {
|
|
173111
|
-
if (mode === "inherit") {
|
|
173112
|
-
return process.env;
|
|
173113
|
-
}
|
|
173114
|
-
if (mode === "restricted" || mode === void 0) {
|
|
173115
|
-
return filterEnv();
|
|
173116
|
-
}
|
|
173117
|
-
return { ...filterEnv(), ...mode };
|
|
173118
|
-
}
|
|
173119
|
-
|
|
173120
|
-
// utils/browser.ts
|
|
173121
173722
|
var CHROME_PATHS = ["/usr/bin/google-chrome-stable"];
|
|
173122
173723
|
var systemChromePath;
|
|
173123
173724
|
function findSystemChromePath() {
|
|
@@ -173125,7 +173726,7 @@ function findSystemChromePath() {
|
|
|
173125
173726
|
return systemChromePath || void 0;
|
|
173126
173727
|
}
|
|
173127
173728
|
for (const p of CHROME_PATHS) {
|
|
173128
|
-
if (
|
|
173729
|
+
if (existsSync5(p)) {
|
|
173129
173730
|
systemChromePath = p;
|
|
173130
173731
|
log2.info(`found system chrome: ${p}`);
|
|
173131
173732
|
return p;
|
|
@@ -173209,8 +173810,8 @@ function closeBrowserDaemon(toolState) {
|
|
|
173209
173810
|
|
|
173210
173811
|
// mcp/checkout.ts
|
|
173211
173812
|
import { createHash as createHash2 } from "node:crypto";
|
|
173212
|
-
import { statSync, unlinkSync as unlinkSync3, writeFileSync as
|
|
173213
|
-
import { join as
|
|
173813
|
+
import { statSync, unlinkSync as unlinkSync3, writeFileSync as writeFileSync10 } from "node:fs";
|
|
173814
|
+
import { join as join15 } from "node:path";
|
|
173214
173815
|
|
|
173215
173816
|
// node_modules/.pnpm/@ark+schema@0.56.0/node_modules/@ark/schema/out/shared/errors.js
|
|
173216
173817
|
var ArkError = class _ArkError extends CastableBase {
|
|
@@ -180682,8 +181283,8 @@ function ensureRepoState(toolState, init) {
|
|
|
180682
181283
|
|
|
180683
181284
|
// utils/changeImpact.ts
|
|
180684
181285
|
import { spawn as spawn4 } from "node:child_process";
|
|
180685
|
-
import { writeFileSync as
|
|
180686
|
-
import { join as
|
|
181286
|
+
import { writeFileSync as writeFileSync8 } from "node:fs";
|
|
181287
|
+
import { join as join9 } from "node:path";
|
|
180687
181288
|
var MAX_CANDIDATES = 24;
|
|
180688
181289
|
var MAX_ATOM_LENGTH = 128;
|
|
180689
181290
|
var MAX_ATOMS = 12;
|
|
@@ -181030,8 +181631,8 @@ async function createChangeImpactArtifact(ctx, params) {
|
|
|
181030
181631
|
headSha: params.headSha,
|
|
181031
181632
|
lookupError: lookup2.error
|
|
181032
181633
|
});
|
|
181033
|
-
const path4 =
|
|
181034
|
-
|
|
181634
|
+
const path4 = join9(ctx.tmpdir, `pr-${params.pullNumber}-${params.headSha.slice(0, 7)}-impact.md`);
|
|
181635
|
+
writeFileSync8(path4, artifact.content);
|
|
181035
181636
|
return {
|
|
181036
181637
|
path: path4,
|
|
181037
181638
|
candidateCount: candidates.selected.length,
|
|
@@ -181283,8 +181884,8 @@ function readNumber(params) {
|
|
|
181283
181884
|
// utils/gitAuth.ts
|
|
181284
181885
|
import { execSync } from "node:child_process";
|
|
181285
181886
|
import { createHash } from "node:crypto";
|
|
181286
|
-
import { readFileSync as
|
|
181287
|
-
import { join as
|
|
181887
|
+
import { readFileSync as readFileSync4, realpathSync, unlinkSync } from "node:fs";
|
|
181888
|
+
import { join as join10 } from "node:path";
|
|
181288
181889
|
|
|
181289
181890
|
// utils/shell.ts
|
|
181290
181891
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
@@ -181345,7 +181946,7 @@ var TRANSIENT_AUTH_PATTERNS = [
|
|
|
181345
181946
|
];
|
|
181346
181947
|
var gitBinary;
|
|
181347
181948
|
function hashFile(path4) {
|
|
181348
|
-
return createHash("sha256").update(
|
|
181949
|
+
return createHash("sha256").update(readFileSync4(path4)).digest("hex");
|
|
181349
181950
|
}
|
|
181350
181951
|
function resolveGit() {
|
|
181351
181952
|
const whichPath = execSync("which git", { encoding: "utf-8" }).trim();
|
|
@@ -181374,7 +181975,7 @@ function resolveHooksDir(cwd, gitPath) {
|
|
|
181374
181975
|
cwd,
|
|
181375
181976
|
log: false
|
|
181376
181977
|
}).trim();
|
|
181377
|
-
const hooksDir =
|
|
181978
|
+
const hooksDir = join10(commonDir, "hooks");
|
|
181378
181979
|
hooksDirCache.set(cwd, hooksDir);
|
|
181379
181980
|
return hooksDir;
|
|
181380
181981
|
}
|
|
@@ -181681,7 +182282,7 @@ function postProcessRangeDiff(raw2, contextLines = 3) {
|
|
|
181681
182282
|
}
|
|
181682
182283
|
|
|
181683
182284
|
// yes/index.ts
|
|
181684
|
-
import { performance as
|
|
182285
|
+
import { performance as performance8 } from "node:perf_hooks";
|
|
181685
182286
|
import { setTimeout as sleep2 } from "node:timers/promises";
|
|
181686
182287
|
|
|
181687
182288
|
// node_modules/.pnpm/lru-cache@11.5.2/node_modules/lru-cache/dist/esm/node/index.min.js
|
|
@@ -182396,14 +182997,14 @@ function _op(fn2, options) {
|
|
|
182396
182997
|
`failed to create cache key${namePrefix ? ` for ${options.name}` : ""}: ${errorMessage}`
|
|
182397
182998
|
);
|
|
182398
182999
|
}
|
|
182399
|
-
const startTime =
|
|
183000
|
+
const startTime = performance8.now();
|
|
182400
183001
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
182401
183002
|
log3.debug(`${namePrefix}[${timestamp}] cache lookup started`, { key });
|
|
182402
183003
|
if (shouldCache && lruCache) {
|
|
182403
183004
|
const cached4 = lruCache.get(key);
|
|
182404
183005
|
if (cached4 !== void 0) {
|
|
182405
183006
|
if (keyMap?.get(key) === void 0) keyMap?.set(key, input);
|
|
182406
|
-
const runtime =
|
|
183007
|
+
const runtime = performance8.now() - startTime;
|
|
182407
183008
|
log3.debug(`${namePrefix}[${timestamp}] cache hit (from lru)`, {
|
|
182408
183009
|
key,
|
|
182409
183010
|
runtime: `${Math.round(runtime)}ms`
|
|
@@ -182422,12 +183023,12 @@ function _op(fn2, options) {
|
|
|
182422
183023
|
defaultCacheMiss(key);
|
|
182423
183024
|
const retries = options.retries ?? [];
|
|
182424
183025
|
let lastError;
|
|
182425
|
-
const execStartTime =
|
|
183026
|
+
const execStartTime = performance8.now();
|
|
182426
183027
|
const promise2 = (async () => {
|
|
182427
183028
|
for (let attempt = 0; attempt <= retries.length; attempt++) {
|
|
182428
183029
|
try {
|
|
182429
183030
|
const result = acceptsCtx ? await fn2(input, ctx) : await fn2(input);
|
|
182430
|
-
const execRuntime2 =
|
|
183031
|
+
const execRuntime2 = performance8.now() - execStartTime;
|
|
182431
183032
|
const skip = options.skipCache ? options.skipCache(result) : false;
|
|
182432
183033
|
if (shouldCache && lruCache && result !== null && result !== void 0 && !skip) {
|
|
182433
183034
|
lruCache.set(key, result);
|
|
@@ -182480,7 +183081,7 @@ function _op(fn2, options) {
|
|
|
182480
183081
|
}
|
|
182481
183082
|
}
|
|
182482
183083
|
}
|
|
182483
|
-
const execRuntime =
|
|
183084
|
+
const execRuntime = performance8.now() - execStartTime;
|
|
182484
183085
|
log3.debug(`${namePrefix}[${timestamp}] function failed after all retries`, {
|
|
182485
183086
|
key,
|
|
182486
183087
|
runtime: `${Math.round(execRuntime)}ms`,
|
|
@@ -182545,13 +183146,13 @@ function _op(fn2, options) {
|
|
|
182545
183146
|
|
|
182546
183147
|
// mcp/git.ts
|
|
182547
183148
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
182548
|
-
import { writeFileSync as
|
|
182549
|
-
import { join as
|
|
183149
|
+
import { writeFileSync as writeFileSync9 } from "node:fs";
|
|
183150
|
+
import { join as join13 } from "node:path";
|
|
182550
183151
|
|
|
182551
183152
|
// utils/apiCommit.ts
|
|
182552
183153
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
182553
183154
|
import { lstat, readlink } from "node:fs/promises";
|
|
182554
|
-
import { join as
|
|
183155
|
+
import { join as join11 } from "node:path";
|
|
182555
183156
|
var GITHUB_API = "https://api.github.com";
|
|
182556
183157
|
var MAX_BLOB_BYTES = 30 * 1024 * 1024;
|
|
182557
183158
|
var BLOB_UPLOAD_CONCURRENCY = 8;
|
|
@@ -182616,7 +183217,7 @@ async function assertApiCommittable(files) {
|
|
|
182616
183217
|
const root = getRepoRoot();
|
|
182617
183218
|
const attrs = $(
|
|
182618
183219
|
"git",
|
|
182619
|
-
["check-attr", "filter", "-z", "--", ...present.map((p) =>
|
|
183220
|
+
["check-attr", "filter", "-z", "--", ...present.map((p) => join11(root, p))],
|
|
182620
183221
|
{ log: false }
|
|
182621
183222
|
);
|
|
182622
183223
|
const parts = attrs.split("\0");
|
|
@@ -182628,7 +183229,7 @@ async function assertApiCommittable(files) {
|
|
|
182628
183229
|
}
|
|
182629
183230
|
}
|
|
182630
183231
|
for (const path4 of present) {
|
|
182631
|
-
const stat = await lstat(
|
|
183232
|
+
const stat = await lstat(join11(root, path4));
|
|
182632
183233
|
if (stat.isDirectory()) {
|
|
182633
183234
|
throw new Error(
|
|
182634
183235
|
`'${path4}' is a directory (nested repository or submodule?) \u2014 signed commits only support files and symlinks.`
|
|
@@ -182637,7 +183238,7 @@ async function assertApiCommittable(files) {
|
|
|
182637
183238
|
}
|
|
182638
183239
|
}
|
|
182639
183240
|
async function createBlobEntry(params) {
|
|
182640
|
-
const absPath =
|
|
183241
|
+
const absPath = join11(params.repoRoot, params.path);
|
|
182641
183242
|
const stat = await lstat(absPath);
|
|
182642
183243
|
if (stat.size > MAX_BLOB_BYTES) {
|
|
182643
183244
|
throw new Error(
|
|
@@ -182814,10 +183415,10 @@ this usually means your local branch has commits that were never pushed \u2014 s
|
|
|
182814
183415
|
}
|
|
182815
183416
|
|
|
182816
183417
|
// utils/github.ts
|
|
182817
|
-
var
|
|
183418
|
+
var core4 = __toESM(require_core(), 1);
|
|
182818
183419
|
import { createSign } from "node:crypto";
|
|
182819
183420
|
import { rename, writeFile } from "node:fs/promises";
|
|
182820
|
-
import { dirname as dirname3, join as
|
|
183421
|
+
import { dirname as dirname3, join as join12 } from "node:path";
|
|
182821
183422
|
|
|
182822
183423
|
// node_modules/.pnpm/@octokit+plugin-throttling@11.0.5_@octokit+core@7.0.7/node_modules/@octokit/plugin-throttling/dist-bundle/index.js
|
|
182823
183424
|
var import_light = __toESM(require_light(), 1);
|
|
@@ -187015,7 +187616,7 @@ async function fetchIdTokenFromStash(creds) {
|
|
|
187015
187616
|
throw new Error("ID token response has no value field");
|
|
187016
187617
|
}
|
|
187017
187618
|
if (isGitHubActions) {
|
|
187018
|
-
|
|
187619
|
+
core4.setSecret(body.value);
|
|
187019
187620
|
}
|
|
187020
187621
|
return body.value;
|
|
187021
187622
|
}
|
|
@@ -187028,7 +187629,7 @@ function translateIdTokenError(error52) {
|
|
|
187028
187629
|
var mintIdToken = op(
|
|
187029
187630
|
async () => {
|
|
187030
187631
|
try {
|
|
187031
|
-
return await
|
|
187632
|
+
return await core4.getIDToken(OIDC_AUDIENCE);
|
|
187032
187633
|
} catch (error52) {
|
|
187033
187634
|
throw translateIdTokenError(error52);
|
|
187034
187635
|
}
|
|
@@ -187237,7 +187838,7 @@ function getGitHubUsageSummary() {
|
|
|
187237
187838
|
}
|
|
187238
187839
|
async function writeGitHubUsageSummaryToFile(path4) {
|
|
187239
187840
|
const summary2 = getGitHubUsageSummary();
|
|
187240
|
-
const tmpPath =
|
|
187841
|
+
const tmpPath = join12(dirname3(path4), `.usage-summary-${process.pid}.tmp`);
|
|
187241
187842
|
await writeFile(tmpPath, JSON.stringify(summary2));
|
|
187242
187843
|
await rename(tmpPath, path4);
|
|
187243
187844
|
}
|
|
@@ -188389,8 +188990,8 @@ function countAhead(head, base, cwd) {
|
|
|
188389
188990
|
function spillGitOutput(params) {
|
|
188390
188991
|
const tempDir = process.env.PULLFROG_TEMP_DIR;
|
|
188391
188992
|
if (!tempDir) throw new Error("PULLFROG_TEMP_DIR not set");
|
|
188392
|
-
const outputPath =
|
|
188393
|
-
|
|
188993
|
+
const outputPath = join13(tempDir, `git-${params.command}-${randomUUID3().slice(0, 8)}.txt`);
|
|
188994
|
+
writeFileSync9(outputPath, params.output);
|
|
188394
188995
|
const previewByLines = params.output.split("\n").slice(0, OVERFLOW_PREVIEW_LINES).join("\n");
|
|
188395
188996
|
const preview = previewByLines.length <= OVERFLOW_PREVIEW_MAX_CHARS ? previewByLines : `${previewByLines.slice(0, OVERFLOW_PREVIEW_MAX_CHARS)}\u2026`;
|
|
188396
188997
|
log2.info(
|
|
@@ -189904,9 +190505,9 @@ async function reportReviewNodeId(ctx, params) {
|
|
|
189904
190505
|
import { execFileSync as execFileSync7, execSync as execSync2 } from "node:child_process";
|
|
189905
190506
|
import { mkdtempSync as mkdtempSync2, readdirSync, realpathSync as realpathSync2, unlinkSync as unlinkSync2 } from "node:fs";
|
|
189906
190507
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
189907
|
-
import { join as
|
|
190508
|
+
import { join as join14 } from "node:path";
|
|
189908
190509
|
function createTempDirectory() {
|
|
189909
|
-
const sharedTempDir = mkdtempSync2(
|
|
190510
|
+
const sharedTempDir = mkdtempSync2(join14(tmpdir3(), "pullfrog-"));
|
|
189910
190511
|
process.env.PULLFROG_TEMP_DIR = sharedTempDir;
|
|
189911
190512
|
log2.info(`\xBB created temp dir at ${sharedTempDir}`);
|
|
189912
190513
|
return sharedTempDir;
|
|
@@ -189951,13 +190552,13 @@ function wipeRunnerLeakSurface() {
|
|
|
189951
190552
|
return [];
|
|
189952
190553
|
}
|
|
189953
190554
|
};
|
|
189954
|
-
const fileCommandsDir =
|
|
190555
|
+
const fileCommandsDir = join14(runnerTemp, "_runner_file_commands");
|
|
189955
190556
|
for (const entry of listDir(fileCommandsDir)) {
|
|
189956
|
-
tryUnlink(
|
|
190557
|
+
tryUnlink(join14(fileCommandsDir, entry));
|
|
189957
190558
|
}
|
|
189958
190559
|
for (const entry of listDir(runnerTemp)) {
|
|
189959
190560
|
if (entry.endsWith(".sh") || /^git-credentials-.*\.config$/.test(entry)) {
|
|
189960
|
-
tryUnlink(
|
|
190561
|
+
tryUnlink(join14(runnerTemp, entry));
|
|
189961
190562
|
}
|
|
189962
190563
|
}
|
|
189963
190564
|
if (wiped.length > 0) {
|
|
@@ -190507,11 +191108,11 @@ function CheckoutPrTool(ctx) {
|
|
|
190507
191108
|
headSha: checkoutSha
|
|
190508
191109
|
});
|
|
190509
191110
|
if (incremental.status === "ok") {
|
|
190510
|
-
incrementalDiffPath =
|
|
191111
|
+
incrementalDiffPath = join15(
|
|
190511
191112
|
tempDir,
|
|
190512
191113
|
`pr-${pull_number}-${beforeShort}-${headShort}-incremental.diff`
|
|
190513
191114
|
);
|
|
190514
|
-
|
|
191115
|
+
writeFileSync10(incrementalDiffPath, incremental.diff);
|
|
190515
191116
|
log2.info(
|
|
190516
191117
|
`\xBB incremental diff computed (${incremental.diff.length} bytes) \u2192 ${incrementalDiffPath}`
|
|
190517
191118
|
);
|
|
@@ -190524,8 +191125,8 @@ function CheckoutPrTool(ctx) {
|
|
|
190524
191125
|
const diffPreview = formatResult.content.split("\n").slice(0, 100).join("\n");
|
|
190525
191126
|
log2.debug(`formatted diff preview (first 100 lines):
|
|
190526
191127
|
${diffPreview}`);
|
|
190527
|
-
const diffPath =
|
|
190528
|
-
|
|
191128
|
+
const diffPath = join15(tempDir, `pr-${pull_number}-${headShort}.diff`);
|
|
191129
|
+
writeFileSync10(diffPath, formatResult.content);
|
|
190529
191130
|
log2.debug(`wrote diff to ${diffPath} (${formatResult.content.length} bytes)`);
|
|
190530
191131
|
primary.diffCoverage = createDiffCoverageState({
|
|
190531
191132
|
diffPath,
|
|
@@ -190682,8 +191283,8 @@ ${dirty}`
|
|
|
190682
191283
|
}
|
|
190683
191284
|
|
|
190684
191285
|
// mcp/checkSuite.ts
|
|
190685
|
-
import { mkdirSync as
|
|
190686
|
-
import { join as
|
|
191286
|
+
import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync11 } from "node:fs";
|
|
191287
|
+
import { join as join16 } from "node:path";
|
|
190687
191288
|
var GetCheckSuiteLogs = type({
|
|
190688
191289
|
check_suite_id: type.number.describe("the id from check_suite.id")
|
|
190689
191290
|
});
|
|
@@ -190779,8 +191380,8 @@ function GetCheckSuiteLogsTool(ctx) {
|
|
|
190779
191380
|
if (!tempDir) {
|
|
190780
191381
|
throw new Error("PULLFROG_TEMP_DIR not set");
|
|
190781
191382
|
}
|
|
190782
|
-
const logsDir =
|
|
190783
|
-
|
|
191383
|
+
const logsDir = join16(tempDir, "ci-logs");
|
|
191384
|
+
mkdirSync8(logsDir, { recursive: true });
|
|
190784
191385
|
const jobResults = [];
|
|
190785
191386
|
for (const run4 of failedRuns) {
|
|
190786
191387
|
const jobs = await ctx.octokit.paginate(ctx.octokit.rest.actions.listJobsForWorkflowRun, {
|
|
@@ -190806,8 +191407,8 @@ function GetCheckSuiteLogsTool(ctx) {
|
|
|
190806
191407
|
);
|
|
190807
191408
|
}
|
|
190808
191409
|
const logsText = await logsResult.text();
|
|
190809
|
-
const logPath =
|
|
190810
|
-
|
|
191410
|
+
const logPath = join16(logsDir, `job-${job.id}.log`);
|
|
191411
|
+
writeFileSync11(logPath, logsText);
|
|
190811
191412
|
const analysis = analyzeLog(logsText, 80);
|
|
190812
191413
|
const failedSteps = job.steps?.filter((s) => s.conclusion === "failure").map((s) => `Step ${s.number}: ${s.name}`) ?? [];
|
|
190813
191414
|
jobResults.push({
|
|
@@ -190855,8 +191456,8 @@ function GetCheckSuiteLogsTool(ctx) {
|
|
|
190855
191456
|
}
|
|
190856
191457
|
|
|
190857
191458
|
// mcp/commitInfo.ts
|
|
190858
|
-
import { writeFileSync as
|
|
190859
|
-
import { join as
|
|
191459
|
+
import { writeFileSync as writeFileSync12 } from "node:fs";
|
|
191460
|
+
import { join as join17 } from "node:path";
|
|
190860
191461
|
var CommitInfo = type({
|
|
190861
191462
|
sha: type.string.describe("the commit SHA (full or abbreviated) to fetch")
|
|
190862
191463
|
});
|
|
@@ -190880,8 +191481,8 @@ function CommitInfoTool(ctx) {
|
|
|
190880
191481
|
"PULLFROG_TEMP_DIR not set - get_commit_info must run in pullfrog action context"
|
|
190881
191482
|
);
|
|
190882
191483
|
}
|
|
190883
|
-
const diffFile =
|
|
190884
|
-
|
|
191484
|
+
const diffFile = join17(tempDir, `commit-${sha.slice(0, 7)}.diff`);
|
|
191485
|
+
writeFileSync12(diffFile, formatResult.content);
|
|
190885
191486
|
log2.debug(`wrote commit diff to ${diffFile} (${formatResult.content.length} bytes)`);
|
|
190886
191487
|
return {
|
|
190887
191488
|
sha: data.sha,
|
|
@@ -191014,17 +191615,17 @@ function ReopenCurrentTool(ctx) {
|
|
|
191014
191615
|
}
|
|
191015
191616
|
|
|
191016
191617
|
// prep/index.ts
|
|
191017
|
-
import { performance as
|
|
191618
|
+
import { performance as performance9 } from "node:perf_hooks";
|
|
191018
191619
|
|
|
191019
191620
|
// prep/installNodeDependencies.ts
|
|
191020
|
-
import { existsSync as
|
|
191021
|
-
import { join as
|
|
191621
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
191622
|
+
import { join as join19 } from "node:path";
|
|
191022
191623
|
|
|
191023
191624
|
// utils/packageManager.ts
|
|
191024
191625
|
var import_semver2 = __toESM(require_semver2(), 1);
|
|
191025
|
-
import { existsSync as
|
|
191626
|
+
import { existsSync as existsSync6 } from "node:fs";
|
|
191026
191627
|
import { mkdir, readFile as readFile2 } from "node:fs/promises";
|
|
191027
|
-
import { delimiter, join as
|
|
191628
|
+
import { delimiter, join as join18 } from "node:path";
|
|
191028
191629
|
var SUPPORTED_NAMES = ["npm", "pnpm", "yarn", "bun"];
|
|
191029
191630
|
var COREPACK_MANAGED = ["pnpm", "yarn"];
|
|
191030
191631
|
function isSupported(name) {
|
|
@@ -191062,8 +191663,8 @@ function parseDevEnginesField(field) {
|
|
|
191062
191663
|
};
|
|
191063
191664
|
}
|
|
191064
191665
|
async function resolvePackageManagerSpec(cwd) {
|
|
191065
|
-
const pkgPath =
|
|
191066
|
-
if (!
|
|
191666
|
+
const pkgPath = join18(cwd, "package.json");
|
|
191667
|
+
if (!existsSync6(pkgPath)) return null;
|
|
191067
191668
|
let pkg;
|
|
191068
191669
|
try {
|
|
191069
191670
|
pkg = JSON.parse(await readFile2(pkgPath, "utf-8"));
|
|
@@ -191121,7 +191722,7 @@ async function currentVersion(name) {
|
|
|
191121
191722
|
return result.stdout.trim();
|
|
191122
191723
|
}
|
|
191123
191724
|
function packageManagerBinDir(tmpdir4) {
|
|
191124
|
-
return
|
|
191725
|
+
return join18(tmpdir4, "pm-bin");
|
|
191125
191726
|
}
|
|
191126
191727
|
async function ensurePackageManager(params) {
|
|
191127
191728
|
const spec = params.spec;
|
|
@@ -191184,7 +191785,7 @@ async function installFallback(name, installSpec) {
|
|
|
191184
191785
|
});
|
|
191185
191786
|
if (result.exitCode !== 0) return result.stderr || `failed to install ${name}`;
|
|
191186
191787
|
if (name === "deno") {
|
|
191187
|
-
const denoPath =
|
|
191788
|
+
const denoPath = join18(process.env.HOME || "", ".deno", "bin");
|
|
191188
191789
|
process.env.PATH = `${denoPath}:${process.env.PATH}`;
|
|
191189
191790
|
}
|
|
191190
191791
|
log2.info(`\xBB installed ${name}`);
|
|
@@ -191217,8 +191818,8 @@ async function isCommandAvailable2(command) {
|
|
|
191217
191818
|
var installNodeDependencies = {
|
|
191218
191819
|
name: "installNodeDependencies",
|
|
191219
191820
|
shouldRun: () => {
|
|
191220
|
-
const packageJsonPath =
|
|
191221
|
-
return
|
|
191821
|
+
const packageJsonPath = join19(process.cwd(), "package.json");
|
|
191822
|
+
return existsSync7(packageJsonPath);
|
|
191222
191823
|
},
|
|
191223
191824
|
run: async (options) => {
|
|
191224
191825
|
const declared = await resolvePackageManagerSpec(process.cwd());
|
|
@@ -191312,14 +191913,14 @@ ${errorMessage}`]
|
|
|
191312
191913
|
};
|
|
191313
191914
|
|
|
191314
191915
|
// prep/installPythonDependencies.ts
|
|
191315
|
-
import { existsSync as
|
|
191316
|
-
import { join as
|
|
191916
|
+
import { existsSync as existsSync8, readFileSync as readFileSync5 } from "node:fs";
|
|
191917
|
+
import { join as join20 } from "node:path";
|
|
191317
191918
|
function declaresBuildSystem(path4) {
|
|
191318
|
-
return /^\s*\[\s*build-system\s*\]/m.test(
|
|
191919
|
+
return /^\s*\[\s*build-system\s*\]/m.test(readFileSync5(path4, "utf8"));
|
|
191319
191920
|
}
|
|
191320
191921
|
function configApplies(config3, cwd) {
|
|
191321
|
-
const path4 =
|
|
191322
|
-
return
|
|
191922
|
+
const path4 = join20(cwd, config3.file);
|
|
191923
|
+
return existsSync8(path4) && (config3.applies?.(path4) ?? true);
|
|
191323
191924
|
}
|
|
191324
191925
|
var PYTHON_CONFIGS = [
|
|
191325
191926
|
{
|
|
@@ -191473,7 +192074,7 @@ var installPythonDependencies = {
|
|
|
191473
192074
|
var prepSteps = [installNodeDependencies, installPythonDependencies];
|
|
191474
192075
|
async function runPrepPhase(options) {
|
|
191475
192076
|
log2.debug("\xBB starting prep phase...");
|
|
191476
|
-
const startTime =
|
|
192077
|
+
const startTime = performance9.now();
|
|
191477
192078
|
const results = [];
|
|
191478
192079
|
const preDirty = await dirtyTrackedPaths();
|
|
191479
192080
|
try {
|
|
@@ -191495,7 +192096,7 @@ async function runPrepPhase(options) {
|
|
|
191495
192096
|
} finally {
|
|
191496
192097
|
await restoreDirtiedSince({ before: preDirty, actor: "prep" });
|
|
191497
192098
|
}
|
|
191498
|
-
const totalDurationMs =
|
|
192099
|
+
const totalDurationMs = performance9.now() - startTime;
|
|
191499
192100
|
log2.debug(`\xBB prep phase completed (${Math.round(totalDurationMs)}ms)`);
|
|
191500
192101
|
return results;
|
|
191501
192102
|
}
|
|
@@ -191640,15 +192241,15 @@ function AwaitDependencyInstallationTool(ctx) {
|
|
|
191640
192241
|
}
|
|
191641
192242
|
|
|
191642
192243
|
// mcp/gh.ts
|
|
191643
|
-
import { mkdirSync as
|
|
191644
|
-
import { join as
|
|
192244
|
+
import { mkdirSync as mkdirSync9 } from "node:fs";
|
|
192245
|
+
import { join as join22 } from "node:path";
|
|
191645
192246
|
|
|
191646
192247
|
// mcp/shell.ts
|
|
191647
192248
|
import { spawn as spawn5, spawnSync as spawnSync6 } from "node:child_process";
|
|
191648
192249
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
191649
|
-
import { closeSync, openSync, writeFileSync as
|
|
192250
|
+
import { closeSync, openSync, writeFileSync as writeFileSync13 } from "node:fs";
|
|
191650
192251
|
import { userInfo as userInfo2 } from "node:os";
|
|
191651
|
-
import { join as
|
|
192252
|
+
import { join as join21 } from "node:path";
|
|
191652
192253
|
import { setTimeout as sleep3 } from "node:timers/promises";
|
|
191653
192254
|
var ShellParams = type({
|
|
191654
192255
|
command: "string",
|
|
@@ -191911,8 +192512,8 @@ ${spawnError}` : spawnError;
|
|
|
191911
192512
|
}
|
|
191912
192513
|
function capOutput(output) {
|
|
191913
192514
|
if (output.length <= MAX_OUTPUT_CHARS) return output;
|
|
191914
|
-
const fullPath =
|
|
191915
|
-
|
|
192515
|
+
const fullPath = join21(getTempDir(), `shell-${randomUUID4().slice(0, 8)}.log`);
|
|
192516
|
+
writeFileSync13(fullPath, output);
|
|
191916
192517
|
const elided = output.length - MAX_OUTPUT_CHARS;
|
|
191917
192518
|
return `... [${elided} chars truncated; full output saved to ${fullPath}] ...
|
|
191918
192519
|
${output.slice(-MAX_OUTPUT_CHARS)}`;
|
|
@@ -191966,8 +192567,8 @@ Do NOT use this tool for git commands \u2014 use the dedicated git tools instead
|
|
|
191966
192567
|
if (params.background) {
|
|
191967
192568
|
const tempDir = getTempDir();
|
|
191968
192569
|
const handle = `bg-${randomUUID4().slice(0, 8)}`;
|
|
191969
|
-
const outputPath =
|
|
191970
|
-
const pidPath =
|
|
192570
|
+
const outputPath = join21(tempDir, `${handle}.log`);
|
|
192571
|
+
const pidPath = join21(tempDir, `${handle}.pid`);
|
|
191971
192572
|
const logFd = openSync(outputPath, "a");
|
|
191972
192573
|
let proc;
|
|
191973
192574
|
try {
|
|
@@ -191984,7 +192585,7 @@ Do NOT use this tool for git commands \u2014 use the dedicated git tools instead
|
|
|
191984
192585
|
throw new Error("failed to start background process");
|
|
191985
192586
|
}
|
|
191986
192587
|
proc.unref();
|
|
191987
|
-
|
|
192588
|
+
writeFileSync13(pidPath, `${proc.pid}
|
|
191988
192589
|
`);
|
|
191989
192590
|
ctx.toolState.backgroundProcesses.set(handle, { pid: proc.pid, outputPath, pidPath });
|
|
191990
192591
|
return {
|
|
@@ -192064,8 +192665,8 @@ function GhTool(ctx) {
|
|
|
192064
192665
|
description: `Run the GitHub CLI against ${ctx.repo.owner}/${ctx.repo.name}. Pass argv as an array \u2014 there is no shell, so pipes, redirects and \`&&\` do not work; use gh's own \`--json\`/\`--jq\` flags instead. \`gh api graphql\` is available. Authenticated with ${permissions ? formatPermissions(permissions) : "no permissions"} on this repo only; anything else 403s. Pushing, merging and ref writes are not available \u2014 use the git tools.`,
|
|
192065
192666
|
parameters: GhParams,
|
|
192066
192667
|
execute: execute(async (params) => {
|
|
192067
|
-
const configDir =
|
|
192068
|
-
|
|
192668
|
+
const configDir = join22(ctx.tmpdir, "gh-config");
|
|
192669
|
+
mkdirSync9(configDir, { recursive: true });
|
|
192069
192670
|
const command = ["gh", ...params.args.map(shellQuote)].join(" ");
|
|
192070
192671
|
const result = await runSandboxed({
|
|
192071
192672
|
command,
|
|
@@ -192788,8 +193389,8 @@ function PullRequestInfoTool(ctx) {
|
|
|
192788
193389
|
}
|
|
192789
193390
|
|
|
192790
193391
|
// mcp/reviewComments.ts
|
|
192791
|
-
import { writeFileSync as
|
|
192792
|
-
import { join as
|
|
193392
|
+
import { writeFileSync as writeFileSync14 } from "node:fs";
|
|
193393
|
+
import { join as join23 } from "node:path";
|
|
192793
193394
|
var COMMENTS_PER_THREAD = 50;
|
|
192794
193395
|
var REVIEW_THREADS_QUERY = `
|
|
192795
193396
|
query ($owner: String!, $name: String!, $prNumber: Int!, $cursor: String) {
|
|
@@ -193262,8 +193863,8 @@ function GetReviewCommentsTool(ctx) {
|
|
|
193262
193863
|
throw new Error("PULLFROG_TEMP_DIR not set");
|
|
193263
193864
|
}
|
|
193264
193865
|
const filename = `review-${params.review_id}-threads.md`;
|
|
193265
|
-
const commentsPath =
|
|
193266
|
-
|
|
193866
|
+
const commentsPath = join23(tempDir, filename);
|
|
193867
|
+
writeFileSync14(commentsPath, formatted.content);
|
|
193267
193868
|
log2.debug(`wrote ${threadBlocks.length} threads to ${commentsPath}`);
|
|
193268
193869
|
return {
|
|
193269
193870
|
review_id: params.review_id,
|
|
@@ -193596,8 +194197,8 @@ function UploadFileTool(ctx) {
|
|
|
193596
194197
|
}
|
|
193597
194198
|
|
|
193598
194199
|
// mcp/xrepo.ts
|
|
193599
|
-
import { mkdirSync as
|
|
193600
|
-
import { join as
|
|
194200
|
+
import { mkdirSync as mkdirSync10, rmSync as rmSync3 } from "node:fs";
|
|
194201
|
+
import { join as join24 } from "node:path";
|
|
193601
194202
|
function assertValidRepoName(name) {
|
|
193602
194203
|
if (!/^[A-Za-z0-9._-]+$/.test(name) || name.startsWith("-") || name.includes("..")) {
|
|
193603
194204
|
throw new Error(
|
|
@@ -193677,8 +194278,8 @@ function CheckoutRepoTool(ctx) {
|
|
|
193677
194278
|
return { path: existing.dir, access: existing.access, note: "already checked out." };
|
|
193678
194279
|
}
|
|
193679
194280
|
const access = accessFor(ctx, repo);
|
|
193680
|
-
const dir =
|
|
193681
|
-
|
|
194281
|
+
const dir = join24(ctx.tmpdir, "xrepo", repo);
|
|
194282
|
+
mkdirSync10(dir, { recursive: true });
|
|
193682
194283
|
const state = ensureRepoState(ctx.toolState, { owner, name: repo, dir, access });
|
|
193683
194284
|
const rc = resolveRepoCtx(ctx, repo);
|
|
193684
194285
|
try {
|
|
@@ -193926,6 +194527,9 @@ function hasEnvVar2(name) {
|
|
|
193926
194527
|
function hasClaudeCodeAuth() {
|
|
193927
194528
|
return hasEnvVar2("CLAUDE_CODE_OAUTH_TOKEN") || hasEnvVar2("ANTHROPIC_API_KEY");
|
|
193928
194529
|
}
|
|
194530
|
+
function hasCodexAuth() {
|
|
194531
|
+
return hasEnvVar2("CODEX_AUTH_JSON") || hasEnvVar2("OPENAI_API_KEY");
|
|
194532
|
+
}
|
|
193929
194533
|
function hasBedrockAuth() {
|
|
193930
194534
|
return hasEnvVar2("AWS_BEARER_TOKEN_BEDROCK") || hasEnvVar2("AWS_ACCESS_KEY_ID") && hasEnvVar2("AWS_SECRET_ACCESS_KEY");
|
|
193931
194535
|
}
|
|
@@ -193952,6 +194556,15 @@ function resolveSlug(slug2) {
|
|
|
193952
194556
|
}
|
|
193953
194557
|
return vertexId;
|
|
193954
194558
|
}
|
|
194559
|
+
if (alias?.routing === "azure") {
|
|
194560
|
+
const deployment = process.env[AZURE_DEPLOYMENT_ENV]?.trim();
|
|
194561
|
+
if (!deployment) {
|
|
194562
|
+
throw new Error(
|
|
194563
|
+
`${AZURE_DEPLOYMENT_ENV} env var is required when the model is set to "${slug2}". set it to the name of your Azure OpenAI deployment (not the model it serves \u2014 Azure routes on the deployment name). see https://docs.pullfrog.com/azure for setup.`
|
|
194564
|
+
);
|
|
194565
|
+
}
|
|
194566
|
+
return `${AZURE_PROVIDER}/${deployment}`;
|
|
194567
|
+
}
|
|
193955
194568
|
if (alias?.routing === "openai-compatible") {
|
|
193956
194569
|
const modelId = process.env[OPENAI_COMPATIBLE_MODEL_ENV]?.trim();
|
|
193957
194570
|
if (!modelId) {
|
|
@@ -193990,6 +194603,7 @@ function resolveAgent(ctx) {
|
|
|
193990
194603
|
}
|
|
193991
194604
|
log2.warning(`\xBB unknown PULLFROG_AGENT="${envAgent}" \u2014 falling through to auto-select`);
|
|
193992
194605
|
}
|
|
194606
|
+
if (ctx.proxyModel) return agents.opencode;
|
|
193993
194607
|
if (ctx.model && hasBedrockAuth() && process.env[BEDROCK_MODEL_ID_ENV]?.trim() === ctx.model) {
|
|
193994
194608
|
return isBedrockAnthropicId(ctx.model) ? agents.claude : agents.opencode;
|
|
193995
194609
|
}
|
|
@@ -193999,12 +194613,14 @@ function resolveAgent(ctx) {
|
|
|
193999
194613
|
if (ctx.model) {
|
|
194000
194614
|
try {
|
|
194001
194615
|
const provider2 = getModelProvider(ctx.model);
|
|
194002
|
-
if (provider2 === "anthropic" && hasClaudeCodeAuth())
|
|
194003
|
-
|
|
194004
|
-
}
|
|
194616
|
+
if (provider2 === "anthropic" && hasClaudeCodeAuth()) return agents.claude;
|
|
194617
|
+
if (provider2 === "openai" && ctx.codexAgent && hasCodexAuth()) return agents.codex;
|
|
194005
194618
|
} catch {
|
|
194006
194619
|
}
|
|
194007
194620
|
}
|
|
194621
|
+
if (!ctx.model && ctx.codexAgent && hasCodexAuth() && !hasClaudeCodeAuth()) {
|
|
194622
|
+
return agents.codex;
|
|
194623
|
+
}
|
|
194008
194624
|
return agents.opencode;
|
|
194009
194625
|
}
|
|
194010
194626
|
|
|
@@ -194102,10 +194718,37 @@ auto-compaction is disabled, so long runs grow until your endpoint refuses them.
|
|
|
194102
194718
|
|
|
194103
194719
|
for full setup instructions, see https://docs.pullfrog.com/openai-compatible`;
|
|
194104
194720
|
}
|
|
194721
|
+
function buildAzureSetupError(params) {
|
|
194722
|
+
const githubSecretsUrl = `https://github.com/${params.owner}/${params.name}/settings/secrets/actions`;
|
|
194723
|
+
return `Azure OpenAI selected but required configuration is missing: ${params.missing.join(", ")}.
|
|
194724
|
+
|
|
194725
|
+
only the API key is sensitive \u2014 add it as a secret at ${githubSecretsUrl}. the rest is plain workflow \`env:\`:
|
|
194726
|
+
|
|
194727
|
+
${AZURE_RESOURCE_NAME_ENV}: <name>
|
|
194728
|
+
${AZURE_API_KEY_ENV}: \${{ secrets.${AZURE_API_KEY_ENV} }}
|
|
194729
|
+
${AZURE_DEPLOYMENT_ENV}: <deployment-name>
|
|
194730
|
+
${AZURE_CONTEXT_ENV}: "400000"
|
|
194731
|
+
${AZURE_MAX_OUTPUT_ENV}: "128000"
|
|
194732
|
+
|
|
194733
|
+
${AZURE_RESOURCE_NAME_ENV} is the \`<name>\` in your endpoint https://<name>.openai.azure.com.
|
|
194734
|
+
${AZURE_DEPLOYMENT_ENV} is the name of the deployment, which is not necessarily the name of
|
|
194735
|
+
the model it serves \u2014 Azure routes on the deployment name.
|
|
194736
|
+
|
|
194737
|
+
set the last two to the real limits of whichever model your deployment serves. Pullfrog can't
|
|
194738
|
+
discover them \u2014 a deployment name carries no catalog metadata \u2014 and without them completions
|
|
194739
|
+
are capped at 32000 tokens (rejected outright by models with a smaller cap) and auto-compaction
|
|
194740
|
+
is disabled, so long runs grow until Azure refuses them.
|
|
194741
|
+
|
|
194742
|
+
for full setup instructions, see https://docs.pullfrog.com/azure`;
|
|
194743
|
+
}
|
|
194105
194744
|
function hasEnvVar3(name) {
|
|
194106
194745
|
const value2 = process.env[name];
|
|
194107
194746
|
return typeof value2 === "string" && value2.length > 0;
|
|
194108
194747
|
}
|
|
194748
|
+
function modelHasRuntimeAuth(model) {
|
|
194749
|
+
const authVars = [...getModelEnvVars(model), ...getModelManagedCredentials(model)];
|
|
194750
|
+
return authVars.length === 0 || authVars.some(hasEnvVar3);
|
|
194751
|
+
}
|
|
194109
194752
|
function hasPositiveNumberEnvVar(name) {
|
|
194110
194753
|
return Number(process.env[name]) > 0;
|
|
194111
194754
|
}
|
|
@@ -194124,6 +194767,17 @@ function validateOpenAICompatibleSetup(params) {
|
|
|
194124
194767
|
);
|
|
194125
194768
|
}
|
|
194126
194769
|
}
|
|
194770
|
+
function validateAzureSetup(params) {
|
|
194771
|
+
const missing = [];
|
|
194772
|
+
if (!hasEnvVar3(AZURE_API_KEY_ENV)) missing.push(AZURE_API_KEY_ENV);
|
|
194773
|
+
if (!hasEnvVar3(AZURE_RESOURCE_NAME_ENV)) missing.push(AZURE_RESOURCE_NAME_ENV);
|
|
194774
|
+
if (!hasEnvVar3(AZURE_DEPLOYMENT_ENV)) missing.push(AZURE_DEPLOYMENT_ENV);
|
|
194775
|
+
if (!hasPositiveNumberEnvVar(AZURE_CONTEXT_ENV)) missing.push(AZURE_CONTEXT_ENV);
|
|
194776
|
+
if (!hasPositiveNumberEnvVar(AZURE_MAX_OUTPUT_ENV)) missing.push(AZURE_MAX_OUTPUT_ENV);
|
|
194777
|
+
if (missing.length > 0) {
|
|
194778
|
+
throw new Error(buildAzureSetupError({ owner: params.owner, name: params.name, missing }));
|
|
194779
|
+
}
|
|
194780
|
+
}
|
|
194127
194781
|
function validateBedrockSetup(params) {
|
|
194128
194782
|
const hasAuth = hasEnvVar3("AWS_BEARER_TOKEN_BEDROCK") || hasEnvVar3("AWS_ACCESS_KEY_ID") && hasEnvVar3("AWS_SECRET_ACCESS_KEY");
|
|
194129
194783
|
const missing = [];
|
|
@@ -194147,6 +194801,12 @@ function validateVertexSetup(params) {
|
|
|
194147
194801
|
throw new Error(buildVertexSetupError({ owner: params.owner, name: params.name, missing }));
|
|
194148
194802
|
}
|
|
194149
194803
|
}
|
|
194804
|
+
function hasSingleProviderAuth(agentName) {
|
|
194805
|
+
if (agentName === "codex") {
|
|
194806
|
+
return hasEnvVar3("OPENAI_API_KEY") || hasEnvVar3("CODEX_AUTH_JSON");
|
|
194807
|
+
}
|
|
194808
|
+
return hasEnvVar3("ANTHROPIC_API_KEY") || hasEnvVar3("CLAUDE_CODE_OAUTH_TOKEN");
|
|
194809
|
+
}
|
|
194150
194810
|
function validateAgentApiKey(params) {
|
|
194151
194811
|
if (params.model) {
|
|
194152
194812
|
const alias = resolveDisplayAlias(params.model);
|
|
@@ -194162,6 +194822,10 @@ function validateAgentApiKey(params) {
|
|
|
194162
194822
|
validateOpenAICompatibleSetup({ owner: params.owner, name: params.name });
|
|
194163
194823
|
return;
|
|
194164
194824
|
}
|
|
194825
|
+
if (params.model.startsWith(`${AZURE_PROVIDER}/`)) {
|
|
194826
|
+
validateAzureSetup({ owner: params.owner, name: params.name });
|
|
194827
|
+
return;
|
|
194828
|
+
}
|
|
194165
194829
|
if (!params.model.includes("/")) {
|
|
194166
194830
|
if (process.env[VERTEX_MODEL_ID_ENV]?.trim() === params.model) {
|
|
194167
194831
|
validateVertexSetup({ owner: params.owner, name: params.name });
|
|
@@ -194185,7 +194849,7 @@ function validateAgentApiKey(params) {
|
|
|
194185
194849
|
})
|
|
194186
194850
|
);
|
|
194187
194851
|
}
|
|
194188
|
-
if (
|
|
194852
|
+
if (hasSingleProviderAuth(params.agent.name)) return;
|
|
194189
194853
|
throw new Error(
|
|
194190
194854
|
buildKeyError({
|
|
194191
194855
|
owner: params.owner,
|
|
@@ -194197,7 +194861,7 @@ function validateAgentApiKey(params) {
|
|
|
194197
194861
|
);
|
|
194198
194862
|
}
|
|
194199
194863
|
if (params.agent.name === "opencode") {
|
|
194200
|
-
if (params.authorized.
|
|
194864
|
+
if ([...params.authorized].some(modelHasRuntimeAuth)) return;
|
|
194201
194865
|
const reason = getModelsFailure();
|
|
194202
194866
|
if (reason) throw new Error(reason);
|
|
194203
194867
|
throw new Error(
|
|
@@ -194209,7 +194873,7 @@ function validateAgentApiKey(params) {
|
|
|
194209
194873
|
})
|
|
194210
194874
|
);
|
|
194211
194875
|
}
|
|
194212
|
-
if (
|
|
194876
|
+
if (hasSingleProviderAuth(params.agent.name)) return;
|
|
194213
194877
|
throw new Error(
|
|
194214
194878
|
buildKeyError({
|
|
194215
194879
|
owner: params.owner,
|
|
@@ -194582,9 +195246,9 @@ async function checkConfiguredCredentials(params) {
|
|
|
194582
195246
|
|
|
194583
195247
|
// utils/gitAuthServer.ts
|
|
194584
195248
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
194585
|
-
import { writeFileSync as
|
|
195249
|
+
import { writeFileSync as writeFileSync15 } from "node:fs";
|
|
194586
195250
|
import { createServer as createServer3 } from "node:http";
|
|
194587
|
-
import { join as
|
|
195251
|
+
import { join as join25 } from "node:path";
|
|
194588
195252
|
var REVOKED_TRAP_MS = 6e4;
|
|
194589
195253
|
function revokeGitHubToken(token) {
|
|
194590
195254
|
fetch("https://api.github.com/installation/token", {
|
|
@@ -194653,7 +195317,7 @@ async function startGitAuthServer(tmpdir4) {
|
|
|
194653
195317
|
function writeAskpassScript(code) {
|
|
194654
195318
|
const scriptId = randomUUID5();
|
|
194655
195319
|
const scriptName = `askpass-${scriptId}.js`;
|
|
194656
|
-
const scriptPath =
|
|
195320
|
+
const scriptPath = join25(tmpdir4, scriptName);
|
|
194657
195321
|
const content = [
|
|
194658
195322
|
`#!/usr/bin/env node`,
|
|
194659
195323
|
`var a=process.argv[2]||"";`,
|
|
@@ -194666,7 +195330,7 @@ async function startGitAuthServer(tmpdir4) {
|
|
|
194666
195330
|
`r.on("end",function(){process.stdout.write(d+"\\n")})`,
|
|
194667
195331
|
`}).on("error",function(){process.exit(1)})}`
|
|
194668
195332
|
].join("\n");
|
|
194669
|
-
|
|
195333
|
+
writeFileSync15(scriptPath, content, { mode: 448 });
|
|
194670
195334
|
return scriptPath;
|
|
194671
195335
|
}
|
|
194672
195336
|
async function close() {
|
|
@@ -195105,7 +195769,7 @@ function resolveInstructions(ctx) {
|
|
|
195105
195769
|
|
|
195106
195770
|
// utils/learnings.ts
|
|
195107
195771
|
import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
|
|
195108
|
-
import { dirname as dirname4, join as
|
|
195772
|
+
import { dirname as dirname4, join as join26 } from "node:path";
|
|
195109
195773
|
|
|
195110
195774
|
// utils/learningsTruncate.ts
|
|
195111
195775
|
var MAX_LEARNINGS_LENGTH = 1e5;
|
|
@@ -195123,10 +195787,10 @@ function truncateAtLineBoundary(body, cap) {
|
|
|
195123
195787
|
var LEARNINGS_FILE_NAME = "pullfrog-learnings.md";
|
|
195124
195788
|
var XREPO_LEARNINGS_FILE_NAME = "pullfrog-xrepo-learnings.md";
|
|
195125
195789
|
function learningsFilePath(tmpdir4) {
|
|
195126
|
-
return
|
|
195790
|
+
return join26(tmpdir4, LEARNINGS_FILE_NAME);
|
|
195127
195791
|
}
|
|
195128
195792
|
function xrepoLearningsFilePath(tmpdir4) {
|
|
195129
|
-
return
|
|
195793
|
+
return join26(tmpdir4, XREPO_LEARNINGS_FILE_NAME);
|
|
195130
195794
|
}
|
|
195131
195795
|
async function seedLearningsFile(params) {
|
|
195132
195796
|
const path4 = learningsFilePath(params.tmpdir);
|
|
@@ -195242,7 +195906,7 @@ async function persistXrepoLearnings(ctx) {
|
|
|
195242
195906
|
// utils/modelAccess.ts
|
|
195243
195907
|
function decideModelAccess(input) {
|
|
195244
195908
|
if (!input.modelExplicit || !input.model) return { kind: "ok" };
|
|
195245
|
-
const byokAuthorized = !!input.resolvedModel && (input.authorized.has(input.resolvedModel) || !input.resolvedModel.includes("/") || input.resolvedModel.startsWith(`${OPENAI_COMPATIBLE_PROVIDER}/`));
|
|
195909
|
+
const byokAuthorized = !!input.resolvedModel && (input.authorized.has(input.resolvedModel) || !input.resolvedModel.includes("/") || input.resolvedModel.startsWith(`${OPENAI_COMPATIBLE_PROVIDER}/`) || input.resolvedModel.startsWith(`${AZURE_PROVIDER}/`));
|
|
195246
195910
|
if (input.proxyActive) {
|
|
195247
195911
|
const target = resolveOpenRouterModel(input.model);
|
|
195248
195912
|
if (input.oss) {
|
|
@@ -195287,7 +195951,7 @@ function buildModelAccessError(input) {
|
|
|
195287
195951
|
}
|
|
195288
195952
|
|
|
195289
195953
|
// utils/normalizeEnv.ts
|
|
195290
|
-
var
|
|
195954
|
+
var core5 = __toESM(require_core(), 1);
|
|
195291
195955
|
function hasControlCharacter(value2) {
|
|
195292
195956
|
return [...value2].some((ch) => {
|
|
195293
195957
|
const code = ch.charCodeAt(0);
|
|
@@ -195313,7 +195977,7 @@ function sanitizeSecret(key, value2) {
|
|
|
195313
195977
|
`\xBB stripped whitespace from ${key} (whitespace in secret values breaks GitHub Actions log masking)`
|
|
195314
195978
|
);
|
|
195315
195979
|
}
|
|
195316
|
-
|
|
195980
|
+
core5.setSecret(trimmed);
|
|
195317
195981
|
return trimmed;
|
|
195318
195982
|
}
|
|
195319
195983
|
function normalizeEnv() {
|
|
@@ -195357,7 +196021,7 @@ function normalizeEnv() {
|
|
|
195357
196021
|
}
|
|
195358
196022
|
|
|
195359
196023
|
// utils/overrides.ts
|
|
195360
|
-
var
|
|
196024
|
+
var core6 = __toESM(require_core(), 1);
|
|
195361
196025
|
var DENIED_OVERRIDE_NAMES = /* @__PURE__ */ new Set([
|
|
195362
196026
|
"GITHUB_TOKEN",
|
|
195363
196027
|
"GH_TOKEN",
|
|
@@ -195403,7 +196067,7 @@ function applyOverrides(params) {
|
|
|
195403
196067
|
denied.push(key);
|
|
195404
196068
|
continue;
|
|
195405
196069
|
}
|
|
195406
|
-
if (value2.length > 0)
|
|
196070
|
+
if (value2.length > 0) core6.setSecret(value2);
|
|
195407
196071
|
params.env[key] = value2;
|
|
195408
196072
|
applied.push(key);
|
|
195409
196073
|
}
|
|
@@ -195412,8 +196076,8 @@ function applyOverrides(params) {
|
|
|
195412
196076
|
}
|
|
195413
196077
|
|
|
195414
196078
|
// utils/payload.ts
|
|
195415
|
-
var
|
|
195416
|
-
import { readFileSync as
|
|
196079
|
+
var core7 = __toESM(require_core(), 1);
|
|
196080
|
+
import { readFileSync as readFileSync7 } from "node:fs";
|
|
195417
196081
|
import { isAbsolute as isAbsolute2, resolve as resolve2 } from "node:path";
|
|
195418
196082
|
|
|
195419
196083
|
// utils/versioning.ts
|
|
@@ -195500,8 +196164,8 @@ function resolveCwd(cwd) {
|
|
|
195500
196164
|
return workspace ? resolve2(workspace, cwd) : cwd;
|
|
195501
196165
|
}
|
|
195502
196166
|
function resolvePromptInput() {
|
|
195503
|
-
const promptInput =
|
|
195504
|
-
const promptFile =
|
|
196167
|
+
const promptInput = core7.getInput("prompt");
|
|
196168
|
+
const promptFile = core7.getInput("prompt_file");
|
|
195505
196169
|
if (promptInput && promptFile) {
|
|
195506
196170
|
throw new Error("set exactly one of 'prompt' or 'prompt_file' inputs, not both.");
|
|
195507
196171
|
}
|
|
@@ -195527,7 +196191,7 @@ function resolvePromptInput() {
|
|
|
195527
196191
|
function resolvePromptFile(input) {
|
|
195528
196192
|
const workspace = process.env.GITHUB_WORKSPACE;
|
|
195529
196193
|
const path4 = isAbsolute2(input) ? input : workspace ? resolve2(workspace, input) : resolve2(input);
|
|
195530
|
-
const content =
|
|
196194
|
+
const content = readFileSync7(path4, "utf-8");
|
|
195531
196195
|
if (!content.trim()) {
|
|
195532
196196
|
throw new Error(`prompt_file ${JSON.stringify(input)} is empty.`);
|
|
195533
196197
|
}
|
|
@@ -195535,7 +196199,7 @@ function resolvePromptFile(input) {
|
|
|
195535
196199
|
}
|
|
195536
196200
|
function warnIfDeprecatedStatusChecks(value2) {
|
|
195537
196201
|
if (value2 !== void 0) {
|
|
195538
|
-
|
|
196202
|
+
core7.warning(
|
|
195539
196203
|
"`status_checks` is deprecated. Both checks are now repository settings \u2014 open the Pullfrog console for this repo (Automations \u2192 Review PRs) and set them there, then remove `status_checks` from your workflow. It keeps working until you do."
|
|
195540
196204
|
);
|
|
195541
196205
|
}
|
|
@@ -195543,15 +196207,15 @@ function warnIfDeprecatedStatusChecks(value2) {
|
|
|
195543
196207
|
}
|
|
195544
196208
|
function resolveNonPromptInputs() {
|
|
195545
196209
|
return Inputs.omit("prompt", "prompt_file").assert({
|
|
195546
|
-
model:
|
|
195547
|
-
effort:
|
|
195548
|
-
debug:
|
|
195549
|
-
timeout:
|
|
195550
|
-
cwd:
|
|
195551
|
-
push:
|
|
195552
|
-
shell:
|
|
195553
|
-
status_checks: warnIfDeprecatedStatusChecks(
|
|
195554
|
-
progress_comments:
|
|
196210
|
+
model: core7.getInput("model") || void 0,
|
|
196211
|
+
effort: core7.getInput("effort") || void 0,
|
|
196212
|
+
debug: core7.getInput("debug") || void 0,
|
|
196213
|
+
timeout: core7.getInput("timeout") || void 0,
|
|
196214
|
+
cwd: core7.getInput("cwd") || void 0,
|
|
196215
|
+
push: core7.getInput("push") || void 0,
|
|
196216
|
+
shell: core7.getInput("shell") || void 0,
|
|
196217
|
+
status_checks: warnIfDeprecatedStatusChecks(core7.getInput("status_checks") || void 0),
|
|
196218
|
+
progress_comments: core7.getInput("progress_comments") || void 0
|
|
195555
196219
|
});
|
|
195556
196220
|
}
|
|
195557
196221
|
function resolvePayload(resolvedPromptInput, repoSettings) {
|
|
@@ -195619,7 +196283,7 @@ function resolvePayload(resolvedPromptInput, repoSettings) {
|
|
|
195619
196283
|
};
|
|
195620
196284
|
}
|
|
195621
196285
|
function resolveOutputSchema() {
|
|
195622
|
-
const raw2 =
|
|
196286
|
+
const raw2 = core7.getInput("output_schema");
|
|
195623
196287
|
if (!raw2) return void 0;
|
|
195624
196288
|
let parsed2;
|
|
195625
196289
|
try {
|
|
@@ -195635,10 +196299,10 @@ function resolveOutputSchema() {
|
|
|
195635
196299
|
}
|
|
195636
196300
|
|
|
195637
196301
|
// utils/proxy.ts
|
|
195638
|
-
var
|
|
196302
|
+
var core9 = __toESM(require_core(), 1);
|
|
195639
196303
|
|
|
195640
196304
|
// utils/token.ts
|
|
195641
|
-
var
|
|
196305
|
+
var core8 = __toESM(require_core(), 1);
|
|
195642
196306
|
import assert2 from "node:assert/strict";
|
|
195643
196307
|
var mcpTokenValue;
|
|
195644
196308
|
var refreshMcpTokenFn;
|
|
@@ -195646,7 +196310,7 @@ function getMcpTokenRefresh() {
|
|
|
195646
196310
|
return refreshMcpTokenFn;
|
|
195647
196311
|
}
|
|
195648
196312
|
function getJobToken() {
|
|
195649
|
-
const inputToken =
|
|
196313
|
+
const inputToken = core8.getInput("token");
|
|
195650
196314
|
if (inputToken) {
|
|
195651
196315
|
return inputToken;
|
|
195652
196316
|
}
|
|
@@ -195662,7 +196326,7 @@ async function resolveTokens(params) {
|
|
|
195662
196326
|
if (externalToken) {
|
|
195663
196327
|
mcpTokenValue = externalToken;
|
|
195664
196328
|
if (isGitHubActions) {
|
|
195665
|
-
|
|
196329
|
+
core8.setSecret(externalToken);
|
|
195666
196330
|
}
|
|
195667
196331
|
log2.info("\xBB using external GH_TOKEN for both git and MCP");
|
|
195668
196332
|
return {
|
|
@@ -195682,7 +196346,7 @@ async function resolveTokens(params) {
|
|
|
195682
196346
|
const gitPermissions = params.push === "disabled" ? { contents: "read" } : { contents: "write", workflows: "write" };
|
|
195683
196347
|
const gitToken = await acquireNewToken({ repos: writeRepos, permissions: gitPermissions });
|
|
195684
196348
|
if (isGitHubActions) {
|
|
195685
|
-
|
|
196349
|
+
core8.setSecret(gitToken);
|
|
195686
196350
|
}
|
|
195687
196351
|
log2.info(
|
|
195688
196352
|
`\xBB acquired git token (${Object.entries(gitPermissions).map((e) => e.join(":")).join(", ")})`
|
|
@@ -195699,7 +196363,7 @@ async function resolveTokens(params) {
|
|
|
195699
196363
|
};
|
|
195700
196364
|
const mcpToken = await acquireNewToken({ repos: writeRepos, permissions: mcpPermissions });
|
|
195701
196365
|
if (isGitHubActions) {
|
|
195702
|
-
|
|
196366
|
+
core8.setSecret(mcpToken);
|
|
195703
196367
|
}
|
|
195704
196368
|
log2.info(
|
|
195705
196369
|
`\xBB acquired scoped MCP token (${Object.entries(mcpPermissions).map((e) => e.join(":")).join(", ")})`
|
|
@@ -195708,7 +196372,7 @@ async function resolveTokens(params) {
|
|
|
195708
196372
|
let ghToken;
|
|
195709
196373
|
if (ghPermissions) {
|
|
195710
196374
|
ghToken = await acquireNewToken({ permissions: ghPermissions });
|
|
195711
|
-
if (isGitHubActions)
|
|
196375
|
+
if (isGitHubActions) core8.setSecret(ghToken);
|
|
195712
196376
|
log2.info(
|
|
195713
196377
|
`\xBB acquired gh token mirroring ${params.authorPermission} (${formatPermissions(ghPermissions)})`
|
|
195714
196378
|
);
|
|
@@ -195719,7 +196383,7 @@ async function resolveTokens(params) {
|
|
|
195719
196383
|
repos: params.xrepo.read,
|
|
195720
196384
|
permissions: { contents: "read" }
|
|
195721
196385
|
});
|
|
195722
|
-
if (isGitHubActions)
|
|
196386
|
+
if (isGitHubActions) core8.setSecret(readToken);
|
|
195723
196387
|
log2.info(`\xBB acquired cross-repo read token (contents:read, ${params.xrepo.read.length} repos)`);
|
|
195724
196388
|
}
|
|
195725
196389
|
mcpTokenValue = mcpToken;
|
|
@@ -195738,7 +196402,7 @@ async function resolveTokens(params) {
|
|
|
195738
196402
|
oidc: params.oidc ?? void 0
|
|
195739
196403
|
}).then((fresh) => {
|
|
195740
196404
|
if (isGitHubActions) {
|
|
195741
|
-
|
|
196405
|
+
core8.setSecret(fresh);
|
|
195742
196406
|
}
|
|
195743
196407
|
mcpTokenValue = fresh;
|
|
195744
196408
|
currentMcpToken = fresh;
|
|
@@ -195759,7 +196423,7 @@ async function resolveTokens(params) {
|
|
|
195759
196423
|
permissions: gitPermissions,
|
|
195760
196424
|
oidc: params.oidc ?? void 0
|
|
195761
196425
|
}).then((fresh) => {
|
|
195762
|
-
if (isGitHubActions)
|
|
196426
|
+
if (isGitHubActions) core8.setSecret(fresh);
|
|
195763
196427
|
void revokeGitHubInstallationToken(currentGitToken);
|
|
195764
196428
|
currentGitToken = fresh;
|
|
195765
196429
|
log2.warning("\xBB GitHub rejected the git token; re-acquired a fresh git token");
|
|
@@ -195776,7 +196440,7 @@ async function resolveTokens(params) {
|
|
|
195776
196440
|
permissions: { contents: "read" },
|
|
195777
196441
|
oidc: params.oidc ?? void 0
|
|
195778
196442
|
}).then((fresh) => {
|
|
195779
|
-
if (isGitHubActions)
|
|
196443
|
+
if (isGitHubActions) core8.setSecret(fresh);
|
|
195780
196444
|
void revokeGitHubInstallationToken(read2);
|
|
195781
196445
|
currentReadToken = fresh;
|
|
195782
196446
|
log2.warning("\xBB GitHub rejected the read token; re-acquired a fresh read token");
|
|
@@ -195990,7 +196654,7 @@ async function resolveProxyModel(ctx) {
|
|
|
195990
196654
|
});
|
|
195991
196655
|
if (!key) return;
|
|
195992
196656
|
process.env.OPENROUTER_API_KEY = key;
|
|
195993
|
-
|
|
196657
|
+
core9.setSecret(key);
|
|
195994
196658
|
ctx.payload.proxyModel = ctx.proxyModel;
|
|
195995
196659
|
ctx.toolState.model = ctx.proxyModel;
|
|
195996
196660
|
const label = ctx.oss ? "oss" : "router";
|
|
@@ -196061,7 +196725,7 @@ async function runProxyResolution(ctx) {
|
|
|
196061
196725
|
|
|
196062
196726
|
// utils/prSummary.ts
|
|
196063
196727
|
import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile3 } from "node:fs/promises";
|
|
196064
|
-
import { dirname as dirname5, join as
|
|
196728
|
+
import { dirname as dirname5, join as join27 } from "node:path";
|
|
196065
196729
|
var SUMMARY_FILE_NAME = "pullfrog-summary.md";
|
|
196066
196730
|
var SUMMARY_SCAFFOLD = `# PR summary
|
|
196067
196731
|
|
|
@@ -196071,7 +196735,7 @@ var SUMMARY_SCAFFOLD = `# PR summary
|
|
|
196071
196735
|
var MIN_SNAPSHOT_LENGTH = 60;
|
|
196072
196736
|
var MAX_SNAPSHOT_LENGTH = 32768;
|
|
196073
196737
|
function summaryFilePath(tmpdir4) {
|
|
196074
|
-
return
|
|
196738
|
+
return join27(tmpdir4, SUMMARY_FILE_NAME);
|
|
196075
196739
|
}
|
|
196076
196740
|
async function seedSummaryFile(params) {
|
|
196077
196741
|
const path4 = summaryFilePath(params.tmpdir);
|
|
@@ -196200,6 +196864,7 @@ var defaultSettings = {
|
|
|
196200
196864
|
shell: "restricted",
|
|
196201
196865
|
prApproveEnabled: false,
|
|
196202
196866
|
autoMergeEnabled: false,
|
|
196867
|
+
codexAgent: false,
|
|
196203
196868
|
signedCommits: false,
|
|
196204
196869
|
repoIntelligence: false,
|
|
196205
196870
|
progressComments: true,
|
|
@@ -196688,7 +197353,7 @@ ${genericBody}`,
|
|
|
196688
197353
|
}
|
|
196689
197354
|
|
|
196690
197355
|
// utils/runLifecycle.ts
|
|
196691
|
-
var
|
|
197356
|
+
var core10 = __toESM(require_core(), 1);
|
|
196692
197357
|
|
|
196693
197358
|
// utils/autoMerge.ts
|
|
196694
197359
|
function hasBlockingHumanReview(reviews) {
|
|
@@ -197074,7 +197739,7 @@ async function finalizeSuccessRun(input) {
|
|
|
197074
197739
|
}
|
|
197075
197740
|
if (input.toolState.output) {
|
|
197076
197741
|
log2.info(`::pullfrog-output::${Buffer.from(input.toolState.output).toString("base64")}`);
|
|
197077
|
-
|
|
197742
|
+
core10.setOutput("result", input.toolState.output);
|
|
197078
197743
|
}
|
|
197079
197744
|
if (input.result.success) {
|
|
197080
197745
|
await approveAfterFix(input.toolContext).catch((error52) => {
|
|
@@ -197538,7 +198203,11 @@ async function main() {
|
|
|
197538
198203
|
}
|
|
197539
198204
|
const resolvedModel = credentials.kind === "fellBack" ? credentials.replacement : configuredModel;
|
|
197540
198205
|
vertexCredentials = materializeVertexCredentials({ model: resolvedModel });
|
|
197541
|
-
const agent2 = resolveAgent({
|
|
198206
|
+
const agent2 = resolveAgent({
|
|
198207
|
+
model: resolvedModel,
|
|
198208
|
+
proxyModel: payload.proxyModel,
|
|
198209
|
+
codexAgent: runContext.repoSettings.codexAgent
|
|
198210
|
+
});
|
|
197542
198211
|
const effectiveModel = payload.proxyModel ?? resolvedModel ?? payload.model;
|
|
197543
198212
|
toolState.model = effectiveModel;
|
|
197544
198213
|
if (!payload.proxyModel) {
|
|
@@ -197698,11 +198367,16 @@ async function main() {
|
|
|
197698
198367
|
xrepoLearningsFilePath: toolState.xrepoLearningsFilePath ?? null,
|
|
197699
198368
|
xrepoLearningsHeadings: runContext.repoSettings.xrepoLearningsHeadings
|
|
197700
198369
|
});
|
|
197701
|
-
|
|
198370
|
+
const danglingToolRefs = findDanglingPromptToolRefs({
|
|
197702
198371
|
agentId,
|
|
197703
198372
|
prompt: instructions.full,
|
|
197704
198373
|
toolNames: mcpHttpServer.toolNames
|
|
197705
198374
|
});
|
|
198375
|
+
if (danglingToolRefs.length > 0) {
|
|
198376
|
+
log2.warning(
|
|
198377
|
+
`\xBB prompt advertises ${danglingToolRefs.length} tool(s) the MCP server did not register: ${danglingToolRefs.join(", ")}`
|
|
198378
|
+
);
|
|
198379
|
+
}
|
|
197706
198380
|
const logParts = [
|
|
197707
198381
|
instructions.eventInstructions ? `EVENT-LEVEL INSTRUCTIONS:
|
|
197708
198382
|
${instructions.eventInstructions}` : null,
|
|
@@ -197717,8 +198391,8 @@ ${instructions.user}` : null,
|
|
|
197717
198391
|
log2.info(instructions.full);
|
|
197718
198392
|
});
|
|
197719
198393
|
if (agentId === "opencode") {
|
|
197720
|
-
const pluginDir =
|
|
197721
|
-
const hasPlugins =
|
|
198394
|
+
const pluginDir = join28(process.cwd(), ".opencode", "plugin");
|
|
198395
|
+
const hasPlugins = existsSync9(pluginDir) && readdirSync2(pluginDir).some((f) => /\.[jt]sx?$/.test(f));
|
|
197722
198396
|
if (hasPlugins && toolState.dependencyInstallation?.promise) {
|
|
197723
198397
|
log2.info(
|
|
197724
198398
|
"\xBB .opencode/plugin/ detected \u2014 awaiting dependency installation before agent start"
|
|
@@ -197910,27 +198584,27 @@ async function runMain() {
|
|
|
197910
198584
|
}
|
|
197911
198585
|
} catch (error52) {
|
|
197912
198586
|
const errorMessage = error52 instanceof Error ? error52.message : "unknown error occurred";
|
|
197913
|
-
|
|
198587
|
+
core11.setFailed(`action failed: ${errorMessage}`);
|
|
197914
198588
|
}
|
|
197915
198589
|
}
|
|
197916
198590
|
async function tokenMain() {
|
|
197917
|
-
const reposInput =
|
|
198591
|
+
const reposInput = core11.getInput("repos");
|
|
197918
198592
|
const additionalRepos = reposInput ? reposInput.split(",").map((r2) => r2.trim()).filter(Boolean) : [];
|
|
197919
198593
|
const token = await acquireNewToken({ repos: additionalRepos });
|
|
197920
|
-
|
|
197921
|
-
|
|
197922
|
-
|
|
198594
|
+
core11.setSecret(token);
|
|
198595
|
+
core11.saveState(STATE_TOKEN, token);
|
|
198596
|
+
core11.setOutput("token", token);
|
|
197923
198597
|
const scope2 = additionalRepos.length ? `current repo + ${additionalRepos.join(", ")}` : "current repo only";
|
|
197924
|
-
|
|
198598
|
+
core11.info(`\xBB installation token acquired (${scope2})`);
|
|
197925
198599
|
}
|
|
197926
198600
|
async function tokenPost() {
|
|
197927
|
-
const token =
|
|
198601
|
+
const token = core11.getState(STATE_TOKEN);
|
|
197928
198602
|
if (!token) {
|
|
197929
|
-
|
|
198603
|
+
core11.debug("no token found in state, skipping revocation");
|
|
197930
198604
|
return;
|
|
197931
198605
|
}
|
|
197932
198606
|
await revokeGitHubInstallationToken(token);
|
|
197933
|
-
|
|
198607
|
+
core11.info("\xBB installation token revoked");
|
|
197934
198608
|
}
|
|
197935
198609
|
function printGhaUsage(params) {
|
|
197936
198610
|
params.stream(`usage: ${params.prog} gha [subcommand]
|
|
@@ -198046,7 +198720,7 @@ async function run(args2) {
|
|
|
198046
198720
|
}
|
|
198047
198721
|
} catch (error52) {
|
|
198048
198722
|
const message = error52 instanceof Error ? error52.message : String(error52);
|
|
198049
|
-
|
|
198723
|
+
core11.setFailed(message);
|
|
198050
198724
|
}
|
|
198051
198725
|
}
|
|
198052
198726
|
|
|
@@ -198893,7 +199567,7 @@ async function runCli4(input) {
|
|
|
198893
199567
|
}
|
|
198894
199568
|
|
|
198895
199569
|
// cli.ts
|
|
198896
|
-
var VERSION10 = "0.1.
|
|
199570
|
+
var VERSION10 = "0.1.59";
|
|
198897
199571
|
var bin = basename2(process.argv[1] || "");
|
|
198898
199572
|
var PROG = bin === "pf" || bin === "pullfrog" ? bin : "pullfrog";
|
|
198899
199573
|
var rawArgs = process.argv.slice(2);
|