@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.
Files changed (136) hide show
  1. package/README.md +20 -7
  2. package/dist/src/agent/event-forwarder.js +185 -16
  3. package/dist/src/cli/commands/cron.js +39 -35
  4. package/dist/src/cli/program.js +0 -6
  5. package/dist/src/core/types.js +2 -0
  6. package/dist/src/cron/config.js +2 -2
  7. package/dist/src/cron/service.js +87 -23
  8. package/dist/src/cron/store.js +1 -1
  9. package/package.json +9 -3
  10. package/.env.example +0 -8
  11. package/AGENTS.md +0 -267
  12. package/ROADMAP.md +0 -34
  13. package/config/cron.example.json +0 -9
  14. package/config/gateway.example.json +0 -132
  15. package/dist/plugins/connector-discord/src/mapper.js +0 -75
  16. package/dist/src/cli/tests/config-command.test.js +0 -42
  17. package/dist/src/cli/tests/config-io.test.js +0 -64
  18. package/dist/src/cli/tests/config-mutators.test.js +0 -47
  19. package/dist/src/cli/tests/discord-mapper.test.js +0 -90
  20. package/dist/src/cli/tests/doctor.test.js +0 -252
  21. package/dist/src/cli/tests/init-catalog.test.js +0 -134
  22. package/dist/src/cli/tests/program-options.test.js +0 -78
  23. package/dist/src/cli/tests/routing-config.test.js +0 -254
  24. package/dist/src/core/tests/control-command.test.js +0 -17
  25. package/dist/src/core/tests/runtime-registry.test.js +0 -116
  26. package/dist/src/core/tests/typing-controller.test.js +0 -103
  27. package/docs/BOXLITE_SANDBOX_FEASIBILITY.md +0 -175
  28. package/docs/CRON_SCHEDULER_DESIGN.md +0 -374
  29. package/docs/DOCKER_SANDBOX_vs_BOXLITE.md +0 -77
  30. package/docs/EXTENSION_SYSTEM_ARCHITECTURE.md +0 -119
  31. package/docs/MVP.md +0 -135
  32. package/docs/RUNBOOK.md +0 -243
  33. package/docs/TEAMWORK_HANDOFF_DESIGN.md +0 -440
  34. package/plugins/connector-discord/dobby.manifest.json +0 -18
  35. package/plugins/connector-discord/index.js +0 -1
  36. package/plugins/connector-discord/package-lock.json +0 -360
  37. package/plugins/connector-discord/package.json +0 -38
  38. package/plugins/connector-discord/src/connector.ts +0 -345
  39. package/plugins/connector-discord/src/contribution.ts +0 -21
  40. package/plugins/connector-discord/src/mapper.ts +0 -101
  41. package/plugins/connector-discord/tsconfig.json +0 -19
  42. package/plugins/connector-feishu/dobby.manifest.json +0 -18
  43. package/plugins/connector-feishu/index.js +0 -1
  44. package/plugins/connector-feishu/package-lock.json +0 -618
  45. package/plugins/connector-feishu/package.json +0 -38
  46. package/plugins/connector-feishu/src/connector.ts +0 -343
  47. package/plugins/connector-feishu/src/contribution.ts +0 -26
  48. package/plugins/connector-feishu/src/mapper.ts +0 -401
  49. package/plugins/connector-feishu/tsconfig.json +0 -19
  50. package/plugins/plugin-sdk/index.d.ts +0 -261
  51. package/plugins/plugin-sdk/index.js +0 -1
  52. package/plugins/plugin-sdk/package-lock.json +0 -12
  53. package/plugins/plugin-sdk/package.json +0 -22
  54. package/plugins/provider-claude/dobby.manifest.json +0 -17
  55. package/plugins/provider-claude/index.js +0 -1
  56. package/plugins/provider-claude/package-lock.json +0 -3398
  57. package/plugins/provider-claude/package.json +0 -39
  58. package/plugins/provider-claude/src/contribution.ts +0 -1018
  59. package/plugins/provider-claude/tsconfig.json +0 -19
  60. package/plugins/provider-claude-cli/dobby.manifest.json +0 -17
  61. package/plugins/provider-claude-cli/index.js +0 -1
  62. package/plugins/provider-claude-cli/package-lock.json +0 -2898
  63. package/plugins/provider-claude-cli/package.json +0 -38
  64. package/plugins/provider-claude-cli/src/contribution.ts +0 -1673
  65. package/plugins/provider-claude-cli/tsconfig.json +0 -19
  66. package/plugins/provider-pi/dobby.manifest.json +0 -17
  67. package/plugins/provider-pi/index.js +0 -1
  68. package/plugins/provider-pi/package-lock.json +0 -3877
  69. package/plugins/provider-pi/package.json +0 -40
  70. package/plugins/provider-pi/src/contribution.ts +0 -606
  71. package/plugins/provider-pi/tsconfig.json +0 -19
  72. package/plugins/sandbox-core/boxlite.js +0 -1
  73. package/plugins/sandbox-core/dobby.manifest.json +0 -17
  74. package/plugins/sandbox-core/docker.js +0 -1
  75. package/plugins/sandbox-core/package-lock.json +0 -136
  76. package/plugins/sandbox-core/package.json +0 -39
  77. package/plugins/sandbox-core/src/boxlite-context.ts +0 -2
  78. package/plugins/sandbox-core/src/boxlite-contribution.ts +0 -53
  79. package/plugins/sandbox-core/src/boxlite-executor.ts +0 -911
  80. package/plugins/sandbox-core/src/docker-contribution.ts +0 -43
  81. package/plugins/sandbox-core/src/docker-executor.ts +0 -217
  82. package/plugins/sandbox-core/tsconfig.json +0 -19
  83. package/scripts/local-extensions.mjs +0 -168
  84. package/src/agent/event-forwarder.ts +0 -414
  85. package/src/cli/commands/config.ts +0 -328
  86. package/src/cli/commands/configure.ts +0 -92
  87. package/src/cli/commands/cron.ts +0 -410
  88. package/src/cli/commands/doctor.ts +0 -331
  89. package/src/cli/commands/extension.ts +0 -207
  90. package/src/cli/commands/init.ts +0 -211
  91. package/src/cli/commands/start.ts +0 -223
  92. package/src/cli/commands/topology.ts +0 -415
  93. package/src/cli/index.ts +0 -9
  94. package/src/cli/program.ts +0 -314
  95. package/src/cli/shared/config-io.ts +0 -245
  96. package/src/cli/shared/config-mutators.ts +0 -470
  97. package/src/cli/shared/config-schema.ts +0 -228
  98. package/src/cli/shared/config-types.ts +0 -129
  99. package/src/cli/shared/configure-sections.ts +0 -595
  100. package/src/cli/shared/discord-config.ts +0 -14
  101. package/src/cli/shared/init-catalog.ts +0 -249
  102. package/src/cli/shared/local-extension-specs.ts +0 -108
  103. package/src/cli/shared/runtime.ts +0 -33
  104. package/src/cli/shared/schema-prompts.ts +0 -443
  105. package/src/cli/tests/config-command.test.ts +0 -56
  106. package/src/cli/tests/config-io.test.ts +0 -92
  107. package/src/cli/tests/config-mutators.test.ts +0 -59
  108. package/src/cli/tests/discord-mapper.test.ts +0 -128
  109. package/src/cli/tests/doctor.test.ts +0 -269
  110. package/src/cli/tests/init-catalog.test.ts +0 -144
  111. package/src/cli/tests/program-options.test.ts +0 -95
  112. package/src/cli/tests/routing-config.test.ts +0 -281
  113. package/src/core/control-command.ts +0 -12
  114. package/src/core/dedup-store.ts +0 -103
  115. package/src/core/gateway.ts +0 -609
  116. package/src/core/routing.ts +0 -404
  117. package/src/core/runtime-registry.ts +0 -141
  118. package/src/core/tests/control-command.test.ts +0 -20
  119. package/src/core/tests/runtime-registry.test.ts +0 -140
  120. package/src/core/tests/typing-controller.test.ts +0 -129
  121. package/src/core/types.ts +0 -324
  122. package/src/core/typing-controller.ts +0 -119
  123. package/src/cron/config.ts +0 -154
  124. package/src/cron/schedule.ts +0 -61
  125. package/src/cron/service.ts +0 -249
  126. package/src/cron/store.ts +0 -155
  127. package/src/cron/types.ts +0 -60
  128. package/src/extension/loader.ts +0 -145
  129. package/src/extension/manager.ts +0 -355
  130. package/src/extension/manifest.ts +0 -26
  131. package/src/extension/registry.ts +0 -229
  132. package/src/main.ts +0 -8
  133. package/src/sandbox/executor.ts +0 -44
  134. package/src/sandbox/host-executor.ts +0 -118
  135. package/src/shared/dobby-repo.ts +0 -48
  136. package/tsconfig.json +0 -18
@@ -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
- }