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