@dsh-enhanced/assistant-automations 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +135 -0
- package/cordis.patch.yml +36 -0
- package/lib/artifacts.d.ts +15 -0
- package/lib/artifacts.d.ts.map +1 -0
- package/lib/artifacts.js +68 -0
- package/lib/artifacts.js.map +1 -0
- package/lib/coordinator.d.ts +126 -0
- package/lib/coordinator.d.ts.map +1 -0
- package/lib/coordinator.js +374 -0
- package/lib/coordinator.js.map +1 -0
- package/lib/index.d.ts +11 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +11 -0
- package/lib/index.js.map +1 -0
- package/lib/operator.d.ts +4 -0
- package/lib/operator.d.ts.map +1 -0
- package/lib/operator.js +12 -0
- package/lib/operator.js.map +1 -0
- package/lib/proposals.d.ts +89 -0
- package/lib/proposals.d.ts.map +1 -0
- package/lib/proposals.js +499 -0
- package/lib/proposals.js.map +1 -0
- package/lib/runner.d.ts +34 -0
- package/lib/runner.d.ts.map +1 -0
- package/lib/runner.js +272 -0
- package/lib/runner.js.map +1 -0
- package/lib/schedule.d.ts +32 -0
- package/lib/schedule.d.ts.map +1 -0
- package/lib/schedule.js +245 -0
- package/lib/schedule.js.map +1 -0
- package/lib/service.d.ts +159 -0
- package/lib/service.d.ts.map +1 -0
- package/lib/service.js +445 -0
- package/lib/service.js.map +1 -0
- package/lib/sqlite.d.ts +8 -0
- package/lib/sqlite.d.ts.map +1 -0
- package/lib/sqlite.js +281 -0
- package/lib/sqlite.js.map +1 -0
- package/lib/store.d.ts +169 -0
- package/lib/store.d.ts.map +1 -0
- package/lib/store.js +1002 -0
- package/lib/store.js.map +1 -0
- package/lib/tools.d.ts +4 -0
- package/lib/tools.d.ts.map +1 -0
- package/lib/tools.js +226 -0
- package/lib/tools.js.map +1 -0
- package/lib/types.d.ts +182 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/types.js +2 -0
- package/lib/types.js.map +1 -0
- package/lib/version.d.ts +2 -0
- package/lib/version.d.ts.map +1 -0
- package/lib/version.js +2 -0
- package/lib/version.js.map +1 -0
- package/package.json +106 -0
package/lib/runner.js
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { installModelSelection, } from '@deepseek-ai/dsh-agent';
|
|
2
|
+
import { createUserMessage } from '@deepseek-ai/dsh-llm';
|
|
3
|
+
import { SessionId } from '@deepseek-ai/dsh-session';
|
|
4
|
+
import { resolveLlmRouteCapability } from '@dsh-enhanced/llm-route-capabilities';
|
|
5
|
+
import { AutomationRunnerAmbiguousError, } from './coordinator.js';
|
|
6
|
+
const usageFields = [
|
|
7
|
+
'inputTokens',
|
|
8
|
+
'outputTokens',
|
|
9
|
+
'cacheReadTokens',
|
|
10
|
+
'cacheWriteTokens',
|
|
11
|
+
'reasoningTokens',
|
|
12
|
+
];
|
|
13
|
+
function summarize(events, signal) {
|
|
14
|
+
let output = '';
|
|
15
|
+
// Seeded empty, not zeroed: execution evidence must distinguish a provider
|
|
16
|
+
// that reported zero from one that never supplied usage at all.
|
|
17
|
+
const usage = {};
|
|
18
|
+
let turnReason;
|
|
19
|
+
for (const event of events) {
|
|
20
|
+
if (event.type === 'assistant/message') {
|
|
21
|
+
const text = event.data.message.content
|
|
22
|
+
.filter(block => block.type === 'text')
|
|
23
|
+
.map(block => block.type === 'text' ? block.text : '')
|
|
24
|
+
.join('');
|
|
25
|
+
if (text !== '')
|
|
26
|
+
output = text;
|
|
27
|
+
if (event.data.usage !== undefined) {
|
|
28
|
+
for (const field of usageFields) {
|
|
29
|
+
const amount = event.data.usage[field];
|
|
30
|
+
if (amount !== undefined)
|
|
31
|
+
usage[field] = (usage[field] ?? 0) + amount;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (event.type === 'turn/end')
|
|
36
|
+
turnReason = event.data.reason;
|
|
37
|
+
}
|
|
38
|
+
let outcome = 'unknown';
|
|
39
|
+
if (signal.aborted)
|
|
40
|
+
outcome = 'cancelled';
|
|
41
|
+
else if (typeof turnReason === 'object' && turnReason !== null && 'kind' in turnReason) {
|
|
42
|
+
const kind = turnReason.kind;
|
|
43
|
+
if (kind === 'completed' || kind === 'max-tokens')
|
|
44
|
+
outcome = 'succeeded';
|
|
45
|
+
else if (kind === 'aborted')
|
|
46
|
+
outcome = 'cancelled';
|
|
47
|
+
else if (kind === 'blocked' || kind === 'error')
|
|
48
|
+
outcome = 'failed';
|
|
49
|
+
}
|
|
50
|
+
return { outcome, output, usage };
|
|
51
|
+
}
|
|
52
|
+
export class AutomationBudgetReplayError extends Error {
|
|
53
|
+
reservationStatus;
|
|
54
|
+
code = 'automation-budget-reservation-replayed';
|
|
55
|
+
constructor(reservationStatus) {
|
|
56
|
+
super(`assistant-automations: budget reservation replay is ${reservationStatus}; refusing duplicate execution`);
|
|
57
|
+
this.reservationStatus = reservationStatus;
|
|
58
|
+
this.name = 'AutomationBudgetReplayError';
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export const AUTOMATION_RUN_BUDGET_METRIC = 'automation-runs';
|
|
62
|
+
/** Prove the configured Policy budget uses the fixed per-run unit before reservation. */
|
|
63
|
+
export function assertAutomationRunBudget(policy, budgetId) {
|
|
64
|
+
const budget = policy.getBudgetConfig(budgetId);
|
|
65
|
+
if (budget === undefined) {
|
|
66
|
+
throw new Error(`assistant-automations: budget is not configured: ${budgetId}`);
|
|
67
|
+
}
|
|
68
|
+
if (budget.id !== budgetId || budget.metric !== AUTOMATION_RUN_BUDGET_METRIC) {
|
|
69
|
+
throw new Error(`assistant-automations: budget ${budgetId} must use ${AUTOMATION_RUN_BUDGET_METRIC}, got ${budget.metric}`);
|
|
70
|
+
}
|
|
71
|
+
return budget;
|
|
72
|
+
}
|
|
73
|
+
function requireToolCapability(llm, provider, model, presetId, toolCount, declaredToolCapableProviders, unknownRouteToolCalls) {
|
|
74
|
+
if (toolCount === 0)
|
|
75
|
+
return;
|
|
76
|
+
const capability = resolveLlmRouteCapability(llm, provider, model);
|
|
77
|
+
if (capability?.toolCalls === 'native' || capability?.toolCalls === 'bridge')
|
|
78
|
+
return;
|
|
79
|
+
// A provider-owned declaration is authoritative in both directions: an
|
|
80
|
+
// explicit `none` still fails closed even when the route is allowlisted or
|
|
81
|
+
// unknown routes are admitted. Only routes with no declaration at all reach
|
|
82
|
+
// the host policy, and the DSH `generate` contract accepts `tools` for every
|
|
83
|
+
// adapter, so admitting them matches the adapter baseline.
|
|
84
|
+
if (capability?.toolCalls !== 'none') {
|
|
85
|
+
if (declaredToolCapableProviders.has(provider))
|
|
86
|
+
return;
|
|
87
|
+
if (unknownRouteToolCalls === 'allow')
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
throw new Error(`assistant-automations: provider ${provider}/${model} has no tool-call capability for preset ${presetId}`);
|
|
91
|
+
}
|
|
92
|
+
export class DshAutomationRunner {
|
|
93
|
+
ctx;
|
|
94
|
+
policy;
|
|
95
|
+
allowUnbudgetedExecution;
|
|
96
|
+
toolCapableProviders;
|
|
97
|
+
unknownRouteToolCalls;
|
|
98
|
+
constructor(ctx, policy, options = {}) {
|
|
99
|
+
this.ctx = ctx;
|
|
100
|
+
this.policy = policy;
|
|
101
|
+
this.allowUnbudgetedExecution = options.allowUnbudgetedExecution ?? false;
|
|
102
|
+
this.toolCapableProviders = new Set(options.toolCapableProviders ?? ['deepseek-official']);
|
|
103
|
+
this.unknownRouteToolCalls = options.unknownRouteToolCalls ?? 'allow';
|
|
104
|
+
}
|
|
105
|
+
async run(input) {
|
|
106
|
+
const agents = this.ctx.get('agents');
|
|
107
|
+
const sessions = this.ctx.get('sessions');
|
|
108
|
+
const tools = this.ctx.get('tools');
|
|
109
|
+
const llm = this.ctx.get('llm');
|
|
110
|
+
if (agents === undefined || sessions === undefined || tools === undefined || llm === undefined) {
|
|
111
|
+
throw new Error('assistant-automations: agents, sessions, and tools services are required');
|
|
112
|
+
}
|
|
113
|
+
const allowed = new Set(input.occurrence.dryRun ? [] : input.automation.definition.allowedTools);
|
|
114
|
+
if (input.signal.aborted)
|
|
115
|
+
throw new Error('assistant-automations: run was cancelled before Agent creation');
|
|
116
|
+
const budgetId = input.automation.definition.budgetId;
|
|
117
|
+
if (budgetId === undefined && !this.allowUnbudgetedExecution) {
|
|
118
|
+
throw new Error('assistant-automations: a configured budget is required for unattended execution');
|
|
119
|
+
}
|
|
120
|
+
if (budgetId !== undefined)
|
|
121
|
+
assertAutomationRunBudget(this.policy, budgetId);
|
|
122
|
+
const agentPresets = this.ctx.get('agentPresets');
|
|
123
|
+
const presetId = agentPresets === undefined
|
|
124
|
+
? input.automation.definition.agentPreset
|
|
125
|
+
: (await agentPresets.resolve(input.automation.definition.agentPreset)).id;
|
|
126
|
+
let reservationId;
|
|
127
|
+
let reservationSettled = false;
|
|
128
|
+
if (budgetId !== undefined) {
|
|
129
|
+
const reservation = this.policy.reserve({
|
|
130
|
+
budgetId,
|
|
131
|
+
subject: {
|
|
132
|
+
kind: 'background',
|
|
133
|
+
id: input.automation.id,
|
|
134
|
+
workspace: input.automation.definition.workspace,
|
|
135
|
+
principal: input.automation.definition.principal,
|
|
136
|
+
},
|
|
137
|
+
amount: input.automation.definition.budgetAmount,
|
|
138
|
+
idempotencyKey: [
|
|
139
|
+
'automation-budget', input.automation.id, input.occurrence.id, AUTOMATION_RUN_BUDGET_METRIC, budgetId,
|
|
140
|
+
].join(':'),
|
|
141
|
+
});
|
|
142
|
+
if (reservation.replayed || reservation.status !== 'reserved') {
|
|
143
|
+
throw new AutomationBudgetReplayError(reservation.status);
|
|
144
|
+
}
|
|
145
|
+
reservationId = reservation.reservationId;
|
|
146
|
+
}
|
|
147
|
+
let handle;
|
|
148
|
+
let agentCreationSubmitted = false;
|
|
149
|
+
let followupSubmitted = false;
|
|
150
|
+
let removeAbort;
|
|
151
|
+
let result;
|
|
152
|
+
try {
|
|
153
|
+
const globalNames = tools.schemas().map(schema => schema.name);
|
|
154
|
+
let toolCalls = 0;
|
|
155
|
+
agentCreationSubmitted = true;
|
|
156
|
+
handle = await agents.create({
|
|
157
|
+
sessionId: SessionId(input.sessionId),
|
|
158
|
+
meta: {
|
|
159
|
+
cwd: input.automation.definition.workspace,
|
|
160
|
+
agentPreset: presetId,
|
|
161
|
+
},
|
|
162
|
+
agentOptions: {
|
|
163
|
+
provider: input.automation.definition.provider,
|
|
164
|
+
model: input.automation.definition.model,
|
|
165
|
+
maxTokens: input.automation.definition.maxOutputTokens,
|
|
166
|
+
},
|
|
167
|
+
signal: input.signal,
|
|
168
|
+
setup: async (agentCtx) => {
|
|
169
|
+
if (agentCtx.agent === undefined) {
|
|
170
|
+
throw new Error('assistant-automations: unpublished Agent identity is missing during setup');
|
|
171
|
+
}
|
|
172
|
+
if (agentCtx.agent.session.header.cwd !== input.automation.definition.workspace
|
|
173
|
+
|| agentCtx.agent.session.header.agentPreset !== presetId) {
|
|
174
|
+
throw new Error('assistant-automations: background Agent identity does not match the immutable definition');
|
|
175
|
+
}
|
|
176
|
+
const unbindInitiator = this.policy.bindInitiator(agentCtx.agent, 'background');
|
|
177
|
+
agentCtx.effect(() => unbindInitiator, 'assistant-automations.background-initiator');
|
|
178
|
+
const delivery = this.ctx.get('assistantDelivery');
|
|
179
|
+
const bindingId = input.automation.definition.deliveryBindingId;
|
|
180
|
+
if (bindingId !== undefined && typeof delivery?.bindAgentApprovalRoute === 'function') {
|
|
181
|
+
const unbindApproval = delivery.bindAgentApprovalRoute(agentCtx.agent, { bindingId });
|
|
182
|
+
agentCtx.effect(() => unbindApproval, 'assistant-automations.approval-route');
|
|
183
|
+
}
|
|
184
|
+
installModelSelection(agentCtx, {
|
|
185
|
+
current: {
|
|
186
|
+
provider: input.automation.definition.provider,
|
|
187
|
+
model: input.automation.definition.model,
|
|
188
|
+
},
|
|
189
|
+
assembled: undefined,
|
|
190
|
+
});
|
|
191
|
+
await agentPresets?.mount(agentCtx, presetId);
|
|
192
|
+
const mountedNames = agentCtx.tools.schemas(agentCtx.agent).map(schema => schema.name);
|
|
193
|
+
for (const name of allowed) {
|
|
194
|
+
if (!mountedNames.includes(name)) {
|
|
195
|
+
throw new Error(`assistant-automations: unknown allowlist tool after preset mount: ${name}`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
const denied = globalNames.filter(name => !allowed.has(name));
|
|
199
|
+
if (denied.length > 0)
|
|
200
|
+
agentCtx.tools.restrict({ deny: denied });
|
|
201
|
+
const finalSchemas = agentCtx.tools.schemas(agentCtx.agent);
|
|
202
|
+
const outsideAllowlist = finalSchemas.map(schema => schema.name).filter(name => !allowed.has(name));
|
|
203
|
+
if (outsideAllowlist.length > 0) {
|
|
204
|
+
throw new Error(`assistant-automations: preset ${presetId} exposes tools outside the immutable allowlist: ${outsideAllowlist.join(', ')}`);
|
|
205
|
+
}
|
|
206
|
+
requireToolCapability(llm, input.automation.definition.provider, input.automation.definition.model, presetId, finalSchemas.length, this.toolCapableProviders, this.unknownRouteToolCalls);
|
|
207
|
+
agentCtx.tools.guard((execution) => {
|
|
208
|
+
if (!allowed.has(execution.name))
|
|
209
|
+
return 'assistant-automations: tool is outside the immutable allowlist';
|
|
210
|
+
if (toolCalls >= input.automation.definition.maxToolCalls) {
|
|
211
|
+
return 'assistant-automations: immutable tool-call budget exhausted';
|
|
212
|
+
}
|
|
213
|
+
toolCalls += 1;
|
|
214
|
+
return undefined;
|
|
215
|
+
});
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
const agent = handle.agent;
|
|
219
|
+
const abort = () => agent.cancel({ kind: 'hook', reason: 'assistant-automations-signal' });
|
|
220
|
+
input.signal.addEventListener('abort', abort, { once: true });
|
|
221
|
+
removeAbort = () => input.signal.removeEventListener('abort', abort);
|
|
222
|
+
followupSubmitted = true;
|
|
223
|
+
agent.followup(createUserMessage({
|
|
224
|
+
content: [{ type: 'text', text: input.automation.definition.prompt }],
|
|
225
|
+
source: {
|
|
226
|
+
kind: 'plugin',
|
|
227
|
+
plugin: '@dsh-enhanced/assistant-automations',
|
|
228
|
+
form: 'notice',
|
|
229
|
+
summary: `Automation: ${input.automation.definition.name}`,
|
|
230
|
+
},
|
|
231
|
+
}));
|
|
232
|
+
await agent.whenIdle();
|
|
233
|
+
result = {
|
|
234
|
+
...summarize(agent.session.events, input.signal),
|
|
235
|
+
sessionId: input.sessionId,
|
|
236
|
+
};
|
|
237
|
+
await sessions.flush(agent.session);
|
|
238
|
+
if (reservationId !== undefined) {
|
|
239
|
+
this.policy.finalize(reservationId, input.automation.definition.budgetAmount);
|
|
240
|
+
reservationSettled = true;
|
|
241
|
+
}
|
|
242
|
+
return result;
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
let caught = error;
|
|
246
|
+
if (reservationId !== undefined && !reservationSettled) {
|
|
247
|
+
try {
|
|
248
|
+
if (!agentCreationSubmitted)
|
|
249
|
+
this.policy.release(reservationId);
|
|
250
|
+
else
|
|
251
|
+
this.policy.finalize(reservationId, input.automation.definition.budgetAmount);
|
|
252
|
+
reservationSettled = true;
|
|
253
|
+
}
|
|
254
|
+
catch (settlementError) {
|
|
255
|
+
caught = new AutomationRunnerAmbiguousError(`assistant-automations: conservative budget settlement failed: ${settlementError instanceof Error ? settlementError.message : String(settlementError)}`, { cause: settlementError });
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
if (caught instanceof AutomationBudgetReplayError) {
|
|
259
|
+
throw caught;
|
|
260
|
+
}
|
|
261
|
+
if (followupSubmitted) {
|
|
262
|
+
throw new AutomationRunnerAmbiguousError(`assistant-automations: Agent execution may have produced side effects: ${caught instanceof Error ? caught.message : String(caught)}`, { cause: caught });
|
|
263
|
+
}
|
|
264
|
+
throw caught;
|
|
265
|
+
}
|
|
266
|
+
finally {
|
|
267
|
+
removeAbort?.();
|
|
268
|
+
await handle?.dispose();
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type AutomationSchedule = {
|
|
2
|
+
kind: 'at';
|
|
3
|
+
at: string;
|
|
4
|
+
} | {
|
|
5
|
+
kind: 'every';
|
|
6
|
+
anchorAt: string;
|
|
7
|
+
intervalMs: number;
|
|
8
|
+
} | {
|
|
9
|
+
kind: 'cron';
|
|
10
|
+
expression: string;
|
|
11
|
+
timezone: string;
|
|
12
|
+
};
|
|
13
|
+
export interface CronFields {
|
|
14
|
+
minute: number[];
|
|
15
|
+
hour: number[];
|
|
16
|
+
dayOfMonth: number[];
|
|
17
|
+
month: number[];
|
|
18
|
+
dayOfWeek: number[];
|
|
19
|
+
dayOfMonthWildcard: boolean;
|
|
20
|
+
dayOfWeekWildcard: boolean;
|
|
21
|
+
}
|
|
22
|
+
export type ScheduleErrorCode = 'invalid-cron' | 'invalid-schedule' | 'invalid-timezone' | 'scan-limit';
|
|
23
|
+
export declare class ScheduleError extends Error {
|
|
24
|
+
readonly code: ScheduleErrorCode;
|
|
25
|
+
constructor(code: ScheduleErrorCode, message: string);
|
|
26
|
+
}
|
|
27
|
+
export declare function validateSchedule(value: unknown): AutomationSchedule;
|
|
28
|
+
export declare function parseCronExpression(expression: string): CronFields;
|
|
29
|
+
export declare function nextOccurrence(schedule: AutomationSchedule, after: number): number | undefined;
|
|
30
|
+
export declare function previousOccurrence(schedule: AutomationSchedule, atOrBefore: number): number | undefined;
|
|
31
|
+
export declare function dueOccurrences(schedule: AutomationSchedule, after: number, now: number, limit: number): number[];
|
|
32
|
+
//# sourceMappingURL=schedule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule.d.ts","sourceRoot":"","sources":["../src/schedule.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAC1B;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC1B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAA;AAE1D,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,kBAAkB,EAAE,OAAO,CAAA;IAC3B,iBAAiB,EAAE,OAAO,CAAA;CAC3B;AAED,MAAM,MAAM,iBAAiB,GAAG,cAAc,GAAG,kBAAkB,GAAG,kBAAkB,GAAG,YAAY,CAAA;AAEvG,qBAAa,aAAc,SAAQ,KAAK;IAC1B,QAAQ,CAAC,IAAI,EAAE,iBAAiB;gBAAvB,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM;CAI9D;AA4BD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,kBAAkB,CAwCnE;AA0CD,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,CAalE;AA8CD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAwB9F;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAuBvG;AAED,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,kBAAkB,EAC5B,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GACZ,MAAM,EAAE,CAgBV"}
|
package/lib/schedule.js
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
export class ScheduleError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
constructor(code, message) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.code = code;
|
|
6
|
+
this.name = 'ScheduleError';
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
const MAX_SCAN_MINUTES = 5 * 366 * 24 * 60;
|
|
10
|
+
const formatters = new Map();
|
|
11
|
+
function canonicalInstant(value, field) {
|
|
12
|
+
if (typeof value !== 'string' || !Number.isFinite(Date.parse(value))) {
|
|
13
|
+
throw new ScheduleError('invalid-schedule', `${field} must be a canonical ISO instant`);
|
|
14
|
+
}
|
|
15
|
+
const parsed = new Date(value);
|
|
16
|
+
if (parsed.toISOString() !== value) {
|
|
17
|
+
throw new ScheduleError('invalid-schedule', `${field} must use canonical ISO milliseconds and Z`);
|
|
18
|
+
}
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
function timezone(value) {
|
|
22
|
+
if (typeof value !== 'string' || value.trim() === '') {
|
|
23
|
+
throw new ScheduleError('invalid-timezone', 'timezone must be a non-empty IANA zone');
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
new Intl.DateTimeFormat('en-CA', { timeZone: value }).format(0);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
throw new ScheduleError('invalid-timezone', `invalid IANA timezone: ${value}`);
|
|
30
|
+
}
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
33
|
+
export function validateSchedule(value) {
|
|
34
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
35
|
+
throw new ScheduleError('invalid-schedule', 'schedule must be an object');
|
|
36
|
+
}
|
|
37
|
+
const input = value;
|
|
38
|
+
if (input['kind'] === 'at') {
|
|
39
|
+
if (Object.keys(input).some(key => key !== 'at' && key !== 'kind')) {
|
|
40
|
+
throw new ScheduleError('invalid-schedule', 'at schedule contains an unknown field');
|
|
41
|
+
}
|
|
42
|
+
return Object.freeze({ kind: 'at', at: canonicalInstant(input['at'], 'at') });
|
|
43
|
+
}
|
|
44
|
+
if (input['kind'] === 'every') {
|
|
45
|
+
if (Object.keys(input).some(key => !['anchorAt', 'intervalMs', 'kind'].includes(key))) {
|
|
46
|
+
throw new ScheduleError('invalid-schedule', 'every schedule contains an unknown field');
|
|
47
|
+
}
|
|
48
|
+
const intervalMs = input['intervalMs'];
|
|
49
|
+
if (!Number.isSafeInteger(intervalMs) || intervalMs < 60_000) {
|
|
50
|
+
throw new ScheduleError('invalid-schedule', 'intervalMs must be a safe integer of at least 60000');
|
|
51
|
+
}
|
|
52
|
+
return Object.freeze({
|
|
53
|
+
kind: 'every',
|
|
54
|
+
anchorAt: canonicalInstant(input['anchorAt'], 'anchorAt'),
|
|
55
|
+
intervalMs: intervalMs,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
if (input['kind'] === 'cron') {
|
|
59
|
+
if (Object.keys(input).some(key => !['expression', 'kind', 'timezone'].includes(key))) {
|
|
60
|
+
throw new ScheduleError('invalid-schedule', 'cron schedule contains an unknown field');
|
|
61
|
+
}
|
|
62
|
+
if (typeof input['expression'] !== 'string') {
|
|
63
|
+
throw new ScheduleError('invalid-cron', 'cron expression must be a string');
|
|
64
|
+
}
|
|
65
|
+
parseCronExpression(input['expression']);
|
|
66
|
+
return Object.freeze({
|
|
67
|
+
kind: 'cron',
|
|
68
|
+
expression: input['expression'],
|
|
69
|
+
timezone: timezone(input['timezone']),
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
throw new ScheduleError('invalid-schedule', 'schedule kind must be at, every, or cron');
|
|
73
|
+
}
|
|
74
|
+
function integer(value, minimum, maximum) {
|
|
75
|
+
if (!/^\d+$/.test(value))
|
|
76
|
+
throw new ScheduleError('invalid-cron', `invalid cron integer: ${value}`);
|
|
77
|
+
const parsed = Number(value);
|
|
78
|
+
if (!Number.isSafeInteger(parsed) || parsed < minimum || parsed > maximum) {
|
|
79
|
+
throw new ScheduleError('invalid-cron', `cron integer is outside ${minimum}-${maximum}: ${value}`);
|
|
80
|
+
}
|
|
81
|
+
return parsed;
|
|
82
|
+
}
|
|
83
|
+
function field(value, minimum, maximum, sundayAlias = false) {
|
|
84
|
+
if (value === '')
|
|
85
|
+
throw new ScheduleError('invalid-cron', 'cron field must not be empty');
|
|
86
|
+
const values = new Set();
|
|
87
|
+
for (const segment of value.split(',')) {
|
|
88
|
+
if (segment === '')
|
|
89
|
+
throw new ScheduleError('invalid-cron', 'cron list contains an empty item');
|
|
90
|
+
const slash = segment.split('/');
|
|
91
|
+
if (slash.length > 2)
|
|
92
|
+
throw new ScheduleError('invalid-cron', `invalid cron step: ${segment}`);
|
|
93
|
+
const base = slash[0];
|
|
94
|
+
const step = slash[1] === undefined ? 1 : integer(slash[1], 1, maximum - minimum + 1);
|
|
95
|
+
let start;
|
|
96
|
+
let end;
|
|
97
|
+
if (base === '*') {
|
|
98
|
+
start = minimum;
|
|
99
|
+
end = maximum;
|
|
100
|
+
}
|
|
101
|
+
else if (base.includes('-')) {
|
|
102
|
+
const range = base.split('-');
|
|
103
|
+
if (range.length !== 2)
|
|
104
|
+
throw new ScheduleError('invalid-cron', `invalid cron range: ${base}`);
|
|
105
|
+
start = integer(range[0], minimum, maximum);
|
|
106
|
+
end = integer(range[1], minimum, maximum);
|
|
107
|
+
if (start > end)
|
|
108
|
+
throw new ScheduleError('invalid-cron', `cron range is descending: ${base}`);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
start = integer(base, minimum, maximum);
|
|
112
|
+
end = start;
|
|
113
|
+
}
|
|
114
|
+
for (let current = start; current <= end; current += step) {
|
|
115
|
+
values.add(sundayAlias && current === 7 ? 0 : current);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return [...values].sort((left, right) => left - right);
|
|
119
|
+
}
|
|
120
|
+
export function parseCronExpression(expression) {
|
|
121
|
+
const parts = expression.trim().split(/\s+/);
|
|
122
|
+
if (parts.length !== 5)
|
|
123
|
+
throw new ScheduleError('invalid-cron', 'cron expression must contain exactly five fields');
|
|
124
|
+
const [minute, hour, dayOfMonth, month, dayOfWeek] = parts;
|
|
125
|
+
return Object.freeze({
|
|
126
|
+
minute: Object.freeze(field(minute, 0, 59)),
|
|
127
|
+
hour: Object.freeze(field(hour, 0, 23)),
|
|
128
|
+
dayOfMonth: Object.freeze(field(dayOfMonth, 1, 31)),
|
|
129
|
+
month: Object.freeze(field(month, 1, 12)),
|
|
130
|
+
dayOfWeek: Object.freeze(field(dayOfWeek, 0, 7, true)),
|
|
131
|
+
dayOfMonthWildcard: dayOfMonth === '*',
|
|
132
|
+
dayOfWeekWildcard: dayOfWeek === '*',
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
function formatter(zone) {
|
|
136
|
+
let value = formatters.get(zone);
|
|
137
|
+
if (value !== undefined)
|
|
138
|
+
return value;
|
|
139
|
+
value = new Intl.DateTimeFormat('en-CA', {
|
|
140
|
+
timeZone: zone,
|
|
141
|
+
year: 'numeric',
|
|
142
|
+
month: '2-digit',
|
|
143
|
+
day: '2-digit',
|
|
144
|
+
hour: '2-digit',
|
|
145
|
+
minute: '2-digit',
|
|
146
|
+
hourCycle: 'h23',
|
|
147
|
+
});
|
|
148
|
+
formatters.set(zone, value);
|
|
149
|
+
return value;
|
|
150
|
+
}
|
|
151
|
+
function localParts(instant, zone) {
|
|
152
|
+
const parts = new Map(formatter(zone).formatToParts(new Date(instant)).map(part => [part.type, part.value]));
|
|
153
|
+
const year = Number(parts.get('year'));
|
|
154
|
+
const month = Number(parts.get('month'));
|
|
155
|
+
const day = Number(parts.get('day'));
|
|
156
|
+
const hour = Number(parts.get('hour')) % 24;
|
|
157
|
+
const minute = Number(parts.get('minute'));
|
|
158
|
+
return { year, month, day, hour, minute, dayOfWeek: new Date(Date.UTC(year, month - 1, day)).getUTCDay() };
|
|
159
|
+
}
|
|
160
|
+
function cronMatches(fields, local) {
|
|
161
|
+
if (!fields.minute.includes(local.minute) || !fields.hour.includes(local.hour) || !fields.month.includes(local.month)) {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
const dayOfMonth = fields.dayOfMonth.includes(local.day);
|
|
165
|
+
const dayOfWeek = fields.dayOfWeek.includes(local.dayOfWeek);
|
|
166
|
+
if (fields.dayOfMonthWildcard)
|
|
167
|
+
return dayOfWeek;
|
|
168
|
+
if (fields.dayOfWeekWildcard)
|
|
169
|
+
return dayOfMonth;
|
|
170
|
+
return dayOfMonth || dayOfWeek;
|
|
171
|
+
}
|
|
172
|
+
export function nextOccurrence(schedule, after) {
|
|
173
|
+
if (!Number.isSafeInteger(after))
|
|
174
|
+
throw new ScheduleError('invalid-schedule', 'after must be a safe millisecond instant');
|
|
175
|
+
switch (schedule.kind) {
|
|
176
|
+
case 'at': {
|
|
177
|
+
const instant = Date.parse(schedule.at);
|
|
178
|
+
return instant > after ? instant : undefined;
|
|
179
|
+
}
|
|
180
|
+
case 'every': {
|
|
181
|
+
const anchor = Date.parse(schedule.anchorAt);
|
|
182
|
+
if (after < anchor)
|
|
183
|
+
return anchor;
|
|
184
|
+
const periods = Math.floor((after - anchor) / schedule.intervalMs) + 1;
|
|
185
|
+
const instant = anchor + periods * schedule.intervalMs;
|
|
186
|
+
if (!Number.isSafeInteger(instant))
|
|
187
|
+
throw new ScheduleError('scan-limit', 'fixed interval exceeds safe time range');
|
|
188
|
+
return instant;
|
|
189
|
+
}
|
|
190
|
+
case 'cron': {
|
|
191
|
+
const fields = parseCronExpression(schedule.expression);
|
|
192
|
+
let candidate = Math.floor(after / 60_000) * 60_000 + 60_000;
|
|
193
|
+
for (let scanned = 0; scanned < MAX_SCAN_MINUTES; scanned += 1, candidate += 60_000) {
|
|
194
|
+
if (cronMatches(fields, localParts(candidate, schedule.timezone)))
|
|
195
|
+
return candidate;
|
|
196
|
+
}
|
|
197
|
+
throw new ScheduleError('scan-limit', 'no cron occurrence found within five years');
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
export function previousOccurrence(schedule, atOrBefore) {
|
|
202
|
+
if (!Number.isSafeInteger(atOrBefore)) {
|
|
203
|
+
throw new ScheduleError('invalid-schedule', 'atOrBefore must be a safe millisecond instant');
|
|
204
|
+
}
|
|
205
|
+
switch (schedule.kind) {
|
|
206
|
+
case 'at': {
|
|
207
|
+
const instant = Date.parse(schedule.at);
|
|
208
|
+
return instant <= atOrBefore ? instant : undefined;
|
|
209
|
+
}
|
|
210
|
+
case 'every': {
|
|
211
|
+
const anchor = Date.parse(schedule.anchorAt);
|
|
212
|
+
if (atOrBefore < anchor)
|
|
213
|
+
return undefined;
|
|
214
|
+
return anchor + Math.floor((atOrBefore - anchor) / schedule.intervalMs) * schedule.intervalMs;
|
|
215
|
+
}
|
|
216
|
+
case 'cron': {
|
|
217
|
+
const fields = parseCronExpression(schedule.expression);
|
|
218
|
+
let candidate = Math.floor(atOrBefore / 60_000) * 60_000;
|
|
219
|
+
for (let scanned = 0; scanned < MAX_SCAN_MINUTES; scanned += 1, candidate -= 60_000) {
|
|
220
|
+
if (cronMatches(fields, localParts(candidate, schedule.timezone)))
|
|
221
|
+
return candidate;
|
|
222
|
+
}
|
|
223
|
+
throw new ScheduleError('scan-limit', 'no prior cron occurrence found within five years');
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
export function dueOccurrences(schedule, after, now, limit) {
|
|
228
|
+
if (!Number.isSafeInteger(now) || now < after) {
|
|
229
|
+
throw new ScheduleError('invalid-schedule', 'now must be a safe instant at or after the cursor');
|
|
230
|
+
}
|
|
231
|
+
if (!Number.isSafeInteger(limit) || limit <= 0 || limit > 10_000) {
|
|
232
|
+
throw new ScheduleError('invalid-schedule', 'due occurrence limit must be between 1 and 10000');
|
|
233
|
+
}
|
|
234
|
+
const output = [];
|
|
235
|
+
let cursor = after;
|
|
236
|
+
while (output.length < limit) {
|
|
237
|
+
const next = nextOccurrence(schedule, cursor);
|
|
238
|
+
if (next === undefined || next > now)
|
|
239
|
+
break;
|
|
240
|
+
output.push(next);
|
|
241
|
+
cursor = next;
|
|
242
|
+
}
|
|
243
|
+
return output;
|
|
244
|
+
}
|
|
245
|
+
//# sourceMappingURL=schedule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule.js","sourceRoot":"","sources":["../src/schedule.ts"],"names":[],"mappings":"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"}
|