@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
package/dist/state.d.ts
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { type GitRunner } from '@openagt/agent-data';
|
|
2
|
+
import { type Publish } from '@openagt/agent-runner';
|
|
3
|
+
import { type AgentName } from './names.js';
|
|
4
|
+
import { type ScheduledCommand } from './schedule.js';
|
|
5
|
+
import type { PacePick } from './pace.js';
|
|
6
|
+
/**
|
|
7
|
+
* The tool's state (#1774): one JSON file under `.scheduler/` at the repository root,
|
|
8
|
+
* written by the tool and read by anyone — a dashboard shows it as it is. Per user, never
|
|
9
|
+
* tracked: the directory is hidden through the repository's exclude file, the way `.branches/`
|
|
10
|
+
* is, so no tracked file changes and nothing rides a sweeping `git add -A`.
|
|
11
|
+
*
|
|
12
|
+
* What is here is what would otherwise live in a process's memory: whether the scheduler is on,
|
|
13
|
+
* whether it should outlive whatever started it, the model this user's scheduled runs start on
|
|
14
|
+
* and the spend cushion they take, which scheduled commands this machine switched on, the pace and the number of agents at once a person set for one here, how far this machine's runs of a scheduled command publish where a person picked it, the pid of the scheduler's own process when one runs, and the last tick with what it
|
|
15
|
+
* decided per command. A restart loses nothing.
|
|
16
|
+
*/
|
|
17
|
+
/** What the tick decided for one command. */
|
|
18
|
+
export interface TickDecision {
|
|
19
|
+
command: string;
|
|
20
|
+
/** One line, for a person: `started`, `not due`, `cap reached (…)`, `quota: …`, … */
|
|
21
|
+
outcome: string;
|
|
22
|
+
/** The run's id, when one was started or resumed. */
|
|
23
|
+
run?: string;
|
|
24
|
+
}
|
|
25
|
+
/** One command of the schedule as the tick read it, for a dashboard to list with its switch. */
|
|
26
|
+
export interface ListedCommand {
|
|
27
|
+
command: string;
|
|
28
|
+
/** How often at most, as written (`1d`). */
|
|
29
|
+
every?: string;
|
|
30
|
+
/** The check, when the skill gives one. */
|
|
31
|
+
when?: string;
|
|
32
|
+
/** What the check waits for, in one plain line, when the skill gives one. */
|
|
33
|
+
waitsFor?: string;
|
|
34
|
+
/** How often the check runs between the minute's ticks, as written (`15s`), when the skill says. */
|
|
35
|
+
checkEvery?: string;
|
|
36
|
+
/** What the command's skill does, in the skill's own words, when it says. */
|
|
37
|
+
description?: string;
|
|
38
|
+
/** Whether the row resumes the runs its check names, each on its own coding agent and model, and starts none. */
|
|
39
|
+
resumes?: true;
|
|
40
|
+
/** How many runs of the command its skill lets be in flight at once, when it is more than one. */
|
|
41
|
+
agents?: number;
|
|
42
|
+
/** Whether the command is an automation a person keeps on this machine alone, not a skill of the project. */
|
|
43
|
+
onThisMachine?: true;
|
|
44
|
+
/** Whether the command is a person's own automation as the tool wrote it: `show`, `edit` and `remove` take it. */
|
|
45
|
+
editable?: true;
|
|
46
|
+
/** The coding agent the command is made for: the one its skill names, else Claude Code when it can run the command, else the one that can. */
|
|
47
|
+
agent: AgentName;
|
|
48
|
+
/** The model its skill names, when it names one. */
|
|
49
|
+
model?: string;
|
|
50
|
+
/** The coding agent that model is a model of: the one the skill names, Claude Code when it names none. Said with the model. */
|
|
51
|
+
modelAgent?: AgentName;
|
|
52
|
+
/** The coding agents that can run the command: those whose own skills folder holds its skill; every one for an automation kept on this machine. */
|
|
53
|
+
able: AgentName[];
|
|
54
|
+
}
|
|
55
|
+
/** One tick as the state remembers it. */
|
|
56
|
+
export interface TickRecord {
|
|
57
|
+
/** ISO timestamp. */
|
|
58
|
+
at: string;
|
|
59
|
+
decisions: TickDecision[];
|
|
60
|
+
/** The schedule's commands, as this tick read them. */
|
|
61
|
+
schedule: ListedCommand[];
|
|
62
|
+
/** Why the tick decided nothing for the scheduled commands, when it could not: the scheduler is off, no skill schedules a command, the pull failed. */
|
|
63
|
+
note?: string;
|
|
64
|
+
}
|
|
65
|
+
export interface State {
|
|
66
|
+
/** Whether ticks start agents. Off is the default: nothing runs until a person says so. */
|
|
67
|
+
on: boolean;
|
|
68
|
+
/** Whether the scheduler's process outlives whatever started it. Read by `stop --unless-keep-alive` only, the line a dashboard runs when it closes. */
|
|
69
|
+
keepAlive: boolean;
|
|
70
|
+
/** The model a scheduled run on Claude Code starts on, where neither its command's skill nor a person names another. */
|
|
71
|
+
model: string;
|
|
72
|
+
/** How far past the spend boundary a run may still start, in percentage points. */
|
|
73
|
+
spendOffset: number;
|
|
74
|
+
/** The scheduled commands this machine switched on, each with when it was, ISO. Every command starts switched off: a skill that arrives in a project starts no agent by itself. */
|
|
75
|
+
switches?: Record<string, string>;
|
|
76
|
+
/** This machine's publish pick per command. */
|
|
77
|
+
publishes?: Record<string, PublishPick>;
|
|
78
|
+
/** This machine's pace per command, kept only where a person set one: a command without one runs at its skill's pace. */
|
|
79
|
+
paces?: Record<string, PacePick>;
|
|
80
|
+
/** This machine's number of runs of a command in flight at once, kept only where a person set one: a command without one has its skill's number. */
|
|
81
|
+
agents?: Record<string, number>;
|
|
82
|
+
/** The coding agent this machine's runs of a command are on, kept only where a person picked one: a command without one is on the agent its skill is made for. */
|
|
83
|
+
runsOn?: Record<string, AgentName>;
|
|
84
|
+
/** The model this machine's runs of a command start on, kept only where a person picked one, with the coding agent it was picked for: a model is one agent's, and the pick holds only while the command runs on that agent. */
|
|
85
|
+
models?: Record<string, ModelPick>;
|
|
86
|
+
/** The scheduler's own process, while `start` has one running. */
|
|
87
|
+
pid?: number;
|
|
88
|
+
/** When that process started, ISO. */
|
|
89
|
+
startedAt?: string;
|
|
90
|
+
lastTick?: TickRecord;
|
|
91
|
+
}
|
|
92
|
+
/** A person's pick of how far a scheduled command's runs publish on their machine: nothing, or one of the levels a run may be given. */
|
|
93
|
+
export type PublishPick = 'nothing' | Publish;
|
|
94
|
+
export declare const PUBLISH_PICKS: readonly PublishPick[];
|
|
95
|
+
/** A person's pick of a model for one command: the model's id, and the coding agent it is a model of. */
|
|
96
|
+
export interface ModelPick {
|
|
97
|
+
agent: AgentName;
|
|
98
|
+
model: string;
|
|
99
|
+
}
|
|
100
|
+
export declare const DEFAULT_STATE: State;
|
|
101
|
+
export declare function stateDir(repo: string): string;
|
|
102
|
+
export declare function statePath(repo: string): string;
|
|
103
|
+
/** The state as written, defaults filled in; the default state when there is none or it does not parse. */
|
|
104
|
+
export declare function readState(repo: string): Promise<State>;
|
|
105
|
+
/**
|
|
106
|
+
* Write the state. The first write also hides the directory from git; that is best-effort, since
|
|
107
|
+
* a repository whose exclude file cannot be written still has a scheduler.
|
|
108
|
+
*/
|
|
109
|
+
export declare function writeState(repo: string, state: State, git?: GitRunner): Promise<void>;
|
|
110
|
+
/**
|
|
111
|
+
* The state without the scheduler's process, when that process is `pid`; unchanged otherwise. A
|
|
112
|
+
* scheduler ending must not clear a pid another scheduler wrote meanwhile: a dashboard's close
|
|
113
|
+
* hook stops one and its open hook starts the next while the first still finishes its tick.
|
|
114
|
+
*/
|
|
115
|
+
export declare function withoutPid(state: State, pid: number): State;
|
|
116
|
+
/**
|
|
117
|
+
* The state with nothing of one command left: its switch, its publish pick, its pace, its number
|
|
118
|
+
* of agents, its coding agent and its model. What a command saved anew under a name starts from: a switch left on for a
|
|
119
|
+
* command of that name that is gone would start the new one unasked.
|
|
120
|
+
*/
|
|
121
|
+
export declare function withoutCommand(state: State, command: string): State;
|
|
122
|
+
/**
|
|
123
|
+
* The state with a command off the last tick's record: the schedule it read and what it decided.
|
|
124
|
+
* For a command removed since that tick, so whoever lists the record's commands, a dashboard,
|
|
125
|
+
* stops listing it at once and not a tick later. The state itself is answered when the record
|
|
126
|
+
* names no such command.
|
|
127
|
+
*/
|
|
128
|
+
export declare function withoutListed(state: State, command: string): State;
|
|
129
|
+
/**
|
|
130
|
+
* The names whose picks on this machine go before a tick: an automation kept here that the last
|
|
131
|
+
* tick listed and whose file is gone now (removed or renamed), and a name a skill and an
|
|
132
|
+
* automation kept here both have. A switch left under such a name would otherwise start whatever
|
|
133
|
+
* takes the name next: a skill of the project, which starts no agent before a person switches it on.
|
|
134
|
+
* An automation whose file is still there keeps its picks, also while a slip in the file keeps it
|
|
135
|
+
* off the list.
|
|
136
|
+
*/
|
|
137
|
+
export declare function namesGivenUp(lastTick: TickRecord | undefined, schedule: {
|
|
138
|
+
commands: {
|
|
139
|
+
name: string;
|
|
140
|
+
text?: string;
|
|
141
|
+
}[];
|
|
142
|
+
unreadable?: {
|
|
143
|
+
skill: string;
|
|
144
|
+
own?: true;
|
|
145
|
+
}[];
|
|
146
|
+
clashes?: string[];
|
|
147
|
+
}): string[];
|
|
148
|
+
/** The state with nothing left under a name: the picks of the command of that name, and of every command that is that name and a word (`triage quick`). */
|
|
149
|
+
export declare function withoutName(state: State, name: string): State;
|
|
150
|
+
/** When a person switched a scheduled command on on this machine, ISO; nothing for a command that is off. The state is a file a person may edit: anything but a time is off. */
|
|
151
|
+
export declare function switchedOnAt(state: State, command: string): string | undefined;
|
|
152
|
+
/** Whether a scheduled command runs on this machine: only where a person switched it on. */
|
|
153
|
+
export declare function isSwitchedOn(state: State, command: string): boolean;
|
|
154
|
+
/** The state with one command switched on at a time, or off when no time is given: only a command switched on is kept, so switching it off leaves no trace. */
|
|
155
|
+
export declare function withSwitch(state: State, command: string, at: string | undefined): State;
|
|
156
|
+
/** How far a run of a scheduled command publishes on this machine: its publish pick here; absent for nothing. */
|
|
157
|
+
export declare function publishInForce(state: State, command: string): Publish | undefined;
|
|
158
|
+
/** The state with one command's publish pick set. */
|
|
159
|
+
export declare function withPublish(state: State, command: string, pick: PublishPick): State;
|
|
160
|
+
/** The state with one command's pace set, or taken back when there is none: the command then runs at its skill's pace again. */
|
|
161
|
+
export declare function withPace(state: State, command: string, pick: PacePick | undefined): State;
|
|
162
|
+
/**
|
|
163
|
+
* How many runs of a command may be in flight at once, as this machine counts: the number a
|
|
164
|
+
* person set here, else the skill's. The count it is held against is every machine's runs. The
|
|
165
|
+
* state is a file a person may edit: a value that is no such number is no number set.
|
|
166
|
+
*/
|
|
167
|
+
export declare function capInForce(state: State, command: {
|
|
168
|
+
name: string;
|
|
169
|
+
cap: number;
|
|
170
|
+
}): number;
|
|
171
|
+
/** The state with one command's number of agents at once set, or taken back when there is none: the command then has its skill's number again. */
|
|
172
|
+
export declare function withAgents(state: State, command: string, count: number | undefined): State;
|
|
173
|
+
/**
|
|
174
|
+
* The coding agent a run of a command is on, on this machine: the one a person picked here, else
|
|
175
|
+
* the one the command is made for ({@link homeAgent}). The state is a file a person may edit: a
|
|
176
|
+
* word that names no agent is no pick.
|
|
177
|
+
*/
|
|
178
|
+
export declare function agentInForce(state: State, command: Pick<ScheduledCommand, 'name' | 'agent' | 'dirs' | 'text'>): AgentName;
|
|
179
|
+
/**
|
|
180
|
+
* The model a run of a command starts on, on this machine, given the agent it is on: the one a
|
|
181
|
+
* person picked here for that agent; else the one its skill names for that agent
|
|
182
|
+
* ({@link ScheduledCommand.model}); else, on Claude Code, the scheduler's own model. Nothing on
|
|
183
|
+
* any other agent: the run then starts on that agent's own default. A pick made for another agent
|
|
184
|
+
* is no pick: the agent a command runs on can change without a person's doing, when its skill
|
|
185
|
+
* comes to name one or reaches another agent's folder.
|
|
186
|
+
*/
|
|
187
|
+
export declare function modelInForce(state: State, command: Pick<ScheduledCommand, 'name' | 'agent' | 'model'>, agent: AgentName): string | undefined;
|
|
188
|
+
/** The state with the coding agent of one command picked, or the pick taken back when there is none. The model picked for the command goes with it either way: a model is one agent's. */
|
|
189
|
+
export declare function withAgent(state: State, command: string, agent: AgentName | undefined): State;
|
|
190
|
+
/** The state with the model of one command picked, for the coding agent it is a model of, or the pick taken back when there is none. */
|
|
191
|
+
export declare function withModel(state: State, command: string, pick: ModelPick | undefined): State;
|
|
192
|
+
/** Read, change, write: one edit of the state. */
|
|
193
|
+
export declare function updateState(repo: string, change: (state: State) => State, git?: GitRunner): Promise<State>;
|
|
194
|
+
//# sourceMappingURL=state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"}
|
package/dist/state.js
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { excludeFromGit, nodeGitRunner } from '@openagt/agent-data';
|
|
4
|
+
import { PUBLISH_LEVELS } from '@openagt/agent-runner';
|
|
5
|
+
import { DEFAULT_AGENT, DEFAULT_MODEL, DEFAULT_PUBLISH, DEFAULT_SPEND_OFFSET, STATE_DIR, STATE_FILE, isAgent, isAgents, isTime } from './names.js';
|
|
6
|
+
import { homeAgent } from './schedule.js';
|
|
7
|
+
export const PUBLISH_PICKS = ['nothing', ...PUBLISH_LEVELS];
|
|
8
|
+
/** Where the state keeps what a person set for one command on this machine. */
|
|
9
|
+
const PICKS = ['switches', 'publishes', 'paces', 'agents', 'runsOn', 'models'];
|
|
10
|
+
export const DEFAULT_STATE = { on: false, keepAlive: false, model: DEFAULT_MODEL, spendOffset: DEFAULT_SPEND_OFFSET };
|
|
11
|
+
export function stateDir(repo) {
|
|
12
|
+
return join(repo, STATE_DIR);
|
|
13
|
+
}
|
|
14
|
+
export function statePath(repo) {
|
|
15
|
+
return join(stateDir(repo), STATE_FILE);
|
|
16
|
+
}
|
|
17
|
+
/** The state as written, defaults filled in; the default state when there is none or it does not parse. */
|
|
18
|
+
export async function readState(repo) {
|
|
19
|
+
const raw = await readFile(statePath(repo), 'utf8').catch(() => undefined);
|
|
20
|
+
if (raw === undefined)
|
|
21
|
+
return { ...DEFAULT_STATE };
|
|
22
|
+
try {
|
|
23
|
+
const parsed = JSON.parse(raw);
|
|
24
|
+
return { ...DEFAULT_STATE, ...(parsed && typeof parsed === 'object' ? parsed : {}) };
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return { ...DEFAULT_STATE };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Write the state. The first write also hides the directory from git; that is best-effort, since
|
|
32
|
+
* a repository whose exclude file cannot be written still has a scheduler.
|
|
33
|
+
*/
|
|
34
|
+
export async function writeState(repo, state, git = nodeGitRunner()) {
|
|
35
|
+
await mkdir(stateDir(repo), { recursive: true });
|
|
36
|
+
await excludeFromGit(repo, `/${STATE_DIR}`, undefined, git).catch(() => { });
|
|
37
|
+
await writeFile(statePath(repo), JSON.stringify(state, null, 2) + '\n');
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The state without the scheduler's process, when that process is `pid`; unchanged otherwise. A
|
|
41
|
+
* scheduler ending must not clear a pid another scheduler wrote meanwhile: a dashboard's close
|
|
42
|
+
* hook stops one and its open hook starts the next while the first still finishes its tick.
|
|
43
|
+
*/
|
|
44
|
+
export function withoutPid(state, pid) {
|
|
45
|
+
if (state.pid !== pid)
|
|
46
|
+
return state;
|
|
47
|
+
const { pid: _pid, startedAt: _startedAt, ...rest } = state;
|
|
48
|
+
return rest;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The state with nothing of one command left: its switch, its publish pick, its pace, its number
|
|
52
|
+
* of agents, its coding agent and its model. What a command saved anew under a name starts from: a switch left on for a
|
|
53
|
+
* command of that name that is gone would start the new one unasked.
|
|
54
|
+
*/
|
|
55
|
+
export function withoutCommand(state, command) {
|
|
56
|
+
let rest = state;
|
|
57
|
+
for (const key of PICKS) {
|
|
58
|
+
const picks = state[key];
|
|
59
|
+
if (!picks || !Object.hasOwn(picks, command))
|
|
60
|
+
continue;
|
|
61
|
+
const { [command]: _gone, ...others } = picks;
|
|
62
|
+
// The state itself is answered when it holds nothing of the command, so a caller can tell there is nothing to write.
|
|
63
|
+
rest = { ...rest };
|
|
64
|
+
if (Object.keys(others).length)
|
|
65
|
+
Object.assign(rest, { [key]: others });
|
|
66
|
+
else
|
|
67
|
+
delete rest[key];
|
|
68
|
+
}
|
|
69
|
+
return rest;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The state with a command off the last tick's record: the schedule it read and what it decided.
|
|
73
|
+
* For a command removed since that tick, so whoever lists the record's commands, a dashboard,
|
|
74
|
+
* stops listing it at once and not a tick later. The state itself is answered when the record
|
|
75
|
+
* names no such command.
|
|
76
|
+
*/
|
|
77
|
+
export function withoutListed(state, command) {
|
|
78
|
+
const tick = state.lastTick;
|
|
79
|
+
if (!tick || !(tick.schedule.some(c => c.command === command) || tick.decisions.some(d => d.command === command)))
|
|
80
|
+
return state;
|
|
81
|
+
return { ...state, lastTick: { ...tick, schedule: tick.schedule.filter(c => c.command !== command), decisions: tick.decisions.filter(d => d.command !== command) } };
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* The names whose picks on this machine go before a tick: an automation kept here that the last
|
|
85
|
+
* tick listed and whose file is gone now (removed or renamed), and a name a skill and an
|
|
86
|
+
* automation kept here both have. A switch left under such a name would otherwise start whatever
|
|
87
|
+
* takes the name next: a skill of the project, which starts no agent before a person switches it on.
|
|
88
|
+
* An automation whose file is still there keeps its picks, also while a slip in the file keeps it
|
|
89
|
+
* off the list.
|
|
90
|
+
*/
|
|
91
|
+
export function namesGivenUp(lastTick, schedule) {
|
|
92
|
+
const kept = new Set([...schedule.commands.filter(c => c.text !== undefined).map(c => c.name), ...(schedule.unreadable ?? []).filter(u => u.own).map(u => u.skill)]);
|
|
93
|
+
const gone = (lastTick?.schedule ?? []).filter(c => c.onThisMachine === true && !kept.has(c.command)).map(c => c.command);
|
|
94
|
+
return [...new Set([...gone, ...(schedule.clashes ?? [])])];
|
|
95
|
+
}
|
|
96
|
+
/** The state with nothing left under a name: the picks of the command of that name, and of every command that is that name and a word (`triage quick`). */
|
|
97
|
+
export function withoutName(state, name) {
|
|
98
|
+
let rest = state;
|
|
99
|
+
for (const key of PICKS) {
|
|
100
|
+
for (const command of Object.keys(state[key] ?? {})) {
|
|
101
|
+
if (command.split(' ')[0] === name)
|
|
102
|
+
rest = withoutCommand(rest, command);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return rest;
|
|
106
|
+
}
|
|
107
|
+
/** When a person switched a scheduled command on on this machine, ISO; nothing for a command that is off. The state is a file a person may edit: anything but a time is off. */
|
|
108
|
+
export function switchedOnAt(state, command) {
|
|
109
|
+
const at = state.switches?.[command];
|
|
110
|
+
return isTime(at) ? at : undefined;
|
|
111
|
+
}
|
|
112
|
+
/** Whether a scheduled command runs on this machine: only where a person switched it on. */
|
|
113
|
+
export function isSwitchedOn(state, command) {
|
|
114
|
+
return switchedOnAt(state, command) !== undefined;
|
|
115
|
+
}
|
|
116
|
+
/** The state with one command switched on at a time, or off when no time is given: only a command switched on is kept, so switching it off leaves no trace. */
|
|
117
|
+
export function withSwitch(state, command, at) {
|
|
118
|
+
const { [command]: _previous, ...others } = state.switches ?? {};
|
|
119
|
+
const switches = at !== undefined ? { ...others, [command]: at } : others;
|
|
120
|
+
const { switches: _switches, ...rest } = state;
|
|
121
|
+
return Object.keys(switches).length ? { ...rest, switches } : rest;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* This machine's publish pick for a scheduled command: what a person picked here, else commit. The
|
|
125
|
+
* state is a file a person may edit: a word that is no pick is no pick.
|
|
126
|
+
*/
|
|
127
|
+
function publishPick(state, command) {
|
|
128
|
+
const pick = state.publishes?.[command];
|
|
129
|
+
return pick !== undefined && PUBLISH_PICKS.includes(pick) ? pick : DEFAULT_PUBLISH;
|
|
130
|
+
}
|
|
131
|
+
/** How far a run of a scheduled command publishes on this machine: its publish pick here; absent for nothing. */
|
|
132
|
+
export function publishInForce(state, command) {
|
|
133
|
+
const pick = publishPick(state, command);
|
|
134
|
+
return pick === 'nothing' ? undefined : pick;
|
|
135
|
+
}
|
|
136
|
+
/** The state with one command's publish pick set. */
|
|
137
|
+
export function withPublish(state, command, pick) {
|
|
138
|
+
return { ...state, publishes: { ...state.publishes, [command]: pick } };
|
|
139
|
+
}
|
|
140
|
+
/** The state with one command's pace set, or taken back when there is none: the command then runs at its skill's pace again. */
|
|
141
|
+
export function withPace(state, command, pick) {
|
|
142
|
+
const { [command]: _previous, ...others } = state.paces ?? {};
|
|
143
|
+
const paces = pick === undefined ? others : { ...others, [command]: pick };
|
|
144
|
+
const { paces: _paces, ...rest } = state;
|
|
145
|
+
return Object.keys(paces).length ? { ...rest, paces } : rest;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* How many runs of a command may be in flight at once, as this machine counts: the number a
|
|
149
|
+
* person set here, else the skill's. The count it is held against is every machine's runs. The
|
|
150
|
+
* state is a file a person may edit: a value that is no such number is no number set.
|
|
151
|
+
*/
|
|
152
|
+
export function capInForce(state, command) {
|
|
153
|
+
const own = state.agents?.[command.name];
|
|
154
|
+
return isAgents(own) ? own : command.cap;
|
|
155
|
+
}
|
|
156
|
+
/** The state with one command's number of agents at once set, or taken back when there is none: the command then has its skill's number again. */
|
|
157
|
+
export function withAgents(state, command, count) {
|
|
158
|
+
const { [command]: _previous, ...others } = state.agents ?? {};
|
|
159
|
+
const agents = count === undefined ? others : { ...others, [command]: count };
|
|
160
|
+
const { agents: _agents, ...rest } = state;
|
|
161
|
+
return Object.keys(agents).length ? { ...rest, agents } : rest;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* The coding agent a run of a command is on, on this machine: the one a person picked here, else
|
|
165
|
+
* the one the command is made for ({@link homeAgent}). The state is a file a person may edit: a
|
|
166
|
+
* word that names no agent is no pick.
|
|
167
|
+
*/
|
|
168
|
+
export function agentInForce(state, command) {
|
|
169
|
+
const pick = state.runsOn?.[command.name];
|
|
170
|
+
return isAgent(pick) ? pick : homeAgent(command);
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* The model a run of a command starts on, on this machine, given the agent it is on: the one a
|
|
174
|
+
* person picked here for that agent; else the one its skill names for that agent
|
|
175
|
+
* ({@link ScheduledCommand.model}); else, on Claude Code, the scheduler's own model. Nothing on
|
|
176
|
+
* any other agent: the run then starts on that agent's own default. A pick made for another agent
|
|
177
|
+
* is no pick: the agent a command runs on can change without a person's doing, when its skill
|
|
178
|
+
* comes to name one or reaches another agent's folder.
|
|
179
|
+
*/
|
|
180
|
+
export function modelInForce(state, command, agent) {
|
|
181
|
+
const pick = state.models?.[command.name];
|
|
182
|
+
if (pick && typeof pick === 'object' && pick.agent === agent && typeof pick.model === 'string' && pick.model.trim())
|
|
183
|
+
return pick.model;
|
|
184
|
+
if (command.model !== undefined && agent === (command.agent ?? DEFAULT_AGENT))
|
|
185
|
+
return command.model;
|
|
186
|
+
return agent === DEFAULT_AGENT ? state.model : undefined;
|
|
187
|
+
}
|
|
188
|
+
/** The state with the coding agent of one command picked, or the pick taken back when there is none. The model picked for the command goes with it either way: a model is one agent's. */
|
|
189
|
+
export function withAgent(state, command, agent) {
|
|
190
|
+
const { [command]: _previous, ...others } = state.runsOn ?? {};
|
|
191
|
+
const runsOn = agent === undefined ? others : { ...others, [command]: agent };
|
|
192
|
+
const { runsOn: _runsOn, ...rest } = withModel(state, command, undefined);
|
|
193
|
+
return Object.keys(runsOn).length ? { ...rest, runsOn } : rest;
|
|
194
|
+
}
|
|
195
|
+
/** The state with the model of one command picked, for the coding agent it is a model of, or the pick taken back when there is none. */
|
|
196
|
+
export function withModel(state, command, pick) {
|
|
197
|
+
const { [command]: _previous, ...others } = state.models ?? {};
|
|
198
|
+
const models = pick === undefined ? others : { ...others, [command]: pick };
|
|
199
|
+
const { models: _models, ...rest } = state;
|
|
200
|
+
return Object.keys(models).length ? { ...rest, models } : rest;
|
|
201
|
+
}
|
|
202
|
+
/** Read, change, write: one edit of the state. */
|
|
203
|
+
export async function updateState(repo, change, git) {
|
|
204
|
+
const next = change(await readState(repo));
|
|
205
|
+
await writeState(repo, next, git);
|
|
206
|
+
return next;
|
|
207
|
+
}
|
|
208
|
+
//# sourceMappingURL=state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type AnyDiaryLine } from '@openagt/skill-logs';
|
|
2
|
+
/**
|
|
3
|
+
* A project for the tests: one commit on `main`, a bare `origin`, the `agent-data` branch born
|
|
4
|
+
* on origin, a tracked `.claude/skills/work-queue`. Real git, because the records, the checkouts
|
|
5
|
+
* and the reclaim rule are git.
|
|
6
|
+
*/
|
|
7
|
+
export declare const git: import("@openagt/agent-data").GitRunner;
|
|
8
|
+
export declare const RETRIED_RM: {
|
|
9
|
+
readonly recursive: true;
|
|
10
|
+
readonly force: true;
|
|
11
|
+
readonly maxRetries: 10;
|
|
12
|
+
};
|
|
13
|
+
export declare function testRepo(): Promise<string>;
|
|
14
|
+
/** A skill of the project, in the folder Claude Code reads it from, with the lines given as the rest of its front matter. */
|
|
15
|
+
export declare function writeSkill(repo: string, name: string, frontMatter: string): Promise<void>;
|
|
16
|
+
/** The repository and its origin go together. */
|
|
17
|
+
export declare function removeRepo(repo: string): Promise<void>;
|
|
18
|
+
/** A run's diary with each line's time checked and taken off: what is left is what happened. */
|
|
19
|
+
export declare function readUntimedDiary(repo: string, id: string): Promise<AnyDiaryLine[]>;
|
|
20
|
+
//# sourceMappingURL=test-repo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-repo.d.ts","sourceRoot":"","sources":["../src/test-repo.ts"],"names":[],"mappings":"AAKA,OAAO,EAAa,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAElE;;;;GAIG;AAEH,eAAO,MAAM,GAAG,yCAAkB,CAAA;AAElC,eAAO,MAAM,UAAU;aAAK,SAAS;aAAQ,KAAK;aAAQ,UAAU,EAAE,EAAE;CAAW,CAAA;AAEnF,wBAAsB,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,CAwBhD;AAED,6HAA6H;AAC7H,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG/F;AAED,iDAAiD;AACjD,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE5D;AAED,gGAAgG;AAChG,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAMxF"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { mkdir, mkdtemp, realpath, rm, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { tmpdir } from 'node:os';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { strict as assert } from 'node:assert';
|
|
5
|
+
import { DATA_BRANCH, nodeGitRunner, writeSharing } from '@openagt/agent-data';
|
|
6
|
+
import { readDiary } from '@openagt/skill-logs';
|
|
7
|
+
/**
|
|
8
|
+
* A project for the tests: one commit on `main`, a bare `origin`, the `agent-data` branch born
|
|
9
|
+
* on origin, a tracked `.claude/skills/work-queue`. Real git, because the records, the checkouts
|
|
10
|
+
* and the reclaim rule are git.
|
|
11
|
+
*/
|
|
12
|
+
export const git = nodeGitRunner();
|
|
13
|
+
export const RETRIED_RM = { recursive: true, force: true, maxRetries: 10 };
|
|
14
|
+
export async function testRepo() {
|
|
15
|
+
const base = await realpath(await mkdtemp(join(tmpdir(), 'scheduler-')));
|
|
16
|
+
const repo = join(base, 'repo');
|
|
17
|
+
const origin = join(base, 'origin.git');
|
|
18
|
+
await mkdir(repo);
|
|
19
|
+
await git(['init', '-q', '-b', 'main'], repo);
|
|
20
|
+
await git(['config', 'user.email', 'tester@example.com'], repo);
|
|
21
|
+
await git(['config', 'user.name', 'tester'], repo);
|
|
22
|
+
await writeFile(join(repo, 'README.md'), '# t\n');
|
|
23
|
+
await mkdir(join(repo, '.claude', 'skills', 'work-queue'), { recursive: true });
|
|
24
|
+
await writeFile(join(repo, '.claude', 'skills', 'work-queue', 'SKILL.md'), '---\nname: work-queue\n---\nWork one queued task.\n');
|
|
25
|
+
await git(['add', '-A'], repo);
|
|
26
|
+
await git(['commit', '-q', '-m', 'init'], repo);
|
|
27
|
+
await git(['init', '-q', '--bare', origin], base);
|
|
28
|
+
await git(['remote', 'add', 'origin', origin], repo);
|
|
29
|
+
await git(['push', '-q', '-u', 'origin', 'main'], repo);
|
|
30
|
+
// The data branch, parentless, as the skills make it.
|
|
31
|
+
const tree = (await git(['hash-object', '-t', 'tree', '/dev/null'], repo)).trim();
|
|
32
|
+
const commit = (await git(['commit-tree', tree, '-m', `create the ${DATA_BRANCH} branch`], repo)).trim();
|
|
33
|
+
await git(['push', '-q', 'origin', `${commit}:refs/heads/${DATA_BRANCH}`], repo);
|
|
34
|
+
await git(['fetch', '-q', 'origin'], repo);
|
|
35
|
+
// A project that shares its records with origin: the person's yes, given once per clone.
|
|
36
|
+
await writeSharing(repo, true);
|
|
37
|
+
return repo;
|
|
38
|
+
}
|
|
39
|
+
/** A skill of the project, in the folder Claude Code reads it from, with the lines given as the rest of its front matter. */
|
|
40
|
+
export async function writeSkill(repo, name, frontMatter) {
|
|
41
|
+
await mkdir(join(repo, '.claude', 'skills', name), { recursive: true });
|
|
42
|
+
await writeFile(join(repo, '.claude', 'skills', name, 'SKILL.md'), `---\nname: ${name}\n${frontMatter}---\nDo the job.\n`);
|
|
43
|
+
}
|
|
44
|
+
/** The repository and its origin go together. */
|
|
45
|
+
export async function removeRepo(repo) {
|
|
46
|
+
await rm(dirname(repo), RETRIED_RM);
|
|
47
|
+
}
|
|
48
|
+
/** A run's diary with each line's time checked and taken off: what is left is what happened. */
|
|
49
|
+
export async function readUntimedDiary(repo, id) {
|
|
50
|
+
const lines = (await readDiary(repo, id)) ?? assert.fail(`no diary for ${id}`);
|
|
51
|
+
return lines.map(({ at, ...line }) => {
|
|
52
|
+
assert.equal(typeof at === 'string' && new Date(at).toISOString(), at, `a time on ${line.kind}`);
|
|
53
|
+
return line;
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=test-repo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-repo.js","sourceRoot":"","sources":["../src/test-repo.ts"],"names":[],"mappings":"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"}
|