@qihongmu/dsh-plugins-scheduled-task 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,134 @@
1
+ /**
2
+ * The external scheduled-task domain declaration: record schema and the
3
+ * `defineDomain` spec the service opens (mirrors the storage-domain pattern).
4
+ * @module @qihongmu/dsh-plugins-scheduled-task/src/spec
5
+ */
6
+ import { z } from 'zod';
7
+ import { SessionId } from '@deepseek-ai/dsh-session/types';
8
+ import type { ScheduledTaskId } from './types.ts';
9
+ /**
10
+ * Durable shape of one task record. `title`/`prompt` are non-empty after
11
+ * trimming; `rule` carries the schedule and next target; timestamps are ISO-8601.
12
+ */
13
+ export declare const scheduledTaskRecord: z.ZodObject<{
14
+ id: z.ZodPipe<z.ZodString, z.ZodTransform<ScheduledTaskId, string>>;
15
+ title: z.ZodString;
16
+ prompt: z.ZodString;
17
+ rule: z.ZodDiscriminatedUnion<[z.ZodObject<{
18
+ kind: z.ZodLiteral<"after">;
19
+ afterSeconds: z.ZodNumber;
20
+ scheduledAt: z.ZodString;
21
+ }, z.core.$strip>, z.ZodObject<{
22
+ kind: z.ZodLiteral<"at">;
23
+ scheduledAt: z.ZodString;
24
+ }, z.core.$strip>, z.ZodObject<{
25
+ kind: z.ZodLiteral<"every">;
26
+ everySeconds: z.ZodNumber;
27
+ scheduledAt: z.ZodString;
28
+ }, z.core.$strip>, z.ZodObject<{
29
+ kind: z.ZodLiteral<"hourly">;
30
+ minute: z.ZodNumber;
31
+ scheduledAt: z.ZodString;
32
+ }, z.core.$strip>, z.ZodObject<{
33
+ kind: z.ZodLiteral<"daily">;
34
+ time: z.ZodString;
35
+ time_zone: z.ZodString;
36
+ scheduledAt: z.ZodString;
37
+ }, z.core.$strip>, z.ZodObject<{
38
+ kind: z.ZodLiteral<"weekly">;
39
+ weekdays: z.ZodArray<z.ZodNumber>;
40
+ time: z.ZodString;
41
+ time_zone: z.ZodString;
42
+ scheduledAt: z.ZodString;
43
+ }, z.core.$strip>, z.ZodObject<{
44
+ kind: z.ZodLiteral<"monthly">;
45
+ dayOfMonth: z.ZodNumber;
46
+ time: z.ZodString;
47
+ time_zone: z.ZodString;
48
+ scheduledAt: z.ZodString;
49
+ }, z.core.$strip>], "kind">;
50
+ status: z.ZodEnum<{
51
+ active: "active";
52
+ paused: "paused";
53
+ completed: "completed";
54
+ }>;
55
+ sessionId: z.ZodPipe<z.ZodString, z.ZodTransform<SessionId, string>>;
56
+ createdAt: z.ZodString;
57
+ workspaceId: z.ZodOptional<z.ZodString>;
58
+ cwd: z.ZodOptional<z.ZodString>;
59
+ model: z.ZodOptional<z.ZodObject<{
60
+ provider: z.ZodString;
61
+ model: z.ZodString;
62
+ }, z.core.$strip>>;
63
+ confirmBeforeChange: z.ZodBoolean;
64
+ lastRunAt: z.ZodOptional<z.ZodString>;
65
+ lastReadAt: z.ZodOptional<z.ZodString>;
66
+ lastError: z.ZodOptional<z.ZodObject<{
67
+ at: z.ZodString;
68
+ message: z.ZodString;
69
+ }, z.core.$strip>>;
70
+ }, z.core.$strip>;
71
+ /** One stored task record, inferred from {@link scheduledTaskRecord}. */
72
+ export type ScheduledTaskRecord = z.infer<typeof scheduledTaskRecord>;
73
+ /** The scheduled-task domain spec: one `tasks` table keyed by task id. */
74
+ export declare const scheduledTaskDomainSpec: {
75
+ name: string;
76
+ version: number;
77
+ tables: {
78
+ tasks: import("@deepseek-ai/dsh-storage-domain").DomainTableSpec<ScheduledTaskId, {
79
+ id: ScheduledTaskId;
80
+ title: string;
81
+ prompt: string;
82
+ rule: {
83
+ kind: "after";
84
+ afterSeconds: number;
85
+ scheduledAt: string;
86
+ } | {
87
+ kind: "at";
88
+ scheduledAt: string;
89
+ } | {
90
+ kind: "every";
91
+ everySeconds: number;
92
+ scheduledAt: string;
93
+ } | {
94
+ kind: "hourly";
95
+ minute: number;
96
+ scheduledAt: string;
97
+ } | {
98
+ kind: "daily";
99
+ time: string;
100
+ time_zone: string;
101
+ scheduledAt: string;
102
+ } | {
103
+ kind: "weekly";
104
+ weekdays: number[];
105
+ time: string;
106
+ time_zone: string;
107
+ scheduledAt: string;
108
+ } | {
109
+ kind: "monthly";
110
+ dayOfMonth: number;
111
+ time: string;
112
+ time_zone: string;
113
+ scheduledAt: string;
114
+ };
115
+ status: "active" | "paused" | "completed";
116
+ sessionId: SessionId;
117
+ createdAt: string;
118
+ confirmBeforeChange: boolean;
119
+ workspaceId?: string | undefined;
120
+ cwd?: string | undefined;
121
+ model?: {
122
+ provider: string;
123
+ model: string;
124
+ } | undefined;
125
+ lastRunAt?: string | undefined;
126
+ lastReadAt?: string | undefined;
127
+ lastError?: {
128
+ at: string;
129
+ message: string;
130
+ } | undefined;
131
+ }>;
132
+ };
133
+ };
134
+ //# sourceMappingURL=spec.d.ts.map
@@ -0,0 +1,89 @@
1
+ /**
2
+ * The external scheduled-task domain declaration: record schema and the
3
+ * `defineDomain` spec the service opens (mirrors the storage-domain pattern).
4
+ * @module @qihongmu/dsh-plugins-scheduled-task/src/spec
5
+ */
6
+ import { z } from 'zod';
7
+ import { SessionId } from '@deepseek-ai/dsh-session/types';
8
+ import { defineDomain, domainTable } from '@deepseek-ai/dsh-storage-domain';
9
+ /** Task id schema at the durable boundary; branding has no runtime representation. */
10
+ const scheduledTaskId = z.string().transform(value => value);
11
+ /** Session id schema; branding has no runtime representation. */
12
+ const sessionId = z.string().transform(SessionId);
13
+ const afterRule = z.object({
14
+ kind: z.literal('after'),
15
+ afterSeconds: z.number().int().positive(),
16
+ scheduledAt: z.string(),
17
+ });
18
+ const atRule = z.object({
19
+ kind: z.literal('at'),
20
+ scheduledAt: z.string(),
21
+ });
22
+ const everyRule = z.object({
23
+ kind: z.literal('every'),
24
+ everySeconds: z.number().int().min(300),
25
+ scheduledAt: z.string(),
26
+ });
27
+ const hourlyRule = z.object({
28
+ kind: z.literal('hourly'),
29
+ minute: z.number().int().min(0).max(59),
30
+ scheduledAt: z.string(),
31
+ });
32
+ const dailyRule = z.object({
33
+ kind: z.literal('daily'),
34
+ time: z.string(),
35
+ time_zone: z.string(),
36
+ scheduledAt: z.string(),
37
+ });
38
+ const weeklyRule = z.object({
39
+ kind: z.literal('weekly'),
40
+ weekdays: z.array(z.number().int().min(1).max(7)).min(1),
41
+ time: z.string(),
42
+ time_zone: z.string(),
43
+ scheduledAt: z.string(),
44
+ });
45
+ const monthlyRule = z.object({
46
+ kind: z.literal('monthly'),
47
+ dayOfMonth: z.number().int().min(1).max(31),
48
+ time: z.string(),
49
+ time_zone: z.string(),
50
+ scheduledAt: z.string(),
51
+ });
52
+ const rule = z.discriminatedUnion('kind', [
53
+ afterRule, atRule, everyRule, hourlyRule, dailyRule, weeklyRule, monthlyRule,
54
+ ]);
55
+ /** Provider/model pair stored on a task. */
56
+ const model = z.object({
57
+ provider: z.string().min(1),
58
+ model: z.string().min(1),
59
+ });
60
+ /**
61
+ * Durable shape of one task record. `title`/`prompt` are non-empty after
62
+ * trimming; `rule` carries the schedule and next target; timestamps are ISO-8601.
63
+ */
64
+ export const scheduledTaskRecord = z.object({
65
+ id: scheduledTaskId,
66
+ title: z.string().min(1),
67
+ prompt: z.string().min(1),
68
+ rule,
69
+ status: z.enum(['active', 'paused', 'completed']),
70
+ sessionId,
71
+ createdAt: z.string(),
72
+ workspaceId: z.string().optional(),
73
+ cwd: z.string().optional(),
74
+ model: model.optional(),
75
+ confirmBeforeChange: z.boolean(),
76
+ lastRunAt: z.string().optional(),
77
+ lastReadAt: z.string().optional(),
78
+ /** Failure of the most recent run-admission attempt, if it did not succeed. */
79
+ lastError: z.object({
80
+ at: z.string(),
81
+ message: z.string().min(1),
82
+ }).optional(),
83
+ });
84
+ /** The scheduled-task domain spec: one `tasks` table keyed by task id. */
85
+ export const scheduledTaskDomainSpec = defineDomain({
86
+ name: 'scheduled_task',
87
+ version: 1,
88
+ tables: { tasks: domainTable(scheduledTaskRecord) },
89
+ });
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Wire-facing global scheduled-task value types (client-safe; no DSH repo edits).
3
+ * @module @qihongmu/dsh-plugins-scheduled-task
4
+ */
5
+ import type { Branded } from '@deepseek-ai/dsh-brand';
6
+ import type { SessionId } from '@deepseek-ai/dsh-session/types';
7
+ /** Stable task identity that is unique and never reused. */
8
+ export type ScheduledTaskId = Branded<'ScheduledTaskId'>;
9
+ /** Lifecycle a task can occupy; `completed` is terminal and set only after a one-shot fires. */
10
+ export type ScheduledTaskStatus = 'active' | 'paused' | 'completed';
11
+ /** Selector statuses the browser may set directly; `completed` is scheduler-derived. */
12
+ export type ScheduledTaskSettableStatus = 'active' | 'paused';
13
+ /** One-shot delayed rule: fire once `afterSeconds` after creation. */
14
+ export interface AfterScheduledTaskRule {
15
+ kind: 'after';
16
+ afterSeconds: number;
17
+ scheduledAt: string;
18
+ }
19
+ /** One-shot absolute rule: fire at one exact instant. */
20
+ export interface AtScheduledTaskRule {
21
+ kind: 'at';
22
+ scheduledAt: string;
23
+ }
24
+ /** Fixed-rate rule: fire every `everySeconds`, creation-anchored. */
25
+ export interface EveryScheduledTaskRule {
26
+ kind: 'every';
27
+ everySeconds: number;
28
+ scheduledAt: string;
29
+ }
30
+ /**
31
+ * Recurring wall-clock rules: each carries its next absolute `scheduledAt` (the
32
+ * earliest un-fired occurrence past its anchor) plus the params needed to
33
+ * advance to the following occurrence in the local time zone.
34
+ */
35
+ /** Hourly rule: fire at `minute` (0-59) past each hour, in the process zone. */
36
+ export interface HourlyScheduledTaskRule {
37
+ kind: 'hourly';
38
+ minute: number;
39
+ scheduledAt: string;
40
+ }
41
+ /** Daily rule: fire each day at `time` (HH:mm) in `time_zone`. */
42
+ export interface DailyScheduledTaskRule {
43
+ kind: 'daily';
44
+ time: string;
45
+ time_zone: string;
46
+ scheduledAt: string;
47
+ }
48
+ /** Weekly rule: fire on each selected weekday (1=Mon..7=Sun) at `time` in `time_zone`. */
49
+ export interface WeeklyScheduledTaskRule {
50
+ kind: 'weekly';
51
+ weekdays: number[];
52
+ time: string;
53
+ time_zone: string;
54
+ scheduledAt: string;
55
+ }
56
+ /** Monthly rule: fire on `dayOfMonth` (1-31) at `time` in `time_zone`; months without the day are skipped. */
57
+ export interface MonthlyScheduledTaskRule {
58
+ kind: 'monthly';
59
+ dayOfMonth: number;
60
+ time: string;
61
+ time_zone: string;
62
+ scheduledAt: string;
63
+ }
64
+ /** The scheduled-task rule union. */
65
+ export type ScheduledTaskRule = AfterScheduledTaskRule | AtScheduledTaskRule | EveryScheduledTaskRule | HourlyScheduledTaskRule | DailyScheduledTaskRule | WeeklyScheduledTaskRule | MonthlyScheduledTaskRule;
66
+ /** Structured local-calendar absolute input accepted by `at`. */
67
+ export interface ScheduledTaskAtInput {
68
+ date: string;
69
+ time: string;
70
+ time_zone: string;
71
+ }
72
+ /** Hourly selector: fire each hour at `minute` (0-59) past the hour. */
73
+ export interface ScheduledTaskHourlyInput {
74
+ minute: number;
75
+ }
76
+ /** Daily selector: fire each day at `time` (HH:mm) in `time_zone`. */
77
+ export interface ScheduledTaskDailyInput {
78
+ time: string;
79
+ time_zone: string;
80
+ }
81
+ /** Weekly selector: fire on each weekday (1=Mon..7=Sun) at `time` in `time_zone`. */
82
+ export interface ScheduledTaskWeeklyInput {
83
+ weekdays: number[];
84
+ time: string;
85
+ time_zone: string;
86
+ }
87
+ /** Monthly selector: fire on `dayOfMonth` (1-31) at `time` in `time_zone`. */
88
+ export interface ScheduledTaskMonthlyInput {
89
+ dayOfMonth: number;
90
+ time: string;
91
+ time_zone: string;
92
+ }
93
+ /** Provider/model pair a scheduled task runs with (applied as the agent's options at fire time). */
94
+ export interface ScheduledTaskModel {
95
+ provider: string;
96
+ model: string;
97
+ }
98
+ /** Common create/update carry fields (not part of the schedule selector). */
99
+ export interface ScheduledTaskCarryFields {
100
+ /** The task instruction (the Prompt executed at fire time). */
101
+ prompt?: string;
102
+ /** Optional project workspace id the task runs in (drives the run directory). */
103
+ workspaceId?: string;
104
+ /** Canonical project path used as the run session `cwd`. */
105
+ cwd?: string;
106
+ /** Provider/model the task runs with; absent keeps the deployment default. */
107
+ model?: ScheduledTaskModel;
108
+ /** Whether to ask the user before the run makes changes (approval policy `ask`). */
109
+ confirmBeforeChange?: boolean;
110
+ }
111
+ /** One schedule selector, exactly one of which is required on create. */
112
+ export interface ScheduledTaskScheduleSelectorFields {
113
+ after_seconds?: number;
114
+ at?: ScheduledTaskAtInput;
115
+ every_seconds?: number;
116
+ hourly?: ScheduledTaskHourlyInput;
117
+ daily?: ScheduledTaskDailyInput;
118
+ weekly?: ScheduledTaskWeeklyInput;
119
+ monthly?: ScheduledTaskMonthlyInput;
120
+ }
121
+ /** Create input: a non-empty title, a non-empty prompt, and exactly one schedule selector. */
122
+ export interface ScheduledTaskCreateInput extends ScheduledTaskCarryFields, ScheduledTaskScheduleSelectorFields {
123
+ title: string;
124
+ prompt: string;
125
+ }
126
+ /** Update input: any supplied field replaces the stored one; an absent selector keeps the current rule. */
127
+ export interface ScheduledTaskUpdateInput extends ScheduledTaskCarryFields, ScheduledTaskScheduleSelectorFields {
128
+ title?: string;
129
+ }
130
+ /** Coarse display phase derived from status + wall clock. */
131
+ export type ScheduledTaskState = 'scheduled' | 'overdue' | 'completed';
132
+ /** Complete client-facing view of one task. */
133
+ export interface ScheduledTaskView {
134
+ id: ScheduledTaskId;
135
+ title: string;
136
+ prompt: string;
137
+ rule: ScheduledTaskRule;
138
+ status: ScheduledTaskStatus;
139
+ sessionId: SessionId;
140
+ createdAt: string;
141
+ workspaceId?: string;
142
+ cwd?: string;
143
+ model?: ScheduledTaskModel;
144
+ confirmBeforeChange: boolean;
145
+ lastRunAt?: string;
146
+ nextRunAt?: string;
147
+ state: ScheduledTaskState;
148
+ unread: boolean;
149
+ /** Failure of the most recent run-admission attempt, if it did not succeed. */
150
+ lastError?: ScheduledTaskRunError;
151
+ }
152
+ /** One failed run admission (session creation/queueing), kept for surfacing. */
153
+ export interface ScheduledTaskRunError {
154
+ /** ISO-8601 instant of the failure. */
155
+ at: string;
156
+ /** Rendered failure message (process-side diagnostics wording). */
157
+ message: string;
158
+ }
159
+ /** Closed v1 management error codes. */
160
+ export type ScheduledTaskErrorCode = 'invalid_title' | 'invalid_prompt' | 'invalid_selector' | 'invalid_rule' | 'invalid_time_zone' | 'not_future' | 'time_out_of_range' | 'frequency_too_high' | 'task_not_found' | 'internal_error';
161
+ /** Successful or failed create/update/status mutation. */
162
+ export type ScheduledTaskMutationResult = {
163
+ ok: true;
164
+ task: ScheduledTaskView;
165
+ } | {
166
+ ok: false;
167
+ code: ScheduledTaskErrorCode;
168
+ message: string;
169
+ };
170
+ /** Successful or failed delete. */
171
+ export type ScheduledTaskDeleteResult = {
172
+ ok: true;
173
+ deleted: boolean;
174
+ } | {
175
+ ok: false;
176
+ code: ScheduledTaskErrorCode;
177
+ message: string;
178
+ };
179
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Wire-facing global scheduled-task value types (client-safe; no DSH repo edits).
3
+ * @module @qihongmu/dsh-plugins-scheduled-task
4
+ */
5
+ export {};
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@qihongmu/dsh-plugins-scheduled-task",
3
+ "version": "0.1.0",
4
+ "license": "MIT",
5
+ "author": "Qihong <qihong.m.u+dev@gmail.com>",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/qihongmu/dsh-plugins.git",
9
+ "directory": "packages/scheduled-task/host"
10
+ },
11
+ "description": "External user plugin: global scheduled tasks for DeepSeek Harness (host Service + scheduler + Remote surface), no changes to the dsh library.",
12
+ "type": "module",
13
+ "main": "lib/types/index.js",
14
+ "types": "lib/types/index.d.ts",
15
+ "exports": {
16
+ ".": {
17
+ "types": "./lib/types/index.d.ts",
18
+ "default": "./lib/types/index.js"
19
+ },
20
+ "./invariant": {
21
+ "types": "./lib/types/invariant.d.ts",
22
+ "default": "./lib/types/invariant.js"
23
+ },
24
+ "./types": {
25
+ "types": "./lib/types/types.d.ts",
26
+ "default": "./lib/types/types.js"
27
+ },
28
+ "./remote": {
29
+ "types": "./lib/typert.remote-client.d.ts"
30
+ },
31
+ "./src/*": "./src/*",
32
+ "./package.json": "./package.json"
33
+ },
34
+ "scripts": {
35
+ "build": "tsc -p tsconfig.json",
36
+ "typecheck": "tsc -p tsconfig.json --noEmit"
37
+ },
38
+ "dependencies": {
39
+ "zod": "^4.4.3"
40
+ },
41
+ "peerDependencies": {
42
+ "@deepseek-ai/cordis": "*",
43
+ "@deepseek-ai/dsh-agent": "*",
44
+ "@deepseek-ai/dsh-brand": "*",
45
+ "@deepseek-ai/dsh-invariants": "*",
46
+ "@deepseek-ai/dsh-llm": "*",
47
+ "@deepseek-ai/dsh-schedule": "*",
48
+ "@deepseek-ai/dsh-session": "*",
49
+ "@deepseek-ai/dsh-storage-domain": "*",
50
+ "@deepseek-ai/dsh-typert-protocol": "*"
51
+ },
52
+ "dsh": {
53
+ "bundle": {
54
+ "patch": "./cordis.patch.yml"
55
+ }
56
+ },
57
+ "files": [
58
+ "lib",
59
+ "cordis.patch.yml",
60
+ "!lib/**/*.map",
61
+ "!lib/**/*.tsbuildinfo"
62
+ ]
63
+ }