@shalwin04/x404r-sdk 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 (58) hide show
  1. package/README.md +391 -0
  2. package/dist/ai/index.d.ts +21 -0
  3. package/dist/ai/index.d.ts.map +1 -0
  4. package/dist/ai/index.js +344 -0
  5. package/dist/ai/index.js.map +1 -0
  6. package/dist/backend/cloud.d.ts +91 -0
  7. package/dist/backend/cloud.d.ts.map +1 -0
  8. package/dist/backend/cloud.js +257 -0
  9. package/dist/backend/cloud.js.map +1 -0
  10. package/dist/backend/embedded.d.ts +79 -0
  11. package/dist/backend/embedded.d.ts.map +1 -0
  12. package/dist/backend/embedded.js +307 -0
  13. package/dist/backend/embedded.js.map +1 -0
  14. package/dist/backend/index.d.ts +11 -0
  15. package/dist/backend/index.d.ts.map +1 -0
  16. package/dist/backend/index.js +8 -0
  17. package/dist/backend/index.js.map +1 -0
  18. package/dist/backend/interface.d.ts +88 -0
  19. package/dist/backend/interface.d.ts.map +1 -0
  20. package/dist/backend/interface.js +11 -0
  21. package/dist/backend/interface.js.map +1 -0
  22. package/dist/chaos.d.ts +117 -0
  23. package/dist/chaos.d.ts.map +1 -0
  24. package/dist/chaos.js +215 -0
  25. package/dist/chaos.js.map +1 -0
  26. package/dist/client.d.ts +242 -0
  27. package/dist/client.d.ts.map +1 -0
  28. package/dist/client.js +401 -0
  29. package/dist/client.js.map +1 -0
  30. package/dist/context.d.ts +18 -0
  31. package/dist/context.d.ts.map +1 -0
  32. package/dist/context.js +65 -0
  33. package/dist/context.js.map +1 -0
  34. package/dist/durable.d.ts +90 -0
  35. package/dist/durable.d.ts.map +1 -0
  36. package/dist/durable.js +143 -0
  37. package/dist/durable.js.map +1 -0
  38. package/dist/index.d.ts +74 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +76 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/metrics.d.ts +279 -0
  43. package/dist/metrics.d.ts.map +1 -0
  44. package/dist/metrics.js +693 -0
  45. package/dist/metrics.js.map +1 -0
  46. package/dist/types.d.ts +240 -0
  47. package/dist/types.d.ts.map +1 -0
  48. package/dist/types.js +16 -0
  49. package/dist/types.js.map +1 -0
  50. package/dist/worker.d.ts +74 -0
  51. package/dist/worker.d.ts.map +1 -0
  52. package/dist/worker.js +269 -0
  53. package/dist/worker.js.map +1 -0
  54. package/dist/workflow.d.ts +48 -0
  55. package/dist/workflow.d.ts.map +1 -0
  56. package/dist/workflow.js +190 -0
  57. package/dist/workflow.js.map +1 -0
  58. package/package.json +93 -0
@@ -0,0 +1,257 @@
1
+ /**
2
+ * Cloud Backend
3
+ * HTTP API client for hosted x404-r platform
4
+ */
5
+ /**
6
+ * Cloud backend - connects to hosted x404-r API
7
+ * Used when running in cloud mode (no local DB needed)
8
+ */
9
+ export class CloudBackend {
10
+ apiKey;
11
+ baseUrl;
12
+ constructor(config) {
13
+ this.apiKey = config.apiKey;
14
+ this.baseUrl = config.baseUrl || 'https://api.x404r.io';
15
+ }
16
+ async ready() {
17
+ // Validate API key by calling health endpoint
18
+ const response = await this.request('GET', '/health');
19
+ if (!response.data) {
20
+ throw new Error('Failed to connect to x404-r API');
21
+ }
22
+ }
23
+ async close() {
24
+ // No cleanup needed for HTTP client
25
+ }
26
+ // ============ HTTP Client ============
27
+ async request(method, path, body) {
28
+ const url = `${this.baseUrl}${path}`;
29
+ const headers = {
30
+ Authorization: `Bearer ${this.apiKey}`,
31
+ 'Content-Type': 'application/json',
32
+ };
33
+ const options = {
34
+ method,
35
+ headers,
36
+ };
37
+ if (body) {
38
+ options.body = JSON.stringify(body);
39
+ }
40
+ try {
41
+ const response = await fetch(url, options);
42
+ const data = (await response.json());
43
+ if (!response.ok) {
44
+ return { error: data.error || `HTTP ${response.status}` };
45
+ }
46
+ return { data: data };
47
+ }
48
+ catch (error) {
49
+ return {
50
+ error: error instanceof Error ? error.message : 'Unknown error',
51
+ };
52
+ }
53
+ }
54
+ handleError(response, context) {
55
+ throw new Error(`${context}: ${response.error}`);
56
+ }
57
+ // ============ Workflow Operations ============
58
+ async createWorkflow(name, version, input, priority = 0) {
59
+ const response = await this.request('POST', '/workflows', {
60
+ name,
61
+ version,
62
+ input,
63
+ priority,
64
+ });
65
+ if (response.error || !response.data) {
66
+ this.handleError(response, 'Failed to create workflow');
67
+ }
68
+ return response.data;
69
+ }
70
+ async getWorkflow(id) {
71
+ const response = await this.request('GET', `/workflows/${id}`);
72
+ if (response.error) {
73
+ if (response.error.includes('404')) {
74
+ return null;
75
+ }
76
+ this.handleError(response, 'Failed to get workflow');
77
+ }
78
+ return response.data || null;
79
+ }
80
+ async updateWorkflowStatus(id, status, output, error) {
81
+ const response = await this.request('PUT', `/workflows/${id}/status`, {
82
+ status,
83
+ output,
84
+ error,
85
+ });
86
+ if (response.error) {
87
+ this.handleError(response, 'Failed to update workflow status');
88
+ }
89
+ }
90
+ async listWorkflows(options = {}) {
91
+ const params = new URLSearchParams();
92
+ if (options.status)
93
+ params.set('status', options.status);
94
+ if (options.limit)
95
+ params.set('limit', String(options.limit));
96
+ if (options.offset)
97
+ params.set('offset', String(options.offset));
98
+ const query = params.toString() ? `?${params}` : '';
99
+ const response = await this.request('GET', `/workflows${query}`);
100
+ if (response.error || !response.data) {
101
+ this.handleError(response, 'Failed to list workflows');
102
+ }
103
+ return response.data;
104
+ }
105
+ // ============ Task Operations ============
106
+ async createTasks(workflowId, tasks) {
107
+ const response = await this.request('POST', `/workflows/${workflowId}/tasks`, { tasks });
108
+ if (response.error || !response.data) {
109
+ this.handleError(response, 'Failed to create tasks');
110
+ }
111
+ return response.data;
112
+ }
113
+ async getWorkflowTasks(workflowId) {
114
+ const response = await this.request('GET', `/workflows/${workflowId}/tasks`);
115
+ if (response.error || !response.data) {
116
+ this.handleError(response, 'Failed to get workflow tasks');
117
+ }
118
+ return response.data;
119
+ }
120
+ // Note: claimTask and heartbeat are not available in cloud mode
121
+ // Workers run on Lambda, not locally
122
+ async completeTask(taskId, output) {
123
+ const response = await this.request('PUT', `/tasks/${taskId}/complete`, {
124
+ output,
125
+ });
126
+ if (response.error) {
127
+ this.handleError(response, 'Failed to complete task');
128
+ }
129
+ }
130
+ async failTask(taskId, error) {
131
+ const response = await this.request('PUT', `/tasks/${taskId}/fail`, {
132
+ error,
133
+ });
134
+ if (response.error) {
135
+ this.handleError(response, 'Failed to fail task');
136
+ }
137
+ }
138
+ // ============ Checkpoint Operations ============
139
+ async createCheckpoint(taskId, stepIndex, state) {
140
+ const response = await this.request('POST', `/tasks/${taskId}/checkpoint`, {
141
+ stepIndex,
142
+ state,
143
+ });
144
+ if (response.error) {
145
+ this.handleError(response, 'Failed to create checkpoint');
146
+ }
147
+ }
148
+ async getCheckpoint(taskId) {
149
+ const response = await this.request('GET', `/tasks/${taskId}/checkpoint`);
150
+ if (response.error) {
151
+ if (response.error.includes('404')) {
152
+ return null;
153
+ }
154
+ this.handleError(response, 'Failed to get checkpoint');
155
+ }
156
+ return response.data || null;
157
+ }
158
+ async getWorkflowCheckpoints(workflowId) {
159
+ const response = await this.request('GET', `/workflows/${workflowId}/checkpoints`);
160
+ if (response.error || !response.data) {
161
+ this.handleError(response, 'Failed to get workflow checkpoints');
162
+ }
163
+ return response.data.map((cp) => ({
164
+ ...cp,
165
+ createdAt: new Date(cp.createdAt),
166
+ }));
167
+ }
168
+ // ============ Memory Operations ============
169
+ async storeMemory(taskId, eventType, summary, embedding, taskType, errorCategory, resolution) {
170
+ const response = await this.request('POST', '/memories', {
171
+ taskId,
172
+ eventType,
173
+ summary,
174
+ embedding,
175
+ taskType,
176
+ errorCategory,
177
+ resolution,
178
+ });
179
+ if (response.error) {
180
+ this.handleError(response, 'Failed to store memory');
181
+ }
182
+ }
183
+ async queryMemories(embedding, taskType, limit = 5) {
184
+ const response = await this.request('POST', '/memories/query', {
185
+ embedding,
186
+ taskType,
187
+ limit,
188
+ });
189
+ if (response.error || !response.data) {
190
+ this.handleError(response, 'Failed to query memories');
191
+ }
192
+ return response.data;
193
+ }
194
+ // ============ Workflow Status ============
195
+ async isWorkflowComplete(workflowId) {
196
+ const response = await this.request('GET', `/workflows/${workflowId}/status`);
197
+ if (response.error || !response.data) {
198
+ this.handleError(response, 'Failed to get workflow status');
199
+ }
200
+ return response.data;
201
+ }
202
+ // ============ Time Travel ============
203
+ async replayFromCheckpoint(workflowId, checkpointId, newInput) {
204
+ const response = await this.request('POST', `/workflows/${workflowId}/replay`, {
205
+ checkpointId,
206
+ newInput,
207
+ });
208
+ if (response.error || !response.data) {
209
+ this.handleError(response, 'Failed to replay from checkpoint');
210
+ }
211
+ return response.data;
212
+ }
213
+ // ============ Cost Tracking ============
214
+ async getWorkflowCost(workflowId) {
215
+ const response = await this.request('GET', `/workflows/${workflowId}/cost`);
216
+ if (response.error || !response.data) {
217
+ this.handleError(response, 'Failed to get workflow cost');
218
+ }
219
+ return response.data;
220
+ }
221
+ // ============ Cloud-Specific Methods ============
222
+ /**
223
+ * Submit a workflow for execution (cloud workers will pick it up)
224
+ */
225
+ async submit(workflowName, input, options = {}) {
226
+ const response = await this.request('POST', '/submit', {
227
+ workflow: workflowName,
228
+ input,
229
+ priority: options.priority || 0,
230
+ wait: options.wait || false,
231
+ timeout: options.timeout,
232
+ });
233
+ if (response.error || !response.data) {
234
+ this.handleError(response, 'Failed to submit workflow');
235
+ }
236
+ return response.data;
237
+ }
238
+ /**
239
+ * Wait for a workflow to complete
240
+ */
241
+ async waitForCompletion(workflowId, options = {}) {
242
+ const { timeout = 300000, pollInterval = 1000 } = options;
243
+ const startTime = Date.now();
244
+ while (Date.now() - startTime < timeout) {
245
+ const workflow = await this.getWorkflow(workflowId);
246
+ if (!workflow) {
247
+ throw new Error(`Workflow ${workflowId} not found`);
248
+ }
249
+ if (workflow.status === 'completed' || workflow.status === 'failed') {
250
+ return workflow;
251
+ }
252
+ await new Promise((resolve) => setTimeout(resolve, pollInterval));
253
+ }
254
+ throw new Error(`Workflow ${workflowId} timed out after ${timeout}ms`);
255
+ }
256
+ }
257
+ //# sourceMappingURL=cloud.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloud.js","sourceRoot":"","sources":["../../src/backend/cloud.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Embedded Backend
3
+ * Direct CockroachDB connection for self-hosted mode
4
+ */
5
+ import { Pool } from 'pg';
6
+ import type { Backend } from './interface.js';
7
+ import type { Workflow, Task, WorkflowStatus } from '../types.js';
8
+ export interface EmbeddedBackendConfig {
9
+ connectionString: string;
10
+ tenantId: string;
11
+ ssl?: boolean;
12
+ }
13
+ /**
14
+ * Embedded backend - connects directly to CockroachDB
15
+ * Used when running workers locally or self-hosting
16
+ */
17
+ export declare class EmbeddedBackend implements Backend {
18
+ private pool;
19
+ private tenantId;
20
+ constructor(config: EmbeddedBackendConfig);
21
+ ready(): Promise<void>;
22
+ close(): Promise<void>;
23
+ /** Get the raw database pool (for advanced use cases) */
24
+ get db(): Pool;
25
+ createWorkflow(name: string, version: string, input: Record<string, unknown>, priority?: number): Promise<Workflow>;
26
+ getWorkflow(id: string): Promise<Workflow | null>;
27
+ updateWorkflowStatus(id: string, status: WorkflowStatus, output?: Record<string, unknown>, error?: string): Promise<void>;
28
+ listWorkflows(options?: {
29
+ status?: WorkflowStatus;
30
+ limit?: number;
31
+ offset?: number;
32
+ }): Promise<Workflow[]>;
33
+ createTasks(workflowId: string, tasks: Array<{
34
+ name: string;
35
+ type: string;
36
+ input: Record<string, unknown>;
37
+ dependsOn: string[];
38
+ maxAttempts?: number;
39
+ }>): Promise<Task[]>;
40
+ getWorkflowTasks(workflowId: string): Promise<Task[]>;
41
+ claimTask(workerId: string, taskTypes?: string[]): Promise<Task | null>;
42
+ heartbeat(taskId: string): Promise<void>;
43
+ completeTask(taskId: string, output: Record<string, unknown>): Promise<void>;
44
+ failTask(taskId: string, error: string): Promise<void>;
45
+ createCheckpoint(taskId: string, stepIndex: number, state: Record<string, unknown>): Promise<void>;
46
+ getCheckpoint(taskId: string): Promise<{
47
+ stepIndex: number;
48
+ state: Record<string, unknown>;
49
+ } | null>;
50
+ getWorkflowCheckpoints(workflowId: string): Promise<Array<{
51
+ taskId: string;
52
+ taskName: string;
53
+ stepIndex: number;
54
+ state: Record<string, unknown>;
55
+ createdAt: Date;
56
+ }>>;
57
+ storeMemory(taskId: string, eventType: string, summary: string, embedding: number[], taskType?: string, errorCategory?: string, resolution?: string): Promise<void>;
58
+ queryMemories(embedding: number[], taskType?: string, limit?: number): Promise<Array<{
59
+ summary: string;
60
+ eventType: string;
61
+ resolution?: string;
62
+ similarity: number;
63
+ }>>;
64
+ isWorkflowComplete(workflowId: string): Promise<{
65
+ complete: boolean;
66
+ failed: number;
67
+ done: number;
68
+ pending: number;
69
+ }>;
70
+ replayFromCheckpoint(workflowId: string, checkpointId: string, newInput?: Record<string, unknown>): Promise<Workflow>;
71
+ getWorkflowCost(workflowId: string): Promise<{
72
+ totalTokens: number;
73
+ estimatedCostUsd: number;
74
+ savedByRecoveryUsd: number;
75
+ }>;
76
+ private mapWorkflow;
77
+ private mapTask;
78
+ }
79
+ //# sourceMappingURL=embedded.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedded.d.ts","sourceRoot":"","sources":["../../src/backend/embedded.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,307 @@
1
+ /**
2
+ * Embedded Backend
3
+ * Direct CockroachDB connection for self-hosted mode
4
+ */
5
+ import { Pool } from 'pg';
6
+ /**
7
+ * Embedded backend - connects directly to CockroachDB
8
+ * Used when running workers locally or self-hosting
9
+ */
10
+ export class EmbeddedBackend {
11
+ pool;
12
+ tenantId;
13
+ constructor(config) {
14
+ this.pool = new Pool({
15
+ connectionString: config.connectionString,
16
+ ssl: config.ssl !== false ? { rejectUnauthorized: false } : undefined,
17
+ });
18
+ this.tenantId = config.tenantId;
19
+ }
20
+ async ready() {
21
+ // Test connection
22
+ await this.pool.query('SELECT 1');
23
+ }
24
+ async close() {
25
+ await this.pool.end();
26
+ }
27
+ /** Get the raw database pool (for advanced use cases) */
28
+ get db() {
29
+ return this.pool;
30
+ }
31
+ // ============ Workflow Operations ============
32
+ async createWorkflow(name, version, input, priority = 0) {
33
+ const result = await this.pool.query(`INSERT INTO jobs (tenant_id, name, description, input_payload, priority, status)
34
+ VALUES ($1, $2, $3, $4, $5, 'pending')
35
+ RETURNING *`, [this.tenantId, name, version, JSON.stringify(input), priority]);
36
+ return this.mapWorkflow(result.rows[0]);
37
+ }
38
+ async getWorkflow(id) {
39
+ const result = await this.pool.query('SELECT * FROM jobs WHERE id = $1 AND tenant_id = $2', [id, this.tenantId]);
40
+ return result.rows[0] ? this.mapWorkflow(result.rows[0]) : null;
41
+ }
42
+ async updateWorkflowStatus(id, status, output, error) {
43
+ const completedAt = status === 'completed' || status === 'failed' ? 'now()' : null;
44
+ await this.pool.query(`UPDATE jobs SET
45
+ status = $2,
46
+ result_payload = COALESCE($3, result_payload),
47
+ completed_at = $4,
48
+ updated_at = now()
49
+ WHERE id = $1 AND tenant_id = $5`, [
50
+ id,
51
+ status,
52
+ output ? JSON.stringify(output) : null,
53
+ completedAt,
54
+ this.tenantId,
55
+ ]);
56
+ }
57
+ async listWorkflows(options = {}) {
58
+ const { status, limit = 50, offset = 0 } = options;
59
+ let query = 'SELECT * FROM jobs WHERE tenant_id = $1';
60
+ const params = [this.tenantId];
61
+ if (status) {
62
+ params.push(status);
63
+ query += ` AND status = $${params.length}`;
64
+ }
65
+ query += ` ORDER BY created_at DESC LIMIT $${params.length + 1} OFFSET $${params.length + 2}`;
66
+ params.push(limit, offset);
67
+ const result = await this.pool.query(query, params);
68
+ return result.rows.map((row) => this.mapWorkflow(row));
69
+ }
70
+ // ============ Task Operations ============
71
+ async createTasks(workflowId, tasks) {
72
+ if (tasks.length === 0)
73
+ return [];
74
+ const values = [];
75
+ const placeholders = [];
76
+ let paramIndex = 1;
77
+ for (const task of tasks) {
78
+ placeholders.push(`($${paramIndex++}, $${paramIndex++}, $${paramIndex++}, $${paramIndex++}, $${paramIndex++}, $${paramIndex++}, $${paramIndex++})`);
79
+ values.push(this.tenantId, workflowId, task.type, task.name, JSON.stringify(task.input), task.dependsOn, task.maxAttempts || 3);
80
+ }
81
+ const result = await this.pool.query(`INSERT INTO task_nodes (tenant_id, job_id, task_type, name, input_payload, depends_on, max_attempts)
82
+ VALUES ${placeholders.join(', ')}
83
+ RETURNING *`, values);
84
+ return result.rows.map((row) => this.mapTask(row));
85
+ }
86
+ async getWorkflowTasks(workflowId) {
87
+ const result = await this.pool.query('SELECT * FROM task_nodes WHERE job_id = $1 ORDER BY created_at', [workflowId]);
88
+ return result.rows.map((row) => this.mapTask(row));
89
+ }
90
+ async claimTask(workerId, taskTypes) {
91
+ let query = `
92
+ WITH ready_tasks AS (
93
+ SELECT t.id FROM task_nodes t
94
+ JOIN jobs j ON t.job_id = j.id
95
+ JOIN tenants ten ON t.tenant_id = ten.id
96
+ WHERE t.status = 'pending'
97
+ AND t.tenant_id = $1
98
+ AND NOT EXISTS (
99
+ SELECT 1 FROM task_nodes dep
100
+ WHERE dep.id = ANY(t.depends_on) AND dep.status != 'done'
101
+ )
102
+ `;
103
+ const params = [this.tenantId, workerId];
104
+ if (taskTypes && taskTypes.length > 0) {
105
+ params.push(taskTypes);
106
+ query += ` AND t.task_type = ANY($${params.length})`;
107
+ }
108
+ query += `
109
+ ORDER BY
110
+ CASE ten.plan
111
+ WHEN 'enterprise' THEN 0
112
+ WHEN 'team' THEN 1
113
+ WHEN 'pro' THEN 2
114
+ ELSE 3
115
+ END,
116
+ j.priority DESC,
117
+ t.created_at ASC
118
+ LIMIT 1
119
+ FOR UPDATE OF t SKIP LOCKED
120
+ )
121
+ UPDATE task_nodes
122
+ SET status = 'claimed',
123
+ claimed_by = $2,
124
+ claimed_at = now(),
125
+ heartbeat_at = now(),
126
+ attempt_count = attempt_count + 1,
127
+ updated_at = now()
128
+ FROM ready_tasks
129
+ WHERE task_nodes.id = ready_tasks.id
130
+ RETURNING task_nodes.*
131
+ `;
132
+ const result = await this.pool.query(query, params);
133
+ return result.rows[0] ? this.mapTask(result.rows[0]) : null;
134
+ }
135
+ async heartbeat(taskId) {
136
+ await this.pool.query('UPDATE task_nodes SET heartbeat_at = now() WHERE id = $1', [taskId]);
137
+ }
138
+ async completeTask(taskId, output) {
139
+ await this.pool.query(`UPDATE task_nodes SET
140
+ status = 'done',
141
+ output_payload = $2,
142
+ completed_at = now(),
143
+ updated_at = now()
144
+ WHERE id = $1`, [taskId, JSON.stringify(output)]);
145
+ }
146
+ async failTask(taskId, error) {
147
+ await this.pool.query(`UPDATE task_nodes SET
148
+ status = 'failed',
149
+ error_message = $2,
150
+ completed_at = now(),
151
+ updated_at = now()
152
+ WHERE id = $1`, [taskId, error]);
153
+ }
154
+ // ============ Checkpoint Operations ============
155
+ async createCheckpoint(taskId, stepIndex, state) {
156
+ await this.pool.query(`INSERT INTO checkpoints (task_id, step_number, state)
157
+ VALUES ($1, $2, $3)
158
+ ON CONFLICT (task_id, step_number)
159
+ DO UPDATE SET state = $3, created_at = now()`, [taskId, stepIndex, JSON.stringify(state)]);
160
+ }
161
+ async getCheckpoint(taskId) {
162
+ const result = await this.pool.query(`SELECT step_number, state FROM checkpoints
163
+ WHERE task_id = $1
164
+ ORDER BY step_number DESC
165
+ LIMIT 1`, [taskId]);
166
+ if (result.rows.length === 0)
167
+ return null;
168
+ return {
169
+ stepIndex: result.rows[0].step_number,
170
+ state: result.rows[0].state,
171
+ };
172
+ }
173
+ async getWorkflowCheckpoints(workflowId) {
174
+ const result = await this.pool.query(`SELECT c.task_id, t.name as task_name, c.step_number, c.state, c.created_at
175
+ FROM checkpoints c
176
+ JOIN task_nodes t ON c.task_id = t.id
177
+ WHERE t.job_id = $1
178
+ ORDER BY c.created_at DESC`, [workflowId]);
179
+ return result.rows.map((row) => ({
180
+ taskId: row.task_id,
181
+ taskName: row.task_name,
182
+ stepIndex: row.step_number,
183
+ state: row.state,
184
+ createdAt: row.created_at,
185
+ }));
186
+ }
187
+ // ============ Memory Operations ============
188
+ async storeMemory(taskId, eventType, summary, embedding, taskType, errorCategory, resolution) {
189
+ await this.pool.query(`INSERT INTO memory_vectors
190
+ (tenant_id, task_id, event_type, context_summary, embedding, task_type, error_category, resolution)
191
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`, [
192
+ this.tenantId,
193
+ taskId,
194
+ eventType,
195
+ summary,
196
+ embedding,
197
+ taskType,
198
+ errorCategory,
199
+ resolution,
200
+ ]);
201
+ }
202
+ async queryMemories(embedding, taskType, limit = 5) {
203
+ const embeddingStr = `ARRAY[${embedding.join(',')}]::FLOAT8[]`;
204
+ let query = `
205
+ SELECT
206
+ context_summary as summary,
207
+ event_type,
208
+ resolution,
209
+ COALESCE(
210
+ (SELECT SUM(a * b) FROM UNNEST(embedding, ${embeddingStr}) AS t(a, b)) /
211
+ NULLIF(
212
+ SQRT((SELECT SUM(a * a) FROM UNNEST(embedding) AS t(a))) *
213
+ SQRT((SELECT SUM(b * b) FROM UNNEST(${embeddingStr}) AS t(b))),
214
+ 0
215
+ ),
216
+ 0
217
+ ) AS similarity
218
+ FROM memory_vectors
219
+ WHERE tenant_id = $1
220
+ `;
221
+ const params = [this.tenantId];
222
+ if (taskType) {
223
+ params.push(taskType);
224
+ query += ` AND task_type = $${params.length}`;
225
+ }
226
+ query += ` ORDER BY similarity DESC LIMIT $${params.length + 1}`;
227
+ params.push(limit);
228
+ const result = await this.pool.query(query, params);
229
+ return result.rows;
230
+ }
231
+ // ============ Workflow Status ============
232
+ async isWorkflowComplete(workflowId) {
233
+ const result = await this.pool.query(`SELECT
234
+ COUNT(*) FILTER (WHERE status = 'done') as done,
235
+ COUNT(*) FILTER (WHERE status = 'failed') as failed,
236
+ COUNT(*) FILTER (WHERE status NOT IN ('done', 'failed')) as pending
237
+ FROM task_nodes WHERE job_id = $1`, [workflowId]);
238
+ const row = result.rows[0];
239
+ return {
240
+ complete: parseInt(row.pending) === 0,
241
+ done: parseInt(row.done),
242
+ failed: parseInt(row.failed),
243
+ pending: parseInt(row.pending),
244
+ };
245
+ }
246
+ // ============ Time Travel ============
247
+ async replayFromCheckpoint(workflowId, checkpointId, newInput) {
248
+ // Get the original workflow
249
+ const workflow = await this.getWorkflow(workflowId);
250
+ if (!workflow) {
251
+ throw new Error(`Workflow ${workflowId} not found`);
252
+ }
253
+ // Create a new workflow with the same config
254
+ const newWorkflow = await this.createWorkflow(workflow.name, workflow.version, newInput || workflow.input, 0);
255
+ // TODO: Copy state from checkpoint to new workflow
256
+ // This is a simplified implementation
257
+ return newWorkflow;
258
+ }
259
+ // ============ Cost Tracking ============
260
+ async getWorkflowCost(workflowId) {
261
+ // This would query metrics if available
262
+ // For now, return placeholder
263
+ return {
264
+ totalTokens: 0,
265
+ estimatedCostUsd: 0,
266
+ savedByRecoveryUsd: 0,
267
+ };
268
+ }
269
+ // ============ Mappers ============
270
+ mapWorkflow(row) {
271
+ return {
272
+ id: row.id,
273
+ name: row.name,
274
+ version: row.description || '1.0.0',
275
+ status: row.status,
276
+ input: row.input_payload,
277
+ output: row.result_payload,
278
+ tenantId: row.tenant_id,
279
+ createdAt: row.created_at,
280
+ updatedAt: row.updated_at,
281
+ completedAt: row.completed_at,
282
+ };
283
+ }
284
+ mapTask(row) {
285
+ return {
286
+ id: row.id,
287
+ workflowId: row.job_id,
288
+ name: row.name,
289
+ type: row.task_type,
290
+ status: row.status,
291
+ input: row.input_payload,
292
+ output: row.output_payload,
293
+ error: row.error_message,
294
+ dependsOn: row.depends_on || [],
295
+ claimedBy: row.claimed_by,
296
+ claimedAt: row.claimed_at,
297
+ heartbeatAt: row.heartbeat_at,
298
+ attemptCount: row.attempt_count,
299
+ maxAttempts: row.max_attempts,
300
+ tenantId: row.tenant_id,
301
+ createdAt: row.created_at,
302
+ updatedAt: row.updated_at,
303
+ completedAt: row.completed_at,
304
+ };
305
+ }
306
+ }
307
+ //# sourceMappingURL=embedded.js.map