Fix undefined bug

This commit is contained in:
Colin McDonnell
2026-01-19 17:44:12 +00:00
committed by pullfrog[bot]
parent e1b017f6e2
commit f65cb4d2e3
6 changed files with 35 additions and 55 deletions
+13 -17
View File
@@ -137869,18 +137869,14 @@ function resolveAgent(params) {
log.debug( log.debug(
`\xBB determineAgent: agentOverride=${agentOverride}, payload.agent=${params.payload.agent}, repoSettings.defaultAgent=${params.repoSettings.defaultAgent}` `\xBB determineAgent: agentOverride=${agentOverride}, payload.agent=${params.payload.agent}, repoSettings.defaultAgent=${params.repoSettings.defaultAgent}`
); );
const configuredAgentName = agentOverride || params.payload.agent || params.repoSettings.defaultAgent || null; const configuredAgentName = agentOverride || params.payload.agent || params.repoSettings.defaultAgent || void 0;
if (configuredAgentName) { if (configuredAgentName) {
const agent3 = agents[configuredAgentName]; const agent3 = agents[configuredAgentName];
if (!agent3) { if (!agent3) {
throw new Error(`invalid agent name: ${configuredAgentName}`); throw new Error(`invalid agent name: ${configuredAgentName}`);
} }
const isExplicitOverride = agentOverride !== void 0 || params.payload.agent !== null; const isExplicitOverride = agentOverride !== void 0 || params.payload.agent !== void 0;
if (isExplicitOverride) { if (isExplicitOverride || agentHasApiKeys(agent3)) {
log.info(`\xBB selected configured agent: ${agent3.name}`);
return agent3;
}
if (agentHasApiKeys(agent3)) {
log.info(`\xBB selected configured agent: ${agent3.name}`); log.info(`\xBB selected configured agent: ${agent3.name}`);
return agent3; return agent3;
} }
@@ -138183,11 +138179,11 @@ var ToolPermissionInput = type.enumerated("disabled", "enabled");
var BashPermissionInput = type.enumerated("disabled", "restricted", "enabled"); var BashPermissionInput = type.enumerated("disabled", "restricted", "enabled");
var JsonPayload = type({ var JsonPayload = type({
"~pullfrog": "true", "~pullfrog": "true",
"agent?": AgentName.or("null"), "agent?": AgentName.or("undefined"),
"prompt?": "string", "prompt?": "string",
"repoInstructions?": "string", "repoInstructions?": "string",
"event?": "object", "event?": "object",
"effort?": Effort "effort?": Effort.or("undefined")
}); });
var COLLABORATOR_PERMISSIONS = ["admin", "maintain", "write"]; var COLLABORATOR_PERMISSIONS = ["admin", "maintain", "write"];
function isCollaborator(event) { function isCollaborator(event) {
@@ -138196,13 +138192,13 @@ function isCollaborator(event) {
} }
var Inputs = type({ var Inputs = type({
prompt: "string", prompt: "string",
"effort?": Effort, "effort?": Effort.or("undefined"),
"agent?": AgentName.or("null"), "agent?": AgentName.or("undefined"),
"web?": ToolPermissionInput.or("undefined"), "web?": ToolPermissionInput.or("undefined"),
"search?": ToolPermissionInput.or("undefined"), "search?": ToolPermissionInput.or("undefined"),
"write?": ToolPermissionInput.or("undefined"), "write?": ToolPermissionInput.or("undefined"),
"bash?": BashPermissionInput.or("undefined"), "bash?": BashPermissionInput.or("undefined"),
"cwd?": "string|null" "cwd?": type.string.or("undefined")
}); });
function isAgentName(value2) { function isAgentName(value2) {
return typeof value2 === "string" && AgentName(value2) instanceof type.errors === false; return typeof value2 === "string" && AgentName(value2) instanceof type.errors === false;
@@ -138212,7 +138208,7 @@ function isPayloadEvent(value2) {
} }
function resolveCwd(cwd2) { function resolveCwd(cwd2) {
const workspace = process.env.GITHUB_WORKSPACE; const workspace = process.env.GITHUB_WORKSPACE;
if (!cwd2) return workspace ?? null; if (!cwd2) return workspace;
if (isAbsolute(cwd2)) return cwd2; if (isAbsolute(cwd2)) return cwd2;
return workspace ? resolve(workspace, cwd2) : cwd2; return workspace ? resolve(workspace, cwd2) : cwd2;
} }
@@ -138220,14 +138216,14 @@ function resolvePayload(repoSettings) {
const inputs = Inputs.assert({ const inputs = Inputs.assert({
prompt: core4.getInput("prompt", { required: true }), prompt: core4.getInput("prompt", { required: true }),
effort: core4.getInput("effort") || void 0, effort: core4.getInput("effort") || void 0,
agent: core4.getInput("agent") || null, agent: core4.getInput("agent") || void 0,
cwd: core4.getInput("cwd") || null, cwd: core4.getInput("cwd") || void 0,
web: core4.getInput("web") || void 0, web: core4.getInput("web") || void 0,
search: core4.getInput("search") || void 0, search: core4.getInput("search") || void 0,
write: core4.getInput("write") || void 0, write: core4.getInput("write") || void 0,
bash: core4.getInput("bash") || void 0 bash: core4.getInput("bash") || void 0
}); });
const agent2 = inputs.agent !== void 0 && inputs.agent !== "null" && isAgentName(inputs.agent) ? inputs.agent : null; const agent2 = inputs.agent !== void 0 && isAgentName(inputs.agent) ? inputs.agent : void 0;
let jsonPayload = null; let jsonPayload = null;
try { try {
const parsed2 = JSON.parse(inputs.prompt); const parsed2 = JSON.parse(inputs.prompt);
@@ -138242,7 +138238,7 @@ function resolvePayload(repoSettings) {
const rawEvent = jsonPayload?.event; const rawEvent = jsonPayload?.event;
const event = isPayloadEvent(rawEvent) ? rawEvent : { trigger: "unknown" }; const event = isPayloadEvent(rawEvent) ? rawEvent : { trigger: "unknown" };
const jsonAgent = jsonPayload?.agent; const jsonAgent = jsonPayload?.agent;
const resolvedAgent = agent2 ?? (jsonAgent !== void 0 && jsonAgent !== "null" && isAgentName(jsonAgent) ? jsonAgent : null); const resolvedAgent = agent2 ?? (jsonAgent !== void 0 && isAgentName(jsonAgent) ? jsonAgent : void 0);
const shouldRestrict = !isCollaborator(event); const shouldRestrict = !isCollaborator(event);
return { return {
"~pullfrog": true, "~pullfrog": true,
+2 -2
View File
@@ -245,7 +245,7 @@ export type PayloadEvent =
export interface WriteablePayload { export interface WriteablePayload {
"~pullfrog": true; "~pullfrog": true;
/** agent slug identifier (e.g., "claude", "codex", "gemini") */ /** agent slug identifier (e.g., "claude", "codex", "gemini") */
agent: AgentName | null; agent?: AgentName | undefined;
/** the prompt/instructions for the agent to execute (body if @pullfrog tagged + per-trigger instructions) */ /** the prompt/instructions for the agent to execute (body if @pullfrog tagged + per-trigger instructions) */
prompt: string; prompt: string;
/** repo-level instructions (macro-expanded server-side) */ /** repo-level instructions (macro-expanded server-side) */
@@ -255,7 +255,7 @@ export interface WriteablePayload {
/** effort level for model selection (mini, auto, max) - defaults to "auto" */ /** effort level for model selection (mini, auto, max) - defaults to "auto" */
effort?: Effort | undefined; effort?: Effort | undefined;
/** working directory for the agent */ /** working directory for the agent */
cwd?: string | null | undefined; cwd?: string | undefined;
} }
// immutable payload type for agent execution // immutable payload type for agent execution
-1
View File
@@ -14,7 +14,6 @@ import type { Payload } from "../../external.ts";
*/ */
export default { export default {
"~pullfrog": true, "~pullfrog": true,
agent: null,
prompt: `Create a file called test-runner.js with the following content: prompt: `Create a file called test-runner.js with the following content:
\`\`\`javascript \`\`\`javascript
-1
View File
@@ -2,7 +2,6 @@ import type { Payload } from "../../external.ts";
export default { export default {
"~pullfrog": true, "~pullfrog": true,
agent: null,
prompt: prompt:
"List all files in the current directory, then create a file called dynamic-test.txt with the content 'This was loaded from a TypeScript file!', then delete it.", "List all files in the current directory, then create a file called dynamic-test.txt with the content 'This was loaded from a TypeScript file!', then delete it.",
event: { event: {
+4 -9
View File
@@ -28,7 +28,7 @@ export function resolveAgent(params: {
`» determineAgent: agentOverride=${agentOverride}, payload.agent=${params.payload.agent}, repoSettings.defaultAgent=${params.repoSettings.defaultAgent}` `» determineAgent: agentOverride=${agentOverride}, payload.agent=${params.payload.agent}, repoSettings.defaultAgent=${params.repoSettings.defaultAgent}`
); );
const configuredAgentName = const configuredAgentName =
agentOverride || params.payload.agent || params.repoSettings.defaultAgent || null; agentOverride || params.payload.agent || params.repoSettings.defaultAgent || undefined;
if (configuredAgentName) { if (configuredAgentName) {
const agent = agents[configuredAgentName]; const agent = agents[configuredAgentName];
@@ -38,14 +38,9 @@ export function resolveAgent(params: {
// if explicitly configured (via override or payload), respect it even without matching keys // if explicitly configured (via override or payload), respect it even without matching keys
// this allows users to force an agent selection (will fail later with clear error if no keys) // this allows users to force an agent selection (will fail later with clear error if no keys)
const isExplicitOverride = agentOverride !== undefined || params.payload.agent !== null; // for repo-level defaults, only select if agent has matching API keys
if (isExplicitOverride) { const isExplicitOverride = agentOverride !== undefined || params.payload.agent !== undefined;
log.info(`» selected configured agent: ${agent.name}`); if (isExplicitOverride || agentHasApiKeys(agent)) {
return agent;
}
// for repo-level defaults, check if agent has matching keys before selecting
if (agentHasApiKeys(agent)) {
log.info(`» selected configured agent: ${agent.name}`); log.info(`» selected configured agent: ${agent.name}`);
return agent; return agent;
} }
+16 -25
View File
@@ -1,13 +1,7 @@
import { isAbsolute, resolve } from "node:path"; import { isAbsolute, resolve } from "node:path";
import * as core from "@actions/core"; import * as core from "@actions/core";
import { type } from "arktype"; import { type } from "arktype";
import { import { AgentName, type AuthorPermission, Effort, type PayloadEvent } from "../external.ts";
AgentName,
type AgentName as AgentNameType,
type AuthorPermission,
Effort,
type PayloadEvent,
} from "../external.ts";
import type { RepoSettings } from "./repoSettings.ts"; import type { RepoSettings } from "./repoSettings.ts";
// tool permission enum types for inputs // tool permission enum types for inputs
@@ -19,11 +13,11 @@ const BashPermissionInput = type.enumerated("disabled", "restricted", "enabled")
// permissions are derived from event.authorPermission instead // permissions are derived from event.authorPermission instead
const JsonPayload = type({ const JsonPayload = type({
"~pullfrog": "true", "~pullfrog": "true",
"agent?": AgentName.or("null"), "agent?": AgentName.or("undefined"),
"prompt?": "string", "prompt?": "string",
"repoInstructions?": "string", "repoInstructions?": "string",
"event?": "object", "event?": "object",
"effort?": Effort, "effort?": Effort.or("undefined"),
}); });
// permission levels that indicate collaborator status (have push access) // permission levels that indicate collaborator status (have push access)
@@ -42,18 +36,18 @@ function isCollaborator(event: PayloadEvent): boolean {
// if included, must match the type - so we need to explicitly allow undefined. // if included, must match the type - so we need to explicitly allow undefined.
export const Inputs = type({ export const Inputs = type({
prompt: "string", prompt: "string",
"effort?": Effort, "effort?": Effort.or("undefined"),
"agent?": AgentName.or("null"), "agent?": AgentName.or("undefined"),
"web?": ToolPermissionInput.or("undefined"), "web?": ToolPermissionInput.or("undefined"),
"search?": ToolPermissionInput.or("undefined"), "search?": ToolPermissionInput.or("undefined"),
"write?": ToolPermissionInput.or("undefined"), "write?": ToolPermissionInput.or("undefined"),
"bash?": BashPermissionInput.or("undefined"), "bash?": BashPermissionInput.or("undefined"),
"cwd?": "string|null", "cwd?": type.string.or("undefined"),
}); });
export type Inputs = typeof Inputs.infer; export type Inputs = typeof Inputs.infer;
function isAgentName(value: unknown): value is AgentNameType { function isAgentName(value: unknown): value is AgentName {
return typeof value === "string" && AgentName(value) instanceof type.errors === false; return typeof value === "string" && AgentName(value) instanceof type.errors === false;
} }
@@ -61,9 +55,9 @@ function isPayloadEvent(value: unknown): value is PayloadEvent {
return typeof value === "object" && value !== null && "trigger" in value; return typeof value === "object" && value !== null && "trigger" in value;
} }
function resolveCwd(cwd: string | null | undefined): string | null { function resolveCwd(cwd: string | undefined): string | undefined {
const workspace = process.env.GITHUB_WORKSPACE; const workspace = process.env.GITHUB_WORKSPACE;
if (!cwd) return workspace ?? null; if (!cwd) return workspace;
if (isAbsolute(cwd)) return cwd; if (isAbsolute(cwd)) return cwd;
return workspace ? resolve(workspace, cwd) : cwd; return workspace ? resolve(workspace, cwd) : cwd;
} }
@@ -72,19 +66,17 @@ export function resolvePayload(repoSettings: RepoSettings) {
const inputs = Inputs.assert({ const inputs = Inputs.assert({
prompt: core.getInput("prompt", { required: true }), prompt: core.getInput("prompt", { required: true }),
effort: core.getInput("effort") || undefined, effort: core.getInput("effort") || undefined,
agent: core.getInput("agent") || null, agent: core.getInput("agent") || undefined,
cwd: core.getInput("cwd") || null, cwd: core.getInput("cwd") || undefined,
web: core.getInput("web") || undefined, web: core.getInput("web") || undefined,
search: core.getInput("search") || undefined, search: core.getInput("search") || undefined,
write: core.getInput("write") || undefined, write: core.getInput("write") || undefined,
bash: core.getInput("bash") || undefined, bash: core.getInput("bash") || undefined,
}); });
// convert "null" string to null, validate agent name // validate agent name
const agent: AgentNameType | null = const agent: AgentName | undefined =
inputs.agent !== undefined && inputs.agent !== "null" && isAgentName(inputs.agent) inputs.agent !== undefined && isAgentName(inputs.agent) ? inputs.agent : undefined;
? inputs.agent
: null;
// try to parse prompt as JSON payload (internal invocation) // try to parse prompt as JSON payload (internal invocation)
let jsonPayload: typeof JsonPayload.infer | null = null; let jsonPayload: typeof JsonPayload.infer | null = null;
@@ -108,9 +100,8 @@ export function resolvePayload(repoSettings: RepoSettings) {
// resolve agent from jsonPayload with type guard // resolve agent from jsonPayload with type guard
const jsonAgent = jsonPayload?.agent; const jsonAgent = jsonPayload?.agent;
const resolvedAgent: AgentNameType | null = const resolvedAgent: AgentName | undefined =
agent ?? agent ?? (jsonAgent !== undefined && isAgentName(jsonAgent) ? jsonAgent : undefined);
(jsonAgent !== undefined && jsonAgent !== "null" && isAgentName(jsonAgent) ? jsonAgent : null);
// determine if permissions should be restricted based on event author // determine if permissions should be restricted based on event author
// non-collaborators (read, triage, none, or missing) get restricted bash access // non-collaborators (read, triage, none, or missing) get restricted bash access