refactor: centralize cli timeout parsing
This commit is contained in:
@@ -114,7 +114,7 @@
|
|||||||
- Docs: expand parameter descriptions for agent/wake hooks. (#532) — thanks @mcinteerj
|
- Docs: expand parameter descriptions for agent/wake hooks. (#532) — thanks @mcinteerj
|
||||||
- Docs: add community showcase entries from Discord. (#476) — thanks @gupsammy
|
- Docs: add community showcase entries from Discord. (#476) — thanks @gupsammy
|
||||||
- TUI: refresh status bar after think/verbose/reasoning changes. (#519) — thanks @jdrhyne
|
- TUI: refresh status bar after think/verbose/reasoning changes. (#519) — thanks @jdrhyne
|
||||||
- TUI: stop overriding agent timeout so config defaults apply. (#549)
|
- TUI: stop overriding agent timeout so config defaults apply; warn on invalid `--timeout-ms`. (#549)
|
||||||
- Status: show Verbose/Elevated only when enabled.
|
- Status: show Verbose/Elevated only when enabled.
|
||||||
- Status: filter usage summary to the active model provider.
|
- Status: filter usage summary to the active model provider.
|
||||||
- Status: map model providers to usage sources so unrelated usage doesn’t appear.
|
- Status: map model providers to usage sources so unrelated usage doesn’t appear.
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ Session lifecycle:
|
|||||||
- `--session <key>`: Session key (default: `main`, or `global` when scope is global)
|
- `--session <key>`: Session key (default: `main`, or `global` when scope is global)
|
||||||
- `--deliver`: Deliver assistant replies to the provider (default off)
|
- `--deliver`: Deliver assistant replies to the provider (default off)
|
||||||
- `--thinking <level>`: Override thinking level for sends
|
- `--thinking <level>`: Override thinking level for sends
|
||||||
- `--timeout-ms <ms>`: Agent timeout (defaults to `agents.defaults.timeoutSeconds`)
|
- `--timeout-ms <ms>`: Agent timeout in ms (defaults to `agents.defaults.timeoutSeconds`)
|
||||||
- `--history-limit <n>`: History entries to load (default 200)
|
- `--history-limit <n>`: History entries to load (default 200)
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { parseTimeoutMs } from "./parse-timeout.js";
|
||||||
|
|
||||||
export function parseEnvPairs(
|
export function parseEnvPairs(
|
||||||
pairs: unknown,
|
pairs: unknown,
|
||||||
): Record<string, string> | undefined {
|
): Record<string, string> | undefined {
|
||||||
@@ -14,17 +16,4 @@ export function parseEnvPairs(
|
|||||||
return Object.keys(env).length > 0 ? env : undefined;
|
return Object.keys(env).length > 0 ? env : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseTimeoutMs(raw: unknown): number | undefined {
|
export { parseTimeoutMs };
|
||||||
if (raw === undefined || raw === null) return undefined;
|
|
||||||
let value = Number.NaN;
|
|
||||||
if (typeof raw === "number") {
|
|
||||||
value = raw;
|
|
||||||
} else if (typeof raw === "bigint") {
|
|
||||||
value = Number(raw);
|
|
||||||
} else if (typeof raw === "string") {
|
|
||||||
const trimmed = raw.trim();
|
|
||||||
if (!trimmed) return undefined;
|
|
||||||
value = Number.parseInt(trimmed, 10);
|
|
||||||
}
|
|
||||||
return Number.isFinite(value) ? value : undefined;
|
|
||||||
}
|
|
||||||
|
|||||||
14
src/cli/parse-timeout.ts
Normal file
14
src/cli/parse-timeout.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
export function parseTimeoutMs(raw: unknown): number | undefined {
|
||||||
|
if (raw === undefined || raw === null) return undefined;
|
||||||
|
let value = Number.NaN;
|
||||||
|
if (typeof raw === "number") {
|
||||||
|
value = raw;
|
||||||
|
} else if (typeof raw === "bigint") {
|
||||||
|
value = Number(raw);
|
||||||
|
} else if (typeof raw === "string") {
|
||||||
|
const trimmed = raw.trim();
|
||||||
|
if (!trimmed) return undefined;
|
||||||
|
value = Number.parseInt(trimmed, 10);
|
||||||
|
}
|
||||||
|
return Number.isFinite(value) ? value : undefined;
|
||||||
|
}
|
||||||
@@ -98,6 +98,19 @@ describe("cli program", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("warns and ignores invalid tui timeout override", async () => {
|
||||||
|
const program = buildProgram();
|
||||||
|
await program.parseAsync(["tui", "--timeout-ms", "nope"], {
|
||||||
|
from: "user",
|
||||||
|
});
|
||||||
|
expect(runtime.error).toHaveBeenCalledWith(
|
||||||
|
'warning: invalid --timeout-ms "nope"; ignoring',
|
||||||
|
);
|
||||||
|
expect(runTui).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({ timeoutMs: undefined }),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it("runs config alias as configure", async () => {
|
it("runs config alias as configure", async () => {
|
||||||
const program = buildProgram();
|
const program = buildProgram();
|
||||||
await program.parseAsync(["config"], { from: "user" });
|
await program.parseAsync(["config"], { from: "user" });
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import type { Command } from "commander";
|
import type { Command } from "commander";
|
||||||
import { defaultRuntime } from "../runtime.js";
|
import { defaultRuntime } from "../runtime.js";
|
||||||
import { runTui } from "../tui/tui.js";
|
import { runTui } from "../tui/tui.js";
|
||||||
|
import { parseTimeoutMs } from "./parse-timeout.js";
|
||||||
|
|
||||||
export function registerTuiCli(program: Command) {
|
export function registerTuiCli(program: Command) {
|
||||||
program
|
program
|
||||||
@@ -26,14 +27,12 @@ export function registerTuiCli(program: Command) {
|
|||||||
.option("--history-limit <n>", "History entries to load", "200")
|
.option("--history-limit <n>", "History entries to load", "200")
|
||||||
.action(async (opts) => {
|
.action(async (opts) => {
|
||||||
try {
|
try {
|
||||||
const timeoutMs =
|
const timeoutMs = parseTimeoutMs(opts.timeoutMs);
|
||||||
typeof opts.timeoutMs === "undefined"
|
if (opts.timeoutMs !== undefined && timeoutMs === undefined) {
|
||||||
? undefined
|
defaultRuntime.error(
|
||||||
: Number.parseInt(String(opts.timeoutMs), 10);
|
`warning: invalid --timeout-ms "${String(opts.timeoutMs)}"; ignoring`,
|
||||||
const normalizedTimeoutMs =
|
);
|
||||||
typeof timeoutMs === "number" && Number.isFinite(timeoutMs)
|
}
|
||||||
? timeoutMs
|
|
||||||
: undefined;
|
|
||||||
const historyLimit = Number.parseInt(
|
const historyLimit = Number.parseInt(
|
||||||
String(opts.historyLimit ?? "200"),
|
String(opts.historyLimit ?? "200"),
|
||||||
10,
|
10,
|
||||||
@@ -46,7 +45,7 @@ export function registerTuiCli(program: Command) {
|
|||||||
deliver: Boolean(opts.deliver),
|
deliver: Boolean(opts.deliver),
|
||||||
thinking: opts.thinking as string | undefined,
|
thinking: opts.thinking as string | undefined,
|
||||||
message: opts.message as string | undefined,
|
message: opts.message as string | undefined,
|
||||||
timeoutMs: normalizedTimeoutMs,
|
timeoutMs,
|
||||||
historyLimit: Number.isNaN(historyLimit) ? undefined : historyLimit,
|
historyLimit: Number.isNaN(historyLimit) ? undefined : historyLimit,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
Reference in New Issue
Block a user