@dobby.ai/dobby 0.1.1 → 0.1.2
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.md +20 -7
- package/dist/src/agent/event-forwarder.js +185 -16
- package/dist/src/cli/commands/cron.js +39 -35
- package/dist/src/cli/program.js +0 -6
- package/dist/src/core/types.js +2 -0
- package/dist/src/cron/config.js +2 -2
- package/dist/src/cron/service.js +87 -23
- package/dist/src/cron/store.js +1 -1
- package/package.json +9 -3
- package/.env.example +0 -8
- package/AGENTS.md +0 -267
- package/ROADMAP.md +0 -34
- package/config/cron.example.json +0 -9
- package/config/gateway.example.json +0 -132
- package/dist/plugins/connector-discord/src/mapper.js +0 -75
- package/dist/src/cli/tests/config-command.test.js +0 -42
- package/dist/src/cli/tests/config-io.test.js +0 -64
- package/dist/src/cli/tests/config-mutators.test.js +0 -47
- package/dist/src/cli/tests/discord-mapper.test.js +0 -90
- package/dist/src/cli/tests/doctor.test.js +0 -252
- package/dist/src/cli/tests/init-catalog.test.js +0 -134
- package/dist/src/cli/tests/program-options.test.js +0 -78
- package/dist/src/cli/tests/routing-config.test.js +0 -254
- package/dist/src/core/tests/control-command.test.js +0 -17
- package/dist/src/core/tests/runtime-registry.test.js +0 -116
- package/dist/src/core/tests/typing-controller.test.js +0 -103
- package/docs/BOXLITE_SANDBOX_FEASIBILITY.md +0 -175
- package/docs/CRON_SCHEDULER_DESIGN.md +0 -374
- package/docs/DOCKER_SANDBOX_vs_BOXLITE.md +0 -77
- package/docs/EXTENSION_SYSTEM_ARCHITECTURE.md +0 -119
- package/docs/MVP.md +0 -135
- package/docs/RUNBOOK.md +0 -243
- package/docs/TEAMWORK_HANDOFF_DESIGN.md +0 -440
- package/plugins/connector-discord/dobby.manifest.json +0 -18
- package/plugins/connector-discord/index.js +0 -1
- package/plugins/connector-discord/package-lock.json +0 -360
- package/plugins/connector-discord/package.json +0 -38
- package/plugins/connector-discord/src/connector.ts +0 -345
- package/plugins/connector-discord/src/contribution.ts +0 -21
- package/plugins/connector-discord/src/mapper.ts +0 -101
- package/plugins/connector-discord/tsconfig.json +0 -19
- package/plugins/connector-feishu/dobby.manifest.json +0 -18
- package/plugins/connector-feishu/index.js +0 -1
- package/plugins/connector-feishu/package-lock.json +0 -618
- package/plugins/connector-feishu/package.json +0 -38
- package/plugins/connector-feishu/src/connector.ts +0 -343
- package/plugins/connector-feishu/src/contribution.ts +0 -26
- package/plugins/connector-feishu/src/mapper.ts +0 -401
- package/plugins/connector-feishu/tsconfig.json +0 -19
- package/plugins/plugin-sdk/index.d.ts +0 -261
- package/plugins/plugin-sdk/index.js +0 -1
- package/plugins/plugin-sdk/package-lock.json +0 -12
- package/plugins/plugin-sdk/package.json +0 -22
- package/plugins/provider-claude/dobby.manifest.json +0 -17
- package/plugins/provider-claude/index.js +0 -1
- package/plugins/provider-claude/package-lock.json +0 -3398
- package/plugins/provider-claude/package.json +0 -39
- package/plugins/provider-claude/src/contribution.ts +0 -1018
- package/plugins/provider-claude/tsconfig.json +0 -19
- package/plugins/provider-claude-cli/dobby.manifest.json +0 -17
- package/plugins/provider-claude-cli/index.js +0 -1
- package/plugins/provider-claude-cli/package-lock.json +0 -2898
- package/plugins/provider-claude-cli/package.json +0 -38
- package/plugins/provider-claude-cli/src/contribution.ts +0 -1673
- package/plugins/provider-claude-cli/tsconfig.json +0 -19
- package/plugins/provider-pi/dobby.manifest.json +0 -17
- package/plugins/provider-pi/index.js +0 -1
- package/plugins/provider-pi/package-lock.json +0 -3877
- package/plugins/provider-pi/package.json +0 -40
- package/plugins/provider-pi/src/contribution.ts +0 -606
- package/plugins/provider-pi/tsconfig.json +0 -19
- package/plugins/sandbox-core/boxlite.js +0 -1
- package/plugins/sandbox-core/dobby.manifest.json +0 -17
- package/plugins/sandbox-core/docker.js +0 -1
- package/plugins/sandbox-core/package-lock.json +0 -136
- package/plugins/sandbox-core/package.json +0 -39
- package/plugins/sandbox-core/src/boxlite-context.ts +0 -2
- package/plugins/sandbox-core/src/boxlite-contribution.ts +0 -53
- package/plugins/sandbox-core/src/boxlite-executor.ts +0 -911
- package/plugins/sandbox-core/src/docker-contribution.ts +0 -43
- package/plugins/sandbox-core/src/docker-executor.ts +0 -217
- package/plugins/sandbox-core/tsconfig.json +0 -19
- package/scripts/local-extensions.mjs +0 -168
- package/src/agent/event-forwarder.ts +0 -414
- package/src/cli/commands/config.ts +0 -328
- package/src/cli/commands/configure.ts +0 -92
- package/src/cli/commands/cron.ts +0 -410
- package/src/cli/commands/doctor.ts +0 -331
- package/src/cli/commands/extension.ts +0 -207
- package/src/cli/commands/init.ts +0 -211
- package/src/cli/commands/start.ts +0 -223
- package/src/cli/commands/topology.ts +0 -415
- package/src/cli/index.ts +0 -9
- package/src/cli/program.ts +0 -314
- package/src/cli/shared/config-io.ts +0 -245
- package/src/cli/shared/config-mutators.ts +0 -470
- package/src/cli/shared/config-schema.ts +0 -228
- package/src/cli/shared/config-types.ts +0 -129
- package/src/cli/shared/configure-sections.ts +0 -595
- package/src/cli/shared/discord-config.ts +0 -14
- package/src/cli/shared/init-catalog.ts +0 -249
- package/src/cli/shared/local-extension-specs.ts +0 -108
- package/src/cli/shared/runtime.ts +0 -33
- package/src/cli/shared/schema-prompts.ts +0 -443
- package/src/cli/tests/config-command.test.ts +0 -56
- package/src/cli/tests/config-io.test.ts +0 -92
- package/src/cli/tests/config-mutators.test.ts +0 -59
- package/src/cli/tests/discord-mapper.test.ts +0 -128
- package/src/cli/tests/doctor.test.ts +0 -269
- package/src/cli/tests/init-catalog.test.ts +0 -144
- package/src/cli/tests/program-options.test.ts +0 -95
- package/src/cli/tests/routing-config.test.ts +0 -281
- package/src/core/control-command.ts +0 -12
- package/src/core/dedup-store.ts +0 -103
- package/src/core/gateway.ts +0 -609
- package/src/core/routing.ts +0 -404
- package/src/core/runtime-registry.ts +0 -141
- package/src/core/tests/control-command.test.ts +0 -20
- package/src/core/tests/runtime-registry.test.ts +0 -140
- package/src/core/tests/typing-controller.test.ts +0 -129
- package/src/core/types.ts +0 -324
- package/src/core/typing-controller.ts +0 -119
- package/src/cron/config.ts +0 -154
- package/src/cron/schedule.ts +0 -61
- package/src/cron/service.ts +0 -249
- package/src/cron/store.ts +0 -155
- package/src/cron/types.ts +0 -60
- package/src/extension/loader.ts +0 -145
- package/src/extension/manager.ts +0 -355
- package/src/extension/manifest.ts +0 -26
- package/src/extension/registry.ts +0 -229
- package/src/main.ts +0 -8
- package/src/sandbox/executor.ts +0 -44
- package/src/sandbox/host-executor.ts +0 -118
- package/src/shared/dobby-repo.ts +0 -48
- package/tsconfig.json +0 -18
package/src/cli/commands/cron.ts
DELETED
|
@@ -1,410 +0,0 @@
|
|
|
1
|
-
import { loadGatewayConfig } from "../../core/routing.js";
|
|
2
|
-
import type { GatewayConfig } from "../../core/types.js";
|
|
3
|
-
import { loadCronConfig } from "../../cron/config.js";
|
|
4
|
-
import { computeInitialNextRunAtMs, describeSchedule } from "../../cron/schedule.js";
|
|
5
|
-
import { CronStore } from "../../cron/store.js";
|
|
6
|
-
import type { CronSessionPolicy, JobSchedule, ScheduledJob } from "../../cron/types.js";
|
|
7
|
-
import { resolveConfigPath } from "../shared/config-io.js";
|
|
8
|
-
import { createLogger } from "../shared/runtime.js";
|
|
9
|
-
|
|
10
|
-
interface CronCommandSharedOptions {
|
|
11
|
-
cronConfigPath?: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
interface LoadedCronContext {
|
|
15
|
-
configPath: string;
|
|
16
|
-
gatewayConfig: GatewayConfig;
|
|
17
|
-
cronConfigPath: string;
|
|
18
|
-
store: CronStore;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
interface ScheduleInput {
|
|
22
|
-
at?: string;
|
|
23
|
-
everyMs?: number;
|
|
24
|
-
cronExpr?: string;
|
|
25
|
-
tz?: string;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function slugify(value: string): string {
|
|
29
|
-
const normalized = value
|
|
30
|
-
.trim()
|
|
31
|
-
.toLowerCase()
|
|
32
|
-
.replaceAll(/[^a-z0-9]+/g, "-")
|
|
33
|
-
.replaceAll(/^-+|-+$/g, "");
|
|
34
|
-
return normalized.length > 0 ? normalized : "job";
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function parseSchedule(input: ScheduleInput): JobSchedule {
|
|
38
|
-
const variants = [input.at ? "at" : null, input.everyMs !== undefined ? "every" : null, input.cronExpr ? "cron" : null]
|
|
39
|
-
.filter((item): item is "at" | "every" | "cron" => item !== null);
|
|
40
|
-
if (variants.length !== 1) {
|
|
41
|
-
throw new Error("Exactly one schedule option is required: --at | --every-ms | --cron");
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (input.at) {
|
|
45
|
-
return { kind: "at", at: input.at };
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (input.everyMs !== undefined) {
|
|
49
|
-
if (!Number.isFinite(input.everyMs) || input.everyMs <= 0) {
|
|
50
|
-
throw new Error("--every-ms must be a positive integer");
|
|
51
|
-
}
|
|
52
|
-
return { kind: "every", everyMs: Math.floor(input.everyMs) };
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (!input.cronExpr) {
|
|
56
|
-
throw new Error("Missing --cron expression");
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return {
|
|
60
|
-
kind: "cron",
|
|
61
|
-
expr: input.cronExpr,
|
|
62
|
-
...(input.tz ? { tz: input.tz } : {}),
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function parseSessionPolicy(value: CronSessionPolicy | string | undefined): CronSessionPolicy | undefined {
|
|
67
|
-
if (value === undefined) {
|
|
68
|
-
return undefined;
|
|
69
|
-
}
|
|
70
|
-
if (value === "stateless" || value === "shared-session") {
|
|
71
|
-
return value;
|
|
72
|
-
}
|
|
73
|
-
throw new Error(`Invalid session policy '${value}'. Expected 'stateless' or 'shared-session'.`);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function assertDeliveryReferences(
|
|
77
|
-
config: GatewayConfig,
|
|
78
|
-
input: {
|
|
79
|
-
connectorId: string;
|
|
80
|
-
routeId: string;
|
|
81
|
-
},
|
|
82
|
-
): void {
|
|
83
|
-
if (!config.connectors.items[input.connectorId]) {
|
|
84
|
-
throw new Error(`Unknown connectorId '${input.connectorId}'`);
|
|
85
|
-
}
|
|
86
|
-
if (!config.routes.items[input.routeId]) {
|
|
87
|
-
throw new Error(`Unknown routeId '${input.routeId}'`);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
async function loadCronContext(options?: CronCommandSharedOptions): Promise<LoadedCronContext> {
|
|
92
|
-
const configPath = resolveConfigPath();
|
|
93
|
-
const gatewayConfig = await loadGatewayConfig(configPath);
|
|
94
|
-
const loadedCronConfig = await loadCronConfig({
|
|
95
|
-
gatewayConfigPath: configPath,
|
|
96
|
-
gatewayConfig,
|
|
97
|
-
...(options?.cronConfigPath ? { explicitCronConfigPath: options.cronConfigPath } : {}),
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
const logger = createLogger();
|
|
101
|
-
const store = new CronStore(loadedCronConfig.config.storeFile, loadedCronConfig.config.runLogFile, logger);
|
|
102
|
-
await store.load();
|
|
103
|
-
|
|
104
|
-
return {
|
|
105
|
-
configPath,
|
|
106
|
-
gatewayConfig,
|
|
107
|
-
cronConfigPath: loadedCronConfig.configPath,
|
|
108
|
-
store,
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
export async function runCronAddCommand(options: {
|
|
113
|
-
name: string;
|
|
114
|
-
prompt: string;
|
|
115
|
-
connectorId: string;
|
|
116
|
-
routeId: string;
|
|
117
|
-
channelId: string;
|
|
118
|
-
threadId?: string;
|
|
119
|
-
sessionPolicy?: CronSessionPolicy;
|
|
120
|
-
at?: string;
|
|
121
|
-
everyMs?: number;
|
|
122
|
-
cronExpr?: string;
|
|
123
|
-
tz?: string;
|
|
124
|
-
cronConfigPath?: string;
|
|
125
|
-
}): Promise<void> {
|
|
126
|
-
const context = await loadCronContext(
|
|
127
|
-
options.cronConfigPath ? { cronConfigPath: options.cronConfigPath } : undefined,
|
|
128
|
-
);
|
|
129
|
-
assertDeliveryReferences(context.gatewayConfig, {
|
|
130
|
-
connectorId: options.connectorId,
|
|
131
|
-
routeId: options.routeId,
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
const schedule = parseSchedule({
|
|
135
|
-
...(options.at ? { at: options.at } : {}),
|
|
136
|
-
...(options.everyMs !== undefined ? { everyMs: options.everyMs } : {}),
|
|
137
|
-
...(options.cronExpr ? { cronExpr: options.cronExpr } : {}),
|
|
138
|
-
...(options.tz ? { tz: options.tz } : {}),
|
|
139
|
-
});
|
|
140
|
-
const now = Date.now();
|
|
141
|
-
const nextRunAtMs = computeInitialNextRunAtMs(schedule, now);
|
|
142
|
-
const id = `${slugify(options.name)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
143
|
-
const sessionPolicy = parseSessionPolicy(options.sessionPolicy) ?? "stateless";
|
|
144
|
-
|
|
145
|
-
const job: ScheduledJob = {
|
|
146
|
-
id,
|
|
147
|
-
name: options.name,
|
|
148
|
-
enabled: true,
|
|
149
|
-
schedule,
|
|
150
|
-
sessionPolicy,
|
|
151
|
-
prompt: options.prompt,
|
|
152
|
-
delivery: {
|
|
153
|
-
connectorId: options.connectorId,
|
|
154
|
-
routeId: options.routeId,
|
|
155
|
-
channelId: options.channelId,
|
|
156
|
-
...(options.threadId ? { threadId: options.threadId } : {}),
|
|
157
|
-
},
|
|
158
|
-
createdAtMs: now,
|
|
159
|
-
updatedAtMs: now,
|
|
160
|
-
state: {
|
|
161
|
-
...(nextRunAtMs !== undefined ? { nextRunAtMs } : {}),
|
|
162
|
-
consecutiveErrors: 0,
|
|
163
|
-
},
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
await context.store.upsertJob(job);
|
|
167
|
-
console.log(`Added cron job ${job.id}`);
|
|
168
|
-
console.log(`- schedule: ${describeSchedule(job.schedule)}`);
|
|
169
|
-
console.log(`- delivery: ${job.delivery.connectorId}/${job.delivery.routeId}/${job.delivery.channelId}`);
|
|
170
|
-
console.log(`- cron config: ${context.cronConfigPath}`);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
export async function runCronListCommand(options: {
|
|
174
|
-
cronConfigPath?: string;
|
|
175
|
-
json?: boolean;
|
|
176
|
-
}): Promise<void> {
|
|
177
|
-
const context = await loadCronContext(
|
|
178
|
-
options.cronConfigPath ? { cronConfigPath: options.cronConfigPath } : undefined,
|
|
179
|
-
);
|
|
180
|
-
const jobs = context.store.listJobs();
|
|
181
|
-
|
|
182
|
-
if (options.json) {
|
|
183
|
-
console.log(JSON.stringify({ jobs, cronConfigPath: context.cronConfigPath }, null, 2));
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
if (jobs.length === 0) {
|
|
188
|
-
console.log(`No cron jobs configured (${context.cronConfigPath})`);
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
console.log(`Cron jobs (${context.cronConfigPath}):`);
|
|
193
|
-
for (const job of jobs) {
|
|
194
|
-
const next = job.state.nextRunAtMs ? new Date(job.state.nextRunAtMs).toISOString() : "-";
|
|
195
|
-
const last = job.state.lastRunAtMs ? new Date(job.state.lastRunAtMs).toISOString() : "-";
|
|
196
|
-
const schedule = describeSchedule(job.schedule);
|
|
197
|
-
console.log(`- ${job.id} [${job.enabled ? "enabled" : "paused"}] ${job.name}`);
|
|
198
|
-
console.log(` schedule=${schedule}`);
|
|
199
|
-
console.log(` next=${next} last=${last} status=${job.state.lastStatus ?? "-"}`);
|
|
200
|
-
console.log(` delivery=${job.delivery.connectorId}/${job.delivery.routeId}/${job.delivery.channelId}`);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
export async function runCronStatusCommand(options: {
|
|
205
|
-
jobId?: string;
|
|
206
|
-
cronConfigPath?: string;
|
|
207
|
-
json?: boolean;
|
|
208
|
-
}): Promise<void> {
|
|
209
|
-
const context = await loadCronContext(
|
|
210
|
-
options.cronConfigPath ? { cronConfigPath: options.cronConfigPath } : undefined,
|
|
211
|
-
);
|
|
212
|
-
const target = options.jobId ? context.store.getJob(options.jobId) : null;
|
|
213
|
-
|
|
214
|
-
if (options.jobId && !target) {
|
|
215
|
-
throw new Error(`Cron job '${options.jobId}' does not exist`);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
if (options.json) {
|
|
219
|
-
if (target) {
|
|
220
|
-
console.log(JSON.stringify(target, null, 2));
|
|
221
|
-
return;
|
|
222
|
-
}
|
|
223
|
-
console.log(JSON.stringify(context.store.listJobs(), null, 2));
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
if (target) {
|
|
228
|
-
console.log(`Cron status for ${target.id}`);
|
|
229
|
-
console.log(`- name: ${target.name}`);
|
|
230
|
-
console.log(`- enabled: ${target.enabled}`);
|
|
231
|
-
console.log(`- schedule: ${describeSchedule(target.schedule)}`);
|
|
232
|
-
console.log(`- sessionPolicy: ${target.sessionPolicy ?? "stateless"}`);
|
|
233
|
-
console.log(`- nextRun: ${target.state.nextRunAtMs ? new Date(target.state.nextRunAtMs).toISOString() : "-"}`);
|
|
234
|
-
console.log(`- lastRun: ${target.state.lastRunAtMs ? new Date(target.state.lastRunAtMs).toISOString() : "-"}`);
|
|
235
|
-
console.log(`- lastStatus: ${target.state.lastStatus ?? "-"}`);
|
|
236
|
-
if (target.state.lastError) {
|
|
237
|
-
console.log(`- lastError: ${target.state.lastError}`);
|
|
238
|
-
}
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
await runCronListCommand({
|
|
243
|
-
...(options.cronConfigPath ? { cronConfigPath: options.cronConfigPath } : {}),
|
|
244
|
-
json: false,
|
|
245
|
-
});
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
export async function runCronRunCommand(options: {
|
|
249
|
-
jobId: string;
|
|
250
|
-
cronConfigPath?: string;
|
|
251
|
-
}): Promise<void> {
|
|
252
|
-
const context = await loadCronContext(
|
|
253
|
-
options.cronConfigPath ? { cronConfigPath: options.cronConfigPath } : undefined,
|
|
254
|
-
);
|
|
255
|
-
const now = Date.now();
|
|
256
|
-
await context.store.updateJob(options.jobId, (current) => ({
|
|
257
|
-
...current,
|
|
258
|
-
enabled: true,
|
|
259
|
-
updatedAtMs: now,
|
|
260
|
-
state: {
|
|
261
|
-
...current.state,
|
|
262
|
-
nextRunAtMs: now,
|
|
263
|
-
},
|
|
264
|
-
}));
|
|
265
|
-
console.log(`Scheduled cron job ${options.jobId} to run on next scheduler tick.`);
|
|
266
|
-
console.log("Ensure the gateway process is running for execution.");
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
export async function runCronUpdateCommand(options: {
|
|
270
|
-
jobId: string;
|
|
271
|
-
name?: string;
|
|
272
|
-
prompt?: string;
|
|
273
|
-
connectorId?: string;
|
|
274
|
-
routeId?: string;
|
|
275
|
-
channelId?: string;
|
|
276
|
-
threadId?: string;
|
|
277
|
-
clearThread?: boolean;
|
|
278
|
-
sessionPolicy?: CronSessionPolicy;
|
|
279
|
-
at?: string;
|
|
280
|
-
everyMs?: number;
|
|
281
|
-
cronExpr?: string;
|
|
282
|
-
tz?: string;
|
|
283
|
-
cronConfigPath?: string;
|
|
284
|
-
}): Promise<void> {
|
|
285
|
-
const context = await loadCronContext(
|
|
286
|
-
options.cronConfigPath ? { cronConfigPath: options.cronConfigPath } : undefined,
|
|
287
|
-
);
|
|
288
|
-
const now = Date.now();
|
|
289
|
-
const hasScheduleUpdate = options.at !== undefined || options.everyMs !== undefined || options.cronExpr !== undefined;
|
|
290
|
-
const nextSchedule = hasScheduleUpdate
|
|
291
|
-
? parseSchedule({
|
|
292
|
-
...(options.at ? { at: options.at } : {}),
|
|
293
|
-
...(options.everyMs !== undefined ? { everyMs: options.everyMs } : {}),
|
|
294
|
-
...(options.cronExpr ? { cronExpr: options.cronExpr } : {}),
|
|
295
|
-
...(options.tz ? { tz: options.tz } : {}),
|
|
296
|
-
})
|
|
297
|
-
: null;
|
|
298
|
-
|
|
299
|
-
await context.store.updateJob(options.jobId, (current) => {
|
|
300
|
-
const updatedDelivery: ScheduledJob["delivery"] = {
|
|
301
|
-
connectorId: options.connectorId ?? current.delivery.connectorId,
|
|
302
|
-
routeId: options.routeId ?? current.delivery.routeId,
|
|
303
|
-
channelId: options.channelId ?? current.delivery.channelId,
|
|
304
|
-
};
|
|
305
|
-
const resolvedThreadId = options.clearThread ? undefined : (options.threadId ?? current.delivery.threadId);
|
|
306
|
-
if (resolvedThreadId !== undefined) {
|
|
307
|
-
updatedDelivery.threadId = resolvedThreadId;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
assertDeliveryReferences(context.gatewayConfig, {
|
|
311
|
-
connectorId: updatedDelivery.connectorId,
|
|
312
|
-
routeId: updatedDelivery.routeId,
|
|
313
|
-
});
|
|
314
|
-
|
|
315
|
-
const schedule = nextSchedule ?? current.schedule;
|
|
316
|
-
const nextRunAtMs = nextSchedule
|
|
317
|
-
? computeInitialNextRunAtMs(schedule, now)
|
|
318
|
-
: current.state.nextRunAtMs;
|
|
319
|
-
const nextState = {
|
|
320
|
-
...current.state,
|
|
321
|
-
};
|
|
322
|
-
if (nextSchedule) {
|
|
323
|
-
if (nextRunAtMs === undefined) {
|
|
324
|
-
delete nextState.nextRunAtMs;
|
|
325
|
-
} else {
|
|
326
|
-
nextState.nextRunAtMs = nextRunAtMs;
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
const parsedSessionPolicy = parseSessionPolicy(options.sessionPolicy);
|
|
331
|
-
const nextJob: ScheduledJob = {
|
|
332
|
-
...current,
|
|
333
|
-
name: options.name ?? current.name,
|
|
334
|
-
prompt: options.prompt ?? current.prompt,
|
|
335
|
-
schedule,
|
|
336
|
-
delivery: updatedDelivery,
|
|
337
|
-
updatedAtMs: now,
|
|
338
|
-
state: nextState,
|
|
339
|
-
};
|
|
340
|
-
const nextSessionPolicy = parsedSessionPolicy ?? current.sessionPolicy;
|
|
341
|
-
if (nextSessionPolicy !== undefined) {
|
|
342
|
-
nextJob.sessionPolicy = nextSessionPolicy;
|
|
343
|
-
} else {
|
|
344
|
-
delete nextJob.sessionPolicy;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
return nextJob;
|
|
348
|
-
});
|
|
349
|
-
|
|
350
|
-
console.log(`Updated cron job ${options.jobId}`);
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
export async function runCronRemoveCommand(options: {
|
|
354
|
-
jobId: string;
|
|
355
|
-
cronConfigPath?: string;
|
|
356
|
-
}): Promise<void> {
|
|
357
|
-
const context = await loadCronContext(
|
|
358
|
-
options.cronConfigPath ? { cronConfigPath: options.cronConfigPath } : undefined,
|
|
359
|
-
);
|
|
360
|
-
const removed = await context.store.removeJob(options.jobId);
|
|
361
|
-
if (!removed) {
|
|
362
|
-
throw new Error(`Cron job '${options.jobId}' does not exist`);
|
|
363
|
-
}
|
|
364
|
-
console.log(`Removed cron job ${options.jobId}`);
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
export async function runCronPauseCommand(options: {
|
|
368
|
-
jobId: string;
|
|
369
|
-
cronConfigPath?: string;
|
|
370
|
-
}): Promise<void> {
|
|
371
|
-
const context = await loadCronContext(
|
|
372
|
-
options.cronConfigPath ? { cronConfigPath: options.cronConfigPath } : undefined,
|
|
373
|
-
);
|
|
374
|
-
const now = Date.now();
|
|
375
|
-
await context.store.updateJob(options.jobId, (current) => ({
|
|
376
|
-
...current,
|
|
377
|
-
enabled: false,
|
|
378
|
-
updatedAtMs: now,
|
|
379
|
-
}));
|
|
380
|
-
console.log(`Paused cron job ${options.jobId}`);
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
export async function runCronResumeCommand(options: {
|
|
384
|
-
jobId: string;
|
|
385
|
-
cronConfigPath?: string;
|
|
386
|
-
}): Promise<void> {
|
|
387
|
-
const context = await loadCronContext(
|
|
388
|
-
options.cronConfigPath ? { cronConfigPath: options.cronConfigPath } : undefined,
|
|
389
|
-
);
|
|
390
|
-
const now = Date.now();
|
|
391
|
-
await context.store.updateJob(options.jobId, (current) => {
|
|
392
|
-
const nextState = {
|
|
393
|
-
...current.state,
|
|
394
|
-
};
|
|
395
|
-
const nextRunAtMs = computeInitialNextRunAtMs(current.schedule, now);
|
|
396
|
-
if (nextRunAtMs === undefined) {
|
|
397
|
-
delete nextState.nextRunAtMs;
|
|
398
|
-
} else {
|
|
399
|
-
nextState.nextRunAtMs = nextRunAtMs;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
return {
|
|
403
|
-
...current,
|
|
404
|
-
enabled: true,
|
|
405
|
-
updatedAtMs: now,
|
|
406
|
-
state: nextState,
|
|
407
|
-
};
|
|
408
|
-
});
|
|
409
|
-
console.log(`Resumed cron job ${options.jobId}`);
|
|
410
|
-
}
|