@usejarvis/brain 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.
Files changed (266) hide show
  1. package/LICENSE +153 -0
  2. package/README.md +278 -0
  3. package/bin/jarvis.ts +413 -0
  4. package/package.json +74 -0
  5. package/scripts/ensure-bun.cjs +8 -0
  6. package/src/actions/README.md +421 -0
  7. package/src/actions/app-control/desktop-controller.test.ts +26 -0
  8. package/src/actions/app-control/desktop-controller.ts +438 -0
  9. package/src/actions/app-control/interface.ts +64 -0
  10. package/src/actions/app-control/linux.ts +273 -0
  11. package/src/actions/app-control/macos.ts +54 -0
  12. package/src/actions/app-control/sidecar-launcher.test.ts +23 -0
  13. package/src/actions/app-control/sidecar-launcher.ts +286 -0
  14. package/src/actions/app-control/windows.ts +44 -0
  15. package/src/actions/browser/cdp.ts +138 -0
  16. package/src/actions/browser/chrome-launcher.ts +252 -0
  17. package/src/actions/browser/session.ts +437 -0
  18. package/src/actions/browser/stealth.ts +49 -0
  19. package/src/actions/index.ts +20 -0
  20. package/src/actions/terminal/executor.ts +157 -0
  21. package/src/actions/terminal/wsl-bridge.ts +126 -0
  22. package/src/actions/test.ts +93 -0
  23. package/src/actions/tools/agents.ts +321 -0
  24. package/src/actions/tools/builtin.ts +846 -0
  25. package/src/actions/tools/commitments.ts +192 -0
  26. package/src/actions/tools/content.ts +217 -0
  27. package/src/actions/tools/delegate.ts +147 -0
  28. package/src/actions/tools/desktop.test.ts +55 -0
  29. package/src/actions/tools/desktop.ts +305 -0
  30. package/src/actions/tools/goals.ts +376 -0
  31. package/src/actions/tools/local-tools-guard.ts +20 -0
  32. package/src/actions/tools/registry.ts +171 -0
  33. package/src/actions/tools/research.ts +111 -0
  34. package/src/actions/tools/sidecar-list.ts +57 -0
  35. package/src/actions/tools/sidecar-route.ts +105 -0
  36. package/src/actions/tools/workflows.ts +216 -0
  37. package/src/agents/agent.ts +132 -0
  38. package/src/agents/delegation.ts +107 -0
  39. package/src/agents/hierarchy.ts +113 -0
  40. package/src/agents/index.ts +19 -0
  41. package/src/agents/messaging.ts +125 -0
  42. package/src/agents/orchestrator.ts +576 -0
  43. package/src/agents/role-discovery.ts +61 -0
  44. package/src/agents/sub-agent-runner.ts +307 -0
  45. package/src/agents/task-manager.ts +151 -0
  46. package/src/authority/approval-delivery.ts +59 -0
  47. package/src/authority/approval.ts +196 -0
  48. package/src/authority/audit.ts +158 -0
  49. package/src/authority/authority.test.ts +519 -0
  50. package/src/authority/deferred-executor.ts +103 -0
  51. package/src/authority/emergency.ts +66 -0
  52. package/src/authority/engine.ts +297 -0
  53. package/src/authority/index.ts +12 -0
  54. package/src/authority/learning.ts +111 -0
  55. package/src/authority/tool-action-map.ts +74 -0
  56. package/src/awareness/analytics.ts +466 -0
  57. package/src/awareness/awareness.test.ts +332 -0
  58. package/src/awareness/capture-engine.ts +305 -0
  59. package/src/awareness/context-graph.ts +130 -0
  60. package/src/awareness/context-tracker.ts +349 -0
  61. package/src/awareness/index.ts +25 -0
  62. package/src/awareness/intelligence.ts +321 -0
  63. package/src/awareness/ocr-engine.ts +88 -0
  64. package/src/awareness/service.ts +528 -0
  65. package/src/awareness/struggle-detector.ts +342 -0
  66. package/src/awareness/suggestion-engine.ts +476 -0
  67. package/src/awareness/types.ts +201 -0
  68. package/src/cli/autostart.ts +241 -0
  69. package/src/cli/deps.ts +449 -0
  70. package/src/cli/doctor.ts +230 -0
  71. package/src/cli/helpers.ts +401 -0
  72. package/src/cli/onboard.ts +580 -0
  73. package/src/comms/README.md +329 -0
  74. package/src/comms/auth-error.html +48 -0
  75. package/src/comms/channels/discord.ts +228 -0
  76. package/src/comms/channels/signal.ts +56 -0
  77. package/src/comms/channels/telegram.ts +316 -0
  78. package/src/comms/channels/whatsapp.ts +60 -0
  79. package/src/comms/channels.test.ts +173 -0
  80. package/src/comms/desktop-notify.ts +114 -0
  81. package/src/comms/example.ts +129 -0
  82. package/src/comms/index.ts +129 -0
  83. package/src/comms/streaming.ts +142 -0
  84. package/src/comms/voice.test.ts +152 -0
  85. package/src/comms/voice.ts +291 -0
  86. package/src/comms/websocket.test.ts +409 -0
  87. package/src/comms/websocket.ts +473 -0
  88. package/src/config/README.md +387 -0
  89. package/src/config/index.ts +6 -0
  90. package/src/config/loader.test.ts +137 -0
  91. package/src/config/loader.ts +142 -0
  92. package/src/config/types.ts +260 -0
  93. package/src/daemon/README.md +232 -0
  94. package/src/daemon/agent-service-interface.ts +9 -0
  95. package/src/daemon/agent-service.ts +600 -0
  96. package/src/daemon/api-routes.ts +2119 -0
  97. package/src/daemon/background-agent-service.ts +396 -0
  98. package/src/daemon/background-agent.test.ts +78 -0
  99. package/src/daemon/channel-service.ts +201 -0
  100. package/src/daemon/commitment-executor.ts +297 -0
  101. package/src/daemon/event-classifier.ts +239 -0
  102. package/src/daemon/event-coalescer.ts +123 -0
  103. package/src/daemon/event-reactor.ts +214 -0
  104. package/src/daemon/health.ts +220 -0
  105. package/src/daemon/index.ts +1004 -0
  106. package/src/daemon/llm-settings.ts +316 -0
  107. package/src/daemon/observer-service.ts +150 -0
  108. package/src/daemon/pid.ts +98 -0
  109. package/src/daemon/research-queue.ts +155 -0
  110. package/src/daemon/services.ts +175 -0
  111. package/src/daemon/ws-service.ts +788 -0
  112. package/src/goals/accountability.ts +240 -0
  113. package/src/goals/awareness-bridge.ts +185 -0
  114. package/src/goals/estimator.ts +185 -0
  115. package/src/goals/events.ts +28 -0
  116. package/src/goals/goals.test.ts +400 -0
  117. package/src/goals/integration.test.ts +329 -0
  118. package/src/goals/nl-builder.test.ts +220 -0
  119. package/src/goals/nl-builder.ts +256 -0
  120. package/src/goals/rhythm.test.ts +177 -0
  121. package/src/goals/rhythm.ts +275 -0
  122. package/src/goals/service.test.ts +135 -0
  123. package/src/goals/service.ts +348 -0
  124. package/src/goals/types.ts +106 -0
  125. package/src/goals/workflow-bridge.ts +96 -0
  126. package/src/integrations/google-api.ts +134 -0
  127. package/src/integrations/google-auth.ts +175 -0
  128. package/src/llm/README.md +291 -0
  129. package/src/llm/anthropic.ts +386 -0
  130. package/src/llm/gemini.ts +371 -0
  131. package/src/llm/index.ts +19 -0
  132. package/src/llm/manager.ts +153 -0
  133. package/src/llm/ollama.ts +307 -0
  134. package/src/llm/openai.ts +350 -0
  135. package/src/llm/provider.test.ts +231 -0
  136. package/src/llm/provider.ts +60 -0
  137. package/src/llm/test.ts +87 -0
  138. package/src/observers/README.md +278 -0
  139. package/src/observers/calendar.ts +113 -0
  140. package/src/observers/clipboard.ts +136 -0
  141. package/src/observers/email.ts +109 -0
  142. package/src/observers/example.ts +58 -0
  143. package/src/observers/file-watcher.ts +124 -0
  144. package/src/observers/index.ts +159 -0
  145. package/src/observers/notifications.ts +197 -0
  146. package/src/observers/observers.test.ts +203 -0
  147. package/src/observers/processes.ts +225 -0
  148. package/src/personality/README.md +61 -0
  149. package/src/personality/adapter.ts +196 -0
  150. package/src/personality/index.ts +20 -0
  151. package/src/personality/learner.ts +209 -0
  152. package/src/personality/model.ts +132 -0
  153. package/src/personality/personality.test.ts +236 -0
  154. package/src/roles/README.md +252 -0
  155. package/src/roles/authority.ts +119 -0
  156. package/src/roles/example-usage.ts +198 -0
  157. package/src/roles/index.ts +42 -0
  158. package/src/roles/loader.ts +143 -0
  159. package/src/roles/prompt-builder.ts +194 -0
  160. package/src/roles/test-multi.ts +102 -0
  161. package/src/roles/test-role.yaml +77 -0
  162. package/src/roles/test-utils.ts +93 -0
  163. package/src/roles/test.ts +106 -0
  164. package/src/roles/tool-guide.ts +190 -0
  165. package/src/roles/types.ts +36 -0
  166. package/src/roles/utils.ts +200 -0
  167. package/src/scripts/google-setup.ts +168 -0
  168. package/src/sidecar/connection.ts +179 -0
  169. package/src/sidecar/index.ts +6 -0
  170. package/src/sidecar/manager.ts +542 -0
  171. package/src/sidecar/protocol.ts +85 -0
  172. package/src/sidecar/rpc.ts +161 -0
  173. package/src/sidecar/scheduler.ts +136 -0
  174. package/src/sidecar/types.ts +112 -0
  175. package/src/sidecar/validator.ts +144 -0
  176. package/src/vault/README.md +110 -0
  177. package/src/vault/awareness.ts +341 -0
  178. package/src/vault/commitments.ts +299 -0
  179. package/src/vault/content-pipeline.ts +260 -0
  180. package/src/vault/conversations.ts +173 -0
  181. package/src/vault/entities.ts +180 -0
  182. package/src/vault/extractor.test.ts +356 -0
  183. package/src/vault/extractor.ts +345 -0
  184. package/src/vault/facts.ts +190 -0
  185. package/src/vault/goals.ts +477 -0
  186. package/src/vault/index.ts +87 -0
  187. package/src/vault/keychain.ts +99 -0
  188. package/src/vault/observations.ts +115 -0
  189. package/src/vault/relationships.ts +178 -0
  190. package/src/vault/retrieval.test.ts +126 -0
  191. package/src/vault/retrieval.ts +227 -0
  192. package/src/vault/schema.ts +658 -0
  193. package/src/vault/settings.ts +38 -0
  194. package/src/vault/vectors.ts +92 -0
  195. package/src/vault/workflows.ts +403 -0
  196. package/src/workflows/auto-suggest.ts +290 -0
  197. package/src/workflows/engine.ts +366 -0
  198. package/src/workflows/events.ts +24 -0
  199. package/src/workflows/executor.ts +207 -0
  200. package/src/workflows/nl-builder.ts +198 -0
  201. package/src/workflows/nodes/actions/agent-task.ts +73 -0
  202. package/src/workflows/nodes/actions/calendar-action.ts +85 -0
  203. package/src/workflows/nodes/actions/code-execution.ts +73 -0
  204. package/src/workflows/nodes/actions/discord.ts +77 -0
  205. package/src/workflows/nodes/actions/file-write.ts +73 -0
  206. package/src/workflows/nodes/actions/gmail.ts +69 -0
  207. package/src/workflows/nodes/actions/http-request.ts +117 -0
  208. package/src/workflows/nodes/actions/notification.ts +85 -0
  209. package/src/workflows/nodes/actions/run-tool.ts +55 -0
  210. package/src/workflows/nodes/actions/send-message.ts +82 -0
  211. package/src/workflows/nodes/actions/shell-command.ts +76 -0
  212. package/src/workflows/nodes/actions/telegram.ts +60 -0
  213. package/src/workflows/nodes/builtin.ts +119 -0
  214. package/src/workflows/nodes/error/error-handler.ts +37 -0
  215. package/src/workflows/nodes/error/fallback.ts +47 -0
  216. package/src/workflows/nodes/error/retry.ts +82 -0
  217. package/src/workflows/nodes/logic/delay.ts +42 -0
  218. package/src/workflows/nodes/logic/if-else.ts +41 -0
  219. package/src/workflows/nodes/logic/loop.ts +90 -0
  220. package/src/workflows/nodes/logic/merge.ts +38 -0
  221. package/src/workflows/nodes/logic/race.ts +40 -0
  222. package/src/workflows/nodes/logic/switch.ts +59 -0
  223. package/src/workflows/nodes/logic/template-render.ts +53 -0
  224. package/src/workflows/nodes/logic/variable-get.ts +37 -0
  225. package/src/workflows/nodes/logic/variable-set.ts +59 -0
  226. package/src/workflows/nodes/registry.ts +99 -0
  227. package/src/workflows/nodes/transform/aggregate.ts +99 -0
  228. package/src/workflows/nodes/transform/csv-parse.ts +70 -0
  229. package/src/workflows/nodes/transform/json-parse.ts +63 -0
  230. package/src/workflows/nodes/transform/map-filter.ts +84 -0
  231. package/src/workflows/nodes/transform/regex-match.ts +89 -0
  232. package/src/workflows/nodes/triggers/calendar.ts +33 -0
  233. package/src/workflows/nodes/triggers/clipboard.ts +32 -0
  234. package/src/workflows/nodes/triggers/cron.ts +40 -0
  235. package/src/workflows/nodes/triggers/email.ts +40 -0
  236. package/src/workflows/nodes/triggers/file-change.ts +45 -0
  237. package/src/workflows/nodes/triggers/git.ts +46 -0
  238. package/src/workflows/nodes/triggers/manual.ts +23 -0
  239. package/src/workflows/nodes/triggers/poll.ts +81 -0
  240. package/src/workflows/nodes/triggers/process.ts +44 -0
  241. package/src/workflows/nodes/triggers/screen-event.ts +37 -0
  242. package/src/workflows/nodes/triggers/webhook.ts +39 -0
  243. package/src/workflows/safe-eval.ts +139 -0
  244. package/src/workflows/template.ts +118 -0
  245. package/src/workflows/triggers/cron.ts +311 -0
  246. package/src/workflows/triggers/manager.ts +285 -0
  247. package/src/workflows/triggers/observer-bridge.ts +172 -0
  248. package/src/workflows/triggers/poller.ts +201 -0
  249. package/src/workflows/triggers/screen-condition.ts +218 -0
  250. package/src/workflows/triggers/triggers.test.ts +740 -0
  251. package/src/workflows/triggers/webhook.ts +191 -0
  252. package/src/workflows/types.ts +133 -0
  253. package/src/workflows/variables.ts +72 -0
  254. package/src/workflows/workflows.test.ts +383 -0
  255. package/src/workflows/yaml.ts +104 -0
  256. package/ui/dist/index-j75njzc1.css +1199 -0
  257. package/ui/dist/index-p2zh407q.js +80603 -0
  258. package/ui/dist/index.html +13 -0
  259. package/ui/public/openwakeword/models/embedding_model.onnx +0 -0
  260. package/ui/public/openwakeword/models/hey_jarvis_v0.1.onnx +0 -0
  261. package/ui/public/openwakeword/models/melspectrogram.onnx +0 -0
  262. package/ui/public/openwakeword/models/silero_vad.onnx +0 -0
  263. package/ui/public/ort/ort-wasm-simd-threaded.jsep.mjs +106 -0
  264. package/ui/public/ort/ort-wasm-simd-threaded.jsep.wasm +0 -0
  265. package/ui/public/ort/ort-wasm-simd-threaded.mjs +59 -0
  266. package/ui/public/ort/ort-wasm-simd-threaded.wasm +0 -0
@@ -0,0 +1,191 @@
1
+ /**
2
+ * WebhookManager — manages inbound webhook endpoints for workflow triggers
3
+ *
4
+ * Each workflow can have a unique webhook path. Requests are validated
5
+ * against an optional HMAC-SHA256 secret (X-Jarvis-Signature header).
6
+ */
7
+
8
+ // ── Types ──
9
+
10
+ export type WebhookRoute = {
11
+ workflowId: string;
12
+ path: string;
13
+ secret: string | null;
14
+ registeredAt: number;
15
+ };
16
+
17
+ export type WebhookTriggerCallback = (workflowId: string, data: Record<string, unknown>) => void;
18
+
19
+ // ── Helpers ──
20
+
21
+ /**
22
+ * Compute an HMAC-SHA256 hex digest for the given body using the Web Crypto API.
23
+ * Works in both Bun and browser contexts.
24
+ */
25
+ async function computeHmac(secret: string, body: string): Promise<string> {
26
+ const encoder = new TextEncoder();
27
+ const keyMaterial = await crypto.subtle.importKey(
28
+ 'raw',
29
+ encoder.encode(secret),
30
+ { name: 'HMAC', hash: 'SHA-256' },
31
+ false,
32
+ ['sign'],
33
+ );
34
+
35
+ const signature = await crypto.subtle.sign('HMAC', keyMaterial, encoder.encode(body));
36
+ return Array.from(new Uint8Array(signature))
37
+ .map(b => b.toString(16).padStart(2, '0'))
38
+ .join('');
39
+ }
40
+
41
+ // ── WebhookManager ──
42
+
43
+ export class WebhookManager {
44
+ private routes: Map<string, WebhookRoute> = new Map();
45
+ private triggerCallback: WebhookTriggerCallback | null = null;
46
+
47
+ /**
48
+ * Register a workflow webhook.
49
+ * @returns the webhook path (e.g. "/webhooks/wf_abc123")
50
+ */
51
+ register(workflowId: string, secret?: string): string {
52
+ const path = `/webhooks/${workflowId}`;
53
+
54
+ this.routes.set(workflowId, {
55
+ workflowId,
56
+ path,
57
+ secret: secret ?? null,
58
+ registeredAt: Date.now(),
59
+ });
60
+
61
+ console.log(`[WebhookManager] Registered webhook for workflow "${workflowId}" at ${path}`);
62
+ return path;
63
+ }
64
+
65
+ /**
66
+ * Remove a workflow's webhook registration.
67
+ */
68
+ unregister(workflowId: string): void {
69
+ if (this.routes.delete(workflowId)) {
70
+ console.log(`[WebhookManager] Unregistered webhook for workflow "${workflowId}"`);
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Handle an inbound webhook request.
76
+ *
77
+ * Validates the optional HMAC secret, extracts the JSON body, and fires
78
+ * the trigger callback. Returns a proper HTTP Response.
79
+ */
80
+ async handleRequest(workflowId: string, req: Request): Promise<Response> {
81
+ const route = this.routes.get(workflowId);
82
+
83
+ if (!route) {
84
+ return new Response(JSON.stringify({ error: 'Webhook not found' }), {
85
+ status: 404,
86
+ headers: { 'Content-Type': 'application/json' },
87
+ });
88
+ }
89
+
90
+ // Read raw body once
91
+ let rawBody: string;
92
+ try {
93
+ rawBody = await req.text();
94
+ } catch {
95
+ return new Response(JSON.stringify({ error: 'Failed to read request body' }), {
96
+ status: 400,
97
+ headers: { 'Content-Type': 'application/json' },
98
+ });
99
+ }
100
+
101
+ // Validate HMAC signature if a secret is configured
102
+ if (route.secret) {
103
+ const signature = req.headers.get('x-jarvis-signature') ?? req.headers.get('X-Jarvis-Signature');
104
+
105
+ if (!signature) {
106
+ return new Response(JSON.stringify({ error: 'Missing signature header' }), {
107
+ status: 401,
108
+ headers: { 'Content-Type': 'application/json' },
109
+ });
110
+ }
111
+
112
+ const expected = await computeHmac(route.secret, rawBody);
113
+
114
+ // Constant-time comparison to prevent timing attacks
115
+ if (!timingSafeEqual(signature.toLowerCase(), expected.toLowerCase())) {
116
+ return new Response(JSON.stringify({ error: 'Invalid signature' }), {
117
+ status: 401,
118
+ headers: { 'Content-Type': 'application/json' },
119
+ });
120
+ }
121
+ }
122
+
123
+ // Parse body
124
+ let data: Record<string, unknown> = {};
125
+ if (rawBody.trim()) {
126
+ try {
127
+ const parsed = JSON.parse(rawBody);
128
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
129
+ data = parsed as Record<string, unknown>;
130
+ } else {
131
+ data = { body: parsed };
132
+ }
133
+ } catch {
134
+ // Not JSON — pass as raw string
135
+ data = { body: rawBody };
136
+ }
137
+ }
138
+
139
+ // Enrich with request metadata
140
+ data._webhook = {
141
+ method: req.method,
142
+ url: req.url,
143
+ timestamp: Date.now(),
144
+ headers: Object.fromEntries(req.headers.entries()),
145
+ };
146
+
147
+ // Fire callback (non-blocking)
148
+ if (this.triggerCallback) {
149
+ try {
150
+ this.triggerCallback(workflowId, data);
151
+ } catch (err) {
152
+ console.error(`[WebhookManager] Trigger callback threw for workflow "${workflowId}":`, err);
153
+ }
154
+ } else {
155
+ console.warn(`[WebhookManager] No trigger callback set; webhook fired for "${workflowId}" but nothing will execute`);
156
+ }
157
+
158
+ return new Response(JSON.stringify({ ok: true, workflowId }), {
159
+ status: 200,
160
+ headers: { 'Content-Type': 'application/json' },
161
+ });
162
+ }
163
+
164
+ /**
165
+ * Set the callback invoked when a webhook fires successfully.
166
+ */
167
+ setTriggerCallback(cb: WebhookTriggerCallback): void {
168
+ this.triggerCallback = cb;
169
+ }
170
+
171
+ /**
172
+ * Returns the map of all registered routes keyed by workflowId.
173
+ */
174
+ getRoutes(): Map<string, WebhookRoute> {
175
+ return new Map(this.routes);
176
+ }
177
+ }
178
+
179
+ // ── Utilities ──
180
+
181
+ /**
182
+ * Constant-time string comparison to prevent timing-based secret leakage.
183
+ */
184
+ function timingSafeEqual(a: string, b: string): boolean {
185
+ if (a.length !== b.length) return false;
186
+ let diff = 0;
187
+ for (let i = 0; i < a.length; i++) {
188
+ diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
189
+ }
190
+ return diff === 0;
191
+ }
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Workflow Automation Engine — Core Types
3
+ */
4
+
5
+ // ── Node System ──
6
+
7
+ export type NodeCategory = 'trigger' | 'action' | 'logic' | 'transform' | 'error';
8
+
9
+ export type NodeConfigFieldType = 'string' | 'number' | 'boolean' | 'select' | 'code' | 'template' | 'json';
10
+
11
+ export type NodeConfigField = {
12
+ type: NodeConfigFieldType;
13
+ label: string;
14
+ description?: string;
15
+ required: boolean;
16
+ default?: unknown;
17
+ options?: { label: string; value: string }[];
18
+ placeholder?: string;
19
+ };
20
+
21
+ // ── Workflow Definition (serialized graph) ──
22
+
23
+ export type WorkflowDefinition = {
24
+ nodes: WorkflowNode[];
25
+ edges: WorkflowEdge[];
26
+ settings: WorkflowSettings;
27
+ };
28
+
29
+ export type WorkflowNode = {
30
+ id: string;
31
+ type: string; // e.g., 'trigger.cron', 'action.http_request'
32
+ label: string;
33
+ position: { x: number; y: number };
34
+ config: Record<string, unknown>;
35
+ retryPolicy?: RetryPolicy;
36
+ fallbackNodeId?: string;
37
+ };
38
+
39
+ export type WorkflowEdge = {
40
+ id: string;
41
+ source: string;
42
+ target: string;
43
+ sourceHandle?: string; // e.g., 'true', 'false', 'default', 'error'
44
+ condition?: string;
45
+ label?: string;
46
+ };
47
+
48
+ export type WorkflowSettings = {
49
+ maxRetries: number; // default 3
50
+ retryDelayMs: number; // default 5000
51
+ timeoutMs: number; // default 300000 (5 min)
52
+ parallelism: 'sequential' | 'parallel';
53
+ onError: 'stop' | 'continue' | 'self_heal';
54
+ };
55
+
56
+ export type RetryPolicy = {
57
+ maxRetries: number;
58
+ delayMs: number;
59
+ backoff: 'fixed' | 'exponential';
60
+ };
61
+
62
+ export const DEFAULT_WORKFLOW_SETTINGS: WorkflowSettings = {
63
+ maxRetries: 3,
64
+ retryDelayMs: 5000,
65
+ timeoutMs: 300_000,
66
+ parallelism: 'parallel',
67
+ onError: 'stop',
68
+ };
69
+
70
+ // ── Execution ──
71
+
72
+ export type ExecutionStatus = 'running' | 'completed' | 'failed' | 'cancelled' | 'paused';
73
+ export type StepStatus = 'pending' | 'running' | 'completed' | 'failed' | 'skipped' | 'waiting';
74
+
75
+ // ── Vault Types ──
76
+
77
+ export type Workflow = {
78
+ id: string;
79
+ name: string;
80
+ description: string;
81
+ enabled: boolean;
82
+ authority_level: number;
83
+ authority_approved: boolean;
84
+ approved_at: number | null;
85
+ approved_by: string | null;
86
+ tags: string[];
87
+ current_version: number;
88
+ execution_count: number;
89
+ last_executed_at: number | null;
90
+ last_success_at: number | null;
91
+ last_failure_at: number | null;
92
+ created_at: number;
93
+ updated_at: number;
94
+ };
95
+
96
+ export type WorkflowVersion = {
97
+ id: string;
98
+ workflow_id: string;
99
+ version: number;
100
+ definition: WorkflowDefinition;
101
+ changelog: string | null;
102
+ created_by: string;
103
+ created_at: number;
104
+ };
105
+
106
+ export type WorkflowExecution = {
107
+ id: string;
108
+ workflow_id: string;
109
+ version: number;
110
+ trigger_type: string;
111
+ trigger_data: Record<string, unknown> | null;
112
+ status: ExecutionStatus;
113
+ variables: Record<string, unknown>;
114
+ error_message: string | null;
115
+ started_at: number;
116
+ completed_at: number | null;
117
+ duration_ms: number | null;
118
+ };
119
+
120
+ export type WorkflowStepResult = {
121
+ id: string;
122
+ execution_id: string;
123
+ node_id: string;
124
+ node_type: string;
125
+ status: StepStatus;
126
+ input_data: Record<string, unknown> | null;
127
+ output_data: Record<string, unknown> | null;
128
+ error_message: string | null;
129
+ retry_count: number;
130
+ started_at: number | null;
131
+ completed_at: number | null;
132
+ duration_ms: number | null;
133
+ };
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Variable Scope — execution-scoped + persistent
3
+ *
4
+ * Execution-scoped variables live in memory for the current run.
5
+ * Persistent variables survive across executions (stored in vault).
6
+ */
7
+
8
+ import * as vault from '../vault/workflows.ts';
9
+ import type { VariableScopeInterface } from './nodes/registry.ts';
10
+
11
+ export class VariableScope implements VariableScopeInterface {
12
+ private executionVars: Map<string, unknown> = new Map();
13
+ private workflowId: string;
14
+
15
+ constructor(workflowId: string, initialVars?: Record<string, unknown>) {
16
+ this.workflowId = workflowId;
17
+ if (initialVars) {
18
+ for (const [k, v] of Object.entries(initialVars)) {
19
+ this.executionVars.set(k, v);
20
+ }
21
+ }
22
+ }
23
+
24
+ /**
25
+ * Get variable — checks execution scope first, then persistent vault.
26
+ */
27
+ get(key: string): unknown {
28
+ if (this.executionVars.has(key)) {
29
+ return this.executionVars.get(key);
30
+ }
31
+ return vault.getVariable(this.workflowId, key);
32
+ }
33
+
34
+ /**
35
+ * Set execution-scoped variable (in-memory only).
36
+ */
37
+ set(key: string, value: unknown): void {
38
+ this.executionVars.set(key, value);
39
+ }
40
+
41
+ /**
42
+ * Set persistent variable (survives across executions).
43
+ */
44
+ setPersistent(key: string, value: unknown): void {
45
+ vault.setVariable(this.workflowId, key, value);
46
+ // Also set in execution scope for current run
47
+ this.executionVars.set(key, value);
48
+ }
49
+
50
+ /**
51
+ * Get all variables (execution + persistent merged).
52
+ */
53
+ toObject(): Record<string, unknown> {
54
+ const persistent = vault.getVariables(this.workflowId);
55
+ const result: Record<string, unknown> = { ...persistent };
56
+ for (const [k, v] of this.executionVars) {
57
+ result[k] = v;
58
+ }
59
+ return result;
60
+ }
61
+
62
+ /**
63
+ * Serialize execution variables for storage.
64
+ */
65
+ serialize(): string {
66
+ const obj: Record<string, unknown> = {};
67
+ for (const [k, v] of this.executionVars) {
68
+ obj[k] = v;
69
+ }
70
+ return JSON.stringify(obj);
71
+ }
72
+ }