@deepseek-ai/dsh-schedule 0.2.0-rc.2 → 0.2.1-alpha.1
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/README.i18n.yaml +14 -14
- package/README.md +6 -5
- package/README.zh.md +6 -5
- package/lib/index.js +37 -645
- package/lib/typert.host.js +16 -9
- package/lib/typert.remote-client.js +8 -5
- package/lib/types/domain.d.ts +3 -3
- package/lib/types/domain.js +1 -1
- package/lib/types/index.d.ts +24 -5
- package/lib/types/index.js +40 -30
- package/lib/types/types.d.ts +6 -1
- package/package.json +35 -40
- package/lib/invariant.js +0 -370
- package/lib/types/invariant.d.ts +0 -16
- package/lib/types/invariant.js +0 -58
- package/lib/types/tools.d.ts +0 -15
- package/lib/types/tools.js +0 -505
package/lib/invariant.js
DELETED
|
@@ -1,370 +0,0 @@
|
|
|
1
|
-
import "@js-temporal/polyfill";
|
|
2
|
-
import { SessionLogOffset } from "@deepseek-ai/dsh-session";
|
|
3
|
-
const MIN_FOUR_DIGIT_YEAR_MS = Date.parse("0001-01-01T00:00:00.000Z");
|
|
4
|
-
const MAX_FOUR_DIGIT_YEAR_MS = Date.parse("9999-12-31T23:59:59.999Z");
|
|
5
|
-
const UTC_INSTANT = /^(?!0000)\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d\.\d{3}Z$/;
|
|
6
|
-
new RegExp(String.raw`^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})` + String.raw`T(?<hour>\d{2}):(?<minute>\d{2}):(?<second>\d{2})` + String.raw`(?:\.(?<fraction>\d{1,3}))?(?<zone>Z|(?<sign>[+-])` + String.raw`(?<offsetHour>\d{2}):(?<offsetMinute>\d{2}))$`);
|
|
7
|
-
/** Error from malformed or transition-invalid durable Schedule data. */
|
|
8
|
-
var ScheduleLogError = class extends Error {
|
|
9
|
-
/** Stable machine-readable error code. */
|
|
10
|
-
code = "corrupt_schedule_log";
|
|
11
|
-
/**
|
|
12
|
-
* Construct a durable-log failure.
|
|
13
|
-
* @param message - Package-specific violated invariant.
|
|
14
|
-
*/
|
|
15
|
-
constructor(message) {
|
|
16
|
-
super(message);
|
|
17
|
-
this.name = "ScheduleLogError";
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
/**
|
|
21
|
-
* Brand a raw session-local id without changing its runtime value.
|
|
22
|
-
* @param value - Raw session-local id.
|
|
23
|
-
* @returns The same string with the Schedule brand.
|
|
24
|
-
*/
|
|
25
|
-
function ScheduleId(value) {
|
|
26
|
-
return value;
|
|
27
|
-
}
|
|
28
|
-
/** Whether an unknown value is a non-array object. */
|
|
29
|
-
function isRecord(value) {
|
|
30
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
31
|
-
}
|
|
32
|
-
/** Require exactly the named durable object keys. */
|
|
33
|
-
function hasExactKeys(value, expected) {
|
|
34
|
-
const allowed = new Set(expected);
|
|
35
|
-
return expected.every((key) => key in value) && Object.keys(value).every((key) => allowed.has(key));
|
|
36
|
-
}
|
|
37
|
-
/** Require the named durable keys while admitting further optional members. */
|
|
38
|
-
function hasExactKeysWithOptional(value, required, optional) {
|
|
39
|
-
const allowed = new Set([...required, ...optional]);
|
|
40
|
-
return required.every((key) => key in value) && Object.keys(value).every((key) => allowed.has(key));
|
|
41
|
-
}
|
|
42
|
-
/** Stable diagnostic for a title that is missing or empty after trimming. */
|
|
43
|
-
const REQUIRED_TITLE_MESSAGE = "title is required and must be non-empty after trimming.";
|
|
44
|
-
/**
|
|
45
|
-
* Validate one required stored title at the durable boundary.
|
|
46
|
-
*
|
|
47
|
-
* Only records written after titles became required are read: a missing,
|
|
48
|
-
* blank-after-trim, untrimmed, or over-long stored title is invalid, and no name
|
|
49
|
-
* is derived from the instruction.
|
|
50
|
-
* @param value - Untrusted durable title field.
|
|
51
|
-
* @returns The stored title; an invalid title throws ScheduleLogError.
|
|
52
|
-
*/
|
|
53
|
-
function decodeStoredTitle(value) {
|
|
54
|
-
if (typeof value !== "string" || value.trim().length === 0) throw new ScheduleLogError(REQUIRED_TITLE_MESSAGE);
|
|
55
|
-
if (value.length > 120) throw new ScheduleLogError(`title must be at most 120 characters`);
|
|
56
|
-
if (value.trim() !== value) throw new ScheduleLogError("title must be a trimmed string");
|
|
57
|
-
return value;
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Decode the stored title of one historical `schedule/change` create record.
|
|
61
|
-
*
|
|
62
|
-
* A version-1 event written before names existed has no `title` member, so the
|
|
63
|
-
* key set is required without it and the absent member decodes as undefined. A
|
|
64
|
-
* present title stays subject to the canonical stored form.
|
|
65
|
-
* @param value - Untrusted durable record already known to be an object.
|
|
66
|
-
* @param expected - Exact keys the record may carry; `title` is optional within them.
|
|
67
|
-
* @param message - Diagnostic naming the record's keys.
|
|
68
|
-
* @returns The stored title, or undefined when the historical record predates it.
|
|
69
|
-
*/
|
|
70
|
-
function decodeHistoricalRecordTitle(value, expected, message) {
|
|
71
|
-
if (!hasExactKeysWithOptional(value, expected.filter((key) => key !== "title"), ["title"])) throw new ScheduleLogError(message);
|
|
72
|
-
return value["title"] === void 0 ? void 0 : decodeStoredTitle(value["title"]);
|
|
73
|
-
}
|
|
74
|
-
/** Validate one stable session-local id at the durable boundary. */
|
|
75
|
-
function decodeId(value) {
|
|
76
|
-
if (typeof value !== "string" || value.length === 0 || value.trim() !== value) throw new ScheduleLogError("schedule id must be a non-empty string without surrounding whitespace");
|
|
77
|
-
return ScheduleId(value);
|
|
78
|
-
}
|
|
79
|
-
/** Validate one canonical four-digit-year UTC instant. */
|
|
80
|
-
function decodeInstant(value) {
|
|
81
|
-
if (typeof value !== "string" || !UTC_INSTANT.test(value)) throw new ScheduleLogError("scheduledAt must be a canonical four-digit-year RFC 3339 UTC instant");
|
|
82
|
-
const epoch = Date.parse(value);
|
|
83
|
-
if (!Number.isFinite(epoch) || new Date(epoch).toISOString() !== value) throw new ScheduleLogError("scheduledAt is not a real UTC calendar instant");
|
|
84
|
-
return value;
|
|
85
|
-
}
|
|
86
|
-
/** Decode the exact v1 after record shape. */
|
|
87
|
-
function decodeAfterRecord(value) {
|
|
88
|
-
/* v8 ignore next -- decodeLegacyScheduleRecord rejects a non-object before it dispatches here. */
|
|
89
|
-
if (!isRecord(value)) throw new ScheduleLogError("after schedule must be an object");
|
|
90
|
-
const title = decodeHistoricalRecordTitle(value, [
|
|
91
|
-
"id",
|
|
92
|
-
"kind",
|
|
93
|
-
"title",
|
|
94
|
-
"prompt",
|
|
95
|
-
"afterSeconds",
|
|
96
|
-
"scheduledAt"
|
|
97
|
-
], "after schedule must contain exactly id, kind, title, prompt, afterSeconds, and scheduledAt");
|
|
98
|
-
const prompt = value["prompt"];
|
|
99
|
-
if (typeof prompt !== "string" || prompt.length === 0 || prompt.trim() !== prompt) throw new ScheduleLogError("after prompt must be non-empty and already trimmed");
|
|
100
|
-
const afterSeconds = value["afterSeconds"];
|
|
101
|
-
if (!Number.isSafeInteger(afterSeconds) || afterSeconds <= 0) throw new ScheduleLogError("afterSeconds must be a positive safe integer");
|
|
102
|
-
return Object.freeze({
|
|
103
|
-
id: decodeId(value["id"]),
|
|
104
|
-
kind: "after",
|
|
105
|
-
...title === void 0 ? {} : { title },
|
|
106
|
-
prompt,
|
|
107
|
-
afterSeconds,
|
|
108
|
-
scheduledAt: decodeInstant(value["scheduledAt"])
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
/** Decode the exact v1 absolute one-shot record shape. */
|
|
112
|
-
function decodeAtRecord(value) {
|
|
113
|
-
/* v8 ignore next -- decodeLegacyScheduleRecord rejects a non-object before it dispatches here. */
|
|
114
|
-
if (!isRecord(value)) throw new ScheduleLogError("at schedule must be an object");
|
|
115
|
-
const title = decodeHistoricalRecordTitle(value, [
|
|
116
|
-
"id",
|
|
117
|
-
"kind",
|
|
118
|
-
"title",
|
|
119
|
-
"prompt",
|
|
120
|
-
"scheduledAt"
|
|
121
|
-
], "at schedule must contain exactly id, kind, title, prompt, and scheduledAt");
|
|
122
|
-
const prompt = value["prompt"];
|
|
123
|
-
if (typeof prompt !== "string" || prompt.length === 0 || prompt.trim() !== prompt) throw new ScheduleLogError("at prompt must be non-empty and already trimmed");
|
|
124
|
-
return Object.freeze({
|
|
125
|
-
id: decodeId(value["id"]),
|
|
126
|
-
kind: "at",
|
|
127
|
-
...title === void 0 ? {} : { title },
|
|
128
|
-
prompt,
|
|
129
|
-
scheduledAt: decodeInstant(value["scheduledAt"])
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
/** Decode the exact v1 fixed-rate record shape. */
|
|
133
|
-
function decodeEveryRecord(value) {
|
|
134
|
-
/* v8 ignore next -- decodeLegacyScheduleRecord rejects a non-object before it dispatches here. */
|
|
135
|
-
if (!isRecord(value)) throw new ScheduleLogError("every schedule must be an object");
|
|
136
|
-
const title = decodeHistoricalRecordTitle(value, [
|
|
137
|
-
"id",
|
|
138
|
-
"kind",
|
|
139
|
-
"title",
|
|
140
|
-
"prompt",
|
|
141
|
-
"everySeconds",
|
|
142
|
-
"scheduledAt"
|
|
143
|
-
], "every schedule must contain exactly id, kind, title, prompt, everySeconds, and scheduledAt");
|
|
144
|
-
const prompt = value["prompt"];
|
|
145
|
-
if (typeof prompt !== "string" || prompt.length === 0 || prompt.trim() !== prompt) throw new ScheduleLogError("every prompt must be non-empty and already trimmed");
|
|
146
|
-
const everySeconds = value["everySeconds"];
|
|
147
|
-
const interval = typeof everySeconds === "number" ? everySeconds * 1e3 : NaN;
|
|
148
|
-
if (!Number.isSafeInteger(everySeconds) || everySeconds < 60 || !Number.isSafeInteger(interval)) throw new ScheduleLogError(`everySeconds must be a safe integer of at least 60`);
|
|
149
|
-
return Object.freeze({
|
|
150
|
-
id: decodeId(value["id"]),
|
|
151
|
-
kind: "every",
|
|
152
|
-
...title === void 0 ? {} : { title },
|
|
153
|
-
prompt,
|
|
154
|
-
everySeconds,
|
|
155
|
-
scheduledAt: decodeInstant(value["scheduledAt"])
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Decode only the variants admitted by historical version-1 Session events.
|
|
160
|
-
*
|
|
161
|
-
* A record written before titles existed decodes without that member, so the
|
|
162
|
-
* fold keeps reading a log that the current creation path could not write.
|
|
163
|
-
* @param value - Untrusted durable JSON record from a Session event.
|
|
164
|
-
* @returns Detached frozen record, without a title when the event omitted it.
|
|
165
|
-
*/
|
|
166
|
-
function decodeLegacyScheduleRecord(value) {
|
|
167
|
-
if (!isRecord(value)) throw new ScheduleLogError("schedule record must be an object");
|
|
168
|
-
switch (value["kind"]) {
|
|
169
|
-
case "after": return decodeAfterRecord(value);
|
|
170
|
-
case "at": return decodeAtRecord(value);
|
|
171
|
-
case "every": return decodeEveryRecord(value);
|
|
172
|
-
default: throw new ScheduleLogError("v1 schedule kind must be \"after\", \"at\", or \"every\"");
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
/**
|
|
176
|
-
* Decode one strict version-1 `schedule/change` payload.
|
|
177
|
-
* @param value - Untrusted durable JSON value.
|
|
178
|
-
* @returns Detached, frozen Schedule change.
|
|
179
|
-
*/
|
|
180
|
-
function decodeScheduleChange(value) {
|
|
181
|
-
if (!isRecord(value)) throw new ScheduleLogError("schedule/change payload must be an object");
|
|
182
|
-
if (value["version"] !== 1) throw new ScheduleLogError("schedule/change version must be 1");
|
|
183
|
-
switch (value["operation"]) {
|
|
184
|
-
case "create":
|
|
185
|
-
if (!hasExactKeys(value, [
|
|
186
|
-
"version",
|
|
187
|
-
"operation",
|
|
188
|
-
"schedule"
|
|
189
|
-
])) throw new ScheduleLogError("schedule create must contain exactly version, operation, and schedule");
|
|
190
|
-
return Object.freeze({
|
|
191
|
-
version: 1,
|
|
192
|
-
operation: "create",
|
|
193
|
-
schedule: decodeLegacyScheduleRecord(value["schedule"])
|
|
194
|
-
});
|
|
195
|
-
case "delete":
|
|
196
|
-
if (!hasExactKeys(value, [
|
|
197
|
-
"version",
|
|
198
|
-
"operation",
|
|
199
|
-
"id"
|
|
200
|
-
])) throw new ScheduleLogError("schedule delete must contain exactly version, operation, and id");
|
|
201
|
-
return Object.freeze({
|
|
202
|
-
version: 1,
|
|
203
|
-
operation: "delete",
|
|
204
|
-
id: decodeId(value["id"])
|
|
205
|
-
});
|
|
206
|
-
case "dispatch":
|
|
207
|
-
if (hasExactKeys(value, [
|
|
208
|
-
"version",
|
|
209
|
-
"operation",
|
|
210
|
-
"id"
|
|
211
|
-
])) return Object.freeze({
|
|
212
|
-
version: 1,
|
|
213
|
-
operation: "dispatch",
|
|
214
|
-
id: decodeId(value["id"])
|
|
215
|
-
});
|
|
216
|
-
if (hasExactKeys(value, [
|
|
217
|
-
"version",
|
|
218
|
-
"operation",
|
|
219
|
-
"id",
|
|
220
|
-
"acceptedAt"
|
|
221
|
-
])) return Object.freeze({
|
|
222
|
-
version: 1,
|
|
223
|
-
operation: "dispatch",
|
|
224
|
-
id: decodeId(value["id"]),
|
|
225
|
-
acceptedAt: decodeInstant(value["acceptedAt"])
|
|
226
|
-
});
|
|
227
|
-
throw new ScheduleLogError("schedule dispatch must contain id and optional acceptedAt only");
|
|
228
|
-
default: throw new ScheduleLogError("schedule/change operation must be create, delete, or dispatch");
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
/**
|
|
232
|
-
* Resolve one fixed-rate decision without enumerating missed occurrences.
|
|
233
|
-
* @param record - Active record whose target is the earliest unaccepted occurrence.
|
|
234
|
-
* @param acceptedAt - Wall-clock decision time in epoch milliseconds.
|
|
235
|
-
* @returns The latest due occurrence and first strictly future target, if representable.
|
|
236
|
-
*/
|
|
237
|
-
function resolveEveryOccurrence(record, acceptedAt) {
|
|
238
|
-
const target = Date.parse(record.scheduledAt);
|
|
239
|
-
const interval = record.everySeconds * 1e3;
|
|
240
|
-
if (!Number.isSafeInteger(acceptedAt) || acceptedAt < MIN_FOUR_DIGIT_YEAR_MS || acceptedAt > MAX_FOUR_DIGIT_YEAR_MS) throw new ScheduleLogError("every acceptedAt must be a representable four-digit-year instant");
|
|
241
|
-
if (!Number.isSafeInteger(interval) || interval <= 0) throw new ScheduleLogError("every interval milliseconds must be a positive safe integer");
|
|
242
|
-
if (acceptedAt < target) throw new ScheduleLogError("every dispatch cannot precede the active scheduledAt");
|
|
243
|
-
const occurrence = target + Math.floor((acceptedAt - target) / interval) * interval;
|
|
244
|
-
/* v8 ignore next -- bounded operands and a quotient-derived product stay safe. */
|
|
245
|
-
if (!Number.isSafeInteger(occurrence) || occurrence < target || occurrence > acceptedAt) throw new ScheduleLogError("every occurrence arithmetic must stay within the accepted interval");
|
|
246
|
-
const occurrenceAt = new Date(occurrence).toISOString();
|
|
247
|
-
const next = occurrence + interval;
|
|
248
|
-
if (!Number.isSafeInteger(next) || next > MAX_FOUR_DIGIT_YEAR_MS) return Object.freeze({ occurrenceAt });
|
|
249
|
-
return Object.freeze({
|
|
250
|
-
occurrenceAt,
|
|
251
|
-
nextScheduledAt: new Date(next).toISOString()
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
/** Apply one decoded dispatch to its exact active record. */
|
|
255
|
-
function dispatchedRecord(record, change) {
|
|
256
|
-
const hasAcceptedAt = "acceptedAt" in change;
|
|
257
|
-
if (record.kind !== "every") {
|
|
258
|
-
if (hasAcceptedAt) throw new ScheduleLogError("one-shot dispatch must not contain acceptedAt");
|
|
259
|
-
return;
|
|
260
|
-
}
|
|
261
|
-
if (!hasAcceptedAt) throw new ScheduleLogError("every dispatch must contain acceptedAt");
|
|
262
|
-
const occurrence = resolveEveryOccurrence(record, Date.parse(change.acceptedAt));
|
|
263
|
-
return occurrence.nextScheduledAt === void 0 ? void 0 : Object.freeze({
|
|
264
|
-
...record,
|
|
265
|
-
scheduledAt: occurrence.nextScheduledAt
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
/**
|
|
269
|
-
* Apply already-decoded Schedule changes to one complete fold value.
|
|
270
|
-
*
|
|
271
|
-
* The transition authority for full-log replay. One mutable Map/Set pair spans
|
|
272
|
-
* the whole batch; the returned arrays are materialized and frozen once.
|
|
273
|
-
* @param folded - complete active records and used-id history before the changes.
|
|
274
|
-
* @param changes - strictly decoded durable mutations in log order.
|
|
275
|
-
* @returns the complete fold value after every mutation.
|
|
276
|
-
*/
|
|
277
|
-
function applyScheduleChanges(folded, changes) {
|
|
278
|
-
const active = new Map(folded.active.map((record) => [record.id, record]));
|
|
279
|
-
const seen = new Set(folded.seenIds);
|
|
280
|
-
for (const change of changes) switch (change.operation) {
|
|
281
|
-
case "create":
|
|
282
|
-
if (seen.has(change.schedule.id)) throw new ScheduleLogError(`schedule id ${JSON.stringify(change.schedule.id)} was reused`);
|
|
283
|
-
seen.add(change.schedule.id);
|
|
284
|
-
active.set(change.schedule.id, change.schedule);
|
|
285
|
-
break;
|
|
286
|
-
case "delete":
|
|
287
|
-
if (!active.delete(change.id)) throw new ScheduleLogError(`schedule delete targets inactive id ${JSON.stringify(change.id)}`);
|
|
288
|
-
break;
|
|
289
|
-
case "dispatch": {
|
|
290
|
-
const record = active.get(change.id);
|
|
291
|
-
if (record === void 0) throw new ScheduleLogError(`schedule dispatch targets inactive id ${JSON.stringify(change.id)}`);
|
|
292
|
-
const next = dispatchedRecord(record, change);
|
|
293
|
-
if (next === void 0) active.delete(change.id);
|
|
294
|
-
else active.set(change.id, next);
|
|
295
|
-
break;
|
|
296
|
-
}
|
|
297
|
-
/* v8 ignore next 3 -- decodeScheduleChange returns a closed operation union. */
|
|
298
|
-
default: throw new ScheduleLogError(`unknown decoded schedule change ${String(change)}`);
|
|
299
|
-
}
|
|
300
|
-
return Object.freeze({
|
|
301
|
-
active: Object.freeze([...active.values()]),
|
|
302
|
-
seenIds: Object.freeze([...seen])
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
/**
|
|
306
|
-
* Fold the package-owned stream after the durable fork seed boundary.
|
|
307
|
-
* @param events - Complete ordered session log or candidate-extended log.
|
|
308
|
-
* @param inheritedEventCount - Inherited prefix length excluded from child ownership.
|
|
309
|
-
* @returns Active records and all previously used ids.
|
|
310
|
-
*/
|
|
311
|
-
function foldScheduleEvents(events, inheritedEventCount = SessionLogOffset(0)) {
|
|
312
|
-
if (!Number.isSafeInteger(inheritedEventCount) || inheritedEventCount < 0 || inheritedEventCount > events.length) throw new ScheduleLogError("schedule inheritedEventCount must be within the supplied event log");
|
|
313
|
-
const initial = Object.freeze({
|
|
314
|
-
active: Object.freeze([]),
|
|
315
|
-
seenIds: Object.freeze([])
|
|
316
|
-
});
|
|
317
|
-
const changes = function* () {
|
|
318
|
-
for (const event of events.slice(inheritedEventCount)) if (event.type === "schedule/change") yield decodeScheduleChange(event.data);
|
|
319
|
-
};
|
|
320
|
-
return applyScheduleChanges(initial, changes());
|
|
321
|
-
}
|
|
322
|
-
//#endregion
|
|
323
|
-
//#region lib/types/invariant.js
|
|
324
|
-
/**
|
|
325
|
-
* Package-owned strict Schedule stream invariant.
|
|
326
|
-
* @module @deepseek-ai/dsh-schedule/invariant
|
|
327
|
-
*/
|
|
328
|
-
const PACKAGE_NAME = "@deepseek-ai/dsh-schedule";
|
|
329
|
-
/** Cordis invariant-companion plugin name. */
|
|
330
|
-
const name = "schedule-invariant";
|
|
331
|
-
/** Service required before reserving this package's invariant ownership. */
|
|
332
|
-
const inject = ["invariants"];
|
|
333
|
-
/** Validate a complete exact-session stream under its fork suffix policy. */
|
|
334
|
-
function validate(events, fail) {
|
|
335
|
-
try {
|
|
336
|
-
foldScheduleEvents(events);
|
|
337
|
-
} catch (error) {
|
|
338
|
-
/* v8 ignore next -- foldScheduleEvents normalizes every rejected stream to ScheduleLogError. */
|
|
339
|
-
if (!(error instanceof ScheduleLogError)) throw error;
|
|
340
|
-
fail(error.message);
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
/**
|
|
344
|
-
* Install replay and pre-append validation for the owned event stream.
|
|
345
|
-
*
|
|
346
|
-
* The durable task table is not asserted here: `scheduleDomain` validates every stored
|
|
347
|
-
* record through its table schema when the domain opens, and its only writer stores each
|
|
348
|
-
* task under `task.record.id`, so a check of the write payload would observe the same value
|
|
349
|
-
* the writer had just built.
|
|
350
|
-
*/
|
|
351
|
-
const install = Object.assign((ctx, fail) => {
|
|
352
|
-
for (const session of ctx.sessions.list()) validate(session.ownEvents(), fail);
|
|
353
|
-
ctx.on("session/created", (session) => {
|
|
354
|
-
validate(session.ownEvents(), fail);
|
|
355
|
-
}, { global: true });
|
|
356
|
-
ctx.on("internal/dispatch", (_mode, eventName, args) => {
|
|
357
|
-
if (eventName !== "session/event") return;
|
|
358
|
-
const [session, event] = args;
|
|
359
|
-
if (event.type !== "schedule/change") return;
|
|
360
|
-
validate([...session.ownEvents(), event], fail);
|
|
361
|
-
}, { global: true });
|
|
362
|
-
}, { inject: ["sessions"] });
|
|
363
|
-
/**
|
|
364
|
-
* Register the package-owned invariant companion.
|
|
365
|
-
* @param ctx - Cordis context carrying the invariant registry.
|
|
366
|
-
* @returns Exact registration disposer after child setup succeeds.
|
|
367
|
-
*/
|
|
368
|
-
const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
|
|
369
|
-
//#endregion
|
|
370
|
-
export { apply, inject, name };
|
package/lib/types/invariant.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Package-owned strict Schedule stream invariant.
|
|
3
|
-
* @module @deepseek-ai/dsh-schedule/invariant
|
|
4
|
-
*/
|
|
5
|
-
import type { Context } from '@deepseek-ai/cordis';
|
|
6
|
-
/** Cordis invariant-companion plugin name. */
|
|
7
|
-
export declare const name = "schedule-invariant";
|
|
8
|
-
/** Service required before reserving this package's invariant ownership. */
|
|
9
|
-
export declare const inject: string[];
|
|
10
|
-
/**
|
|
11
|
-
* Register the package-owned invariant companion.
|
|
12
|
-
* @param ctx - Cordis context carrying the invariant registry.
|
|
13
|
-
* @returns Exact registration disposer after child setup succeeds.
|
|
14
|
-
*/
|
|
15
|
-
export declare const apply: (ctx: Context) => Promise<() => void>;
|
|
16
|
-
//# sourceMappingURL=invariant.d.ts.map
|
package/lib/types/invariant.js
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Package-owned strict Schedule stream invariant.
|
|
3
|
-
* @module @deepseek-ai/dsh-schedule/invariant
|
|
4
|
-
*/
|
|
5
|
-
import { foldScheduleEvents, ScheduleLogError } from "./domain.js";
|
|
6
|
-
const PACKAGE_NAME = '@deepseek-ai/dsh-schedule';
|
|
7
|
-
/** Cordis invariant-companion plugin name. */
|
|
8
|
-
export const name = 'schedule-invariant';
|
|
9
|
-
/** Service required before reserving this package's invariant ownership. */
|
|
10
|
-
export const inject = ['invariants'];
|
|
11
|
-
/** Validate a complete exact-session stream under its fork suffix policy. */
|
|
12
|
-
function validate(events, fail) {
|
|
13
|
-
try {
|
|
14
|
-
foldScheduleEvents(events);
|
|
15
|
-
}
|
|
16
|
-
catch (error) {
|
|
17
|
-
/* v8 ignore next -- foldScheduleEvents normalizes every rejected stream to ScheduleLogError. */
|
|
18
|
-
if (!(error instanceof ScheduleLogError))
|
|
19
|
-
throw error;
|
|
20
|
-
fail(error.message);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
/* jscpd:ignore-start -- package companions share replay and dispatch plumbing */
|
|
24
|
-
/**
|
|
25
|
-
* Install replay and pre-append validation for the owned event stream.
|
|
26
|
-
*
|
|
27
|
-
* The durable task table is not asserted here: `scheduleDomain` validates every stored
|
|
28
|
-
* record through its table schema when the domain opens, and its only writer stores each
|
|
29
|
-
* task under `task.record.id`, so a check of the write payload would observe the same value
|
|
30
|
-
* the writer had just built.
|
|
31
|
-
*/
|
|
32
|
-
const install = Object.assign((ctx, fail) => {
|
|
33
|
-
for (const session of ctx.sessions.list()) {
|
|
34
|
-
// oxlint-disable-next-line typescript/no-deprecated -- Existing Session history read; migration deferred.
|
|
35
|
-
validate(session.ownEvents(), fail);
|
|
36
|
-
}
|
|
37
|
-
ctx.on('session/created', (session) => {
|
|
38
|
-
// oxlint-disable-next-line typescript/no-deprecated -- Existing Session history read; migration deferred.
|
|
39
|
-
validate(session.ownEvents(), fail);
|
|
40
|
-
}, { global: true });
|
|
41
|
-
ctx.on('internal/dispatch', (_mode, eventName, args) => {
|
|
42
|
-
if (eventName !== 'session/event')
|
|
43
|
-
return;
|
|
44
|
-
const [session, event] = args;
|
|
45
|
-
if (event.type !== 'schedule/change')
|
|
46
|
-
return;
|
|
47
|
-
// oxlint-disable-next-line typescript/no-deprecated -- Existing Session history read; migration deferred.
|
|
48
|
-
validate([...session.ownEvents(), event], fail);
|
|
49
|
-
}, { global: true });
|
|
50
|
-
}, { inject: ['sessions'] });
|
|
51
|
-
/* jscpd:ignore-end */
|
|
52
|
-
/**
|
|
53
|
-
* Register the package-owned invariant companion.
|
|
54
|
-
* @param ctx - Cordis context carrying the invariant registry.
|
|
55
|
-
* @returns Exact registration disposer after child setup succeeds.
|
|
56
|
-
*/
|
|
57
|
-
export const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
|
|
58
|
-
//# sourceMappingURL=invariant.js.map
|
package/lib/types/tools.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent-scoped consumers of the shared Host Schedule management service.
|
|
3
|
-
* @module @deepseek-ai/dsh-schedule
|
|
4
|
-
*/
|
|
5
|
-
import type { Context } from '@deepseek-ai/cordis';
|
|
6
|
-
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
7
|
-
/**
|
|
8
|
-
* Register all four Schedule tools in one exact agent scope.
|
|
9
|
-
* @param rootCtx - Host context owning the shared Schedule service.
|
|
10
|
-
* @param toolCtx - Exact agent-scoped context receiving the definitions.
|
|
11
|
-
* @param agent - Exact live owner whose session the tools mutate.
|
|
12
|
-
* @returns Idempotent aggregate disposer for the four registrations.
|
|
13
|
-
*/
|
|
14
|
-
export declare function registerScheduleTools(rootCtx: Context, toolCtx: Context, agent: Agent): () => void;
|
|
15
|
-
//# sourceMappingURL=tools.d.ts.map
|