@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.
- package/README.md +391 -0
- package/dist/ai/index.d.ts +21 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +344 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/backend/cloud.d.ts +91 -0
- package/dist/backend/cloud.d.ts.map +1 -0
- package/dist/backend/cloud.js +257 -0
- package/dist/backend/cloud.js.map +1 -0
- package/dist/backend/embedded.d.ts +79 -0
- package/dist/backend/embedded.d.ts.map +1 -0
- package/dist/backend/embedded.js +307 -0
- package/dist/backend/embedded.js.map +1 -0
- package/dist/backend/index.d.ts +11 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/backend/index.js +8 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/interface.d.ts +88 -0
- package/dist/backend/interface.d.ts.map +1 -0
- package/dist/backend/interface.js +11 -0
- package/dist/backend/interface.js.map +1 -0
- package/dist/chaos.d.ts +117 -0
- package/dist/chaos.d.ts.map +1 -0
- package/dist/chaos.js +215 -0
- package/dist/chaos.js.map +1 -0
- package/dist/client.d.ts +242 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +401 -0
- package/dist/client.js.map +1 -0
- package/dist/context.d.ts +18 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +65 -0
- package/dist/context.js.map +1 -0
- package/dist/durable.d.ts +90 -0
- package/dist/durable.d.ts.map +1 -0
- package/dist/durable.js +143 -0
- package/dist/durable.js.map +1 -0
- package/dist/index.d.ts +74 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +76 -0
- package/dist/index.js.map +1 -0
- package/dist/metrics.d.ts +279 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +693 -0
- package/dist/metrics.js.map +1 -0
- package/dist/types.d.ts +240 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +16 -0
- package/dist/types.js.map +1 -0
- package/dist/worker.d.ts +74 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +269 -0
- package/dist/worker.js.map +1 -0
- package/dist/workflow.d.ts +48 -0
- package/dist/workflow.d.ts.map +1 -0
- package/dist/workflow.js +190 -0
- package/dist/workflow.js.map +1 -0
- 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":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAC1B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElE,MAAM,WAAW,qBAAqB;IACpC,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED;;;GAGG;AACH,qBAAa,eAAgB,YAAW,OAAO;IAC7C,OAAO,CAAC,IAAI,CAAO;IACnB,OAAO,CAAC,QAAQ,CAAS;gBAEb,MAAM,EAAE,qBAAqB;IAQnC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAKtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,yDAAyD;IACzD,IAAI,EAAE,IAAI,IAAI,CAEb;IAIK,cAAc,CAClB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,QAAQ,GAAE,MAAU,GACnB,OAAO,CAAC,QAAQ,CAAC;IAUd,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAQjD,oBAAoB,CACxB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,cAAc,EACtB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC;IAoBV,aAAa,CACjB,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,cAAc,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO,GACzE,OAAO,CAAC,QAAQ,EAAE,CAAC;IAmBhB,WAAW,CACf,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,KAAK,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC/B,SAAS,EAAE,MAAM,EAAE,CAAC;QACpB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC,GACD,OAAO,CAAC,IAAI,EAAE,CAAC;IAgCZ,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAQrD,SAAS,CACb,QAAQ,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,EAAE,GACnB,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAkDjB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOxC,YAAY,CAChB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,IAAI,CAAC;IAYV,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IActD,gBAAgB,CACpB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,OAAO,CAAC,IAAI,CAAC;IAUV,aAAa,CACjB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAAG,IAAI,CAAC;IAiBlE,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CACvD,KAAK,CAAC;QACJ,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC/B,SAAS,EAAE,IAAI,CAAC;KACjB,CAAC,CACH;IAqBK,WAAW,CACf,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EAAE,EACnB,QAAQ,CAAC,EAAE,MAAM,EACjB,aAAa,CAAC,EAAE,MAAM,EACtB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC;IAkBV,aAAa,CACjB,SAAS,EAAE,MAAM,EAAE,EACnB,QAAQ,CAAC,EAAE,MAAM,EACjB,KAAK,SAAI,GACR,OAAO,CACR,KAAK,CAAC;QACJ,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC,CACH;IAqCK,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;QACpD,QAAQ,EAAE,OAAO,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IAqBI,oBAAoB,CACxB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,OAAO,CAAC,QAAQ,CAAC;IAuBd,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;QACjD,WAAW,EAAE,MAAM,CAAC;QACpB,gBAAgB,EAAE,MAAM,CAAC;QACzB,kBAAkB,EAAE,MAAM,CAAC;KAC5B,CAAC;IAYF,OAAO,CAAC,WAAW;IAenB,OAAO,CAAC,OAAO;CAsBhB"}
|
|
@@ -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
|