pullfrog 0.1.104 → 0.1.106
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/README.md +3 -3
- package/dist/cli.mjs +328 -181
- package/dist/external.d.ts +3 -2
- package/dist/index.js +153 -48
- package/dist/internal/index.d.ts +1 -0
- package/dist/internal.js +52 -3
- package/dist/models.d.ts +21 -0
- package/dist/utils/agent.d.ts +9 -0
- package/dist/utils/apiKeys.d.ts +2 -0
- package/dist/utils/runEffort.d.ts +10 -0
- package/dist/utils/setup.d.ts +2 -0
- package/package.json +1 -1
package/dist/external.d.ts
CHANGED
|
@@ -375,8 +375,9 @@ export interface WriteablePayload {
|
|
|
375
375
|
export type Payload = Readonly<WriteablePayload>;
|
|
376
376
|
/**
|
|
377
377
|
* Whether `find_similar_issues` is registered for this run: an entitled account,
|
|
378
|
-
* on an issue
|
|
379
|
-
* the
|
|
378
|
+
* on an issue or a run with no target (`pullfrog run "enrich issue #42"`), never a PR.
|
|
379
|
+
* Shared by the MCP registration and the prompt so the duplicate-detection
|
|
380
|
+
* instructions can never describe an absent tool.
|
|
380
381
|
*/
|
|
381
382
|
export declare function hasSimilarIssues(params: {
|
|
382
383
|
repoIntelligence: boolean;
|
package/dist/index.js
CHANGED
|
@@ -109939,9 +109939,34 @@ var AZURE_USE_CHAT_COMPLETIONS_ENV = "AZURE_USE_CHAT_COMPLETIONS";
|
|
|
109939
109939
|
var OPENAI_COMPATIBLE_PROVIDER = "openai-compatible";
|
|
109940
109940
|
var OPENAI_COMPATIBLE_BASE_URL_ENV = "OPENAI_COMPATIBLE_BASE_URL";
|
|
109941
109941
|
var OPENAI_COMPATIBLE_API_KEY_ENV = "OPENAI_COMPATIBLE_API_KEY";
|
|
109942
|
-
var OPENAI_COMPATIBLE_MODEL_ENV = "OPENAI_COMPATIBLE_MODEL";
|
|
109943
109942
|
var OPENAI_COMPATIBLE_CONTEXT_ENV = "OPENAI_COMPATIBLE_CONTEXT";
|
|
109944
109943
|
var OPENAI_COMPATIBLE_MAX_OUTPUT_ENV = "OPENAI_COMPATIBLE_MAX_OUTPUT";
|
|
109944
|
+
function isOpenAICompatibleSetName(name) {
|
|
109945
|
+
return name !== "byok" && name.length <= 32 && /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name);
|
|
109946
|
+
}
|
|
109947
|
+
function openAICompatibleSetName(slug2) {
|
|
109948
|
+
const prefix = `${OPENAI_COMPATIBLE_PROVIDER}/`;
|
|
109949
|
+
if (!slug2.startsWith(prefix)) return void 0;
|
|
109950
|
+
const name = slug2.slice(prefix.length);
|
|
109951
|
+
return isOpenAICompatibleSetName(name) ? name : void 0;
|
|
109952
|
+
}
|
|
109953
|
+
var OPENAI_COMPATIBLE_FIELDS = [
|
|
109954
|
+
"baseUrl",
|
|
109955
|
+
"apiKey",
|
|
109956
|
+
"model",
|
|
109957
|
+
"context",
|
|
109958
|
+
"maxOutput"
|
|
109959
|
+
];
|
|
109960
|
+
function openAICompatibleEnv(name) {
|
|
109961
|
+
const prefix = `OPENAI_COMPATIBLE_${name ? `${name.toUpperCase().replaceAll("-", "_")}_` : ""}`;
|
|
109962
|
+
return {
|
|
109963
|
+
baseUrl: `${prefix}BASE_URL`,
|
|
109964
|
+
apiKey: `${prefix}API_KEY`,
|
|
109965
|
+
model: `${prefix}MODEL`,
|
|
109966
|
+
context: `${prefix}CONTEXT`,
|
|
109967
|
+
maxOutput: `${prefix}MAX_OUTPUT`
|
|
109968
|
+
};
|
|
109969
|
+
}
|
|
109945
109970
|
var PROVIDER_GATEWAY_URL_ENV = {
|
|
109946
109971
|
anthropic: "ANTHROPIC_BASE_URL",
|
|
109947
109972
|
openai: "OPENAI_BASE_URL"
|
|
@@ -109986,7 +110011,7 @@ function findDanglingPromptToolRefs(params) {
|
|
|
109986
110011
|
return [...new Set(extractMcpToolRefs(params.agentId, params.prompt))].filter((name) => !registered.has(name)).sort();
|
|
109987
110012
|
}
|
|
109988
110013
|
function hasSimilarIssues(params) {
|
|
109989
|
-
return params.repoIntelligence &&
|
|
110014
|
+
return params.repoIntelligence && !params.event.is_pr;
|
|
109990
110015
|
}
|
|
109991
110016
|
|
|
109992
110017
|
// utils/activity.ts
|
|
@@ -111814,7 +111839,7 @@ import { chmodSync, createWriteStream, existsSync as existsSync3, mkdirSync } fr
|
|
|
111814
111839
|
import { join } from "node:path";
|
|
111815
111840
|
import { pipeline } from "node:stream/promises";
|
|
111816
111841
|
function resolveNpm() {
|
|
111817
|
-
const npmCli = process.env.
|
|
111842
|
+
const npmCli = process.env.NPM_EXECPATH;
|
|
111818
111843
|
if (npmCli?.endsWith("npm-cli.js")) return { command: process.execPath, args: [npmCli] };
|
|
111819
111844
|
return { command: "npm", args: [] };
|
|
111820
111845
|
}
|
|
@@ -112115,7 +112140,11 @@ function resolveRunEffort(ctx) {
|
|
|
112115
112140
|
const configured = ctx.payload.effort !== void 0;
|
|
112116
112141
|
const position = ctx.payload.effort ?? DEFAULT_EFFORT_POSITION;
|
|
112117
112142
|
const alias = resolveRunAlias(ctx);
|
|
112118
|
-
if (!alias)
|
|
112143
|
+
if (!alias) {
|
|
112144
|
+
const declarable = configured && !ctx.resolvedModel?.startsWith(`${AZURE_PROVIDER}/`);
|
|
112145
|
+
const rung = declarable && ctx.declaredVariants ? resolveRung({ position, published: ctx.declaredVariants }) : void 0;
|
|
112146
|
+
return { position, configured, rung, alias: void 0, declarable };
|
|
112147
|
+
}
|
|
112119
112148
|
return {
|
|
112120
112149
|
position,
|
|
112121
112150
|
configured,
|
|
@@ -112124,7 +112153,8 @@ function resolveRunEffort(ctx) {
|
|
|
112124
112153
|
position,
|
|
112125
112154
|
useOpenRouter: !!ctx.payload.proxyModel
|
|
112126
112155
|
}),
|
|
112127
|
-
alias
|
|
112156
|
+
alias,
|
|
112157
|
+
declarable: false
|
|
112128
112158
|
};
|
|
112129
112159
|
}
|
|
112130
112160
|
|
|
@@ -112141,7 +112171,7 @@ var import_semver = __toESM(require_semver2(), 1);
|
|
|
112141
112171
|
// package.json
|
|
112142
112172
|
var package_default = {
|
|
112143
112173
|
name: "pullfrog",
|
|
112144
|
-
version: "0.1.
|
|
112174
|
+
version: "0.1.106",
|
|
112145
112175
|
cliContractVersion: "1",
|
|
112146
112176
|
type: "module",
|
|
112147
112177
|
bin: {
|
|
@@ -124270,6 +124300,17 @@ function parseModel2(value2) {
|
|
|
124270
124300
|
if (slash <= 0) return void 0;
|
|
124271
124301
|
return { providerID: value2.slice(0, slash), modelID: value2.slice(slash + 1) };
|
|
124272
124302
|
}
|
|
124303
|
+
async function resolveDeclaredRung(ctx, params) {
|
|
124304
|
+
const resp = await params.client.config.providers();
|
|
124305
|
+
const provider2 = resp.data?.providers.find((p) => p.id === params.model.providerID);
|
|
124306
|
+
const variants = provider2?.models[params.model.modelID]?.variants ?? {};
|
|
124307
|
+
const name = `${params.model.providerID}/${params.model.modelID}`;
|
|
124308
|
+
const rung = resolveRunEffort({ ...ctx, declaredVariants: Object.keys(variants) }).rung;
|
|
124309
|
+
log.info(
|
|
124310
|
+
`\xBB effort: ${rung ? `${rung} (declared by opencode for ${name})` : `not applied \u2014 opencode declares no variants for ${name}`}`
|
|
124311
|
+
);
|
|
124312
|
+
return rung;
|
|
124313
|
+
}
|
|
124273
124314
|
function bootOpencodeServer(params) {
|
|
124274
124315
|
const logLevel = isDebugEnabled() ? "INFO" : "ERROR";
|
|
124275
124316
|
if (logLevel !== "ERROR") log.info(`\xBB opencode log level: ${logLevel} (debug run)`);
|
|
@@ -124924,6 +124965,11 @@ var opencode = agent({
|
|
|
124924
124965
|
log.info(`\xBB opencode session: ${sessionID}`);
|
|
124925
124966
|
const labeler = new SessionLabeler();
|
|
124926
124967
|
labeler.labelFor(sessionID);
|
|
124968
|
+
const sdkModel = parseModel2(model);
|
|
124969
|
+
const variant = effort.declarable && sdkModel ? await resolveDeclaredRung(
|
|
124970
|
+
{ ...ctx, resolvedModel: rawModel },
|
|
124971
|
+
{ client: client2, model: sdkModel }
|
|
124972
|
+
) : effort.rung;
|
|
124927
124973
|
const runnerCtx = {
|
|
124928
124974
|
client: client2,
|
|
124929
124975
|
sessionID,
|
|
@@ -124932,7 +124978,7 @@ var opencode = agent({
|
|
|
124932
124978
|
labeler,
|
|
124933
124979
|
toolState: ctx.toolState,
|
|
124934
124980
|
// `rawModel` folds in the auto-select pick — see the opencode.ts twin.
|
|
124935
|
-
variant
|
|
124981
|
+
variant,
|
|
124936
124982
|
todoTracker: ctx.todoTracker,
|
|
124937
124983
|
onActivityTimeout: ctx.onActivityTimeout,
|
|
124938
124984
|
onTurnRecovered: ctx.onTurnRecovered,
|
|
@@ -124994,7 +125040,6 @@ var opencode = agent({
|
|
|
124994
125040
|
timeoutMs: AGENT_ACTIVITY_TIMEOUT_MS,
|
|
124995
125041
|
abortTurn: () => turnController.abort()
|
|
124996
125042
|
});
|
|
124997
|
-
const sdkModel = parseModel2(model);
|
|
124998
125043
|
let salvagesLeft = 1;
|
|
124999
125044
|
const runTurn = async (text) => {
|
|
125000
125045
|
const attempt = (prompt) => {
|
|
@@ -190132,14 +190177,15 @@ function computeIncrementalDiff(params) {
|
|
|
190132
190177
|
const tips = [`origin/${params.baseBranch}`, ...params.formerBaseTips];
|
|
190133
190178
|
const oldBase = versionBase({ sha: params.beforeSha, tips });
|
|
190134
190179
|
const newBase = versionBase({ sha: params.headSha, tips });
|
|
190180
|
+
const replayed = oldBase === newBase ? null : replay({ sha: params.beforeSha, from: oldBase, onto: newBase });
|
|
190135
190181
|
const raw2 = $(
|
|
190136
190182
|
"sh",
|
|
190137
190183
|
[
|
|
190138
190184
|
"-c",
|
|
190139
190185
|
'git range-diff --no-color --creation-factor=1000 "$1..$(git commit-tree "$2^{tree}" -p "$1" -m x)" "$3..$(git commit-tree "$4^{tree}" -p "$3" -m x)"',
|
|
190140
190186
|
"--",
|
|
190141
|
-
oldBase,
|
|
190142
|
-
params.beforeSha,
|
|
190187
|
+
replayed ? newBase : oldBase,
|
|
190188
|
+
replayed ?? params.beforeSha,
|
|
190143
190189
|
newBase,
|
|
190144
190190
|
params.headSha
|
|
190145
190191
|
],
|
|
@@ -190174,6 +190220,22 @@ function versionBase(params) {
|
|
|
190174
190220
|
}
|
|
190175
190221
|
return best.sha;
|
|
190176
190222
|
}
|
|
190223
|
+
function replay(params) {
|
|
190224
|
+
try {
|
|
190225
|
+
return git([
|
|
190226
|
+
"merge-tree",
|
|
190227
|
+
"--write-tree",
|
|
190228
|
+
`--merge-base=${params.from}`,
|
|
190229
|
+
params.onto,
|
|
190230
|
+
params.sha
|
|
190231
|
+
]);
|
|
190232
|
+
} catch {
|
|
190233
|
+
log.info(
|
|
190234
|
+
`\xBB incremental diff: ${params.sha.slice(0, 7)} does not replay onto the new base; comparing each on its own`
|
|
190235
|
+
);
|
|
190236
|
+
return null;
|
|
190237
|
+
}
|
|
190238
|
+
}
|
|
190177
190239
|
function isDiffPrefix(ch) {
|
|
190178
190240
|
return ch === " " || ch === "+" || ch === "-";
|
|
190179
190241
|
}
|
|
@@ -196384,13 +196446,16 @@ function buildImplementPlanLink(ctx, issueNumber, commentId) {
|
|
|
196384
196446
|
const apiUrl = getApiUrl();
|
|
196385
196447
|
return `[Implement plan \u2794](${apiUrl}/trigger/${ctx.repo.owner}/${ctx.repo.name}/${issueNumber}?action=implement&comment_id=${commentId})`;
|
|
196386
196448
|
}
|
|
196387
|
-
function
|
|
196449
|
+
function runIssueNumber(ctx) {
|
|
196450
|
+
return ctx.payload.event.issue_number ?? primaryRepoState(ctx.toolState).issueNumber;
|
|
196451
|
+
}
|
|
196452
|
+
function buildEnrichmentLinks(ctx, issueNumber) {
|
|
196388
196453
|
const event = ctx.payload.event;
|
|
196389
|
-
|
|
196390
|
-
|
|
196391
|
-
|
|
196454
|
+
const mode = ctx.toolState.selectedMode;
|
|
196455
|
+
const enriching = mode === "Enrich" || event.trigger === "issues_opened" && !ctx.payload.prompt && mode !== "Build";
|
|
196456
|
+
if (issueNumber === void 0 || event.is_pr || !enriching) return [];
|
|
196392
196457
|
return [
|
|
196393
|
-
`[Implement a fix \u2794](${getApiUrl()}/trigger/${ctx.repo.owner}/${ctx.repo.name}/${
|
|
196458
|
+
`[Implement a fix \u2794](${getApiUrl()}/trigger/${ctx.repo.owner}/${ctx.repo.name}/${issueNumber}?action=build)`
|
|
196394
196459
|
];
|
|
196395
196460
|
}
|
|
196396
196461
|
function addFooter(ctx, body) {
|
|
@@ -196426,10 +196491,11 @@ function CreateCommentTool(ctx) {
|
|
|
196426
196491
|
});
|
|
196427
196492
|
ctx.toolState.wasUpdated = true;
|
|
196428
196493
|
log.info(`\xBB created comment ${result.data.id}`);
|
|
196429
|
-
|
|
196494
|
+
const ownTarget = issueNumber === runIssueNumber(ctx);
|
|
196495
|
+
if (ownTarget) {
|
|
196430
196496
|
ctx.toolState.standaloneCommentId = result.data.id;
|
|
196431
196497
|
}
|
|
196432
|
-
const enrichmentLinks =
|
|
196498
|
+
const enrichmentLinks = ownTarget ? buildEnrichmentLinks(ctx, issueNumber) : [];
|
|
196433
196499
|
if (commentType === "Plan" || enrichmentLinks.length > 0) {
|
|
196434
196500
|
if (commentType === "Plan" && result.data.node_id) {
|
|
196435
196501
|
await patchWorkflowRunFields(ctx, { planCommentNodeId: result.data.node_id });
|
|
@@ -196509,9 +196575,9 @@ async function reportProgress(ctx, params) {
|
|
|
196509
196575
|
if (params.liveProgress && !ctx.payload.progressComments) {
|
|
196510
196576
|
return { body, action: "skipped" };
|
|
196511
196577
|
}
|
|
196512
|
-
const issueNumber =
|
|
196578
|
+
const issueNumber = runIssueNumber(ctx);
|
|
196513
196579
|
const isPlanMode = ctx.toolState.selectedMode === "Plan";
|
|
196514
|
-
const enrichmentLinks = params.liveProgress ? [] : buildEnrichmentLinks(ctx);
|
|
196580
|
+
const enrichmentLinks = params.liveProgress ? [] : buildEnrichmentLinks(ctx, issueNumber);
|
|
196515
196581
|
const apiCtx = { octokit: ctx.octokit, owner: ctx.repo.owner, repo: ctx.repo.name };
|
|
196516
196582
|
if (target_plan_comment === true && ctx.toolState.existingPlanCommentId === void 0) {
|
|
196517
196583
|
log.warning("target_plan_comment requested but no existingPlanCommentId in tool state");
|
|
@@ -197429,11 +197495,19 @@ import { execFileSync as execFileSync6, execSync as execSync2 } from "node:child
|
|
|
197429
197495
|
import { mkdtempSync as mkdtempSync2, readdirSync, realpathSync as realpathSync2, rmSync as rmSync2, unlinkSync as unlinkSync2 } from "node:fs";
|
|
197430
197496
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
197431
197497
|
import { join as join15 } from "node:path";
|
|
197498
|
+
var TEMP_DIR_STATE = "temp_dir";
|
|
197432
197499
|
function createTempDirectory() {
|
|
197433
197500
|
const path4 = mkdtempSync2(join15(tmpdir2(), "pullfrog-"));
|
|
197434
197501
|
process.env.PULLFROG_TEMP_DIR = path4;
|
|
197435
197502
|
log.info(`\xBB created temp dir at ${path4}`);
|
|
197436
|
-
|
|
197503
|
+
const tracked = process.env.RUNNER_ENVIRONMENT !== "github-hosted";
|
|
197504
|
+
if (tracked) saveSecretState(TEMP_DIR_STATE, path4);
|
|
197505
|
+
return {
|
|
197506
|
+
path: path4,
|
|
197507
|
+
[Symbol.dispose]: () => {
|
|
197508
|
+
if (removeTempDirectory(path4) && tracked) saveSecretState(TEMP_DIR_STATE, "");
|
|
197509
|
+
}
|
|
197510
|
+
};
|
|
197437
197511
|
}
|
|
197438
197512
|
function removeTempDirectory(path4) {
|
|
197439
197513
|
try {
|
|
@@ -197444,10 +197518,12 @@ function removeTempDirectory(path4) {
|
|
|
197444
197518
|
rmSync2(path4, { recursive: true, force: true });
|
|
197445
197519
|
}
|
|
197446
197520
|
log.debug(`\xBB removed temp dir at ${path4}`);
|
|
197521
|
+
return true;
|
|
197447
197522
|
} catch (err) {
|
|
197448
197523
|
log.warning(
|
|
197449
197524
|
`\xBB could not remove temp dir at ${path4}: ${err instanceof Error ? err.message : String(err)}`
|
|
197450
197525
|
);
|
|
197526
|
+
return false;
|
|
197451
197527
|
}
|
|
197452
197528
|
}
|
|
197453
197529
|
function wipeRunnerLeakSurface() {
|
|
@@ -199522,7 +199598,7 @@ function GetIssueCommentsTool(ctx) {
|
|
|
199522
199598
|
description: "Get all comments for a GitHub issue. Returns all comments including the issue body and all subsequent discussion comments. Example: `get_issue_comments({ issue_number: 1234 })`.",
|
|
199523
199599
|
parameters: GetIssueComments,
|
|
199524
199600
|
execute: execute(async ({ issue_number }) => {
|
|
199525
|
-
primaryRepoState(ctx.toolState).issueNumber
|
|
199601
|
+
primaryRepoState(ctx.toolState).issueNumber ??= issue_number;
|
|
199526
199602
|
const comments = await ctx.octokit.paginate(ctx.octokit.rest.issues.listComments, {
|
|
199527
199603
|
owner: ctx.repo.owner,
|
|
199528
199604
|
repo: ctx.repo.name,
|
|
@@ -199560,7 +199636,7 @@ function GetIssueEventsTool(ctx) {
|
|
|
199560
199636
|
description: "Get timeline events for a GitHub issue that aren't reflected in the current state. Returns cross-references to other issues/PRs and commit references. Note: current labels, assignees, state, and milestone are already available via get_issue.",
|
|
199561
199637
|
parameters: GetIssueEvents,
|
|
199562
199638
|
execute: execute(async ({ issue_number }) => {
|
|
199563
|
-
primaryRepoState(ctx.toolState).issueNumber
|
|
199639
|
+
primaryRepoState(ctx.toolState).issueNumber ??= issue_number;
|
|
199564
199640
|
const events = await ctx.octokit.paginate(ctx.octokit.rest.issues.listEventsForTimeline, {
|
|
199565
199641
|
owner: ctx.repo.owner,
|
|
199566
199642
|
repo: ctx.repo.name,
|
|
@@ -199644,7 +199720,7 @@ function IssueInfoTool(ctx) {
|
|
|
199644
199720
|
tmpdir: ctx.tmpdir,
|
|
199645
199721
|
githubToken: ctx.githubInstallationToken
|
|
199646
199722
|
});
|
|
199647
|
-
primaryRepoState(ctx.toolState).issueNumber
|
|
199723
|
+
primaryRepoState(ctx.toolState).issueNumber ??= issue_number;
|
|
199648
199724
|
const hints = [];
|
|
199649
199725
|
if (data.comments > 0) {
|
|
199650
199726
|
hints.push("use get_issue_comments to retrieve all comments for this issue");
|
|
@@ -201112,8 +201188,11 @@ function SimilarIssuesTool(ctx) {
|
|
|
201112
201188
|
mutates: true,
|
|
201113
201189
|
parameters: SimilarIssues,
|
|
201114
201190
|
execute: execute(async (input2) => {
|
|
201115
|
-
|
|
201116
|
-
|
|
201191
|
+
const repoState = primaryRepoState(ctx.toolState);
|
|
201192
|
+
repoState.issueNumber ??= input2.issue_number;
|
|
201193
|
+
const subject = ctx.payload.event.issue_number ?? repoState.issueNumber;
|
|
201194
|
+
if (ctx.payload.event.is_pr || subject !== input2.issue_number) {
|
|
201195
|
+
throw new Error(`find_similar_issues is limited to this run's issue, #${subject}`);
|
|
201117
201196
|
}
|
|
201118
201197
|
const response = await apiFetch({
|
|
201119
201198
|
path: `/api/repo/${ctx.repo.owner}/${ctx.repo.name}/issues/${input2.issue_number}/similar`,
|
|
@@ -201395,7 +201474,7 @@ function buildCommonTools(ctx, outputSchema) {
|
|
|
201395
201474
|
if (hasSimilarIssues({ repoIntelligence: ctx.repoIntelligence, event: ctx.payload.event })) {
|
|
201396
201475
|
tools.push(SimilarIssuesTool(ctx));
|
|
201397
201476
|
}
|
|
201398
|
-
if (
|
|
201477
|
+
if (!ctx.payload.event.is_pr) {
|
|
201399
201478
|
tools.push(SearchIssuesTool(ctx));
|
|
201400
201479
|
}
|
|
201401
201480
|
const isStandalone = ctx.payload.event.trigger === "unknown";
|
|
@@ -201793,11 +201872,11 @@ function buildOpenAICompatibleSetupError(params) {
|
|
|
201793
201872
|
missing: params.missing,
|
|
201794
201873
|
where: `Set them on the OpenAI-compatible provider in [Pullfrog's provider settings](${getApiUrl()}/console/${params.owner}#billing), or in the workflow's \`env:\` block with the key as an [Actions secret](${secretsUrl(params)}):`,
|
|
201795
201874
|
env: [
|
|
201796
|
-
`${
|
|
201797
|
-
`${
|
|
201798
|
-
`${
|
|
201799
|
-
`${
|
|
201800
|
-
`${
|
|
201875
|
+
`${params.env.baseUrl}: https://your-endpoint.example.com/v1`,
|
|
201876
|
+
`${params.env.apiKey}: \${{ secrets.${params.env.apiKey} }}`,
|
|
201877
|
+
`${params.env.model}: <model-id>`,
|
|
201878
|
+
`${params.env.context}: "128000"`,
|
|
201879
|
+
`${params.env.maxOutput}: "16384"`
|
|
201801
201880
|
],
|
|
201802
201881
|
note: "Use the real context and output limits of the model your endpoint serves: Pullfrog can't discover them, and without them long runs grow until the endpoint refuses them.",
|
|
201803
201882
|
guide: "https://docs.pullfrog.com/openai-compatible"
|
|
@@ -201831,17 +201910,16 @@ function hasPositiveNumberEnvVar(name) {
|
|
|
201831
201910
|
return Number(process.env[name]) > 0;
|
|
201832
201911
|
}
|
|
201833
201912
|
function validateOpenAICompatibleSetup(params) {
|
|
201913
|
+
const env2 = openAICompatibleEnv(params.set);
|
|
201834
201914
|
const missing = [];
|
|
201835
|
-
if (!hasEnvVar2(
|
|
201836
|
-
if (!hasEnvVar2(
|
|
201837
|
-
if (!hasEnvVar2(
|
|
201838
|
-
if (!hasPositiveNumberEnvVar(
|
|
201839
|
-
|
|
201840
|
-
if (!hasPositiveNumberEnvVar(OPENAI_COMPATIBLE_MAX_OUTPUT_ENV))
|
|
201841
|
-
missing.push(OPENAI_COMPATIBLE_MAX_OUTPUT_ENV);
|
|
201915
|
+
if (!hasEnvVar2(env2.baseUrl)) missing.push(env2.baseUrl);
|
|
201916
|
+
if (!hasEnvVar2(env2.apiKey)) missing.push(env2.apiKey);
|
|
201917
|
+
if (!hasEnvVar2(env2.model)) missing.push(env2.model);
|
|
201918
|
+
if (!hasPositiveNumberEnvVar(env2.context)) missing.push(env2.context);
|
|
201919
|
+
if (!hasPositiveNumberEnvVar(env2.maxOutput)) missing.push(env2.maxOutput);
|
|
201842
201920
|
if (missing.length > 0) {
|
|
201843
201921
|
throw new Error(
|
|
201844
|
-
buildOpenAICompatibleSetupError({ owner: params.owner, name: params.name, missing })
|
|
201922
|
+
buildOpenAICompatibleSetupError({ owner: params.owner, name: params.name, missing, env: env2 })
|
|
201845
201923
|
);
|
|
201846
201924
|
}
|
|
201847
201925
|
}
|
|
@@ -201897,7 +201975,11 @@ function validateAgentApiKey(params) {
|
|
|
201897
201975
|
return;
|
|
201898
201976
|
}
|
|
201899
201977
|
if (params.model.startsWith(`${OPENAI_COMPATIBLE_PROVIDER}/`)) {
|
|
201900
|
-
validateOpenAICompatibleSetup({
|
|
201978
|
+
validateOpenAICompatibleSetup({
|
|
201979
|
+
owner: params.owner,
|
|
201980
|
+
name: params.name,
|
|
201981
|
+
set: params.openAICompatibleSet
|
|
201982
|
+
});
|
|
201901
201983
|
return;
|
|
201902
201984
|
}
|
|
201903
201985
|
if (params.model.startsWith(`${AZURE_PROVIDER}/`)) {
|
|
@@ -202211,17 +202293,37 @@ function resolveSlug(slug2) {
|
|
|
202211
202293
|
}
|
|
202212
202294
|
return `${AZURE_PROVIDER}/${deployment}`;
|
|
202213
202295
|
}
|
|
202214
|
-
|
|
202215
|
-
|
|
202296
|
+
const set2 = heldOpenAICompatibleSet(slug2);
|
|
202297
|
+
if (alias?.routing === "openai-compatible" || set2) {
|
|
202298
|
+
const modelEnv = openAICompatibleEnv(set2).model;
|
|
202299
|
+
const modelId = process.env[modelEnv]?.trim();
|
|
202216
202300
|
if (!modelId) {
|
|
202217
202301
|
throw new Error(
|
|
202218
|
-
`\`${
|
|
202302
|
+
`\`${modelEnv}\` ${BYOK_SLUG_MARKER} \`${slug2}\`. Set it to the model ID your endpoint serves, on the OpenAI-compatible provider in Pullfrog or in the workflow's \`env:\` block. [OpenAI-compatible setup guide](https://docs.pullfrog.com/openai-compatible)`
|
|
202219
202303
|
);
|
|
202220
202304
|
}
|
|
202221
202305
|
return `${OPENAI_COMPATIBLE_PROVIDER}/${modelId}`;
|
|
202222
202306
|
}
|
|
202223
202307
|
return resolveCliModel(slug2);
|
|
202224
202308
|
}
|
|
202309
|
+
function heldOpenAICompatibleSet(slug2) {
|
|
202310
|
+
const set2 = openAICompatibleSetName(slug2);
|
|
202311
|
+
return set2 && Object.values(openAICompatibleEnv(set2)).some(hasEnvVar3) ? set2 : void 0;
|
|
202312
|
+
}
|
|
202313
|
+
function activateOpenAICompatibleSet(ctx) {
|
|
202314
|
+
const slug2 = process.env.PULLFROG_MODEL?.trim() || ctx.slug?.trim();
|
|
202315
|
+
const set2 = slug2 ? heldOpenAICompatibleSet(slug2) : void 0;
|
|
202316
|
+
if (!set2) return void 0;
|
|
202317
|
+
const from = openAICompatibleEnv(set2);
|
|
202318
|
+
const to = openAICompatibleEnv();
|
|
202319
|
+
for (const field of OPENAI_COMPATIBLE_FIELDS) {
|
|
202320
|
+
const value2 = process.env[from[field]];
|
|
202321
|
+
if (value2 === void 0) delete process.env[to[field]];
|
|
202322
|
+
else process.env[to[field]] = value2;
|
|
202323
|
+
}
|
|
202324
|
+
log.info(`\xBB using the OpenAI-compatible endpoint "${set2}"`);
|
|
202325
|
+
return set2;
|
|
202326
|
+
}
|
|
202225
202327
|
function resolveModel(ctx) {
|
|
202226
202328
|
const envModel = process.env.PULLFROG_MODEL?.trim();
|
|
202227
202329
|
if (envModel) {
|
|
@@ -203264,7 +203366,7 @@ Rules:
|
|
|
203264
203366
|
### GitHub
|
|
203265
203367
|
|
|
203266
203368
|
Use MCP tools from ${pullfrogMcpName} for all GitHub operations. Never use the \`gh\` CLI \u2014 it is not authenticated and will fail. The MCP tools handle authentication and enforce permissions.
|
|
203267
|
-
${hasSimilarIssues({ repoIntelligence: ctx.repoIntelligence, event: ctx.payload.event }) ? `
|
|
203369
|
+
${ctx.payload.event.issue_number !== void 0 && hasSimilarIssues({ repoIntelligence: ctx.repoIntelligence, event: ctx.payload.event }) ? `
|
|
203268
203370
|
#### Duplicate detection (enabled for this repository)
|
|
203269
203371
|
|
|
203270
203372
|
Call \`${t("find_similar_issues")}\` for #${ctx.payload.event.issue_number} before planning. If it duplicates an existing issue, link that instead of producing a plan; never close or label on similarity alone.
|
|
@@ -205143,6 +205245,9 @@ function resolveModelForLog(ctx) {
|
|
|
205143
205245
|
function resolveEffortForLog(ctx) {
|
|
205144
205246
|
const effort = resolveRunEffort(ctx);
|
|
205145
205247
|
if (!ctx.resolvedModel && !ctx.payload.proxyModel) return "pending \u2014 model not chosen yet";
|
|
205248
|
+
if (effort.declarable && ctx.agentName === "opencode") {
|
|
205249
|
+
return "pending \u2014 reading the variants opencode declares";
|
|
205250
|
+
}
|
|
205146
205251
|
if (!effort.alias) return "not applied \u2014 model not recognized";
|
|
205147
205252
|
if (!effort.rung) return "n/a (model has no effort control)";
|
|
205148
205253
|
return effort.configured ? effort.rung : `${effort.rung} (default)`;
|
|
@@ -205161,9 +205266,7 @@ function logRunStartup(ctx) {
|
|
|
205161
205266
|
log.info(
|
|
205162
205267
|
`\xBB model: ${resolveModelForLog({ payload: ctx.payload, resolvedModel: ctx.resolvedModel })}`
|
|
205163
205268
|
);
|
|
205164
|
-
log.info(
|
|
205165
|
-
`\xBB effort: ${resolveEffortForLog({ payload: ctx.payload, resolvedModel: ctx.resolvedModel })}`
|
|
205166
|
-
);
|
|
205269
|
+
log.info(`\xBB effort: ${resolveEffortForLog(ctx)}`);
|
|
205167
205270
|
const routing = ctx.payload.routing;
|
|
205168
205271
|
if (routing) {
|
|
205169
205272
|
log.info(
|
|
@@ -205434,6 +205537,7 @@ async function main() {
|
|
|
205434
205537
|
const count = Object.keys(runContext.dbSecrets).length;
|
|
205435
205538
|
if (count > 0) log.info(`\xBB ${count} db secret(s) loaded`);
|
|
205436
205539
|
}
|
|
205540
|
+
const openAICompatibleSet = activateOpenAICompatibleSet({ slug: payload.model });
|
|
205437
205541
|
await initializeCredentialPool({ ctx: runContext, slug: payload.model, injected });
|
|
205438
205542
|
installCodexAuth();
|
|
205439
205543
|
installXaiAuth();
|
|
@@ -205582,7 +205686,8 @@ async function main() {
|
|
|
205582
205686
|
owner: runContext.repo.owner,
|
|
205583
205687
|
name: runContext.repo.name,
|
|
205584
205688
|
secretsUnavailable: runContext.secretsUnavailable,
|
|
205585
|
-
routerUnfunded: runContext.routerUnfunded
|
|
205689
|
+
routerUnfunded: runContext.routerUnfunded,
|
|
205690
|
+
openAICompatibleSet
|
|
205586
205691
|
});
|
|
205587
205692
|
} catch (missingKey) {
|
|
205588
205693
|
const funded = runContext.trialFallback && missingKey instanceof NoUsableCredentialError ? await resolveTrialFallback({
|
package/dist/internal/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export type { ConfigField, ConfigScope, ConfigValue } from "../configuration.ts"
|
|
|
7
7
|
export { configEntrySchema, configFields, configResponseSchema, configValueSchema, } from "../configuration.ts";
|
|
8
8
|
export type { AuthorPermission, AutoTier, EffortPosition, ModelAlias, ModelProvider, Payload, PayloadEvent, PayloadRouting, ProviderConfig, PushPermission, RouterSource, RouterTier, ShellPermission, ToolPermission, WriteablePayload, XrepoConfig, } from "../external.ts";
|
|
9
9
|
export { AUTO_EFFICIENT, AUTO_INTELLIGENT, AUTO_ROUTER, autoLadder, autoRoutedSlug, DEFAULT_EFFORT_POSITION, DEFAULT_PROXY_MODEL, defaultAutoTier, EFFORT_ALIASES, getAutoSelectHintModel, getModelEffortLevels, getModelEnvVars, getModelManagedCredentials, getModelProvider, getProviderDisplayName, isAutoRouted, isAutoSlug, isAutoTier, isCardGatedModel, isEffortPosition, isOssAllowedModel, isRouterTier, ladderRungs, modelAliases, modelHasStoredAuth, modelIdLabel, OSS_MODEL_ALLOWLIST, OSS_RECOMMENDED_MODEL, offeredRungs, ossFundedModelNames, PROVIDER_GATEWAY_URL_ENV, parseEffortPosition, parseModel, providers, pullfrogMcpName, ROUTED_PROVIDERS, ROUTER_LADDER, ROUTER_TIERS, resolveAutoTier, resolveCliModel, resolveDisplayAlias, resolveModelRung, resolveModelSlug, resolveOpenRouterModel, resolvePickModel, resolveRoutedModel, resolveRung, routerProxyOptOut, rungLabel, rungPosition, SUBSIDY_RUNG, TRIAL_FUNDED_USD_LIMIT, } from "../external.ts";
|
|
10
|
+
export { isOpenAICompatibleSetName, openAICompatibleEnv, openAICompatibleSetAlias, openAICompatibleSetName, openAICompatibleSetOf, openAICompatibleSets, } from "../models.ts";
|
|
10
11
|
export type { Mode } from "../modes.ts";
|
|
11
12
|
export { modes } from "../modes.ts";
|
|
12
13
|
export { type CommercialRefusal, commercialPaywallBody } from "../utils/billingErrors.ts";
|
package/dist/internal.js
CHANGED
|
@@ -8,7 +8,7 @@ var __export = (target, all) => {
|
|
|
8
8
|
// package.json
|
|
9
9
|
var package_default = {
|
|
10
10
|
name: "pullfrog",
|
|
11
|
-
version: "0.1.
|
|
11
|
+
version: "0.1.106",
|
|
12
12
|
cliContractVersion: "1",
|
|
13
13
|
type: "module",
|
|
14
14
|
bin: {
|
|
@@ -20079,7 +20079,7 @@ var repoConfigFields = [
|
|
|
20079
20079
|
key: "address-reviews.enabled",
|
|
20080
20080
|
field: "codingAddressReviews",
|
|
20081
20081
|
kind: "toggle",
|
|
20082
|
-
description: "address
|
|
20082
|
+
description: "address reviews on Pullfrog-authored PRs"
|
|
20083
20083
|
},
|
|
20084
20084
|
{
|
|
20085
20085
|
key: "fix-ci.own-prs",
|
|
@@ -21651,7 +21651,10 @@ function modelHasStoredAuth(params) {
|
|
|
21651
21651
|
const authVars = [
|
|
21652
21652
|
...getModelEnvVars(slug),
|
|
21653
21653
|
...getModelManagedCredentials(slug),
|
|
21654
|
-
...HARNESS_ONLY_CREDENTIALS[getModelProvider(slug)] ?? []
|
|
21654
|
+
...HARNESS_ONLY_CREDENTIALS[getModelProvider(slug)] ?? [],
|
|
21655
|
+
// the default endpoint's vars above still count: a runner holding no such set runs the
|
|
21656
|
+
// slug as a raw model id on it
|
|
21657
|
+
...openAICompatibleSetEnvVars(slug)
|
|
21655
21658
|
];
|
|
21656
21659
|
return authVars.some((v) => params.secretNames.includes(v));
|
|
21657
21660
|
}
|
|
@@ -21877,6 +21880,46 @@ function isOssAllowedModel(slug) {
|
|
|
21877
21880
|
function getAutoSelectHintModel() {
|
|
21878
21881
|
return defaultProxyDisplayName;
|
|
21879
21882
|
}
|
|
21883
|
+
var OPENAI_COMPATIBLE_PROVIDER = "openai-compatible";
|
|
21884
|
+
function isOpenAICompatibleSetName(name) {
|
|
21885
|
+
return name !== "byok" && name.length <= 32 && /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name);
|
|
21886
|
+
}
|
|
21887
|
+
function openAICompatibleSetName(slug) {
|
|
21888
|
+
const prefix = `${OPENAI_COMPATIBLE_PROVIDER}/`;
|
|
21889
|
+
if (!slug.startsWith(prefix)) return void 0;
|
|
21890
|
+
const name = slug.slice(prefix.length);
|
|
21891
|
+
return isOpenAICompatibleSetName(name) ? name : void 0;
|
|
21892
|
+
}
|
|
21893
|
+
function openAICompatibleEnv(name) {
|
|
21894
|
+
const prefix = `OPENAI_COMPATIBLE_${name ? `${name.toUpperCase().replaceAll("-", "_")}_` : ""}`;
|
|
21895
|
+
return {
|
|
21896
|
+
baseUrl: `${prefix}BASE_URL`,
|
|
21897
|
+
apiKey: `${prefix}API_KEY`,
|
|
21898
|
+
model: `${prefix}MODEL`,
|
|
21899
|
+
context: `${prefix}CONTEXT`,
|
|
21900
|
+
maxOutput: `${prefix}MAX_OUTPUT`
|
|
21901
|
+
};
|
|
21902
|
+
}
|
|
21903
|
+
function openAICompatibleSetEnvVars(slug) {
|
|
21904
|
+
const set2 = openAICompatibleSetName(slug);
|
|
21905
|
+
if (!set2) return [];
|
|
21906
|
+
const env = openAICompatibleEnv(set2);
|
|
21907
|
+
return [env.baseUrl, env.apiKey, env.model];
|
|
21908
|
+
}
|
|
21909
|
+
function openAICompatibleSetOf(envName) {
|
|
21910
|
+
const match = /^OPENAI_COMPATIBLE_([A-Z0-9]+(?:_[A-Z0-9]+)*)_(?:BASE_URL|API_KEY|MODEL|CONTEXT|MAX_OUTPUT)$/.exec(
|
|
21911
|
+
envName
|
|
21912
|
+
);
|
|
21913
|
+
const name = match?.[1]?.toLowerCase().replaceAll("_", "-");
|
|
21914
|
+
return name && isOpenAICompatibleSetName(name) ? name : void 0;
|
|
21915
|
+
}
|
|
21916
|
+
function openAICompatibleSets(names) {
|
|
21917
|
+
return [...new Set(names.flatMap((name) => openAICompatibleSetOf(name) ?? []))].sort();
|
|
21918
|
+
}
|
|
21919
|
+
function openAICompatibleSetAlias(set2) {
|
|
21920
|
+
const byok = resolveDisplayAlias(`${OPENAI_COMPATIBLE_PROVIDER}/byok`);
|
|
21921
|
+
return byok && { ...byok, slug: `${OPENAI_COMPATIBLE_PROVIDER}/${set2}`, displayName: set2 };
|
|
21922
|
+
}
|
|
21880
21923
|
var PROVIDER_GATEWAY_URL_ENV = {
|
|
21881
21924
|
anthropic: "ANTHROPIC_BASE_URL",
|
|
21882
21925
|
openai: "OPENAI_BASE_URL"
|
|
@@ -23534,6 +23577,7 @@ export {
|
|
|
23534
23577
|
isEffortPosition,
|
|
23535
23578
|
isLeapingIntoActionCommentBody,
|
|
23536
23579
|
isLiveChecklistCommentBody,
|
|
23580
|
+
isOpenAICompatibleSetName,
|
|
23537
23581
|
isOssAllowedModel,
|
|
23538
23582
|
isPullfrog,
|
|
23539
23583
|
isRouterTier,
|
|
@@ -23544,6 +23588,11 @@ export {
|
|
|
23544
23588
|
modelIdLabel,
|
|
23545
23589
|
modes,
|
|
23546
23590
|
offeredRungs,
|
|
23591
|
+
openAICompatibleEnv,
|
|
23592
|
+
openAICompatibleSetAlias,
|
|
23593
|
+
openAICompatibleSetName,
|
|
23594
|
+
openAICompatibleSetOf,
|
|
23595
|
+
openAICompatibleSets,
|
|
23547
23596
|
ossFundedModelNames,
|
|
23548
23597
|
parseCodexAuthBody,
|
|
23549
23598
|
parseEffortPosition,
|
package/dist/models.d.ts
CHANGED
|
@@ -464,6 +464,27 @@ export declare const OPENAI_COMPATIBLE_CONTEXT_ENV = "OPENAI_COMPATIBLE_CONTEXT"
|
|
|
464
464
|
* `context` + `output` together, so the pair is validated and emitted as a unit.
|
|
465
465
|
*/
|
|
466
466
|
export declare const OPENAI_COMPATIBLE_MAX_OUTPUT_ENV = "OPENAI_COMPATIBLE_MAX_OUTPUT";
|
|
467
|
+
/**
|
|
468
|
+
* a NAMED OpenAI-compatible endpoint: the slug `openai-compatible/<name>` runs on the five
|
|
469
|
+
* `OPENAI_COMPATIBLE_<NAME>_*` values, so one account holds several endpoints and each repo,
|
|
470
|
+
* trigger or `--model=` picks one. `byok` stays the unnamed default on the bare names. 32 is
|
|
471
|
+
* what keeps `OPENAI_COMPATIBLE_<NAME>_MAX_OUTPUT` under the 64-character secret-name cap.
|
|
472
|
+
*/
|
|
473
|
+
export declare function isOpenAICompatibleSetName(name: string): boolean;
|
|
474
|
+
/**
|
|
475
|
+
* the set a slug names, by shape alone. `openai-compatible/<x>` is also a raw specifier (model
|
|
476
|
+
* `x` on the default endpoint), so a runner treats it as a set only when it holds that set's values.
|
|
477
|
+
*/
|
|
478
|
+
export declare function openAICompatibleSetName(slug: string): string | undefined;
|
|
479
|
+
export declare const OPENAI_COMPATIBLE_FIELDS: readonly ["baseUrl", "apiKey", "model", "context", "maxOutput"];
|
|
480
|
+
/** the env var names one endpoint is configured by: a named set's, or the default's. */
|
|
481
|
+
export declare function openAICompatibleEnv(name?: string): Record<(typeof OPENAI_COMPATIBLE_FIELDS)[number], string>;
|
|
482
|
+
/** the set a variable belongs to: `OPENAI_COMPATIBLE_VLLM_A_API_KEY` → `vllm-a`. */
|
|
483
|
+
export declare function openAICompatibleSetOf(envName: string): string | undefined;
|
|
484
|
+
/** the named endpoints `names` (stored secret or env var names) hold any value of. */
|
|
485
|
+
export declare function openAICompatibleSets(names: string[]): string[];
|
|
486
|
+
/** a named endpoint as a picker entry: the default endpoint's routing alias under its own slug. */
|
|
487
|
+
export declare function openAICompatibleSetAlias(set: string): ModelAlias | undefined;
|
|
467
488
|
/**
|
|
468
489
|
* Providers whose endpoint can be re-pointed at a customer gateway, and the env
|
|
469
490
|
* var that does it. Deliberately a short explicit map rather than a derived
|
package/dist/utils/agent.d.ts
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import type { Agent } from "../agents/index.ts";
|
|
2
|
+
/**
|
|
3
|
+
* make the run's named set (`openai-compatible/<name>`) its endpoint: the set's five values
|
|
4
|
+
* replace the bare `OPENAI_COMPATIBLE_*` that validation and the opencode provider read. a value
|
|
5
|
+
* the set lacks is cleared, never inherited, so the default endpoint's key cannot reach the set's
|
|
6
|
+
* URL. returns the set, so setup errors can name its own variables.
|
|
7
|
+
*/
|
|
8
|
+
export declare function activateOpenAICompatibleSet(ctx: {
|
|
9
|
+
slug: string | undefined;
|
|
10
|
+
}): string | undefined;
|
|
2
11
|
/**
|
|
3
12
|
* resolve the effective model for this run.
|
|
4
13
|
*
|
package/dist/utils/apiKeys.d.ts
CHANGED
|
@@ -121,6 +121,8 @@ export declare function validateAgentApiKey(params: {
|
|
|
121
121
|
* says nothing about what the user actually configured. */
|
|
122
122
|
secretsUnavailable?: boolean | undefined;
|
|
123
123
|
routerUnfunded?: boolean | undefined;
|
|
124
|
+
/** the named OpenAI-compatible set the run is on, from `activateOpenAICompatibleSet`. */
|
|
125
|
+
openAICompatibleSet?: string | undefined;
|
|
124
126
|
}): void;
|
|
125
127
|
/**
|
|
126
128
|
* Detect agent-runtime auth failures that should be reformatted as an actionable
|
|
@@ -20,6 +20,11 @@ export interface RunEffort {
|
|
|
20
20
|
rung: string | undefined;
|
|
21
21
|
/** the catalog alias the ladder came from, if we recognized one. */
|
|
22
22
|
alias: ModelAlias | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* true when the catalog has no ladder for a configured effort and the variants
|
|
25
|
+
* the opencode server declares for the model may stand in (`declaredVariants`).
|
|
26
|
+
*/
|
|
27
|
+
declarable: boolean;
|
|
23
28
|
}
|
|
24
29
|
/**
|
|
25
30
|
* the position a subsidised run is pinned to — the `high` rung on the ladder of
|
|
@@ -39,4 +44,9 @@ export declare function ossEffortFloor(ctx: {
|
|
|
39
44
|
export declare function resolveRunEffort(ctx: {
|
|
40
45
|
payload: ResolvedPayload;
|
|
41
46
|
resolvedModel?: string | undefined;
|
|
47
|
+
/**
|
|
48
|
+
* the variant names the opencode server lists for the running model, in its
|
|
49
|
+
* order. only consulted when the catalog has no alias for the model.
|
|
50
|
+
*/
|
|
51
|
+
declaredVariants?: readonly string[] | undefined;
|
|
42
52
|
}): RunEffort;
|
package/dist/utils/setup.d.ts
CHANGED
|
@@ -14,6 +14,8 @@ export declare function createTempDirectory(): {
|
|
|
14
14
|
path: string;
|
|
15
15
|
[Symbol.dispose]: () => void;
|
|
16
16
|
};
|
|
17
|
+
/** the `post:` hook's half of `createTempDirectory`: removes the directory a cancelled run left. */
|
|
18
|
+
export declare function removeAbandonedTempDirectory(): void;
|
|
17
19
|
/**
|
|
18
20
|
* snapshot-and-delete the GHA runner's known credential leak surfaces inside
|
|
19
21
|
* `$RUNNER_TEMP` before the agent spawns. without this, a shell-capable agent
|