diff --git a/entry b/entry index 2072553..4c4efee 100755 --- a/entry +++ b/entry @@ -137869,18 +137869,14 @@ function resolveAgent(params) { log.debug( `\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) { const agent3 = agents[configuredAgentName]; if (!agent3) { throw new Error(`invalid agent name: ${configuredAgentName}`); } - const isExplicitOverride = agentOverride !== void 0 || params.payload.agent !== null; - if (isExplicitOverride) { - log.info(`\xBB selected configured agent: ${agent3.name}`); - return agent3; - } - if (agentHasApiKeys(agent3)) { + const isExplicitOverride = agentOverride !== void 0 || params.payload.agent !== void 0; + if (isExplicitOverride || agentHasApiKeys(agent3)) { log.info(`\xBB selected configured agent: ${agent3.name}`); return agent3; } @@ -138183,11 +138179,11 @@ var ToolPermissionInput = type.enumerated("disabled", "enabled"); var BashPermissionInput = type.enumerated("disabled", "restricted", "enabled"); var JsonPayload = type({ "~pullfrog": "true", - "agent?": AgentName.or("null"), + "agent?": AgentName.or("undefined"), "prompt?": "string", "repoInstructions?": "string", "event?": "object", - "effort?": Effort + "effort?": Effort.or("undefined") }); var COLLABORATOR_PERMISSIONS = ["admin", "maintain", "write"]; function isCollaborator(event) { @@ -138196,13 +138192,13 @@ function isCollaborator(event) { } var Inputs = type({ prompt: "string", - "effort?": Effort, - "agent?": AgentName.or("null"), + "effort?": Effort.or("undefined"), + "agent?": AgentName.or("undefined"), "web?": ToolPermissionInput.or("undefined"), "search?": ToolPermissionInput.or("undefined"), "write?": ToolPermissionInput.or("undefined"), "bash?": BashPermissionInput.or("undefined"), - "cwd?": "string|null" + "cwd?": type.string.or("undefined") }); function isAgentName(value2) { return typeof value2 === "string" && AgentName(value2) instanceof type.errors === false; @@ -138212,7 +138208,7 @@ function isPayloadEvent(value2) { } function resolveCwd(cwd2) { const workspace = process.env.GITHUB_WORKSPACE; - if (!cwd2) return workspace ?? null; + if (!cwd2) return workspace; if (isAbsolute(cwd2)) return cwd2; return workspace ? resolve(workspace, cwd2) : cwd2; } @@ -138220,14 +138216,14 @@ function resolvePayload(repoSettings) { const inputs = Inputs.assert({ prompt: core4.getInput("prompt", { required: true }), effort: core4.getInput("effort") || void 0, - agent: core4.getInput("agent") || null, - cwd: core4.getInput("cwd") || null, + agent: core4.getInput("agent") || void 0, + cwd: core4.getInput("cwd") || void 0, web: core4.getInput("web") || void 0, search: core4.getInput("search") || void 0, write: core4.getInput("write") || 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; try { const parsed2 = JSON.parse(inputs.prompt); @@ -138242,7 +138238,7 @@ function resolvePayload(repoSettings) { const rawEvent = jsonPayload?.event; const event = isPayloadEvent(rawEvent) ? rawEvent : { trigger: "unknown" }; 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); return { "~pullfrog": true, diff --git a/external.ts b/external.ts index b4a3d60..daedf78 100644 --- a/external.ts +++ b/external.ts @@ -245,7 +245,7 @@ export type PayloadEvent = export interface WriteablePayload { "~pullfrog": true; /** 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) */ prompt: string; /** 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?: Effort | undefined; /** working directory for the agent */ - cwd?: string | null | undefined; + cwd?: string | undefined; } // immutable payload type for agent execution diff --git a/test/fixtures/bash-test.ts b/test/fixtures/bash-test.ts index 4cdd8d4..764c0c6 100644 --- a/test/fixtures/bash-test.ts +++ b/test/fixtures/bash-test.ts @@ -14,7 +14,6 @@ import type { Payload } from "../../external.ts"; */ export default { "~pullfrog": true, - agent: null, prompt: `Create a file called test-runner.js with the following content: \`\`\`javascript diff --git a/test/fixtures/basic.ts b/test/fixtures/basic.ts index b464d1d..b252353 100644 --- a/test/fixtures/basic.ts +++ b/test/fixtures/basic.ts @@ -2,7 +2,6 @@ import type { Payload } from "../../external.ts"; export default { "~pullfrog": true, - agent: null, 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.", event: { diff --git a/utils/agent.ts b/utils/agent.ts index 1804230..09c19ee 100644 --- a/utils/agent.ts +++ b/utils/agent.ts @@ -28,7 +28,7 @@ export function resolveAgent(params: { `» determineAgent: agentOverride=${agentOverride}, payload.agent=${params.payload.agent}, repoSettings.defaultAgent=${params.repoSettings.defaultAgent}` ); const configuredAgentName = - agentOverride || params.payload.agent || params.repoSettings.defaultAgent || null; + agentOverride || params.payload.agent || params.repoSettings.defaultAgent || undefined; if (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 // 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; - if (isExplicitOverride) { - log.info(`» selected configured agent: ${agent.name}`); - return agent; - } - - // for repo-level defaults, check if agent has matching keys before selecting - if (agentHasApiKeys(agent)) { + // for repo-level defaults, only select if agent has matching API keys + const isExplicitOverride = agentOverride !== undefined || params.payload.agent !== undefined; + if (isExplicitOverride || agentHasApiKeys(agent)) { log.info(`» selected configured agent: ${agent.name}`); return agent; } diff --git a/utils/payload.ts b/utils/payload.ts index 881be48..c590ed6 100644 --- a/utils/payload.ts +++ b/utils/payload.ts @@ -1,13 +1,7 @@ import { isAbsolute, resolve } from "node:path"; import * as core from "@actions/core"; import { type } from "arktype"; -import { - AgentName, - type AgentName as AgentNameType, - type AuthorPermission, - Effort, - type PayloadEvent, -} from "../external.ts"; +import { AgentName, type AuthorPermission, Effort, type PayloadEvent } from "../external.ts"; import type { RepoSettings } from "./repoSettings.ts"; // tool permission enum types for inputs @@ -19,11 +13,11 @@ const BashPermissionInput = type.enumerated("disabled", "restricted", "enabled") // permissions are derived from event.authorPermission instead const JsonPayload = type({ "~pullfrog": "true", - "agent?": AgentName.or("null"), + "agent?": AgentName.or("undefined"), "prompt?": "string", "repoInstructions?": "string", "event?": "object", - "effort?": Effort, + "effort?": Effort.or("undefined"), }); // 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. export const Inputs = type({ prompt: "string", - "effort?": Effort, - "agent?": AgentName.or("null"), + "effort?": Effort.or("undefined"), + "agent?": AgentName.or("undefined"), "web?": ToolPermissionInput.or("undefined"), "search?": ToolPermissionInput.or("undefined"), "write?": ToolPermissionInput.or("undefined"), "bash?": BashPermissionInput.or("undefined"), - "cwd?": "string|null", + "cwd?": type.string.or("undefined"), }); 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; } @@ -61,9 +55,9 @@ function isPayloadEvent(value: unknown): value is PayloadEvent { 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; - if (!cwd) return workspace ?? null; + if (!cwd) return workspace; if (isAbsolute(cwd)) return cwd; return workspace ? resolve(workspace, cwd) : cwd; } @@ -72,19 +66,17 @@ export function resolvePayload(repoSettings: RepoSettings) { const inputs = Inputs.assert({ prompt: core.getInput("prompt", { required: true }), effort: core.getInput("effort") || undefined, - agent: core.getInput("agent") || null, - cwd: core.getInput("cwd") || null, + agent: core.getInput("agent") || undefined, + cwd: core.getInput("cwd") || undefined, web: core.getInput("web") || undefined, search: core.getInput("search") || undefined, write: core.getInput("write") || undefined, bash: core.getInput("bash") || undefined, }); - // convert "null" string to null, validate agent name - const agent: AgentNameType | null = - inputs.agent !== undefined && inputs.agent !== "null" && isAgentName(inputs.agent) - ? inputs.agent - : null; + // validate agent name + const agent: AgentName | undefined = + inputs.agent !== undefined && isAgentName(inputs.agent) ? inputs.agent : undefined; // try to parse prompt as JSON payload (internal invocation) let jsonPayload: typeof JsonPayload.infer | null = null; @@ -108,9 +100,8 @@ export function resolvePayload(repoSettings: RepoSettings) { // resolve agent from jsonPayload with type guard const jsonAgent = jsonPayload?.agent; - const resolvedAgent: AgentNameType | null = - agent ?? - (jsonAgent !== undefined && jsonAgent !== "null" && isAgentName(jsonAgent) ? jsonAgent : null); + const resolvedAgent: AgentName | undefined = + agent ?? (jsonAgent !== undefined && isAgentName(jsonAgent) ? jsonAgent : undefined); // determine if permissions should be restricted based on event author // non-collaborators (read, triage, none, or missing) get restricted bash access