@agentlensai/server 0.9.0 → 0.11.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/dist/cloud/auth/api-key-middleware.d.ts +66 -0
- package/dist/cloud/auth/api-key-middleware.d.ts.map +1 -0
- package/dist/cloud/auth/api-key-middleware.js +147 -0
- package/dist/cloud/auth/api-key-middleware.js.map +1 -0
- package/dist/cloud/auth/api-keys.d.ts +90 -0
- package/dist/cloud/auth/api-keys.d.ts.map +1 -0
- package/dist/cloud/auth/api-keys.js +162 -0
- package/dist/cloud/auth/api-keys.js.map +1 -0
- package/dist/cloud/auth/audit-log.d.ts +66 -0
- package/dist/cloud/auth/audit-log.d.ts.map +1 -0
- package/dist/cloud/auth/audit-log.js +92 -0
- package/dist/cloud/auth/audit-log.js.map +1 -0
- package/dist/cloud/auth/auth-service.d.ts +77 -0
- package/dist/cloud/auth/auth-service.d.ts.map +1 -0
- package/dist/cloud/auth/auth-service.js +229 -0
- package/dist/cloud/auth/auth-service.js.map +1 -0
- package/dist/cloud/auth/brute-force.d.ts +36 -0
- package/dist/cloud/auth/brute-force.d.ts.map +1 -0
- package/dist/cloud/auth/brute-force.js +67 -0
- package/dist/cloud/auth/brute-force.js.map +1 -0
- package/dist/cloud/auth/index.d.ts +11 -0
- package/dist/cloud/auth/index.d.ts.map +1 -0
- package/dist/cloud/auth/index.js +11 -0
- package/dist/cloud/auth/index.js.map +1 -0
- package/dist/cloud/auth/jwt.d.ts +34 -0
- package/dist/cloud/auth/jwt.d.ts.map +1 -0
- package/dist/cloud/auth/jwt.js +68 -0
- package/dist/cloud/auth/jwt.js.map +1 -0
- package/dist/cloud/auth/oauth.d.ts +37 -0
- package/dist/cloud/auth/oauth.d.ts.map +1 -0
- package/dist/cloud/auth/oauth.js +120 -0
- package/dist/cloud/auth/oauth.js.map +1 -0
- package/dist/cloud/auth/passwords.d.ts +25 -0
- package/dist/cloud/auth/passwords.d.ts.map +1 -0
- package/dist/cloud/auth/passwords.js +50 -0
- package/dist/cloud/auth/passwords.js.map +1 -0
- package/dist/cloud/auth/rbac.d.ts +51 -0
- package/dist/cloud/auth/rbac.d.ts.map +1 -0
- package/dist/cloud/auth/rbac.js +89 -0
- package/dist/cloud/auth/rbac.js.map +1 -0
- package/dist/cloud/auth/tokens.d.ts +18 -0
- package/dist/cloud/auth/tokens.d.ts.map +1 -0
- package/dist/cloud/auth/tokens.js +29 -0
- package/dist/cloud/auth/tokens.js.map +1 -0
- package/dist/cloud/billing/billing-service.d.ts +44 -0
- package/dist/cloud/billing/billing-service.d.ts.map +1 -0
- package/dist/cloud/billing/billing-service.js +153 -0
- package/dist/cloud/billing/billing-service.js.map +1 -0
- package/dist/cloud/billing/index.d.ts +11 -0
- package/dist/cloud/billing/index.d.ts.map +1 -0
- package/dist/cloud/billing/index.js +11 -0
- package/dist/cloud/billing/index.js.map +1 -0
- package/dist/cloud/billing/invoice-service.d.ts +57 -0
- package/dist/cloud/billing/invoice-service.d.ts.map +1 -0
- package/dist/cloud/billing/invoice-service.js +123 -0
- package/dist/cloud/billing/invoice-service.js.map +1 -0
- package/dist/cloud/billing/plan-management.d.ts +46 -0
- package/dist/cloud/billing/plan-management.d.ts.map +1 -0
- package/dist/cloud/billing/plan-management.js +157 -0
- package/dist/cloud/billing/plan-management.js.map +1 -0
- package/dist/cloud/billing/quota-enforcement.d.ts +53 -0
- package/dist/cloud/billing/quota-enforcement.d.ts.map +1 -0
- package/dist/cloud/billing/quota-enforcement.js +143 -0
- package/dist/cloud/billing/quota-enforcement.js.map +1 -0
- package/dist/cloud/billing/stripe-client.d.ts +142 -0
- package/dist/cloud/billing/stripe-client.d.ts.map +1 -0
- package/dist/cloud/billing/stripe-client.js +169 -0
- package/dist/cloud/billing/stripe-client.js.map +1 -0
- package/dist/cloud/billing/trial-service.d.ts +47 -0
- package/dist/cloud/billing/trial-service.d.ts.map +1 -0
- package/dist/cloud/billing/trial-service.js +104 -0
- package/dist/cloud/billing/trial-service.js.map +1 -0
- package/dist/cloud/billing/usage-metering.d.ts +83 -0
- package/dist/cloud/billing/usage-metering.d.ts.map +1 -0
- package/dist/cloud/billing/usage-metering.js +174 -0
- package/dist/cloud/billing/usage-metering.js.map +1 -0
- package/dist/cloud/ingestion/backpressure.d.ts +107 -0
- package/dist/cloud/ingestion/backpressure.d.ts.map +1 -0
- package/dist/cloud/ingestion/backpressure.js +134 -0
- package/dist/cloud/ingestion/backpressure.js.map +1 -0
- package/dist/cloud/ingestion/batch-writer.d.ts +115 -0
- package/dist/cloud/ingestion/batch-writer.d.ts.map +1 -0
- package/dist/cloud/ingestion/batch-writer.js +319 -0
- package/dist/cloud/ingestion/batch-writer.js.map +1 -0
- package/dist/cloud/ingestion/dlq-manager.d.ts +116 -0
- package/dist/cloud/ingestion/dlq-manager.d.ts.map +1 -0
- package/dist/cloud/ingestion/dlq-manager.js +244 -0
- package/dist/cloud/ingestion/dlq-manager.js.map +1 -0
- package/dist/cloud/ingestion/event-queue.d.ts +105 -0
- package/dist/cloud/ingestion/event-queue.d.ts.map +1 -0
- package/dist/cloud/ingestion/event-queue.js +185 -0
- package/dist/cloud/ingestion/event-queue.js.map +1 -0
- package/dist/cloud/ingestion/gateway.d.ts +68 -0
- package/dist/cloud/ingestion/gateway.d.ts.map +1 -0
- package/dist/cloud/ingestion/gateway.js +198 -0
- package/dist/cloud/ingestion/gateway.js.map +1 -0
- package/dist/cloud/ingestion/index.d.ts +7 -0
- package/dist/cloud/ingestion/index.d.ts.map +1 -0
- package/dist/cloud/ingestion/index.js +7 -0
- package/dist/cloud/ingestion/index.js.map +1 -0
- package/dist/cloud/ingestion/rate-limiter.d.ts +73 -0
- package/dist/cloud/ingestion/rate-limiter.d.ts.map +1 -0
- package/dist/cloud/ingestion/rate-limiter.js +153 -0
- package/dist/cloud/ingestion/rate-limiter.js.map +1 -0
- package/dist/cloud/migrate.d.ts +45 -0
- package/dist/cloud/migrate.d.ts.map +1 -0
- package/dist/cloud/migrate.js +147 -0
- package/dist/cloud/migrate.js.map +1 -0
- package/dist/cloud/migration/export-import.d.ts +56 -0
- package/dist/cloud/migration/export-import.d.ts.map +1 -0
- package/dist/cloud/migration/export-import.js +289 -0
- package/dist/cloud/migration/export-import.js.map +1 -0
- package/dist/cloud/migration/index.d.ts +5 -0
- package/dist/cloud/migration/index.d.ts.map +1 -0
- package/dist/cloud/migration/index.js +5 -0
- package/dist/cloud/migration/index.js.map +1 -0
- package/dist/cloud/org-service.d.ts +68 -0
- package/dist/cloud/org-service.d.ts.map +1 -0
- package/dist/cloud/org-service.js +169 -0
- package/dist/cloud/org-service.js.map +1 -0
- package/dist/cloud/partition-maintenance.d.ts +29 -0
- package/dist/cloud/partition-maintenance.d.ts.map +1 -0
- package/dist/cloud/partition-maintenance.js +96 -0
- package/dist/cloud/partition-maintenance.js.map +1 -0
- package/dist/cloud/retention/index.d.ts +7 -0
- package/dist/cloud/retention/index.d.ts.map +1 -0
- package/dist/cloud/retention/index.js +7 -0
- package/dist/cloud/retention/index.js.map +1 -0
- package/dist/cloud/retention/partition-management.d.ts +61 -0
- package/dist/cloud/retention/partition-management.d.ts.map +1 -0
- package/dist/cloud/retention/partition-management.js +167 -0
- package/dist/cloud/retention/partition-management.js.map +1 -0
- package/dist/cloud/retention/retention-job.d.ts +70 -0
- package/dist/cloud/retention/retention-job.d.ts.map +1 -0
- package/dist/cloud/retention/retention-job.js +160 -0
- package/dist/cloud/retention/retention-job.js.map +1 -0
- package/dist/cloud/retention/retention-policy.d.ts +27 -0
- package/dist/cloud/retention/retention-policy.d.ts.map +1 -0
- package/dist/cloud/retention/retention-policy.js +36 -0
- package/dist/cloud/retention/retention-policy.js.map +1 -0
- package/dist/cloud/routes/api-key-routes.d.ts +38 -0
- package/dist/cloud/routes/api-key-routes.d.ts.map +1 -0
- package/dist/cloud/routes/api-key-routes.js +84 -0
- package/dist/cloud/routes/api-key-routes.js.map +1 -0
- package/dist/cloud/routes/audit-routes.d.ts +36 -0
- package/dist/cloud/routes/audit-routes.d.ts.map +1 -0
- package/dist/cloud/routes/audit-routes.js +47 -0
- package/dist/cloud/routes/audit-routes.js.map +1 -0
- package/dist/cloud/routes/billing-routes.d.ts +51 -0
- package/dist/cloud/routes/billing-routes.d.ts.map +1 -0
- package/dist/cloud/routes/billing-routes.js +114 -0
- package/dist/cloud/routes/billing-routes.js.map +1 -0
- package/dist/cloud/routes/onboarding-routes.d.ts +34 -0
- package/dist/cloud/routes/onboarding-routes.d.ts.map +1 -0
- package/dist/cloud/routes/onboarding-routes.js +58 -0
- package/dist/cloud/routes/onboarding-routes.js.map +1 -0
- package/dist/cloud/routes/org-routes.d.ts +80 -0
- package/dist/cloud/routes/org-routes.d.ts.map +1 -0
- package/dist/cloud/routes/org-routes.js +153 -0
- package/dist/cloud/routes/org-routes.js.map +1 -0
- package/dist/cloud/routes/usage-routes.d.ts +18 -0
- package/dist/cloud/routes/usage-routes.d.ts.map +1 -0
- package/dist/cloud/routes/usage-routes.js +66 -0
- package/dist/cloud/routes/usage-routes.js.map +1 -0
- package/dist/cloud/storage/adapter.d.ts +102 -0
- package/dist/cloud/storage/adapter.d.ts.map +1 -0
- package/dist/cloud/storage/adapter.js +21 -0
- package/dist/cloud/storage/adapter.js.map +1 -0
- package/dist/cloud/storage/index.d.ts +8 -0
- package/dist/cloud/storage/index.d.ts.map +1 -0
- package/dist/cloud/storage/index.js +7 -0
- package/dist/cloud/storage/index.js.map +1 -0
- package/dist/cloud/storage/postgres-adapter.d.ts +34 -0
- package/dist/cloud/storage/postgres-adapter.d.ts.map +1 -0
- package/dist/cloud/storage/postgres-adapter.js +544 -0
- package/dist/cloud/storage/postgres-adapter.js.map +1 -0
- package/dist/cloud/storage/sqlite-adapter.d.ts +29 -0
- package/dist/cloud/storage/sqlite-adapter.d.ts.map +1 -0
- package/dist/cloud/storage/sqlite-adapter.js +176 -0
- package/dist/cloud/storage/sqlite-adapter.js.map +1 -0
- package/dist/cloud/tenant-pool.d.ts +49 -0
- package/dist/cloud/tenant-pool.d.ts.map +1 -0
- package/dist/cloud/tenant-pool.js +61 -0
- package/dist/cloud/tenant-pool.js.map +1 -0
- package/dist/db/capability-store.d.ts +4 -0
- package/dist/db/capability-store.d.ts.map +1 -1
- package/dist/db/capability-store.js +20 -0
- package/dist/db/capability-store.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -1
- package/dist/routes/audit.js +3 -3
- package/dist/routes/audit.js.map +1 -1
- package/dist/routes/capabilities-top.d.ts +15 -0
- package/dist/routes/capabilities-top.d.ts.map +1 -0
- package/dist/routes/capabilities-top.js +77 -0
- package/dist/routes/capabilities-top.js.map +1 -0
- package/dist/routes/community.d.ts.map +1 -1
- package/dist/routes/community.js +85 -3
- package/dist/routes/community.js.map +1 -1
- package/dist/routes/delegations-top.d.ts +12 -0
- package/dist/routes/delegations-top.d.ts.map +1 -0
- package/dist/routes/delegations-top.js +43 -0
- package/dist/routes/delegations-top.js.map +1 -0
- package/dist/services/community-service.d.ts +6 -0
- package/dist/services/community-service.d.ts.map +1 -1
- package/dist/services/community-service.js +31 -0
- package/dist/services/community-service.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,544 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostgreSQL Storage Adapter (S-4.2, S-4.3, S-4.4)
|
|
3
|
+
*
|
|
4
|
+
* Implements StorageAdapter for the cloud Postgres backend.
|
|
5
|
+
* Uses the tenant pool from B2A for automatic org scoping via
|
|
6
|
+
* SET LOCAL app.current_org within transactions.
|
|
7
|
+
*
|
|
8
|
+
* All queries use org_id composite indexes. RLS provides automatic
|
|
9
|
+
* tenant scoping as defense-in-depth (queries also filter by org_id
|
|
10
|
+
* explicitly for index usage).
|
|
11
|
+
*
|
|
12
|
+
* S-4.3: Analytics queries use date_trunc + window functions for Postgres.
|
|
13
|
+
* S-4.4: Full-text search uses tsvector/to_tsquery with GIN indexes.
|
|
14
|
+
*/
|
|
15
|
+
import { withTenantTransaction } from '../tenant-pool.js';
|
|
16
|
+
// ─── Helpers ────────────────────────────────────────────────
|
|
17
|
+
function safeJson(val, fallback) {
|
|
18
|
+
if (val === null || val === undefined)
|
|
19
|
+
return fallback;
|
|
20
|
+
if (typeof val === 'object')
|
|
21
|
+
return val;
|
|
22
|
+
if (typeof val === 'string') {
|
|
23
|
+
try {
|
|
24
|
+
return JSON.parse(val);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return fallback;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return fallback;
|
|
31
|
+
}
|
|
32
|
+
function mapEventRow(row) {
|
|
33
|
+
return {
|
|
34
|
+
id: row.id,
|
|
35
|
+
timestamp: row.timestamp,
|
|
36
|
+
sessionId: (row.session_id ?? row.sessionId),
|
|
37
|
+
agentId: (row.agent_id ?? row.agentId),
|
|
38
|
+
eventType: (row.event_type ?? row.eventType),
|
|
39
|
+
severity: row.severity,
|
|
40
|
+
payload: safeJson(row.payload, {}),
|
|
41
|
+
metadata: safeJson(row.metadata, {}),
|
|
42
|
+
prevHash: (row.prev_hash ?? row.prevHash),
|
|
43
|
+
hash: row.hash,
|
|
44
|
+
tenantId: (row.tenant_id ?? row.tenantId ?? row.org_id ?? row.orgId),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function mapSessionRow(row) {
|
|
48
|
+
return {
|
|
49
|
+
id: row.id,
|
|
50
|
+
agentId: (row.agent_id ?? row.agentId),
|
|
51
|
+
agentName: (row.agent_name ?? row.agentName),
|
|
52
|
+
startedAt: (row.started_at ?? row.startedAt),
|
|
53
|
+
endedAt: (row.ended_at ?? row.endedAt),
|
|
54
|
+
status: row.status,
|
|
55
|
+
eventCount: Number(row.event_count ?? row.eventCount ?? 0),
|
|
56
|
+
toolCallCount: Number(row.tool_call_count ?? row.toolCallCount ?? 0),
|
|
57
|
+
errorCount: Number(row.error_count ?? row.errorCount ?? 0),
|
|
58
|
+
totalCostUsd: Number(row.total_cost_usd ?? row.totalCostUsd ?? 0),
|
|
59
|
+
llmCallCount: Number(row.llm_call_count ?? row.llmCallCount ?? 0),
|
|
60
|
+
totalInputTokens: Number(row.total_input_tokens ?? row.totalInputTokens ?? 0),
|
|
61
|
+
totalOutputTokens: Number(row.total_output_tokens ?? row.totalOutputTokens ?? 0),
|
|
62
|
+
tags: safeJson(row.tags, []),
|
|
63
|
+
tenantId: (row.tenant_id ?? row.tenantId ?? row.org_id ?? row.orgId),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function mapAgentRow(row) {
|
|
67
|
+
return {
|
|
68
|
+
id: row.id,
|
|
69
|
+
name: row.name,
|
|
70
|
+
description: row.description,
|
|
71
|
+
firstSeenAt: (row.first_seen_at ?? row.firstSeenAt),
|
|
72
|
+
lastSeenAt: (row.last_seen_at ?? row.lastSeenAt),
|
|
73
|
+
sessionCount: Number(row.session_count ?? row.sessionCount ?? 0),
|
|
74
|
+
tenantId: (row.tenant_id ?? row.tenantId ?? row.org_id ?? row.orgId),
|
|
75
|
+
modelOverride: (row.model_override ?? row.modelOverride),
|
|
76
|
+
pausedAt: (row.paused_at ?? row.pausedAt),
|
|
77
|
+
pauseReason: (row.pause_reason ?? row.pauseReason),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function buildEventWhere(orgId, query) {
|
|
81
|
+
const where = [`org_id = $1`];
|
|
82
|
+
const params = [orgId];
|
|
83
|
+
let idx = 2;
|
|
84
|
+
if (query.sessionId) {
|
|
85
|
+
where.push(`session_id = $${idx}`);
|
|
86
|
+
params.push(query.sessionId);
|
|
87
|
+
idx++;
|
|
88
|
+
}
|
|
89
|
+
if (query.agentId) {
|
|
90
|
+
where.push(`agent_id = $${idx}`);
|
|
91
|
+
params.push(query.agentId);
|
|
92
|
+
idx++;
|
|
93
|
+
}
|
|
94
|
+
if (query.eventType) {
|
|
95
|
+
const types = Array.isArray(query.eventType) ? query.eventType : [query.eventType];
|
|
96
|
+
where.push(`event_type = ANY($${idx})`);
|
|
97
|
+
params.push(types);
|
|
98
|
+
idx++;
|
|
99
|
+
}
|
|
100
|
+
if (query.severity) {
|
|
101
|
+
const sevs = Array.isArray(query.severity) ? query.severity : [query.severity];
|
|
102
|
+
where.push(`severity = ANY($${idx})`);
|
|
103
|
+
params.push(sevs);
|
|
104
|
+
idx++;
|
|
105
|
+
}
|
|
106
|
+
if (query.from) {
|
|
107
|
+
where.push(`timestamp >= $${idx}`);
|
|
108
|
+
params.push(query.from);
|
|
109
|
+
idx++;
|
|
110
|
+
}
|
|
111
|
+
if (query.to) {
|
|
112
|
+
where.push(`timestamp <= $${idx}`);
|
|
113
|
+
params.push(query.to);
|
|
114
|
+
idx++;
|
|
115
|
+
}
|
|
116
|
+
if (query.search) {
|
|
117
|
+
where.push(`payload::text ILIKE $${idx}`);
|
|
118
|
+
params.push(`%${query.search}%`);
|
|
119
|
+
idx++;
|
|
120
|
+
}
|
|
121
|
+
return { where, params, paramIdx: idx };
|
|
122
|
+
}
|
|
123
|
+
function buildSessionWhere(orgId, query) {
|
|
124
|
+
const where = [`org_id = $1`];
|
|
125
|
+
const params = [orgId];
|
|
126
|
+
let idx = 2;
|
|
127
|
+
if (query.agentId) {
|
|
128
|
+
where.push(`agent_id = $${idx}`);
|
|
129
|
+
params.push(query.agentId);
|
|
130
|
+
idx++;
|
|
131
|
+
}
|
|
132
|
+
if (query.status) {
|
|
133
|
+
const statuses = Array.isArray(query.status) ? query.status : [query.status];
|
|
134
|
+
where.push(`status = ANY($${idx})`);
|
|
135
|
+
params.push(statuses);
|
|
136
|
+
idx++;
|
|
137
|
+
}
|
|
138
|
+
if (query.from) {
|
|
139
|
+
where.push(`started_at >= $${idx}`);
|
|
140
|
+
params.push(query.from);
|
|
141
|
+
idx++;
|
|
142
|
+
}
|
|
143
|
+
if (query.to) {
|
|
144
|
+
where.push(`started_at <= $${idx}`);
|
|
145
|
+
params.push(query.to);
|
|
146
|
+
idx++;
|
|
147
|
+
}
|
|
148
|
+
if (query.tags && query.tags.length > 0) {
|
|
149
|
+
where.push(`tags ?| $${idx}`);
|
|
150
|
+
params.push(query.tags);
|
|
151
|
+
idx++;
|
|
152
|
+
}
|
|
153
|
+
return { where, params, paramIdx: idx };
|
|
154
|
+
}
|
|
155
|
+
// ─── Analytics Helpers (S-4.3) ──────────────────────────────
|
|
156
|
+
const ALLOWED_GRANULARITY = { hour: 'hour', day: 'day', week: 'week' };
|
|
157
|
+
function pgDateTrunc(granularity) {
|
|
158
|
+
const val = ALLOWED_GRANULARITY[granularity];
|
|
159
|
+
if (!val)
|
|
160
|
+
throw new Error(`Invalid granularity: ${granularity}`);
|
|
161
|
+
return val;
|
|
162
|
+
}
|
|
163
|
+
// ─── PostgreSQL Storage Adapter ─────────────────────────────
|
|
164
|
+
export class PostgresStorageAdapter {
|
|
165
|
+
pool;
|
|
166
|
+
constructor(pool) {
|
|
167
|
+
this.pool = pool;
|
|
168
|
+
}
|
|
169
|
+
async queryEvents(orgId, query) {
|
|
170
|
+
return withTenantTransaction(this.pool, orgId, async (client) => {
|
|
171
|
+
const { where, params, paramIdx } = buildEventWhere(orgId, query);
|
|
172
|
+
const whereClause = where.join(' AND ');
|
|
173
|
+
const orderDir = query.order === 'asc' ? 'ASC' : 'DESC';
|
|
174
|
+
const limit = Math.min(query.limit ?? 50, 500);
|
|
175
|
+
const offset = query.offset ?? 0;
|
|
176
|
+
const countResult = await client.query(`SELECT COUNT(*)::int AS total FROM events WHERE ${whereClause}`, params);
|
|
177
|
+
const total = countResult.rows[0]?.total ?? 0;
|
|
178
|
+
const dataResult = await client.query(`SELECT * FROM events WHERE ${whereClause} ORDER BY timestamp ${orderDir} LIMIT $${paramIdx} OFFSET $${paramIdx + 1}`, [...params, limit, offset]);
|
|
179
|
+
const events = dataResult.rows.map(mapEventRow);
|
|
180
|
+
return { events, total, hasMore: offset + events.length < total };
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
async getEventsBySession(orgId, sessionId) {
|
|
184
|
+
return withTenantTransaction(this.pool, orgId, async (client) => {
|
|
185
|
+
const result = await client.query(`SELECT * FROM events WHERE org_id = $1 AND session_id = $2 ORDER BY timestamp ASC`, [orgId, sessionId]);
|
|
186
|
+
return result.rows.map(mapEventRow);
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
async getSessions(orgId, query) {
|
|
190
|
+
return withTenantTransaction(this.pool, orgId, async (client) => {
|
|
191
|
+
const { where, params, paramIdx } = buildSessionWhere(orgId, query);
|
|
192
|
+
const whereClause = where.join(' AND ');
|
|
193
|
+
const limit = Math.min(query.limit ?? 50, 500);
|
|
194
|
+
const offset = query.offset ?? 0;
|
|
195
|
+
const countResult = await client.query(`SELECT COUNT(*)::int AS total FROM sessions WHERE ${whereClause}`, params);
|
|
196
|
+
const total = countResult.rows[0]?.total ?? 0;
|
|
197
|
+
const dataResult = await client.query(`SELECT * FROM sessions WHERE ${whereClause} ORDER BY started_at DESC LIMIT $${paramIdx} OFFSET $${paramIdx + 1}`, [...params, limit, offset]);
|
|
198
|
+
const items = dataResult.rows.map(mapSessionRow);
|
|
199
|
+
return { items, total, hasMore: offset + items.length < total };
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
async getSession(orgId, sessionId) {
|
|
203
|
+
return withTenantTransaction(this.pool, orgId, async (client) => {
|
|
204
|
+
const result = await client.query(`SELECT * FROM sessions WHERE org_id = $1 AND id = $2 LIMIT 1`, [orgId, sessionId]);
|
|
205
|
+
if (result.rows.length === 0)
|
|
206
|
+
return null;
|
|
207
|
+
return mapSessionRow(result.rows[0]);
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
async getAgents(orgId) {
|
|
211
|
+
return withTenantTransaction(this.pool, orgId, async (client) => {
|
|
212
|
+
const result = await client.query(`SELECT * FROM agents WHERE org_id = $1 ORDER BY last_seen_at DESC`, [orgId]);
|
|
213
|
+
return result.rows.map(mapAgentRow);
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
async getStats(orgId) {
|
|
217
|
+
return withTenantTransaction(this.pool, orgId, async (client) => {
|
|
218
|
+
const eventCount = await client.query(`SELECT COUNT(*)::int AS c FROM events WHERE org_id = $1`, [orgId]);
|
|
219
|
+
const sessionCount = await client.query(`SELECT COUNT(*)::int AS c FROM sessions WHERE org_id = $1`, [orgId]);
|
|
220
|
+
const agentCount = await client.query(`SELECT COUNT(*)::int AS c FROM agents WHERE org_id = $1`, [orgId]);
|
|
221
|
+
const oldest = await client.query(`SELECT timestamp FROM events WHERE org_id = $1 ORDER BY timestamp ASC LIMIT 1`, [orgId]);
|
|
222
|
+
const newest = await client.query(`SELECT timestamp FROM events WHERE org_id = $1 ORDER BY timestamp DESC LIMIT 1`, [orgId]);
|
|
223
|
+
const sizeResult = await client.query(`SELECT pg_total_relation_size('events') AS size_bytes`);
|
|
224
|
+
return {
|
|
225
|
+
totalEvents: eventCount.rows[0]?.c ?? 0,
|
|
226
|
+
totalSessions: sessionCount.rows[0]?.c ?? 0,
|
|
227
|
+
totalAgents: agentCount.rows[0]?.c ?? 0,
|
|
228
|
+
oldestEvent: oldest.rows[0]?.timestamp,
|
|
229
|
+
newestEvent: newest.rows[0]?.timestamp,
|
|
230
|
+
storageSizeBytes: Number(sizeResult.rows[0]?.size_bytes ?? 0),
|
|
231
|
+
};
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
// ═══════════════════════════════════════════════════════════
|
|
235
|
+
// S-4.3: Analytics Queries (Postgres-optimized)
|
|
236
|
+
// ═══════════════════════════════════════════════════════════
|
|
237
|
+
async getCostAnalytics(orgId, query) {
|
|
238
|
+
return withTenantTransaction(this.pool, orgId, async (client) => {
|
|
239
|
+
const trunc = pgDateTrunc(query.granularity);
|
|
240
|
+
const params = [orgId, query.from, query.to];
|
|
241
|
+
let agentFilter = '';
|
|
242
|
+
if (query.agentId) {
|
|
243
|
+
agentFilter = `AND agent_id = $4`;
|
|
244
|
+
params.push(query.agentId);
|
|
245
|
+
}
|
|
246
|
+
const result = await client.query(`SELECT
|
|
247
|
+
date_trunc('${trunc}', timestamp) AS bucket,
|
|
248
|
+
COALESCE(SUM((payload->>'costUsd')::numeric), 0)::float AS total_cost,
|
|
249
|
+
COUNT(*)::int AS event_count
|
|
250
|
+
FROM events
|
|
251
|
+
WHERE org_id = $1
|
|
252
|
+
AND timestamp >= $2
|
|
253
|
+
AND timestamp <= $3
|
|
254
|
+
AND event_type = 'cost_tracked'
|
|
255
|
+
${agentFilter}
|
|
256
|
+
GROUP BY bucket
|
|
257
|
+
ORDER BY bucket ASC`, params);
|
|
258
|
+
const buckets = result.rows.map((row) => ({
|
|
259
|
+
timestamp: String(row.bucket),
|
|
260
|
+
totalCostUsd: Number(row.total_cost ?? 0),
|
|
261
|
+
eventCount: Number(row.event_count ?? 0),
|
|
262
|
+
}));
|
|
263
|
+
const totalCostUsd = buckets.reduce((sum, b) => sum + b.totalCostUsd, 0);
|
|
264
|
+
const totalEvents = buckets.reduce((sum, b) => sum + b.eventCount, 0);
|
|
265
|
+
return { buckets, totalCostUsd, totalEvents };
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
async getHealthAnalytics(orgId, query) {
|
|
269
|
+
return withTenantTransaction(this.pool, orgId, async (client) => {
|
|
270
|
+
const params = [orgId, query.from, query.to];
|
|
271
|
+
let agentFilter = '';
|
|
272
|
+
if (query.agentId) {
|
|
273
|
+
agentFilter = `AND agent_id = $4`;
|
|
274
|
+
params.push(query.agentId);
|
|
275
|
+
}
|
|
276
|
+
const result = await client.query(`SELECT
|
|
277
|
+
agent_id,
|
|
278
|
+
date::text AS date,
|
|
279
|
+
overall_score,
|
|
280
|
+
error_rate_score,
|
|
281
|
+
cost_efficiency_score,
|
|
282
|
+
tool_success_score,
|
|
283
|
+
latency_score,
|
|
284
|
+
completion_rate_score,
|
|
285
|
+
session_count
|
|
286
|
+
FROM health_snapshots
|
|
287
|
+
WHERE org_id = $1
|
|
288
|
+
AND date >= $2::date
|
|
289
|
+
AND date <= $3::date
|
|
290
|
+
${agentFilter}
|
|
291
|
+
ORDER BY date ASC, agent_id ASC`, params);
|
|
292
|
+
const snapshots = result.rows.map((row) => ({
|
|
293
|
+
agentId: row.agent_id,
|
|
294
|
+
date: row.date,
|
|
295
|
+
overallScore: Number(row.overall_score ?? 0),
|
|
296
|
+
errorRateScore: Number(row.error_rate_score ?? 0),
|
|
297
|
+
costEfficiencyScore: Number(row.cost_efficiency_score ?? 0),
|
|
298
|
+
toolSuccessScore: Number(row.tool_success_score ?? 0),
|
|
299
|
+
latencyScore: Number(row.latency_score ?? 0),
|
|
300
|
+
completionRateScore: Number(row.completion_rate_score ?? 0),
|
|
301
|
+
sessionCount: Number(row.session_count ?? 0),
|
|
302
|
+
}));
|
|
303
|
+
return { snapshots };
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
async getTokenUsage(orgId, query) {
|
|
307
|
+
return withTenantTransaction(this.pool, orgId, async (client) => {
|
|
308
|
+
const trunc = pgDateTrunc(query.granularity);
|
|
309
|
+
const params = [orgId, query.from, query.to];
|
|
310
|
+
let agentFilter = '';
|
|
311
|
+
if (query.agentId) {
|
|
312
|
+
agentFilter = `AND agent_id = $4`;
|
|
313
|
+
params.push(query.agentId);
|
|
314
|
+
}
|
|
315
|
+
const result = await client.query(`SELECT
|
|
316
|
+
date_trunc('${trunc}', timestamp) AS bucket,
|
|
317
|
+
COALESCE(SUM((payload->>'inputTokens')::int), 0)::int AS input_tokens,
|
|
318
|
+
COALESCE(SUM((payload->>'outputTokens')::int), 0)::int AS output_tokens,
|
|
319
|
+
COALESCE(SUM((payload->>'inputTokens')::int + (payload->>'outputTokens')::int), 0)::int AS total_tokens,
|
|
320
|
+
COUNT(*)::int AS llm_call_count
|
|
321
|
+
FROM events
|
|
322
|
+
WHERE org_id = $1
|
|
323
|
+
AND timestamp >= $2
|
|
324
|
+
AND timestamp <= $3
|
|
325
|
+
AND event_type = 'llm_response'
|
|
326
|
+
${agentFilter}
|
|
327
|
+
GROUP BY bucket
|
|
328
|
+
ORDER BY bucket ASC`, params);
|
|
329
|
+
const buckets = result.rows.map((row) => ({
|
|
330
|
+
timestamp: String(row.bucket),
|
|
331
|
+
inputTokens: Number(row.input_tokens ?? 0),
|
|
332
|
+
outputTokens: Number(row.output_tokens ?? 0),
|
|
333
|
+
totalTokens: Number(row.total_tokens ?? 0),
|
|
334
|
+
llmCallCount: Number(row.llm_call_count ?? 0),
|
|
335
|
+
}));
|
|
336
|
+
const totals = buckets.reduce((acc, b) => ({
|
|
337
|
+
inputTokens: acc.inputTokens + b.inputTokens,
|
|
338
|
+
outputTokens: acc.outputTokens + b.outputTokens,
|
|
339
|
+
totalTokens: acc.totalTokens + b.totalTokens,
|
|
340
|
+
llmCallCount: acc.llmCallCount + b.llmCallCount,
|
|
341
|
+
}), { inputTokens: 0, outputTokens: 0, totalTokens: 0, llmCallCount: 0 });
|
|
342
|
+
return { buckets, totals };
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
async getAnalytics(orgId, query) {
|
|
346
|
+
return withTenantTransaction(this.pool, orgId, async (client) => {
|
|
347
|
+
const trunc = pgDateTrunc(query.granularity);
|
|
348
|
+
const params = [orgId, query.from, query.to];
|
|
349
|
+
let agentFilter = '';
|
|
350
|
+
if (query.agentId) {
|
|
351
|
+
agentFilter = `AND agent_id = $4`;
|
|
352
|
+
params.push(query.agentId);
|
|
353
|
+
}
|
|
354
|
+
// Bucketed query using date_trunc (Postgres-optimized)
|
|
355
|
+
const bucketResult = await client.query(`SELECT
|
|
356
|
+
date_trunc('${trunc}', timestamp) AS bucket,
|
|
357
|
+
COUNT(*)::int AS event_count,
|
|
358
|
+
SUM(CASE WHEN event_type = 'tool_call' THEN 1 ELSE 0 END)::int AS tool_call_count,
|
|
359
|
+
SUM(CASE WHEN severity IN ('error', 'critical') OR event_type = 'tool_error' THEN 1 ELSE 0 END)::int AS error_count,
|
|
360
|
+
COUNT(DISTINCT session_id)::int AS unique_sessions,
|
|
361
|
+
COALESCE(AVG(CASE WHEN event_type = 'tool_response' THEN (payload->>'durationMs')::numeric ELSE NULL END), 0)::float AS avg_latency_ms,
|
|
362
|
+
COALESCE(SUM(CASE WHEN event_type = 'cost_tracked' THEN (payload->>'costUsd')::numeric ELSE 0 END), 0)::float AS total_cost_usd
|
|
363
|
+
FROM events
|
|
364
|
+
WHERE org_id = $1 AND timestamp >= $2 AND timestamp <= $3
|
|
365
|
+
${agentFilter}
|
|
366
|
+
GROUP BY bucket
|
|
367
|
+
ORDER BY bucket ASC`, params);
|
|
368
|
+
// Totals query
|
|
369
|
+
const totalsResult = await client.query(`SELECT
|
|
370
|
+
COUNT(*)::int AS event_count,
|
|
371
|
+
SUM(CASE WHEN event_type = 'tool_call' THEN 1 ELSE 0 END)::int AS tool_call_count,
|
|
372
|
+
SUM(CASE WHEN severity IN ('error', 'critical') OR event_type = 'tool_error' THEN 1 ELSE 0 END)::int AS error_count,
|
|
373
|
+
COUNT(DISTINCT session_id)::int AS unique_sessions,
|
|
374
|
+
COUNT(DISTINCT agent_id)::int AS unique_agents,
|
|
375
|
+
COALESCE(AVG(CASE WHEN event_type = 'tool_response' THEN (payload->>'durationMs')::numeric ELSE NULL END), 0)::float AS avg_latency_ms,
|
|
376
|
+
COALESCE(SUM(CASE WHEN event_type = 'cost_tracked' THEN (payload->>'costUsd')::numeric ELSE 0 END), 0)::float AS total_cost_usd
|
|
377
|
+
FROM events
|
|
378
|
+
WHERE org_id = $1 AND timestamp >= $2 AND timestamp <= $3
|
|
379
|
+
${agentFilter}`, params);
|
|
380
|
+
const totalsRow = totalsResult.rows[0];
|
|
381
|
+
return {
|
|
382
|
+
buckets: bucketResult.rows.map((row) => ({
|
|
383
|
+
timestamp: String(row.bucket),
|
|
384
|
+
eventCount: Number(row.event_count ?? 0),
|
|
385
|
+
toolCallCount: Number(row.tool_call_count ?? 0),
|
|
386
|
+
errorCount: Number(row.error_count ?? 0),
|
|
387
|
+
avgLatencyMs: Number(row.avg_latency_ms ?? 0),
|
|
388
|
+
totalCostUsd: Number(row.total_cost_usd ?? 0),
|
|
389
|
+
uniqueSessions: Number(row.unique_sessions ?? 0),
|
|
390
|
+
})),
|
|
391
|
+
totals: {
|
|
392
|
+
eventCount: Number(totalsRow?.event_count ?? 0),
|
|
393
|
+
toolCallCount: Number(totalsRow?.tool_call_count ?? 0),
|
|
394
|
+
errorCount: Number(totalsRow?.error_count ?? 0),
|
|
395
|
+
avgLatencyMs: Number(totalsRow?.avg_latency_ms ?? 0),
|
|
396
|
+
totalCostUsd: Number(totalsRow?.total_cost_usd ?? 0),
|
|
397
|
+
uniqueSessions: Number(totalsRow?.unique_sessions ?? 0),
|
|
398
|
+
uniqueAgents: Number(totalsRow?.unique_agents ?? 0),
|
|
399
|
+
},
|
|
400
|
+
};
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
// ═══════════════════════════════════════════════════════════
|
|
404
|
+
// S-4.4: Full-Text Search (Postgres tsvector/to_tsquery)
|
|
405
|
+
// ═══════════════════════════════════════════════════════════
|
|
406
|
+
async search(orgId, query) {
|
|
407
|
+
return withTenantTransaction(this.pool, orgId, async (client) => {
|
|
408
|
+
const limit = Math.min(query.limit ?? 20, 100);
|
|
409
|
+
const offset = query.offset ?? 0;
|
|
410
|
+
const scope = query.scope ?? 'all';
|
|
411
|
+
// Sanitize query for to_tsquery: replace spaces with & for AND semantics
|
|
412
|
+
const tsQuery = query.query
|
|
413
|
+
.trim()
|
|
414
|
+
.split(/\s+/)
|
|
415
|
+
.filter(Boolean)
|
|
416
|
+
.map((w) => w.replace(/[^\w]/g, ''))
|
|
417
|
+
.filter(Boolean)
|
|
418
|
+
.join(' & ');
|
|
419
|
+
if (!tsQuery) {
|
|
420
|
+
return { items: [], total: 0, hasMore: false };
|
|
421
|
+
}
|
|
422
|
+
const items = [];
|
|
423
|
+
let total = 0;
|
|
424
|
+
// Search events
|
|
425
|
+
if (scope === 'events' || scope === 'all') {
|
|
426
|
+
const timeFilters = [];
|
|
427
|
+
const params = [orgId, tsQuery];
|
|
428
|
+
let idx = 3;
|
|
429
|
+
if (query.from) {
|
|
430
|
+
timeFilters.push(`AND e.timestamp >= $${idx}`);
|
|
431
|
+
params.push(query.from);
|
|
432
|
+
idx++;
|
|
433
|
+
}
|
|
434
|
+
if (query.to) {
|
|
435
|
+
timeFilters.push(`AND e.timestamp <= $${idx}`);
|
|
436
|
+
params.push(query.to);
|
|
437
|
+
idx++;
|
|
438
|
+
}
|
|
439
|
+
const timeFilterStr = timeFilters.join(' ');
|
|
440
|
+
// Use to_tsvector on payload::text + event_type for full-text search
|
|
441
|
+
// ts_rank for scoring, ts_headline for highlighted snippets
|
|
442
|
+
const eventResult = await client.query(`WITH matched AS (
|
|
443
|
+
SELECT
|
|
444
|
+
e.id,
|
|
445
|
+
e.session_id,
|
|
446
|
+
e.timestamp,
|
|
447
|
+
ts_rank(
|
|
448
|
+
to_tsvector('english', COALESCE(e.event_type, '') || ' ' || COALESCE(e.payload::text, '')),
|
|
449
|
+
to_tsquery('english', $2)
|
|
450
|
+
) AS score,
|
|
451
|
+
ts_headline('english',
|
|
452
|
+
COALESCE(e.event_type, '') || ' ' || COALESCE(e.payload::text, ''),
|
|
453
|
+
to_tsquery('english', $2),
|
|
454
|
+
'MaxWords=30, MinWords=10, StartSel=<<, StopSel=>>'
|
|
455
|
+
) AS headline
|
|
456
|
+
FROM events e
|
|
457
|
+
WHERE e.org_id = $1
|
|
458
|
+
AND to_tsvector('english', COALESCE(e.event_type, '') || ' ' || COALESCE(e.payload::text, ''))
|
|
459
|
+
@@ to_tsquery('english', $2)
|
|
460
|
+
${timeFilterStr}
|
|
461
|
+
)
|
|
462
|
+
SELECT *, (SELECT COUNT(*)::int FROM matched) AS total_count
|
|
463
|
+
FROM matched
|
|
464
|
+
ORDER BY score DESC
|
|
465
|
+
LIMIT $${idx} OFFSET $${idx + 1}`, [...params, limit, offset]);
|
|
466
|
+
for (const row of eventResult.rows) {
|
|
467
|
+
items.push({
|
|
468
|
+
type: 'event',
|
|
469
|
+
id: row.id,
|
|
470
|
+
score: Number(row.score ?? 0),
|
|
471
|
+
headline: row.headline,
|
|
472
|
+
timestamp: row.timestamp,
|
|
473
|
+
sessionId: row.session_id,
|
|
474
|
+
});
|
|
475
|
+
total = Number(row.total_count ?? 0);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
// Search sessions
|
|
479
|
+
if (scope === 'sessions' || scope === 'all') {
|
|
480
|
+
const timeFilters = [];
|
|
481
|
+
const params = [orgId, tsQuery];
|
|
482
|
+
let idx = 3;
|
|
483
|
+
if (query.from) {
|
|
484
|
+
timeFilters.push(`AND s.started_at >= $${idx}`);
|
|
485
|
+
params.push(query.from);
|
|
486
|
+
idx++;
|
|
487
|
+
}
|
|
488
|
+
if (query.to) {
|
|
489
|
+
timeFilters.push(`AND s.started_at <= $${idx}`);
|
|
490
|
+
params.push(query.to);
|
|
491
|
+
idx++;
|
|
492
|
+
}
|
|
493
|
+
const timeFilterStr = timeFilters.join(' ');
|
|
494
|
+
const sessionResult = await client.query(`WITH matched AS (
|
|
495
|
+
SELECT
|
|
496
|
+
s.id,
|
|
497
|
+
s.started_at AS timestamp,
|
|
498
|
+
ts_rank(
|
|
499
|
+
to_tsvector('english', COALESCE(s.agent_name, '') || ' ' || COALESCE(s.tags::text, '')),
|
|
500
|
+
to_tsquery('english', $2)
|
|
501
|
+
) AS score,
|
|
502
|
+
ts_headline('english',
|
|
503
|
+
COALESCE(s.agent_name, '') || ' ' || COALESCE(s.tags::text, ''),
|
|
504
|
+
to_tsquery('english', $2),
|
|
505
|
+
'MaxWords=30, MinWords=10, StartSel=<<, StopSel=>>'
|
|
506
|
+
) AS headline
|
|
507
|
+
FROM sessions s
|
|
508
|
+
WHERE s.org_id = $1
|
|
509
|
+
AND to_tsvector('english', COALESCE(s.agent_name, '') || ' ' || COALESCE(s.tags::text, ''))
|
|
510
|
+
@@ to_tsquery('english', $2)
|
|
511
|
+
${timeFilterStr}
|
|
512
|
+
)
|
|
513
|
+
SELECT *, (SELECT COUNT(*)::int FROM matched) AS total_count
|
|
514
|
+
FROM matched
|
|
515
|
+
ORDER BY score DESC
|
|
516
|
+
LIMIT $${idx} OFFSET $${idx + 1}`, [...params, limit, offset]);
|
|
517
|
+
const sessionTotal = Number(sessionResult.rows[0]?.total_count ?? 0);
|
|
518
|
+
for (const row of sessionResult.rows) {
|
|
519
|
+
items.push({
|
|
520
|
+
type: 'session',
|
|
521
|
+
id: row.id,
|
|
522
|
+
score: Number(row.score ?? 0),
|
|
523
|
+
headline: row.headline,
|
|
524
|
+
timestamp: row.timestamp,
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
if (scope === 'all') {
|
|
528
|
+
total += sessionTotal;
|
|
529
|
+
}
|
|
530
|
+
else {
|
|
531
|
+
total = sessionTotal;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
// Sort combined results by score descending
|
|
535
|
+
items.sort((a, b) => b.score - a.score);
|
|
536
|
+
return {
|
|
537
|
+
items: items.slice(0, limit),
|
|
538
|
+
total,
|
|
539
|
+
hasMore: offset + items.length < total,
|
|
540
|
+
};
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
//# sourceMappingURL=postgres-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres-adapter.js","sourceRoot":"","sources":["../../../src/cloud/storage/postgres-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite Storage Adapter (S-4.1, S-4.3, S-4.4)
|
|
3
|
+
*
|
|
4
|
+
* Wraps the existing SqliteEventStore to implement the StorageAdapter interface.
|
|
5
|
+
* orgId is mapped to tenantId for multi-tenant SQLite (self-hosted).
|
|
6
|
+
*
|
|
7
|
+
* S-4.3: Analytics use SQLite strftime for time bucketing.
|
|
8
|
+
* S-4.4: Full-text search uses LIKE (SQLite lacks tsvector; FTS5 optional).
|
|
9
|
+
*/
|
|
10
|
+
import type { AgentLensEvent, EventQuery, EventQueryResult, Session, SessionQuery, Agent } from '@agentlensai/core';
|
|
11
|
+
import type { AnalyticsResult, StorageStats } from '@agentlensai/core';
|
|
12
|
+
import type { StorageAdapter, PaginatedResult, AnalyticsQuery, CostAnalyticsResult, HealthAnalyticsResult, TokenUsageResult, SearchQuery, SearchResult } from './adapter.js';
|
|
13
|
+
import type { SqliteEventStore } from '../../db/sqlite-store.js';
|
|
14
|
+
export declare class SqliteStorageAdapter implements StorageAdapter {
|
|
15
|
+
private readonly store;
|
|
16
|
+
constructor(store: SqliteEventStore);
|
|
17
|
+
queryEvents(orgId: string, query: EventQuery): Promise<EventQueryResult>;
|
|
18
|
+
getEventsBySession(orgId: string, sessionId: string): Promise<AgentLensEvent[]>;
|
|
19
|
+
getSessions(orgId: string, query: SessionQuery): Promise<PaginatedResult<Session>>;
|
|
20
|
+
getSession(orgId: string, sessionId: string): Promise<Session | null>;
|
|
21
|
+
getAgents(orgId: string): Promise<Agent[]>;
|
|
22
|
+
getStats(orgId: string): Promise<StorageStats>;
|
|
23
|
+
getCostAnalytics(orgId: string, query: AnalyticsQuery): Promise<CostAnalyticsResult>;
|
|
24
|
+
getHealthAnalytics(_orgId: string, _query: AnalyticsQuery): Promise<HealthAnalyticsResult>;
|
|
25
|
+
getTokenUsage(orgId: string, query: AnalyticsQuery): Promise<TokenUsageResult>;
|
|
26
|
+
getAnalytics(orgId: string, query: AnalyticsQuery): Promise<AnalyticsResult>;
|
|
27
|
+
search(orgId: string, query: SearchQuery): Promise<SearchResult>;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=sqlite-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-adapter.d.ts","sourceRoot":"","sources":["../../../src/cloud/storage/sqlite-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,OAAO,EACP,YAAY,EACZ,KAAK,EAEN,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,qBAAqB,EACrB,gBAAgB,EAChB,WAAW,EACX,YAAY,EACb,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,qBAAa,oBAAqB,YAAW,cAAc;IAC7C,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,gBAAgB;IAE9C,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAIxE,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAI/E,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;IAWlF,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAIrE,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAI1C,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAQ9C,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAsBpF,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAO1F,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA4B9E,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IAc5E,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;CA+EvE"}
|