feat: change --timeout from milliseconds to seconds

Accept seconds (including decimals like 0.5) instead of milliseconds
for the --timeout flag. Converts to ms internally. Default is now 10
(seconds) instead of 10000. Error messages display seconds.

Update AGENTS.md, tests, and skill docs to match.
This commit is contained in:
2026-05-02 20:10:20 -04:00
parent 6adb5111de
commit d02df19469
3 changed files with 13 additions and 13 deletions

View File

@@ -30,7 +30,7 @@ Do not attempt a live Kagi test unless `KAGI_TOKEN` is available.
- Browser execution should be headless by default. - Browser execution should be headless by default.
- Use `--no-headless` as the opt-out. - Use `--no-headless` as the opt-out.
- Keep `--url=<server>` support for connecting to an existing WebDriver server. - Keep `--url=<server>` support for connecting to an existing WebDriver server.
- `--timeout=<ms>` is a top-level option for command waits and defaults to `10000`. - `--timeout=<seconds>` is a top-level option for command waits and defaults to `10`.
- `--wait-js=<code>` and `--wait-until=<state>` are top-level wait options available to every `glimpse` subcommand. - `--wait-js=<code>` and `--wait-until=<state>` are top-level wait options available to every `glimpse` subcommand.
- `--js=<code>` and `--script=<file>` are top-level options available to every `glimpse` subcommand and run before command-specific behavior. - `--js=<code>` and `--script=<file>` are top-level options available to every `glimpse` subcommand and run before command-specific behavior.
- Prefer structured JSON output for objects/arrays. - Prefer structured JSON output for objects/arrays.

View File

@@ -6,7 +6,7 @@ import { searchKagi, type SearchResult } from "./providers/kagi.js";
import { readFileSync, writeFileSync } from "node:fs"; import { readFileSync, writeFileSync } from "node:fs";
import TurndownService from "turndown"; import TurndownService from "turndown";
const DEFAULT_TIMEOUT_MS = 10000; const DEFAULT_TIMEOUT_S = 10;
const POLL_INTERVAL_MS = 200; const POLL_INTERVAL_MS = 200;
const startTime = Date.now(); const startTime = Date.now();
const runContext: { targetUrl?: string; currentUrl?: string } = {}; const runContext: { targetUrl?: string; currentUrl?: string } = {};
@@ -34,7 +34,7 @@ const waitJs = getOption("--wait-js");
const waitUntil = getOption("--wait-until") ?? "none"; const waitUntil = getOption("--wait-until") ?? "none";
const configPath = getOption("--config"); const configPath = getOption("--config");
let appConfig: GlimpseConfig = {}; let appConfig: GlimpseConfig = {};
let timeoutMs = DEFAULT_TIMEOUT_MS; let timeoutMs: number;
function getOption(name: string) { function getOption(name: string) {
const prefix = `${name}=`; const prefix = `${name}=`;
@@ -97,7 +97,7 @@ Common Options:
--help Show this help --help Show this help
--no-headless Show Firefox instead of running headless --no-headless Show Firefox instead of running headless
--url=<server> Connect to an existing WebDriver server --url=<server> Connect to an existing WebDriver server
--timeout=<ms> Maximum wait time in milliseconds (default: 10000) --timeout=<seconds> Maximum wait time in seconds (default: 10)
--wait-js=<code> Poll JS until it returns a truthy value --wait-js=<code> Poll JS until it returns a truthy value
--wait-until=<state> Wait for readiness: none, interactive, complete (default: none) --wait-until=<state> Wait for readiness: none, interactive, complete (default: none)
--js=<code> Execute inline JS before command logic --js=<code> Execute inline JS before command logic
@@ -145,15 +145,15 @@ function usage() {
function parseTimeout() { function parseTimeout() {
const value = getOption("--timeout"); const value = getOption("--timeout");
if (value === undefined) { if (value === undefined) {
return DEFAULT_TIMEOUT_MS; return DEFAULT_TIMEOUT_S * 1000;
} }
const parsed = Number.parseInt(value, 10); const parsed = Number.parseFloat(value);
if (!Number.isInteger(parsed) || parsed <= 0 || String(parsed) !== value) { if (!Number.isFinite(parsed) || parsed <= 0) {
cliError("INVALID_OPTION", "--timeout must be a positive integer."); cliError("INVALID_OPTION", "--timeout must be a positive number.");
} }
return parsed; return Math.round(parsed * 1000);
} }
function validateCommonOptions() { function validateCommonOptions() {
@@ -214,7 +214,7 @@ async function waitForReadyState(driver: WebDriver) {
} catch { } catch {
cliError( cliError(
"WAIT_TIMEOUT", "WAIT_TIMEOUT",
`Timed out after ${timeoutMs}ms waiting for --wait-until=${waitUntil}`, `Timed out after ${timeoutMs / 1000}s waiting for --wait-until=${waitUntil}`,
); );
} }
} }
@@ -243,7 +243,7 @@ async function waitForJs(driver: WebDriver) {
cliError( cliError(
"WAIT_TIMEOUT", "WAIT_TIMEOUT",
`Timed out after ${timeoutMs}ms waiting for --wait-js`, `Timed out after ${timeoutMs / 1000}s waiting for --wait-js`,
); );
} }

View File

@@ -254,7 +254,7 @@ test(
assert.equal(output.ok, false); assert.equal(output.ok, false);
assert.equal(output.error.code, "INVALID_OPTION"); assert.equal(output.error.code, "INVALID_OPTION");
assert.match(output.error.message, /--timeout must be a positive integer/); assert.match(output.error.message, /--timeout must be a positive number/);
assert.equal(typeof output.elapsedMs, "number"); assert.equal(typeof output.elapsedMs, "number");
}, },
); );
@@ -290,7 +290,7 @@ test("wait-js timeout returns wait timeout", ["wait", "errors"], () => {
dataHtml("<title>Hello</title>"), dataHtml("<title>Hello</title>"),
"--no-reader", "--no-reader",
"--wait-js=return false", "--wait-js=return false",
"--timeout=1", "--timeout=0.001",
]); ]);
assert.equal(output.ok, false); assert.equal(output.ok, false);