@wirecat/cli-core 0.583.0 → 0.584.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,19 @@ shape of this file.
|
|
|
7
7
|
|
|
8
8
|
## Unreleased
|
|
9
9
|
|
|
10
|
+
## 0.584.0 — 06.11.2026
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`schedule list` gives an agent schedule's cost caps.** `max_cost_usd` is the cap on one run (`--max-cost`, null
|
|
15
|
+
when none) and `max_cost_per_day_usd` the daily cap in force, the schedule's `--max-cost-per-day` or the config's
|
|
16
|
+
(0 for none), so a screen can show `$0.84 of $5.00`; the text line says `today $0.84 of $5.00`.
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- **`schedule list`'s output schema describes what it prints.** `spent_today_usd`, and the last run's `cost_usd`
|
|
21
|
+
and `skipped`, were printed but missing from the strict `scheduled_job` schema.
|
|
22
|
+
|
|
10
23
|
## 0.583.0 — 05.11.2026
|
|
11
24
|
|
|
12
25
|
### Changed — may break callers
|
|
@@ -138,6 +138,12 @@ export const scheduleLimitsOf = (config) => {
|
|
|
138
138
|
const given = (limits) => Object.fromEntries(Object.entries(limits).filter(([, value]) => value !== undefined));
|
|
139
139
|
const shown = (argv) => argv.map((arg) => (arg === "" ? '""' : arg)).join(" ");
|
|
140
140
|
const usd = (value) => `$${value.toFixed(2)}`;
|
|
141
|
+
/** The per-run cap an agent schedule was made with (`--max-cost`, passed to claude as --max-budget-usd), or null. */
|
|
142
|
+
const runCapOf = (argv) => {
|
|
143
|
+
const at = argv.indexOf("--max-budget-usd");
|
|
144
|
+
const cap = at < 0 ? Number.NaN : Number(argv[at + 1]);
|
|
145
|
+
return Number.isFinite(cap) ? cap : null;
|
|
146
|
+
};
|
|
141
147
|
/**
|
|
142
148
|
* Runs the CLI's own commands, or an agent, later or on a timer — through systemd (Linux), launchd
|
|
143
149
|
* (macOS) or Task Scheduler (Windows). Every timer runs `schedule exec <file>`; the schedule file holds
|
|
@@ -184,19 +190,21 @@ export const scheduleCommandFor = ({ app, context: contextOf, newMail, limits: c
|
|
|
184
190
|
* Why a run does not start now, or nothing: an agent whose runs reached the day's cost cap waits for tomorrow, and
|
|
185
191
|
* one gated on mail waits for mail past its holder's mark — on its timer, until enough of it waits.
|
|
186
192
|
*/
|
|
193
|
+
/** A schedule's own limits, else the config file's, else the defaults. */
|
|
194
|
+
const limitsOf = (self, schedule) => ({
|
|
195
|
+
...SCHEDULE_DEFAULTS,
|
|
196
|
+
...given(configured?.(self) ?? {}),
|
|
197
|
+
...given({
|
|
198
|
+
mailWaitMinutes: schedule.mailWaitMinutes,
|
|
199
|
+
mailBatch: schedule.mailBatch,
|
|
200
|
+
maxCostPerDay: schedule.maxCostPerDay,
|
|
201
|
+
}),
|
|
202
|
+
});
|
|
187
203
|
const waits = async (self, file, { timed }) => {
|
|
188
204
|
if (!existsSync(file))
|
|
189
205
|
return undefined;
|
|
190
206
|
const schedule = readSchedule(file);
|
|
191
|
-
const { mailWaitMinutes, mailBatch, maxCostPerDay } =
|
|
192
|
-
...SCHEDULE_DEFAULTS,
|
|
193
|
-
...given(configured?.(self) ?? {}),
|
|
194
|
-
...given({
|
|
195
|
-
mailWaitMinutes: schedule.mailWaitMinutes,
|
|
196
|
-
mailBatch: schedule.mailBatch,
|
|
197
|
-
maxCostPerDay: schedule.maxCostPerDay,
|
|
198
|
-
}),
|
|
199
|
-
};
|
|
207
|
+
const { mailWaitMinutes, mailBatch, maxCostPerDay } = limitsOf(self, schedule);
|
|
200
208
|
if (schedule.kind === "agent" && maxCostPerDay > 0) {
|
|
201
209
|
const spent = spentToday(file);
|
|
202
210
|
if (spent >= maxCostPerDay) {
|
|
@@ -342,7 +350,13 @@ export const scheduleCommandFor = ({ app, context: contextOf, newMail, limits: c
|
|
|
342
350
|
kind: schedule.kind,
|
|
343
351
|
when: describeWhen(schedule.when),
|
|
344
352
|
last: lastRun(scheduleFile(state, schedule.name)) ?? null,
|
|
345
|
-
...(schedule.kind === "agent"
|
|
353
|
+
...(schedule.kind === "agent"
|
|
354
|
+
? {
|
|
355
|
+
spentTodayUsd: spentToday(scheduleFile(state, schedule.name)),
|
|
356
|
+
maxCostUsd: runCapOf(schedule.argv),
|
|
357
|
+
maxCostPerDayUsd: limitsOf(this, schedule).maxCostPerDay,
|
|
358
|
+
}
|
|
359
|
+
: {}),
|
|
346
360
|
}));
|
|
347
361
|
const answer = listOf("schedule list", {
|
|
348
362
|
items: rows.map((row) => snakeKeys(row)),
|
|
@@ -355,7 +369,7 @@ export const scheduleCommandFor = ({ app, context: contextOf, newMail, limits: c
|
|
|
355
369
|
return "";
|
|
356
370
|
}
|
|
357
371
|
return rows
|
|
358
|
-
.map(({ name, kind, when, last, spentTodayUsd }) => [
|
|
372
|
+
.map(({ name, kind, when, last, spentTodayUsd, maxCostPerDayUsd }) => [
|
|
359
373
|
name,
|
|
360
374
|
kind,
|
|
361
375
|
when,
|
|
@@ -366,7 +380,9 @@ export const scheduleCommandFor = ({ app, context: contextOf, newMail, limits: c
|
|
|
366
380
|
`${last.failures} in a row${last.reason ? `: ${last.reason}` : ""} — ${last.output}`
|
|
367
381
|
: "")
|
|
368
382
|
: "not run yet",
|
|
369
|
-
...(spentTodayUsd
|
|
383
|
+
...(spentTodayUsd
|
|
384
|
+
? [`today ${usd(spentTodayUsd)}${maxCostPerDayUsd ? ` of ${usd(maxCostPerDayUsd)}` : ""}`]
|
|
385
|
+
: []),
|
|
370
386
|
...(last?.skipped
|
|
371
387
|
? [`skipped ${last.skipped.at.slice(0, 16).replace("T", " ")}: ${last.skipped.why}`]
|
|
372
388
|
: []),
|
package/dist/entities/index.d.ts
CHANGED
|
@@ -3979,7 +3979,15 @@ export declare const ENTITIES: {
|
|
|
3979
3979
|
readonly error_code: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
3980
3980
|
readonly failing_since: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
|
|
3981
3981
|
readonly failures: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
3982
|
+
readonly cost_usd: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
3983
|
+
readonly skipped: v.OptionalSchema<v.StrictObjectSchema<{
|
|
3984
|
+
readonly at: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
|
|
3985
|
+
readonly why: v.StringSchema<undefined>;
|
|
3986
|
+
}, undefined>, undefined>;
|
|
3982
3987
|
}, undefined>, undefined>;
|
|
3988
|
+
readonly spent_today_usd: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
3989
|
+
readonly max_cost_usd: v.OptionalSchema<v.NullableSchema<v.NumberSchema<undefined>, undefined>, undefined>;
|
|
3990
|
+
readonly max_cost_per_day_usd: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
3983
3991
|
}, undefined>;
|
|
3984
3992
|
readonly call_record: v.StrictObjectSchema<{
|
|
3985
3993
|
readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
|
|
@@ -57,7 +57,19 @@ export declare const scheduledJob: v.StrictObjectSchema<{
|
|
|
57
57
|
readonly error_code: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
58
58
|
readonly failing_since: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
|
|
59
59
|
readonly failures: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
60
|
+
readonly cost_usd: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
61
|
+
/** The last time a run did not start, and why: the day's cost cap, or too little new mail. */
|
|
62
|
+
readonly skipped: v.OptionalSchema<v.StrictObjectSchema<{
|
|
63
|
+
readonly at: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
|
|
64
|
+
readonly why: v.StringSchema<undefined>;
|
|
65
|
+
}, undefined>, undefined>;
|
|
60
66
|
}, undefined>, undefined>;
|
|
67
|
+
/** Agent schedules: what today's runs cost, in US dollars. */
|
|
68
|
+
readonly spent_today_usd: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
69
|
+
/** Agent schedules: the cap on one run (`--max-cost`), null when none. */
|
|
70
|
+
readonly max_cost_usd: v.OptionalSchema<v.NullableSchema<v.NumberSchema<undefined>, undefined>, undefined>;
|
|
71
|
+
/** Agent schedules: the daily cap in force, the schedule's `--max-cost-per-day` or the config's; 0 for none. */
|
|
72
|
+
readonly max_cost_per_day_usd: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
61
73
|
}, undefined>;
|
|
62
74
|
export declare const botTemplate: v.StrictObjectSchema<{
|
|
63
75
|
readonly name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
@@ -41,7 +41,16 @@ export const scheduledJob = v.strictObject({
|
|
|
41
41
|
error_code: v.optional(text),
|
|
42
42
|
failing_since: v.optional(time),
|
|
43
43
|
failures: v.optional(v.number()),
|
|
44
|
+
cost_usd: v.optional(v.number()),
|
|
45
|
+
/** The last time a run did not start, and why: the day's cost cap, or too little new mail. */
|
|
46
|
+
skipped: v.optional(v.strictObject({ at: time, why: text })),
|
|
44
47
|
})),
|
|
48
|
+
/** Agent schedules: what today's runs cost, in US dollars. */
|
|
49
|
+
spent_today_usd: v.optional(v.number()),
|
|
50
|
+
/** Agent schedules: the cap on one run (`--max-cost`), null when none. */
|
|
51
|
+
max_cost_usd: v.optional(v.nullable(v.number())),
|
|
52
|
+
/** Agent schedules: the daily cap in force, the schedule's `--max-cost-per-day` or the config's; 0 for none. */
|
|
53
|
+
max_cost_per_day_usd: v.optional(v.number()),
|
|
45
54
|
});
|
|
46
55
|
export const botTemplate = v.strictObject({
|
|
47
56
|
name: v.nullable(text),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wirecat/cli-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.584.0",
|
|
4
4
|
"description": "The messenger-neutral half of a messaging CLI: domain model, message locators, rendering, name resolution, the SQLite seam, the command skeleton and shared read commands, the send guard, run records and the message store",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Viacheslav Ptsarev",
|