@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/typert.host.js
CHANGED
|
@@ -346,6 +346,9 @@ const _deepseek_ai_dsh_schedule_schedule_update_result$schema = () => (_deepseek
|
|
|
346
346
|
}), z.object({
|
|
347
347
|
'code': z.literal("frequency_too_high").readonly(),
|
|
348
348
|
'message': z.string().readonly(),
|
|
349
|
+
}), z.object({
|
|
350
|
+
'code': z.literal("subagent_session").readonly(),
|
|
351
|
+
'message': z.string().readonly(),
|
|
349
352
|
}), z.object({
|
|
350
353
|
'code': z.literal("internal_error").readonly(),
|
|
351
354
|
'message': z.string().readonly(),
|
|
@@ -370,7 +373,7 @@ export const TYPERT = {
|
|
|
370
373
|
typeSymbol: '@deepseek-ai/dsh-schedule#schedule/catalog:result',
|
|
371
374
|
create: _deepseek_ai_dsh_schedule_schedule_catalog_result$schema,
|
|
372
375
|
},
|
|
373
|
-
sourceLocation: {"file":"packages/schedule/schedule/src/index.ts","line":
|
|
376
|
+
sourceLocation: {"file":"packages/schedule/schedule/src/index.ts","line":285,"column":9},
|
|
374
377
|
},
|
|
375
378
|
{
|
|
376
379
|
id: '@deepseek-ai/dsh-schedule#schedule/delete',
|
|
@@ -396,7 +399,7 @@ export const TYPERT = {
|
|
|
396
399
|
typeSymbol: '@deepseek-ai/dsh-schedule/client#ScheduleDeleteResult',
|
|
397
400
|
create: _deepseek_ai_dsh_schedule_schedule_delete_result$schema,
|
|
398
401
|
},
|
|
399
|
-
sourceLocation: {"file":"packages/schedule/schedule/src/index.ts","line":
|
|
402
|
+
sourceLocation: {"file":"packages/schedule/schedule/src/index.ts","line":326,"column":9},
|
|
400
403
|
},
|
|
401
404
|
{
|
|
402
405
|
id: '@deepseek-ai/dsh-schedule#schedule/history',
|
|
@@ -421,7 +424,7 @@ export const TYPERT = {
|
|
|
421
424
|
typeSymbol: '@deepseek-ai/dsh-schedule/client#ScheduleDeliveryHistoryResult',
|
|
422
425
|
create: _deepseek_ai_dsh_schedule_schedule_history_result$schema,
|
|
423
426
|
},
|
|
424
|
-
sourceLocation: {"file":"packages/schedule/schedule/src/index.ts","line":
|
|
427
|
+
sourceLocation: {"file":"packages/schedule/schedule/src/index.ts","line":303,"column":9},
|
|
425
428
|
},
|
|
426
429
|
{
|
|
427
430
|
id: '@deepseek-ai/dsh-schedule#schedule/list',
|
|
@@ -446,7 +449,7 @@ export const TYPERT = {
|
|
|
446
449
|
typeSymbol: '@deepseek-ai/dsh-schedule#schedule/list:result',
|
|
447
450
|
create: _deepseek_ai_dsh_schedule_schedule_list_result$schema,
|
|
448
451
|
},
|
|
449
|
-
sourceLocation: {"file":"packages/schedule/schedule/src/index.ts","line":
|
|
452
|
+
sourceLocation: {"file":"packages/schedule/schedule/src/index.ts","line":271,"column":9},
|
|
450
453
|
},
|
|
451
454
|
{
|
|
452
455
|
id: '@deepseek-ai/dsh-schedule#schedule/update',
|
|
@@ -472,7 +475,7 @@ export const TYPERT = {
|
|
|
472
475
|
typeSymbol: '@deepseek-ai/dsh-schedule/client#ScheduleUpdateResult',
|
|
473
476
|
create: _deepseek_ai_dsh_schedule_schedule_update_result$schema,
|
|
474
477
|
},
|
|
475
|
-
sourceLocation: {"file":"packages/schedule/schedule/src/index.ts","line":
|
|
478
|
+
sourceLocation: {"file":"packages/schedule/schedule/src/index.ts","line":356,"column":9},
|
|
476
479
|
},
|
|
477
480
|
],
|
|
478
481
|
model: {
|
|
@@ -495,7 +498,7 @@ export const TYPERT = {
|
|
|
495
498
|
"name": "create",
|
|
496
499
|
"signature": "async create(sessionId: SessionId, request: ScheduleCreateRequest, signal?: AbortSignal): Promise<ScheduleRecord>",
|
|
497
500
|
"summary": "Create a reminder bound to the caller-selected Session without activating it.",
|
|
498
|
-
"jsDoc": "/**\n * Create a reminder bound to the caller-selected Session without activating it.\n *\n * The request must supply a title; a missing, blank-after-trim, or over-long\n * title rejects with `invalid_prompt` instead of deriving one from the prompt.\n * The record is built from the clock reading taken before the request joins the\n * serialized queue, so a create that waits behind a longer operation keeps its\n * request-time anchor and may already be due when the queue reaches it.\n * @param sessionId - Original Session receiving the reminder.\n * @param request - Validated tool selector, required title, and reminder content.\n * @param signal - Optional cancellation checked before persistence begins, including after FIFO waits.\n * @returns The durably stored schedule. Cancellation does not roll back an in-flight write.\n */"
|
|
501
|
+
"jsDoc": "/**\n * Create a reminder bound to the caller-selected Session without activating it.\n *\n * The request must supply a title; a missing, blank-after-trim, or over-long\n * title rejects with `invalid_prompt` instead of deriving one from the prompt.\n * A Session a delegated child owns rejects with `subagent_session`, because delivery\n * can never reach it: the child is one whose delegation depth is above zero.\n * The record is built from the clock reading taken before the request joins the\n * serialized queue, so a create that waits behind a longer operation keeps its\n * request-time anchor and may already be due when the queue reaches it.\n * @param sessionId - Original Session receiving the reminder.\n * @param request - Validated tool selector, required title, and reminder content.\n * @param signal - Optional cancellation checked before persistence begins, including after FIFO waits.\n * @returns The durably stored schedule. Cancellation does not roll back an in-flight write.\n */"
|
|
499
502
|
},
|
|
500
503
|
{
|
|
501
504
|
"kind": "method",
|
|
@@ -523,14 +526,14 @@ export const TYPERT = {
|
|
|
523
526
|
"name": "delete",
|
|
524
527
|
"signature": "@Remote('delete') async delete(request: ScheduleDeleteRequest, signal?: AbortSignal): Promise<ScheduleDeleteResult>",
|
|
525
528
|
"summary": "Delete one task belonging to the selected Session, leaving queued messages intact.",
|
|
526
|
-
"jsDoc": "/**\n * Delete one task belonging to the selected Session, leaving queued messages intact.\n *\n * The row is removed: the task no longer schedules, leaves `list` and `catalog`, and its\n * saved delivery records go with it.\n * @param request - Session and exact task identity.\n * @param signal - Optional cancellation checked before persistence begins, including after FIFO waits.\n * @returns Whether that Session owned a deleted task. Cancellation does not roll back an in-flight write.\n */"
|
|
529
|
+
"jsDoc": "/**\n * Delete one task belonging to the selected Session, leaving queued messages intact.\n *\n * The row is removed: the task no longer schedules, leaves `list` and `catalog`, and its\n * saved delivery records go with it. A task bound to a Session a delegated child owns\n * stays deletable even though creation and timing edits refuse that binding, so a task\n * stored before that rule existed remains removable.\n * @param request - Session and exact task identity.\n * @param signal - Optional cancellation checked before persistence begins, including after FIFO waits.\n * @returns Whether that Session owned a deleted task. Cancellation does not roll back an in-flight write.\n */"
|
|
527
530
|
},
|
|
528
531
|
{
|
|
529
532
|
"kind": "method",
|
|
530
533
|
"name": "update",
|
|
531
534
|
"signature": "@Remote('update') async update(request: ScheduleUpdateRequest, signal?: AbortSignal): Promise<ScheduleUpdateResult>",
|
|
532
535
|
"summary": "Update the name, instruction, and timing of an active task within the original Session binding without activating the Session or changing saved deliveries.",
|
|
533
|
-
"jsDoc": "/**\n * Update the name, instruction, and timing of an active task within the original Session\n * binding without activating the Session or changing saved deliveries.\n *\n * Each supplied field replaces its stored value; an omitted field keeps it. A name or\n * instruction change alone does not reset the committed target.\n * @param request - Task binding, complete observed record, and any combination of timing, name, and instruction.\n * @param signal - Cancellation checked after domain readiness and FIFO waits, before persistence begins.\n * @returns The committed record, unchanged record for a no-op, or a non-mutating input/lookup/conflict result.\n * Storage and lifecycle failures reject; cancellation after a write starts does not roll it back.\n */"
|
|
536
|
+
"jsDoc": "/**\n * Update the name, instruction, and timing of an active task within the original Session\n * binding without activating the Session or changing saved deliveries.\n *\n * Each supplied field replaces its stored value; an omitted field keeps it. A name or\n * instruction change alone does not reset the committed target. A Session a delegated\n * child owns returns the non-mutating `subagent_session` result, so an edit cannot\n * re-arm a task bound to a Session delivery can never reach, and the Web editor can\n * explain the refusal through the ordinary result it already renders.\n * @param request - Task binding, complete observed record, and any combination of timing, name, and instruction.\n * @param signal - Cancellation checked after domain readiness and FIFO waits, before persistence begins.\n * @returns The committed record, unchanged record for a no-op, or a non-mutating input/lookup/conflict/refusal result.\n * Storage and lifecycle failures reject; cancellation after a write starts does not roll it back.\n */"
|
|
534
537
|
}
|
|
535
538
|
],
|
|
536
539
|
"types": [
|
|
@@ -668,7 +671,7 @@ export const TYPERT = {
|
|
|
668
671
|
},
|
|
669
672
|
{
|
|
670
673
|
"name": "ScheduleToolError",
|
|
671
|
-
"declaration": "export type ScheduleToolError = InvalidPromptError | InvalidSelectorError | InvalidRuleError | InvalidTimeZoneError | NotFutureError | TimeOutOfRangeError | FrequencyTooHighError | InternalScheduleError;"
|
|
674
|
+
"declaration": "export type ScheduleToolError = InvalidPromptError | InvalidSelectorError | InvalidRuleError | InvalidTimeZoneError | NotFutureError | TimeOutOfRangeError | FrequencyTooHighError | SubagentSessionError | InternalScheduleError;"
|
|
672
675
|
},
|
|
673
676
|
{
|
|
674
677
|
"name": "ScheduleUpdateContent",
|
|
@@ -690,6 +693,10 @@ export const TYPERT = {
|
|
|
690
693
|
"name": "SessionId",
|
|
691
694
|
"declaration": "export type SessionId = Branded<'SessionId'>;"
|
|
692
695
|
},
|
|
696
|
+
{
|
|
697
|
+
"name": "SubagentSessionError",
|
|
698
|
+
"declaration": "export interface SubagentSessionError {\n readonly code: 'subagent_session';\n readonly message: string;\n}"
|
|
699
|
+
},
|
|
693
700
|
{
|
|
694
701
|
"name": "TimeOutOfRangeError",
|
|
695
702
|
"declaration": "export interface TimeOutOfRangeError {\n readonly code: 'time_out_of_range';\n readonly message: string;\n}"
|
|
@@ -346,6 +346,9 @@ const _deepseek_ai_dsh_schedule_schedule_update_result$schema = () => (_deepseek
|
|
|
346
346
|
}), z.object({
|
|
347
347
|
'code': z.literal("frequency_too_high").readonly(),
|
|
348
348
|
'message': z.string().readonly(),
|
|
349
|
+
}), z.object({
|
|
350
|
+
'code': z.literal("subagent_session").readonly(),
|
|
351
|
+
'message': z.string().readonly(),
|
|
349
352
|
}), z.object({
|
|
350
353
|
'code': z.literal("internal_error").readonly(),
|
|
351
354
|
'message': z.string().readonly(),
|
|
@@ -367,7 +370,7 @@ export const TYPERT_REMOTE = {
|
|
|
367
370
|
typeSymbol: '@deepseek-ai/dsh-schedule#schedule/catalog:result',
|
|
368
371
|
create: _deepseek_ai_dsh_schedule_schedule_catalog_result$schema,
|
|
369
372
|
},
|
|
370
|
-
sourceLocation: {"file":"packages/schedule/schedule/src/index.ts","line":
|
|
373
|
+
sourceLocation: {"file":"packages/schedule/schedule/src/index.ts","line":285,"column":9},
|
|
371
374
|
},
|
|
372
375
|
{
|
|
373
376
|
id: '@deepseek-ai/dsh-schedule#schedule/delete',
|
|
@@ -393,7 +396,7 @@ export const TYPERT_REMOTE = {
|
|
|
393
396
|
typeSymbol: '@deepseek-ai/dsh-schedule/client#ScheduleDeleteResult',
|
|
394
397
|
create: _deepseek_ai_dsh_schedule_schedule_delete_result$schema,
|
|
395
398
|
},
|
|
396
|
-
sourceLocation: {"file":"packages/schedule/schedule/src/index.ts","line":
|
|
399
|
+
sourceLocation: {"file":"packages/schedule/schedule/src/index.ts","line":326,"column":9},
|
|
397
400
|
},
|
|
398
401
|
{
|
|
399
402
|
id: '@deepseek-ai/dsh-schedule#schedule/history',
|
|
@@ -418,7 +421,7 @@ export const TYPERT_REMOTE = {
|
|
|
418
421
|
typeSymbol: '@deepseek-ai/dsh-schedule/client#ScheduleDeliveryHistoryResult',
|
|
419
422
|
create: _deepseek_ai_dsh_schedule_schedule_history_result$schema,
|
|
420
423
|
},
|
|
421
|
-
sourceLocation: {"file":"packages/schedule/schedule/src/index.ts","line":
|
|
424
|
+
sourceLocation: {"file":"packages/schedule/schedule/src/index.ts","line":303,"column":9},
|
|
422
425
|
},
|
|
423
426
|
{
|
|
424
427
|
id: '@deepseek-ai/dsh-schedule#schedule/list',
|
|
@@ -443,7 +446,7 @@ export const TYPERT_REMOTE = {
|
|
|
443
446
|
typeSymbol: '@deepseek-ai/dsh-schedule#schedule/list:result',
|
|
444
447
|
create: _deepseek_ai_dsh_schedule_schedule_list_result$schema,
|
|
445
448
|
},
|
|
446
|
-
sourceLocation: {"file":"packages/schedule/schedule/src/index.ts","line":
|
|
449
|
+
sourceLocation: {"file":"packages/schedule/schedule/src/index.ts","line":271,"column":9},
|
|
447
450
|
},
|
|
448
451
|
{
|
|
449
452
|
id: '@deepseek-ai/dsh-schedule#schedule/update',
|
|
@@ -469,7 +472,7 @@ export const TYPERT_REMOTE = {
|
|
|
469
472
|
typeSymbol: '@deepseek-ai/dsh-schedule/client#ScheduleUpdateResult',
|
|
470
473
|
create: _deepseek_ai_dsh_schedule_schedule_update_result$schema,
|
|
471
474
|
},
|
|
472
|
-
sourceLocation: {"file":"packages/schedule/schedule/src/index.ts","line":
|
|
475
|
+
sourceLocation: {"file":"packages/schedule/schedule/src/index.ts","line":356,"column":9},
|
|
473
476
|
},
|
|
474
477
|
],
|
|
475
478
|
}
|
package/lib/types/domain.d.ts
CHANGED
|
@@ -31,17 +31,17 @@ export declare class ScheduleLogError extends Error {
|
|
|
31
31
|
*/
|
|
32
32
|
constructor(message: string);
|
|
33
33
|
}
|
|
34
|
-
/** Error from a model-supplied Schedule rule that cannot become a record. */
|
|
34
|
+
/** Error from a model-supplied Schedule rule or target Session that cannot become a record. */
|
|
35
35
|
export declare class ScheduleInputError extends Error {
|
|
36
36
|
/** Stable public Schedule input code. */
|
|
37
|
-
readonly code: 'invalid_prompt' | 'invalid_selector' | 'invalid_rule' | 'invalid_time_zone' | 'not_future' | 'time_out_of_range' | 'frequency_too_high';
|
|
37
|
+
readonly code: 'invalid_prompt' | 'invalid_selector' | 'invalid_rule' | 'invalid_time_zone' | 'not_future' | 'time_out_of_range' | 'frequency_too_high' | 'subagent_session';
|
|
38
38
|
/**
|
|
39
39
|
* Construct a stable input failure.
|
|
40
40
|
* @param code - Public Schedule error discriminator.
|
|
41
41
|
* @param message - Stable public diagnostic.
|
|
42
42
|
* @param options - Optional contained implementation cause.
|
|
43
43
|
*/
|
|
44
|
-
constructor(code: 'invalid_prompt' | 'invalid_selector' | 'invalid_rule' | 'invalid_time_zone' | 'not_future' | 'time_out_of_range' | 'frequency_too_high', message: string, options?: ErrorOptions);
|
|
44
|
+
constructor(code: 'invalid_prompt' | 'invalid_selector' | 'invalid_rule' | 'invalid_time_zone' | 'not_future' | 'time_out_of_range' | 'frequency_too_high' | 'subagent_session', message: string, options?: ErrorOptions);
|
|
45
45
|
}
|
|
46
46
|
/** Pure replay result, retaining active create order and every used id. */
|
|
47
47
|
export interface FoldedSchedules {
|
package/lib/types/domain.js
CHANGED
|
@@ -44,7 +44,7 @@ export class ScheduleLogError extends Error {
|
|
|
44
44
|
this.name = 'ScheduleLogError';
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
-
/** Error from a model-supplied Schedule rule that cannot become a record. */
|
|
47
|
+
/** Error from a model-supplied Schedule rule or target Session that cannot become a record. */
|
|
48
48
|
export class ScheduleInputError extends Error {
|
|
49
49
|
/** Stable public Schedule input code. */
|
|
50
50
|
code;
|
package/lib/types/index.d.ts
CHANGED
|
@@ -4,11 +4,10 @@ import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
|
|
|
4
4
|
import type { SessionId } from '@deepseek-ai/dsh-session';
|
|
5
5
|
import type { ScheduleCatalogEntry, ScheduleCreateRequest, ScheduleDeleteRequest, ScheduleDeleteResult, ScheduleDeliveryHistoryRequest, ScheduleDeliveryHistoryResult, ScheduleListRequest, ScheduleRecord, ScheduleUpdateRequest, ScheduleUpdateResult } from './types.ts';
|
|
6
6
|
export type * from './types.ts';
|
|
7
|
-
export { registerScheduleTools } from './tools.ts';
|
|
8
7
|
export { scheduleDomain } from './storage.ts';
|
|
9
8
|
export type { ScheduleTask } from './storage.ts';
|
|
10
9
|
export type { RecurringOccurrence } from './domain.ts';
|
|
11
|
-
export { SCHEDULE_CHANGE_VERSION, MIN_EVERY_INTERVAL_SECONDS, MAX_TITLE_LENGTH, ScheduleId, ScheduleInputError, ScheduleLogError, canonicalizeCronExpression, createAfterScheduleRecord, createAtScheduleRecord, createEveryScheduleRecord, createDailyScheduleRecord, createWeeklyScheduleRecord, createCronScheduleRecord, decodeScheduleChange, decodeScheduleRecord, foldScheduleEvents, isRecurringScheduleRecord, normalizeWeekdays, parseCronInput, parseWeeklyInput, renderReminderFraming, renderRecurringReminderBatchFraming, resolveEveryOccurrence, resolveDailyOccurrence, resolveWeeklyOccurrence, resolveCronOccurrence, resolveRecurringOccurrence, scheduleTitle, scheduleView, weeklyTime, } from './domain.ts';
|
|
10
|
+
export { SCHEDULE_CHANGE_VERSION, MIN_EVERY_INTERVAL_SECONDS, MAX_TITLE_LENGTH, REQUIRED_TITLE_MESSAGE, ScheduleId, ScheduleInputError, ScheduleLogError, canonicalizeCronExpression, createAfterScheduleRecord, createAtScheduleRecord, createEveryScheduleRecord, createDailyScheduleRecord, createWeeklyScheduleRecord, createCronScheduleRecord, decodeScheduleChange, decodeScheduleRecord, foldScheduleEvents, isRecurringScheduleRecord, normalizeWeekdays, parseCronInput, parseWeeklyInput, renderReminderFraming, renderRecurringReminderBatchFraming, resolveEveryOccurrence, resolveDailyOccurrence, resolveWeeklyOccurrence, resolveCronOccurrence, resolveRecurringOccurrence, scheduleTitle, scheduleView, weeklyTime, } from './domain.ts';
|
|
12
11
|
declare module '@deepseek-ai/cordis' {
|
|
13
12
|
interface Context {
|
|
14
13
|
/** Durable Host-wide reminder management. */
|
|
@@ -57,6 +56,8 @@ export declare class ScheduleService extends TypertRemoteService {
|
|
|
57
56
|
*
|
|
58
57
|
* The request must supply a title; a missing, blank-after-trim, or over-long
|
|
59
58
|
* title rejects with `invalid_prompt` instead of deriving one from the prompt.
|
|
59
|
+
* A Session a delegated child owns rejects with `subagent_session`, because delivery
|
|
60
|
+
* can never reach it: the child is one whose delegation depth is above zero.
|
|
60
61
|
* The record is built from the clock reading taken before the request joins the
|
|
61
62
|
* serialized queue, so a create that waits behind a longer operation keeps its
|
|
62
63
|
* request-time anchor and may already be due when the queue reaches it.
|
|
@@ -91,7 +92,9 @@ export declare class ScheduleService extends TypertRemoteService {
|
|
|
91
92
|
* Delete one task belonging to the selected Session, leaving queued messages intact.
|
|
92
93
|
*
|
|
93
94
|
* The row is removed: the task no longer schedules, leaves `list` and `catalog`, and its
|
|
94
|
-
* saved delivery records go with it.
|
|
95
|
+
* saved delivery records go with it. A task bound to a Session a delegated child owns
|
|
96
|
+
* stays deletable even though creation and timing edits refuse that binding, so a task
|
|
97
|
+
* stored before that rule existed remains removable.
|
|
95
98
|
* @param request - Session and exact task identity.
|
|
96
99
|
* @param signal - Optional cancellation checked before persistence begins, including after FIFO waits.
|
|
97
100
|
* @returns Whether that Session owned a deleted task. Cancellation does not roll back an in-flight write.
|
|
@@ -102,10 +105,13 @@ export declare class ScheduleService extends TypertRemoteService {
|
|
|
102
105
|
* binding without activating the Session or changing saved deliveries.
|
|
103
106
|
*
|
|
104
107
|
* Each supplied field replaces its stored value; an omitted field keeps it. A name or
|
|
105
|
-
* instruction change alone does not reset the committed target.
|
|
108
|
+
* instruction change alone does not reset the committed target. A Session a delegated
|
|
109
|
+
* child owns returns the non-mutating `subagent_session` result, so an edit cannot
|
|
110
|
+
* re-arm a task bound to a Session delivery can never reach, and the Web editor can
|
|
111
|
+
* explain the refusal through the ordinary result it already renders.
|
|
106
112
|
* @param request - Task binding, complete observed record, and any combination of timing, name, and instruction.
|
|
107
113
|
* @param signal - Cancellation checked after domain readiness and FIFO waits, before persistence begins.
|
|
108
|
-
* @returns The committed record, unchanged record for a no-op, or a non-mutating input/lookup/conflict result.
|
|
114
|
+
* @returns The committed record, unchanged record for a no-op, or a non-mutating input/lookup/conflict/refusal result.
|
|
109
115
|
* Storage and lifecycle failures reject; cancellation after a write starts does not roll it back.
|
|
110
116
|
*/
|
|
111
117
|
update(request: ScheduleUpdateRequest, signal?: AbortSignal): Promise<ScheduleUpdateResult>;
|
|
@@ -117,6 +123,19 @@ export declare class ScheduleService extends TypertRemoteService {
|
|
|
117
123
|
*/
|
|
118
124
|
private emitChanged;
|
|
119
125
|
private getDomain;
|
|
126
|
+
/**
|
|
127
|
+
* Refuse a Session no delivery can reach because a delegated child owns it.
|
|
128
|
+
*
|
|
129
|
+
* Delivery resolves the bound Session through `ctx.sessionController.resolveAgent`,
|
|
130
|
+
* which rejects the live Agent of a delegated child; a stored task for such a Session
|
|
131
|
+
* would stay permanently overdue and retry on every drive. Both operations that can
|
|
132
|
+
* arm a delivery read that same fact here instead of restating it: a delegated child
|
|
133
|
+
* is one whose {@link delegationDepthOf} is above zero, the accounting the delegation
|
|
134
|
+
* cap itself enforces, which survives a cold resume through the persisted header.
|
|
135
|
+
* @param sessionId - Session the task would be bound to.
|
|
136
|
+
* @returns The stable refusal for a delegated child's Session, or undefined when the Session is eligible.
|
|
137
|
+
*/
|
|
138
|
+
private reminderTargetRefusal;
|
|
120
139
|
/**
|
|
121
140
|
* Remove every active task stored for one Session, inside the queue the tools
|
|
122
141
|
* use.
|
package/lib/types/index.js
CHANGED
|
@@ -37,15 +37,14 @@ import { randomUUID } from 'node:crypto';
|
|
|
37
37
|
import z from '@deepseek-ai/schemastery';
|
|
38
38
|
import { Service } from '@deepseek-ai/cordis';
|
|
39
39
|
import { TypertRemoteService, Remote } from '@deepseek-ai/dsh-typert-protocol';
|
|
40
|
+
import { delegationDepthOf } from '@deepseek-ai/dsh-subagent';
|
|
40
41
|
import { ScheduleRuntime } from "./runtime.js";
|
|
41
|
-
import { registerScheduleTools } from "./tools.js";
|
|
42
42
|
import { scheduleDomain } from "./storage.js";
|
|
43
43
|
import { deliveryHistoryPage } from "./delivery-history.js";
|
|
44
44
|
import { resolveScheduleUpdate } from "./update.js";
|
|
45
45
|
import { foldScheduleEvents, ScheduleInputError, ScheduleLogError, ScheduleId, createAfterScheduleRecord, createAtScheduleRecord, createEveryScheduleRecord, createDailyScheduleRecord, createWeeklyScheduleRecord, createCronScheduleRecord, scheduleTitle, } from "./domain.js";
|
|
46
|
-
export { registerScheduleTools } from "./tools.js";
|
|
47
46
|
export { scheduleDomain } from "./storage.js";
|
|
48
|
-
export { SCHEDULE_CHANGE_VERSION, MIN_EVERY_INTERVAL_SECONDS, MAX_TITLE_LENGTH, ScheduleId, ScheduleInputError, ScheduleLogError, canonicalizeCronExpression, createAfterScheduleRecord, createAtScheduleRecord, createEveryScheduleRecord, createDailyScheduleRecord, createWeeklyScheduleRecord, createCronScheduleRecord, decodeScheduleChange, decodeScheduleRecord, foldScheduleEvents, isRecurringScheduleRecord, normalizeWeekdays, parseCronInput, parseWeeklyInput, renderReminderFraming, renderRecurringReminderBatchFraming, resolveEveryOccurrence, resolveDailyOccurrence, resolveWeeklyOccurrence, resolveCronOccurrence, resolveRecurringOccurrence, scheduleTitle, scheduleView, weeklyTime, } from "./domain.js";
|
|
47
|
+
export { SCHEDULE_CHANGE_VERSION, MIN_EVERY_INTERVAL_SECONDS, MAX_TITLE_LENGTH, REQUIRED_TITLE_MESSAGE, ScheduleId, ScheduleInputError, ScheduleLogError, canonicalizeCronExpression, createAfterScheduleRecord, createAtScheduleRecord, createEveryScheduleRecord, createDailyScheduleRecord, createWeeklyScheduleRecord, createCronScheduleRecord, decodeScheduleChange, decodeScheduleRecord, foldScheduleEvents, isRecurringScheduleRecord, normalizeWeekdays, parseCronInput, parseWeeklyInput, renderReminderFraming, renderRecurringReminderBatchFraming, resolveEveryOccurrence, resolveDailyOccurrence, resolveWeeklyOccurrence, resolveCronOccurrence, resolveRecurringOccurrence, scheduleTitle, scheduleView, weeklyTime, } from "./domain.js";
|
|
49
48
|
/** Retained delivery-history window applied when the deployment states none. */
|
|
50
49
|
const DEFAULT_DELIVERY_HISTORY_DAYS = 30;
|
|
51
50
|
/** Retained delivery-history record cap applied when the deployment states none. */
|
|
@@ -81,7 +80,7 @@ let ScheduleService = (() => {
|
|
|
81
80
|
__esDecorate(this, null, _update_decorators, { kind: "method", name: "update", static: false, private: false, access: { has: obj => "update" in obj, get: obj => obj.update }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
82
81
|
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
83
82
|
}
|
|
84
|
-
static inject = ['agents', 'sessions', '
|
|
83
|
+
static inject = ['agents', 'sessions', 'storageDomain', 'sessionController', 'sessionPersistence'];
|
|
85
84
|
static Config = z.object({
|
|
86
85
|
deliveryHistoryDays: z.number().step(1).min(1).max(3650).default(DEFAULT_DELIVERY_HISTORY_DAYS),
|
|
87
86
|
deliveryHistoryRecords: z.number().step(1).min(1).max(10_000).default(DEFAULT_DELIVERY_HISTORY_RECORDS),
|
|
@@ -142,27 +141,6 @@ let ScheduleService = (() => {
|
|
|
142
141
|
this.runtime.requestDrive();
|
|
143
142
|
return cleanup;
|
|
144
143
|
});
|
|
145
|
-
const registered = new WeakSet();
|
|
146
|
-
const attached = new Map();
|
|
147
|
-
const attach = (agent) => {
|
|
148
|
-
if (this.stopping || registered.has(agent) || !ctx.agents.roots().includes(agent))
|
|
149
|
-
return;
|
|
150
|
-
registered.add(agent);
|
|
151
|
-
// The plugin-scope effect is what tears the Agent-scoped registration down when this
|
|
152
|
-
// plugin unloads, so it must also be disposed when the Agent itself is released.
|
|
153
|
-
attached.set(agent, ctx.effect(() => agent.ctx.effect(() => registerScheduleTools(ctx, agent.ctx, agent))));
|
|
154
|
-
};
|
|
155
|
-
ctx.on('agent/created', ({ agent }) => { attach(agent); });
|
|
156
|
-
ctx.on('agent/disposed', ({ agent }) => {
|
|
157
|
-
const detach = attached.get(agent);
|
|
158
|
-
if (detach === undefined)
|
|
159
|
-
return;
|
|
160
|
-
attached.delete(agent);
|
|
161
|
-
// `agent/disposed` declares a void listener, so the disposer promise is not returned;
|
|
162
|
-
// this teardown chain is synchronous, and a failure throws into
|
|
163
|
-
// `AgentRegistry.emitDisposed`, which reports it as a listener throw.
|
|
164
|
-
void detach();
|
|
165
|
-
});
|
|
166
144
|
ctx.on('session/created', (session) => {
|
|
167
145
|
// Historical Schedule events remain readable but do not populate Host tasks.
|
|
168
146
|
// A throwing `session/created` listener rolls the attach back, so an unreadable
|
|
@@ -207,8 +185,6 @@ let ScheduleService = (() => {
|
|
|
207
185
|
activity();
|
|
208
186
|
};
|
|
209
187
|
}, 'schedule.archiveAdmission()');
|
|
210
|
-
for (const agent of ctx.agents.roots())
|
|
211
|
-
attach(agent);
|
|
212
188
|
}
|
|
213
189
|
async [Service.init]() {
|
|
214
190
|
await this.initialized;
|
|
@@ -218,6 +194,8 @@ let ScheduleService = (() => {
|
|
|
218
194
|
*
|
|
219
195
|
* The request must supply a title; a missing, blank-after-trim, or over-long
|
|
220
196
|
* title rejects with `invalid_prompt` instead of deriving one from the prompt.
|
|
197
|
+
* A Session a delegated child owns rejects with `subagent_session`, because delivery
|
|
198
|
+
* can never reach it: the child is one whose delegation depth is above zero.
|
|
221
199
|
* The record is built from the clock reading taken before the request joins the
|
|
222
200
|
* serialized queue, so a create that waits behind a longer operation keeps its
|
|
223
201
|
* request-time anchor and may already be due when the queue reaches it.
|
|
@@ -254,6 +232,9 @@ let ScheduleService = (() => {
|
|
|
254
232
|
else
|
|
255
233
|
throw new ScheduleInputError('invalid_selector', 'Exactly one reminder selector is required.');
|
|
256
234
|
return this.serialize(async () => {
|
|
235
|
+
const refusal = this.reminderTargetRefusal(sessionId);
|
|
236
|
+
if (refusal !== undefined)
|
|
237
|
+
throw new ScheduleInputError('subagent_session', refusal.message);
|
|
257
238
|
const domain = await this.getDomain();
|
|
258
239
|
signal?.throwIfAborted();
|
|
259
240
|
await domain.table('tasks').put(id, {
|
|
@@ -311,7 +292,9 @@ let ScheduleService = (() => {
|
|
|
311
292
|
* Delete one task belonging to the selected Session, leaving queued messages intact.
|
|
312
293
|
*
|
|
313
294
|
* The row is removed: the task no longer schedules, leaves `list` and `catalog`, and its
|
|
314
|
-
* saved delivery records go with it.
|
|
295
|
+
* saved delivery records go with it. A task bound to a Session a delegated child owns
|
|
296
|
+
* stays deletable even though creation and timing edits refuse that binding, so a task
|
|
297
|
+
* stored before that rule existed remains removable.
|
|
315
298
|
* @param request - Session and exact task identity.
|
|
316
299
|
* @param signal - Optional cancellation checked before persistence begins, including after FIFO waits.
|
|
317
300
|
* @returns Whether that Session owned a deleted task. Cancellation does not roll back an in-flight write.
|
|
@@ -335,14 +318,20 @@ let ScheduleService = (() => {
|
|
|
335
318
|
* binding without activating the Session or changing saved deliveries.
|
|
336
319
|
*
|
|
337
320
|
* Each supplied field replaces its stored value; an omitted field keeps it. A name or
|
|
338
|
-
* instruction change alone does not reset the committed target.
|
|
321
|
+
* instruction change alone does not reset the committed target. A Session a delegated
|
|
322
|
+
* child owns returns the non-mutating `subagent_session` result, so an edit cannot
|
|
323
|
+
* re-arm a task bound to a Session delivery can never reach, and the Web editor can
|
|
324
|
+
* explain the refusal through the ordinary result it already renders.
|
|
339
325
|
* @param request - Task binding, complete observed record, and any combination of timing, name, and instruction.
|
|
340
326
|
* @param signal - Cancellation checked after domain readiness and FIFO waits, before persistence begins.
|
|
341
|
-
* @returns The committed record, unchanged record for a no-op, or a non-mutating input/lookup/conflict result.
|
|
327
|
+
* @returns The committed record, unchanged record for a no-op, or a non-mutating input/lookup/conflict/refusal result.
|
|
342
328
|
* Storage and lifecycle failures reject; cancellation after a write starts does not roll it back.
|
|
343
329
|
*/
|
|
344
330
|
async update(request, signal) {
|
|
345
331
|
return this.serialize(async () => {
|
|
332
|
+
const refusal = this.reminderTargetRefusal(request.sessionId);
|
|
333
|
+
if (refusal !== undefined)
|
|
334
|
+
return refusal;
|
|
346
335
|
const tasks = (await this.getDomain()).table('tasks');
|
|
347
336
|
signal?.throwIfAborted();
|
|
348
337
|
const current = tasks.get(request.id);
|
|
@@ -381,6 +370,27 @@ let ScheduleService = (() => {
|
|
|
381
370
|
await this.initialized;
|
|
382
371
|
return this.ready;
|
|
383
372
|
}
|
|
373
|
+
/**
|
|
374
|
+
* Refuse a Session no delivery can reach because a delegated child owns it.
|
|
375
|
+
*
|
|
376
|
+
* Delivery resolves the bound Session through `ctx.sessionController.resolveAgent`,
|
|
377
|
+
* which rejects the live Agent of a delegated child; a stored task for such a Session
|
|
378
|
+
* would stay permanently overdue and retry on every drive. Both operations that can
|
|
379
|
+
* arm a delivery read that same fact here instead of restating it: a delegated child
|
|
380
|
+
* is one whose {@link delegationDepthOf} is above zero, the accounting the delegation
|
|
381
|
+
* cap itself enforces, which survives a cold resume through the persisted header.
|
|
382
|
+
* @param sessionId - Session the task would be bound to.
|
|
383
|
+
* @returns The stable refusal for a delegated child's Session, or undefined when the Session is eligible.
|
|
384
|
+
*/
|
|
385
|
+
reminderTargetRefusal(sessionId) {
|
|
386
|
+
const agent = this.ctx.agents.get(sessionId);
|
|
387
|
+
if (agent === undefined || delegationDepthOf(agent) === 0)
|
|
388
|
+
return undefined;
|
|
389
|
+
return {
|
|
390
|
+
code: 'subagent_session',
|
|
391
|
+
message: 'This Session belongs to subagent routing, which never receives reminder delivery.',
|
|
392
|
+
};
|
|
393
|
+
}
|
|
384
394
|
/**
|
|
385
395
|
* Remove every active task stored for one Session, inside the queue the tools
|
|
386
396
|
* use.
|
package/lib/types/types.d.ts
CHANGED
|
@@ -265,13 +265,18 @@ export interface FrequencyTooHighError {
|
|
|
265
265
|
readonly code: 'frequency_too_high';
|
|
266
266
|
readonly message: string;
|
|
267
267
|
}
|
|
268
|
+
/** Stable error returned when the target Session belongs to subagent routing, which never receives reminder delivery. */
|
|
269
|
+
export interface SubagentSessionError {
|
|
270
|
+
readonly code: 'subagent_session';
|
|
271
|
+
readonly message: string;
|
|
272
|
+
}
|
|
268
273
|
/** Stable fallback that does not disclose an internal exception. */
|
|
269
274
|
export interface InternalScheduleError {
|
|
270
275
|
readonly code: 'internal_error';
|
|
271
276
|
readonly message: string;
|
|
272
277
|
}
|
|
273
278
|
/** Closed v1 Schedule management error union. */
|
|
274
|
-
export type ScheduleToolError = InvalidPromptError | InvalidSelectorError | InvalidRuleError | InvalidTimeZoneError | NotFutureError | TimeOutOfRangeError | FrequencyTooHighError | InternalScheduleError;
|
|
279
|
+
export type ScheduleToolError = InvalidPromptError | InvalidSelectorError | InvalidRuleError | InvalidTimeZoneError | NotFutureError | TimeOutOfRangeError | FrequencyTooHighError | SubagentSessionError | InternalScheduleError;
|
|
275
280
|
/** Canonical `schedule_create` value. */
|
|
276
281
|
export type ScheduleCreateValue = ScheduleView | ScheduleToolError;
|
|
277
282
|
/** Canonical `schedule_list` value. */
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-schedule",
|
|
3
3
|
"description": "Host-wide durable reminders with shared management and original-Session delivery",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.1-alpha.1",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -18,10 +18,6 @@
|
|
|
18
18
|
"types": "./lib/types/index.d.ts",
|
|
19
19
|
"default": "./lib/index.js"
|
|
20
20
|
},
|
|
21
|
-
"./invariant": {
|
|
22
|
-
"types": "./lib/types/invariant.d.ts",
|
|
23
|
-
"default": "./lib/invariant.js"
|
|
24
|
-
},
|
|
25
21
|
"./client": {
|
|
26
22
|
"types": "./lib/types/client.d.ts",
|
|
27
23
|
"default": "./lib/types/client.js"
|
|
@@ -41,7 +37,6 @@
|
|
|
41
37
|
"files": [
|
|
42
38
|
"locale/*.json",
|
|
43
39
|
"lib/index.js",
|
|
44
|
-
"lib/invariant.js",
|
|
45
40
|
"lib/types/**/*.js",
|
|
46
41
|
"lib/types/**/*.d.ts",
|
|
47
42
|
"lib/typert.host.js",
|
|
@@ -51,45 +46,45 @@
|
|
|
51
46
|
],
|
|
52
47
|
"license": "MIT",
|
|
53
48
|
"peerDependencies": {
|
|
54
|
-
"@deepseek-ai/dsh-
|
|
55
|
-
"@deepseek-ai/dsh-
|
|
56
|
-
"@deepseek-ai/dsh-brand": "0.2.
|
|
57
|
-
"@deepseek-ai/dsh-llm": "0.2.
|
|
58
|
-
"@deepseek-ai/dsh-session": "0.2.
|
|
59
|
-
"@deepseek-ai/dsh-
|
|
60
|
-
"@deepseek-ai/dsh-
|
|
61
|
-
"@deepseek-ai/dsh-
|
|
62
|
-
"@deepseek-ai/dsh-
|
|
63
|
-
"@deepseek-ai/dsh-
|
|
64
|
-
"@deepseek-ai/dsh-
|
|
65
|
-
"@deepseek-ai/
|
|
66
|
-
"@deepseek-ai/
|
|
49
|
+
"@deepseek-ai/dsh-agent": "0.2.1-alpha.1",
|
|
50
|
+
"@deepseek-ai/dsh-api-session-controller": "0.2.1-alpha.1",
|
|
51
|
+
"@deepseek-ai/dsh-brand": "0.2.1-alpha.1",
|
|
52
|
+
"@deepseek-ai/dsh-llm": "0.2.1-alpha.1",
|
|
53
|
+
"@deepseek-ai/dsh-session": "0.2.1-alpha.1",
|
|
54
|
+
"@deepseek-ai/dsh-session-persistence": "0.2.1-alpha.1",
|
|
55
|
+
"@deepseek-ai/dsh-session-projection": "0.2.1-alpha.1",
|
|
56
|
+
"@deepseek-ai/dsh-storage-domain": "0.2.1-alpha.1",
|
|
57
|
+
"@deepseek-ai/dsh-subagent": "0.2.1-alpha.1",
|
|
58
|
+
"@deepseek-ai/dsh-tools": "0.2.1-alpha.1",
|
|
59
|
+
"@deepseek-ai/dsh-typert-protocol": "0.2.1-alpha.1",
|
|
60
|
+
"@deepseek-ai/dsh-workspace": "0.2.1-alpha.1",
|
|
61
|
+
"@deepseek-ai/cordis": "~4.0.5-alpha.1"
|
|
67
62
|
},
|
|
68
63
|
"dependencies": {
|
|
69
64
|
"@js-temporal/polyfill": "0.5.1",
|
|
70
65
|
"zod": "^4.4.3",
|
|
71
|
-
"@deepseek-ai/schemastery": "~3.18.
|
|
66
|
+
"@deepseek-ai/schemastery": "~3.18.5-alpha.1"
|
|
72
67
|
},
|
|
73
68
|
"devDependencies": {
|
|
74
|
-
"@deepseek-ai/cordis-plugin-loader": "~1.0.
|
|
75
|
-
"@deepseek-ai/dsh-agent": "0.2.
|
|
76
|
-
"@deepseek-ai/dsh-agent-loop": "0.2.
|
|
77
|
-
"@deepseek-ai/dsh-agent-loop-testkit": "0.2.
|
|
78
|
-
"@deepseek-ai/dsh-api-session-controller": "0.2.
|
|
79
|
-
"@deepseek-ai/dsh-
|
|
80
|
-
"@deepseek-ai/dsh-llm": "0.2.
|
|
81
|
-
"@deepseek-ai/dsh-session": "0.2.
|
|
82
|
-
"@deepseek-ai/dsh-session-persistence": "0.2.
|
|
83
|
-
"@deepseek-ai/dsh-session-persistence-jsonl": "0.2.
|
|
84
|
-
"@deepseek-ai/dsh-session-projection": "0.2.
|
|
85
|
-
"@deepseek-ai/dsh-storage": "0.2.
|
|
86
|
-
"@deepseek-ai/dsh-storage-domain": "0.2.
|
|
87
|
-
"@deepseek-ai/dsh-storage-json": "0.2.
|
|
88
|
-
"@deepseek-ai/dsh-system-prompt": "0.2.
|
|
89
|
-
"@deepseek-ai/dsh-tools": "0.2.
|
|
90
|
-
"@deepseek-ai/dsh-
|
|
91
|
-
"@deepseek-ai/dsh-
|
|
92
|
-
"@deepseek-ai/
|
|
93
|
-
"@deepseek-ai/
|
|
69
|
+
"@deepseek-ai/cordis-plugin-loader": "~1.0.6-alpha.1",
|
|
70
|
+
"@deepseek-ai/dsh-agent": "0.2.1-alpha.1",
|
|
71
|
+
"@deepseek-ai/dsh-agent-loop": "0.2.1-alpha.1",
|
|
72
|
+
"@deepseek-ai/dsh-agent-loop-testkit": "0.2.1-alpha.1",
|
|
73
|
+
"@deepseek-ai/dsh-api-session-controller": "0.2.1-alpha.1",
|
|
74
|
+
"@deepseek-ai/dsh-brand": "0.2.1-alpha.1",
|
|
75
|
+
"@deepseek-ai/dsh-llm": "0.2.1-alpha.1",
|
|
76
|
+
"@deepseek-ai/dsh-session": "0.2.1-alpha.1",
|
|
77
|
+
"@deepseek-ai/dsh-session-persistence": "0.2.1-alpha.1",
|
|
78
|
+
"@deepseek-ai/dsh-session-persistence-jsonl": "0.2.1-alpha.1",
|
|
79
|
+
"@deepseek-ai/dsh-session-projection": "0.2.1-alpha.1",
|
|
80
|
+
"@deepseek-ai/dsh-storage": "0.2.1-alpha.1",
|
|
81
|
+
"@deepseek-ai/dsh-storage-domain": "0.2.1-alpha.1",
|
|
82
|
+
"@deepseek-ai/dsh-storage-json": "0.2.1-alpha.1",
|
|
83
|
+
"@deepseek-ai/dsh-system-prompt": "0.2.1-alpha.1",
|
|
84
|
+
"@deepseek-ai/dsh-tools": "0.2.1-alpha.1",
|
|
85
|
+
"@deepseek-ai/dsh-workspace": "0.2.1-alpha.1",
|
|
86
|
+
"@deepseek-ai/dsh-typert-protocol": "0.2.1-alpha.1",
|
|
87
|
+
"@deepseek-ai/dsh-subagent": "0.2.1-alpha.1",
|
|
88
|
+
"@deepseek-ai/cordis": "~4.0.5-alpha.1"
|
|
94
89
|
}
|
|
95
90
|
}
|