botinabox 2.5.2 → 2.6.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.
Files changed (277) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +190 -190
  3. package/bin/botinabox.mjs +1 -1
  4. package/dist/{chunk-UACT2WXX.js → chunk-7AGWGYZC.js} +43 -5
  5. package/dist/cli.js +1 -1
  6. package/dist/connectors/google/index.d.ts +10 -1
  7. package/dist/connectors/google/index.js +1 -1
  8. package/dist/{gmail-connector-2FVYTQJH.js → gmail-connector-VP5FF56J.js} +2 -1
  9. package/dist/index.d.ts +64 -1
  10. package/dist/index.js +44 -10
  11. package/package.json +100 -100
  12. package/dist/channels/discord/adapter.d.ts +0 -32
  13. package/dist/channels/discord/adapter.js +0 -70
  14. package/dist/channels/discord/inbound.d.ts +0 -25
  15. package/dist/channels/discord/inbound.js +0 -24
  16. package/dist/channels/discord/models.d.ts +0 -8
  17. package/dist/channels/discord/models.js +0 -5
  18. package/dist/channels/discord/outbound.d.ts +0 -14
  19. package/dist/channels/discord/outbound.js +0 -38
  20. package/dist/channels/slack/adapter.d.ts +0 -33
  21. package/dist/channels/slack/adapter.js +0 -74
  22. package/dist/channels/slack/inbound.d.ts +0 -59
  23. package/dist/channels/slack/inbound.js +0 -96
  24. package/dist/channels/slack/models.d.ts +0 -9
  25. package/dist/channels/slack/models.js +0 -5
  26. package/dist/channels/slack/outbound.d.ts +0 -12
  27. package/dist/channels/slack/outbound.js +0 -18
  28. package/dist/channels/slack/transcribe.d.ts +0 -41
  29. package/dist/channels/slack/transcribe.js +0 -106
  30. package/dist/channels/webhook/adapter.d.ts +0 -23
  31. package/dist/channels/webhook/adapter.js +0 -86
  32. package/dist/channels/webhook/hmac.d.ts +0 -13
  33. package/dist/channels/webhook/hmac.js +0 -26
  34. package/dist/channels/webhook/models.d.ts +0 -9
  35. package/dist/channels/webhook/models.js +0 -5
  36. package/dist/channels/webhook/server.d.ts +0 -20
  37. package/dist/channels/webhook/server.js +0 -91
  38. package/dist/chat-pipeline-C-XlLGNl.d.ts +0 -648
  39. package/dist/chat-pipeline-CR1KF6eX.d.ts +0 -652
  40. package/dist/chat-pipeline-DisuC8SB.d.ts +0 -643
  41. package/dist/chunk-2LGXQPEA.js +0 -41
  42. package/dist/chunk-3X3YKI4T.js +0 -357
  43. package/dist/chunk-D47AIFOD.js +0 -351
  44. package/dist/chunk-DSNJKNEW.js +0 -328
  45. package/dist/chunk-GS2JFL6I.js +0 -144
  46. package/dist/chunk-J6S6QMUY.js +0 -144
  47. package/dist/chunk-QLA6YOFN.js +0 -22
  48. package/dist/cli/templates/config.yml.d.ts +0 -7
  49. package/dist/cli/templates/config.yml.js +0 -61
  50. package/dist/cli/templates/env.d.ts +0 -1
  51. package/dist/cli/templates/env.js +0 -30
  52. package/dist/cli/templates/index.ts.d.ts +0 -2
  53. package/dist/cli/templates/index.ts.js +0 -30
  54. package/dist/cli/templates/package.json.d.ts +0 -5
  55. package/dist/cli/templates/package.json.js +0 -28
  56. package/dist/connector-DDahQw-2.d.ts +0 -63
  57. package/dist/connectors/google/calendar-connector.d.ts +0 -40
  58. package/dist/connectors/google/calendar-connector.js +0 -243
  59. package/dist/connectors/google/gmail-connector.d.ts +0 -42
  60. package/dist/connectors/google/gmail-connector.js +0 -345
  61. package/dist/connectors/google/oauth.d.ts +0 -48
  62. package/dist/connectors/google/oauth.js +0 -112
  63. package/dist/connectors/google/types.d.ts +0 -78
  64. package/dist/connectors/google/types.js +0 -2
  65. package/dist/core/chat/auto-discovery.d.ts +0 -16
  66. package/dist/core/chat/auto-discovery.js +0 -54
  67. package/dist/core/chat/channel-registry.d.ts +0 -45
  68. package/dist/core/chat/channel-registry.js +0 -96
  69. package/dist/core/chat/chat-pipeline.d.ts +0 -113
  70. package/dist/core/chat/chat-pipeline.js +0 -395
  71. package/dist/core/chat/chat-responder.d.ts +0 -90
  72. package/dist/core/chat/chat-responder.js +0 -185
  73. package/dist/core/chat/formatter.d.ts +0 -11
  74. package/dist/core/chat/formatter.js +0 -60
  75. package/dist/core/chat/index.d.ts +0 -24
  76. package/dist/core/chat/index.js +0 -18
  77. package/dist/core/chat/message-interpreter.d.ts +0 -91
  78. package/dist/core/chat/message-interpreter.js +0 -166
  79. package/dist/core/chat/message-store.d.ts +0 -66
  80. package/dist/core/chat/message-store.js +0 -131
  81. package/dist/core/chat/notification-queue.d.ts +0 -34
  82. package/dist/core/chat/notification-queue.js +0 -111
  83. package/dist/core/chat/pipeline.d.ts +0 -38
  84. package/dist/core/chat/pipeline.js +0 -89
  85. package/dist/core/chat/policies.d.ts +0 -16
  86. package/dist/core/chat/policies.js +0 -25
  87. package/dist/core/chat/routing.d.ts +0 -17
  88. package/dist/core/chat/routing.js +0 -36
  89. package/dist/core/chat/session-key.d.ts +0 -30
  90. package/dist/core/chat/session-key.js +0 -65
  91. package/dist/core/chat/session-manager.d.ts +0 -17
  92. package/dist/core/chat/session-manager.js +0 -23
  93. package/dist/core/chat/text-chunker.d.ts +0 -9
  94. package/dist/core/chat/text-chunker.js +0 -48
  95. package/dist/core/chat/triage-router.d.ts +0 -75
  96. package/dist/core/chat/triage-router.js +0 -142
  97. package/dist/core/chat/types.d.ts +0 -5
  98. package/dist/core/chat/types.js +0 -5
  99. package/dist/core/config/defaults.d.ts +0 -2
  100. package/dist/core/config/defaults.js +0 -38
  101. package/dist/core/config/index.d.ts +0 -6
  102. package/dist/core/config/index.js +0 -4
  103. package/dist/core/config/interpolate.d.ts +0 -5
  104. package/dist/core/config/interpolate.js +0 -27
  105. package/dist/core/config/loader.d.ts +0 -24
  106. package/dist/core/config/loader.js +0 -59
  107. package/dist/core/config/schema.d.ts +0 -5
  108. package/dist/core/config/schema.js +0 -119
  109. package/dist/core/data/core-entity-contexts.d.ts +0 -14
  110. package/dist/core/data/core-entity-contexts.js +0 -197
  111. package/dist/core/data/core-migrations.d.ts +0 -5
  112. package/dist/core/data/core-migrations.js +0 -45
  113. package/dist/core/data/core-schema.d.ts +0 -6
  114. package/dist/core/data/core-schema.js +0 -454
  115. package/dist/core/data/data-store.d.ts +0 -67
  116. package/dist/core/data/data-store.js +0 -218
  117. package/dist/core/data/domain-entity-contexts.d.ts +0 -29
  118. package/dist/core/data/domain-entity-contexts.js +0 -321
  119. package/dist/core/data/domain-schema.d.ts +0 -36
  120. package/dist/core/data/domain-schema.js +0 -323
  121. package/dist/core/data/index.d.ts +0 -7
  122. package/dist/core/data/index.js +0 -7
  123. package/dist/core/data/types.d.ts +0 -111
  124. package/dist/core/data/types.js +0 -1
  125. package/dist/core/hooks/hook-bus.d.ts +0 -18
  126. package/dist/core/hooks/hook-bus.js +0 -120
  127. package/dist/core/hooks/index.d.ts +0 -2
  128. package/dist/core/hooks/index.js +0 -1
  129. package/dist/core/hooks/types.d.ts +0 -19
  130. package/dist/core/hooks/types.js +0 -1
  131. package/dist/core/index.d.ts +0 -4
  132. package/dist/core/index.js +0 -4
  133. package/dist/core/llm/auto-discovery.d.ts +0 -11
  134. package/dist/core/llm/auto-discovery.js +0 -49
  135. package/dist/core/llm/cost-tracker.d.ts +0 -6
  136. package/dist/core/llm/cost-tracker.js +0 -38
  137. package/dist/core/llm/index.d.ts +0 -4
  138. package/dist/core/llm/index.js +0 -3
  139. package/dist/core/llm/model-router.d.ts +0 -25
  140. package/dist/core/llm/model-router.js +0 -49
  141. package/dist/core/llm/provider-registry.d.ts +0 -9
  142. package/dist/core/llm/provider-registry.js +0 -25
  143. package/dist/core/llm/types.d.ts +0 -2
  144. package/dist/core/llm/types.js +0 -2
  145. package/dist/core/orchestrator/adapters/api-adapter.d.ts +0 -34
  146. package/dist/core/orchestrator/adapters/api-adapter.js +0 -88
  147. package/dist/core/orchestrator/adapters/cli-adapter.d.ts +0 -22
  148. package/dist/core/orchestrator/adapters/cli-adapter.js +0 -69
  149. package/dist/core/orchestrator/adapters/deterministic-adapter.d.ts +0 -35
  150. package/dist/core/orchestrator/adapters/deterministic-adapter.js +0 -75
  151. package/dist/core/orchestrator/adapters/env-whitelist.d.ts +0 -4
  152. package/dist/core/orchestrator/adapters/env-whitelist.js +0 -27
  153. package/dist/core/orchestrator/adapters/output-extractor.d.ts +0 -11
  154. package/dist/core/orchestrator/adapters/output-extractor.js +0 -59
  155. package/dist/core/orchestrator/adapters/process-manager.d.ts +0 -15
  156. package/dist/core/orchestrator/adapters/process-manager.js +0 -26
  157. package/dist/core/orchestrator/adapters/tool-loop.d.ts +0 -22
  158. package/dist/core/orchestrator/adapters/tool-loop.js +0 -66
  159. package/dist/core/orchestrator/agent-registry.d.ts +0 -31
  160. package/dist/core/orchestrator/agent-registry.js +0 -135
  161. package/dist/core/orchestrator/budget-controller.d.ts +0 -19
  162. package/dist/core/orchestrator/budget-controller.js +0 -73
  163. package/dist/core/orchestrator/chain-guard.d.ts +0 -14
  164. package/dist/core/orchestrator/chain-guard.js +0 -23
  165. package/dist/core/orchestrator/circuit-breaker.d.ts +0 -65
  166. package/dist/core/orchestrator/circuit-breaker.js +0 -159
  167. package/dist/core/orchestrator/claude-stream-parser.d.ts +0 -31
  168. package/dist/core/orchestrator/claude-stream-parser.js +0 -99
  169. package/dist/core/orchestrator/config-revisions.d.ts +0 -6
  170. package/dist/core/orchestrator/config-revisions.js +0 -17
  171. package/dist/core/orchestrator/dependency-resolver.d.ts +0 -20
  172. package/dist/core/orchestrator/dependency-resolver.js +0 -78
  173. package/dist/core/orchestrator/governance-gate.d.ts +0 -110
  174. package/dist/core/orchestrator/governance-gate.js +0 -170
  175. package/dist/core/orchestrator/learning-pipeline.d.ts +0 -109
  176. package/dist/core/orchestrator/learning-pipeline.js +0 -249
  177. package/dist/core/orchestrator/loop-detector.d.ts +0 -51
  178. package/dist/core/orchestrator/loop-detector.js +0 -133
  179. package/dist/core/orchestrator/ndjson-logger.d.ts +0 -6
  180. package/dist/core/orchestrator/ndjson-logger.js +0 -18
  181. package/dist/core/orchestrator/permission-relay.d.ts +0 -72
  182. package/dist/core/orchestrator/permission-relay.js +0 -164
  183. package/dist/core/orchestrator/run-manager.d.ts +0 -31
  184. package/dist/core/orchestrator/run-manager.js +0 -178
  185. package/dist/core/orchestrator/scheduler.d.ts +0 -70
  186. package/dist/core/orchestrator/scheduler.js +0 -198
  187. package/dist/core/orchestrator/secret-store.d.ts +0 -57
  188. package/dist/core/orchestrator/secret-store.js +0 -171
  189. package/dist/core/orchestrator/session-manager.d.ts +0 -13
  190. package/dist/core/orchestrator/session-manager.js +0 -66
  191. package/dist/core/orchestrator/task-queue.d.ts +0 -34
  192. package/dist/core/orchestrator/task-queue.js +0 -83
  193. package/dist/core/orchestrator/template-interpolate.d.ts +0 -5
  194. package/dist/core/orchestrator/template-interpolate.js +0 -18
  195. package/dist/core/orchestrator/user-registry.d.ts +0 -47
  196. package/dist/core/orchestrator/user-registry.js +0 -76
  197. package/dist/core/orchestrator/wakeup-queue.d.ts +0 -9
  198. package/dist/core/orchestrator/wakeup-queue.js +0 -45
  199. package/dist/core/orchestrator/workflow-engine.d.ts +0 -47
  200. package/dist/core/orchestrator/workflow-engine.js +0 -204
  201. package/dist/core/security/audit.d.ts +0 -20
  202. package/dist/core/security/audit.js +0 -33
  203. package/dist/core/security/column-validator.d.ts +0 -20
  204. package/dist/core/security/column-validator.js +0 -37
  205. package/dist/core/security/index.d.ts +0 -5
  206. package/dist/core/security/index.js +0 -5
  207. package/dist/core/security/process-env.d.ts +0 -13
  208. package/dist/core/security/process-env.js +0 -49
  209. package/dist/core/security/sanitizer.d.ts +0 -11
  210. package/dist/core/security/sanitizer.js +0 -39
  211. package/dist/core/security/types.d.ts +0 -11
  212. package/dist/core/security/types.js +0 -1
  213. package/dist/core/update/auto-update.d.ts +0 -21
  214. package/dist/core/update/auto-update.js +0 -102
  215. package/dist/core/update/backup-manager.d.ts +0 -7
  216. package/dist/core/update/backup-manager.js +0 -24
  217. package/dist/core/update/index.d.ts +0 -8
  218. package/dist/core/update/index.js +0 -6
  219. package/dist/core/update/migration-hooks.d.ts +0 -11
  220. package/dist/core/update/migration-hooks.js +0 -10
  221. package/dist/core/update/types.d.ts +0 -11
  222. package/dist/core/update/types.js +0 -1
  223. package/dist/core/update/update-checker.d.ts +0 -11
  224. package/dist/core/update/update-checker.js +0 -63
  225. package/dist/core/update/update-manager.d.ts +0 -25
  226. package/dist/core/update/update-manager.js +0 -101
  227. package/dist/core/update/version-utils.d.ts +0 -6
  228. package/dist/core/update/version-utils.js +0 -34
  229. package/dist/gmail-connector-MNUBRNFM.js +0 -6
  230. package/dist/gmail-connector-PS2VLGNE.js +0 -6
  231. package/dist/gmail-connector-ULSMN6X2.js +0 -6
  232. package/dist/gmail-connector-URRFX6A3.js +0 -6
  233. package/dist/inbound-AFBUPSPG.js +0 -10
  234. package/dist/inbound-AFOHYNUY.js +0 -6
  235. package/dist/inbound-CGIXRXGC.js +0 -8
  236. package/dist/inbound-MCOLRH6U.js +0 -10
  237. package/dist/inbound-SNEMBLGA.js +0 -6
  238. package/dist/inbound-ZJHAYVMF.js +0 -10
  239. package/dist/provider-qqJYv9nv.d.ts +0 -75
  240. package/dist/providers/anthropic/models.d.ts +0 -2
  241. package/dist/providers/anthropic/models.js +0 -29
  242. package/dist/providers/anthropic/provider.d.ts +0 -13
  243. package/dist/providers/anthropic/provider.js +0 -119
  244. package/dist/providers/anthropic/tool-converter.d.ts +0 -10
  245. package/dist/providers/anthropic/tool-converter.js +0 -7
  246. package/dist/providers/ollama/provider.d.ts +0 -17
  247. package/dist/providers/ollama/provider.js +0 -185
  248. package/dist/providers/openai/models.d.ts +0 -2
  249. package/dist/providers/openai/models.js +0 -29
  250. package/dist/providers/openai/provider.d.ts +0 -13
  251. package/dist/providers/openai/provider.js +0 -163
  252. package/dist/providers/openai/tool-converter.d.ts +0 -10
  253. package/dist/providers/openai/tool-converter.js +0 -10
  254. package/dist/shared/constants.d.ts +0 -50
  255. package/dist/shared/constants.js +0 -64
  256. package/dist/shared/index.d.ts +0 -14
  257. package/dist/shared/index.js +0 -14
  258. package/dist/shared/types/agent.d.ts +0 -36
  259. package/dist/shared/types/agent.js +0 -2
  260. package/dist/shared/types/channel.d.ts +0 -70
  261. package/dist/shared/types/channel.js +0 -2
  262. package/dist/shared/types/config.d.ts +0 -111
  263. package/dist/shared/types/config.js +0 -2
  264. package/dist/shared/types/connector.d.ts +0 -77
  265. package/dist/shared/types/connector.js +0 -2
  266. package/dist/shared/types/execution.d.ts +0 -29
  267. package/dist/shared/types/execution.js +0 -2
  268. package/dist/shared/types/provider.d.ts +0 -73
  269. package/dist/shared/types/provider.js +0 -2
  270. package/dist/shared/types/task.d.ts +0 -47
  271. package/dist/shared/types/task.js +0 -2
  272. package/dist/shared/types/workflow.d.ts +0 -39
  273. package/dist/shared/types/workflow.js +0 -2
  274. package/dist/shared/utils.d.ts +0 -6
  275. package/dist/shared/utils.js +0 -13
  276. package/dist/update-check.d.ts +0 -5
  277. package/dist/update-check.js +0 -56
@@ -1,31 +0,0 @@
1
- import type { DataStore } from '../data/data-store.js';
2
- import type { HookBus } from '../hooks/hook-bus.js';
3
- import type { CircuitBreaker } from './circuit-breaker.js';
4
- export declare class RunManager {
5
- private db;
6
- private hooks;
7
- private config?;
8
- private locks;
9
- private orphanTimer;
10
- private readonly staleThresholdMs;
11
- private circuitBreaker?;
12
- constructor(db: DataStore, hooks: HookBus, config?: {
13
- staleThresholdMs?: number;
14
- maxBackoffMs?: number;
15
- } | undefined);
16
- /**
17
- * Attach a CircuitBreaker to prevent retries on broken agents.
18
- */
19
- setCircuitBreaker(cb: CircuitBreaker): void;
20
- isLocked(agentId: string): boolean;
21
- startRun(agentId: string, taskId: string, adapter?: string): Promise<string>;
22
- finishRun(runId: string, result: {
23
- exitCode: number;
24
- output?: string;
25
- costCents?: number;
26
- usage?: unknown;
27
- }): Promise<void>;
28
- reapOrphans(): Promise<void>;
29
- startOrphanReaper(intervalMs?: number): void;
30
- stopOrphanReaper(): void;
31
- }
@@ -1,178 +0,0 @@
1
- import { checkChainDepth, MAX_CHAIN_DEPTH } from './chain-guard.js';
2
- import { interpolate } from './template-interpolate.js';
3
- const DEFAULT_STALE_THRESHOLD_MS = 30 * 60 * 1000; // 30 minutes
4
- const BASE_BACKOFF_MS = 5_000;
5
- const DEFAULT_MAX_BACKOFF_MS = 5 * 60 * 1000; // 5 minutes
6
- export class RunManager {
7
- db;
8
- hooks;
9
- config;
10
- locks = new Map(); // agentId → runId
11
- orphanTimer = null;
12
- staleThresholdMs;
13
- circuitBreaker;
14
- constructor(db, hooks, config) {
15
- this.db = db;
16
- this.hooks = hooks;
17
- this.config = config;
18
- this.staleThresholdMs = config?.staleThresholdMs ?? DEFAULT_STALE_THRESHOLD_MS;
19
- }
20
- /**
21
- * Attach a CircuitBreaker to prevent retries on broken agents.
22
- */
23
- setCircuitBreaker(cb) {
24
- this.circuitBreaker = cb;
25
- }
26
- isLocked(agentId) {
27
- return this.locks.has(agentId);
28
- }
29
- async startRun(agentId, taskId, adapter) {
30
- if (this.locks.has(agentId)) {
31
- throw new Error(`Agent already has an active run`);
32
- }
33
- const row = await this.db.insert('runs', {
34
- agent_id: agentId,
35
- task_id: taskId,
36
- adapter: adapter,
37
- status: 'running',
38
- started_at: new Date().toISOString(),
39
- });
40
- const runId = row['id'];
41
- this.locks.set(agentId, runId);
42
- return runId;
43
- }
44
- async finishRun(runId, result) {
45
- const run = await this.db.get('runs', { id: runId });
46
- if (!run)
47
- throw new Error(`Run not found: ${runId}`);
48
- const succeeded = result.exitCode === 0;
49
- const status = succeeded ? 'succeeded' : 'failed';
50
- const usage = result.usage;
51
- await this.db.update('runs', { id: runId }, {
52
- status,
53
- completed_at: new Date().toISOString(),
54
- exit_code: result.exitCode,
55
- cost_cents: result.costCents ?? 0,
56
- input_tokens: usage?.['inputTokens'] ?? 0,
57
- output_tokens: usage?.['outputTokens'] ?? 0,
58
- error_message: result.exitCode !== 0 ? result.output : undefined,
59
- });
60
- // Release lock
61
- const agentId = run['agent_id'];
62
- this.locks.delete(agentId);
63
- const taskId = run['task_id'];
64
- if (!succeeded) {
65
- // Record failure in circuit breaker (if attached)
66
- if (this.circuitBreaker) {
67
- await this.circuitBreaker.recordFailure(agentId, result.output);
68
- }
69
- // Retry policy — skip retry if circuit breaker is open
70
- const task = await this.db.get('tasks', { id: taskId });
71
- if (task) {
72
- const retryCount = task['retry_count'] ?? 0;
73
- const maxRetries = task['max_retries'] ?? 0;
74
- const circuitOpen = this.circuitBreaker
75
- ? !this.circuitBreaker.canExecute(agentId)
76
- : false;
77
- if (retryCount < maxRetries && !circuitOpen) {
78
- // Exponential backoff: BASE_BACKOFF_MS * 2^retryCount
79
- const maxBackoff = this.config?.maxBackoffMs ?? DEFAULT_MAX_BACKOFF_MS;
80
- const backoffMs = Math.min(BASE_BACKOFF_MS * Math.pow(2, retryCount), maxBackoff);
81
- const nextRetryAt = new Date(Date.now() + backoffMs).toISOString();
82
- await this.db.update('tasks', { id: taskId }, {
83
- retry_count: retryCount + 1,
84
- next_retry_at: nextRetryAt,
85
- status: 'todo',
86
- execution_run_id: null,
87
- updated_at: new Date().toISOString(),
88
- });
89
- }
90
- else {
91
- // Retries exhausted or circuit open — mark task as failed
92
- await this.db.update('tasks', { id: taskId }, {
93
- status: 'failed',
94
- updated_at: new Date().toISOString(),
95
- });
96
- }
97
- }
98
- }
99
- else {
100
- // Record success in circuit breaker (if attached)
101
- if (this.circuitBreaker) {
102
- await this.circuitBreaker.recordSuccess(agentId);
103
- }
104
- // Mark task done with result before emitting run.completed,
105
- // so hook handlers can read task.result immediately.
106
- await this.db.update('tasks', { id: taskId }, {
107
- status: 'done',
108
- result: result.output,
109
- updated_at: new Date().toISOString(),
110
- });
111
- // Followup chain
112
- const task = await this.db.get('tasks', { id: taskId });
113
- if (task && task['followup_agent_id']) {
114
- const chainDepth = (task['chain_depth'] ?? 0) + 1;
115
- checkChainDepth(chainDepth, MAX_CHAIN_DEPTH);
116
- const followupAgentId = task['followup_agent_id'];
117
- const followupTemplate = task['followup_template'] ?? 'Followup: {{output}}';
118
- const context = { output: result.output ?? '' };
119
- const title = interpolate(followupTemplate, context);
120
- const chainOriginId = task['chain_origin_id'] ?? taskId;
121
- await this.db.insert('tasks', {
122
- title,
123
- description: title,
124
- assignee_id: followupAgentId,
125
- status: 'todo',
126
- priority: task['priority'] ?? 5,
127
- chain_depth: chainDepth,
128
- chain_origin_id: chainOriginId,
129
- });
130
- await this.hooks.emit('task.followup.created', {
131
- originTaskId: taskId,
132
- followupAgentId,
133
- chainDepth,
134
- });
135
- }
136
- }
137
- await this.hooks.emit('run.completed', {
138
- runId,
139
- agentId,
140
- taskId,
141
- status,
142
- exitCode: result.exitCode,
143
- });
144
- }
145
- async reapOrphans() {
146
- const cutoff = new Date(Date.now() - this.staleThresholdMs).toISOString();
147
- const staleRuns = (await this.db.query('runs', { where: { status: 'running' } }))
148
- .filter((r) => {
149
- const startedAt = r['started_at'];
150
- return startedAt != null && startedAt < cutoff;
151
- });
152
- for (const run of staleRuns) {
153
- await this.db.update('runs', { id: run['id'] }, {
154
- status: 'failed',
155
- completed_at: new Date().toISOString(),
156
- error_message: 'Orphaned run reaped by RunManager',
157
- });
158
- // Release in-memory lock if we hold it
159
- const agentId = run['agent_id'];
160
- if (this.locks.get(agentId) === run['id']) {
161
- this.locks.delete(agentId);
162
- }
163
- }
164
- }
165
- startOrphanReaper(intervalMs = 60_000) {
166
- if (this.orphanTimer)
167
- return;
168
- this.orphanTimer = setInterval(() => {
169
- void this.reapOrphans();
170
- }, intervalMs);
171
- }
172
- stopOrphanReaper() {
173
- if (this.orphanTimer) {
174
- clearInterval(this.orphanTimer);
175
- this.orphanTimer = null;
176
- }
177
- }
178
- }
@@ -1,70 +0,0 @@
1
- /**
2
- * Scheduler — database-backed job scheduling with cron expressions.
3
- *
4
- * Supports one-time and recurring schedules. When a schedule fires,
5
- * it emits the schedule's `action` as a hook event with the
6
- * `action_config` payload. Consumers subscribe to handle the action.
7
- *
8
- * Supports one-time and recurring use cases.
9
- */
10
- import type { DataStore } from "../data/data-store.js";
11
- import type { HookBus } from "../hooks/hook-bus.js";
12
- export interface ScheduleDef {
13
- name: string;
14
- description?: string;
15
- /** Cron expression for recurring schedules */
16
- cron?: string;
17
- /** ISO 8601 datetime for one-time schedules */
18
- runAt?: string;
19
- /** Hook event name to emit when fired */
20
- action: string;
21
- /** JSON-serializable payload passed to the hook */
22
- actionConfig?: Record<string, unknown>;
23
- timezone?: string;
24
- }
25
- export interface Schedule {
26
- id: string;
27
- name: string;
28
- description: string | null;
29
- type: "one_time" | "recurring";
30
- cron: string | null;
31
- run_at: string | null;
32
- timezone: string;
33
- enabled: number;
34
- action: string;
35
- action_config: string;
36
- last_fired_at: string | null;
37
- next_fire_at: string | null;
38
- created_at: string;
39
- updated_at: string;
40
- deleted_at: string | null;
41
- }
42
- export declare class Scheduler {
43
- private db;
44
- private hooks;
45
- private timer;
46
- constructor(db: DataStore, hooks: HookBus);
47
- /**
48
- * Start the scheduler. Computes initial next_fire_at for schedules
49
- * that don't have one, then polls for due schedules.
50
- */
51
- start(pollIntervalMs?: number): Promise<void>;
52
- stop(): void;
53
- /** Check for and fire due schedules. */
54
- tick(): Promise<void>;
55
- /** Register a new schedule. */
56
- register(def: ScheduleDef): Promise<string>;
57
- /** Update an existing schedule. */
58
- update(id: string, changes: Partial<Pick<ScheduleDef, "name" | "cron" | "runAt" | "action" | "actionConfig" | "timezone" | "description">> & {
59
- enabled?: boolean;
60
- }): Promise<void>;
61
- /** Soft-delete a schedule. */
62
- unregister(id: string): Promise<void>;
63
- /** List schedules, optionally filtered. */
64
- list(filter?: {
65
- enabled?: boolean;
66
- action?: string;
67
- }): Promise<Schedule[]>;
68
- /** Compute next_fire_at for any enabled schedule missing it. */
69
- private initializeNextFireTimes;
70
- }
@@ -1,198 +0,0 @@
1
- /**
2
- * Scheduler — database-backed job scheduling with cron expressions.
3
- *
4
- * Supports one-time and recurring schedules. When a schedule fires,
5
- * it emits the schedule's `action` as a hook event with the
6
- * `action_config` payload. Consumers subscribe to handle the action.
7
- *
8
- * Supports one-time and recurring use cases.
9
- */
10
- import cronParser from "cron-parser";
11
- import { v4 as uuid } from "uuid";
12
- function computeNextFire(cron, timezone, after) {
13
- const interval = cronParser.parseExpression(cron, {
14
- currentDate: after ?? new Date(),
15
- tz: timezone,
16
- });
17
- return interval.next().toISOString();
18
- }
19
- export class Scheduler {
20
- db;
21
- hooks;
22
- timer = null;
23
- constructor(db, hooks) {
24
- this.db = db;
25
- this.hooks = hooks;
26
- }
27
- /**
28
- * Start the scheduler. Computes initial next_fire_at for schedules
29
- * that don't have one, then polls for due schedules.
30
- */
31
- async start(pollIntervalMs = 30_000) {
32
- await this.initializeNextFireTimes();
33
- this.timer = setInterval(() => {
34
- void this.tick();
35
- }, pollIntervalMs);
36
- // Fire immediately on start
37
- void this.tick();
38
- }
39
- stop() {
40
- if (this.timer) {
41
- clearInterval(this.timer);
42
- this.timer = null;
43
- }
44
- }
45
- /** Check for and fire due schedules. */
46
- async tick() {
47
- const now = new Date().toISOString();
48
- const schedules = (await this.db.query("schedules", {
49
- where: { enabled: 1 },
50
- })).filter((s) => s["deleted_at"] == null &&
51
- s["next_fire_at"] != null &&
52
- s["next_fire_at"] <= now);
53
- for (const schedule of schedules) {
54
- try {
55
- const config = JSON.parse(schedule.action_config || "{}");
56
- // Filter prototype pollution vectors
57
- const safeConfig = {};
58
- for (const [k, v] of Object.entries(config)) {
59
- if (!k.startsWith('__'))
60
- safeConfig[k] = v;
61
- }
62
- // Emit the action hook (e.g. 'connector.sync', 'channel.send')
63
- await this.hooks.emit(schedule.action, {
64
- schedule_id: schedule.id,
65
- schedule_name: schedule.name,
66
- ...safeConfig,
67
- });
68
- // Emit observability hook
69
- await this.hooks.emit("schedule.fired", {
70
- schedule_id: schedule.id,
71
- schedule_name: schedule.name,
72
- action: schedule.action,
73
- fired_at: now,
74
- });
75
- // Update last_fired_at and compute next
76
- if (schedule.type === "recurring" && schedule.cron) {
77
- const nextFire = computeNextFire(schedule.cron, schedule.timezone, new Date());
78
- await this.db.update("schedules", { id: schedule.id }, {
79
- last_fired_at: now,
80
- next_fire_at: nextFire,
81
- updated_at: now,
82
- });
83
- }
84
- else {
85
- // One-time: disable after firing
86
- await this.db.update("schedules", { id: schedule.id }, {
87
- last_fired_at: now,
88
- next_fire_at: null,
89
- enabled: 0,
90
- updated_at: now,
91
- });
92
- }
93
- }
94
- catch (err) {
95
- console.error(`[Scheduler] Error firing schedule "${schedule.name}":`, err);
96
- await this.hooks.emit("schedule.error", {
97
- schedule_id: schedule.id,
98
- schedule_name: schedule.name,
99
- error: String(err),
100
- });
101
- }
102
- }
103
- }
104
- /** Register a new schedule. */
105
- async register(def) {
106
- const id = uuid();
107
- const type = def.cron ? "recurring" : "one_time";
108
- const timezone = def.timezone ?? "UTC";
109
- let nextFire = null;
110
- if (def.cron) {
111
- nextFire = computeNextFire(def.cron, timezone);
112
- }
113
- else if (def.runAt) {
114
- nextFire = new Date(def.runAt).toISOString();
115
- }
116
- await this.db.insert("schedules", {
117
- id,
118
- name: def.name,
119
- description: def.description ?? null,
120
- type,
121
- cron: def.cron ?? null,
122
- run_at: def.runAt ?? null,
123
- timezone,
124
- enabled: 1,
125
- action: def.action,
126
- action_config: JSON.stringify(def.actionConfig ?? {}),
127
- next_fire_at: nextFire,
128
- });
129
- return id;
130
- }
131
- /** Update an existing schedule. */
132
- async update(id, changes) {
133
- const row = {
134
- updated_at: new Date().toISOString(),
135
- };
136
- if (changes.name !== undefined)
137
- row["name"] = changes.name;
138
- if (changes.description !== undefined)
139
- row["description"] = changes.description;
140
- if (changes.action !== undefined)
141
- row["action"] = changes.action;
142
- if (changes.actionConfig !== undefined)
143
- row["action_config"] = JSON.stringify(changes.actionConfig);
144
- if (changes.enabled !== undefined)
145
- row["enabled"] = changes.enabled ? 1 : 0;
146
- if (changes.cron !== undefined) {
147
- row["cron"] = changes.cron;
148
- row["type"] = "recurring";
149
- row["run_at"] = null;
150
- row["next_fire_at"] = computeNextFire(changes.cron, changes.timezone ?? "UTC");
151
- }
152
- else if (changes.runAt !== undefined) {
153
- row["run_at"] = changes.runAt;
154
- row["type"] = "one_time";
155
- row["cron"] = null;
156
- row["next_fire_at"] = new Date(changes.runAt).toISOString();
157
- }
158
- if (changes.timezone !== undefined)
159
- row["timezone"] = changes.timezone;
160
- await this.db.update("schedules", { id }, row);
161
- }
162
- /** Soft-delete a schedule. */
163
- async unregister(id) {
164
- await this.db.update("schedules", { id }, {
165
- enabled: 0,
166
- deleted_at: new Date().toISOString(),
167
- updated_at: new Date().toISOString(),
168
- });
169
- }
170
- /** List schedules, optionally filtered. */
171
- async list(filter) {
172
- const where = {};
173
- if (filter?.enabled !== undefined)
174
- where["enabled"] = filter.enabled ? 1 : 0;
175
- if (filter?.action !== undefined)
176
- where["action"] = filter.action;
177
- return (await this.db.query("schedules", { where })).filter((s) => s["deleted_at"] == null);
178
- }
179
- /** Compute next_fire_at for any enabled schedule missing it. */
180
- async initializeNextFireTimes() {
181
- const schedules = (await this.db.query("schedules", { where: { enabled: 1 } })).filter((s) => s["deleted_at"] == null && s["next_fire_at"] == null);
182
- for (const s of schedules) {
183
- let nextFire = null;
184
- if (s.type === "recurring" && s.cron) {
185
- nextFire = computeNextFire(s.cron, s.timezone);
186
- }
187
- else if (s.type === "one_time" && s.run_at) {
188
- nextFire = new Date(s.run_at).toISOString();
189
- }
190
- if (nextFire) {
191
- await this.db.update("schedules", { id: s.id }, {
192
- next_fire_at: nextFire,
193
- updated_at: new Date().toISOString(),
194
- });
195
- }
196
- }
197
- }
198
- }
@@ -1,57 +0,0 @@
1
- import type { DataStore } from "../data/data-store.js";
2
- import type { HookBus } from "../hooks/hook-bus.js";
3
- export interface SecretInput {
4
- name: string;
5
- type?: string;
6
- environment?: string;
7
- value?: string;
8
- location?: string;
9
- description?: string;
10
- rotation_schedule?: string;
11
- expires_at?: string;
12
- notes?: string;
13
- org_id?: string;
14
- }
15
- export interface SecretMeta {
16
- id: string;
17
- org_id: string | null;
18
- name: string;
19
- type: string;
20
- environment: string;
21
- location: string | null;
22
- description: string | null;
23
- rotation_schedule: string | null;
24
- expires_at: string | null;
25
- notes: string | null;
26
- created_at: string;
27
- updated_at: string;
28
- }
29
- export declare class SecretStore {
30
- private readonly db;
31
- private readonly hooks;
32
- private readonly encKey;
33
- /**
34
- * @param db - DataStore instance
35
- * @param hooks - HookBus instance
36
- * @param encryptionKey - Optional master key for encrypting secrets at rest.
37
- * When provided, all new secrets are encrypted with AES-256-GCM.
38
- * Existing plaintext secrets are read transparently (passthrough on decrypt).
39
- */
40
- constructor(db: DataStore, hooks: HookBus, encryptionKey?: string);
41
- set(input: SecretInput): Promise<SecretMeta>;
42
- get(name: string, environment?: string): Promise<string | null>;
43
- getMeta(name: string, environment?: string): Promise<SecretMeta | null>;
44
- list(): Promise<SecretMeta[]>;
45
- rotate(name: string, newValue: string, environment?: string): Promise<void>;
46
- delete(name: string, environment?: string): Promise<void>;
47
- /**
48
- * Load a sync cursor by key. Returns undefined if not found.
49
- * Cursors are stored as secrets with type='sync_cursor'.
50
- */
51
- loadCursor(key: string): Promise<string | undefined>;
52
- /**
53
- * Persist a sync cursor by key. Creates or updates the secret.
54
- */
55
- saveCursor(key: string, value: string): Promise<void>;
56
- private _toMeta;
57
- }