@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
package/README.md
ADDED
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
# @x404-r/sdk
|
|
2
|
+
|
|
3
|
+
**The runtime where context is never lost.**
|
|
4
|
+
|
|
5
|
+
Database-native infrastructure for crash-proof AI agents. Built on CockroachDB for distributed, fault-tolerant agent execution.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @x404-r/sdk
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Why x404-r?
|
|
14
|
+
|
|
15
|
+
Long-running AI agents lose context when workers crash. Hours of progress? **404 Not Found.**
|
|
16
|
+
|
|
17
|
+
x404-r fixes this. State lives in CockroachDB, not memory. Workers are stateless. Kill one, another picks up exactly where it left off.
|
|
18
|
+
|
|
19
|
+
## Features
|
|
20
|
+
|
|
21
|
+
- **Crash-Proof Execution**: Checkpoint state at any point. Resume exactly where you left off.
|
|
22
|
+
- **Dual Mode**: Run embedded (your DB) or cloud (our Lambda workers).
|
|
23
|
+
- **DAG Workflows**: Define complex workflows with step dependencies. Parallel execution when possible.
|
|
24
|
+
- **Priority Scheduling**: Enterprise tenants processed first via `FOR UPDATE SKIP LOCKED`.
|
|
25
|
+
- **AI Integration**: Built-in support for Gemini, OpenAI, and Anthropic.
|
|
26
|
+
- **Memory & Learning**: Query embeddings of past executions for context.
|
|
27
|
+
- **Multi-Tenant**: Full tenant isolation with usage tracking.
|
|
28
|
+
|
|
29
|
+
## Two Modes
|
|
30
|
+
|
|
31
|
+
### Mode A: Embedded (Self-Hosted)
|
|
32
|
+
|
|
33
|
+
Run everything on your infrastructure. Direct CockroachDB connection, local workers.
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { x404r } from '@x404-r/sdk';
|
|
37
|
+
|
|
38
|
+
const runtime = await new x404r({
|
|
39
|
+
mode: 'embedded', // optional, this is the default
|
|
40
|
+
connectionString: process.env.DATABASE_URL,
|
|
41
|
+
ai: { provider: 'gemini', apiKey: process.env.GEMINI_API_KEY },
|
|
42
|
+
}).ready();
|
|
43
|
+
|
|
44
|
+
// Define workflows with handlers
|
|
45
|
+
const workflow = runtime.workflow('my-task', {
|
|
46
|
+
steps: [{ name: 'process', handler: async (ctx) => { ... } }]
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Run your own workers
|
|
50
|
+
const worker = runtime.worker({ concurrency: 5 });
|
|
51
|
+
worker.register(workflow);
|
|
52
|
+
await worker.start();
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Mode B: Cloud (Hosted)
|
|
56
|
+
|
|
57
|
+
Zero infrastructure. Just submit jobs, Lambda workers execute them.
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import { x404r } from '@x404-r/sdk';
|
|
61
|
+
|
|
62
|
+
const runtime = new x404r({
|
|
63
|
+
mode: 'cloud',
|
|
64
|
+
apiKey: 'x404r_live_...', // Get from dashboard
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Submit job - Lambda executes it
|
|
68
|
+
const job = await runtime.submit('my-task', { input: 'data' });
|
|
69
|
+
|
|
70
|
+
// Check status
|
|
71
|
+
const status = await runtime.status(job.workflowId);
|
|
72
|
+
|
|
73
|
+
// Wait for completion
|
|
74
|
+
const result = await runtime.wait(job.workflowId);
|
|
75
|
+
|
|
76
|
+
// Time travel - replay from checkpoint
|
|
77
|
+
const checkpoints = await runtime.checkpoints(job.workflowId);
|
|
78
|
+
await runtime.replay(job.workflowId, checkpoints[0].id);
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Quick Start (Embedded Mode)
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
import { x404r } from '@x404-r/sdk';
|
|
85
|
+
|
|
86
|
+
// Initialize the runtime
|
|
87
|
+
const runtime = await new x404r({
|
|
88
|
+
connectionString: process.env.DATABASE_URL,
|
|
89
|
+
ai: {
|
|
90
|
+
provider: 'gemini',
|
|
91
|
+
apiKey: process.env.GEMINI_API_KEY,
|
|
92
|
+
},
|
|
93
|
+
debug: true,
|
|
94
|
+
}).ready();
|
|
95
|
+
|
|
96
|
+
// Define a crash-proof workflow
|
|
97
|
+
const myWorkflow = runtime.workflow('my-workflow', {
|
|
98
|
+
steps: [
|
|
99
|
+
{
|
|
100
|
+
name: 'process',
|
|
101
|
+
handler: async (ctx) => {
|
|
102
|
+
// Resume from checkpoint if crashed
|
|
103
|
+
let progress = ctx.state.progress || 0;
|
|
104
|
+
|
|
105
|
+
for (let i = progress; i < 100; i++) {
|
|
106
|
+
await doWork(i);
|
|
107
|
+
|
|
108
|
+
// Checkpoint - survives any crash!
|
|
109
|
+
await ctx.checkpoint({ progress: i + 1 });
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return { done: true };
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// Start workers
|
|
119
|
+
const worker = runtime.worker({ concurrency: 5 });
|
|
120
|
+
worker.register(myWorkflow);
|
|
121
|
+
await worker.start();
|
|
122
|
+
|
|
123
|
+
// Run workflows
|
|
124
|
+
const result = await myWorkflow.run({ input: 'data' }, { wait: true });
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Core Concepts
|
|
128
|
+
|
|
129
|
+
### Checkpoints = Context Saved
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
handler: async (ctx) => {
|
|
133
|
+
for (const item of items) {
|
|
134
|
+
await processItem(item);
|
|
135
|
+
|
|
136
|
+
// Saved to CockroachDB - crash-proof!
|
|
137
|
+
await ctx.checkpoint({ lastItem: item });
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
If the worker crashes after checkpoint, the next worker resumes from `ctx.state.lastItem`.
|
|
143
|
+
|
|
144
|
+
### DAG Workflows
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
const workflow = runtime.workflow('pipeline', {
|
|
148
|
+
steps: [
|
|
149
|
+
{ name: 'a', handler: async (ctx) => ({ result: 'a' }) },
|
|
150
|
+
{ name: 'b', handler: async (ctx) => ({ result: 'b' }) },
|
|
151
|
+
{ name: 'c', dependsOn: ['a', 'b'], handler: async (ctx) => ({ result: 'c' }) },
|
|
152
|
+
],
|
|
153
|
+
});
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Steps `a` and `b` run in parallel. Step `c` waits for both.
|
|
157
|
+
|
|
158
|
+
### Workers
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
const worker = runtime.worker({
|
|
162
|
+
concurrency: 5, // Max concurrent tasks
|
|
163
|
+
pollInterval: 1000, // Poll every 1s
|
|
164
|
+
heartbeatInterval: 10000, // Heartbeat every 10s
|
|
165
|
+
taskTypes: ['process'], // Optional: filter by step name
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
worker.register(workflow1);
|
|
169
|
+
worker.register(workflow2);
|
|
170
|
+
|
|
171
|
+
await worker.start();
|
|
172
|
+
await worker.stop(); // Graceful shutdown
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### AI Providers
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
// Gemini (default)
|
|
179
|
+
const runtime = await new x404r({
|
|
180
|
+
ai: { provider: 'gemini', apiKey: '...' },
|
|
181
|
+
}).ready();
|
|
182
|
+
|
|
183
|
+
// OpenAI (requires: npm install openai)
|
|
184
|
+
const runtime = await new x404r({
|
|
185
|
+
ai: { provider: 'openai', apiKey: '...', defaultModel: 'gpt-4-turbo' },
|
|
186
|
+
}).ready();
|
|
187
|
+
|
|
188
|
+
// Anthropic (requires: npm install @anthropic-ai/sdk)
|
|
189
|
+
const runtime = await new x404r({
|
|
190
|
+
ai: { provider: 'anthropic', apiKey: '...', defaultModel: 'claude-3-opus' },
|
|
191
|
+
}).ready();
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
#### Using AI in Handlers
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
handler: async (ctx) => {
|
|
198
|
+
// Simple generation
|
|
199
|
+
const response = await ctx.ai.generate('Analyze this...');
|
|
200
|
+
|
|
201
|
+
// With system prompt
|
|
202
|
+
const analysis = await ctx.ai.generate('Review the code', {
|
|
203
|
+
systemPrompt: 'You are a senior engineer.',
|
|
204
|
+
temperature: 0.3,
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// Structured JSON
|
|
208
|
+
const data = await ctx.ai.generateJSON<{ name: string }>('Extract name from...');
|
|
209
|
+
|
|
210
|
+
return { response, analysis, data };
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## API Reference
|
|
215
|
+
|
|
216
|
+
### x404r (Client)
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
const runtime = new x404r(config);
|
|
220
|
+
await runtime.ready(); // Wait for AI provider init
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
| Option | Type | Description |
|
|
224
|
+
|--------|------|-------------|
|
|
225
|
+
| connectionString | string | CockroachDB connection URL |
|
|
226
|
+
| ai | AIConfig | AI provider config |
|
|
227
|
+
| tenantId | string | Tenant ID (multi-tenant mode) |
|
|
228
|
+
| debug | boolean | Enable debug logging |
|
|
229
|
+
|
|
230
|
+
Methods:
|
|
231
|
+
- `workflow(name, definition)` - Create a workflow
|
|
232
|
+
- `worker(config)` - Create a worker
|
|
233
|
+
- `on(handler)` - Register event handler
|
|
234
|
+
- `close()` - Close connection
|
|
235
|
+
|
|
236
|
+
### WorkflowBuilder
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
const workflow = runtime.workflow<TInput, TOutput>(name, definition);
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Methods:
|
|
243
|
+
- `run(input, options)` - Execute the workflow
|
|
244
|
+
- `name` - Workflow name
|
|
245
|
+
- `version` - Workflow version
|
|
246
|
+
|
|
247
|
+
Run options:
|
|
248
|
+
- `wait: boolean` - Wait for completion
|
|
249
|
+
- `timeout: number` - Timeout in ms
|
|
250
|
+
- `priority: number` - Job priority
|
|
251
|
+
|
|
252
|
+
### Worker
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
const worker = runtime.worker(config);
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
| Option | Type | Default | Description |
|
|
259
|
+
|--------|------|---------|-------------|
|
|
260
|
+
| concurrency | number | 5 | Max concurrent tasks |
|
|
261
|
+
| pollInterval | number | 1000 | Poll interval (ms) |
|
|
262
|
+
| heartbeatInterval | number | 10000 | Heartbeat interval (ms) |
|
|
263
|
+
| taskTypes | string[] | [] | Filter by step name |
|
|
264
|
+
|
|
265
|
+
Methods:
|
|
266
|
+
- `register(workflow)` - Register a workflow
|
|
267
|
+
- `start()` - Start processing
|
|
268
|
+
- `stop()` - Graceful shutdown
|
|
269
|
+
- `id` - Worker ID
|
|
270
|
+
- `isRunning` - Running status
|
|
271
|
+
- `activeTaskCount` - Active tasks
|
|
272
|
+
|
|
273
|
+
### StepContext
|
|
274
|
+
|
|
275
|
+
Available in handlers:
|
|
276
|
+
|
|
277
|
+
| Property | Type | Description |
|
|
278
|
+
|----------|------|-------------|
|
|
279
|
+
| input | TInput | Step input |
|
|
280
|
+
| state | object | Checkpoint state |
|
|
281
|
+
| workflow | object | Workflow info |
|
|
282
|
+
| task | object | Task info |
|
|
283
|
+
| ai | AIProvider | AI provider |
|
|
284
|
+
|
|
285
|
+
Methods:
|
|
286
|
+
- `checkpoint(state?)` - Save checkpoint
|
|
287
|
+
- `log(message, data?)` - Log with prefix
|
|
288
|
+
- `sleep(ms)` - Async sleep
|
|
289
|
+
|
|
290
|
+
### Events
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
runtime.on(async (event) => {
|
|
294
|
+
switch (event.type) {
|
|
295
|
+
case 'workflow:created':
|
|
296
|
+
case 'workflow:completed':
|
|
297
|
+
case 'workflow:failed':
|
|
298
|
+
console.log(event.workflow);
|
|
299
|
+
break;
|
|
300
|
+
case 'task:started':
|
|
301
|
+
case 'task:completed':
|
|
302
|
+
case 'task:failed':
|
|
303
|
+
console.log(event.task);
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## CockroachDB Features
|
|
310
|
+
|
|
311
|
+
| Feature | Usage |
|
|
312
|
+
|---------|-------|
|
|
313
|
+
| `FOR UPDATE SKIP LOCKED` | Atomic task claiming |
|
|
314
|
+
| Transactions | Consistent checkpoints |
|
|
315
|
+
| Multi-region | Workers close to data |
|
|
316
|
+
| JSON columns | Flexible payloads |
|
|
317
|
+
|
|
318
|
+
## Examples
|
|
319
|
+
|
|
320
|
+
```bash
|
|
321
|
+
# Simple checkpoint demo
|
|
322
|
+
npx tsx examples/simple-workflow.ts
|
|
323
|
+
|
|
324
|
+
# AI code review agent
|
|
325
|
+
npx tsx examples/code-review-agent.ts
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## Environment Variables
|
|
329
|
+
|
|
330
|
+
```bash
|
|
331
|
+
DATABASE_URL=postgresql://user:pass@host:26257/db?sslmode=verify-full
|
|
332
|
+
GEMINI_API_KEY=your-gemini-key
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## Recovery Metrics & Benchmarking
|
|
336
|
+
|
|
337
|
+
x404-r tracks the value it provides. See exactly what crashes cost you - and what you saved.
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
import { MetricsCollector } from '@x404-r/sdk/metrics';
|
|
341
|
+
|
|
342
|
+
const metrics = new MetricsCollector();
|
|
343
|
+
|
|
344
|
+
// After running workflows, check your savings
|
|
345
|
+
const summary = metrics.getSummary();
|
|
346
|
+
|
|
347
|
+
console.log({
|
|
348
|
+
// How many times x404-r saved you from starting over
|
|
349
|
+
crashesRecovered: summary.reliability.crashRecoveries,
|
|
350
|
+
|
|
351
|
+
// Tokens you didn't have to re-generate
|
|
352
|
+
tokensSaved: summary.cost.tokensSaved,
|
|
353
|
+
|
|
354
|
+
// Money saved by not re-running crashed tasks
|
|
355
|
+
costSaved: summary.cost.savedByRecoveryUsd,
|
|
356
|
+
|
|
357
|
+
// Recovery success rate
|
|
358
|
+
checkpointHitRate: summary.reliability.checkpointHitRate,
|
|
359
|
+
});
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
### Without x404-r vs With x404-r
|
|
363
|
+
|
|
364
|
+
| Scenario | Without x404-r | With x404-r |
|
|
365
|
+
|----------|---------------|-------------|
|
|
366
|
+
| Worker crashes at step 8/10 | Restart from step 1 | Resume from step 8 |
|
|
367
|
+
| Tokens re-used | 0 (all lost) | ~80% preserved |
|
|
368
|
+
| Cost on crash | Full re-run ($$$) | Only remaining steps |
|
|
369
|
+
| Context | Lost forever | Saved in CockroachDB |
|
|
370
|
+
|
|
371
|
+
### Persist Metrics to Dashboard
|
|
372
|
+
|
|
373
|
+
```typescript
|
|
374
|
+
// Enable database persistence for dashboard visibility
|
|
375
|
+
metrics.setDatabase({
|
|
376
|
+
pool: dbPool,
|
|
377
|
+
tenantId: 'your-tenant-id',
|
|
378
|
+
flushIntervalMs: 30000, // Flush every 30s
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
// View in dashboard at http://localhost:3000
|
|
382
|
+
// See real-time: crashes recovered, tokens saved, cost savings
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
## License
|
|
386
|
+
|
|
387
|
+
MIT
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
**x404-r** - Context is never lost.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Provider Abstraction
|
|
3
|
+
* Supports Gemini, OpenAI, Anthropic, and AWS Bedrock
|
|
4
|
+
*/
|
|
5
|
+
import type { AIProvider, AIConfig, TokenUsage } from '../types.js';
|
|
6
|
+
export declare function estimateCost(model: string, usage: TokenUsage): number;
|
|
7
|
+
/**
|
|
8
|
+
* Create an AI provider from configuration
|
|
9
|
+
*/
|
|
10
|
+
export declare function createAIProvider(config: AIConfig): Promise<AIProvider>;
|
|
11
|
+
/**
|
|
12
|
+
* No-op AI provider for testing
|
|
13
|
+
*/
|
|
14
|
+
export declare class MockAIProvider implements AIProvider {
|
|
15
|
+
private _lastUsage;
|
|
16
|
+
get lastUsage(): TokenUsage;
|
|
17
|
+
generate(prompt: string): Promise<string>;
|
|
18
|
+
generateJSON<T>(): Promise<T>;
|
|
19
|
+
embed(): Promise<number[]>;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAA+B,UAAU,EAAE,MAAM,aAAa,CAAC;AAcjG,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,MAAM,CAMrE;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAa5E;AA8UD;;GAEG;AACH,qBAAa,cAAe,YAAW,UAAU;IAC/C,OAAO,CAAC,UAAU,CAAuE;IAEzF,IAAI,SAAS,IAAI,UAAU,CAE1B;IAEK,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAKzC,YAAY,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC;IAK7B,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;CAIjC"}
|