Skip to content

Commit f7ce1c3

Browse files
committed
refactor: use parse-duration library for timeout parsing
Replace the janky hand-rolled duration regex with the well-tested parse-duration library. This supports more formats including: - Compound expressions: '1h30m', '1hr 20mins' - All common units: ms, s, m, h, d, w - Plain numbers as milliseconds _Generated with `mux`_
1 parent 0f258d5 commit f7ce1c3

File tree

3 files changed

+17
-14
lines changed

3 files changed

+17
-14
lines changed

bun.lock

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
"motion": "^12.23.24",
4848
"ollama-ai-provider-v2": "^1.5.4",
4949
"openai": "^6.9.1",
50+
"parse-duration": "^2.1.4",
5051
"rehype-harden": "^1.1.5",
5152
"shescape": "^2.1.6",
5253
"source-map-support": "^0.5.21",
@@ -2935,6 +2936,8 @@
29352936

29362937
"parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
29372938

2939+
"parse-duration": ["parse-duration@2.1.4", "", {}, "sha512-b98m6MsCh+akxfyoz9w9dt0AlH2dfYLOBss5SdDsr9pkhKNvkWBXU/r8A4ahmIGByBOLV2+4YwfCuFxbDDaGyg=="],
2940+
29382941
"parse-entities": ["parse-entities@4.0.2", "", { "dependencies": { "@types/unist": "^2.0.0", "character-entities-legacy": "^3.0.0", "character-reference-invalid": "^2.0.0", "decode-named-character-reference": "^1.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0", "is-hexadecimal": "^2.0.0" } }, "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw=="],
29392942

29402943
"parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="],

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
"motion": "^12.23.24",
8989
"ollama-ai-provider-v2": "^1.5.4",
9090
"openai": "^6.9.1",
91+
"parse-duration": "^2.1.4",
9192
"rehype-harden": "^1.1.5",
9293
"shescape": "^2.1.6",
9394
"source-map-support": "^0.5.21",

src/cli/run.ts

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import type { ThinkingLevel } from "@/common/types/thinking";
3737
import type { RuntimeConfig } from "@/common/types/runtime";
3838
import { parseRuntimeModeAndHost, RUNTIME_MODE } from "@/common/types/runtime";
3939
import assert from "@/common/utils/assert";
40+
import parseDuration from "parse-duration";
4041

4142
type CLIMode = "plan" | "exec";
4243

@@ -66,25 +67,23 @@ function parseRuntimeConfig(value: string | undefined, srcBaseDir: string): Runt
6667
function parseTimeout(value: string | undefined): number | undefined {
6768
if (!value) return undefined;
6869

69-
const trimmed = value.trim().toLowerCase();
70+
const trimmed = value.trim();
7071

71-
// Parse human-friendly formats: 5m, 300s, 5min, 5minutes, etc.
72-
const regex = /^(\d+(?:\.\d+)?)\s*(s|sec|secs|seconds?|m|min|mins|minutes?|ms)?$/i;
73-
const match = regex.exec(trimmed);
74-
if (!match) {
72+
// Try parsing as plain number (milliseconds)
73+
const asNumber = Number(trimmed);
74+
if (!Number.isNaN(asNumber) && asNumber > 0) {
75+
return Math.round(asNumber);
76+
}
77+
78+
// Use parse-duration for human-friendly formats (5m, 300s, 1h30m, etc.)
79+
const ms = parseDuration(trimmed);
80+
if (ms === null || ms <= 0) {
7581
throw new Error(
76-
`Invalid timeout format "${value}". Use: 300s, 5m, 5min, or milliseconds (e.g., 300000)`
82+
`Invalid timeout format "${value}". Use: 5m, 300s, 1h30m, or milliseconds (e.g., 300000)`
7783
);
7884
}
7985

80-
const num = parseFloat(match[1]);
81-
const unit = (match[2] || "ms").toLowerCase();
82-
83-
if (unit === "ms") return Math.round(num);
84-
if (unit.startsWith("s")) return Math.round(num * 1000);
85-
if (unit.startsWith("m")) return Math.round(num * 60 * 1000);
86-
87-
return Math.round(num);
86+
return Math.round(ms);
8887
}
8988

9089
function parseThinkingLevel(value: string | undefined): ThinkingLevel | undefined {

0 commit comments

Comments
 (0)