@omnixal/openclaw-nats-plugin 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 (74) hide show
  1. package/PLUGIN.md +94 -0
  2. package/bin/cli.ts +75 -0
  3. package/cli/bun-setup.ts +133 -0
  4. package/cli/detect-runtime.ts +40 -0
  5. package/cli/docker-setup.ts +54 -0
  6. package/cli/download-nats.ts +110 -0
  7. package/cli/env-writer.ts +58 -0
  8. package/cli/lifecycle.ts +109 -0
  9. package/cli/nats-config.ts +32 -0
  10. package/cli/paths.ts +20 -0
  11. package/cli/service-units.ts +168 -0
  12. package/cli/setup.ts +23 -0
  13. package/dashboard/dist/assets/index-CafgidIc.css +2 -0
  14. package/dashboard/dist/assets/index-OUWnIZmb.js +15 -0
  15. package/dashboard/dist/index.html +13 -0
  16. package/docker/docker-compose.yml +48 -0
  17. package/hooks/command-publisher/HOOK.md +13 -0
  18. package/hooks/command-publisher/handler.ts +23 -0
  19. package/hooks/gateway-startup/HOOK.md +13 -0
  20. package/hooks/gateway-startup/handler.ts +31 -0
  21. package/hooks/lifecycle-publisher/HOOK.md +12 -0
  22. package/hooks/lifecycle-publisher/handler.ts +20 -0
  23. package/hooks/shared/sidecar-client.ts +23 -0
  24. package/index.ts +3 -0
  25. package/openclaw.plugin.json +8 -0
  26. package/package.json +48 -0
  27. package/plugins/nats-context-engine/PLUGIN.md +14 -0
  28. package/plugins/nats-context-engine/http-handler.ts +131 -0
  29. package/plugins/nats-context-engine/index.ts +89 -0
  30. package/sidecar/Dockerfile +11 -0
  31. package/sidecar/bun.lock +212 -0
  32. package/sidecar/drizzle.config.ts +10 -0
  33. package/sidecar/package.json +28 -0
  34. package/sidecar/src/app.module.ts +33 -0
  35. package/sidecar/src/auth/api-key.middleware.ts +39 -0
  36. package/sidecar/src/config.ts +40 -0
  37. package/sidecar/src/consumer/consumer.module.ts +12 -0
  38. package/sidecar/src/consumer/consumer.service.ts +113 -0
  39. package/sidecar/src/db/migrations/0000_complete_mulholland_black.sql +5 -0
  40. package/sidecar/src/db/migrations/0001_high_psylocke.sql +9 -0
  41. package/sidecar/src/db/migrations/0002_common_stellaris.sql +1 -0
  42. package/sidecar/src/db/migrations/meta/0000_snapshot.json +49 -0
  43. package/sidecar/src/db/migrations/meta/0001_snapshot.json +109 -0
  44. package/sidecar/src/db/migrations/meta/0002_snapshot.json +117 -0
  45. package/sidecar/src/db/migrations/meta/_journal.json +27 -0
  46. package/sidecar/src/db/schema.ts +22 -0
  47. package/sidecar/src/dedup/dedup.module.ts +9 -0
  48. package/sidecar/src/dedup/dedup.repository.ts +29 -0
  49. package/sidecar/src/dedup/dedup.service.ts +38 -0
  50. package/sidecar/src/gateway/gateway-client.module.ts +8 -0
  51. package/sidecar/src/gateway/gateway-client.service.ts +131 -0
  52. package/sidecar/src/health/health.controller.ts +15 -0
  53. package/sidecar/src/health/health.module.ts +13 -0
  54. package/sidecar/src/health/health.service.ts +51 -0
  55. package/sidecar/src/index.ts +21 -0
  56. package/sidecar/src/nats-streams/nats-adapter.service.ts +133 -0
  57. package/sidecar/src/nats-streams/nats-streams.module.ts +8 -0
  58. package/sidecar/src/pending/pending.controller.ts +24 -0
  59. package/sidecar/src/pending/pending.module.ts +11 -0
  60. package/sidecar/src/pending/pending.repository.ts +62 -0
  61. package/sidecar/src/pending/pending.service.ts +38 -0
  62. package/sidecar/src/pre-handlers/dedup.handler.ts +22 -0
  63. package/sidecar/src/pre-handlers/enrich.handler.ts +14 -0
  64. package/sidecar/src/pre-handlers/filter.handler.ts +39 -0
  65. package/sidecar/src/pre-handlers/pipeline.service.ts +38 -0
  66. package/sidecar/src/pre-handlers/pre-handler.interface.ts +10 -0
  67. package/sidecar/src/pre-handlers/pre-handlers.module.ts +14 -0
  68. package/sidecar/src/pre-handlers/priority.handler.ts +14 -0
  69. package/sidecar/src/publisher/envelope.ts +36 -0
  70. package/sidecar/src/publisher/publisher.controller.ts +21 -0
  71. package/sidecar/src/publisher/publisher.module.ts +12 -0
  72. package/sidecar/src/publisher/publisher.service.ts +20 -0
  73. package/sidecar/src/validation/schemas.ts +19 -0
  74. package/sidecar/tsconfig.json +16 -0
@@ -0,0 +1,131 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import type { IncomingMessage, ServerResponse } from 'node:http';
4
+
5
+ const ROUTE_PREFIX = '/nats-dashboard';
6
+ const DIST_DIR = path.resolve(__dirname, '../../dashboard/dist');
7
+ const SIDECAR_URL = process.env.NATS_SIDECAR_URL || 'http://127.0.0.1:3104';
8
+ const API_KEY = process.env.NATS_PLUGIN_API_KEY || 'dev-nats-plugin-key';
9
+
10
+ const MIME_TYPES: Record<string, string> = {
11
+ '.html': 'text/html; charset=utf-8',
12
+ '.js': 'application/javascript; charset=utf-8',
13
+ '.css': 'text/css; charset=utf-8',
14
+ '.json': 'application/json; charset=utf-8',
15
+ '.svg': 'image/svg+xml',
16
+ '.png': 'image/png',
17
+ '.ico': 'image/x-icon',
18
+ '.woff2': 'font/woff2',
19
+ };
20
+
21
+ export function createDashboardHandler() {
22
+ return async (req: IncomingMessage, res: ServerResponse): Promise<boolean> => {
23
+ const url = new URL(req.url!, `http://${req.headers.host}`);
24
+ const subPath = url.pathname.slice(ROUTE_PREFIX.length);
25
+
26
+ // API proxy: /nats-dashboard/api/* → sidecar
27
+ if (subPath.startsWith('/api/')) {
28
+ return proxyToSidecar(subPath, url.search, req, res);
29
+ }
30
+
31
+ // Static files
32
+ if (req.method !== 'GET' && req.method !== 'HEAD') {
33
+ res.statusCode = 405;
34
+ res.end('Method Not Allowed');
35
+ return true;
36
+ }
37
+
38
+ return serveStatic(subPath, res);
39
+ };
40
+ }
41
+
42
+ async function proxyToSidecar(
43
+ subPath: string,
44
+ search: string,
45
+ req: IncomingMessage,
46
+ res: ServerResponse,
47
+ ): Promise<boolean> {
48
+ try {
49
+ const targetUrl = `${SIDECAR_URL}${subPath}${search}`;
50
+ const headers: Record<string, string> = {
51
+ 'Authorization': `Bearer ${API_KEY}`,
52
+ };
53
+ if (req.headers['content-type']) {
54
+ headers['Content-Type'] = req.headers['content-type'];
55
+ }
56
+
57
+ let body: string | undefined;
58
+ if (req.method === 'POST' || req.method === 'PUT') {
59
+ body = await readBody(req);
60
+ }
61
+
62
+ const upstream = await fetch(targetUrl, {
63
+ method: req.method || 'GET',
64
+ headers,
65
+ body,
66
+ signal: AbortSignal.timeout(10000),
67
+ });
68
+
69
+ res.statusCode = upstream.status;
70
+ res.setHeader('content-type', upstream.headers.get('content-type') || 'application/json');
71
+ const responseBody = await upstream.text();
72
+ res.end(responseBody);
73
+ } catch {
74
+ res.statusCode = 502;
75
+ res.setHeader('content-type', 'application/json');
76
+ res.end(JSON.stringify({ error: 'Sidecar unreachable' }));
77
+ }
78
+ return true;
79
+ }
80
+
81
+ const MAX_BODY_BYTES = 1_048_576; // 1MB
82
+
83
+ function readBody(req: IncomingMessage): Promise<string> {
84
+ return new Promise((resolve, reject) => {
85
+ const chunks: Buffer[] = [];
86
+ let total = 0;
87
+ req.on('data', (chunk: Buffer) => {
88
+ total += chunk.length;
89
+ if (total > MAX_BODY_BYTES) { req.destroy(); reject(new Error('Body too large')); return; }
90
+ chunks.push(chunk);
91
+ });
92
+ req.on('end', () => resolve(Buffer.concat(chunks).toString()));
93
+ req.on('error', reject);
94
+ });
95
+ }
96
+
97
+ async function serveStatic(subPath: string, res: ServerResponse): Promise<boolean> {
98
+ let filePath = subPath || '/index.html';
99
+ if (filePath === '/') filePath = '/index.html';
100
+
101
+ const fullPath = path.join(DIST_DIR, filePath);
102
+
103
+ // Prevent directory traversal
104
+ if (!fullPath.startsWith(DIST_DIR)) {
105
+ res.statusCode = 403;
106
+ res.end('Forbidden');
107
+ return true;
108
+ }
109
+
110
+ try {
111
+ const body = await fs.readFile(fullPath);
112
+ const ext = path.extname(fullPath);
113
+ res.statusCode = 200;
114
+ res.setHeader('content-type', MIME_TYPES[ext] || 'application/octet-stream');
115
+ res.setHeader('cache-control', ext === '.html' ? 'no-cache' : 'public, max-age=31536000, immutable');
116
+ res.end(body);
117
+ } catch {
118
+ // SPA fallback
119
+ try {
120
+ const indexHtml = await fs.readFile(path.join(DIST_DIR, 'index.html'));
121
+ res.statusCode = 200;
122
+ res.setHeader('content-type', 'text/html; charset=utf-8');
123
+ res.setHeader('cache-control', 'no-cache');
124
+ res.end(indexHtml);
125
+ } catch {
126
+ res.statusCode = 404;
127
+ res.end('Dashboard not built. Run: cd openclaw-nats-plugin/dashboard && bun run build');
128
+ }
129
+ }
130
+ return true;
131
+ }
@@ -0,0 +1,89 @@
1
+ import { publishToSidecar } from '../../hooks/shared/sidecar-client';
2
+ import { createDashboardHandler } from './http-handler';
3
+
4
+ export default function (api: any) {
5
+ // ── Subagent lifecycle ──────────────────────────────────────────────
6
+
7
+ api.registerHook('agent:subagent:spawned', async (event: any) => {
8
+ void publishToSidecar('agent.events.subagent.spawned', {
9
+ sessionKey: event.sessionKey,
10
+ subagentId: event.subagentId,
11
+ task: event.task,
12
+ timestamp: new Date().toISOString(),
13
+ });
14
+ }, { name: 'nats-subagent-spawned', description: 'Publish subagent spawn to NATS' });
15
+
16
+ api.registerHook('agent:subagent:ended', async (event: any) => {
17
+ void publishToSidecar('agent.events.subagent.ended', {
18
+ sessionKey: event.sessionKey,
19
+ subagentId: event.subagentId,
20
+ result: event.result,
21
+ exitReason: event.exitReason,
22
+ durationMs: event.durationMs,
23
+ timestamp: new Date().toISOString(),
24
+ });
25
+ }, { name: 'nats-subagent-ended', description: 'Publish subagent end to NATS' });
26
+
27
+ // ── Session lifecycle ───────────────────────────────────────────────
28
+
29
+ api.on('session_start', (event: any) => {
30
+ void publishToSidecar('agent.events.session.started', {
31
+ sessionKey: event.sessionKey,
32
+ sessionId: event.sessionId,
33
+ channel: event.channel,
34
+ timestamp: new Date().toISOString(),
35
+ });
36
+ }, { priority: 99 });
37
+
38
+ api.on('session_end', (event: any) => {
39
+ void publishToSidecar('agent.events.session.ended', {
40
+ sessionKey: event.sessionKey,
41
+ sessionId: event.sessionId,
42
+ channel: event.channel,
43
+ timestamp: new Date().toISOString(),
44
+ });
45
+ }, { priority: 99 });
46
+
47
+ // ── Agent run lifecycle ─────────────────────────────────────────────
48
+
49
+ api.on('agent_end', (event: any) => {
50
+ void publishToSidecar('agent.events.agent.run_ended', {
51
+ sessionKey: event.sessionKey,
52
+ runId: event.runId,
53
+ messageCount: event.messages?.length,
54
+ timestamp: new Date().toISOString(),
55
+ });
56
+ }, { priority: 99 });
57
+
58
+ // ── Message delivery ───────────────────────────────────────────────
59
+
60
+ api.registerHook('message:sent', async (event: any) => {
61
+ void publishToSidecar('agent.events.message.sent', {
62
+ sessionKey: event.sessionKey,
63
+ to: event.to,
64
+ channelId: event.channelId,
65
+ success: event.success,
66
+ error: event.error,
67
+ messageId: event.messageId,
68
+ timestamp: new Date().toISOString(),
69
+ });
70
+ }, { name: 'nats-message-sent', description: 'Publish message delivery status to NATS' });
71
+
72
+ // ── Context compaction ─────────────────────────────────────────────
73
+
74
+ api.on('after_compaction', (event: any) => {
75
+ void publishToSidecar('agent.events.context.compacted', {
76
+ sessionKey: event.sessionKey,
77
+ timestamp: new Date().toISOString(),
78
+ }, { priority: 8 });
79
+ }, { priority: 99 });
80
+
81
+ // ── Dashboard UI ─────────────────────────────────────────────────
82
+
83
+ api.registerHttpRoute({
84
+ path: '/nats-dashboard',
85
+ auth: 'plugin',
86
+ match: 'prefix',
87
+ handler: createDashboardHandler(),
88
+ });
89
+ }
@@ -0,0 +1,11 @@
1
+ FROM docker.io/oven/bun:latest AS builder
2
+ WORKDIR /app
3
+ COPY package.json bun.lock ./
4
+ RUN bun install --frozen-lockfile
5
+ COPY . .
6
+
7
+ FROM docker.io/oven/bun:latest
8
+ WORKDIR /app
9
+ COPY --from=builder /app .
10
+ EXPOSE 3104
11
+ CMD ["bun", "run", "src/index.ts"]
@@ -0,0 +1,212 @@
1
+ {
2
+ "lockfileVersion": 1,
3
+ "configVersion": 1,
4
+ "workspaces": {
5
+ "": {
6
+ "name": "@ai-entrepreneur/nats-sidecar",
7
+ "dependencies": {
8
+ "@onebun/core": "^0.2.3",
9
+ "@onebun/drizzle": "^0.2.0",
10
+ "@onebun/envs": "^0.2.0",
11
+ "@onebun/logger": "^0.2.0",
12
+ "@onebun/nats": "^0.2.2",
13
+ "arktype": "^2.2.0",
14
+ "ulid": "^2.3.0",
15
+ },
16
+ "devDependencies": {
17
+ "@types/bun": "latest",
18
+ },
19
+ },
20
+ },
21
+ "packages": {
22
+ "@ark/schema": ["@ark/schema@0.56.0", "", { "dependencies": { "@ark/util": "0.56.0" } }, "sha512-ECg3hox/6Z/nLajxXqNhgPtNdHWC9zNsDyskwO28WinoFEnWow4IsERNz9AnXRhTZJnYIlAJ4uGn3nlLk65vZA=="],
23
+
24
+ "@ark/util": ["@ark/util@0.56.0", "", {}, "sha512-BghfRC8b9pNs3vBoDJhcta0/c1J1rsoS1+HgVUreMFPdhz/CRAKReAu57YEllNaSy98rWAdY1gE+gFup7OXpgA=="],
25
+
26
+ "@drizzle-team/brocli": ["@drizzle-team/brocli@0.10.2", "", {}, "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w=="],
27
+
28
+ "@esbuild-kit/core-utils": ["@esbuild-kit/core-utils@3.3.2", "", { "dependencies": { "esbuild": "~0.18.20", "source-map-support": "^0.5.21" } }, "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ=="],
29
+
30
+ "@esbuild-kit/esm-loader": ["@esbuild-kit/esm-loader@2.6.5", "", { "dependencies": { "@esbuild-kit/core-utils": "^3.3.2", "get-tsconfig": "^4.7.0" } }, "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA=="],
31
+
32
+ "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="],
33
+
34
+ "@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="],
35
+
36
+ "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="],
37
+
38
+ "@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="],
39
+
40
+ "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="],
41
+
42
+ "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="],
43
+
44
+ "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="],
45
+
46
+ "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="],
47
+
48
+ "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="],
49
+
50
+ "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="],
51
+
52
+ "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="],
53
+
54
+ "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="],
55
+
56
+ "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="],
57
+
58
+ "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="],
59
+
60
+ "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="],
61
+
62
+ "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="],
63
+
64
+ "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="],
65
+
66
+ "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="],
67
+
68
+ "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="],
69
+
70
+ "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="],
71
+
72
+ "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="],
73
+
74
+ "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="],
75
+
76
+ "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="],
77
+
78
+ "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="],
79
+
80
+ "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="],
81
+
82
+ "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="],
83
+
84
+ "@nats-io/jetstream": ["@nats-io/jetstream@3.3.1", "", { "dependencies": { "@nats-io/nats-core": "3.3.1" } }, "sha512-oTIxM47pQfv4zCMlLN7FtARxSclMlUUPPn9I3VxRwMH+N2jkj1WCApu+tSL778KuljxfG8txi/MPwoWSXqbbQQ=="],
85
+
86
+ "@nats-io/nats-core": ["@nats-io/nats-core@3.3.1", "", { "dependencies": { "@nats-io/nkeys": "2.0.3", "@nats-io/nuid": "2.0.3" } }, "sha512-myFXGTo4cCfKrsLDjkoEz7FjjjvSfBRjun7Qx3n3Z5OzW4JUY8Ou7VQsGAdXLQxHN3ae/XNXvmXxshDoFPex4w=="],
87
+
88
+ "@nats-io/nkeys": ["@nats-io/nkeys@2.0.3", "", { "dependencies": { "tweetnacl": "^1.0.3" } }, "sha512-JVt56GuE6Z89KUkI4TXUbSI9fmIfAmk6PMPknijmuL72GcD+UgIomTcRWiNvvJKxA01sBbmIPStqJs5cMRBC3A=="],
89
+
90
+ "@nats-io/nuid": ["@nats-io/nuid@2.0.3", "", {}, "sha512-TpA3HEBna/qMVudy+3HZr5M3mo/L1JPofpVT4t0HkFGkz2Cn9wrlrQC8tvR8Md5Oa9//GtGG26eN0qEWF5Vqew=="],
91
+
92
+ "@nats-io/transport-node": ["@nats-io/transport-node@3.3.1", "", { "dependencies": { "@nats-io/nats-core": "3.3.1", "@nats-io/nkeys": "2.0.3", "@nats-io/nuid": "2.0.3" } }, "sha512-GBvY0VcvyQEILgy5bjpqU1GpDYmSF06bW59I7cewZuNGS9u3AoV/gf+a+3ep45T/Z+UC661atq/b7x+QV12w+Q=="],
93
+
94
+ "@onebun/core": ["@onebun/core@0.2.7", "", { "dependencies": { "@onebun/envs": "^0.2.1", "@onebun/logger": "^0.2.1", "@onebun/metrics": "^0.2.1", "@onebun/requests": "^0.2.1", "@onebun/trace": "^0.2.1", "arktype": "^2.0.0", "effect": "^3.13.10" } }, "sha512-KHWfp7LoU52NRyUi6gDr0qsaNea+9i+DJekmExzsMc2kpzt96G3gztUVO14gTQL1LdwMIM9D6VP4IK7CAua5gw=="],
95
+
96
+ "@onebun/drizzle": ["@onebun/drizzle@0.2.2", "", { "dependencies": { "@onebun/envs": "^0.2.1", "@onebun/logger": "^0.2.1", "arktype": "^2.0.0", "drizzle-arktype": "^0.1.3", "drizzle-kit": "^0.31.6", "drizzle-orm": "^0.44.7", "effect": "^3.13.10" }, "peerDependencies": { "@onebun/core": ">=0.2.0" }, "bin": { "onebun-drizzle": "bin/drizzle-kit.ts" } }, "sha512-HxH/+wfy3+ns6aKOfcGmpMz0OL3+KyRTUQ+no255hUGjsXUvxor9Fose8n6rTIXyfOrp4OMCoXZwzQ/dp1rXug=="],
97
+
98
+ "@onebun/envs": ["@onebun/envs@0.2.1", "", { "dependencies": { "effect": "^3.13.10" } }, "sha512-kiXJcA4ct194+aNJK8zkrVuaAgPPVpTkcW8tJU9XN9KOh8003lENOOuUZUcieMCxdMWUgo08lp9UgiwawLan+Q=="],
99
+
100
+ "@onebun/logger": ["@onebun/logger@0.2.1", "", { "dependencies": { "effect": "^3.13.10" } }, "sha512-u/zirsUSGBfbjVv274qqIHG5jzPBWY3vl8HzM6hjzsMCCpExgstkQiP1eP9rF1isIzhetwmyfBpYYc9eYsbrrw=="],
101
+
102
+ "@onebun/metrics": ["@onebun/metrics@0.2.1", "", { "dependencies": { "@onebun/requests": "^0.2.1", "effect": "^3.13.10", "prom-client": "^15.1.3" } }, "sha512-TTcWTSJc2WYAgs7gdSzV8/HyDDxo5HsihZo1jkP/jojLAFR+qiNCnbwj7H2BkdqwAJcV+jZ1s8h9yEQDVJlFqA=="],
103
+
104
+ "@onebun/nats": ["@onebun/nats@0.2.2", "", { "dependencies": { "@nats-io/jetstream": "^3.0.0-31", "@nats-io/transport-node": "^3.0.0-31", "effect": "^3.13.10" }, "peerDependencies": { "@onebun/core": ">=0.2.0" } }, "sha512-HUTFipH+hIul/0Pw+aDAO0N3JvK7ZUggPaJ/c/LqySGyiSA2uTNv21HkJRd+JTNfjTm+RsZ7XChwt4y9zBQlZw=="],
105
+
106
+ "@onebun/requests": ["@onebun/requests@0.2.1", "", { "dependencies": { "effect": "^3.13.10" } }, "sha512-Wit+o3zRiuZOM7O0nAJ0rpFVLgkypJ1UR5uuHi0IZuiCvGmxv+Vus2+QqHoCL141L7SPO1Xlywt8dVqqu4NP7w=="],
107
+
108
+ "@onebun/trace": ["@onebun/trace@0.2.1", "", { "dependencies": { "@onebun/requests": "^0.2.1", "@opentelemetry/api": "^1.8.0", "effect": "^3.13.10" } }, "sha512-PdWU1cHqcZeDpL9rwrIcPrZ9eNWS4sW6juyosOedqHZJQg4rve4SQ4eDR48yjFS7Zl+nealTgRLZnwV1PvF5ag=="],
109
+
110
+ "@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="],
111
+
112
+ "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
113
+
114
+ "@types/bun": ["@types/bun@1.3.10", "", { "dependencies": { "bun-types": "1.3.10" } }, "sha512-0+rlrUrOrTSskibryHbvQkDOWRJwJZqZlxrUs1u4oOoTln8+WIXBPmAuCF35SWB2z4Zl3E84Nl/D0P7803nigQ=="],
115
+
116
+ "@types/node": ["@types/node@25.4.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-9wLpoeWuBlcbBpOY3XmzSTG3oscB6xjBEEtn+pYXTfhyXhIxC5FsBer2KTopBlvKEiW9l13po9fq+SJY/5lkhw=="],
117
+
118
+ "arkregex": ["arkregex@0.0.5", "", { "dependencies": { "@ark/util": "0.56.0" } }, "sha512-ncYjBdLlh5/QnVsAA8De16Tc9EqmYM7y/WU9j+236KcyYNUXogpz3sC4ATIZYzzLxwI+0sEOaQLEmLmRleaEXw=="],
119
+
120
+ "arktype": ["arktype@2.2.0", "", { "dependencies": { "@ark/schema": "0.56.0", "@ark/util": "0.56.0", "arkregex": "0.0.5" } }, "sha512-t54MZ7ti5BhOEvzEkgKnWvqj+UbDfWig+DHr5I34xatymPusKLS0lQpNJd8M6DzmIto2QGszHfNKoFIT8tMCZQ=="],
121
+
122
+ "bintrees": ["bintrees@1.0.2", "", {}, "sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw=="],
123
+
124
+ "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
125
+
126
+ "bun-types": ["bun-types@1.3.10", "", { "dependencies": { "@types/node": "*" } }, "sha512-tcpfCCl6XWo6nCVnpcVrxQ+9AYN1iqMIzgrSKYMB/fjLtV2eyAVEg7AxQJuCq/26R6HpKWykQXuSOq/21RYcbg=="],
127
+
128
+ "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
129
+
130
+ "drizzle-arktype": ["drizzle-arktype@0.1.3", "", { "peerDependencies": { "arktype": ">=2.0.0", "drizzle-orm": ">=0.36.0" } }, "sha512-X66GB2pz7Nb+NmCZefDXpdoglxjGYnB2yRU5umAK2stVkl4rvV6i6XbMg1+w1HiY/ydC8gJVq4jKAARYazpb3g=="],
131
+
132
+ "drizzle-kit": ["drizzle-kit@0.31.9", "", { "dependencies": { "@drizzle-team/brocli": "^0.10.2", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.25.4", "esbuild-register": "^3.5.0" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-GViD3IgsXn7trFyBUUHyTFBpH/FsHTxYJ66qdbVggxef4UBPHRYxQaRzYLTuekYnk9i5FIEL9pbBIwMqX/Uwrg=="],
133
+
134
+ "drizzle-orm": ["drizzle-orm@0.44.7", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-quIpnYznjU9lHshEOAYLoZ9s3jweleHlZIAWR/jX9gAWNg/JhQ1wj0KGRf7/Zm+obRrYd9GjPVJg790QY9N5AQ=="],
135
+
136
+ "effect": ["effect@3.19.19", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-Yc8U/SVXo2dHnaP7zNBlAo83h/nzSJpi7vph6Hzyl4ulgMBIgPmz3UzOjb9sBgpFE00gC0iETR244sfXDNLHRg=="],
137
+
138
+ "esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="],
139
+
140
+ "esbuild-register": ["esbuild-register@3.6.0", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "esbuild": ">=0.12 <1" } }, "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg=="],
141
+
142
+ "fast-check": ["fast-check@3.23.2", "", { "dependencies": { "pure-rand": "^6.1.0" } }, "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A=="],
143
+
144
+ "get-tsconfig": ["get-tsconfig@4.13.6", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw=="],
145
+
146
+ "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
147
+
148
+ "prom-client": ["prom-client@15.1.3", "", { "dependencies": { "@opentelemetry/api": "^1.4.0", "tdigest": "^0.1.1" } }, "sha512-6ZiOBfCywsD4k1BN9IX0uZhF+tJkV8q8llP64G5Hajs4JOeVLPCwpPVcpXy3BwYiUGgyJzsJJQeOIv7+hDSq8g=="],
149
+
150
+ "pure-rand": ["pure-rand@6.1.0", "", {}, "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA=="],
151
+
152
+ "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="],
153
+
154
+ "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
155
+
156
+ "source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="],
157
+
158
+ "tdigest": ["tdigest@0.1.2", "", { "dependencies": { "bintrees": "1.0.2" } }, "sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA=="],
159
+
160
+ "tweetnacl": ["tweetnacl@1.0.3", "", {}, "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw=="],
161
+
162
+ "ulid": ["ulid@2.4.0", "", { "bin": { "ulid": "bin/cli.js" } }, "sha512-fIRiVTJNcSRmXKPZtGzFQv9WRrZ3M9eoptl/teFJvjOzmpU+/K/JH6HZ8deBfb5vMEpicJcLn7JmvdknlMq7Zg=="],
163
+
164
+ "undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="],
165
+
166
+ "@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="],
167
+
168
+ "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="],
169
+
170
+ "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.18.20", "", { "os": "android", "cpu": "arm64" }, "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ=="],
171
+
172
+ "@esbuild-kit/core-utils/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.18.20", "", { "os": "android", "cpu": "x64" }, "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg=="],
173
+
174
+ "@esbuild-kit/core-utils/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.18.20", "", { "os": "darwin", "cpu": "arm64" }, "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA=="],
175
+
176
+ "@esbuild-kit/core-utils/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.18.20", "", { "os": "darwin", "cpu": "x64" }, "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ=="],
177
+
178
+ "@esbuild-kit/core-utils/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.18.20", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw=="],
179
+
180
+ "@esbuild-kit/core-utils/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.18.20", "", { "os": "freebsd", "cpu": "x64" }, "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ=="],
181
+
182
+ "@esbuild-kit/core-utils/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.18.20", "", { "os": "linux", "cpu": "arm" }, "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg=="],
183
+
184
+ "@esbuild-kit/core-utils/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.18.20", "", { "os": "linux", "cpu": "arm64" }, "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA=="],
185
+
186
+ "@esbuild-kit/core-utils/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.18.20", "", { "os": "linux", "cpu": "ia32" }, "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA=="],
187
+
188
+ "@esbuild-kit/core-utils/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg=="],
189
+
190
+ "@esbuild-kit/core-utils/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ=="],
191
+
192
+ "@esbuild-kit/core-utils/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.18.20", "", { "os": "linux", "cpu": "ppc64" }, "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA=="],
193
+
194
+ "@esbuild-kit/core-utils/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A=="],
195
+
196
+ "@esbuild-kit/core-utils/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.18.20", "", { "os": "linux", "cpu": "s390x" }, "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ=="],
197
+
198
+ "@esbuild-kit/core-utils/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.18.20", "", { "os": "linux", "cpu": "x64" }, "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w=="],
199
+
200
+ "@esbuild-kit/core-utils/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.18.20", "", { "os": "none", "cpu": "x64" }, "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A=="],
201
+
202
+ "@esbuild-kit/core-utils/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.18.20", "", { "os": "openbsd", "cpu": "x64" }, "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg=="],
203
+
204
+ "@esbuild-kit/core-utils/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.18.20", "", { "os": "sunos", "cpu": "x64" }, "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ=="],
205
+
206
+ "@esbuild-kit/core-utils/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.18.20", "", { "os": "win32", "cpu": "arm64" }, "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg=="],
207
+
208
+ "@esbuild-kit/core-utils/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.18.20", "", { "os": "win32", "cpu": "ia32" }, "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g=="],
209
+
210
+ "@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="],
211
+ }
212
+ }
@@ -0,0 +1,10 @@
1
+ import { defineConfig } from 'drizzle-kit';
2
+
3
+ export default defineConfig({
4
+ schema: './src/db/schema.ts',
5
+ out: './src/db/migrations',
6
+ dialect: 'sqlite',
7
+ dbCredentials: {
8
+ url: process.env.DB_PATH || './data/nats-sidecar.db',
9
+ },
10
+ });
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "@omnixal/openclaw-nats-sidecar",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "main": "./src/index.ts",
7
+ "scripts": {
8
+ "dev": "bun run --watch src/index.ts",
9
+ "start": "bun run src/index.ts",
10
+ "test": "bun test",
11
+ "typecheck": "bunx tsc --noEmit",
12
+ "db:generate": "bunx onebun-drizzle generate",
13
+ "db:push": "bunx onebun-drizzle push",
14
+ "db:studio": "bunx onebun-drizzle studio"
15
+ },
16
+ "dependencies": {
17
+ "@onebun/core": "^0.2.3",
18
+ "@onebun/drizzle": "^0.2.0",
19
+ "@onebun/envs": "^0.2.0",
20
+ "@onebun/logger": "^0.2.0",
21
+ "@onebun/nats": "^0.2.2",
22
+ "arktype": "^2.2.0",
23
+ "ulid": "^2.3.0"
24
+ },
25
+ "devDependencies": {
26
+ "@types/bun": "latest"
27
+ }
28
+ }
@@ -0,0 +1,33 @@
1
+ import { Module } from '@onebun/core';
2
+ import { DrizzleModule, DatabaseType } from '@onebun/drizzle';
3
+ import { NatsStreamsModule } from './nats-streams/nats-streams.module';
4
+ import { DedupModule } from './dedup/dedup.module';
5
+ import { PublisherModule } from './publisher/publisher.module';
6
+ import { PreHandlersModule } from './pre-handlers/pre-handlers.module';
7
+ import { GatewayClientModule } from './gateway/gateway-client.module';
8
+ import { ConsumerModule } from './consumer/consumer.module';
9
+ import { PendingModule } from './pending/pending.module';
10
+ import { HealthModule } from './health/health.module';
11
+
12
+ @Module({
13
+ imports: [
14
+ DrizzleModule.forRoot({
15
+ connection: {
16
+ type: DatabaseType.SQLITE,
17
+ options: {
18
+ url: process.env.DB_PATH ?? './data/nats-sidecar.db',
19
+ },
20
+ },
21
+ migrationsFolder: './src/db/migrations',
22
+ }),
23
+ NatsStreamsModule,
24
+ DedupModule,
25
+ PublisherModule,
26
+ PreHandlersModule,
27
+ GatewayClientModule,
28
+ ConsumerModule,
29
+ PendingModule,
30
+ HealthModule,
31
+ ],
32
+ })
33
+ export class AppModule {}
@@ -0,0 +1,39 @@
1
+ import { Middleware, BaseMiddleware, type OneBunRequest, type OneBunResponse } from '@onebun/core';
2
+
3
+ export type CallerIdentity = 'plugin';
4
+
5
+ @Middleware()
6
+ export class ApiKeyMiddleware extends BaseMiddleware {
7
+ private pluginApiKey!: string;
8
+
9
+ constructor() {
10
+ super();
11
+ this.pluginApiKey = this.config.get('auth.pluginApiKey') as string;
12
+ }
13
+
14
+ async use(req: OneBunRequest, next: () => Promise<OneBunResponse>): Promise<OneBunResponse> {
15
+ const authHeader = req.headers.get('Authorization');
16
+
17
+ if (!authHeader) {
18
+ return new Response(JSON.stringify({ error: 'Missing Authorization header' }), {
19
+ status: 401,
20
+ headers: { 'Content-Type': 'application/json' },
21
+ });
22
+ }
23
+
24
+ const token = authHeader.startsWith('Bearer ')
25
+ ? authHeader.slice(7)
26
+ : authHeader;
27
+
28
+ if (token !== this.pluginApiKey) {
29
+ this.logger.warn('Invalid API key attempt');
30
+ return new Response(JSON.stringify({ error: 'Invalid API key' }), {
31
+ status: 401,
32
+ headers: { 'Content-Type': 'application/json' },
33
+ });
34
+ }
35
+
36
+ req.headers.set('x-caller', 'plugin');
37
+ return next();
38
+ }
39
+ }
@@ -0,0 +1,40 @@
1
+ import { Env, type InferConfigType } from '@onebun/core';
2
+
3
+ export const envSchema = {
4
+ server: {
5
+ port: Env.number({ default: 3104, env: 'PORT' }),
6
+ host: Env.string({ default: '0.0.0.0', env: 'HOST' }),
7
+ nodeEnv: Env.string({ default: 'development', env: 'NODE_ENV' }),
8
+ },
9
+ database: {
10
+ url: Env.string({ default: './data/nats-sidecar.db', env: 'DB_PATH' }),
11
+ },
12
+ nats: {
13
+ servers: Env.string({ default: 'nats://localhost:4222', env: 'NATS_SERVERS' }),
14
+ nkeyFile: Env.string({ default: '', env: 'NATS_NKEY_FILE' }),
15
+ reconnectDelayMs: Env.number({ default: 1000, env: 'NATS_RECONNECT_DELAY_MS' }),
16
+ maxReconnectAttempts: Env.number({ default: -1, env: 'NATS_MAX_RECONNECT_ATTEMPTS' }),
17
+ },
18
+ gateway: {
19
+ wsUrl: Env.string({ default: 'ws://localhost:18789', env: 'OPENCLAW_WS_URL' }),
20
+ token: Env.string({ default: '', env: 'OPENCLAW_GATEWAY_TOKEN' }),
21
+ },
22
+ consumer: {
23
+ name: Env.string({ default: 'openclaw-main', env: 'NATS_CONSUMER_NAME' }),
24
+ maxDeliver: Env.number({ default: 3, env: 'NATS_MAX_DELIVER' }),
25
+ ackWaitMs: Env.number({ default: 30000, env: 'NATS_ACK_WAIT_MS' }),
26
+ },
27
+ dedup: {
28
+ ttlSeconds: Env.number({ default: 60, env: 'NATS_DEDUP_TTL_SECONDS' }),
29
+ cleanupIntervalMs: Env.number({ default: 300000, env: 'NATS_DEDUP_CLEANUP_INTERVAL_MS' }),
30
+ },
31
+ auth: {
32
+ pluginApiKey: Env.string({ default: 'dev-nats-plugin-key', env: 'NATS_PLUGIN_API_KEY' }),
33
+ },
34
+ };
35
+
36
+ export type AppConfig = InferConfigType<typeof envSchema>;
37
+
38
+ declare module '@onebun/core' {
39
+ interface OneBunAppConfig extends AppConfig {}
40
+ }
@@ -0,0 +1,12 @@
1
+ import { Module } from '@onebun/core';
2
+ import { ConsumerService } from './consumer.service';
3
+ import { NatsStreamsModule } from '../nats-streams/nats-streams.module';
4
+ import { PreHandlersModule } from '../pre-handlers/pre-handlers.module';
5
+ import { GatewayClientModule } from '../gateway/gateway-client.module';
6
+ import { PendingModule } from '../pending/pending.module';
7
+
8
+ @Module({
9
+ imports: [NatsStreamsModule, PreHandlersModule, GatewayClientModule, PendingModule],
10
+ providers: [ConsumerService],
11
+ })
12
+ export class ConsumerModule {}