@openagt/skill-scheduler 0.0.0-stage → 0.1.10
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/LICENSE +21 -0
- package/SKILL.md +28 -0
- package/bin/scheduler +11 -0
- package/dist/automation-file.d.ts +61 -0
- package/dist/automation-file.d.ts.map +1 -0
- package/dist/automation-file.js +153 -0
- package/dist/automation-file.js.map +1 -0
- package/dist/automation.d.ts +189 -0
- package/dist/automation.d.ts.map +1 -0
- package/dist/automation.js +237 -0
- package/dist/automation.js.map +1 -0
- package/dist/cleanup.d.ts +31 -0
- package/dist/cleanup.d.ts.map +1 -0
- package/dist/cleanup.js +20 -0
- package/dist/cleanup.js.map +1 -0
- package/dist/cli.d.ts +19 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +416 -0
- package/dist/cli.js.map +1 -0
- package/dist/dashboard/dashboard.css +3 -0
- package/dist/dashboard/dashboard.js +2323 -0
- package/dist/hook-lines.d.ts +11 -0
- package/dist/hook-lines.d.ts.map +1 -0
- package/dist/hook-lines.js +12 -0
- package/dist/hook-lines.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +40 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +95 -0
- package/dist/init.js.map +1 -0
- package/dist/names.d.ts +83 -0
- package/dist/names.d.ts.map +1 -0
- package/dist/names.js +89 -0
- package/dist/names.js.map +1 -0
- package/dist/pace.d.ts +86 -0
- package/dist/pace.d.ts.map +1 -0
- package/dist/pace.js +99 -0
- package/dist/pace.js.map +1 -0
- package/dist/quota-boundary.d.ts +123 -0
- package/dist/quota-boundary.d.ts.map +1 -0
- package/dist/quota-boundary.js +181 -0
- package/dist/quota-boundary.js.map +1 -0
- package/dist/records.d.ts +45 -0
- package/dist/records.d.ts.map +1 -0
- package/dist/records.js +85 -0
- package/dist/records.js.map +1 -0
- package/dist/schedule.d.ts +241 -0
- package/dist/schedule.d.ts.map +1 -0
- package/dist/schedule.js +379 -0
- package/dist/schedule.js.map +1 -0
- package/dist/scheduler.d.ts +75 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/scheduler.js +244 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/start-point.d.ts +40 -0
- package/dist/start-point.d.ts.map +1 -0
- package/dist/start-point.js +88 -0
- package/dist/start-point.js.map +1 -0
- package/dist/state.d.ts +194 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +208 -0
- package/dist/state.js.map +1 -0
- package/dist/test-repo.d.ts +20 -0
- package/dist/test-repo.d.ts.map +1 -0
- package/dist/test-repo.js +56 -0
- package/dist/test-repo.js.map +1 -0
- package/dist/tick.d.ts +119 -0
- package/dist/tick.d.ts.map +1 -0
- package/dist/tick.js +311 -0
- package/dist/tick.js.map +1 -0
- package/dist/write-line.d.ts +38 -0
- package/dist/write-line.d.ts.map +1 -0
- package/dist/write-line.js +121 -0
- package/dist/write-line.js.map +1 -0
- package/package.json +65 -3
- package/README.md +0 -3
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The spend boundary: how much of the account's week unattended work may have spent by now.
|
|
3
|
+
*
|
|
4
|
+
* The boundary is OpenAgent's (its `quota-boundary.ts`, #879/#960), copied here as it is,
|
|
5
|
+
* and the stand-down is this tool's own: the boundary is the pro-rated share of the week's
|
|
6
|
+
* allowance that has elapsed, rising continuously with the clock, and unattended work stands
|
|
7
|
+
* down once a window in force passes it plus the user's cushion. Two properties fall out of it: nothing is left on the floor, since the boundary
|
|
8
|
+
* reaches the full allowance exactly as the week resets; and work a person asks for cannot be
|
|
9
|
+
* starved by work nobody asked for. Copied rather than imported because this tool depends on
|
|
10
|
+
* @openagt/agent-driver-claude, which reads the windows, and not on OpenAgent, which only draws the boundary.
|
|
11
|
+
*/
|
|
12
|
+
import type { DriverQuotaWindow } from '@openagt/agent-driver';
|
|
13
|
+
/** The quota week, in ms. */
|
|
14
|
+
export declare const QUOTA_WEEK_MS: number;
|
|
15
|
+
/** Where the boundary sits, and the week it is derived from. */
|
|
16
|
+
export interface QuotaBoundary {
|
|
17
|
+
/** When the current quota week began, epoch ms. */
|
|
18
|
+
startsAt: number;
|
|
19
|
+
/** When it resets, epoch ms. */
|
|
20
|
+
resetsAt: number;
|
|
21
|
+
/** Which day of the week we are on, 1-7. */
|
|
22
|
+
day: number;
|
|
23
|
+
/** The share of the week's allowance that may be spent by now, 0-100. */
|
|
24
|
+
percent: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Parse the agent's reset prose into an epoch.
|
|
28
|
+
*
|
|
29
|
+
* The agent prints no year (`Jul 25 at 7am (Asia/Jerusalem)`), which is why the
|
|
30
|
+
* driver keeps this as text. It is recoverable here because we know something
|
|
31
|
+
* the driver does not: a *weekly* window resets within seven days, so of the
|
|
32
|
+
* candidate years exactly one lands anywhere near now.
|
|
33
|
+
*
|
|
34
|
+
* `undefined` for anything that does not parse, which the callers treat as "we
|
|
35
|
+
* do not know where the week is" rather than as a boundary of zero.
|
|
36
|
+
*/
|
|
37
|
+
export declare function parseResetsAt(text: string, now: number): number | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Where the boundary sits, given when the week resets.
|
|
40
|
+
*
|
|
41
|
+
* `percent` is continuous — the plain elapsed share of the week (#960 Edit) — rather than a value
|
|
42
|
+
* that jumps once a day, so it always names the actual instant `now` falls on, on any axis that
|
|
43
|
+
* measures the week the same way. A stepped version once unlocked a whole day's allowance the
|
|
44
|
+
* moment a new day began (including the entire week's worth on the last day), which read as
|
|
45
|
+
* generous on paper but let a burst of spending land the instant the clock ticked over rather than
|
|
46
|
+
* pacing with it; continuous keeps the line honest about what has actually elapsed at the cost of
|
|
47
|
+
* that burst.
|
|
48
|
+
*
|
|
49
|
+
* `day` is 1-based and still names which day of the week `now` falls on — for callers that want to
|
|
50
|
+
* say "day 4 of 7" rather than a percentage — and steps at the exact second the week's own day
|
|
51
|
+
* rolls over, independently of `percent`.
|
|
52
|
+
*/
|
|
53
|
+
export declare function boundaryFromResetsAt(resetsAt: number, now: number): QuotaBoundary;
|
|
54
|
+
/** One quota window measured against the boundary. */
|
|
55
|
+
export interface BoundaryWindow {
|
|
56
|
+
/** The window's own label, as the agent phrased it. */
|
|
57
|
+
label: string;
|
|
58
|
+
/** How much of it is gone, 0-100. */
|
|
59
|
+
percentUsed: number;
|
|
60
|
+
/** Whether it has reached the limit in force. */
|
|
61
|
+
reached: boolean;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The line unattended work actually stops at (#960).
|
|
65
|
+
*
|
|
66
|
+
* The boundary is the policy; this is the policy plus whatever the user asked for with the
|
|
67
|
+
* slider. They are separate values because the panel draws both: moving your own limit should
|
|
68
|
+
* not silently redraw the boundary it is measured against.
|
|
69
|
+
*/
|
|
70
|
+
export interface QuotaLimit {
|
|
71
|
+
/** Where the limit sits, 0-100. */
|
|
72
|
+
percent: number;
|
|
73
|
+
/** How far it is from the boundary, in percentage points. `0` is the default policy. */
|
|
74
|
+
offset: number;
|
|
75
|
+
}
|
|
76
|
+
/** Where the account stands against its boundary. */
|
|
77
|
+
export interface QuotaBoundaryStatus {
|
|
78
|
+
boundary: QuotaBoundary;
|
|
79
|
+
/** The line in force, which is the boundary unless the user moved it (#960). */
|
|
80
|
+
limit: QuotaLimit;
|
|
81
|
+
/** The windows in force: the account's week, plus the selected model's own week when we can tell which it is. */
|
|
82
|
+
windows: BoundaryWindow[];
|
|
83
|
+
/** The window that has reached the limit, or `null` while there is room. */
|
|
84
|
+
reached: BoundaryWindow | null;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Measure the account's windows against the boundary (#879).
|
|
88
|
+
*
|
|
89
|
+
* Both weekly windows bind at once — the account's week and, per Rom's edit, the
|
|
90
|
+
* selected model's own week — so each is measured against the same boundary and
|
|
91
|
+
* whichever reaches it first is the one that stops the work. The model's window
|
|
92
|
+
* is only included when we can tell which model it belongs to; an unrecognized
|
|
93
|
+
* one is left out rather than allowed to stop work for a model nobody selected.
|
|
94
|
+
*
|
|
95
|
+
* `undefined` when there is no reading, or when the week's reset cannot be
|
|
96
|
+
* placed. That is "we do not know", and each caller decides what to do with it:
|
|
97
|
+
* the per-agent guard carries on, unattended work stands down.
|
|
98
|
+
*/
|
|
99
|
+
export declare function quotaBoundaryStatus(input: {
|
|
100
|
+
windows: DriverQuotaWindow[];
|
|
101
|
+
now: number;
|
|
102
|
+
/** The model the work will run on, e.g. `claude-fable-5`. Its own week joins the gate when given. */
|
|
103
|
+
model?: string;
|
|
104
|
+
/**
|
|
105
|
+
* How far the automatic-consumption limit sits from the boundary, in percentage points (#960).
|
|
106
|
+
* Omitted or `0` is the spend-boundary policy (#879): the limit *is* the boundary.
|
|
107
|
+
*/
|
|
108
|
+
limitOffset?: number;
|
|
109
|
+
}): QuotaBoundaryStatus | undefined;
|
|
110
|
+
/** Whether a run may start against the boundary, and the one line that says why not. */
|
|
111
|
+
export type QuotaDecision = {
|
|
112
|
+
start: true;
|
|
113
|
+
} | {
|
|
114
|
+
start: false;
|
|
115
|
+
reason: string;
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* The gate the tick asks before it spends: no reading, or a week the reader cannot place, is
|
|
119
|
+
* "we do not know", and unattended work stands down on not knowing. A reached window names the
|
|
120
|
+
* line it stopped at, the offset included, so a stand-down reads as a setting and not as a bug.
|
|
121
|
+
*/
|
|
122
|
+
export declare function quotaHeadroom(quota: QuotaBoundaryStatus | undefined): QuotaDecision;
|
|
123
|
+
//# sourceMappingURL=quota-boundary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quota-boundary.d.ts","sourceRoot":"","sources":["../src/quota-boundary.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAE9D,6BAA6B;AAC7B,eAAO,MAAM,aAAa,QAA0B,CAAA;AAQpD,gEAAgE;AAChE,MAAM,WAAW,aAAa;IAC5B,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAA;IAChB,gCAAgC;IAChC,QAAQ,EAAE,MAAM,CAAA;IAChB,4CAA4C;IAC5C,GAAG,EAAE,MAAM,CAAA;IACX,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAA;CAChB;AAuCD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CA6B3E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,aAAa,CAKjF;AAED,sDAAsD;AACtD,MAAM,WAAW,cAAc;IAC7B,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAA;IACb,qCAAqC;IACrC,WAAW,EAAE,MAAM,CAAA;IACnB,iDAAiD;IACjD,OAAO,EAAE,OAAO,CAAA;CACjB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAA;IACf,wFAAwF;IACxF,MAAM,EAAE,MAAM,CAAA;CACf;AAED,qDAAqD;AACrD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,aAAa,CAAA;IACvB,gFAAgF;IAChF,KAAK,EAAE,UAAU,CAAA;IACjB,iHAAiH;IACjH,OAAO,EAAE,cAAc,EAAE,CAAA;IACzB,4EAA4E;IAC5E,OAAO,EAAE,cAAc,GAAG,IAAI,CAAA;CAC/B;AAOD;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,OAAO,EAAE,iBAAiB,EAAE,CAAA;IAC5B,GAAG,EAAE,MAAM,CAAA;IACX,qGAAqG;IACrG,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,GAAG,mBAAmB,GAAG,SAAS,CA0BlC;AAED,wFAAwF;AACxF,MAAM,MAAM,aAAa,GAAG;IAAE,KAAK,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAE9E;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,mBAAmB,GAAG,SAAS,GAAG,aAAa,CAUnF"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The spend boundary: how much of the account's week unattended work may have spent by now.
|
|
3
|
+
*
|
|
4
|
+
* The boundary is OpenAgent's (its `quota-boundary.ts`, #879/#960), copied here as it is,
|
|
5
|
+
* and the stand-down is this tool's own: the boundary is the pro-rated share of the week's
|
|
6
|
+
* allowance that has elapsed, rising continuously with the clock, and unattended work stands
|
|
7
|
+
* down once a window in force passes it plus the user's cushion. Two properties fall out of it: nothing is left on the floor, since the boundary
|
|
8
|
+
* reaches the full allowance exactly as the week resets; and work a person asks for cannot be
|
|
9
|
+
* starved by work nobody asked for. Copied rather than imported because this tool depends on
|
|
10
|
+
* @openagt/agent-driver-claude, which reads the windows, and not on OpenAgent, which only draws the boundary.
|
|
11
|
+
*/
|
|
12
|
+
/** The quota week, in ms. */
|
|
13
|
+
export const QUOTA_WEEK_MS = 7 * 24 * 60 * 60 * 1000;
|
|
14
|
+
/** A day of it, in ms. */
|
|
15
|
+
const ONE_DAY_MS = 24 * 60 * 60 * 1000;
|
|
16
|
+
/** Days in the quota week, i.e. the denominator of `n/7`. */
|
|
17
|
+
const WEEK_DAYS = 7;
|
|
18
|
+
const MONTHS = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'];
|
|
19
|
+
/**
|
|
20
|
+
* `Jul 25 at 7am (Asia/Jerusalem)`, with the minutes and the zone both optional. Newer Claude
|
|
21
|
+
* Code prints a comma where older versions print `at` — `Jul 25, 7am` — and both are in the wild.
|
|
22
|
+
*/
|
|
23
|
+
const RESETS_AT = /^([a-z]{3})\s+(\d{1,2})(?:\s+at\s+|,\s*)(\d{1,2})(?::(\d{2}))?\s*(am|pm)\s*(?:\(([^)]+)\))?$/i;
|
|
24
|
+
/** How far `zone` is ahead of UTC at `at`, in ms. */
|
|
25
|
+
function zoneOffsetMs(at, zone) {
|
|
26
|
+
const parts = new Intl.DateTimeFormat('en-US', {
|
|
27
|
+
timeZone: zone,
|
|
28
|
+
hour12: false,
|
|
29
|
+
year: 'numeric',
|
|
30
|
+
month: '2-digit',
|
|
31
|
+
day: '2-digit',
|
|
32
|
+
hour: '2-digit',
|
|
33
|
+
minute: '2-digit',
|
|
34
|
+
second: '2-digit',
|
|
35
|
+
}).formatToParts(at);
|
|
36
|
+
const read = (type) => Number(parts.find(p => p.type === type)?.value);
|
|
37
|
+
// `hour: '2-digit'` with hour12 off prints midnight as 24 in some runtimes.
|
|
38
|
+
const hour = read('hour') % 24;
|
|
39
|
+
const asUtc = Date.UTC(read('year'), read('month') - 1, read('day'), hour, read('minute'), read('second'));
|
|
40
|
+
return asUtc - at;
|
|
41
|
+
}
|
|
42
|
+
/** The epoch of a wall-clock time in `zone`, resolving the offset at that instant rather than now. */
|
|
43
|
+
function zonedTimeToEpoch(year, month, day, hour, minute, zone) {
|
|
44
|
+
const wall = Date.UTC(year, month - 1, day, hour, minute);
|
|
45
|
+
const first = wall - zoneOffsetMs(wall, zone);
|
|
46
|
+
// One correction settles it: the first guess is only wrong when it landed on
|
|
47
|
+
// the far side of a DST change, and the second offset is the right one.
|
|
48
|
+
const second = wall - zoneOffsetMs(first, zone);
|
|
49
|
+
return second;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Parse the agent's reset prose into an epoch.
|
|
53
|
+
*
|
|
54
|
+
* The agent prints no year (`Jul 25 at 7am (Asia/Jerusalem)`), which is why the
|
|
55
|
+
* driver keeps this as text. It is recoverable here because we know something
|
|
56
|
+
* the driver does not: a *weekly* window resets within seven days, so of the
|
|
57
|
+
* candidate years exactly one lands anywhere near now.
|
|
58
|
+
*
|
|
59
|
+
* `undefined` for anything that does not parse, which the callers treat as "we
|
|
60
|
+
* do not know where the week is" rather than as a boundary of zero.
|
|
61
|
+
*/
|
|
62
|
+
export function parseResetsAt(text, now) {
|
|
63
|
+
const match = RESETS_AT.exec(text.trim());
|
|
64
|
+
if (!match)
|
|
65
|
+
return undefined;
|
|
66
|
+
const [, monthName, dayText, hourText, minuteText, meridiem, zoneText] = match;
|
|
67
|
+
const month = MONTHS.indexOf((monthName ?? '').toLowerCase()) + 1;
|
|
68
|
+
if (month === 0)
|
|
69
|
+
return undefined;
|
|
70
|
+
const day = Number(dayText);
|
|
71
|
+
const hour12 = Number(hourText);
|
|
72
|
+
if (hour12 < 1 || hour12 > 12)
|
|
73
|
+
return undefined;
|
|
74
|
+
const hour = (hour12 % 12) + ((meridiem ?? '').toLowerCase() === 'pm' ? 12 : 0);
|
|
75
|
+
const minute = minuteText === undefined ? 0 : Number(minuteText);
|
|
76
|
+
const zone = zoneText?.trim() || Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
77
|
+
const nowYear = new Date(now).getUTCFullYear();
|
|
78
|
+
let best;
|
|
79
|
+
for (const year of [nowYear - 1, nowYear, nowYear + 1]) {
|
|
80
|
+
let at;
|
|
81
|
+
try {
|
|
82
|
+
at = zonedTimeToEpoch(year, month, day, hour, minute, zone);
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// An unknown zone name. Nothing to fall back to that wouldn't be a guess.
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
// Feb 29 in a non-leap year rolls into March; that candidate isn't the date
|
|
89
|
+
// the agent printed.
|
|
90
|
+
if (new Date(at + zoneOffsetMs(at, zone)).getUTCDate() !== day)
|
|
91
|
+
continue;
|
|
92
|
+
if (best === undefined || Math.abs(at - now) < Math.abs(best - now))
|
|
93
|
+
best = at;
|
|
94
|
+
}
|
|
95
|
+
return best;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Where the boundary sits, given when the week resets.
|
|
99
|
+
*
|
|
100
|
+
* `percent` is continuous — the plain elapsed share of the week (#960 Edit) — rather than a value
|
|
101
|
+
* that jumps once a day, so it always names the actual instant `now` falls on, on any axis that
|
|
102
|
+
* measures the week the same way. A stepped version once unlocked a whole day's allowance the
|
|
103
|
+
* moment a new day began (including the entire week's worth on the last day), which read as
|
|
104
|
+
* generous on paper but let a burst of spending land the instant the clock ticked over rather than
|
|
105
|
+
* pacing with it; continuous keeps the line honest about what has actually elapsed at the cost of
|
|
106
|
+
* that burst.
|
|
107
|
+
*
|
|
108
|
+
* `day` is 1-based and still names which day of the week `now` falls on — for callers that want to
|
|
109
|
+
* say "day 4 of 7" rather than a percentage — and steps at the exact second the week's own day
|
|
110
|
+
* rolls over, independently of `percent`.
|
|
111
|
+
*/
|
|
112
|
+
export function boundaryFromResetsAt(resetsAt, now) {
|
|
113
|
+
const startsAt = resetsAt - QUOTA_WEEK_MS;
|
|
114
|
+
const elapsedMs = Math.min(Math.max(now - startsAt, 0), QUOTA_WEEK_MS);
|
|
115
|
+
const day = Math.min(WEEK_DAYS, Math.floor(elapsedMs / ONE_DAY_MS) + 1);
|
|
116
|
+
return { startsAt, resetsAt, day, percent: (elapsedMs / QUOTA_WEEK_MS) * 100 };
|
|
117
|
+
}
|
|
118
|
+
/** The model name a `week-model` window is about, e.g. `Current week (Fable)` -> `fable`. */
|
|
119
|
+
function windowModel(label) {
|
|
120
|
+
return /\(([^)]+)\)/.exec(label)?.[1]?.trim().toLowerCase();
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Measure the account's windows against the boundary (#879).
|
|
124
|
+
*
|
|
125
|
+
* Both weekly windows bind at once — the account's week and, per Rom's edit, the
|
|
126
|
+
* selected model's own week — so each is measured against the same boundary and
|
|
127
|
+
* whichever reaches it first is the one that stops the work. The model's window
|
|
128
|
+
* is only included when we can tell which model it belongs to; an unrecognized
|
|
129
|
+
* one is left out rather than allowed to stop work for a model nobody selected.
|
|
130
|
+
*
|
|
131
|
+
* `undefined` when there is no reading, or when the week's reset cannot be
|
|
132
|
+
* placed. That is "we do not know", and each caller decides what to do with it:
|
|
133
|
+
* the per-agent guard carries on, unattended work stands down.
|
|
134
|
+
*/
|
|
135
|
+
export function quotaBoundaryStatus(input) {
|
|
136
|
+
const week = input.windows.find(w => w.kind === 'week');
|
|
137
|
+
if (!week?.resetsAtText)
|
|
138
|
+
return undefined;
|
|
139
|
+
const resetsAt = parseResetsAt(week.resetsAtText, input.now);
|
|
140
|
+
if (resetsAt === undefined)
|
|
141
|
+
return undefined;
|
|
142
|
+
const boundary = boundaryFromResetsAt(resetsAt, input.now);
|
|
143
|
+
const model = input.model?.toLowerCase();
|
|
144
|
+
const inForce = input.windows.filter(w => {
|
|
145
|
+
if (w.kind === 'week')
|
|
146
|
+
return true;
|
|
147
|
+
if (w.kind !== 'week-model' || !model)
|
|
148
|
+
return false;
|
|
149
|
+
const name = windowModel(w.label);
|
|
150
|
+
return name !== undefined && model.includes(name);
|
|
151
|
+
});
|
|
152
|
+
// Clamped, so a limit dragged past either end of the week stops at the week rather than
|
|
153
|
+
// becoming unreachable (which would read as "never stop") or negative (as "always stopped").
|
|
154
|
+
const offset = input.limitOffset ?? 0;
|
|
155
|
+
const limit = { percent: Math.min(Math.max(boundary.percent + offset, 0), 100), offset };
|
|
156
|
+
const windows = inForce.map(w => ({
|
|
157
|
+
label: w.label,
|
|
158
|
+
percentUsed: w.percentUsed,
|
|
159
|
+
reached: w.percentUsed >= limit.percent,
|
|
160
|
+
}));
|
|
161
|
+
return { boundary, limit, windows, reached: windows.find(w => w.reached) ?? null };
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* The gate the tick asks before it spends: no reading, or a week the reader cannot place, is
|
|
165
|
+
* "we do not know", and unattended work stands down on not knowing. A reached window names the
|
|
166
|
+
* line it stopped at, the offset included, so a stand-down reads as a setting and not as a bug.
|
|
167
|
+
*/
|
|
168
|
+
export function quotaHeadroom(quota) {
|
|
169
|
+
if (!quota)
|
|
170
|
+
return { start: false, reason: 'the quota could not be read, so there is no way to tell what is spare' };
|
|
171
|
+
const reached = quota.reached;
|
|
172
|
+
if (!reached)
|
|
173
|
+
return { start: true };
|
|
174
|
+
const { limit, boundary } = quota;
|
|
175
|
+
const offsetText = `${limit.offset > 0 ? '+' : ''}${Math.round(limit.offset * 10) / 10}`;
|
|
176
|
+
const line = limit.offset === 0
|
|
177
|
+
? `the week's ${Math.round(boundary.percent)}%`
|
|
178
|
+
: `the ${Math.round(limit.percent)}% line (${offsetText} on the week's ${Math.round(boundary.percent)}%)`;
|
|
179
|
+
return { start: false, reason: `${reached.label} is ${Math.round(reached.percentUsed)}% used, at or past day ${boundary.day} of ${line}` };
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=quota-boundary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quota-boundary.js","sourceRoot":"","sources":["../src/quota-boundary.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type LogsDeps, type RunCard } from '@openagt/skill-logs';
|
|
2
|
+
import { type Schedule } from './schedule.js';
|
|
3
|
+
/**
|
|
4
|
+
* The runs a command has, read off the run records on the project's `agent-data` branch, so
|
|
5
|
+
* every machine that shares the branch counts the same ones against a command's cap and pace. A
|
|
6
|
+
* record names only what its run was asked; which command of the schedule that is, is decided
|
|
7
|
+
* here when the records are counted: the scheduled command the prompt names, else the prompt's first
|
|
8
|
+
* word without its slash. A run a person started from a dashboard counts like a scheduled one.
|
|
9
|
+
* Only runs `agent-runner` started, which carry its mark, are counted.
|
|
10
|
+
*
|
|
11
|
+
* A run a row resumed counts for that row too, from its resume on: its record keeps who resumed it
|
|
12
|
+
* and when, and the row counts the resume as its start.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* The command a run counts for, as the machine `host` counts; `undefined` for a run
|
|
16
|
+
* `agent-runner` did not start, and for one whose prompt names no command. A run of an automation
|
|
17
|
+
* kept on a machine counts on that machine alone: another person may keep one of the same name,
|
|
18
|
+
* and theirs is another automation.
|
|
19
|
+
*/
|
|
20
|
+
export declare function commandOf(card: RunCard, schedule: Schedule, host: string): string | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* When one command last started, whatever became of the run; nothing when it never did. A skill's
|
|
23
|
+
* command counts every machine's runs; an automation kept on this machine, this machine's. A
|
|
24
|
+
* scheduled run's start is when its command was asked about, before its check ran: the tick gives
|
|
25
|
+
* the run that moment as its start. A record whose start is not a time is not counted.
|
|
26
|
+
*/
|
|
27
|
+
export declare function lastStart(repo: string, command: string, schedule: Schedule, host: string, deps?: LogsDeps): Promise<string | undefined>;
|
|
28
|
+
/** A command's last run, as a dashboard lists it: which run, when it started, and whether it failed. */
|
|
29
|
+
export interface LastRun {
|
|
30
|
+
id: string;
|
|
31
|
+
/** When the run started, ISO. */
|
|
32
|
+
at: string;
|
|
33
|
+
/** Whether the run ended `failed`. */
|
|
34
|
+
failed?: true;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Each command's last run: the latest run it has, by its start, whatever became of it. It says
|
|
38
|
+
* `failed` only when that run ended `failed`: one still going, ended well, stopped by a person or
|
|
39
|
+
* waiting for an answer does not, so a later run takes a failure's place. Counted like the
|
|
40
|
+
* starts: every machine's runs for a skill's command, this machine's for an automation kept here.
|
|
41
|
+
*/
|
|
42
|
+
export declare function lastRuns(repo: string, schedule: Schedule, host: string, deps?: LogsDeps): Promise<Record<string, LastRun>>;
|
|
43
|
+
/** The runs of one command still in flight: on any machine for a skill's command, on this one for an automation kept here and for a row that resumed them. */
|
|
44
|
+
export declare function inFlight(repo: string, command: string, schedule: Schedule, host: string, deps?: LogsDeps): Promise<RunCard[]>;
|
|
45
|
+
//# sourceMappingURL=records.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"records.d.ts","sourceRoot":"","sources":["../src/records.ts"],"names":[],"mappings":"AACA,OAAO,EAAY,KAAK,QAAQ,EAAE,KAAK,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAE3E,OAAO,EAAiB,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAA;AAE5D;;;;;;;;;;GAUG;AAEH;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAO7F;AAeD;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,QAAa,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAQjJ;AAED,wGAAwG;AACxG,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAA;IACV,iCAAiC;IACjC,EAAE,EAAE,MAAM,CAAA;IACV,sCAAsC;IACtC,MAAM,CAAC,EAAE,IAAI,CAAA;CACd;AAED;;;;;GAKG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,QAAa,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAWpI;AAED,8JAA8J;AAC9J,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,QAAa,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAGvI"}
|
package/dist/records.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { runnerMark } from '@openagt/agent-runner';
|
|
2
|
+
import { listRuns } from '@openagt/skill-logs';
|
|
3
|
+
import { isTime } from './names.js';
|
|
4
|
+
import { promptCommand } from './schedule.js';
|
|
5
|
+
/**
|
|
6
|
+
* The runs a command has, read off the run records on the project's `agent-data` branch, so
|
|
7
|
+
* every machine that shares the branch counts the same ones against a command's cap and pace. A
|
|
8
|
+
* record names only what its run was asked; which command of the schedule that is, is decided
|
|
9
|
+
* here when the records are counted: the scheduled command the prompt names, else the prompt's first
|
|
10
|
+
* word without its slash. A run a person started from a dashboard counts like a scheduled one.
|
|
11
|
+
* Only runs `agent-runner` started, which carry its mark, are counted.
|
|
12
|
+
*
|
|
13
|
+
* A run a row resumed counts for that row too, from its resume on: its record keeps who resumed it
|
|
14
|
+
* and when, and the row counts the resume as its start.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* The command a run counts for, as the machine `host` counts; `undefined` for a run
|
|
18
|
+
* `agent-runner` did not start, and for one whose prompt names no command. A run of an automation
|
|
19
|
+
* kept on a machine counts on that machine alone: another person may keep one of the same name,
|
|
20
|
+
* and theirs is another automation.
|
|
21
|
+
*/
|
|
22
|
+
export function commandOf(card, schedule, host) {
|
|
23
|
+
const mark = runnerMark(card);
|
|
24
|
+
if (!mark || card.intent === undefined)
|
|
25
|
+
return undefined;
|
|
26
|
+
const command = promptCommand(card.intent, schedule);
|
|
27
|
+
if (command === undefined)
|
|
28
|
+
return undefined;
|
|
29
|
+
const own = schedule.commands.some(c => c.name === command && c.text !== undefined);
|
|
30
|
+
return own && mark.host !== host ? undefined : command;
|
|
31
|
+
}
|
|
32
|
+
/** The row that last resumed a run, and when, as the machine `host` counts: only its own runs are resumed here. */
|
|
33
|
+
function resumedBy(card, host) {
|
|
34
|
+
const mark = runnerMark(card);
|
|
35
|
+
return mark?.host === host && mark.resumed !== undefined && isTime(mark.resumed.at) ? mark.resumed : undefined;
|
|
36
|
+
}
|
|
37
|
+
/** When a run started for a command, as `host` counts: its own start for the command it was started for, its last resume for the row that resumed it; nothing for any other command. */
|
|
38
|
+
function startFor(card, command, schedule, host) {
|
|
39
|
+
const resumed = resumedBy(card, host);
|
|
40
|
+
if (resumed?.by === command)
|
|
41
|
+
return resumed.at;
|
|
42
|
+
return commandOf(card, schedule, host) === command && isTime(card.startedAt) ? card.startedAt : undefined;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* When one command last started, whatever became of the run; nothing when it never did. A skill's
|
|
46
|
+
* command counts every machine's runs; an automation kept on this machine, this machine's. A
|
|
47
|
+
* scheduled run's start is when its command was asked about, before its check ran: the tick gives
|
|
48
|
+
* the run that moment as its start. A record whose start is not a time is not counted.
|
|
49
|
+
*/
|
|
50
|
+
export async function lastStart(repo, command, schedule, host, deps = {}) {
|
|
51
|
+
const cards = await listRuns(repo, {}, deps);
|
|
52
|
+
let latest;
|
|
53
|
+
for (const card of cards) {
|
|
54
|
+
const at = startFor(card, command, schedule, host);
|
|
55
|
+
if (at !== undefined && (latest === undefined || at > latest))
|
|
56
|
+
latest = at;
|
|
57
|
+
}
|
|
58
|
+
return latest;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Each command's last run: the latest run it has, by its start, whatever became of it. It says
|
|
62
|
+
* `failed` only when that run ended `failed`: one still going, ended well, stopped by a person or
|
|
63
|
+
* waiting for an answer does not, so a later run takes a failure's place. Counted like the
|
|
64
|
+
* starts: every machine's runs for a skill's command, this machine's for an automation kept here.
|
|
65
|
+
*/
|
|
66
|
+
export async function lastRuns(repo, schedule, host, deps = {}) {
|
|
67
|
+
const latest = new Map();
|
|
68
|
+
for (const card of await listRuns(repo, {}, deps)) {
|
|
69
|
+
for (const command of new Set([commandOf(card, schedule, host), resumedBy(card, host)?.by])) {
|
|
70
|
+
const at = command === undefined ? undefined : startFor(card, command, schedule, host);
|
|
71
|
+
if (command === undefined || at === undefined)
|
|
72
|
+
continue;
|
|
73
|
+
const known = latest.get(command);
|
|
74
|
+
if (!known || at > known.at)
|
|
75
|
+
latest.set(command, { id: card.id, at, ...(card.status === 'failed' ? { failed: true } : {}) });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return Object.fromEntries(latest);
|
|
79
|
+
}
|
|
80
|
+
/** The runs of one command still in flight: on any machine for a skill's command, on this one for an automation kept here and for a row that resumed them. */
|
|
81
|
+
export async function inFlight(repo, command, schedule, host, deps = {}) {
|
|
82
|
+
const cards = await listRuns(repo, {}, deps);
|
|
83
|
+
return cards.filter(card => card.status === 'running' && (commandOf(card, schedule, host) === command || resumedBy(card, host)?.by === command));
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=records.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"records.js","sourceRoot":"","sources":["../src/records.ts"],"names":[],"mappings":"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"}
|