@openagt/skill-scheduler 0.0.0-stage → 0.1.11

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.
Files changed (79) hide show
  1. package/LICENSE +21 -0
  2. package/SKILL.md +28 -0
  3. package/bin/scheduler +11 -0
  4. package/dist/automation-file.d.ts +61 -0
  5. package/dist/automation-file.d.ts.map +1 -0
  6. package/dist/automation-file.js +153 -0
  7. package/dist/automation-file.js.map +1 -0
  8. package/dist/automation.d.ts +189 -0
  9. package/dist/automation.d.ts.map +1 -0
  10. package/dist/automation.js +237 -0
  11. package/dist/automation.js.map +1 -0
  12. package/dist/cleanup.d.ts +31 -0
  13. package/dist/cleanup.d.ts.map +1 -0
  14. package/dist/cleanup.js +20 -0
  15. package/dist/cleanup.js.map +1 -0
  16. package/dist/cli.d.ts +19 -0
  17. package/dist/cli.d.ts.map +1 -0
  18. package/dist/cli.js +409 -0
  19. package/dist/cli.js.map +1 -0
  20. package/dist/dashboard/dashboard.css +3 -0
  21. package/dist/dashboard/dashboard.js +2324 -0
  22. package/dist/hook-lines.d.ts +11 -0
  23. package/dist/hook-lines.d.ts.map +1 -0
  24. package/dist/hook-lines.js +12 -0
  25. package/dist/hook-lines.js.map +1 -0
  26. package/dist/index.d.ts +15 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +15 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/init.d.ts +40 -0
  31. package/dist/init.d.ts.map +1 -0
  32. package/dist/init.js +95 -0
  33. package/dist/init.js.map +1 -0
  34. package/dist/names.d.ts +85 -0
  35. package/dist/names.d.ts.map +1 -0
  36. package/dist/names.js +91 -0
  37. package/dist/names.js.map +1 -0
  38. package/dist/pace.d.ts +86 -0
  39. package/dist/pace.d.ts.map +1 -0
  40. package/dist/pace.js +99 -0
  41. package/dist/pace.js.map +1 -0
  42. package/dist/quota-boundary.d.ts +123 -0
  43. package/dist/quota-boundary.d.ts.map +1 -0
  44. package/dist/quota-boundary.js +181 -0
  45. package/dist/quota-boundary.js.map +1 -0
  46. package/dist/records.d.ts +45 -0
  47. package/dist/records.d.ts.map +1 -0
  48. package/dist/records.js +85 -0
  49. package/dist/records.js.map +1 -0
  50. package/dist/schedule.d.ts +256 -0
  51. package/dist/schedule.d.ts.map +1 -0
  52. package/dist/schedule.js +390 -0
  53. package/dist/schedule.js.map +1 -0
  54. package/dist/scheduler.d.ts +75 -0
  55. package/dist/scheduler.d.ts.map +1 -0
  56. package/dist/scheduler.js +244 -0
  57. package/dist/scheduler.js.map +1 -0
  58. package/dist/start-point.d.ts +40 -0
  59. package/dist/start-point.d.ts.map +1 -0
  60. package/dist/start-point.js +88 -0
  61. package/dist/start-point.js.map +1 -0
  62. package/dist/state.d.ts +194 -0
  63. package/dist/state.d.ts.map +1 -0
  64. package/dist/state.js +208 -0
  65. package/dist/state.js.map +1 -0
  66. package/dist/test-repo.d.ts +20 -0
  67. package/dist/test-repo.d.ts.map +1 -0
  68. package/dist/test-repo.js +56 -0
  69. package/dist/test-repo.js.map +1 -0
  70. package/dist/tick.d.ts +122 -0
  71. package/dist/tick.d.ts.map +1 -0
  72. package/dist/tick.js +334 -0
  73. package/dist/tick.js.map +1 -0
  74. package/dist/write-line.d.ts +38 -0
  75. package/dist/write-line.d.ts.map +1 -0
  76. package/dist/write-line.js +121 -0
  77. package/dist/write-line.js.map +1 -0
  78. package/package.json +65 -3
  79. package/README.md +0 -3
@@ -0,0 +1,2324 @@
1
+ import { createElement as e, forwardRef as t, useEffect as n, useId as r, useRef as i, useState as a } from "react";
2
+ import { Button as o, Card as s, CardContent as c, CardHeader as l, CardTitleLink as u, Input as d, Label as f, MAX_SPEND_OFFSET as p, RadioGroup as m, RadioGroupItem as h, RadioGroupOption as g, Select as _, SelectContent as v, SelectItem as y, SelectTrigger as b, SelectValue as x, SettingsRow as S, SettingsSection as C, Switch as w, Textarea as T, Tooltip as E, TooltipContent as D, TooltipTrigger as O, buttonVariants as k, cn as A, defineModule as j, formatAge as ee, formatDateTime as te, useCodingAgents as ne, useModuleHost as M, usePolled as re } from "@openagt/dashboard/module";
3
+ import { Fragment as N, jsx as P, jsxs as F } from "react/jsx-runtime";
4
+ //#region ../../node_modules/.pnpm/lucide-react@0.469.0_react@19.2.7/node_modules/lucide-react/dist/esm/shared/src/utils.js
5
+ var I = (e) => e.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), L = (...e) => e.filter((e, t, n) => !!e && e.trim() !== "" && n.indexOf(e) === t).join(" ").trim(), R = {
6
+ xmlns: "http://www.w3.org/2000/svg",
7
+ width: 24,
8
+ height: 24,
9
+ viewBox: "0 0 24 24",
10
+ fill: "none",
11
+ stroke: "currentColor",
12
+ strokeWidth: 2,
13
+ strokeLinecap: "round",
14
+ strokeLinejoin: "round"
15
+ }, ie = t(({ color: t = "currentColor", size: n = 24, strokeWidth: r = 2, absoluteStrokeWidth: i, className: a = "", children: o, iconNode: s, ...c }, l) => e("svg", {
16
+ ref: l,
17
+ ...R,
18
+ width: n,
19
+ height: n,
20
+ stroke: t,
21
+ strokeWidth: i ? Number(r) * 24 / Number(n) : r,
22
+ className: L("lucide", a),
23
+ ...c
24
+ }, [...s.map(([t, n]) => e(t, n)), ...Array.isArray(o) ? o : [o]])), z = ((n, r) => {
25
+ let i = t(({ className: t, ...i }, a) => e(ie, {
26
+ ref: a,
27
+ iconNode: r,
28
+ className: L(`lucide-${I(n)}`, t),
29
+ ...i
30
+ }));
31
+ return i.displayName = `${n}`, i;
32
+ })("CalendarClock", [
33
+ ["path", {
34
+ d: "M21 7.5V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h3.5",
35
+ key: "1osxxc"
36
+ }],
37
+ ["path", {
38
+ d: "M16 2v4",
39
+ key: "4m81vk"
40
+ }],
41
+ ["path", {
42
+ d: "M8 2v4",
43
+ key: "1cmpym"
44
+ }],
45
+ ["path", {
46
+ d: "M3 10h5",
47
+ key: "r794hk"
48
+ }],
49
+ ["path", {
50
+ d: "M17.5 17.5 16 16.3V14",
51
+ key: "akvzfd"
52
+ }],
53
+ ["circle", {
54
+ cx: "16",
55
+ cy: "16",
56
+ r: "6",
57
+ key: "qoo3c4"
58
+ }]
59
+ ]), ae = ".scheduler/automations", B = ["claude-code", "codex"];
60
+ function V(e) {
61
+ return B.includes(e);
62
+ }
63
+ var H = {
64
+ "claude-code": "Claude Code",
65
+ codex: "Codex"
66
+ }, U = {
67
+ "claude-code": ".claude/skills",
68
+ codex: ".agents/skills"
69
+ }, W = "claude-code";
70
+ U[W];
71
+ var G = "commit";
72
+ function oe(e) {
73
+ return typeof e == "number" && Number.isInteger(e) && e >= 1 && e <= 99;
74
+ }
75
+ function se(e) {
76
+ return typeof e == "string" && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/.test(e) && !Number.isNaN(Date.parse(e));
77
+ }
78
+ function ce(e) {
79
+ return /^[a-z0-9][a-z0-9-]*$/.test(e) && !e.includes("---");
80
+ }
81
+ //#endregion
82
+ //#region src/pace.ts
83
+ var le = [
84
+ "m",
85
+ "h",
86
+ "d",
87
+ "w",
88
+ "mo"
89
+ ], ue = {
90
+ d: 1,
91
+ w: 7,
92
+ mo: 30
93
+ }, K = 6e4, de = {
94
+ m: K,
95
+ h: 60 * K,
96
+ d: 1440 * K,
97
+ w: 7 * 1440 * K,
98
+ mo: 30 * 1440 * K
99
+ }, fe = 9999;
100
+ function q(e) {
101
+ let t = /^(\d+)(mo|m|h|d|w)$/.exec(e), n = Number(t?.[1]);
102
+ if (!t || n < 1 || n > 9999) return;
103
+ let r = t[2];
104
+ return {
105
+ count: n,
106
+ unit: r,
107
+ ms: n * de[r],
108
+ text: `${n}${r}`
109
+ };
110
+ }
111
+ function pe(e) {
112
+ return ue[e.unit] !== void 0;
113
+ }
114
+ function me(e) {
115
+ let t = /^(\d{1,2}):(\d{2})$/.exec(e), n = Number(t?.[1]), r = Number(t?.[2]);
116
+ if (!(!t || n > 23 || r > 59)) return {
117
+ hour: n,
118
+ minute: r,
119
+ text: `${String(n).padStart(2, "0")}:${t[2]}`
120
+ };
121
+ }
122
+ function he(e, t) {
123
+ let n = t.every ? { every: t.every } : void 0;
124
+ if (e === void 0 || typeof e != "object" || !e) return n;
125
+ if ("work" in e && e.work === !0) return t.when === void 0 ? n : void 0;
126
+ let r = "every" in e && typeof e.every == "string" ? q(e.every) : void 0;
127
+ if (!r) return n;
128
+ let i = e, a = typeof i.at == "string" && pe(r) ? me(i.at) : void 0;
129
+ return {
130
+ every: r,
131
+ ...a ? {
132
+ at: a,
133
+ ...typeof i.since == "string" ? { since: i.since } : {}
134
+ } : {}
135
+ };
136
+ }
137
+ function ge(e, t, n) {
138
+ if (!e.at) return t ? new Date(t.getTime() + e.every.ms) : /* @__PURE__ */ new Date(0);
139
+ let { hour: r, minute: i } = e.at, a = (e, t) => new Date(e.getFullYear(), e.getMonth(), e.getDate() + t, r, i), o = e.since !== void 0 && !Number.isNaN(Date.parse(e.since)) ? new Date(e.since) : void 0, s = o && (a(o, 0).getTime() >= o.getTime() ? a(o, 0) : a(o, 1));
140
+ if (!t) return s ?? a(n, 0);
141
+ let c = a(t, e.every.count * ue[e.every.unit]);
142
+ return s && s.getTime() > c.getTime() ? s : c;
143
+ }
144
+ //#endregion
145
+ //#region dashboard/schedulers.ts
146
+ var _e = {
147
+ nothing: "As the skill says",
148
+ commit: "Commit",
149
+ branch: "Publish branch",
150
+ pr: "Open PR",
151
+ merge: "Merge on green"
152
+ };
153
+ function ve(e, t) {
154
+ return e === "nothing" && t ? "As the prompt says" : _e[e];
155
+ }
156
+ var ye = Object.keys(_e);
157
+ function J(e) {
158
+ return e.runsOn ?? e.home;
159
+ }
160
+ function be(e, t, n = J(e)) {
161
+ return (n === J(e) ? e.model : void 0) ?? (n === e.skillModelAgent ? e.skillModel : void 0) ?? (n === "claude-code" ? t : void 0);
162
+ }
163
+ function xe(e, t, n) {
164
+ return e.find((e) => e.value === t)?.models.find((e) => e.value === n)?.label ?? n;
165
+ }
166
+ function Se(e, t, n) {
167
+ let r = J(e), i = be(e, t, r);
168
+ return i === void 0 ? H[r] : `${H[r]}, ${xe(n, r, i)}`;
169
+ }
170
+ function Ce(e) {
171
+ let t = X(e);
172
+ if (!(typeof t.id != "string" || t.id === "" || !se(t.at))) return {
173
+ id: t.id,
174
+ at: t.at,
175
+ ...t.failed === !0 ? { failed: !0 } : {}
176
+ };
177
+ }
178
+ function Y(e) {
179
+ return e.editable === !0 || e.onThisMachine === !0;
180
+ }
181
+ function we(e) {
182
+ return e.onThisMachine ? e.command : `/${e.command}`;
183
+ }
184
+ function Te(e) {
185
+ return e.own ? `The automation ${e.skill}, kept on this machine, is not listed: ${e.reason}` : `The schedule of the ${e.skill} skill cannot be read, so it is not listed: ${e.reason}`;
186
+ }
187
+ function Ee(e) {
188
+ return ye.includes(e);
189
+ }
190
+ function De(e) {
191
+ let t = X(e);
192
+ return t.work === !0 || typeof t.every == "string" && q(t.every) !== void 0;
193
+ }
194
+ function X(e) {
195
+ return e && typeof e == "object" && !Array.isArray(e) ? e : {};
196
+ }
197
+ var Oe = "unreadable schedule: ", ke = "unlisted automation: ";
198
+ function Ae(e, t) {
199
+ let n = X(t), r = X(n.lastTick), i = X(n.switches), a = X(n.publishes), o = X(n.paces), s = X(n.agents), c = X(n.runsOn), l = X(n.models), u = [];
200
+ for (let e of Array.isArray(r.decisions) ? r.decisions : []) {
201
+ let t = X(e);
202
+ typeof t.command != "string" || typeof t.outcome != "string" || u.push({
203
+ command: t.command,
204
+ outcome: t.outcome,
205
+ ...typeof t.run == "string" ? { run: t.run } : {}
206
+ });
207
+ }
208
+ let d = [];
209
+ for (let e of Array.isArray(n.schedule) ? n.schedule : []) {
210
+ let t = X(e), n = t.command;
211
+ if (typeof n != "string") continue;
212
+ let r = a[n], f = V(t.agent) ? t.agent : W, p = V(c[n]) ? c[n] : f, m = X(l[n]), h = u.find((e) => e.command === n && !e.outcome.startsWith(Oe) && !e.outcome.startsWith(ke));
213
+ d.push({
214
+ command: n,
215
+ ...typeof t.every == "string" ? { every: t.every } : {},
216
+ ...typeof t.when == "string" ? { when: t.when } : {},
217
+ ...typeof t.waitsFor == "string" ? { waitsFor: t.waitsFor } : {},
218
+ ...typeof t.checkEvery == "string" ? { checkEvery: t.checkEvery } : {},
219
+ on: se(i[n]),
220
+ publish: Ee(r) ? r : G,
221
+ ...De(o[n]) ? { pace: o[n] } : {},
222
+ ...oe(t.agents) && t.agents > 1 ? { skillAgents: t.agents } : {},
223
+ ...oe(s[n]) ? { agents: s[n] } : {},
224
+ home: f,
225
+ ...typeof t.model == "string" && t.model !== "" ? {
226
+ skillModel: t.model,
227
+ skillModelAgent: V(t.modelAgent) ? t.modelAgent : W
228
+ } : {},
229
+ able: Array.isArray(t.able) ? B.filter((e) => t.able.includes(e)) : B,
230
+ ...p === f ? {} : { runsOn: p },
231
+ ...m.agent === p && typeof m.model == "string" && m.model.trim() !== "" ? { model: m.model } : {},
232
+ ...typeof t.description == "string" ? { description: t.description } : {},
233
+ ...t.each === !0 ? { each: !0 } : {},
234
+ ...t.onThisMachine === !0 ? { onThisMachine: !0 } : {},
235
+ ...t.editable === !0 ? { editable: !0 } : {},
236
+ ...Ce(t.lastRun) ? { lastRun: Ce(t.lastRun) } : {},
237
+ ...h ? { decision: h } : {}
238
+ });
239
+ }
240
+ let f = n.spendOffset;
241
+ return {
242
+ project: e,
243
+ on: n.on === !0,
244
+ keepAlive: n.keepAlive === !0,
245
+ running: n.running === !0,
246
+ ...typeof n.model == "string" ? { model: n.model } : {},
247
+ ...typeof f == "number" && Number.isFinite(f) ? { spendOffset: f } : {},
248
+ ...typeof r.at == "string" ? { lastTick: {
249
+ at: r.at,
250
+ decisions: u,
251
+ ...typeof r.note == "string" ? { note: r.note } : {}
252
+ } } : {},
253
+ commands: d,
254
+ unreadable: (Array.isArray(n.unreadable) ? n.unreadable : []).flatMap((e) => {
255
+ let t = X(e);
256
+ return typeof t.skill == "string" && typeof t.reason == "string" ? [{
257
+ skill: t.skill,
258
+ reason: t.reason,
259
+ ...t.own === !0 ? { own: !0 } : {}
260
+ }] : [];
261
+ })
262
+ };
263
+ }
264
+ function je(e, t) {
265
+ return Promise.all(t.map(async (t) => {
266
+ let n = await e.runCommand(t.id, ["status"]);
267
+ return n.ok ? Ae(t, n.output) : {
268
+ project: t,
269
+ error: n.error,
270
+ on: !1,
271
+ keepAlive: !1,
272
+ running: !1,
273
+ commands: [],
274
+ unreadable: []
275
+ };
276
+ }));
277
+ }
278
+ function Me(e) {
279
+ let t = e.flatMap((e) => e.spendOffset === void 0 ? [] : [e.spendOffset]);
280
+ return t.length ? Math.max(...t) : void 0;
281
+ }
282
+ function Ne(e) {
283
+ let t = Me(e);
284
+ return e.flatMap((e) => e.spendOffset !== void 0 && e.spendOffset !== t ? [{
285
+ name: e.project.name,
286
+ offset: Math.round(e.spendOffset * 10) / 10
287
+ }] : []);
288
+ }
289
+ function Pe(e) {
290
+ if (!(e.trim() === "" || !Number.isFinite(Number(e)))) return Math.min(Math.max(Math.round(Number(e)), -p), p);
291
+ }
292
+ async function Fe(e, t, n) {
293
+ let r = (await Promise.all(t.map(async (t) => ({
294
+ project: t,
295
+ answer: await e.runCommand(t.id, [
296
+ "offset",
297
+ "--",
298
+ String(n)
299
+ ])
300
+ })))).flatMap(({ project: e, answer: t }) => t.ok ? [] : [`${e.name}: ${t.error}`]);
301
+ return r.length ? {
302
+ ok: !1,
303
+ error: r.join("; ")
304
+ } : { ok: !0 };
305
+ }
306
+ function Ie(e, t) {
307
+ let n = e ? ye : [
308
+ "nothing",
309
+ "commit",
310
+ "branch"
311
+ ];
312
+ return n.includes(t) ? n : [...n, t];
313
+ }
314
+ var Le = {
315
+ m: "minute",
316
+ h: "hour",
317
+ d: "day",
318
+ w: "week",
319
+ mo: "month"
320
+ };
321
+ function Re(e) {
322
+ let t = q(e);
323
+ return t ? `${t.count} ${Le[t.unit]}${t.count === 1 ? "" : "s"}` : e;
324
+ }
325
+ var ze = (e) => e.charAt(0).toUpperCase() + e.slice(1);
326
+ function Be(e) {
327
+ let t = e.waitsFor ?? "when its shell line prints something", n = e.every === void 0 ? void 0 : q(e.every), r = he(e.pace, {
328
+ ...n ? { every: n } : {},
329
+ ...e.when === void 0 ? {} : { when: e.when }
330
+ }), i = r ? Re(r.every.text) : e.pace === void 0 && e.every !== void 0 ? e.every : void 0;
331
+ return i === void 0 ? ze(t) : e.when === void 0 ? r?.at ? `Every ${i} at ${r.at.text}` : `Every ${i}` : r?.at ? `Every ${i} from ${r.at.text}, ${t}` : `Every ${i} at most, ${t}`;
332
+ }
333
+ function Ve(e) {
334
+ return He(e).kind !== "skill";
335
+ }
336
+ function He(e) {
337
+ let t = e.pace;
338
+ if (t === void 0) return { kind: "skill" };
339
+ if ("work" in t && t.work === !0) return e.when !== void 0 && e.every !== void 0 ? { kind: "work" } : { kind: "skill" };
340
+ let n = "every" in t ? q(t.every) : void 0;
341
+ if (!n || !("every" in t)) return { kind: "skill" };
342
+ let r = pe(n) && t.at !== void 0 ? me(t.at) : void 0;
343
+ return {
344
+ kind: "every",
345
+ count: String(n.count),
346
+ unit: n.unit,
347
+ at: r?.text ?? ""
348
+ };
349
+ }
350
+ function Z(e) {
351
+ if (e.kind !== "every") return [e.kind];
352
+ let t = /^\d+$/.test(e.count.trim()) ? q(`${e.count.trim()}${e.unit}`) : void 0;
353
+ if (!t) return;
354
+ if (!pe(t)) return [t.text];
355
+ if (e.atHalfTyped) return;
356
+ if (e.at.trim() === "") return [t.text];
357
+ let n = me(e.at.trim());
358
+ return n ? [t.text, n.text] : void 0;
359
+ }
360
+ function Ue(e) {
361
+ if (!Z(e)) return e.kind === "every" && !(/^\d+$/.test(e.count.trim()) && q(`${e.count.trim()}${e.unit}`)) ? `Type a whole number, from 1 to ${fe}.` : "Finish the time, like 10:00, or clear it.";
362
+ }
363
+ function We(e, t) {
364
+ let n = Z(t);
365
+ if (!n) return e;
366
+ let { pace: r, ...i } = e;
367
+ return n[0] === "skill" ? i : {
368
+ ...i,
369
+ pace: n[0] === "work" ? { work: !0 } : {
370
+ every: n[0],
371
+ ...n[1] === void 0 ? {} : { at: n[1] },
372
+ since: ""
373
+ }
374
+ };
375
+ }
376
+ function Ge(e) {
377
+ return e.agents ?? e.skillAgents ?? 1;
378
+ }
379
+ function Ke(e) {
380
+ return Ge(e) > 1 || e.agents !== void 0;
381
+ }
382
+ function qe(e) {
383
+ return e === 1 ? "One at a time" : `Up to ${e} at once`;
384
+ }
385
+ function Je(e) {
386
+ return e.agents === void 0 ? { kind: "skill" } : {
387
+ kind: "own",
388
+ count: String(e.agents)
389
+ };
390
+ }
391
+ function Ye(e) {
392
+ if (e.kind === "skill") return ["skill"];
393
+ let t = e.count.trim();
394
+ return /^\d+$/.test(t) && oe(Number(t)) ? [String(Number(t))] : void 0;
395
+ }
396
+ function Xe(e) {
397
+ return e.publish === "commit" ? "May commit, pushes nothing" : e.publish === "branch" ? "May publish its branch" : e.publish === "pr" ? "May open a pull request" : e.publish === "merge" ? "May open a pull request that merges on green" : Y(e) ? "As its prompt says" : "As its skill says";
398
+ }
399
+ function Ze(e, t = /* @__PURE__ */ new Date()) {
400
+ let n = $e(e);
401
+ if (n) return n;
402
+ if (!(!e.on || e.decision?.outcome.startsWith("not a command of "))) return Qe(e, t) ?? tt(e.decision?.outcome);
403
+ }
404
+ function Qe(e, t) {
405
+ let n = e.decision?.outcome;
406
+ if (n === void 0 || !/^not due \((last start|next start from) /.test(n)) return;
407
+ let r = /^not due \(next start from (\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d),/.exec(n), i = r && new Date(Number(r[1]), Number(r[2]) - 1, Number(r[3]), Number(r[4]), Number(r[5]));
408
+ return i && i.getTime() > t.getTime() ? `Next start ${ct(i, t)}${e.when === void 0 ? "" : ", if there is work"}` : rt(e, t);
409
+ }
410
+ function $e(e) {
411
+ let t = J(e);
412
+ return e.able.includes(t) ? void 0 : et(H[t], U[t]);
413
+ }
414
+ var et = (e, t) => `Cannot start on ${e}: its skill is not in ${t}`;
415
+ function tt(e) {
416
+ if (e === void 0 || e === "switched off on this machine" || e.startsWith("started ") || e.startsWith("resumed ")) return;
417
+ let t = /^(?:run \S+ not resumed|no run for \S+): (.*)$/.exec(e);
418
+ if (t) return tt(t[1]);
419
+ let n = /^not a command of (.+?): its skill is only under .+, not (\S+)$/.exec(e);
420
+ if (n) return et(n[1], n[2]);
421
+ if (e === "not due") return "No work";
422
+ let r = /^not on (\S+?)( as this clone last saw it)?: /.exec(e);
423
+ if (r) return r[1] === "HEAD" ? "Cannot start yet: its skill is not committed" : `Cannot start yet: its skill is not on ${r[1]}${r[2] ? ", as this machine last saw it" : ""}`;
424
+ let i = /^cap reached \((\d+) in flight/.exec(e);
425
+ return i ? i[1] === "1" ? "One is already running" : `${i[1]} are already running` : ze(e);
426
+ }
427
+ function nt(e) {
428
+ let t = Math.max(1, Math.ceil(e / 6e4));
429
+ if (t < 60) return `${t} min`;
430
+ let n = Math.round(t / 60);
431
+ return n < 48 ? `${n}h` : `${Math.round(n / 24)} days`;
432
+ }
433
+ function rt(e, t = /* @__PURE__ */ new Date()) {
434
+ let n = e.when !== void 0, r = n ? "Starts when there is work" : "Starts at the scheduler's next look", i = e.every === void 0 ? void 0 : q(e.every), a = he(e.pace, {
435
+ ...i ? { every: i } : {},
436
+ ...e.when === void 0 ? {} : { when: e.when }
437
+ });
438
+ if (!a) return r;
439
+ let o = ge(a, e.lastRun === void 0 ? void 0 : new Date(e.lastRun.at), t);
440
+ return o.getTime() <= t.getTime() ? r : `Next start ${a.at ? ct(o, t) : `in ${nt(o.getTime() - t.getTime())}`}${n ? ", if there is work" : ""}`;
441
+ }
442
+ function it(e, t = /* @__PURE__ */ new Date()) {
443
+ let n = $e(e);
444
+ if (n) return n;
445
+ let r = e.decision?.outcome;
446
+ return (r === void 0 || r === "not due" || r.startsWith("not due (") || r.startsWith("started ") || r === "switched off on this machine" ? void 0 : Ze(e, t)) ?? rt(e, t);
447
+ }
448
+ function at(e) {
449
+ if (!e.on) return "The scheduler is off";
450
+ if (!e.running) return "The scheduler is on, but not running";
451
+ }
452
+ var ot = [
453
+ "Sunday",
454
+ "Monday",
455
+ "Tuesday",
456
+ "Wednesday",
457
+ "Thursday",
458
+ "Friday",
459
+ "Saturday"
460
+ ], st = [
461
+ "Jan",
462
+ "Feb",
463
+ "Mar",
464
+ "Apr",
465
+ "May",
466
+ "Jun",
467
+ "Jul",
468
+ "Aug",
469
+ "Sep",
470
+ "Oct",
471
+ "Nov",
472
+ "Dec"
473
+ ];
474
+ function ct(e, t) {
475
+ let n = (e) => String(e).padStart(2, "0");
476
+ if (e.getTime() <= t.getTime()) return "as soon as the scheduler looks";
477
+ let r = `${n(e.getHours())}:${n(e.getMinutes())}`, i = Math.round((new Date(e.getFullYear(), e.getMonth(), e.getDate()).getTime() - new Date(t.getFullYear(), t.getMonth(), t.getDate()).getTime()) / 864e5);
478
+ return i === 0 ? `today ${r}` : i === 1 ? `tomorrow ${r}` : i > 1 && i < 7 ? `${ot[e.getDay()]} ${r}` : `${e.getDate()} ${st[e.getMonth()]} ${r}`;
479
+ }
480
+ function lt(e) {
481
+ return e.error === void 0 ? e.on ? e.running ? {
482
+ label: "on",
483
+ tone: "text-success"
484
+ } : {
485
+ label: "on, not running",
486
+ tone: "text-warning"
487
+ } : {
488
+ label: "off",
489
+ tone: "text-muted-foreground"
490
+ } : {
491
+ label: "not readable",
492
+ tone: "text-danger"
493
+ };
494
+ }
495
+ //#endregion
496
+ //#region dashboard/automation-form.ts
497
+ var ut = 4e3, dt = {
498
+ name: "",
499
+ prompt: "",
500
+ when: "",
501
+ waitsFor: "",
502
+ pace: {
503
+ kind: "every",
504
+ count: "1",
505
+ unit: "d",
506
+ at: ""
507
+ },
508
+ onThisMachine: !1
509
+ };
510
+ function ft(e) {
511
+ return e.pace.kind === "every" ? Z(e.pace)?.[0] : void 0;
512
+ }
513
+ function pt(e) {
514
+ let t = typeof e == "object" && e ? e : {}, { name: n, prompt: r, every: i, when: a, waitsFor: o, file: s } = t;
515
+ if (typeof n != "string" || typeof r != "string" || typeof s != "string") return;
516
+ let c = i === void 0 ? void 0 : typeof i == "string" ? q(i) : void 0;
517
+ if (!(i !== void 0 && !c)) return {
518
+ draft: {
519
+ name: n,
520
+ prompt: r,
521
+ when: typeof a == "string" ? a : "",
522
+ waitsFor: typeof o == "string" ? o : "",
523
+ pace: c ? {
524
+ kind: "every",
525
+ count: String(c.count),
526
+ unit: c.unit,
527
+ at: ""
528
+ } : { kind: "work" },
529
+ onThisMachine: t.onThisMachine === !0
530
+ },
531
+ file: s,
532
+ ...typeof t.version == "string" ? { version: t.version } : {}
533
+ };
534
+ }
535
+ function mt(e, t) {
536
+ let n = He(t);
537
+ return n.kind === "skill" ? e : {
538
+ ...e,
539
+ pace: n
540
+ };
541
+ }
542
+ function ht(e, t) {
543
+ let n = e.name.trim();
544
+ return n === "" ? e.onThisMachine ? "Give it a name, like answer-comments." : "Give it a name. It becomes the command, like /answer-comments." : ce(n) ? n.length > 64 ? "A name is 64 characters at most." : e.prompt.trim() === "" ? "Write what the agent is told." : e.prompt.trim().length > 4e3 ? `What the agent is told is ${e.prompt.trim().length} characters, and this form takes ${ut} at most. ${t === void 0 ? "Save a shorter one, then write the rest into the file." : `Change it in its file, ${t}.`}` : e.when.trim().length > 4e3 ? `The shell line is ${e.when.trim().length} characters, and this form takes ${ut} at most.` : e.when.trim() !== "" && e.waitsFor.trim().length > 4e3 ? `What the line waits for is ${e.waitsFor.trim().length} characters, and this form takes ${ut} at most.` : e.pace.kind === "work" && e.when.trim() === "" ? "Say when it runs: on a pace, by a shell line, or both." : Ue(e.pace) : "A name is lower-case letters, digits and dashes, never three dashes in a row, like answer-comments.";
545
+ }
546
+ function gt(e) {
547
+ if (ht(e) === void 0) return [
548
+ "add",
549
+ ...yt(e),
550
+ ...e.onThisMachine ? ["--private"] : []
551
+ ];
552
+ }
553
+ function _t(e, t) {
554
+ if (ht(e, t) !== void 0) return;
555
+ let n = e.when.trim();
556
+ return [
557
+ "edit",
558
+ e.name.trim(),
559
+ `--prompt=${e.prompt.trim()}`,
560
+ `--every=${ft(e) ?? ""}`,
561
+ `--when=${n}`,
562
+ `--waits-for=${n === "" ? "" : e.waitsFor.trim()}`
563
+ ];
564
+ }
565
+ function vt(e) {
566
+ let t = Z(e.pace);
567
+ if (t) return e.pace.kind === "every" && t[1] !== void 0 ? t : ["skill"];
568
+ }
569
+ function yt(e) {
570
+ let t = ft(e), n = e.when.trim(), r = e.waitsFor.trim();
571
+ return [
572
+ e.name.trim(),
573
+ `--prompt=${e.prompt.trim()}`,
574
+ ...t === void 0 ? [] : [`--every=${t}`],
575
+ ...n === "" ? [] : [`--when=${n}`],
576
+ ...n !== "" && r !== "" ? [`--waits-for=${r}`] : []
577
+ ];
578
+ }
579
+ function bt(e, t) {
580
+ return yt(e).join("\0") === yt(t).join("\0");
581
+ }
582
+ function xt(e) {
583
+ let t = Z(e.pace), n = ft(e), r = e.when.trim();
584
+ if (!t || n === void 0 && r === "") return;
585
+ let i = e.waitsFor.trim();
586
+ return {
587
+ command: e.name.trim(),
588
+ on: !1,
589
+ publish: "commit",
590
+ home: W,
591
+ able: B,
592
+ ...n === void 0 ? {} : { every: n },
593
+ ...r === "" ? {} : {
594
+ when: r,
595
+ ...i === "" ? {} : { waitsFor: i }
596
+ },
597
+ ...n !== void 0 && t[1] !== void 0 ? { pace: {
598
+ every: n,
599
+ at: t[1],
600
+ since: ""
601
+ } } : {}
602
+ };
603
+ }
604
+ function St(e) {
605
+ let t = xt(e);
606
+ return t && Be(t);
607
+ }
608
+ function Ct(e) {
609
+ return e.name === "" && e.prompt === "" && e.when === "" && e.waitsFor === "";
610
+ }
611
+ function wt(e) {
612
+ let t = typeof e == "object" && e ? e : {}, n = typeof t.printed == "string" ? t.printed : "", r = typeof t.lastRun == "string" ? { lastRun: t.lastRun } : {};
613
+ return t.ran === !0 ? t.due === !0 ? {
614
+ ...r,
615
+ printed: n,
616
+ verdict: "It printed something: an agent would start now.",
617
+ tone: "start"
618
+ } : {
619
+ ...r,
620
+ printed: n,
621
+ verdict: "It printed nothing to do: no agent would start.",
622
+ tone: "quiet"
623
+ } : {
624
+ ...r,
625
+ printed: n,
626
+ verdict: `The line failed${typeof t.error == "string" && t.error !== "" ? `: ${t.error}` : "."}`,
627
+ tone: "failed"
628
+ };
629
+ }
630
+ function Tt(e) {
631
+ let t = typeof e == "object" && e ? e : {};
632
+ return typeof t.line == "string" && t.line !== "" ? { line: t.line } : { said: typeof t.none == "string" ? `No line can do that: ${t.none}` : "The line was not written." };
633
+ }
634
+ function Et(e) {
635
+ let t = typeof e == "object" && e ? e : {};
636
+ return {
637
+ file: typeof t.file == "string" ? t.file : "a skill file",
638
+ startsFrom: typeof t.startsFrom == "string" ? t.startsFrom : "HEAD",
639
+ onThisMachine: t.onThisMachine === !0,
640
+ ...typeof t.version == "string" ? { version: t.version } : {}
641
+ };
642
+ }
643
+ function Dt(e) {
644
+ return e.onThisMachine ? "It is kept on this machine alone: nothing to commit, and nobody else gets the row. Its row can start as soon as you switch it on. Its prompt is in the record of each run, which is shared where this project shares its records." : `It is a file of yours, in this project, and nothing was committed for you. ${Nt(e.startsFrom)}`;
645
+ }
646
+ function Ot(e) {
647
+ return `It is a change to a file of yours, in this project, and nothing was committed for you. An agent is told the new words only ${e.startsFrom === "HEAD" ? "once you commit the change" : `once the change is on ${e.startsFrom}: commit it and bring it there`}. The pace and the shell line are read from your file, so the scheduler uses the new ones from its next look. Its past runs, its switch and your picks for it stay.`;
648
+ }
649
+ function kt(e) {
650
+ return e ? e.draft.onThisMachine ? `Kept on this machine alone, outside git: ${e.file}.` : `Its words and its pace are in a skill file of this project, ${e.file}: a change to them is yours to commit. The rest is saved on this machine.` : "Saved for you, in this project, on this machine. No tracked file changes.";
651
+ }
652
+ function At(e) {
653
+ let t = "Its switch and your picks for it go with it. The records of its past runs stay.";
654
+ return e.onThisMachine ? `Its file is deleted. It is kept on this machine alone, outside git, so it cannot be brought back. ${t}` : `Its skill file is deleted from your files in this project, and nothing is committed for you. Git can bring back only what you committed of it: a file never committed, or your last changes to it, cannot be brought back. Everyone else who has the project keeps the row until your deletion reaches them. ${t}`;
655
+ }
656
+ function jt(e, t) {
657
+ let n = typeof t == "object" && t ? t : {}, r = typeof n.file == "string" ? n.file : "its file", i = typeof n.startsFrom == "string" ? n.startsFrom : "HEAD";
658
+ return n.onThisMachine === !0 ? `Removed ${e}: ${r} is deleted. Nothing is to commit.` : n.git === "committed" ? `Removed ${e}: ${r} is deleted, and nothing was committed for you. ${i === "HEAD" ? "Commit the deletion." : `Commit the deletion and bring it to ${i}: until then everyone else who has the project keeps the row.`}` : n.git === "staged" ? `Removed ${e}: ${r} is deleted. It was staged and never committed, so a commit made now would still add it: take it out of the next commit with "git rm --cached ${r}".` : n.git === "nothing" ? `Removed ${e}: ${r} is deleted. Git never had the file, so nothing is to commit.` : `Removed ${e}: ${r} is deleted. What git holds of it could not be read: look with "git status".`;
659
+ }
660
+ function Mt(e) {
661
+ return e.onThisMachine ? "Kept on this machine alone, outside git. The row starts switched off, and can start as soon as you switch it on." : "Saved as a skill file in this project, which you commit. The row starts switched off.";
662
+ }
663
+ function Nt(e) {
664
+ return e === "HEAD" ? "Its row cannot start before you commit the file." : `Its row cannot start before the file is on ${e}: commit it and bring it there.`;
665
+ }
666
+ //#endregion
667
+ //#region dashboard/fields.tsx
668
+ var Q = "text-xs text-muted-foreground", Pt = (e) => /[.!?]$/.test(e.trim()) ? e.trim() : `${e.trim()}.`;
669
+ function $({ title: e, children: t }) {
670
+ return /* @__PURE__ */ F("section", {
671
+ "aria-label": e,
672
+ className: "space-y-2",
673
+ children: [/* @__PURE__ */ P("h4", {
674
+ className: "text-xs font-semibold uppercase tracking-wide text-muted-foreground",
675
+ children: e
676
+ }), t]
677
+ });
678
+ }
679
+ function Ft({ project: e, said: t, agent: n, autoFocus: r, onChange: s }) {
680
+ let c = M(), [l, u] = a(), [p, m] = a(), h = i(0), g = i(0), _ = t.when.trim(), v = t.waitsFor.trim(), y = (e) => {
681
+ s({ when: e }), h.current++, u(void 0);
682
+ }, b = async () => {
683
+ let t = ++h.current;
684
+ u("trying");
685
+ let n = await c.runCommand(e.id, ["try", `--when=${_}`]).catch((e) => ({
686
+ ok: !1,
687
+ error: e instanceof Error ? e.message : String(e)
688
+ }));
689
+ h.current === t && u(n.ok ? wt(n.output) : {
690
+ printed: "",
691
+ verdict: `The line could not be tried: ${n.error}`,
692
+ tone: "failed"
693
+ });
694
+ }, x = async () => {
695
+ let t = ++g.current;
696
+ m("writing");
697
+ let r = await c.runCommand(e.id, [
698
+ "write-line",
699
+ `--words=${v}`,
700
+ `--agent=${n}`
701
+ ]).catch((e) => ({
702
+ ok: !1,
703
+ error: e instanceof Error ? e.message : String(e)
704
+ }));
705
+ if (g.current !== t) return;
706
+ let i = r.ok ? Tt(r.output) : { said: `The line was not written: ${r.error}` };
707
+ "line" in i && y(i.line), m("said" in i ? i.said : void 0);
708
+ };
709
+ return /* @__PURE__ */ F(N, { children: [
710
+ /* @__PURE__ */ P(f, {
711
+ htmlFor: "automation-prompt",
712
+ children: "What the agent is told"
713
+ }),
714
+ /* @__PURE__ */ P(T, {
715
+ id: "automation-prompt",
716
+ rows: 4,
717
+ autoFocus: r,
718
+ value: t.prompt,
719
+ onChange: (e) => s({ prompt: e.target.value }),
720
+ placeholder: "Answer each new comment below."
721
+ }),
722
+ /* @__PURE__ */ F(f, {
723
+ htmlFor: "automation-waits-for",
724
+ className: "pt-1",
725
+ children: ["What the line waits for, in plain words ", /* @__PURE__ */ P("span", {
726
+ className: Q,
727
+ children: "optional, said on the row"
728
+ })]
729
+ }),
730
+ /* @__PURE__ */ P(d, {
731
+ id: "automation-waits-for",
732
+ type: "text",
733
+ value: t.waitsFor,
734
+ onChange: (e) => {
735
+ s({ waitsFor: e.target.value }), g.current++, m(void 0);
736
+ },
737
+ placeholder: "when someone commented",
738
+ className: "bg-background"
739
+ }),
740
+ /* @__PURE__ */ F("div", {
741
+ className: "flex flex-wrap items-center gap-3",
742
+ children: [/* @__PURE__ */ P(o, {
743
+ variant: "outline",
744
+ size: "sm",
745
+ disabled: v === "" || p === "writing",
746
+ onClick: () => void x(),
747
+ children: p === "writing" ? "Writing…" : "Write the line"
748
+ }), /* @__PURE__ */ F("span", {
749
+ className: Q,
750
+ children: [
751
+ "Asks ",
752
+ H[n],
753
+ " once for a shell line from these words, and puts it below; costs a fraction of a cent. Nothing is run or saved."
754
+ ]
755
+ })]
756
+ }),
757
+ p !== void 0 && p !== "writing" && /* @__PURE__ */ P("p", {
758
+ role: "status",
759
+ "aria-label": "What the agent answered",
760
+ className: "text-sm text-danger",
761
+ children: p
762
+ }),
763
+ /* @__PURE__ */ F(f, {
764
+ htmlFor: "automation-when",
765
+ className: "pt-1",
766
+ children: ["A shell line that prints what is new ", /* @__PURE__ */ P("span", {
767
+ className: Q,
768
+ children: "optional"
769
+ })]
770
+ }),
771
+ /* @__PURE__ */ P(T, {
772
+ id: "automation-when",
773
+ rows: 2,
774
+ value: t.when,
775
+ onChange: (e) => {
776
+ y(e.target.value), g.current++, m(void 0);
777
+ },
778
+ placeholder: "gh api \"repos/{owner}/{repo}/issues/comments?since=$LAST_RUN\" --jq '[.[] | select(.body | startswith(\"🤖\") | not) | {url: .html_url}]'",
779
+ spellCheck: !1,
780
+ className: "min-h-12 font-mono text-xs"
781
+ }),
782
+ /* @__PURE__ */ F("p", {
783
+ className: Q,
784
+ children: [
785
+ "Run in this project while the row is on: every minute, or once its wait is over. When it prints something, an agent starts and is handed what it printed; when it prints nothing, or an empty list, nothing starts.",
786
+ " ",
787
+ /* @__PURE__ */ P("span", {
788
+ className: "font-mono",
789
+ children: "$LAST_RUN"
790
+ }),
791
+ " is the time the row last started an agent, or was switched on when that is later."
792
+ ]
793
+ }),
794
+ /* @__PURE__ */ F("div", {
795
+ className: "flex flex-wrap items-center gap-3",
796
+ children: [/* @__PURE__ */ P(o, {
797
+ variant: "outline",
798
+ size: "sm",
799
+ disabled: _ === "" || l === "trying",
800
+ onClick: () => void b(),
801
+ children: l === "trying" ? "Trying…" : "Try it"
802
+ }), /* @__PURE__ */ P("span", {
803
+ className: Q,
804
+ children: "Runs the line once, now, on this machine, for 20 seconds at most. Nothing is saved and no agent starts."
805
+ })]
806
+ }),
807
+ l !== void 0 && l !== "trying" && /* @__PURE__ */ F("div", {
808
+ role: "status",
809
+ "aria-label": "What the line answered",
810
+ className: "rounded-md border border-border bg-background px-3 py-2 text-sm",
811
+ children: [
812
+ /* @__PURE__ */ P("p", {
813
+ className: A(l.tone === "start" && "text-success", l.tone === "failed" && "text-danger"),
814
+ children: l.verdict
815
+ }),
816
+ l.printed !== "" && /* @__PURE__ */ P("pre", {
817
+ className: "mt-2 max-h-48 overflow-auto whitespace-pre-wrap break-words font-mono text-xs",
818
+ children: l.printed
819
+ }),
820
+ l.lastRun !== void 0 && /* @__PURE__ */ F("p", {
821
+ className: "mt-2 text-xs text-muted-foreground",
822
+ children: [
823
+ "Tried as if the row had last started a day ago: $LAST_RUN was ",
824
+ l.lastRun,
825
+ "."
826
+ ]
827
+ })
828
+ ]
829
+ })
830
+ ] });
831
+ }
832
+ function It({ description: e, when: t, waitsFor: n, where: r }) {
833
+ return /* @__PURE__ */ F("div", {
834
+ className: "space-y-2 opacity-70",
835
+ children: [
836
+ /* @__PURE__ */ P("p", {
837
+ className: "rounded-md border border-border bg-muted px-3 py-2 text-sm",
838
+ children: e ?? "It does not say."
839
+ }),
840
+ t !== void 0 && /* @__PURE__ */ F(N, { children: [/* @__PURE__ */ F("p", {
841
+ className: "text-sm",
842
+ children: ["Its shell line", n !== void 0 && /* @__PURE__ */ F("span", {
843
+ className: "text-xs text-muted-foreground",
844
+ children: [" ", n]
845
+ })]
846
+ }), /* @__PURE__ */ P("pre", {
847
+ className: "max-h-32 overflow-auto whitespace-pre-wrap break-words rounded-md border border-border bg-muted px-3 py-2 font-mono text-xs",
848
+ children: t
849
+ })] }),
850
+ /* @__PURE__ */ P("p", {
851
+ className: "text-xs text-muted-foreground",
852
+ children: r
853
+ })
854
+ ]
855
+ });
856
+ }
857
+ function Lt({ name: e, draft: t, work: a, asSaid: o, noWait: s, start: c, counted: l, disabled: u, autoFocus: f, onChange: p }) {
858
+ let S = t.kind === "every" ? t : {
859
+ kind: "every",
860
+ count: String(c.count),
861
+ unit: c.unit,
862
+ at: ""
863
+ }, C = pe({
864
+ count: 1,
865
+ unit: S.unit,
866
+ ms: 0,
867
+ text: ""
868
+ }), w = s || t.kind === "work", T = o !== void 0 || w, E = t.kind === "every", D = r(), O = i(null);
869
+ n(() => {
870
+ f && O.current?.querySelector("[role=\"radio\"][aria-checked=\"true\"]")?.focus();
871
+ }, []);
872
+ let k = (e) => p(e === "every" ? S : e === "work" ? { kind: "work" } : { kind: "skill" }), j = /* @__PURE__ */ F("div", {
873
+ className: A("flex flex-wrap items-center gap-2 text-sm", !E && "opacity-60"),
874
+ children: [
875
+ /* @__PURE__ */ P(d, {
876
+ type: "number",
877
+ min: 1,
878
+ max: fe,
879
+ value: S.count,
880
+ disabled: u,
881
+ onChange: (e) => p({
882
+ ...S,
883
+ count: e.target.value
884
+ }),
885
+ "aria-label": "How long",
886
+ className: "h-8 w-20 bg-background px-2"
887
+ }),
888
+ /* @__PURE__ */ F(_, {
889
+ items: le.map((e) => ({
890
+ value: e,
891
+ label: Rt(e, S.count)
892
+ })),
893
+ value: S.unit,
894
+ disabled: u,
895
+ onValueChange: (e) => p({
896
+ ...S,
897
+ unit: e
898
+ }),
899
+ children: [/* @__PURE__ */ P(b, {
900
+ size: "sm",
901
+ "aria-label": "Unit",
902
+ className: "w-28",
903
+ children: /* @__PURE__ */ P(x, {})
904
+ }), /* @__PURE__ */ P(v, { children: le.map((e) => /* @__PURE__ */ P(y, {
905
+ value: e,
906
+ children: Rt(e, S.count)
907
+ }, e)) })]
908
+ }),
909
+ C && /* @__PURE__ */ F(N, { children: [
910
+ /* @__PURE__ */ P("span", { children: a ? "not before" : "at" }),
911
+ /* @__PURE__ */ P(d, {
912
+ type: "time",
913
+ value: S.at,
914
+ disabled: u,
915
+ onChange: (e) => p({
916
+ kind: "every",
917
+ count: S.count,
918
+ unit: S.unit,
919
+ at: e.target.value,
920
+ ...e.target.validity.badInput ? { atHalfTyped: !0 } : {}
921
+ }),
922
+ "aria-label": a ? "Not before this time of day" : "Time of day",
923
+ className: "h-8 w-auto bg-background px-2"
924
+ }),
925
+ /* @__PURE__ */ F("span", {
926
+ className: Q,
927
+ children: ["optional, this machine's time", S.unit === "mo" ? "; a month counts as 30 days" : ""]
928
+ })
929
+ ] })
930
+ ]
931
+ });
932
+ return /* @__PURE__ */ F("div", {
933
+ className: "space-y-3",
934
+ children: [/* @__PURE__ */ P("p", {
935
+ className: "text-sm",
936
+ children: a ? /* @__PURE__ */ F(N, { children: [
937
+ "Only when there is work: ",
938
+ Pt(a.waitsFor ?? "when its shell line prints something"),
939
+ " ",
940
+ /* @__PURE__ */ F("span", {
941
+ className: "text-muted-foreground",
942
+ children: [
943
+ "The scheduler looks every ",
944
+ a.checkEvery === void 0 ? "minute" : `${parseInt(a.checkEvery, 10)} seconds`,
945
+ "."
946
+ ]
947
+ })
948
+ ] }) : /* @__PURE__ */ F(N, { children: ["By time alone. ", /* @__PURE__ */ P("span", {
949
+ className: "text-muted-foreground",
950
+ children: "It starts again once the wait is over."
951
+ })] })
952
+ }), /* @__PURE__ */ F("div", {
953
+ ...T ? {} : {
954
+ role: "group",
955
+ "aria-labelledby": D
956
+ },
957
+ className: "space-y-2",
958
+ children: [
959
+ /* @__PURE__ */ P("p", {
960
+ id: D,
961
+ className: "text-sm font-medium",
962
+ children: "Wait after a start"
963
+ }),
964
+ T ? /* @__PURE__ */ F(m, {
965
+ ref: O,
966
+ "aria-label": e,
967
+ value: t.kind,
968
+ onValueChange: k,
969
+ disabled: u,
970
+ children: [
971
+ o && /* @__PURE__ */ F(g, {
972
+ value: "skill",
973
+ children: [o.label, /* @__PURE__ */ F("span", {
974
+ className: Q,
975
+ children: [
976
+ "(",
977
+ o.says,
978
+ ")"
979
+ ]
980
+ })]
981
+ }),
982
+ /* @__PURE__ */ F("div", {
983
+ className: "flex items-start gap-2",
984
+ children: [/* @__PURE__ */ P(h, {
985
+ value: "every",
986
+ "aria-label": "A wait you set",
987
+ className: "mt-2"
988
+ }), j]
989
+ }),
990
+ w && /* @__PURE__ */ F(g, {
991
+ value: "work",
992
+ children: ["No wait", /* @__PURE__ */ P("span", {
993
+ className: Q,
994
+ children: s ? "it starts as soon as there is work" : "needs a shell line: without one nothing says when"
995
+ })]
996
+ })
997
+ ]
998
+ }) : j,
999
+ /* @__PURE__ */ P("p", {
1000
+ className: Q,
1001
+ children: l
1002
+ })
1003
+ ]
1004
+ })]
1005
+ });
1006
+ }
1007
+ function Rt(e, t) {
1008
+ return Number(t) === 1 ? Le[e] : `${Le[e]}s`;
1009
+ }
1010
+ function zt({ name: e, draft: t, asSaid: n, start: r, where: i, disabled: a, onChange: o }) {
1011
+ let s = t.kind === "own" ? t : {
1012
+ kind: "own",
1013
+ count: String(r)
1014
+ }, c = /* @__PURE__ */ F("div", {
1015
+ className: A("flex flex-wrap items-center gap-2 text-sm", t.kind !== "own" && "opacity-60"),
1016
+ children: [
1017
+ /* @__PURE__ */ P("span", { children: "Up to" }),
1018
+ /* @__PURE__ */ P(d, {
1019
+ type: "number",
1020
+ min: 1,
1021
+ max: 99,
1022
+ value: s.count,
1023
+ disabled: a,
1024
+ onChange: (e) => o({
1025
+ kind: "own",
1026
+ count: e.target.value
1027
+ }),
1028
+ "aria-label": "How many agents",
1029
+ className: "h-8 w-20 bg-background px-2"
1030
+ }),
1031
+ /* @__PURE__ */ F("span", { children: [Number(s.count) === 1 ? "agent" : "agents", " at once"] })
1032
+ ]
1033
+ });
1034
+ return /* @__PURE__ */ F("fieldset", {
1035
+ disabled: a,
1036
+ className: "space-y-2",
1037
+ children: [n ? /* @__PURE__ */ F(m, {
1038
+ "aria-label": e,
1039
+ value: t.kind,
1040
+ onValueChange: (e) => o(e === "own" ? s : { kind: "skill" }),
1041
+ disabled: a,
1042
+ children: [/* @__PURE__ */ F(g, {
1043
+ value: "skill",
1044
+ children: [n.label, /* @__PURE__ */ F("span", {
1045
+ className: Q,
1046
+ children: [
1047
+ "(",
1048
+ n.says,
1049
+ ")"
1050
+ ]
1051
+ })]
1052
+ }), /* @__PURE__ */ F("div", {
1053
+ className: "flex items-start gap-2",
1054
+ children: [/* @__PURE__ */ P(h, {
1055
+ value: "own",
1056
+ "aria-label": "A number you set",
1057
+ className: "mt-2"
1058
+ }), c]
1059
+ })]
1060
+ }) : c, /* @__PURE__ */ F("p", {
1061
+ className: Q,
1062
+ children: [
1063
+ "A new one starts only when the row is due, and only while fewer than this are working ",
1064
+ i,
1065
+ "."
1066
+ ]
1067
+ })]
1068
+ });
1069
+ }
1070
+ function Bt({ gitHost: e, own: t, pick: n, disabled: r, onChange: i }) {
1071
+ let a = Ie(e, n).map((e) => ({
1072
+ value: e,
1073
+ label: ve(e, t)
1074
+ }));
1075
+ return /* @__PURE__ */ F(_, {
1076
+ items: a,
1077
+ value: n,
1078
+ disabled: r,
1079
+ onValueChange: (e) => i(e),
1080
+ children: [/* @__PURE__ */ P(b, {
1081
+ size: "sm",
1082
+ "aria-label": "What its runs publish",
1083
+ className: "w-56",
1084
+ children: /* @__PURE__ */ P(x, {})
1085
+ }), /* @__PURE__ */ P(v, { children: a.map((e) => /* @__PURE__ */ P(y, {
1086
+ value: e.value,
1087
+ children: e.label
1088
+ }, e.value)) })]
1089
+ });
1090
+ }
1091
+ function Vt({ command: e, schedulerModel: t, agents: n, agent: r, model: i, disabled: a, onChange: o }) {
1092
+ let s = n.find((e) => e.value === r), c = s?.models ?? [], l = r === e.skillModelAgent && e.skillModel !== void 0 ? `As the skill says (${xe(n, r, e.skillModel)})` : r === "claude-code" ? `The scheduler's model${t === void 0 ? "" : ` (${xe(n, r, t)})`}` : `${H[r]}'s own default`, u = B.filter((t) => !e.able.includes(t)), d = [
1093
+ {
1094
+ value: "skill",
1095
+ label: l
1096
+ },
1097
+ ...c,
1098
+ ...i !== "skill" && !c.some((e) => e.value === i) ? [{
1099
+ value: i,
1100
+ label: i
1101
+ }] : []
1102
+ ];
1103
+ return /* @__PURE__ */ F("fieldset", {
1104
+ disabled: a,
1105
+ className: "space-y-2",
1106
+ children: [
1107
+ /* @__PURE__ */ F("div", {
1108
+ className: "flex flex-wrap items-center gap-2 text-sm",
1109
+ children: [/* @__PURE__ */ P(f, {
1110
+ htmlFor: "automation-agent",
1111
+ className: "w-14",
1112
+ children: "Agent"
1113
+ }), /* @__PURE__ */ F(_, {
1114
+ items: B.map((e) => ({
1115
+ value: e,
1116
+ label: H[e]
1117
+ })),
1118
+ value: r,
1119
+ disabled: a,
1120
+ onValueChange: (e) => o({
1121
+ agent: e,
1122
+ model: "skill"
1123
+ }),
1124
+ children: [/* @__PURE__ */ P(b, {
1125
+ id: "automation-agent",
1126
+ size: "sm",
1127
+ className: "w-44",
1128
+ children: /* @__PURE__ */ P(x, {})
1129
+ }), /* @__PURE__ */ P(v, { children: B.map((t) => /* @__PURE__ */ P(y, {
1130
+ value: t,
1131
+ disabled: !e.able.includes(t) && t !== r,
1132
+ children: H[t]
1133
+ }, t)) })]
1134
+ })]
1135
+ }),
1136
+ /* @__PURE__ */ F("div", {
1137
+ className: "flex flex-wrap items-center gap-2 text-sm",
1138
+ children: [/* @__PURE__ */ P(f, {
1139
+ htmlFor: "automation-model",
1140
+ className: "w-14",
1141
+ children: "Model"
1142
+ }), /* @__PURE__ */ F(_, {
1143
+ items: d,
1144
+ value: i,
1145
+ disabled: a,
1146
+ onValueChange: (e) => o({
1147
+ agent: r,
1148
+ model: e
1149
+ }),
1150
+ children: [/* @__PURE__ */ P(b, {
1151
+ id: "automation-model",
1152
+ size: "sm",
1153
+ className: "w-72",
1154
+ children: /* @__PURE__ */ P(x, {})
1155
+ }), /* @__PURE__ */ P(v, { children: d.map((e) => /* @__PURE__ */ P(y, {
1156
+ value: e.value,
1157
+ children: e.label
1158
+ }, e.value)) })]
1159
+ })]
1160
+ }),
1161
+ c.length === 0 && s?.modelsNote !== void 0 && /* @__PURE__ */ P("p", {
1162
+ className: "text-xs text-muted-foreground",
1163
+ children: s.modelsNote
1164
+ }),
1165
+ u.map((e) => /* @__PURE__ */ F("p", {
1166
+ className: "text-xs text-muted-foreground",
1167
+ children: [
1168
+ H[e],
1169
+ " cannot run this row: it reads the project's skills from ",
1170
+ /* @__PURE__ */ P("span", {
1171
+ className: "font-mono",
1172
+ children: U[e]
1173
+ }),
1174
+ ", and this row's skill is not there."
1175
+ ]
1176
+ }, e)),
1177
+ r !== "claude-code" && /* @__PURE__ */ F("p", {
1178
+ className: "text-xs text-muted-foreground",
1179
+ children: [
1180
+ "How much of ",
1181
+ H[r],
1182
+ "'s quota is left cannot be read, so its runs start without that check, and their cost is not recorded."
1183
+ ]
1184
+ })
1185
+ ]
1186
+ });
1187
+ }
1188
+ //#endregion
1189
+ //#region dashboard/AutomationForm.tsx
1190
+ function Ht({ project: e, run: t, onDirty: r, onClose: i, onSaved: s }) {
1191
+ let [c, l] = a(dt), [u, f] = a(!1), [p, h] = a(), [_, v] = a(), y = (e) => {
1192
+ l((t) => ({
1193
+ ...t,
1194
+ ...e
1195
+ })), h(void 0);
1196
+ }, b = ht(c), x = St(c), S = !Ct(c) && !_;
1197
+ n(() => r(S), [S]), n(() => () => r(!1), []);
1198
+ let C = async () => {
1199
+ let e = gt(c), n = vt(c);
1200
+ if (!e || !n) return;
1201
+ f(!0), h(void 0);
1202
+ let r = await t(e);
1203
+ if (!r.ok) return f(!1), h(`Not saved: ${r.error}`);
1204
+ let i = n[0] === "skill" ? void 0 : await t([
1205
+ "pace",
1206
+ c.name.trim(),
1207
+ ...n
1208
+ ]);
1209
+ f(!1), v({
1210
+ command: c.name.trim(),
1211
+ ...Et(r.output),
1212
+ ...i && !i.ok ? { timeNotKept: i.error } : {}
1213
+ }), s();
1214
+ }, w = "mt-3 rounded-md border border-border bg-muted/40 p-4";
1215
+ return _ ? /* @__PURE__ */ F("div", {
1216
+ role: "group",
1217
+ "aria-label": "New automation",
1218
+ className: `${w} text-sm`,
1219
+ children: [
1220
+ /* @__PURE__ */ F("p", { children: [
1221
+ "Saved ",
1222
+ /* @__PURE__ */ P("span", {
1223
+ className: "font-mono",
1224
+ children: _.onThisMachine ? _.command : `/${_.command}`
1225
+ }),
1226
+ " as ",
1227
+ /* @__PURE__ */ P("span", {
1228
+ className: "font-mono",
1229
+ children: _.file
1230
+ }),
1231
+ "."
1232
+ ] }),
1233
+ /* @__PURE__ */ P("p", {
1234
+ className: "mt-2",
1235
+ children: Dt(_)
1236
+ }),
1237
+ _.timeNotKept !== void 0 && /* @__PURE__ */ F("p", {
1238
+ role: "alert",
1239
+ className: "mt-2 text-danger",
1240
+ children: [
1241
+ "Its time of day was not kept: ",
1242
+ _.timeNotKept,
1243
+ ". Its row's Edit sets it."
1244
+ ]
1245
+ }),
1246
+ /* @__PURE__ */ P("p", {
1247
+ className: "mt-2 text-muted-foreground",
1248
+ children: "Its row is in the list now, switched off."
1249
+ }),
1250
+ /* @__PURE__ */ P("div", {
1251
+ className: "mt-3 flex justify-end",
1252
+ children: /* @__PURE__ */ P(o, {
1253
+ size: "sm",
1254
+ autoFocus: !0,
1255
+ onClick: i,
1256
+ children: "Done"
1257
+ })
1258
+ })
1259
+ ]
1260
+ }) : /* @__PURE__ */ F("div", {
1261
+ role: "group",
1262
+ "aria-label": "New automation",
1263
+ onKeyDown: (e) => {
1264
+ e.key === "Escape" && !u && Ct(c) && i();
1265
+ },
1266
+ className: `${w} space-y-5`,
1267
+ children: [
1268
+ /* @__PURE__ */ F("fieldset", {
1269
+ disabled: u,
1270
+ className: "space-y-5",
1271
+ children: [
1272
+ /* @__PURE__ */ P($, {
1273
+ title: "Name",
1274
+ children: /* @__PURE__ */ F("div", {
1275
+ className: "flex items-center gap-1 text-sm",
1276
+ children: [!c.onThisMachine && /* @__PURE__ */ P("span", {
1277
+ className: "font-mono text-muted-foreground",
1278
+ children: "/"
1279
+ }), /* @__PURE__ */ P(d, {
1280
+ type: "text",
1281
+ autoFocus: !0,
1282
+ value: c.name,
1283
+ onChange: (e) => y({ name: e.target.value }),
1284
+ placeholder: "answer-comments",
1285
+ "aria-label": "Name",
1286
+ className: "h-8 w-64 max-w-full bg-background px-2 font-mono"
1287
+ })]
1288
+ })
1289
+ }),
1290
+ /* @__PURE__ */ P($, {
1291
+ title: "What it does",
1292
+ children: /* @__PURE__ */ P(Ft, {
1293
+ project: e,
1294
+ said: c,
1295
+ agent: W,
1296
+ autoFocus: !1,
1297
+ onChange: y
1298
+ })
1299
+ }),
1300
+ /* @__PURE__ */ P($, {
1301
+ title: "When it runs",
1302
+ children: /* @__PURE__ */ P(Lt, {
1303
+ name: "How long the new automation waits after a start",
1304
+ draft: c.pace,
1305
+ work: c.when.trim() === "" ? void 0 : { waitsFor: c.waitsFor.trim() || void 0 },
1306
+ noWait: c.when.trim() !== "",
1307
+ start: {
1308
+ count: 1,
1309
+ unit: "d"
1310
+ },
1311
+ counted: "Counted from its last start.",
1312
+ disabled: u,
1313
+ autoFocus: !1,
1314
+ onChange: (e) => y({ pace: e })
1315
+ })
1316
+ }),
1317
+ /* @__PURE__ */ P($, {
1318
+ title: "Who gets it",
1319
+ children: /* @__PURE__ */ F(m, {
1320
+ "aria-label": "Who gets the automation",
1321
+ value: c.onThisMachine ? "machine" : "project",
1322
+ onValueChange: (e) => y({ onThisMachine: e === "machine" }),
1323
+ disabled: u,
1324
+ children: [/* @__PURE__ */ F(g, {
1325
+ value: "project",
1326
+ children: ["Shared with the project", /* @__PURE__ */ P("span", {
1327
+ className: "text-xs text-muted-foreground",
1328
+ children: "a file you commit; everyone who has the project gets the row, switched off"
1329
+ })]
1330
+ }), /* @__PURE__ */ F(g, {
1331
+ value: "machine",
1332
+ children: ["Only on this machine", /* @__PURE__ */ P("span", {
1333
+ className: "text-xs text-muted-foreground",
1334
+ children: "nothing to commit; nobody else gets the row"
1335
+ })]
1336
+ })]
1337
+ })
1338
+ })
1339
+ ]
1340
+ }),
1341
+ /* @__PURE__ */ P("p", {
1342
+ className: "rounded-md border border-border bg-background px-3 py-2 text-sm",
1343
+ children: b ?? `${x}.`
1344
+ }),
1345
+ p !== void 0 && /* @__PURE__ */ P("p", {
1346
+ role: "alert",
1347
+ className: "text-xs text-danger",
1348
+ children: p
1349
+ }),
1350
+ /* @__PURE__ */ F("div", {
1351
+ className: "flex flex-wrap items-center justify-between gap-3",
1352
+ children: [/* @__PURE__ */ P("p", {
1353
+ className: "min-w-0 flex-1 text-xs text-muted-foreground",
1354
+ children: Mt(c)
1355
+ }), /* @__PURE__ */ F("div", {
1356
+ className: "flex gap-2",
1357
+ children: [/* @__PURE__ */ P(o, {
1358
+ variant: "outline",
1359
+ size: "sm",
1360
+ disabled: u,
1361
+ onClick: i,
1362
+ children: "Cancel"
1363
+ }), /* @__PURE__ */ P(o, {
1364
+ size: "sm",
1365
+ disabled: u || b !== void 0,
1366
+ onClick: () => void C(),
1367
+ children: "Save"
1368
+ })]
1369
+ })]
1370
+ })
1371
+ ]
1372
+ });
1373
+ }
1374
+ //#endregion
1375
+ //#region dashboard/EditPanel.tsx
1376
+ var Ut = (e) => e.charAt(0).toLowerCase() + e.slice(1), Wt = (e) => /[.!?]$/.test(e.trim()) ? e.trim() : `${e.trim()}.`;
1377
+ function Gt(e) {
1378
+ let t = e.pace;
1379
+ if (t === void 0) return ["skill"];
1380
+ if ("work" in t) return ["work"];
1381
+ let n = t.at === void 0 ? void 0 : me(t.at)?.text ?? t.at;
1382
+ return [q(t.every)?.text ?? t.every, ...n === void 0 ? [] : [n]];
1383
+ }
1384
+ function Kt({ project: e, scheduled: t, opened: r, refused: i, schedulerModel: s, agents: c, run: l, reload: u, onDirty: d, onClose: f, onRemoved: p }) {
1385
+ let m = we(t), [h, g] = a(r?.draft), [_] = a(() => r ? mt(r.draft, t) : void 0), [v, y] = a(_), [b, x] = a(() => He(t)), [S, C] = a(() => r ? {
1386
+ kind: "own",
1387
+ count: String(Ge(t))
1388
+ } : Je(t)), [w, T] = a(() => ({
1389
+ agent: J(t),
1390
+ model: t.model ?? "skill"
1391
+ })), [E, D] = a(t.publish), [O, k] = a(!1), [A, j] = a(), [ee, te] = a(!1), [ne, M] = a(r?.version), [re, N] = a(), [I, L] = a(), R = Ye(S), ie = (e) => v && e === String(t.skillAgents ?? 1) ? "skill" : e, z = R === void 0 ? void 0 : ie(R[0]), B = v ? vt(v) : Z(b), V = v !== void 0 && _ !== void 0 && (!bt(v, _) || vt(v)?.join(" ") !== vt(_)?.join(" ")), H = {
1392
+ file: V && v !== void 0 && h !== void 0 && !bt(v, h),
1393
+ pace: B !== void 0 && (v ? V && B.join(" ") !== Gt(t).join(" ") : B.join(" ") !== Z(He(t)).join(" ")),
1394
+ agents: z !== void 0 && z !== ie(Ye(Je(t))[0]),
1395
+ agent: w.agent !== J(t),
1396
+ model: w.model !== (t.model ?? "skill") || w.agent !== J(t) && w.model !== "skill",
1397
+ publish: E !== t.publish
1398
+ }, U = V || H.pace || H.agents || H.agent || H.model || H.publish, W = (v && r ? H.file ? ht(v, r.file) : Ue(v.pace) : Ue(b)) ?? (R ? void 0 : "Type a whole number of agents, from 1 to 99.");
1399
+ n(() => d(U && !I), [U, I]), n(() => () => d(!1), []);
1400
+ let G = (() => {
1401
+ if (z === void 0) return;
1402
+ let e;
1403
+ if (v) {
1404
+ let n = xt(v);
1405
+ if (!n) return;
1406
+ let { pace: r, every: i, when: a, waitsFor: o, ...s } = t, { command: c, on: l, publish: u, ...d } = n;
1407
+ e = {
1408
+ ...s,
1409
+ ...d
1410
+ };
1411
+ } else {
1412
+ if (!Z(b)) return;
1413
+ e = We(t, b);
1414
+ }
1415
+ let { agents: n, ...r } = e, { runsOn: i, model: a, ...o } = {
1416
+ ...r,
1417
+ ...z === "skill" ? {} : { agents: Number(z) },
1418
+ publish: E
1419
+ };
1420
+ return {
1421
+ ...o,
1422
+ ...w.agent === t.home ? {} : { runsOn: w.agent },
1423
+ ...w.model === "skill" ? {} : { model: w.model }
1424
+ };
1425
+ })(), oe = G && `${Be(G)}. ${Ke(G) ? `${qe(Ge(G))}. ` : ""}${Se(G, s, c)}. ${Xe(G)}.`, se = async () => {
1426
+ if (W !== void 0 || B === void 0 || z === void 0) return;
1427
+ let e = [];
1428
+ H.file && v && r && e.push(["It", [..._t(v, r.file), ...ne === void 0 ? [] : [`--was=${ne}`]]]), H.pace && e.push(["The pace", [
1429
+ "pace",
1430
+ t.command,
1431
+ ...B
1432
+ ]]), H.agents && e.push(["The number of agents", [
1433
+ "agents",
1434
+ t.command,
1435
+ z
1436
+ ]]), H.agent && e.push(["The agent", [
1437
+ "agent",
1438
+ t.command,
1439
+ w.agent === t.home ? "skill" : w.agent
1440
+ ]]), H.model && !(H.agent && w.model === "skill") && e.push(["The model", [
1441
+ "model",
1442
+ t.command,
1443
+ w.model
1444
+ ]]), H.publish && e.push(["The publish pick", [
1445
+ "publish",
1446
+ t.command,
1447
+ E
1448
+ ]]), k(!0), j(void 0);
1449
+ let n = re;
1450
+ for (let [t, r] of e) {
1451
+ let e = await l(r);
1452
+ if (!e.ok) {
1453
+ await u().catch(() => {}), k(!1);
1454
+ let r = `${t} was not saved: ${e.error}`;
1455
+ return j(n ? `${Wt(r)} Its words and its pace are saved, in ${n.file}${n.onThisMachine ? "" : ": a change of yours to commit"}.` : r);
1456
+ }
1457
+ r[0] === "edit" && (n = Et(e.output), N(n), g(v), M(n.version));
1458
+ }
1459
+ await u().catch(() => {}), k(!1), n && !n.onThisMachine ? L(n) : f();
1460
+ }, ce = async () => {
1461
+ k(!0), j(void 0);
1462
+ let e = await l(["remove", t.command]);
1463
+ e.ok && p(jt(m, e.output)), await u().catch(() => {}), k(!1), e.ok || j(`It was not removed: ${e.error}`);
1464
+ }, le = () => (te(!1), j(void 0)), ue = "mt-3 rounded-md border border-border bg-muted/40 p-4";
1465
+ if (I) return /* @__PURE__ */ F("div", {
1466
+ role: "group",
1467
+ "aria-label": `Editing ${m}`,
1468
+ className: `${ue} text-sm`,
1469
+ children: [
1470
+ /* @__PURE__ */ F("p", { children: [
1471
+ "Saved ",
1472
+ /* @__PURE__ */ P("span", {
1473
+ className: "font-mono",
1474
+ children: m
1475
+ }),
1476
+ " again, in ",
1477
+ /* @__PURE__ */ P("span", {
1478
+ className: "font-mono",
1479
+ children: I.file
1480
+ }),
1481
+ "."
1482
+ ] }),
1483
+ /* @__PURE__ */ P("p", {
1484
+ className: "mt-2",
1485
+ children: Ot(I)
1486
+ }),
1487
+ /* @__PURE__ */ P("div", {
1488
+ className: "mt-3 flex justify-end",
1489
+ children: /* @__PURE__ */ P(o, {
1490
+ size: "sm",
1491
+ autoFocus: !0,
1492
+ onClick: f,
1493
+ children: "Done"
1494
+ })
1495
+ })
1496
+ ]
1497
+ });
1498
+ if (ee) return /* @__PURE__ */ F("div", {
1499
+ role: "group",
1500
+ "aria-label": `Removing ${m}`,
1501
+ onKeyDown: (e) => {
1502
+ e.key === "Escape" && !O && le();
1503
+ },
1504
+ className: `${ue} text-sm`,
1505
+ children: [
1506
+ /* @__PURE__ */ F("p", { children: [
1507
+ "Remove ",
1508
+ /* @__PURE__ */ P("span", {
1509
+ className: "font-mono",
1510
+ children: m
1511
+ }),
1512
+ "?"
1513
+ ] }),
1514
+ /* @__PURE__ */ P("p", {
1515
+ className: "mt-2",
1516
+ children: At(t)
1517
+ }),
1518
+ A !== void 0 && /* @__PURE__ */ P("p", {
1519
+ role: "alert",
1520
+ className: "mt-2 text-xs text-danger",
1521
+ children: A
1522
+ }),
1523
+ /* @__PURE__ */ F("div", {
1524
+ className: "mt-3 flex justify-end gap-2",
1525
+ children: [/* @__PURE__ */ P(o, {
1526
+ variant: "outline",
1527
+ size: "sm",
1528
+ autoFocus: !0,
1529
+ disabled: O,
1530
+ onClick: le,
1531
+ children: "Cancel"
1532
+ }), /* @__PURE__ */ P(o, {
1533
+ variant: "destructive",
1534
+ size: "sm",
1535
+ disabled: O,
1536
+ onClick: () => void ce(),
1537
+ children: "Remove"
1538
+ })]
1539
+ })
1540
+ ]
1541
+ });
1542
+ let K = t.onThisMachine ? "on this machine" : "on any machine that shares this repository", de = t.every === void 0 ? void 0 : q(t.every), fe = t.onThisMachine || t.editable ? "As it was saved" : "As the skill says";
1543
+ return /* @__PURE__ */ F("div", {
1544
+ role: "group",
1545
+ "aria-label": `Editing ${m}`,
1546
+ onKeyDown: (e) => {
1547
+ e.key === "Escape" && !O && !U && f();
1548
+ },
1549
+ className: `${ue} space-y-5`,
1550
+ children: [
1551
+ /* @__PURE__ */ P($, {
1552
+ title: "What it does",
1553
+ children: v ? /* @__PURE__ */ P("fieldset", {
1554
+ disabled: O,
1555
+ className: "space-y-2",
1556
+ children: /* @__PURE__ */ P(Ft, {
1557
+ project: e,
1558
+ said: v,
1559
+ agent: w.agent,
1560
+ autoFocus: !0,
1561
+ onChange: (e) => (y({
1562
+ ...v,
1563
+ ...e
1564
+ }), j(void 0))
1565
+ })
1566
+ }) : /* @__PURE__ */ P(It, {
1567
+ description: t.description,
1568
+ when: t.when,
1569
+ waitsFor: t.waitsFor,
1570
+ where: i === void 0 ? t.onThisMachine ? `Its words cannot be changed here: its file was changed by hand since it was saved. They are changed in the file itself, ${ae}/${t.command}.md.` : `Its words are its skill's, ${m}: they are changed in the skill's file, by whoever writes the skill.` : `Its words cannot be changed here: ${i}`
1571
+ })
1572
+ }),
1573
+ /* @__PURE__ */ P($, {
1574
+ title: "When it runs",
1575
+ children: v ? /* @__PURE__ */ P(Lt, {
1576
+ name: `How long ${m} waits after a start`,
1577
+ draft: v.pace,
1578
+ work: v.when.trim() === "" ? void 0 : { waitsFor: v.waitsFor.trim() || void 0 },
1579
+ noWait: v.when.trim() !== "",
1580
+ start: {
1581
+ count: 1,
1582
+ unit: "d"
1583
+ },
1584
+ counted: `Counted from its last start, ${K}.`,
1585
+ disabled: O,
1586
+ autoFocus: !1,
1587
+ onChange: (e) => (y({
1588
+ ...v,
1589
+ pace: e
1590
+ }), j(void 0))
1591
+ }) : /* @__PURE__ */ P(Lt, {
1592
+ name: `How long ${m} waits after a start`,
1593
+ draft: b,
1594
+ work: t.when === void 0 ? void 0 : {
1595
+ waitsFor: t.waitsFor,
1596
+ checkEvery: t.checkEvery
1597
+ },
1598
+ asSaid: {
1599
+ label: fe,
1600
+ says: t.every === void 0 ? "no wait" : Re(t.every)
1601
+ },
1602
+ noWait: t.when !== void 0 && t.every !== void 0,
1603
+ start: {
1604
+ count: de?.count ?? 1,
1605
+ unit: de?.unit ?? "d"
1606
+ },
1607
+ counted: `Counted from its last start, ${K}.`,
1608
+ disabled: O,
1609
+ autoFocus: !0,
1610
+ onChange: (e) => (x(e), j(void 0))
1611
+ })
1612
+ }),
1613
+ /* @__PURE__ */ P($, {
1614
+ title: "How many at once",
1615
+ children: /* @__PURE__ */ P(zt, {
1616
+ name: `How many of ${m} at once`,
1617
+ draft: S,
1618
+ asSaid: v ? void 0 : {
1619
+ label: fe,
1620
+ says: Ut(qe(t.skillAgents ?? 1))
1621
+ },
1622
+ start: t.skillAgents ?? 1,
1623
+ where: K,
1624
+ disabled: O,
1625
+ onChange: (e) => (C(e), j(void 0))
1626
+ })
1627
+ }),
1628
+ /* @__PURE__ */ P($, {
1629
+ title: "What it runs on",
1630
+ children: /* @__PURE__ */ P(Vt, {
1631
+ command: t,
1632
+ schedulerModel: s,
1633
+ agents: c,
1634
+ agent: w.agent,
1635
+ model: w.model,
1636
+ disabled: O,
1637
+ onChange: (e) => (T(e), j(void 0))
1638
+ })
1639
+ }),
1640
+ /* @__PURE__ */ F($, {
1641
+ title: "What its runs publish",
1642
+ children: [/* @__PURE__ */ P(Bt, {
1643
+ gitHost: e.gitHost,
1644
+ own: Y(t),
1645
+ pick: E,
1646
+ disabled: O,
1647
+ onChange: (e) => (D(e), j(void 0))
1648
+ }), t.each && /* @__PURE__ */ F("p", {
1649
+ className: "text-sm text-muted-foreground",
1650
+ children: ["A run it continues goes on with the coding agent, model and publish level that started it", "."]
1651
+ })]
1652
+ }),
1653
+ /* @__PURE__ */ P("p", {
1654
+ className: "rounded-md border border-border bg-background px-3 py-2 text-sm",
1655
+ children: W ?? (U ? oe : `${oe} Nothing is changed yet.`)
1656
+ }),
1657
+ A !== void 0 && /* @__PURE__ */ P("p", {
1658
+ role: "alert",
1659
+ className: "text-xs text-danger",
1660
+ children: A
1661
+ }),
1662
+ /* @__PURE__ */ F("div", {
1663
+ className: "flex flex-wrap items-center justify-between gap-3",
1664
+ children: [/* @__PURE__ */ P("p", {
1665
+ className: "min-w-0 flex-1 text-xs text-muted-foreground",
1666
+ children: kt(r)
1667
+ }), /* @__PURE__ */ F("div", {
1668
+ className: "flex gap-2",
1669
+ children: [
1670
+ t.editable && r && /* @__PURE__ */ P(o, {
1671
+ variant: "outline",
1672
+ size: "sm",
1673
+ disabled: O,
1674
+ onClick: () => (te(!0), j(void 0)),
1675
+ className: "text-danger",
1676
+ children: "Remove"
1677
+ }),
1678
+ /* @__PURE__ */ P(o, {
1679
+ variant: "outline",
1680
+ size: "sm",
1681
+ disabled: O,
1682
+ onClick: f,
1683
+ children: "Cancel"
1684
+ }),
1685
+ /* @__PURE__ */ P(o, {
1686
+ size: "sm",
1687
+ disabled: O || W !== void 0 || !U,
1688
+ onClick: () => void se(),
1689
+ children: "Save"
1690
+ })
1691
+ ]
1692
+ })]
1693
+ })
1694
+ ]
1695
+ });
1696
+ }
1697
+ //#endregion
1698
+ //#region dashboard/AutomationsPage.tsx
1699
+ var qt = [], Jt = "no skill of this project schedules a command";
1700
+ function Yt({ projects: e }) {
1701
+ let t = M(), r = ne(), { value: s, loaded: c, reload: l } = re(() => je(t, e), qt, 1e4, [e.map((e) => e.id).join(",")]), u = i(/* @__PURE__ */ new Map()), d = s.map((e) => {
1702
+ e.error === void 0 && u.current.set(e.project.id, e);
1703
+ let t = u.current.get(e.project.id);
1704
+ return e.error !== void 0 && t ? {
1705
+ ...t,
1706
+ error: e.error
1707
+ } : e;
1708
+ }), [f, p] = a([]), [m, h] = a(), [g, _] = a(), [v, y] = a(), [b, x] = a(!1), S = i(!1), C = (e) => {
1709
+ S.current = e, x(e);
1710
+ }, [T, j] = a(), N = i(0), I = b && (g !== void 0 || v !== void 0);
1711
+ n(() => {
1712
+ c && (g && !d.some((e) => e.commands.some((t) => `${e.project.id}/${t.command}` === g.id)) && _(void 0), v !== void 0 && !d.some((e) => e.project.id === v) && y(void 0));
1713
+ }, [
1714
+ d,
1715
+ c,
1716
+ g,
1717
+ v
1718
+ ]);
1719
+ let L = i(/* @__PURE__ */ new Map()), R = (e) => {
1720
+ _((t) => t?.id === e ? void 0 : t), setTimeout(() => L.current.get(e)?.focus());
1721
+ }, ie = i(Promise.resolve()), z = (e, n) => {
1722
+ let r = ie.current.then(() => t.runCommand(e.id, n).catch((e) => ({
1723
+ ok: !1,
1724
+ error: e instanceof Error ? e.message : String(e)
1725
+ })));
1726
+ return ie.current = r, r;
1727
+ }, ae = (e, n) => t.runCommand(e.id, n).catch((e) => ({
1728
+ ok: !1,
1729
+ error: e instanceof Error ? e.message : String(e)
1730
+ })), B = async (e, t, n, r) => {
1731
+ p((t) => [...t, e]), h((t) => t?.id === e ? void 0 : t);
1732
+ let i = await n;
1733
+ await l().catch(() => {}), p((t) => t.filter((n, r) => r !== t.indexOf(e)));
1734
+ let a = r(i);
1735
+ a && h({
1736
+ id: e,
1737
+ ...a
1738
+ });
1739
+ }, V = async (e, t, n) => {
1740
+ let r = ++N.current;
1741
+ if (h((t) => t?.id === e ? void 0 : t), !n.editable) return y(void 0), _({ id: e });
1742
+ p((t) => [...t, e]);
1743
+ let i = await ae(t, ["show", n.command]);
1744
+ if (p((t) => t.filter((n, r) => r !== t.indexOf(e))), N.current !== r || S.current) return;
1745
+ let a = i.ok ? pt(i.output) : void 0;
1746
+ y(void 0), _({
1747
+ id: e,
1748
+ ...a ? { opened: a } : { refused: i.ok ? "its file holds something this panel cannot show" : i.error }
1749
+ });
1750
+ };
1751
+ return /* @__PURE__ */ F("div", {
1752
+ className: "flex min-h-0 flex-1 flex-col overflow-y-auto p-6 max-md:p-4",
1753
+ children: [
1754
+ /* @__PURE__ */ P("h1", {
1755
+ className: "text-lg font-semibold",
1756
+ children: "Automations"
1757
+ }),
1758
+ /* @__PURE__ */ P("p", {
1759
+ className: "mt-1 text-sm text-muted-foreground",
1760
+ children: "What starts by itself while nobody is at the keyboard. Every row starts switched off: it runs on this machine only once you switch it on here."
1761
+ }),
1762
+ !c && /* @__PURE__ */ P("p", {
1763
+ className: "mt-6 text-sm text-muted-foreground",
1764
+ children: "Loading…"
1765
+ }),
1766
+ d.map((e) => {
1767
+ let n = lt(e), i = e.lastTick?.note, a = [["Your automations", e.commands.filter(Y)], ["From the project's skills", e.commands.filter((e) => !Y(e))]];
1768
+ return /* @__PURE__ */ F("section", {
1769
+ "aria-label": e.project.name,
1770
+ className: "mt-6",
1771
+ children: [
1772
+ /* @__PURE__ */ F("div", {
1773
+ className: "flex flex-wrap items-center gap-x-3 gap-y-1 border-b border-border pb-2",
1774
+ children: [
1775
+ /* @__PURE__ */ P("h2", {
1776
+ className: "text-sm font-semibold",
1777
+ children: e.project.name
1778
+ }),
1779
+ /* @__PURE__ */ F("span", {
1780
+ className: A("text-xs font-medium", n.tone),
1781
+ children: ["Scheduler ", n.label]
1782
+ }),
1783
+ e.model && /* @__PURE__ */ P("span", {
1784
+ className: "text-xs text-muted-foreground",
1785
+ children: e.model
1786
+ }),
1787
+ e.lastTick && /* @__PURE__ */ F("span", {
1788
+ className: "text-xs text-muted-foreground",
1789
+ children: [
1790
+ "last tick",
1791
+ " ",
1792
+ /* @__PURE__ */ F(E, { children: [/* @__PURE__ */ P(O, {
1793
+ render: /* @__PURE__ */ P("span", { className: "tabular-nums" }),
1794
+ children: ee(e.lastTick.at)
1795
+ }), /* @__PURE__ */ P(D, { children: te(e.lastTick.at) })] }),
1796
+ i !== void 0 && i !== "off" && i !== Jt && `: ${i}`
1797
+ ]
1798
+ }),
1799
+ e.error === void 0 && v !== e.project.id && /* @__PURE__ */ P(o, {
1800
+ variant: "outline",
1801
+ size: "xs",
1802
+ disabled: I,
1803
+ onClick: () => {
1804
+ N.current++, _(void 0), y(e.project.id);
1805
+ },
1806
+ "aria-label": `New automation in ${e.project.name}`,
1807
+ className: "ml-auto",
1808
+ children: "New automation"
1809
+ })
1810
+ ]
1811
+ }),
1812
+ v === e.project.id && /* @__PURE__ */ P(Ht, {
1813
+ project: e.project,
1814
+ run: (t) => z(e.project, t),
1815
+ onDirty: C,
1816
+ onClose: () => y(void 0),
1817
+ onSaved: () => void l().catch(() => {})
1818
+ }),
1819
+ T?.project === e.project.id && /* @__PURE__ */ F("div", {
1820
+ role: "status",
1821
+ "aria-label": "Removed",
1822
+ className: "mt-3 flex items-start justify-between gap-3 rounded-md border border-border bg-muted/40 p-3 text-sm",
1823
+ children: [/* @__PURE__ */ P("p", { children: T.text }), /* @__PURE__ */ P(o, {
1824
+ variant: "outline",
1825
+ size: "sm",
1826
+ onClick: () => j(void 0),
1827
+ children: "Done"
1828
+ })]
1829
+ }),
1830
+ e.error !== void 0 && /* @__PURE__ */ P("p", {
1831
+ role: "alert",
1832
+ className: "py-3 text-sm text-danger",
1833
+ children: `The scheduler could not be read: ${e.error}`
1834
+ }),
1835
+ e.error === void 0 && !e.on && /* @__PURE__ */ P("p", {
1836
+ className: "py-3 text-sm text-muted-foreground",
1837
+ children: "The scheduler is off in this project, so nothing here starts by itself. It starts with the dashboard once the project has run `npx @openagt/skill-scheduler@0.1 init`, or by hand with `npx @openagt/skill-scheduler@0.1 start`."
1838
+ }),
1839
+ e.error === void 0 && e.on && !e.running && /* @__PURE__ */ P("p", {
1840
+ className: "py-3 text-sm text-warning",
1841
+ children: "The scheduler is on but its process is not running, so nothing here starts by itself. `npx @openagt/skill-scheduler@0.1 start`, run in the project, starts it."
1842
+ }),
1843
+ e.unreadable.map((e, t) => /* @__PURE__ */ P("p", {
1844
+ role: "alert",
1845
+ className: "py-3 text-sm text-danger",
1846
+ children: Te(e)
1847
+ }, `${t}/${e.skill}`)),
1848
+ e.error === void 0 && e.commands.length === 0 && e.unreadable.length === 0 && /* @__PURE__ */ P("p", {
1849
+ className: "py-3 text-sm text-muted-foreground",
1850
+ children: "Nothing here: no skill of this project says it can be scheduled."
1851
+ }),
1852
+ a.map(([n, i]) => i.length > 0 && /* @__PURE__ */ F("div", {
1853
+ role: "group",
1854
+ "aria-label": n,
1855
+ className: "mt-4",
1856
+ children: [/* @__PURE__ */ P("h3", {
1857
+ className: "text-xs font-semibold uppercase tracking-wide text-muted-foreground",
1858
+ children: n
1859
+ }), /* @__PURE__ */ P("ul", {
1860
+ className: "mt-2 divide-y divide-border rounded-lg border border-border",
1861
+ children: i.map((n) => {
1862
+ let i = `${e.project.id}/${n.command}`, a = we(n), s = f.includes(i), c = g?.id === i ? g : void 0, d = m?.id === i ? m : void 0;
1863
+ return /* @__PURE__ */ F("li", {
1864
+ "aria-label": a,
1865
+ className: A("p-4", s && "opacity-60"),
1866
+ children: [
1867
+ /* @__PURE__ */ F("div", {
1868
+ className: "flex items-start justify-between gap-4 max-md:flex-col",
1869
+ children: [/* @__PURE__ */ F("div", {
1870
+ className: "min-w-0",
1871
+ children: [
1872
+ /* @__PURE__ */ F("p", {
1873
+ className: "flex flex-wrap items-baseline gap-x-2 text-sm",
1874
+ children: [/* @__PURE__ */ P("span", {
1875
+ className: "font-mono font-medium",
1876
+ children: a
1877
+ }), Y(n) && /* @__PURE__ */ P("span", {
1878
+ className: "text-xs text-info",
1879
+ children: n.onThisMachine ? "only on this machine" : "shared with the project"
1880
+ })]
1881
+ }),
1882
+ n.description && /* @__PURE__ */ P("p", {
1883
+ className: "line-clamp-2 text-sm text-muted-foreground",
1884
+ children: n.description
1885
+ }),
1886
+ /* @__PURE__ */ P(Zt, {
1887
+ host: t,
1888
+ project: e.project,
1889
+ scheduled: n
1890
+ }),
1891
+ !c && /* @__PURE__ */ P(Qt, {
1892
+ scheduled: n,
1893
+ schedulerModel: e.model,
1894
+ agents: r
1895
+ })
1896
+ ]
1897
+ }), /* @__PURE__ */ F("div", {
1898
+ className: "flex shrink-0 items-center gap-2",
1899
+ children: [
1900
+ /* @__PURE__ */ P(o, {
1901
+ variant: "outline",
1902
+ size: "xs",
1903
+ disabled: s || $e(n) !== void 0,
1904
+ onClick: () => void B(i, e.project, ae(e.project, ["now", n.command]), Xt),
1905
+ "aria-label": `Run ${a} now`,
1906
+ children: "Run now"
1907
+ }),
1908
+ /* @__PURE__ */ P("button", {
1909
+ type: "button",
1910
+ ref: (e) => {
1911
+ e ? L.current.set(i, e) : L.current.delete(i);
1912
+ },
1913
+ disabled: s || c !== void 0 || I,
1914
+ onClick: () => void V(i, e.project, n),
1915
+ "aria-label": `Edit ${a}`,
1916
+ className: k({
1917
+ variant: "outline",
1918
+ size: "xs"
1919
+ }),
1920
+ children: "Edit"
1921
+ }),
1922
+ /* @__PURE__ */ P(w, {
1923
+ checked: n.on,
1924
+ disabled: s,
1925
+ onCheckedChange: (t) => void B(i, e.project, z(e.project, [
1926
+ "switch",
1927
+ n.command,
1928
+ t ? "on" : "off"
1929
+ ]), (e) => e.ok ? void 0 : { failed: `The switch was not saved: ${e.error}` }),
1930
+ "aria-label": `Run ${a} by itself`
1931
+ })
1932
+ ]
1933
+ })]
1934
+ }),
1935
+ c && /* @__PURE__ */ P(Kt, {
1936
+ project: e.project,
1937
+ scheduled: n,
1938
+ opened: c.opened,
1939
+ refused: c.refused,
1940
+ schedulerModel: e.model,
1941
+ agents: r,
1942
+ run: (t) => z(e.project, t),
1943
+ reload: l,
1944
+ onDirty: C,
1945
+ onClose: () => R(i),
1946
+ onRemoved: (t) => {
1947
+ _(void 0), j({
1948
+ project: e.project.id,
1949
+ text: t
1950
+ });
1951
+ let r = u.current.get(e.project.id);
1952
+ r && u.current.set(e.project.id, {
1953
+ ...r,
1954
+ commands: r.commands.filter((e) => e.command !== n.command)
1955
+ });
1956
+ }
1957
+ }),
1958
+ d?.started !== void 0 && /* @__PURE__ */ F("p", {
1959
+ role: "status",
1960
+ className: "mt-2 text-xs text-success",
1961
+ children: [
1962
+ d.resumed ? "Resumed a run." : "Started a run.",
1963
+ " ",
1964
+ d.started !== "" && /* @__PURE__ */ P("button", {
1965
+ type: "button",
1966
+ onClick: () => t.openAgent(e.project.id, d.started),
1967
+ className: "underline",
1968
+ children: "Open it"
1969
+ })
1970
+ ]
1971
+ }),
1972
+ d?.note !== void 0 && /* @__PURE__ */ P("p", {
1973
+ role: "status",
1974
+ className: "mt-2 text-xs text-muted-foreground",
1975
+ children: d.note
1976
+ }),
1977
+ d?.failed !== void 0 && /* @__PURE__ */ P("p", {
1978
+ role: "alert",
1979
+ className: "mt-2 text-xs text-danger",
1980
+ children: d.failed
1981
+ })
1982
+ ]
1983
+ }, i);
1984
+ })
1985
+ })]
1986
+ }, n))
1987
+ ]
1988
+ }, e.project.id);
1989
+ })
1990
+ ]
1991
+ });
1992
+ }
1993
+ function Xt(e) {
1994
+ if (e.ok) {
1995
+ let t = typeof e.output == "object" && e.output !== null ? e.output : {};
1996
+ return {
1997
+ started: typeof t.run == "string" ? t.run : "",
1998
+ ...t.resumed === !0 ? { resumed: !0 } : {}
1999
+ };
2000
+ }
2001
+ if (e.error === "not due") return { note: "Nothing started. No work: its shell line printed nothing." };
2002
+ if (e.error.startsWith("cap reached ")) return { note: `Nothing started. ${tt(e.error)}.` };
2003
+ if (e.error.endsWith(" took too long")) return { failed: "No answer in time. A run may have started all the same: if one did, the row says when it last ran." };
2004
+ let t = tt(e.error) ?? e.error;
2005
+ return { failed: `Nothing started. ${/[.!?]$/.test(t) ? t : `${t}.`}` };
2006
+ }
2007
+ function Zt({ host: e, project: t, scheduled: n }) {
2008
+ let r = n.lastRun, i = Ze(n);
2009
+ return /* @__PURE__ */ F("p", {
2010
+ className: "mt-1 flex flex-wrap items-center gap-x-2 text-xs",
2011
+ children: [
2012
+ /* @__PURE__ */ F("span", {
2013
+ className: A("inline-flex items-center gap-1.5 font-medium", n.on ? "text-success" : "text-muted-foreground"),
2014
+ children: [/* @__PURE__ */ P("span", {
2015
+ "aria-hidden": !0,
2016
+ className: A("h-1.5 w-1.5 rounded-full", n.on ? "bg-success" : "bg-muted-foreground/50")
2017
+ }), n.on ? "On" : "Off"]
2018
+ }),
2019
+ /* @__PURE__ */ P("span", {
2020
+ "aria-hidden": !0,
2021
+ className: "text-muted-foreground",
2022
+ children: "·"
2023
+ }),
2024
+ r === void 0 ? /* @__PURE__ */ P("span", {
2025
+ className: "text-muted-foreground",
2026
+ children: "Never ran"
2027
+ }) : /* @__PURE__ */ F(E, { children: [/* @__PURE__ */ F(O, {
2028
+ render: /* @__PURE__ */ P("button", {
2029
+ type: "button",
2030
+ onClick: () => e.openAgent(t.id, r.id),
2031
+ className: A("underline", r.failed ? "text-danger" : "text-muted-foreground hover:text-foreground")
2032
+ }),
2033
+ children: [
2034
+ r.failed ? "Last run failed" : "Last ran",
2035
+ " ",
2036
+ /* @__PURE__ */ P("span", {
2037
+ className: "tabular-nums",
2038
+ children: ee(r.at)
2039
+ })
2040
+ ]
2041
+ }), /* @__PURE__ */ P(D, { children: te(r.at) })] }),
2042
+ i !== void 0 && /* @__PURE__ */ F(N, { children: [/* @__PURE__ */ P("span", {
2043
+ "aria-hidden": !0,
2044
+ className: "text-muted-foreground",
2045
+ children: "·"
2046
+ }), /* @__PURE__ */ P("span", {
2047
+ className: $e(n) ? "text-warning" : "text-muted-foreground",
2048
+ children: i
2049
+ })] })
2050
+ ]
2051
+ });
2052
+ }
2053
+ function Qt({ scheduled: e, schedulerModel: t, agents: n }) {
2054
+ let r = !Y(e);
2055
+ return /* @__PURE__ */ F("p", {
2056
+ className: "mt-1 flex flex-wrap gap-x-2 text-xs text-muted-foreground",
2057
+ children: [
2058
+ /* @__PURE__ */ P("span", { children: Be(e) }),
2059
+ r && Ve(e) && /* @__PURE__ */ F(N, { children: [/* @__PURE__ */ P("span", {
2060
+ "aria-hidden": !0,
2061
+ children: "·"
2062
+ }), /* @__PURE__ */ P("span", {
2063
+ className: "text-info",
2064
+ children: "your pick"
2065
+ })] }),
2066
+ Ke(e) && /* @__PURE__ */ F(N, { children: [
2067
+ /* @__PURE__ */ P("span", {
2068
+ "aria-hidden": !0,
2069
+ children: "·"
2070
+ }),
2071
+ /* @__PURE__ */ P("span", { children: qe(Ge(e)) }),
2072
+ r && e.agents !== void 0 && /* @__PURE__ */ F(N, { children: [/* @__PURE__ */ P("span", {
2073
+ "aria-hidden": !0,
2074
+ children: "·"
2075
+ }), /* @__PURE__ */ P("span", {
2076
+ className: "text-info",
2077
+ children: "your pick"
2078
+ })] })
2079
+ ] }),
2080
+ /* @__PURE__ */ P("span", {
2081
+ "aria-hidden": !0,
2082
+ children: "·"
2083
+ }),
2084
+ /* @__PURE__ */ P("span", { children: Se(e, t, n) }),
2085
+ r && (e.runsOn !== void 0 || e.model !== void 0) && /* @__PURE__ */ F(N, { children: [/* @__PURE__ */ P("span", {
2086
+ "aria-hidden": !0,
2087
+ children: "·"
2088
+ }), /* @__PURE__ */ P("span", {
2089
+ className: "text-info",
2090
+ children: "your pick"
2091
+ })] }),
2092
+ /* @__PURE__ */ P("span", {
2093
+ "aria-hidden": !0,
2094
+ children: "·"
2095
+ }),
2096
+ /* @__PURE__ */ P("span", { children: Xe(e) })
2097
+ ]
2098
+ });
2099
+ }
2100
+ //#endregion
2101
+ //#region dashboard/SchedulerCard.tsx
2102
+ var $t = [];
2103
+ function en(e, t) {
2104
+ if (e !== 0) return t === 0 ? e === 1 ? "Its one automation is switched off" : `All ${e} are switched off` : e === 1 ? "1 more is switched off" : `${e} more are switched off`;
2105
+ }
2106
+ function tn({ projects: e }) {
2107
+ let t = M(), { value: n, loaded: r } = re(() => je(t, e), $t, 1e4, [e.map((e) => e.id).join(",")]), i = () => t.openPage("automations");
2108
+ return /* @__PURE__ */ F(s, { children: [/* @__PURE__ */ F(l, { children: [/* @__PURE__ */ P(u, {
2109
+ icon: /* @__PURE__ */ P(z, {
2110
+ className: "h-4 w-4 text-muted-foreground",
2111
+ "aria-hidden": !0
2112
+ }),
2113
+ segment: "automations",
2114
+ onOpen: i,
2115
+ children: "Automations"
2116
+ }), /* @__PURE__ */ P("p", {
2117
+ className: "text-xs text-muted-foreground",
2118
+ children: "What starts by itself while nobody is at the keyboard"
2119
+ })] }), /* @__PURE__ */ P(c, { children: r ? /* @__PURE__ */ P("ul", {
2120
+ className: "space-y-4",
2121
+ children: n.map((n) => {
2122
+ let r = lt(n), a = at(n), o = n.commands.filter((e) => e.on), s = en(n.commands.length - o.length, o.length);
2123
+ return /* @__PURE__ */ F("li", {
2124
+ "aria-label": n.project.name,
2125
+ children: [
2126
+ /* @__PURE__ */ F("div", {
2127
+ className: "flex items-center gap-2",
2128
+ children: [
2129
+ e.length > 1 && /* @__PURE__ */ P("span", {
2130
+ className: "truncate text-sm font-medium",
2131
+ children: n.project.name
2132
+ }),
2133
+ /* @__PURE__ */ F("span", {
2134
+ className: A("shrink-0 text-xs font-medium", r.tone),
2135
+ children: ["Scheduler ", r.label]
2136
+ }),
2137
+ n.keepAlive && /* @__PURE__ */ P("span", {
2138
+ className: "shrink-0 rounded-full bg-muted px-2 py-0.5 text-xs text-muted-foreground",
2139
+ children: "keep-alive"
2140
+ }),
2141
+ n.lastTick && /* @__PURE__ */ F("span", {
2142
+ className: "ml-auto shrink-0 text-xs text-muted-foreground",
2143
+ children: [
2144
+ "looked",
2145
+ " ",
2146
+ /* @__PURE__ */ F(E, { children: [/* @__PURE__ */ P(O, {
2147
+ render: /* @__PURE__ */ P("span", { className: "tabular-nums" }),
2148
+ children: ee(n.lastTick.at)
2149
+ }), /* @__PURE__ */ F(D, { children: ["The scheduler last looked ", te(n.lastTick.at)] })] })
2150
+ ]
2151
+ })
2152
+ ]
2153
+ }),
2154
+ n.error !== void 0 && /* @__PURE__ */ P("p", {
2155
+ className: "mt-1 text-xs text-muted-foreground",
2156
+ children: n.error
2157
+ }),
2158
+ n.lastTick?.note && a === void 0 && /* @__PURE__ */ F("p", {
2159
+ className: "mt-1 text-xs text-muted-foreground",
2160
+ children: ["Its last look: ", n.lastTick.note]
2161
+ }),
2162
+ a !== void 0 && n.error === void 0 && o.length > 0 && /* @__PURE__ */ F("p", {
2163
+ className: "mt-1 text-xs text-warning",
2164
+ children: [a, ": nothing starts by itself."]
2165
+ }),
2166
+ o.length > 0 && /* @__PURE__ */ P("ul", {
2167
+ className: "mt-2 space-y-1.5",
2168
+ children: o.map((e) => /* @__PURE__ */ P(nn, {
2169
+ command: e,
2170
+ stopped: a !== void 0,
2171
+ lookedAt: n.lastTick?.at,
2172
+ onOpenRun: (e) => t.openAgent(n.project.id, e)
2173
+ }, e.command))
2174
+ }),
2175
+ n.unreadable.map((e) => /* @__PURE__ */ P("p", {
2176
+ className: "mt-1.5 text-xs text-warning",
2177
+ children: Te(e)
2178
+ }, e.skill)),
2179
+ s !== void 0 && /* @__PURE__ */ F("p", {
2180
+ className: "mt-2 text-xs text-muted-foreground",
2181
+ children: [
2182
+ s,
2183
+ ".",
2184
+ " ",
2185
+ o.length === 0 && /* @__PURE__ */ P("a", {
2186
+ href: t.pageHref("automations"),
2187
+ onClick: (e) => {
2188
+ e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || (e.preventDefault(), i());
2189
+ },
2190
+ className: "underline hover:text-foreground",
2191
+ children: "Switch one on"
2192
+ })
2193
+ ]
2194
+ })
2195
+ ]
2196
+ }, n.project.id);
2197
+ })
2198
+ }) : /* @__PURE__ */ P("p", {
2199
+ className: "py-2 text-sm text-muted-foreground",
2200
+ children: "Loading…"
2201
+ }) })] });
2202
+ }
2203
+ function nn({ command: e, stopped: t, lookedAt: n, onOpenRun: r }) {
2204
+ let i = e.decision?.run;
2205
+ return /* @__PURE__ */ F("li", {
2206
+ className: "flex flex-wrap items-baseline gap-x-3 gap-y-0.5 text-sm",
2207
+ children: [
2208
+ /* @__PURE__ */ P("span", {
2209
+ className: "min-w-0 truncate font-mono text-[13px]",
2210
+ children: we(e)
2211
+ }),
2212
+ !t && /* @__PURE__ */ P("span", {
2213
+ className: "text-xs text-muted-foreground",
2214
+ children: it(e)
2215
+ }),
2216
+ i !== void 0 && /* @__PURE__ */ F("button", {
2217
+ type: "button",
2218
+ onClick: () => r(i),
2219
+ className: "text-xs text-info hover:underline",
2220
+ children: [
2221
+ "Started an agent",
2222
+ n === void 0 ? "" : ` ${ee(n)}`,
2223
+ ": open it"
2224
+ ]
2225
+ })
2226
+ ]
2227
+ });
2228
+ }
2229
+ //#endregion
2230
+ //#region dashboard/SchedulerSettings.tsx
2231
+ var rn = [], an = 500;
2232
+ function on({ projects: e }) {
2233
+ let t = M(), { value: r, reload: o } = re(() => je(t, e), rn, 1e4, [e.map((e) => e.id).join(",")]), [s, c] = a(), l = Me(r), [u, f] = a(), [m, h] = a(), g = i(void 0), _ = i(Promise.resolve());
2234
+ n(() => {
2235
+ u !== void 0 && l === u && f(void 0);
2236
+ }, [l, u]), n(() => () => clearTimeout(g.current), []);
2237
+ let v = u ?? l, y = (n) => {
2238
+ f(n), clearTimeout(g.current), g.current = setTimeout(() => {
2239
+ c(void 0), _.current = _.current.then(async () => {
2240
+ let r = await Fe(t, e, n).catch((e) => ({
2241
+ ok: !1,
2242
+ error: e instanceof Error ? e.message : String(e)
2243
+ }));
2244
+ r.ok || (f(void 0), c(`The spend offset was not saved: ${r.error}`)), await o().catch(() => {});
2245
+ });
2246
+ }, an);
2247
+ }, b = Ne(r), x = r.filter((e) => e.error !== void 0);
2248
+ return e.length === 0 ? null : /* @__PURE__ */ F(C, {
2249
+ description: "How far past the quota scheduled work may go, on this machine. What a project starts by itself is on the Automations page.",
2250
+ children: [
2251
+ v !== void 0 && /* @__PURE__ */ P(S, {
2252
+ label: "Spend offset",
2253
+ description: `How far the scheduler may start work past the quota boundary, in percentage points (max ${p}). Negative holds it back; positive lets it borrow from the days ahead. The handle on the usage bar moves the same number.${b.length > 0 ? ` Shown: the loosest. ${b.map((e) => `${e.name} is at ${e.offset}`).join(", ")}; saving sets each of them to the same number.` : ""}`,
2254
+ control: /* @__PURE__ */ P(d, {
2255
+ type: "number",
2256
+ value: m ?? String(Math.round(v * 10) / 10),
2257
+ min: -p,
2258
+ max: p,
2259
+ onChange: (e) => {
2260
+ let t = e.target.value;
2261
+ h(t);
2262
+ let n = Pe(t);
2263
+ n !== void 0 && y(n);
2264
+ },
2265
+ onBlur: () => h(void 0),
2266
+ "aria-label": "Spend offset",
2267
+ className: "h-8 w-24 bg-background px-2"
2268
+ })
2269
+ }),
2270
+ x.map((e) => /* @__PURE__ */ P("p", {
2271
+ role: "alert",
2272
+ className: "py-2 text-xs text-danger",
2273
+ children: `The scheduler of ${e.project.name} could not be read: ${e.error}`
2274
+ }, e.project.id)),
2275
+ s !== void 0 && /* @__PURE__ */ P("p", {
2276
+ role: "alert",
2277
+ className: "py-2 text-xs text-danger",
2278
+ children: s
2279
+ })
2280
+ ]
2281
+ });
2282
+ }
2283
+ //#endregion
2284
+ //#region dashboard/index.tsx
2285
+ var sn = j({
2286
+ pages: [{
2287
+ segment: "automations",
2288
+ label: "Automations",
2289
+ icon: z,
2290
+ Page: Yt
2291
+ }],
2292
+ cards: [{
2293
+ id: "scheduler",
2294
+ order: 90,
2295
+ Card: tn
2296
+ }],
2297
+ settings: [{
2298
+ id: "scheduler",
2299
+ title: "Scheduler",
2300
+ icon: z,
2301
+ order: 20,
2302
+ Section: on
2303
+ }],
2304
+ usageLimit: {
2305
+ read: async (e, t) => Me(await je(e, t)),
2306
+ save: Fe
2307
+ },
2308
+ schedule: {
2309
+ page: "automations",
2310
+ read: async (e, t) => {
2311
+ let [n] = await je(e, [t]);
2312
+ if (!n || n.error !== void 0) throw Error(n?.error ?? "the scheduler did not answer");
2313
+ let r = at(n);
2314
+ return n.commands.map((e) => ({
2315
+ command: e.command,
2316
+ on: e.on && r === void 0 && $e(e) === void 0,
2317
+ ...e.on ? { note: r ?? it(e) } : {}
2318
+ }));
2319
+ }
2320
+ },
2321
+ stylesheet: "dashboard.css"
2322
+ });
2323
+ //#endregion
2324
+ export { sn as default };