@ash-ai/server 0.0.3 → 0.0.5

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 (184) hide show
  1. package/dist/__tests__/attachments.test.d.ts +2 -0
  2. package/dist/__tests__/attachments.test.d.ts.map +1 -0
  3. package/dist/__tests__/attachments.test.js +57 -0
  4. package/dist/__tests__/attachments.test.js.map +1 -0
  5. package/dist/__tests__/bundle.test.d.ts +2 -0
  6. package/dist/__tests__/bundle.test.d.ts.map +1 -0
  7. package/dist/__tests__/bundle.test.js +55 -0
  8. package/dist/__tests__/bundle.test.js.map +1 -0
  9. package/dist/__tests__/coordinator.test.d.ts +2 -0
  10. package/dist/__tests__/coordinator.test.d.ts.map +1 -0
  11. package/dist/__tests__/coordinator.test.js +283 -0
  12. package/dist/__tests__/coordinator.test.js.map +1 -0
  13. package/dist/__tests__/crypto.test.d.ts +2 -0
  14. package/dist/__tests__/crypto.test.d.ts.map +1 -0
  15. package/dist/__tests__/crypto.test.js +72 -0
  16. package/dist/__tests__/crypto.test.js.map +1 -0
  17. package/dist/__tests__/file-store.test.d.ts +2 -0
  18. package/dist/__tests__/file-store.test.d.ts.map +1 -0
  19. package/dist/__tests__/file-store.test.js +105 -0
  20. package/dist/__tests__/file-store.test.js.map +1 -0
  21. package/dist/__tests__/files.test.js +18 -5
  22. package/dist/__tests__/files.test.js.map +1 -1
  23. package/dist/__tests__/multi-tenant.test.js +15 -1
  24. package/dist/__tests__/multi-tenant.test.js.map +1 -1
  25. package/dist/__tests__/openapi.test.js +6 -3
  26. package/dist/__tests__/openapi.test.js.map +1 -1
  27. package/dist/__tests__/queue.test.d.ts +2 -0
  28. package/dist/__tests__/queue.test.d.ts.map +1 -0
  29. package/dist/__tests__/queue.test.js +151 -0
  30. package/dist/__tests__/queue.test.js.map +1 -0
  31. package/dist/__tests__/usage.test.d.ts +2 -0
  32. package/dist/__tests__/usage.test.d.ts.map +1 -0
  33. package/dist/__tests__/usage.test.js +74 -0
  34. package/dist/__tests__/usage.test.js.map +1 -0
  35. package/dist/auth.d.ts +6 -2
  36. package/dist/auth.d.ts.map +1 -1
  37. package/dist/auth.js +23 -5
  38. package/dist/auth.js.map +1 -1
  39. package/dist/crypto.d.ts +14 -0
  40. package/dist/crypto.d.ts.map +1 -0
  41. package/dist/crypto.js +45 -0
  42. package/dist/crypto.js.map +1 -0
  43. package/dist/db/drizzle-db.d.ts +129 -0
  44. package/dist/db/drizzle-db.d.ts.map +1 -0
  45. package/dist/db/drizzle-db.js +789 -0
  46. package/dist/db/drizzle-db.js.map +1 -0
  47. package/dist/db/index.d.ts +129 -3
  48. package/dist/db/index.d.ts.map +1 -1
  49. package/dist/db/index.js +147 -8
  50. package/dist/db/index.js.map +1 -1
  51. package/dist/db/schema.pg.d.ts +1642 -0
  52. package/dist/db/schema.pg.d.ts.map +1 -0
  53. package/dist/db/schema.pg.js +151 -0
  54. package/dist/db/schema.pg.js.map +1 -0
  55. package/dist/db/schema.sqlite.d.ts +1800 -0
  56. package/dist/db/schema.sqlite.d.ts.map +1 -0
  57. package/dist/db/schema.sqlite.js +151 -0
  58. package/dist/db/schema.sqlite.js.map +1 -0
  59. package/dist/index.d.ts +2 -1
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js +16 -95
  62. package/dist/index.js.map +1 -1
  63. package/dist/queue/processor.d.ts +51 -0
  64. package/dist/queue/processor.d.ts.map +1 -0
  65. package/dist/queue/processor.js +98 -0
  66. package/dist/queue/processor.js.map +1 -0
  67. package/dist/routes/attachments.d.ts +3 -0
  68. package/dist/routes/attachments.d.ts.map +1 -0
  69. package/dist/routes/attachments.js +168 -0
  70. package/dist/routes/attachments.js.map +1 -0
  71. package/dist/routes/credentials.d.ts +11 -0
  72. package/dist/routes/credentials.d.ts.map +1 -0
  73. package/dist/routes/credentials.js +120 -0
  74. package/dist/routes/credentials.js.map +1 -0
  75. package/dist/routes/files.d.ts.map +1 -1
  76. package/dist/routes/files.js +97 -31
  77. package/dist/routes/files.js.map +1 -1
  78. package/dist/routes/health.d.ts.map +1 -1
  79. package/dist/routes/health.js +9 -1
  80. package/dist/routes/health.js.map +1 -1
  81. package/dist/routes/queue.d.ts +3 -0
  82. package/dist/routes/queue.d.ts.map +1 -0
  83. package/dist/routes/queue.js +144 -0
  84. package/dist/routes/queue.js.map +1 -0
  85. package/dist/routes/runners.d.ts +5 -0
  86. package/dist/routes/runners.d.ts.map +1 -1
  87. package/dist/routes/runners.js +42 -5
  88. package/dist/routes/runners.js.map +1 -1
  89. package/dist/routes/sessions.d.ts +2 -1
  90. package/dist/routes/sessions.d.ts.map +1 -1
  91. package/dist/routes/sessions.js +218 -12
  92. package/dist/routes/sessions.js.map +1 -1
  93. package/dist/routes/usage.d.ts +3 -0
  94. package/dist/routes/usage.d.ts.map +1 -0
  95. package/dist/routes/usage.js +64 -0
  96. package/dist/routes/usage.js.map +1 -0
  97. package/dist/routes/workspace.d.ts +4 -0
  98. package/dist/routes/workspace.d.ts.map +1 -0
  99. package/dist/routes/workspace.js +123 -0
  100. package/dist/routes/workspace.js.map +1 -0
  101. package/dist/runner/coordinator.d.ts +77 -9
  102. package/dist/runner/coordinator.d.ts.map +1 -1
  103. package/dist/runner/coordinator.js +163 -89
  104. package/dist/runner/coordinator.js.map +1 -1
  105. package/dist/runner/local-backend.d.ts +1 -0
  106. package/dist/runner/local-backend.d.ts.map +1 -1
  107. package/dist/runner/local-backend.js +8 -0
  108. package/dist/runner/local-backend.js.map +1 -1
  109. package/dist/runner/remote-backend.d.ts +2 -0
  110. package/dist/runner/remote-backend.d.ts.map +1 -1
  111. package/dist/runner/remote-backend.js +9 -0
  112. package/dist/runner/remote-backend.js.map +1 -1
  113. package/dist/runner/runner-client.d.ts +6 -0
  114. package/dist/runner/runner-client.d.ts.map +1 -1
  115. package/dist/runner/runner-client.js +15 -0
  116. package/dist/runner/runner-client.js.map +1 -1
  117. package/dist/runner/types.d.ts +6 -0
  118. package/dist/runner/types.d.ts.map +1 -1
  119. package/dist/schemas.d.ts.map +1 -1
  120. package/dist/schemas.js +85 -1
  121. package/dist/schemas.js.map +1 -1
  122. package/dist/server.d.ts +31 -0
  123. package/dist/server.d.ts.map +1 -0
  124. package/dist/server.js +176 -0
  125. package/dist/server.js.map +1 -0
  126. package/dist/telemetry/exporter.d.ts +16 -0
  127. package/dist/telemetry/exporter.d.ts.map +1 -0
  128. package/dist/telemetry/exporter.js +89 -0
  129. package/dist/telemetry/exporter.js.map +1 -0
  130. package/dist/usage/extractor.d.ts +18 -0
  131. package/dist/usage/extractor.d.ts.map +1 -0
  132. package/dist/usage/extractor.js +48 -0
  133. package/dist/usage/extractor.js.map +1 -0
  134. package/drizzle/pg/0000_thick_loners.sql +75 -0
  135. package/drizzle/pg/0001_rare_lester.sql +13 -0
  136. package/drizzle/pg/0002_short_shinko_yamashiro.sql +1 -0
  137. package/drizzle/pg/0003_remarkable_mastermind.sql +14 -0
  138. package/drizzle/pg/0004_warm_reaper.sql +18 -0
  139. package/drizzle/pg/0005_overconfident_mole_man.sql +14 -0
  140. package/drizzle/pg/0006_third_shiva.sql +13 -0
  141. package/drizzle/pg/0007_keen_shockwave.sql +2 -0
  142. package/drizzle/pg/meta/0000_snapshot.json +648 -0
  143. package/drizzle/pg/meta/0001_snapshot.json +743 -0
  144. package/drizzle/pg/meta/0002_snapshot.json +749 -0
  145. package/drizzle/pg/meta/0003_snapshot.json +841 -0
  146. package/drizzle/pg/meta/0004_snapshot.json +974 -0
  147. package/drizzle/pg/meta/0005_snapshot.json +1079 -0
  148. package/drizzle/pg/meta/0006_snapshot.json +1193 -0
  149. package/drizzle/pg/meta/0007_snapshot.json +1199 -0
  150. package/drizzle/pg/meta/_journal.json +62 -0
  151. package/drizzle/sqlite/0000_massive_kinsey_walden.sql +75 -0
  152. package/drizzle/sqlite/0001_quiet_phantom_reporter.sql +13 -0
  153. package/drizzle/sqlite/0002_broad_sheva_callister.sql +1 -0
  154. package/drizzle/sqlite/0003_thankful_agent_brand.sql +14 -0
  155. package/drizzle/sqlite/0004_productive_wolverine.sql +18 -0
  156. package/drizzle/sqlite/0005_chilly_carlie_cooper.sql +14 -0
  157. package/drizzle/sqlite/0006_workable_starfox.sql +13 -0
  158. package/drizzle/sqlite/0007_quick_hemingway.sql +19 -0
  159. package/drizzle/sqlite/meta/0000_snapshot.json +503 -0
  160. package/drizzle/sqlite/meta/0001_snapshot.json +587 -0
  161. package/drizzle/sqlite/meta/0002_snapshot.json +594 -0
  162. package/drizzle/sqlite/meta/0003_snapshot.json +685 -0
  163. package/drizzle/sqlite/meta/0004_snapshot.json +807 -0
  164. package/drizzle/sqlite/meta/0005_snapshot.json +897 -0
  165. package/drizzle/sqlite/meta/0006_snapshot.json +981 -0
  166. package/drizzle/sqlite/meta/0007_snapshot.json +988 -0
  167. package/drizzle/sqlite/meta/_journal.json +62 -0
  168. package/package.json +10 -5
  169. package/dist/__tests__/schema.test.d.ts +0 -2
  170. package/dist/__tests__/schema.test.d.ts.map +0 -1
  171. package/dist/__tests__/schema.test.js +0 -31
  172. package/dist/__tests__/schema.test.js.map +0 -1
  173. package/dist/db/dump-schema.d.ts +0 -10
  174. package/dist/db/dump-schema.d.ts.map +0 -1
  175. package/dist/db/dump-schema.js +0 -64
  176. package/dist/db/dump-schema.js.map +0 -1
  177. package/dist/db/pg.d.ts +0 -52
  178. package/dist/db/pg.d.ts.map +0 -1
  179. package/dist/db/pg.js +0 -398
  180. package/dist/db/pg.js.map +0 -1
  181. package/dist/db/sqlite.d.ts +0 -51
  182. package/dist/db/sqlite.d.ts.map +0 -1
  183. package/dist/db/sqlite.js +0 -412
  184. package/dist/db/sqlite.js.map +0 -1
@@ -0,0 +1,16 @@
1
+ export interface TelemetryEvent {
2
+ id: string;
3
+ sessionId: string;
4
+ agentName: string;
5
+ type: string;
6
+ data: Record<string, unknown>;
7
+ timestamp: string;
8
+ sequence: number;
9
+ }
10
+ export interface TelemetryExporter {
11
+ emit(event: Omit<TelemetryEvent, 'id' | 'timestamp' | 'sequence'>): void;
12
+ flush(): Promise<void>;
13
+ shutdown(): Promise<void>;
14
+ }
15
+ export declare function createTelemetryExporter(): TelemetryExporter;
16
+ //# sourceMappingURL=exporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exporter.d.ts","sourceRoot":"","sources":["../../src/telemetry/exporter.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,GAAG,WAAW,GAAG,UAAU,CAAC,GAAG,IAAI,CAAC;IACzE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AA8FD,wBAAgB,uBAAuB,IAAI,iBAAiB,CAQ3D"}
@@ -0,0 +1,89 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { hostname } from 'node:os';
3
+ const FLUSH_INTERVAL_MS = 5_000;
4
+ const MAX_BUFFER_SIZE = 100;
5
+ /** Maps Ash SessionEventType to platform event types. */
6
+ function mapEventType(type) {
7
+ if (type === 'tool_result')
8
+ return 'tool_end';
9
+ return type;
10
+ }
11
+ class HttpTelemetryExporter {
12
+ url;
13
+ key;
14
+ buffer = [];
15
+ sequences = new Map();
16
+ timer;
17
+ instanceId = hostname();
18
+ constructor(url, key) {
19
+ this.url = url;
20
+ this.key = key;
21
+ this.timer = setInterval(() => {
22
+ this.flush().catch((err) => console.warn(`[telemetry] flush failed: ${err}`));
23
+ }, FLUSH_INTERVAL_MS);
24
+ // Don't prevent process exit
25
+ this.timer.unref();
26
+ }
27
+ emit(event) {
28
+ const seq = (this.sequences.get(event.sessionId) ?? 0) + 1;
29
+ this.sequences.set(event.sessionId, seq);
30
+ this.buffer.push({
31
+ ...event,
32
+ type: mapEventType(event.type),
33
+ id: randomUUID(),
34
+ timestamp: new Date().toISOString(),
35
+ sequence: seq,
36
+ });
37
+ // Clean up sequence counter when session ends
38
+ if (event.type === 'lifecycle' && event.data?.status === 'ended') {
39
+ this.sequences.delete(event.sessionId);
40
+ }
41
+ if (this.buffer.length >= MAX_BUFFER_SIZE) {
42
+ this.flush().catch((err) => console.warn(`[telemetry] flush failed: ${err}`));
43
+ }
44
+ }
45
+ async flush() {
46
+ if (this.buffer.length === 0)
47
+ return;
48
+ const batch = this.buffer.splice(0);
49
+ try {
50
+ const res = await fetch(this.url, {
51
+ method: 'POST',
52
+ headers: {
53
+ 'Content-Type': 'application/json',
54
+ Authorization: `Bearer ${this.key}`,
55
+ },
56
+ body: JSON.stringify({
57
+ instanceId: this.instanceId,
58
+ events: batch,
59
+ }),
60
+ signal: AbortSignal.timeout(10_000),
61
+ });
62
+ if (!res.ok) {
63
+ console.warn(`[telemetry] POST ${this.url} returned ${res.status}`);
64
+ }
65
+ }
66
+ catch (err) {
67
+ console.warn(`[telemetry] POST failed: ${err}`);
68
+ // Fire-and-forget: drop the batch
69
+ }
70
+ }
71
+ async shutdown() {
72
+ clearInterval(this.timer);
73
+ await this.flush();
74
+ }
75
+ }
76
+ class NoopExporter {
77
+ emit() { }
78
+ async flush() { }
79
+ async shutdown() { }
80
+ }
81
+ export function createTelemetryExporter() {
82
+ const url = process.env.ASH_TELEMETRY_URL;
83
+ const key = process.env.ASH_TELEMETRY_KEY ?? '';
84
+ if (!url)
85
+ return new NoopExporter();
86
+ console.log(`[telemetry] exporter enabled → ${url}`);
87
+ return new HttpTelemetryExporter(url, key);
88
+ }
89
+ //# sourceMappingURL=exporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exporter.js","sourceRoot":"","sources":["../../src/telemetry/exporter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Extract usage metrics from an SDK message and persist as usage events.
3
+ *
4
+ * Claude SDK 'result' messages include a `usage` field:
5
+ * ```json
6
+ * { "type": "result", "usage": { "input_tokens": 100, "output_tokens": 50 } }
7
+ * ```
8
+ *
9
+ * Assistant messages have content blocks at `data.message.content`:
10
+ * ```json
11
+ * { "type": "assistant", "message": { "content": [{ "type": "tool_use", ... }] } }
12
+ * ```
13
+ *
14
+ * This function is non-blocking — it fires and forgets the DB writes.
15
+ * Only call once per turn (on 'result' messages) to avoid double-counting.
16
+ */
17
+ export declare function recordUsageFromMessage(data: Record<string, any>, sessionId: string, agentName: string, tenantId: string): void;
18
+ //# sourceMappingURL=extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/usage/extractor.ts"],"names":[],"mappings":"AAWA;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,IAAI,CAmCN"}
@@ -0,0 +1,48 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { insertUsageEvents } from '../db/index.js';
3
+ /**
4
+ * Extract usage metrics from an SDK message and persist as usage events.
5
+ *
6
+ * Claude SDK 'result' messages include a `usage` field:
7
+ * ```json
8
+ * { "type": "result", "usage": { "input_tokens": 100, "output_tokens": 50 } }
9
+ * ```
10
+ *
11
+ * Assistant messages have content blocks at `data.message.content`:
12
+ * ```json
13
+ * { "type": "assistant", "message": { "content": [{ "type": "tool_use", ... }] } }
14
+ * ```
15
+ *
16
+ * This function is non-blocking — it fires and forgets the DB writes.
17
+ * Only call once per turn (on 'result' messages) to avoid double-counting.
18
+ */
19
+ export function recordUsageFromMessage(data, sessionId, agentName, tenantId) {
20
+ const usage = data.usage;
21
+ const events = [];
22
+ if (usage) {
23
+ if (usage.input_tokens && usage.input_tokens > 0) {
24
+ events.push({ id: randomUUID(), tenantId, sessionId, agentName, eventType: 'input_tokens', value: usage.input_tokens });
25
+ }
26
+ if (usage.output_tokens && usage.output_tokens > 0) {
27
+ events.push({ id: randomUUID(), tenantId, sessionId, agentName, eventType: 'output_tokens', value: usage.output_tokens });
28
+ }
29
+ if (usage.cache_creation_input_tokens && usage.cache_creation_input_tokens > 0) {
30
+ events.push({ id: randomUUID(), tenantId, sessionId, agentName, eventType: 'cache_creation_tokens', value: usage.cache_creation_input_tokens });
31
+ }
32
+ if (usage.cache_read_input_tokens && usage.cache_read_input_tokens > 0) {
33
+ events.push({ id: randomUUID(), tenantId, sessionId, agentName, eventType: 'cache_read_tokens', value: usage.cache_read_input_tokens });
34
+ }
35
+ }
36
+ // Count tool calls from content blocks — SDK uses data.message.content for assistant messages
37
+ const contentBlocks = data.message?.content ?? data.content;
38
+ if (Array.isArray(contentBlocks)) {
39
+ const toolCallCount = contentBlocks.filter((b) => b.type === 'tool_use').length;
40
+ if (toolCallCount > 0) {
41
+ events.push({ id: randomUUID(), tenantId, sessionId, agentName, eventType: 'tool_call', value: toolCallCount });
42
+ }
43
+ }
44
+ // Record a single message event per turn
45
+ events.push({ id: randomUUID(), tenantId, sessionId, agentName, eventType: 'message', value: 1 });
46
+ insertUsageEvents(events).catch((err) => console.error(`[usage] Failed to record usage events: ${err}`));
47
+ }
48
+ //# sourceMappingURL=extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/usage/extractor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AASnD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,sBAAsB,CACpC,IAAyB,EACzB,SAAiB,EACjB,SAAiB,EACjB,QAAgB;IAEhB,MAAM,KAAK,GAAG,IAAI,CAAC,KAA8B,CAAC;IAElD,MAAM,MAAM,GAA4H,EAAE,CAAC;IAE3I,IAAI,KAAK,EAAE,CAAC;QACV,IAAI,KAAK,CAAC,YAAY,IAAI,KAAK,CAAC,YAAY,GAAG,CAAC,EAAE,CAAC;YACjD,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,KAAK,EAAE,KAAK,CAAC,YAAY,EAAE,CAAC,CAAC;QAC1H,CAAC;QACD,IAAI,KAAK,CAAC,aAAa,IAAI,KAAK,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;YACnD,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,eAAe,EAAE,KAAK,EAAE,KAAK,CAAC,aAAa,EAAE,CAAC,CAAC;QAC5H,CAAC;QACD,IAAI,KAAK,CAAC,2BAA2B,IAAI,KAAK,CAAC,2BAA2B,GAAG,CAAC,EAAE,CAAC;YAC/E,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,uBAAuB,EAAE,KAAK,EAAE,KAAK,CAAC,2BAA2B,EAAE,CAAC,CAAC;QAClJ,CAAC;QACD,IAAI,KAAK,CAAC,uBAAuB,IAAI,KAAK,CAAC,uBAAuB,GAAG,CAAC,EAAE,CAAC;YACvE,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,mBAAmB,EAAE,KAAK,EAAE,KAAK,CAAC,uBAAuB,EAAE,CAAC,CAAC;QAC1I,CAAC;IACH,CAAC;IAED,8FAA8F;IAC9F,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC;IAC5D,IAAI,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;QACjC,MAAM,aAAa,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,MAAM,CAAC;QACrF,IAAI,aAAa,GAAG,CAAC,EAAE,CAAC;YACtB,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,CAAC;QAClH,CAAC;IACH,CAAC;IAED,yCAAyC;IACzC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;IAElG,iBAAiB,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CACtC,OAAO,CAAC,KAAK,CAAC,0CAA0C,GAAG,EAAE,CAAC,CAC/D,CAAC;AACJ,CAAC"}
@@ -0,0 +1,75 @@
1
+ CREATE TABLE IF NOT EXISTS "agents" (
2
+ "id" text PRIMARY KEY NOT NULL,
3
+ "tenant_id" text DEFAULT 'default' NOT NULL,
4
+ "name" text NOT NULL,
5
+ "version" integer DEFAULT 1 NOT NULL,
6
+ "path" text NOT NULL,
7
+ "created_at" text NOT NULL,
8
+ "updated_at" text NOT NULL
9
+ );
10
+ --> statement-breakpoint
11
+ CREATE TABLE IF NOT EXISTS "api_keys" (
12
+ "id" text PRIMARY KEY NOT NULL,
13
+ "tenant_id" text NOT NULL,
14
+ "key_hash" text NOT NULL,
15
+ "label" text DEFAULT '' NOT NULL,
16
+ "created_at" text NOT NULL,
17
+ CONSTRAINT "api_keys_key_hash_unique" UNIQUE("key_hash")
18
+ );
19
+ --> statement-breakpoint
20
+ CREATE TABLE IF NOT EXISTS "messages" (
21
+ "id" text PRIMARY KEY NOT NULL,
22
+ "tenant_id" text DEFAULT 'default' NOT NULL,
23
+ "session_id" text NOT NULL,
24
+ "role" text NOT NULL,
25
+ "content" text NOT NULL,
26
+ "sequence" integer NOT NULL,
27
+ "created_at" text NOT NULL
28
+ );
29
+ --> statement-breakpoint
30
+ CREATE TABLE IF NOT EXISTS "sandboxes" (
31
+ "id" text PRIMARY KEY NOT NULL,
32
+ "tenant_id" text DEFAULT 'default' NOT NULL,
33
+ "session_id" text,
34
+ "agent_name" text NOT NULL,
35
+ "state" text DEFAULT 'warming' NOT NULL,
36
+ "workspace_dir" text NOT NULL,
37
+ "created_at" text NOT NULL,
38
+ "last_used_at" text NOT NULL
39
+ );
40
+ --> statement-breakpoint
41
+ CREATE TABLE IF NOT EXISTS "session_events" (
42
+ "id" text PRIMARY KEY NOT NULL,
43
+ "tenant_id" text DEFAULT 'default' NOT NULL,
44
+ "session_id" text NOT NULL,
45
+ "type" text NOT NULL,
46
+ "data" text,
47
+ "sequence" integer NOT NULL,
48
+ "created_at" text NOT NULL
49
+ );
50
+ --> statement-breakpoint
51
+ CREATE TABLE IF NOT EXISTS "sessions" (
52
+ "id" text PRIMARY KEY NOT NULL,
53
+ "tenant_id" text DEFAULT 'default' NOT NULL,
54
+ "agent_name" text NOT NULL,
55
+ "sandbox_id" text NOT NULL,
56
+ "status" text DEFAULT 'starting' NOT NULL,
57
+ "runner_id" text,
58
+ "created_at" text NOT NULL,
59
+ "last_active_at" text NOT NULL
60
+ );
61
+ --> statement-breakpoint
62
+ CREATE UNIQUE INDEX IF NOT EXISTS "idx_agents_tenant_name" ON "agents" USING btree ("tenant_id","name");--> statement-breakpoint
63
+ CREATE INDEX IF NOT EXISTS "idx_agents_tenant" ON "agents" USING btree ("tenant_id");--> statement-breakpoint
64
+ CREATE INDEX IF NOT EXISTS "idx_api_keys_tenant" ON "api_keys" USING btree ("tenant_id");--> statement-breakpoint
65
+ CREATE INDEX IF NOT EXISTS "idx_api_keys_hash" ON "api_keys" USING btree ("key_hash");--> statement-breakpoint
66
+ CREATE UNIQUE INDEX IF NOT EXISTS "idx_messages_unique_seq" ON "messages" USING btree ("tenant_id","session_id","sequence");--> statement-breakpoint
67
+ CREATE INDEX IF NOT EXISTS "idx_messages_session" ON "messages" USING btree ("tenant_id","session_id","sequence");--> statement-breakpoint
68
+ CREATE INDEX IF NOT EXISTS "idx_sandboxes_state" ON "sandboxes" USING btree ("state");--> statement-breakpoint
69
+ CREATE INDEX IF NOT EXISTS "idx_sandboxes_session" ON "sandboxes" USING btree ("session_id");--> statement-breakpoint
70
+ CREATE INDEX IF NOT EXISTS "idx_sandboxes_last_used" ON "sandboxes" USING btree ("last_used_at");--> statement-breakpoint
71
+ CREATE INDEX IF NOT EXISTS "idx_sandboxes_tenant" ON "sandboxes" USING btree ("tenant_id");--> statement-breakpoint
72
+ CREATE UNIQUE INDEX IF NOT EXISTS "idx_session_events_unique_seq" ON "session_events" USING btree ("tenant_id","session_id","sequence");--> statement-breakpoint
73
+ CREATE INDEX IF NOT EXISTS "idx_session_events_session" ON "session_events" USING btree ("tenant_id","session_id","sequence");--> statement-breakpoint
74
+ CREATE INDEX IF NOT EXISTS "idx_session_events_type" ON "session_events" USING btree ("tenant_id","session_id","type");--> statement-breakpoint
75
+ CREATE INDEX IF NOT EXISTS "idx_sessions_tenant" ON "sessions" USING btree ("tenant_id");
@@ -0,0 +1,13 @@
1
+ CREATE TABLE "runners" (
2
+ "id" text PRIMARY KEY NOT NULL,
3
+ "host" text NOT NULL,
4
+ "port" integer NOT NULL,
5
+ "max_sandboxes" integer DEFAULT 100 NOT NULL,
6
+ "active_count" integer DEFAULT 0 NOT NULL,
7
+ "warming_count" integer DEFAULT 0 NOT NULL,
8
+ "last_heartbeat_at" text NOT NULL,
9
+ "registered_at" text NOT NULL
10
+ );
11
+ --> statement-breakpoint
12
+ CREATE INDEX "idx_runners_heartbeat" ON "runners" USING btree ("last_heartbeat_at");--> statement-breakpoint
13
+ CREATE INDEX "idx_sessions_runner" ON "sessions" USING btree ("runner_id");
@@ -0,0 +1 @@
1
+ ALTER TABLE "sessions" ADD COLUMN "parent_session_id" text;
@@ -0,0 +1,14 @@
1
+ CREATE TABLE "credentials" (
2
+ "id" text PRIMARY KEY NOT NULL,
3
+ "tenant_id" text DEFAULT 'default' NOT NULL,
4
+ "type" text NOT NULL,
5
+ "encrypted_key" text NOT NULL,
6
+ "iv" text NOT NULL,
7
+ "auth_tag" text NOT NULL,
8
+ "label" text DEFAULT '' NOT NULL,
9
+ "active" integer DEFAULT 1 NOT NULL,
10
+ "created_at" text NOT NULL,
11
+ "last_used_at" text
12
+ );
13
+ --> statement-breakpoint
14
+ CREATE INDEX "idx_credentials_tenant" ON "credentials" USING btree ("tenant_id");
@@ -0,0 +1,18 @@
1
+ CREATE TABLE "queue_items" (
2
+ "id" text PRIMARY KEY NOT NULL,
3
+ "tenant_id" text DEFAULT 'default' NOT NULL,
4
+ "session_id" text,
5
+ "agent_name" text NOT NULL,
6
+ "prompt" text NOT NULL,
7
+ "status" text DEFAULT 'pending' NOT NULL,
8
+ "priority" integer DEFAULT 0 NOT NULL,
9
+ "retry_count" integer DEFAULT 0 NOT NULL,
10
+ "max_retries" integer DEFAULT 3 NOT NULL,
11
+ "error" text,
12
+ "created_at" text NOT NULL,
13
+ "started_at" text,
14
+ "completed_at" text
15
+ );
16
+ --> statement-breakpoint
17
+ CREATE INDEX "idx_queue_tenant" ON "queue_items" USING btree ("tenant_id");--> statement-breakpoint
18
+ CREATE INDEX "idx_queue_status" ON "queue_items" USING btree ("status","priority");
@@ -0,0 +1,14 @@
1
+ CREATE TABLE "attachments" (
2
+ "id" text PRIMARY KEY NOT NULL,
3
+ "tenant_id" text DEFAULT 'default' NOT NULL,
4
+ "message_id" text NOT NULL,
5
+ "session_id" text NOT NULL,
6
+ "filename" text NOT NULL,
7
+ "mime_type" text NOT NULL,
8
+ "size" integer NOT NULL,
9
+ "storage_path" text NOT NULL,
10
+ "created_at" text NOT NULL
11
+ );
12
+ --> statement-breakpoint
13
+ CREATE INDEX "idx_attachments_session" ON "attachments" USING btree ("tenant_id","session_id");--> statement-breakpoint
14
+ CREATE INDEX "idx_attachments_message" ON "attachments" USING btree ("message_id");
@@ -0,0 +1,13 @@
1
+ CREATE TABLE "usage_events" (
2
+ "id" text PRIMARY KEY NOT NULL,
3
+ "tenant_id" text DEFAULT 'default' NOT NULL,
4
+ "session_id" text NOT NULL,
5
+ "agent_name" text NOT NULL,
6
+ "event_type" text NOT NULL,
7
+ "value" integer NOT NULL,
8
+ "created_at" text NOT NULL
9
+ );
10
+ --> statement-breakpoint
11
+ CREATE INDEX "idx_usage_session" ON "usage_events" USING btree ("tenant_id","session_id");--> statement-breakpoint
12
+ CREATE INDEX "idx_usage_agent" ON "usage_events" USING btree ("tenant_id","agent_name");--> statement-breakpoint
13
+ CREATE INDEX "idx_usage_type" ON "usage_events" USING btree ("event_type");
@@ -0,0 +1,2 @@
1
+ ALTER TABLE "usage_events" ALTER COLUMN "value" SET DATA TYPE real;--> statement-breakpoint
2
+ ALTER TABLE "queue_items" ADD COLUMN "retry_after" text;