@namzu/sdk 45.0.0 → 45.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/dist/authorization/gate.d.ts.map +1 -1
  3. package/dist/authorization/gate.js +12 -2
  4. package/dist/authorization/gate.js.map +1 -1
  5. package/dist/authorization/rules.d.ts.map +1 -1
  6. package/dist/authorization/rules.js +37 -6
  7. package/dist/authorization/rules.js.map +1 -1
  8. package/dist/authorization/shell-lexer.d.ts +14 -0
  9. package/dist/authorization/shell-lexer.d.ts.map +1 -1
  10. package/dist/authorization/shell-lexer.js +19 -6
  11. package/dist/authorization/shell-lexer.js.map +1 -1
  12. package/dist/bridge/a2a/mapper.d.ts.map +1 -1
  13. package/dist/bridge/a2a/mapper.js +2 -0
  14. package/dist/bridge/a2a/mapper.js.map +1 -1
  15. package/dist/bridge/sse/mapper.d.ts.map +1 -1
  16. package/dist/bridge/sse/mapper.js +1 -0
  17. package/dist/bridge/sse/mapper.js.map +1 -1
  18. package/dist/directory/types.d.ts +2 -0
  19. package/dist/directory/types.d.ts.map +1 -1
  20. package/dist/directory/types.js.map +1 -1
  21. package/dist/manager/resident/outbox.d.ts +4 -4
  22. package/dist/prompt/coding-agent-doctrine.d.ts +1 -1
  23. package/dist/prompt/coding-agent-doctrine.d.ts.map +1 -1
  24. package/dist/prompt/coding-agent-doctrine.js +1 -0
  25. package/dist/prompt/coding-agent-doctrine.js.map +1 -1
  26. package/dist/public-runtime.d.ts +4 -1
  27. package/dist/public-runtime.d.ts.map +1 -1
  28. package/dist/public-runtime.js +11 -1
  29. package/dist/public-runtime.js.map +1 -1
  30. package/dist/public-tools.d.ts +4 -0
  31. package/dist/public-tools.d.ts.map +1 -1
  32. package/dist/public-tools.js +10 -0
  33. package/dist/public-tools.js.map +1 -1
  34. package/dist/public-types.d.ts +7 -1
  35. package/dist/public-types.d.ts.map +1 -1
  36. package/dist/runtime/query/declined.d.ts +12 -0
  37. package/dist/runtime/query/declined.d.ts.map +1 -0
  38. package/dist/runtime/query/declined.js +12 -0
  39. package/dist/runtime/query/declined.js.map +1 -0
  40. package/dist/runtime/query/executor.d.ts +3 -1
  41. package/dist/runtime/query/executor.d.ts.map +1 -1
  42. package/dist/runtime/query/executor.js +14 -2
  43. package/dist/runtime/query/executor.js.map +1 -1
  44. package/dist/runtime/query/index.d.ts.map +1 -1
  45. package/dist/runtime/query/index.js +1 -0
  46. package/dist/runtime/query/index.js.map +1 -1
  47. package/dist/runtime/query/iteration/index.d.ts.map +1 -1
  48. package/dist/runtime/query/iteration/index.js +7 -0
  49. package/dist/runtime/query/iteration/index.js.map +1 -1
  50. package/dist/runtime/query/iteration/phases/context.d.ts +6 -0
  51. package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
  52. package/dist/runtime/query/iteration/phases/context.js.map +1 -1
  53. package/dist/runtime/query/iteration/phases/handoff.d.ts +22 -0
  54. package/dist/runtime/query/iteration/phases/handoff.d.ts.map +1 -0
  55. package/dist/runtime/query/iteration/phases/handoff.js +65 -0
  56. package/dist/runtime/query/iteration/phases/handoff.js.map +1 -0
  57. package/dist/runtime/query/iteration/phases/index.d.ts +1 -0
  58. package/dist/runtime/query/iteration/phases/index.d.ts.map +1 -1
  59. package/dist/runtime/query/iteration/phases/index.js +1 -0
  60. package/dist/runtime/query/iteration/phases/index.js.map +1 -1
  61. package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
  62. package/dist/runtime/query/iteration/phases/tool-review.js +8 -3
  63. package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
  64. package/dist/runtime/query/resume-pending.d.ts.map +1 -1
  65. package/dist/runtime/query/resume-pending.js +3 -2
  66. package/dist/runtime/query/resume-pending.js.map +1 -1
  67. package/dist/runtime/query/review-policy.d.ts.map +1 -1
  68. package/dist/runtime/query/review-policy.js +4 -3
  69. package/dist/runtime/query/review-policy.js.map +1 -1
  70. package/dist/schedules/cron.d.ts +21 -0
  71. package/dist/schedules/cron.d.ts.map +1 -0
  72. package/dist/schedules/cron.js +167 -0
  73. package/dist/schedules/cron.js.map +1 -0
  74. package/dist/schedules/describe.d.ts +14 -0
  75. package/dist/schedules/describe.d.ts.map +1 -0
  76. package/dist/schedules/describe.js +133 -0
  77. package/dist/schedules/describe.js.map +1 -0
  78. package/dist/schedules/errors.d.ts +11 -0
  79. package/dist/schedules/errors.d.ts.map +1 -0
  80. package/dist/schedules/errors.js +15 -0
  81. package/dist/schedules/errors.js.map +1 -0
  82. package/dist/schedules/evaluate.d.ts +35 -0
  83. package/dist/schedules/evaluate.d.ts.map +1 -0
  84. package/dist/schedules/evaluate.js +158 -0
  85. package/dist/schedules/evaluate.js.map +1 -0
  86. package/dist/schedules/index.d.ts +11 -0
  87. package/dist/schedules/index.d.ts.map +1 -0
  88. package/dist/schedules/index.js +8 -0
  89. package/dist/schedules/index.js.map +1 -0
  90. package/dist/schedules/next-fire.d.ts +50 -0
  91. package/dist/schedules/next-fire.d.ts.map +1 -0
  92. package/dist/schedules/next-fire.js +250 -0
  93. package/dist/schedules/next-fire.js.map +1 -0
  94. package/dist/schedules/spec.d.ts +30 -0
  95. package/dist/schedules/spec.d.ts.map +1 -0
  96. package/dist/schedules/spec.js +169 -0
  97. package/dist/schedules/spec.js.map +1 -0
  98. package/dist/schedules/types.d.ts +144 -0
  99. package/dist/schedules/types.d.ts.map +1 -0
  100. package/dist/schedules/types.js +11 -0
  101. package/dist/schedules/types.js.map +1 -0
  102. package/dist/schedules/tz.d.ts +44 -0
  103. package/dist/schedules/tz.d.ts.map +1 -0
  104. package/dist/schedules/tz.js +141 -0
  105. package/dist/schedules/tz.js.map +1 -0
  106. package/dist/skills/index.d.ts +1 -1
  107. package/dist/skills/index.d.ts.map +1 -1
  108. package/dist/skills/index.js +1 -1
  109. package/dist/skills/index.js.map +1 -1
  110. package/dist/skills/loader.d.ts +16 -3
  111. package/dist/skills/loader.d.ts.map +1 -1
  112. package/dist/skills/loader.js +48 -4
  113. package/dist/skills/loader.js.map +1 -1
  114. package/dist/tools/builtins/browser-url.d.ts +83 -0
  115. package/dist/tools/builtins/browser-url.d.ts.map +1 -0
  116. package/dist/tools/builtins/browser-url.js +240 -0
  117. package/dist/tools/builtins/browser-url.js.map +1 -0
  118. package/dist/tools/builtins/browser.d.ts +367 -0
  119. package/dist/tools/builtins/browser.d.ts.map +1 -0
  120. package/dist/tools/builtins/browser.js +704 -0
  121. package/dist/tools/builtins/browser.js.map +1 -0
  122. package/dist/tools/builtins/skill.d.ts.map +1 -1
  123. package/dist/tools/builtins/skill.js +15 -0
  124. package/dist/tools/builtins/skill.js.map +1 -1
  125. package/dist/tools/defineTool.d.ts +2 -0
  126. package/dist/tools/defineTool.d.ts.map +1 -1
  127. package/dist/tools/defineTool.js +1 -0
  128. package/dist/tools/defineTool.js.map +1 -1
  129. package/dist/tools/schedules/index.d.ts +5 -0
  130. package/dist/tools/schedules/index.d.ts.map +1 -0
  131. package/dist/tools/schedules/index.js +4 -0
  132. package/dist/tools/schedules/index.js.map +1 -0
  133. package/dist/tools/schedules/loop-tool.d.ts +14 -0
  134. package/dist/tools/schedules/loop-tool.d.ts.map +1 -0
  135. package/dist/tools/schedules/loop-tool.js +81 -0
  136. package/dist/tools/schedules/loop-tool.js.map +1 -0
  137. package/dist/tools/schedules/present.d.ts +16 -0
  138. package/dist/tools/schedules/present.d.ts.map +1 -0
  139. package/dist/tools/schedules/present.js +69 -0
  140. package/dist/tools/schedules/present.js.map +1 -0
  141. package/dist/tools/schedules/prompt-scan.d.ts +17 -0
  142. package/dist/tools/schedules/prompt-scan.d.ts.map +1 -0
  143. package/dist/tools/schedules/prompt-scan.js +92 -0
  144. package/dist/tools/schedules/prompt-scan.js.map +1 -0
  145. package/dist/tools/schedules/schedule-tool.d.ts +16 -0
  146. package/dist/tools/schedules/schedule-tool.d.ts.map +1 -0
  147. package/dist/tools/schedules/schedule-tool.js +327 -0
  148. package/dist/tools/schedules/schedule-tool.js.map +1 -0
  149. package/dist/tools/schedules/types.d.ts +184 -0
  150. package/dist/tools/schedules/types.d.ts.map +1 -0
  151. package/dist/tools/schedules/types.js +11 -0
  152. package/dist/tools/schedules/types.js.map +1 -0
  153. package/dist/types/authorization/index.d.ts +86 -9
  154. package/dist/types/authorization/index.d.ts.map +1 -1
  155. package/dist/types/authorization/index.js +11 -1
  156. package/dist/types/authorization/index.js.map +1 -1
  157. package/dist/types/browser/index.d.ts +280 -0
  158. package/dist/types/browser/index.d.ts.map +1 -0
  159. package/dist/types/browser/index.js +12 -0
  160. package/dist/types/browser/index.js.map +1 -0
  161. package/dist/types/session/events.d.ts +6 -0
  162. package/dist/types/session/events.d.ts.map +1 -1
  163. package/dist/types/session/events.js.map +1 -1
  164. package/dist/types/session/records.d.ts +23 -0
  165. package/dist/types/session/records.d.ts.map +1 -1
  166. package/dist/types/session/records.js +9 -0
  167. package/dist/types/session/records.js.map +1 -1
  168. package/dist/types/tool/index.d.ts +41 -0
  169. package/dist/types/tool/index.d.ts.map +1 -1
  170. package/dist/types/tool/index.js.map +1 -1
  171. package/dist/types/tool/presentation.d.ts +7 -0
  172. package/dist/types/tool/presentation.d.ts.map +1 -1
  173. package/dist/utils/frontmatter.d.ts +18 -2
  174. package/dist/utils/frontmatter.d.ts.map +1 -1
  175. package/dist/utils/frontmatter.js +13 -3
  176. package/dist/utils/frontmatter.js.map +1 -1
  177. package/dist/utils/id.d.ts +8 -0
  178. package/dist/utils/id.d.ts.map +1 -1
  179. package/dist/utils/id.js +12 -0
  180. package/dist/utils/id.js.map +1 -1
  181. package/package.json +1 -1
  182. package/src/authorization/gate.ts +14 -2
  183. package/src/authorization/rules.ts +37 -7
  184. package/src/authorization/shell-lexer.ts +36 -6
  185. package/src/bridge/a2a/mapper.ts +2 -0
  186. package/src/bridge/sse/mapper.ts +1 -0
  187. package/src/directory/types.ts +2 -0
  188. package/src/prompt/coding-agent-doctrine.ts +1 -0
  189. package/src/public-runtime.ts +28 -0
  190. package/src/public-tools.ts +35 -0
  191. package/src/public-types.ts +50 -0
  192. package/src/runtime/query/declined.ts +12 -0
  193. package/src/runtime/query/executor.ts +17 -1
  194. package/src/runtime/query/index.ts +1 -0
  195. package/src/runtime/query/iteration/index.ts +8 -0
  196. package/src/runtime/query/iteration/phases/context.ts +6 -0
  197. package/src/runtime/query/iteration/phases/handoff.ts +74 -0
  198. package/src/runtime/query/iteration/phases/index.ts +1 -0
  199. package/src/runtime/query/iteration/phases/tool-review.ts +11 -4
  200. package/src/runtime/query/resume-pending.ts +3 -2
  201. package/src/runtime/query/review-policy.ts +4 -3
  202. package/src/schedules/cron.ts +202 -0
  203. package/src/schedules/describe.ts +138 -0
  204. package/src/schedules/errors.ts +15 -0
  205. package/src/schedules/evaluate.ts +178 -0
  206. package/src/schedules/index.ts +18 -0
  207. package/src/schedules/next-fire.ts +257 -0
  208. package/src/schedules/spec.ts +210 -0
  209. package/src/schedules/types.ts +163 -0
  210. package/src/schedules/tz.ts +155 -0
  211. package/src/skills/index.ts +1 -1
  212. package/src/skills/loader.ts +55 -4
  213. package/src/tools/builtins/browser-url.ts +251 -0
  214. package/src/tools/builtins/browser.ts +817 -0
  215. package/src/tools/builtins/skill.ts +18 -0
  216. package/src/tools/defineTool.ts +3 -0
  217. package/src/tools/schedules/index.ts +4 -0
  218. package/src/tools/schedules/loop-tool.ts +85 -0
  219. package/src/tools/schedules/present.ts +86 -0
  220. package/src/tools/schedules/prompt-scan.ts +96 -0
  221. package/src/tools/schedules/schedule-tool.ts +376 -0
  222. package/src/tools/schedules/types.ts +197 -0
  223. package/src/types/authorization/index.ts +60 -2
  224. package/src/types/browser/index.ts +341 -0
  225. package/src/types/session/events.ts +6 -0
  226. package/src/types/session/records.ts +10 -0
  227. package/src/types/tool/index.ts +42 -0
  228. package/src/types/tool/presentation.ts +7 -0
  229. package/src/utils/frontmatter.ts +29 -3
  230. package/src/utils/id.ts +14 -0
@@ -0,0 +1,250 @@
1
+ /**
2
+ * When a spec fires: the next instant, the previous one, and how many fall
3
+ * in a window.
4
+ *
5
+ * Cron is walked a local DAY at a time — never a minute at a time over years
6
+ * — and a day with no DST change is computed arithmetically from one offset.
7
+ * Only a day whose offset changes is examined slot by slot, and that is where
8
+ * cronie's rule is applied:
9
+ *
10
+ * - a fixed-time expression (`30 2 * * *`) whose time falls in a
11
+ * spring-forward gap fires once, at the first instant after the gap;
12
+ * whose time is repeated by a fall-back fires once, at the first of the two;
13
+ * - a wildcard or step expression (`0 * * * *`, `*\/15 * * * *`) fires at
14
+ * every instant whose wall time matches: the repeated hour runs twice and
15
+ * slots inside the gap do not exist.
16
+ */
17
+ import { cronMatchesDay, parseCronExpression } from './cron.js';
18
+ import { ScheduleValidationError } from './errors.js';
19
+ import { civil, firstInstantAfterGap, instantsForWall, offsetAt, validateTimeZone } from './tz.js';
20
+ const MINUTE = 60_000;
21
+ const HOUR = 60 * MINUTE;
22
+ const DAY = 24 * HOUR;
23
+ /** How far ahead a cron search looks before deciding the expression never fires. */
24
+ export const CRON_HORIZON_DAYS = 366 * 5 + 2;
25
+ /**
26
+ * Occurrence counts stop here. Counting a day without a DST change costs one
27
+ * multiplication, so the cap bounds the pathological case (a years-long gap
28
+ * on a per-minute job) rather than the ordinary one.
29
+ */
30
+ export const OCCURRENCE_COUNT_CAP = 100_000;
31
+ const parsedCache = new Map();
32
+ function cronOf(expr) {
33
+ let parsed = parsedCache.get(expr);
34
+ if (!parsed) {
35
+ parsed = parseCronExpression(expr);
36
+ if (parsedCache.size > 256)
37
+ parsedCache.clear();
38
+ parsedCache.set(expr, parsed);
39
+ }
40
+ return parsed;
41
+ }
42
+ /** The local-midnight wall value of the day containing `wall`. */
43
+ function dayStart(wall) {
44
+ return Math.floor(wall / DAY) * DAY;
45
+ }
46
+ /**
47
+ * Every instant the expression fires on one local day (`dayWall` is that
48
+ * day's midnight as a wall value), ascending.
49
+ */
50
+ export function cronInstantsOnDay(expr, tz, dayWall) {
51
+ const c = civil(dayWall);
52
+ if (!cronMatchesDay(expr, c.month, c.day, c.weekday))
53
+ return [];
54
+ const before = offsetAt(dayWall - 14 * HOUR, tz);
55
+ const after = offsetAt(dayWall + DAY + 14 * HOUR, tz);
56
+ const out = [];
57
+ if (before === after) {
58
+ for (const h of expr.hours)
59
+ for (const m of expr.minutes)
60
+ out.push(dayWall + h * HOUR + m * MINUTE - before);
61
+ return out;
62
+ }
63
+ // A day the offset changes on (or next to): slot by slot.
64
+ const seen = new Set();
65
+ for (const h of expr.hours) {
66
+ for (const m of expr.minutes) {
67
+ const wall = dayWall + h * HOUR + m * MINUTE;
68
+ const instants = instantsForWall(wall, tz);
69
+ if (instants.length === 0) {
70
+ if (expr.fixedTime) {
71
+ const shifted = firstInstantAfterGap(wall, tz);
72
+ if (!seen.has(shifted)) {
73
+ seen.add(shifted);
74
+ out.push(shifted);
75
+ }
76
+ }
77
+ continue;
78
+ }
79
+ const chosen = expr.fixedTime ? instants.slice(0, 1) : instants;
80
+ for (const t of chosen) {
81
+ if (seen.has(t))
82
+ continue;
83
+ seen.add(t);
84
+ out.push(t);
85
+ }
86
+ }
87
+ }
88
+ return out.sort((a, b) => a - b);
89
+ }
90
+ function validEvery(spec) {
91
+ const anchor = Date.parse(spec.anchorAt);
92
+ if (!Number.isFinite(anchor)) {
93
+ throw new ScheduleValidationError(`anchor "${spec.anchorAt}" is not a date`, spec.anchorAt);
94
+ }
95
+ if (!Number.isSafeInteger(spec.everyMs) || spec.everyMs < MINUTE || spec.everyMs % MINUTE !== 0) {
96
+ throw new ScheduleValidationError('an interval must be a whole number of minutes, at least one', String(spec.everyMs));
97
+ }
98
+ return anchor;
99
+ }
100
+ /**
101
+ * The first instant strictly after `afterExclusive` at which `spec` fires,
102
+ * or `null` when there is none (a past `at`, or a cron expression with no
103
+ * occurrence in the next five years).
104
+ */
105
+ export function nextFireTime(spec, afterExclusive) {
106
+ const after = afterExclusive.getTime();
107
+ switch (spec.kind) {
108
+ case 'at': {
109
+ const at = Date.parse(spec.at);
110
+ return Number.isFinite(at) && at > after ? new Date(at) : null;
111
+ }
112
+ case 'every': {
113
+ const anchor = validEvery(spec);
114
+ const k = after < anchor ? 1 : Math.floor((after - anchor) / spec.everyMs) + 1;
115
+ return new Date(anchor + Math.max(1, k) * spec.everyMs);
116
+ }
117
+ case 'cron': {
118
+ const expr = cronOf(spec.expr);
119
+ const tz = spec.tz;
120
+ // A day early: a gap-shifted or offset-crossing instant of the
121
+ // previous local day can still lie after `after`.
122
+ let day = dayStart(after + offsetAt(after, tz)) - DAY;
123
+ for (let i = 0; i <= CRON_HORIZON_DAYS; i++, day += DAY) {
124
+ for (const t of cronInstantsOnDay(expr, tz, day))
125
+ if (t > after)
126
+ return new Date(t);
127
+ }
128
+ return null;
129
+ }
130
+ }
131
+ }
132
+ /**
133
+ * The last instant at or before `atOrBefore` at which `spec` fired, or
134
+ * `null` if none within the horizon (or before the anchor / the `at`).
135
+ */
136
+ export function previousFireTime(spec, atOrBefore) {
137
+ const before = atOrBefore.getTime();
138
+ switch (spec.kind) {
139
+ case 'at': {
140
+ const at = Date.parse(spec.at);
141
+ return Number.isFinite(at) && at <= before ? new Date(at) : null;
142
+ }
143
+ case 'every': {
144
+ const anchor = validEvery(spec);
145
+ const k = Math.floor((before - anchor) / spec.everyMs);
146
+ return k >= 1 ? new Date(anchor + k * spec.everyMs) : null;
147
+ }
148
+ case 'cron': {
149
+ const expr = cronOf(spec.expr);
150
+ const tz = spec.tz;
151
+ let day = dayStart(before + offsetAt(before, tz)) + DAY;
152
+ for (let i = 0; i <= CRON_HORIZON_DAYS; i++, day -= DAY) {
153
+ const instants = cronInstantsOnDay(expr, tz, day);
154
+ for (let j = instants.length - 1; j >= 0; j--) {
155
+ const t = instants[j];
156
+ if (t <= before)
157
+ return new Date(t);
158
+ }
159
+ }
160
+ return null;
161
+ }
162
+ }
163
+ }
164
+ /**
165
+ * How many times `spec` fires in `(fromExclusive, toInclusive]`, with the
166
+ * first and latest of them. Stops counting at `cap` (default 100 000) and
167
+ * says so, without enumerating beyond it; the latest is exact either way.
168
+ */
169
+ export function countOccurrences(spec, fromExclusive, toInclusive, cap = OCCURRENCE_COUNT_CAP) {
170
+ const from = fromExclusive.getTime();
171
+ const to = toInclusive.getTime();
172
+ if (to <= from)
173
+ return { count: 0, capped: false };
174
+ switch (spec.kind) {
175
+ case 'at': {
176
+ const at = Date.parse(spec.at);
177
+ return at > from && at <= to
178
+ ? { count: 1, capped: false, first: new Date(at), latest: new Date(at) }
179
+ : { count: 0, capped: false };
180
+ }
181
+ case 'every': {
182
+ const anchor = validEvery(spec);
183
+ const firstK = from < anchor ? 1 : Math.floor((from - anchor) / spec.everyMs) + 1;
184
+ const lastK = Math.floor((to - anchor) / spec.everyMs);
185
+ if (lastK < Math.max(1, firstK))
186
+ return { count: 0, capped: false };
187
+ const k0 = Math.max(1, firstK);
188
+ const total = lastK - k0 + 1;
189
+ return {
190
+ count: Math.min(total, cap),
191
+ capped: total > cap,
192
+ first: new Date(anchor + k0 * spec.everyMs),
193
+ latest: new Date(anchor + lastK * spec.everyMs),
194
+ };
195
+ }
196
+ case 'cron': {
197
+ const expr = cronOf(spec.expr);
198
+ const tz = spec.tz;
199
+ const latest = previousFireTime(spec, toInclusive);
200
+ if (!latest || latest.getTime() <= from)
201
+ return { count: 0, capped: false };
202
+ const perUniformDay = expr.hours.length * expr.minutes.length;
203
+ let count = 0;
204
+ let first;
205
+ const lastDay = dayStart(to + offsetAt(to, tz)) + DAY;
206
+ for (let day = dayStart(from + offsetAt(from, tz)) - DAY; day <= lastDay; day += DAY) {
207
+ const c = civil(day);
208
+ if (!cronMatchesDay(expr, c.month, c.day, c.weekday))
209
+ continue;
210
+ const o1 = offsetAt(day - 14 * HOUR, tz);
211
+ const o2 = offsetAt(day + DAY + 14 * HOUR, tz);
212
+ const dayFirst = day - o1;
213
+ const dayLast = day + DAY - o1;
214
+ if (first !== undefined && o1 === o2 && dayFirst > from && dayLast <= to) {
215
+ count += perUniformDay;
216
+ }
217
+ else {
218
+ for (const t of cronInstantsOnDay(expr, tz, day)) {
219
+ if (t <= from || t > to)
220
+ continue;
221
+ if (first === undefined)
222
+ first = t;
223
+ count++;
224
+ }
225
+ }
226
+ if (count > cap)
227
+ break;
228
+ }
229
+ return {
230
+ count: Math.min(count, cap),
231
+ capped: count > cap,
232
+ ...(first !== undefined ? { first: new Date(first) } : {}),
233
+ latest,
234
+ };
235
+ }
236
+ }
237
+ }
238
+ /** Validate a spec as a whole: its zone, its expression, and that it can ever fire after `now`. */
239
+ export function assertSpecFires(spec, now) {
240
+ if (spec.kind === 'cron') {
241
+ validateTimeZone(spec.tz);
242
+ cronOf(spec.expr);
243
+ }
244
+ if (nextFireTime(spec, now) === null) {
245
+ throw new ScheduleValidationError(spec.kind === 'at'
246
+ ? `${spec.at} is in the past`
247
+ : `"${spec.kind === 'cron' ? spec.expr : ''}" never fires in the next five years`, spec.kind === 'cron' ? spec.expr : spec.kind === 'at' ? spec.at : undefined);
248
+ }
249
+ }
250
+ //# sourceMappingURL=next-fire.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next-fire.js","sourceRoot":"","sources":["../../src/schedules/next-fire.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * The words an operator or a model types for a schedule, turned into a spec.
3
+ *
4
+ * | Input | Spec |
5
+ * |---|---|
6
+ * | `at 2026-09-24T09:00`, `at 2026-09-24 09:00`, `at 09:00`, `in 30m` | `at` |
7
+ * | an ISO instant with `Z` or an offset, with or without `at` | `at` |
8
+ * | `every 30m`, `every 2h`, `every 1d`, `every 90m` | `every` |
9
+ * | five-field cron, `@hourly`, `@daily`, `@weekly`, `@monthly`, `@yearly` | `cron` |
10
+ *
11
+ * A local time is read in `tz`. Nothing is rounded silently: `every 30s` is
12
+ * refused and the refusal names the nearest interval that is allowed.
13
+ */
14
+ import type { ScheduleSpec } from './types.js';
15
+ export interface ParseScheduleOptions {
16
+ /** "Now", for `in …`, `at HH:MM` and the anchor of `every`. Default: the clock. */
17
+ readonly now?: Date;
18
+ /** Zone a local time and a cron expression are read in. Default: the host's. */
19
+ readonly tz?: string;
20
+ }
21
+ /** `90m` → 5 400 000. Throws on anything else. */
22
+ export declare function parseDuration(text: string): number;
23
+ /**
24
+ * Parse schedule words into a spec, validated: the zone exists, the
25
+ * expression parses, and the spec fires at least once after `now`.
26
+ */
27
+ export declare function parseScheduleSpec(input: string, options?: ParseScheduleOptions): ScheduleSpec;
28
+ /** The next `count` fire times after `after`. */
29
+ export declare function upcomingFireTimes(spec: ScheduleSpec, after: Date, count?: number): Date[];
30
+ //# sourceMappingURL=spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec.d.ts","sourceRoot":"","sources":["../../src/schedules/spec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AA4B9C,MAAM,WAAW,oBAAoB;IACpC,mFAAmF;IACnF,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,CAAA;IACnB,gFAAgF;IAChF,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,kDAAkD;AAClD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAUlD;AAmGD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB,GAAG,YAAY,CA8BjG;AAED,iDAAiD;AACjD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,SAAI,GAAG,IAAI,EAAE,CAUpF"}
@@ -0,0 +1,169 @@
1
+ /**
2
+ * The words an operator or a model types for a schedule, turned into a spec.
3
+ *
4
+ * | Input | Spec |
5
+ * |---|---|
6
+ * | `at 2026-09-24T09:00`, `at 2026-09-24 09:00`, `at 09:00`, `in 30m` | `at` |
7
+ * | an ISO instant with `Z` or an offset, with or without `at` | `at` |
8
+ * | `every 30m`, `every 2h`, `every 1d`, `every 90m` | `every` |
9
+ * | five-field cron, `@hourly`, `@daily`, `@weekly`, `@monthly`, `@yearly` | `cron` |
10
+ *
11
+ * A local time is read in `tz`. Nothing is rounded silently: `every 30s` is
12
+ * refused and the refusal names the nearest interval that is allowed.
13
+ */
14
+ import { parseCronExpression } from './cron.js';
15
+ import { ScheduleValidationError } from './errors.js';
16
+ import { assertSpecFires, nextFireTime } from './next-fire.js';
17
+ import { civil, hostTimeZone, instantsForWall, validateTimeZone, wallOf } from './tz.js';
18
+ const MINUTE = 60_000;
19
+ const UNIT_MS = {
20
+ s: 1_000,
21
+ sec: 1_000,
22
+ secs: 1_000,
23
+ second: 1_000,
24
+ seconds: 1_000,
25
+ m: MINUTE,
26
+ min: MINUTE,
27
+ mins: MINUTE,
28
+ minute: MINUTE,
29
+ minutes: MINUTE,
30
+ h: 60 * MINUTE,
31
+ hr: 60 * MINUTE,
32
+ hrs: 60 * MINUTE,
33
+ hour: 60 * MINUTE,
34
+ hours: 60 * MINUTE,
35
+ d: 24 * 60 * MINUTE,
36
+ day: 24 * 60 * MINUTE,
37
+ days: 24 * 60 * MINUTE,
38
+ w: 7 * 24 * 60 * MINUTE,
39
+ week: 7 * 24 * 60 * MINUTE,
40
+ weeks: 7 * 24 * 60 * MINUTE,
41
+ };
42
+ /** `90m` → 5 400 000. Throws on anything else. */
43
+ export function parseDuration(text) {
44
+ const match = /^(\d+)\s*([a-z]+)$/i.exec(text.trim());
45
+ const unit = match ? UNIT_MS[(match[2] ?? '').toLowerCase()] : undefined;
46
+ if (!match || unit === undefined) {
47
+ throw new ScheduleValidationError(`"${text}" is not a duration (write it like 30m, 2h, 1d)`, text);
48
+ }
49
+ return Number(match[1]) * unit;
50
+ }
51
+ function formatInterval(ms) {
52
+ if (ms % (24 * 60 * MINUTE) === 0)
53
+ return `${ms / (24 * 60 * MINUTE)}d`;
54
+ if (ms % (60 * MINUTE) === 0)
55
+ return `${ms / (60 * MINUTE)}h`;
56
+ return `${ms / MINUTE}m`;
57
+ }
58
+ function everySpec(text, now) {
59
+ const ms = parseDuration(text);
60
+ if (ms < MINUTE) {
61
+ throw new ScheduleValidationError(`every ${text} is shorter than the minimum interval; the nearest allowed is every 1m`, text);
62
+ }
63
+ if (ms % MINUTE !== 0) {
64
+ const down = Math.floor(ms / MINUTE) * MINUTE;
65
+ const up = down + MINUTE;
66
+ throw new ScheduleValidationError(`every ${text} is not a whole number of minutes; the nearest allowed are every ${formatInterval(down)} and every ${formatInterval(up)}`, text);
67
+ }
68
+ const anchor = new Date(Math.floor(now.getTime() / MINUTE) * MINUTE);
69
+ return { kind: 'every', everyMs: ms, anchorAt: anchor.toISOString() };
70
+ }
71
+ /** Resolve a local `YYYY-MM-DD HH:MM` in `tz` to one instant (the earlier of two). */
72
+ function localToInstant(y, mo, d, h, mi, tz, token) {
73
+ const wall = Date.UTC(y, mo - 1, d, h, mi);
74
+ const c = civil(wall);
75
+ if (c.year !== y || c.month !== mo || c.day !== d || h > 23 || mi > 59) {
76
+ throw new ScheduleValidationError(`"${token}" is not a real date and time`, token);
77
+ }
78
+ const instants = instantsForWall(wall, tz);
79
+ if (instants.length === 0) {
80
+ throw new ScheduleValidationError(`"${token}" does not exist in ${tz} (the clocks skip it); pick a time outside the change`, token);
81
+ }
82
+ return instants[0];
83
+ }
84
+ function atSpec(text, now, tz) {
85
+ const t = text.trim();
86
+ // An instant with its own offset: taken as written.
87
+ if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2}(\.\d+)?)?(Z|[+-]\d{2}:?\d{2})$/i.test(t)) {
88
+ const at = Date.parse(t);
89
+ if (!Number.isFinite(at))
90
+ throw new ScheduleValidationError(`"${t}" is not a date`, t);
91
+ return { kind: 'at', at: new Date(at).toISOString() };
92
+ }
93
+ const full = /^(\d{4})-(\d{2})-(\d{2})[T ](\d{1,2}):(\d{2})$/.exec(t);
94
+ if (full) {
95
+ const [, y, mo, d, h, mi] = full.map(Number);
96
+ const at = localToInstant(y, mo, d, h, mi, tz, t);
97
+ return { kind: 'at', at: new Date(at).toISOString() };
98
+ }
99
+ const clock = /^(\d{1,2}):(\d{2})$/.exec(t);
100
+ if (clock) {
101
+ const h = Number(clock[1]);
102
+ const mi = Number(clock[2]);
103
+ if (h > 23 || mi > 59)
104
+ throw new ScheduleValidationError(`"${t}" is not a time of day`, t);
105
+ // The next time the wall clock reads HH:MM, today or tomorrow.
106
+ const today = civil(wallOf(now.getTime(), tz));
107
+ for (let add = 0; add < 3; add++) {
108
+ const day = new Date(Date.UTC(today.year, today.month - 1, today.day + add));
109
+ const instants = instantsForWall(Date.UTC(day.getUTCFullYear(), day.getUTCMonth(), day.getUTCDate(), h, mi), tz);
110
+ const first = instants.find((i) => i > now.getTime());
111
+ if (first !== undefined)
112
+ return { kind: 'at', at: new Date(first).toISOString() };
113
+ }
114
+ throw new ScheduleValidationError(`"${t}" does not occur in ${tz} in the next two days`, t);
115
+ }
116
+ throw new ScheduleValidationError(`"${t}" is not a time (write 2026-09-24 09:00, 09:00, or an ISO instant)`, t);
117
+ }
118
+ /**
119
+ * Parse schedule words into a spec, validated: the zone exists, the
120
+ * expression parses, and the spec fires at least once after `now`.
121
+ */
122
+ export function parseScheduleSpec(input, options = {}) {
123
+ const now = options.now ?? new Date();
124
+ const tz = validateTimeZone(options.tz ?? hostTimeZone());
125
+ const text = input.trim();
126
+ if (text === '')
127
+ throw new ScheduleValidationError('a schedule is required', '');
128
+ let spec;
129
+ const lower = text.toLowerCase();
130
+ if (lower.startsWith('every ')) {
131
+ spec = everySpec(text.slice(6).trim(), now);
132
+ }
133
+ else if (lower.startsWith('in ')) {
134
+ const ms = parseDuration(text.slice(3).trim());
135
+ if (ms < MINUTE) {
136
+ throw new ScheduleValidationError(`in ${text.slice(3).trim()} is less than a minute away; the nearest allowed is in 1m`, text.slice(3).trim());
137
+ }
138
+ spec = { kind: 'at', at: new Date(now.getTime() + ms).toISOString() };
139
+ }
140
+ else if (lower.startsWith('at ')) {
141
+ spec = atSpec(text.slice(3), now, tz);
142
+ }
143
+ else if (/^\d{4}-\d{2}-\d{2}T/i.test(text)) {
144
+ spec = atSpec(text, now, tz);
145
+ }
146
+ else if (lower === '@reboot') {
147
+ throw new ScheduleValidationError('@reboot is not supported: a job runs on a schedule', text);
148
+ }
149
+ else {
150
+ const expr = parseCronExpression(text);
151
+ spec = { kind: 'cron', expr: expr.source, tz };
152
+ }
153
+ assertSpecFires(spec, now);
154
+ return spec;
155
+ }
156
+ /** The next `count` fire times after `after`. */
157
+ export function upcomingFireTimes(spec, after, count = 3) {
158
+ const out = [];
159
+ let cursor = after;
160
+ for (let i = 0; i < count; i++) {
161
+ const next = nextFireTime(spec, cursor);
162
+ if (!next)
163
+ break;
164
+ out.push(next);
165
+ cursor = next;
166
+ }
167
+ return out;
168
+ }
169
+ //# sourceMappingURL=spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec.js","sourceRoot":"","sources":["../../src/schedules/spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Types of the schedule time engine and evaluator.
3
+ *
4
+ * The SDK owns WHEN something is due and nothing about how a host stores a
5
+ * job or runs it: the CLI keeps its job files, claims and history records to
6
+ * itself, so its on-disk format is not SDK API. The unions exported here
7
+ * (`ScheduleDecision`, `ScheduleSkipReason`, `ScheduleMissedReason`) may grow
8
+ * in a minor release; switch over them with a `default:` branch.
9
+ */
10
+ /** A single instant (ISO-8601 UTC). */
11
+ export interface ScheduleAtSpec {
12
+ readonly kind: 'at';
13
+ readonly at: string;
14
+ }
15
+ /**
16
+ * Elapsed time from an anchor: `anchorAt + k * everyMs` for k ≥ 1. Pure UTC
17
+ * arithmetic, so `every 24h` drifts against the wall clock across a DST
18
+ * change; a cron spec is the way to say "every day at 09:00".
19
+ */
20
+ export interface ScheduleEverySpec {
21
+ readonly kind: 'every';
22
+ /** At least one minute, and a whole number of minutes. */
23
+ readonly everyMs: number;
24
+ readonly anchorAt: string;
25
+ }
26
+ /** Five-field cron, evaluated in an IANA time zone the spec carries. */
27
+ export interface ScheduleCronSpec {
28
+ readonly kind: 'cron';
29
+ /** Normalised five-field text; macros are expanded. */
30
+ readonly expr: string;
31
+ readonly tz: string;
32
+ }
33
+ export type ScheduleSpec = ScheduleAtSpec | ScheduleEverySpec | ScheduleCronSpec;
34
+ /** A parsed cron expression: each field as the sorted set of values it allows. */
35
+ export interface CronExpression {
36
+ readonly source: string;
37
+ readonly minutes: readonly number[];
38
+ readonly hours: readonly number[];
39
+ readonly daysOfMonth: readonly number[];
40
+ readonly months: readonly number[];
41
+ /** 0-6, Sunday = 0 (a written 7 is folded into 0). */
42
+ readonly daysOfWeek: readonly number[];
43
+ /** The day-of-month field does not start with `*`. */
44
+ readonly domRestricted: boolean;
45
+ /** The day-of-week field does not start with `*`. */
46
+ readonly dowRestricted: boolean;
47
+ /**
48
+ * Minute and hour are single values or lists with no `*` or step. Decides
49
+ * the DST rule (cronie's): a fixed-time job fires once per day across a
50
+ * DST change, a wildcard job fires at every instant whose wall time
51
+ * matches.
52
+ */
53
+ readonly fixedTime: boolean;
54
+ }
55
+ /** Why an occurrence did not run. May grow in a minor release. */
56
+ export type ScheduleSkipReason = 'previous-run-active' | 'previous-run-awaiting-approval' | 'paused' | 'awaiting-confirmation' | 'beyond-catch-up-window' | 'one-shot-expired' | 'quota-hold';
57
+ /** Why occurrences were missed. Best effort; may grow in a minor release. */
58
+ export type ScheduleMissedReason = 'daemon-not-running' | 'machine-asleep' | 'clock-jumped-forward';
59
+ /** The lifecycle a job is in, as far as the evaluator cares. */
60
+ export type ScheduleJobLifecycle = 'pending-confirmation' | 'active' | 'paused' | 'completed' | 'expired';
61
+ /** The evaluator's structural view of a job: what it needs and nothing else. */
62
+ export interface ScheduleEvaluationJob {
63
+ readonly spec: ScheduleSpec;
64
+ readonly state: ScheduleJobLifecycle;
65
+ /** Catch-up window; default {@link SCHEDULE_CATCH_UP_WINDOW_MS}. */
66
+ readonly catchUp?: {
67
+ readonly windowMs: number;
68
+ };
69
+ readonly createdAt: string;
70
+ readonly updatedAt: string;
71
+ /** Bumped on every definition change. */
72
+ readonly revision: number;
73
+ }
74
+ /** What the host remembers between evaluations of one job. */
75
+ export interface ScheduleEvaluationState {
76
+ /** Everything up to and including this instant has been decided. */
77
+ readonly lastEvaluatedAt?: string;
78
+ /** The job revision `lastEvaluatedAt` was computed under. */
79
+ readonly jobRevision?: number;
80
+ /** A run of this job that has not finished (or a fire queued but not started). */
81
+ readonly activeRun?: {
82
+ readonly status: 'queued' | 'running' | 'awaiting-approval';
83
+ };
84
+ /** Provider asked to be left alone until this instant. */
85
+ readonly quotaHoldUntil?: string;
86
+ }
87
+ export interface ScheduleObservedGap {
88
+ readonly from: Date;
89
+ readonly to: Date;
90
+ readonly kind: 'asleep' | 'clock-forward' | 'clock-backward';
91
+ }
92
+ export interface ScheduleEvaluationInput {
93
+ readonly job: ScheduleEvaluationJob;
94
+ readonly state: ScheduleEvaluationState;
95
+ readonly now: Date;
96
+ /** When this daemon instance started, and a gap it observed itself. */
97
+ readonly daemon: {
98
+ readonly startedAt: Date;
99
+ readonly observedGap?: ScheduleObservedGap;
100
+ };
101
+ /** How late a fire may be and still count as on time; default {@link SCHEDULE_LATE_GRACE_MS}. */
102
+ readonly lateGraceMs?: number;
103
+ /** Whether an occurrence key was already started (claimed) by someone. */
104
+ readonly isClaimed?: (key: string) => boolean;
105
+ }
106
+ export type ScheduleFireTrigger = 'scheduled' | 'late' | 'catch-up';
107
+ /** What to do about one job now. May grow in a minor release. */
108
+ export interface ScheduleDecision {
109
+ readonly fire?: {
110
+ /** Occurrence key: the scheduled instant in epoch milliseconds. */
111
+ readonly key: string;
112
+ readonly scheduledFor: Date;
113
+ readonly trigger: ScheduleFireTrigger;
114
+ };
115
+ /** Occurrences that will not run, collapsed: one entry per reason. */
116
+ readonly skip: readonly {
117
+ readonly scheduledFor: Date;
118
+ readonly reason: ScheduleSkipReason;
119
+ readonly count: number;
120
+ }[];
121
+ readonly missed?: {
122
+ readonly from: Date;
123
+ readonly to: Date;
124
+ readonly count: number;
125
+ /** The count stopped at the cap; the real number is at least `count`. */
126
+ readonly capped: boolean;
127
+ readonly reason: ScheduleMissedReason;
128
+ };
129
+ readonly jobTransition?: 'completed' | 'expired';
130
+ readonly nextState: {
131
+ readonly lastEvaluatedAt: Date;
132
+ readonly nextFireAt?: Date;
133
+ readonly jobRevision: number;
134
+ };
135
+ }
136
+ /** How occurrences in a window were counted. */
137
+ export interface OccurrenceCount {
138
+ readonly count: number;
139
+ /** The count stopped at the cap. */
140
+ readonly capped: boolean;
141
+ readonly first?: Date;
142
+ readonly latest?: Date;
143
+ }
144
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/schedules/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,uCAAuC;AACvC,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;IACnB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;IACtB,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CACzB;AAED,wEAAwE;AACxE,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,uDAAuD;IACvD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,MAAM,YAAY,GAAG,cAAc,GAAG,iBAAiB,GAAG,gBAAgB,CAAA;AAEhF,kFAAkF;AAClF,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAA;IACvC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;IAClC,sDAAsD;IACtD,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;IACtC,sDAAsD;IACtD,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAA;IAC/B,qDAAqD;IACrD,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAA;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAC3B;AAED,kEAAkE;AAClE,MAAM,MAAM,kBAAkB,GAC3B,qBAAqB,GACrB,gCAAgC,GAChC,QAAQ,GACR,uBAAuB,GACvB,wBAAwB,GACxB,kBAAkB,GAClB,YAAY,CAAA;AAEf,6EAA6E;AAC7E,MAAM,MAAM,oBAAoB,GAAG,oBAAoB,GAAG,gBAAgB,GAAG,sBAAsB,CAAA;AAEnG,gEAAgE;AAChE,MAAM,MAAM,oBAAoB,GAC7B,sBAAsB,GACtB,QAAQ,GACR,QAAQ,GACR,WAAW,GACX,SAAS,CAAA;AAEZ,gFAAgF;AAChF,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAA;IAC3B,QAAQ,CAAC,KAAK,EAAE,oBAAoB,CAAA;IACpC,oEAAoE;IACpE,QAAQ,CAAC,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;IAChD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,yCAAyC;IACzC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CACzB;AAED,8DAA8D;AAC9D,MAAM,WAAW,uBAAuB;IACvC,oEAAoE;IACpE,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAA;IACjC,6DAA6D;IAC7D,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,kFAAkF;IAClF,QAAQ,CAAC,SAAS,CAAC,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,mBAAmB,CAAA;KAAE,CAAA;IACpF,0DAA0D;IAC1D,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAChC;AAED,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;IACnB,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAA;IACjB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,eAAe,GAAG,gBAAgB,CAAA;CAC5D;AAED,MAAM,WAAW,uBAAuB;IACvC,QAAQ,CAAC,GAAG,EAAE,qBAAqB,CAAA;IACnC,QAAQ,CAAC,KAAK,EAAE,uBAAuB,CAAA;IACvC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAA;IAClB,uEAAuE;IACvE,QAAQ,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;QAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,mBAAmB,CAAA;KAAE,CAAA;IACzF,iGAAiG;IACjG,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAA;CAC7C;AAED,MAAM,MAAM,mBAAmB,GAAG,WAAW,GAAG,MAAM,GAAG,UAAU,CAAA;AAEnE,iEAAiE;AACjE,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,IAAI,CAAC,EAAE;QACf,mEAAmE;QACnE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;QACpB,QAAQ,CAAC,YAAY,EAAE,IAAI,CAAA;QAC3B,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAA;KACrC,CAAA;IACD,sEAAsE;IACtE,QAAQ,CAAC,IAAI,EAAE,SAAS;QACvB,QAAQ,CAAC,YAAY,EAAE,IAAI,CAAA;QAC3B,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAA;QACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KACtB,EAAE,CAAA;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE;QACjB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;QACnB,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAA;QACjB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;QACtB,yEAAyE;QACzE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;QACxB,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAA;KACrC,CAAA;IACD,QAAQ,CAAC,aAAa,CAAC,EAAE,WAAW,GAAG,SAAS,CAAA;IAChD,QAAQ,CAAC,SAAS,EAAE;QACnB,QAAQ,CAAC,eAAe,EAAE,IAAI,CAAA;QAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,IAAI,CAAA;QAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;KAC5B,CAAA;CACD;AAED,gDAAgD;AAChD,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,oCAAoC;IACpC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,CAAA;IACrB,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,CAAA;CACtB"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Types of the schedule time engine and evaluator.
3
+ *
4
+ * The SDK owns WHEN something is due and nothing about how a host stores a
5
+ * job or runs it: the CLI keeps its job files, claims and history records to
6
+ * itself, so its on-disk format is not SDK API. The unions exported here
7
+ * (`ScheduleDecision`, `ScheduleSkipReason`, `ScheduleMissedReason`) may grow
8
+ * in a minor release; switch over them with a `default:` branch.
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/schedules/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}