feat: allow hour durations
This commit is contained in:
@@ -148,7 +148,7 @@ If you omit the provider, CLAWDIS currently assumes `anthropic` as a temporary
|
|||||||
deprecation fallback.
|
deprecation fallback.
|
||||||
|
|
||||||
`agent.heartbeat` configures periodic heartbeat runs:
|
`agent.heartbeat` configures periodic heartbeat runs:
|
||||||
- `every`: duration string (`ms`, `s`, `m`); default unit minutes. Omit or set
|
- `every`: duration string (`ms`, `s`, `m`, `h`); default unit minutes. Omit or set
|
||||||
`0m` to disable.
|
`0m` to disable.
|
||||||
- `model`: optional override model for heartbeat runs (`provider/model`).
|
- `model`: optional override model for heartbeat runs (`provider/model`).
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ Goal: add a simple heartbeat poll for the embedded agent that only notifies user
|
|||||||
|
|
||||||
## Config & defaults
|
## Config & defaults
|
||||||
- New config key: `agent.heartbeat` with:
|
- New config key: `agent.heartbeat` with:
|
||||||
- `every`: duration string (`ms`, `s`, `m`; default unit minutes). `0m` disables.
|
- `every`: duration string (`ms`, `s`, `m`, `h`; default unit minutes). `0m` disables.
|
||||||
- `model`: optional override model (`provider/model`) for heartbeat runs.
|
- `model`: optional override model (`provider/model`) for heartbeat runs.
|
||||||
- Default: disabled unless `agent.heartbeat.every` is set.
|
- Default: disabled unless `agent.heartbeat.every` is set.
|
||||||
- New optional idle override for heartbeats: `session.heartbeatIdleMinutes` (defaults to `idleMinutes`). Heartbeat skips do **not** update the session `updatedAt` so idle expiry still works.
|
- New optional idle override for heartbeats: `session.heartbeatIdleMinutes` (defaults to `idleMinutes`). Heartbeat skips do **not** update the session `updatedAt` so idle expiry still works.
|
||||||
|
|||||||
@@ -15,6 +15,10 @@ describe("parseDurationMs", () => {
|
|||||||
expect(parseDurationMs("1m")).toBe(60_000);
|
expect(parseDurationMs("1m")).toBe(60_000);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("parses hours suffix", () => {
|
||||||
|
expect(parseDurationMs("2h")).toBe(7_200_000);
|
||||||
|
});
|
||||||
|
|
||||||
it("supports decimals", () => {
|
it("supports decimals", () => {
|
||||||
expect(parseDurationMs("0.5s")).toBe(500);
|
expect(parseDurationMs("0.5s")).toBe(500);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
export type DurationMsParseOptions = {
|
export type DurationMsParseOptions = {
|
||||||
defaultUnit?: "ms" | "s" | "m";
|
defaultUnit?: "ms" | "s" | "m" | "h";
|
||||||
};
|
};
|
||||||
|
|
||||||
export function parseDurationMs(
|
export function parseDurationMs(
|
||||||
@@ -11,7 +11,7 @@ export function parseDurationMs(
|
|||||||
.toLowerCase();
|
.toLowerCase();
|
||||||
if (!trimmed) throw new Error("invalid duration (empty)");
|
if (!trimmed) throw new Error("invalid duration (empty)");
|
||||||
|
|
||||||
const m = /^(\d+(?:\.\d+)?)(ms|s|m)?$/.exec(trimmed);
|
const m = /^(\d+(?:\.\d+)?)(ms|s|m|h)?$/.exec(trimmed);
|
||||||
if (!m) throw new Error(`invalid duration: ${raw}`);
|
if (!m) throw new Error(`invalid duration: ${raw}`);
|
||||||
|
|
||||||
const value = Number(m[1]);
|
const value = Number(m[1]);
|
||||||
@@ -19,8 +19,13 @@ export function parseDurationMs(
|
|||||||
throw new Error(`invalid duration: ${raw}`);
|
throw new Error(`invalid duration: ${raw}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const unit = (m[2] ?? opts?.defaultUnit ?? "ms") as "ms" | "s" | "m";
|
const unit = (m[2] ?? opts?.defaultUnit ?? "ms") as
|
||||||
const multiplier = unit === "ms" ? 1 : unit === "s" ? 1000 : 60_000;
|
| "ms"
|
||||||
|
| "s"
|
||||||
|
| "m"
|
||||||
|
| "h";
|
||||||
|
const multiplier =
|
||||||
|
unit === "ms" ? 1 : unit === "s" ? 1000 : unit === "m" ? 60_000 : 3_600_000;
|
||||||
const ms = Math.round(value * multiplier);
|
const ms = Math.round(value * multiplier);
|
||||||
if (!Number.isFinite(ms)) throw new Error(`invalid duration: ${raw}`);
|
if (!Number.isFinite(ms)) throw new Error(`invalid duration: ${raw}`);
|
||||||
return ms;
|
return ms;
|
||||||
|
|||||||
@@ -463,7 +463,7 @@ const HeartbeatSchema = z
|
|||||||
ctx.addIssue({
|
ctx.addIssue({
|
||||||
code: z.ZodIssueCode.custom,
|
code: z.ZodIssueCode.custom,
|
||||||
path: ["every"],
|
path: ["every"],
|
||||||
message: "invalid duration (use ms, s, m)",
|
message: "invalid duration (use ms, s, m, h)",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user