add #timeout, macro errors, refactor tests (#191)
This commit is contained in:
committed by
pullfrog[bot]
parent
f77fecc2a0
commit
943409c417
@@ -1,6 +1,6 @@
|
||||
export const PULLFROG_DIVIDER = "<!-- PULLFROG_DIVIDER_DO_NOT_REMOVE_PLZ -->";
|
||||
|
||||
const FROG_LOGO = `<a href="https://pullfrog.com"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pullfrog.com/logos/frog-white-full-128px.png"><img src="https://pullfrog.com/logos/frog-green-full-128px.png" width="9px" height="9px" style="vertical-align: middle; " alt="Pullfrog"></picture></a>`;
|
||||
const FROG_LOGO = `<a href="https://pullfrog.com"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pullfrog.com/logos/frog-white-full-18px.png"><img src="https://pullfrog.com/logos/frog-green-full-18px.png" width="9px" height="9px" style="vertical-align: middle; " alt="Pullfrog"></picture></a>`;
|
||||
|
||||
export interface AgentInfo {
|
||||
displayName: string;
|
||||
|
||||
@@ -24,6 +24,10 @@ describe("Inputs schema", () => {
|
||||
["effort", "mini"],
|
||||
["effort", "auto"],
|
||||
["effort", "max"],
|
||||
["timeout", "10m"],
|
||||
["timeout", "1h30m"],
|
||||
["timeout", "30s"],
|
||||
["timeout", undefined],
|
||||
["agent", "claude"],
|
||||
["agent", "codex"],
|
||||
["agent", "cursor"],
|
||||
@@ -63,6 +67,9 @@ describe("JsonPayload schema", () => {
|
||||
["effort", "mini"],
|
||||
["effort", "auto"],
|
||||
["effort", "max"],
|
||||
["timeout", "10m"],
|
||||
["timeout", "1h30m"],
|
||||
["timeout", "30s"],
|
||||
["event", { trigger: "unknown" }],
|
||||
] as const)("should accept optional %s with value %s", (prop, value) => {
|
||||
const input = { "~pullfrog": true, version: "1.2.3", [prop]: value };
|
||||
|
||||
@@ -22,6 +22,7 @@ export const JsonPayload = type({
|
||||
"repoInstructions?": "string",
|
||||
"event?": "object",
|
||||
"effort?": Effort.or("undefined"),
|
||||
"timeout?": type.string.or("undefined"),
|
||||
});
|
||||
|
||||
// permission levels that indicate collaborator status (have push access)
|
||||
@@ -41,6 +42,7 @@ function isCollaborator(event: PayloadEvent): boolean {
|
||||
export const Inputs = type({
|
||||
prompt: "string",
|
||||
"effort?": Effort.or("undefined"),
|
||||
"timeout?": type.string.or("undefined"),
|
||||
"agent?": AgentName.or("undefined"),
|
||||
"web?": ToolPermissionInput.or("undefined"),
|
||||
"search?": ToolPermissionInput.or("undefined"),
|
||||
@@ -70,6 +72,7 @@ export function resolvePayload(repoSettings: RepoSettings) {
|
||||
const inputs = Inputs.assert({
|
||||
prompt: core.getInput("prompt", { required: true }),
|
||||
effort: core.getInput("effort") || undefined,
|
||||
timeout: core.getInput("timeout") || undefined,
|
||||
agent: core.getInput("agent") || undefined,
|
||||
cwd: core.getInput("cwd") || undefined,
|
||||
web: core.getInput("web") || undefined,
|
||||
@@ -145,6 +148,7 @@ export function resolvePayload(repoSettings: RepoSettings) {
|
||||
repoInstructions: jsonPayload?.repoInstructions,
|
||||
event,
|
||||
effort: inputs.effort ?? jsonPayload?.effort ?? "auto",
|
||||
timeout: inputs.timeout ?? jsonPayload?.timeout,
|
||||
cwd: resolveCwd(inputs.cwd),
|
||||
|
||||
// permissions: inputs > repoSettings > fallbacks
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { isValidTimeString, parseTimeString } from "./time.ts";
|
||||
|
||||
describe("parseTimeString", () => {
|
||||
it.each([
|
||||
["10m", 600000], // 10 minutes
|
||||
["1h", 3600000], // 1 hour
|
||||
["30s", 30000], // 30 seconds
|
||||
["1h30m", 5400000], // 1 hour 30 minutes
|
||||
["10m12s", 612000], // 10 minutes 12 seconds
|
||||
["1h30m45s", 5445000], // 1 hour 30 minutes 45 seconds
|
||||
["2h", 7200000], // 2 hours
|
||||
["90m", 5400000], // 90 minutes
|
||||
["0m", 0], // 0 minutes (edge case)
|
||||
["0s", 0], // 0 seconds (edge case)
|
||||
])("parses '%s' to %d ms", (input, expected) => {
|
||||
expect(parseTimeString(input)).toBe(expected);
|
||||
});
|
||||
|
||||
it.each([
|
||||
[""], // empty string
|
||||
["abc"], // no numbers
|
||||
["10"], // no unit
|
||||
["10x"], // invalid unit
|
||||
["h10m"], // hours without number
|
||||
["m10"], // units before number
|
||||
["10 m"], // space between number and unit
|
||||
["-10m"], // negative number
|
||||
["10.5m"], // decimal
|
||||
["10m 30s"], // space between components
|
||||
])("returns null for invalid input '%s'", (input) => {
|
||||
expect(parseTimeString(input)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe("isValidTimeString", () => {
|
||||
it.each(["10m", "1h", "30s", "1h30m", "10m12s", "1h30m45s"])(
|
||||
"returns true for valid '%s'",
|
||||
(input) => {
|
||||
expect(isValidTimeString(input)).toBe(true);
|
||||
}
|
||||
);
|
||||
|
||||
it.each(["", "abc", "10", "10x", "-10m", "10.5m"])("returns false for invalid '%s'", (input) => {
|
||||
expect(isValidTimeString(input)).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* time string parsing utilities for timeout configuration.
|
||||
* supports formats like "10m", "1h30m", "10m12s", "30s".
|
||||
*/
|
||||
|
||||
// special value indicating timeout is explicitly disabled via #notimeout macro
|
||||
export const TIMEOUT_DISABLED = "none";
|
||||
|
||||
// time string regex: supports formats like "10m", "1h30m", "10m12s", "30s"
|
||||
// at least one component (hours, minutes, or seconds) is required
|
||||
const TIME_STRING_REGEX = /^(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?$/;
|
||||
|
||||
/**
|
||||
* parse a time string like "10m", "1h30m", "10m12s" into milliseconds.
|
||||
* returns null if the string is not a valid time format.
|
||||
*/
|
||||
export function parseTimeString(input: string): number | null {
|
||||
const match = input.match(TIME_STRING_REGEX);
|
||||
if (!match || (!match[1] && !match[2] && !match[3])) return null;
|
||||
|
||||
const hours = parseInt(match[1] || "0", 10);
|
||||
const minutes = parseInt(match[2] || "0", 10);
|
||||
const seconds = parseInt(match[3] || "0", 10);
|
||||
|
||||
return (hours * 3600 + minutes * 60 + seconds) * 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if a string is a valid time format.
|
||||
*/
|
||||
export function isValidTimeString(input: string): boolean {
|
||||
return parseTimeString(input) !== null;
|
||||
}
|
||||
Reference in New Issue
Block a user