nexus-ai-pro 2.0.0 → 2.2.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/API_STABILITY.md +65 -0
- package/CHANGELOG.md +267 -1
- package/MIGRATING.md +1 -1
- package/README.md +17 -8
- package/dist/agent/create-agent.d.ts +9 -1
- package/dist/agent/create-agent.js +40 -1
- package/dist/cache/memory-cache.d.ts +8 -0
- package/dist/cache/memory-cache.js +9 -0
- package/dist/cache/semantic-cache.d.ts +6 -3
- package/dist/cache/semantic-cache.js +5 -2
- package/dist/cli/args.js +3 -0
- package/dist/cli/db.d.ts +16 -4
- package/dist/cli/db.js +169 -22
- package/dist/cli/doctor.d.ts +17 -0
- package/dist/cli/doctor.js +53 -0
- package/dist/cli/graph.d.ts +9 -0
- package/dist/cli/graph.js +47 -0
- package/dist/cli.js +21 -2
- package/dist/core/lifecycle.js +11 -6
- package/dist/core/nexus.d.ts +12 -2
- package/dist/core/nexus.js +106 -23
- package/dist/doctor/index.d.ts +90 -0
- package/dist/doctor/index.js +237 -0
- package/dist/evals/judge.d.ts +11 -0
- package/dist/evals/judge.js +33 -0
- package/dist/evaluate/index.d.ts +1 -0
- package/dist/evaluate/index.js +1 -0
- package/dist/evaluate/provenance.d.ts +22 -0
- package/dist/evaluate/provenance.js +10 -0
- package/dist/evaluate/run.js +20 -4
- package/dist/graph/durability.d.ts +27 -0
- package/dist/graph/durability.js +66 -0
- package/dist/graph/errors.d.ts +30 -4
- package/dist/graph/errors.js +18 -2
- package/dist/graph/event-stream.d.ts +75 -0
- package/dist/graph/event-stream.js +289 -0
- package/dist/graph/functional.d.ts +80 -7
- package/dist/graph/functional.js +138 -35
- package/dist/graph/graph.d.ts +56 -8
- package/dist/graph/graph.js +331 -49
- package/dist/graph/index.d.ts +4 -2
- package/dist/graph/index.js +3 -1
- package/dist/graph/lint.d.ts +57 -0
- package/dist/graph/lint.js +141 -0
- package/dist/graph/run-control.d.ts +28 -0
- package/dist/graph/run-control.js +26 -0
- package/dist/images/evals.js +4 -2
- package/dist/operations/adapters.d.ts +52 -4
- package/dist/operations/adapters.js +194 -7
- package/dist/operations/runner.js +14 -15
- package/dist/operations/stats.js +8 -1
- package/dist/operations/store.d.ts +5 -1
- package/dist/operations/store.js +7 -0
- package/dist/ops/circuit-breaker.d.ts +52 -0
- package/dist/ops/circuit-breaker.js +4 -0
- package/dist/ops/circuit-store.d.ts +13 -2
- package/dist/ops/circuit-store.js +68 -0
- package/dist/ops/circuit-sync.d.ts +17 -0
- package/dist/ops/circuit-sync.js +86 -0
- package/dist/ops/health.d.ts +24 -0
- package/dist/ops/health.js +38 -10
- package/dist/ops/index.d.ts +1 -1
- package/dist/ops/index.js +1 -1
- package/dist/ops/rate-limit-adapters.d.ts +23 -0
- package/dist/ops/rate-limit-adapters.js +34 -0
- package/dist/ops/rate-limiter.d.ts +14 -2
- package/dist/ops/rate-limiter.js +31 -0
- package/dist/postgres/circuits.d.ts +21 -4
- package/dist/postgres/circuits.js +65 -4
- package/dist/postgres/client.d.ts +0 -2
- package/dist/postgres/client.js +0 -4
- package/dist/postgres/evaluate.d.ts +16 -4
- package/dist/postgres/evaluate.js +17 -5
- package/dist/postgres/index.d.ts +32 -11
- package/dist/postgres/index.js +65 -31
- package/dist/postgres/migrations.d.ts +60 -0
- package/dist/postgres/migrations.js +121 -0
- package/dist/postgres/operations.d.ts +14 -3
- package/dist/postgres/operations.js +45 -15
- package/dist/postgres/prompts.d.ts +11 -2
- package/dist/postgres/prompts.js +14 -3
- package/dist/postgres/rollups.d.ts +35 -0
- package/dist/postgres/rollups.js +129 -0
- package/dist/postgres/store.d.ts +11 -2
- package/dist/postgres/store.js +14 -3
- package/dist/postgres/traces.d.ts +13 -3
- package/dist/postgres/traces.js +25 -3
- package/dist/postgres/vectors.d.ts +11 -2
- package/dist/postgres/vectors.js +14 -3
- package/dist/router/auto-router.d.ts +34 -7
- package/dist/router/auto-router.js +201 -68
- package/dist/server/assistant.d.ts +44 -0
- package/dist/server/assistant.js +39 -0
- package/dist/server/errors.d.ts +12 -0
- package/dist/server/errors.js +7 -0
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/runs.d.ts +28 -1
- package/dist/server/runs.js +110 -14
- package/dist/sqlite/index.d.ts +16 -3
- package/dist/sqlite/index.js +16 -3
- package/dist/sqlite/migrations.d.ts +26 -0
- package/dist/sqlite/migrations.js +63 -0
- package/dist/sqlite/operations.d.ts +14 -3
- package/dist/sqlite/operations.js +42 -15
- package/dist/sqlite/store.d.ts +9 -2
- package/dist/sqlite/store.js +13 -3
- package/dist/sqlite/vectors.d.ts +11 -2
- package/dist/sqlite/vectors.js +13 -2
- package/dist/store/tenant.d.ts +12 -0
- package/dist/store/tenant.js +29 -0
- package/dist/tenancy/index.d.ts +113 -0
- package/dist/tenancy/index.js +233 -0
- package/dist/testing/record.d.ts +42 -0
- package/dist/testing/record.js +57 -5
- package/dist/tracing/index.d.ts +3 -3
- package/dist/tracing/index.js +2 -2
- package/dist/tracing/instrument.js +30 -0
- package/dist/tracing/otlp.d.ts +91 -0
- package/dist/tracing/otlp.js +124 -0
- package/dist/tracing/rollups.d.ts +100 -0
- package/dist/tracing/rollups.js +139 -0
- package/dist/tracing/stores.d.ts +17 -0
- package/dist/tracing/stores.js +23 -0
- package/dist/tracing/tracer.d.ts +50 -4
- package/dist/tracing/tracer.js +85 -6
- package/dist/types/config.d.ts +33 -2
- package/dist/types/evaluate.d.ts +37 -0
- package/dist/types/graph.d.ts +354 -9
- package/dist/types/graph.js +3 -1
- package/dist/types/messages.d.ts +5 -0
- package/dist/types/operations.d.ts +22 -2
- package/dist/types/response.d.ts +20 -0
- package/dist/types/server.d.ts +18 -0
- package/dist/types/tracing.d.ts +11 -0
- package/dist/utils/schema-migrations.d.ts +97 -0
- package/dist/utils/schema-migrations.js +91 -0
- package/dist/utils/signals.d.ts +17 -0
- package/dist/utils/signals.js +26 -0
- package/dist/utils/tenant.d.ts +14 -0
- package/dist/utils/tenant.js +16 -0
- package/dist/version.d.ts +5 -0
- package/dist/version.js +1 -0
- package/dist-cjs/agent/create-agent.d.ts +9 -1
- package/dist-cjs/agent/create-agent.js +40 -1
- package/dist-cjs/cache/memory-cache.d.ts +8 -0
- package/dist-cjs/cache/memory-cache.js +9 -0
- package/dist-cjs/cache/semantic-cache.d.ts +6 -3
- package/dist-cjs/cache/semantic-cache.js +5 -2
- package/dist-cjs/cli/args.js +3 -0
- package/dist-cjs/cli/db.d.ts +16 -4
- package/dist-cjs/cli/db.js +200 -20
- package/dist-cjs/cli/doctor.d.ts +17 -0
- package/dist-cjs/cli/doctor.js +56 -0
- package/dist-cjs/cli/graph.d.ts +9 -0
- package/dist-cjs/cli/graph.js +50 -0
- package/dist-cjs/core/lifecycle.js +11 -6
- package/dist-cjs/core/nexus.d.ts +12 -2
- package/dist-cjs/core/nexus.js +106 -23
- package/dist-cjs/doctor/index.d.ts +90 -0
- package/dist-cjs/doctor/index.js +276 -0
- package/dist-cjs/evals/judge.d.ts +11 -0
- package/dist-cjs/evals/judge.js +33 -0
- package/dist-cjs/evaluate/index.d.ts +1 -0
- package/dist-cjs/evaluate/index.js +3 -1
- package/dist-cjs/evaluate/provenance.d.ts +22 -0
- package/dist-cjs/evaluate/provenance.js +14 -0
- package/dist-cjs/evaluate/run.js +20 -4
- package/dist-cjs/graph/durability.d.ts +27 -0
- package/dist-cjs/graph/durability.js +70 -0
- package/dist-cjs/graph/errors.d.ts +30 -4
- package/dist-cjs/graph/errors.js +20 -3
- package/dist-cjs/graph/event-stream.d.ts +75 -0
- package/dist-cjs/graph/event-stream.js +295 -0
- package/dist-cjs/graph/functional.d.ts +80 -7
- package/dist-cjs/graph/functional.js +137 -34
- package/dist-cjs/graph/graph.d.ts +56 -8
- package/dist-cjs/graph/graph.js +330 -48
- package/dist-cjs/graph/index.d.ts +4 -2
- package/dist-cjs/graph/index.js +7 -1
- package/dist-cjs/graph/lint.d.ts +57 -0
- package/dist-cjs/graph/lint.js +144 -0
- package/dist-cjs/graph/run-control.d.ts +28 -0
- package/dist-cjs/graph/run-control.js +30 -0
- package/dist-cjs/images/evals.js +4 -2
- package/dist-cjs/operations/adapters.d.ts +52 -4
- package/dist-cjs/operations/adapters.js +193 -6
- package/dist-cjs/operations/runner.js +14 -15
- package/dist-cjs/operations/stats.js +8 -1
- package/dist-cjs/operations/store.d.ts +5 -1
- package/dist-cjs/operations/store.js +7 -0
- package/dist-cjs/ops/circuit-breaker.d.ts +52 -0
- package/dist-cjs/ops/circuit-breaker.js +4 -0
- package/dist-cjs/ops/circuit-store.d.ts +13 -2
- package/dist-cjs/ops/circuit-store.js +68 -0
- package/dist-cjs/ops/circuit-sync.d.ts +17 -0
- package/dist-cjs/ops/circuit-sync.js +87 -0
- package/dist-cjs/ops/health.d.ts +24 -0
- package/dist-cjs/ops/health.js +38 -10
- package/dist-cjs/ops/index.d.ts +1 -1
- package/dist-cjs/ops/rate-limit-adapters.d.ts +23 -0
- package/dist-cjs/ops/rate-limit-adapters.js +35 -1
- package/dist-cjs/ops/rate-limiter.d.ts +14 -2
- package/dist-cjs/ops/rate-limiter.js +32 -0
- package/dist-cjs/postgres/circuits.d.ts +21 -4
- package/dist-cjs/postgres/circuits.js +98 -3
- package/dist-cjs/postgres/client.d.ts +0 -2
- package/dist-cjs/postgres/client.js +0 -5
- package/dist-cjs/postgres/evaluate.d.ts +16 -4
- package/dist-cjs/postgres/evaluate.js +50 -4
- package/dist-cjs/postgres/index.d.ts +32 -11
- package/dist-cjs/postgres/index.js +69 -20
- package/dist-cjs/postgres/migrations.d.ts +60 -0
- package/dist-cjs/postgres/migrations.js +129 -0
- package/dist-cjs/postgres/operations.d.ts +14 -3
- package/dist-cjs/postgres/operations.js +78 -14
- package/dist-cjs/postgres/prompts.d.ts +11 -2
- package/dist-cjs/postgres/prompts.js +47 -2
- package/dist-cjs/postgres/rollups.d.ts +35 -0
- package/dist-cjs/postgres/rollups.js +168 -0
- package/dist-cjs/postgres/store.d.ts +11 -2
- package/dist-cjs/postgres/store.js +47 -2
- package/dist-cjs/postgres/traces.d.ts +13 -3
- package/dist-cjs/postgres/traces.js +58 -2
- package/dist-cjs/postgres/vectors.d.ts +11 -2
- package/dist-cjs/postgres/vectors.js +47 -2
- package/dist-cjs/router/auto-router.d.ts +34 -7
- package/dist-cjs/router/auto-router.js +201 -68
- package/dist-cjs/server/assistant.d.ts +44 -0
- package/dist-cjs/server/assistant.js +39 -0
- package/dist-cjs/server/errors.d.ts +12 -0
- package/dist-cjs/server/errors.js +9 -1
- package/dist-cjs/server/index.d.ts +1 -1
- package/dist-cjs/server/index.js +2 -1
- package/dist-cjs/server/runs.d.ts +28 -1
- package/dist-cjs/server/runs.js +109 -13
- package/dist-cjs/sqlite/index.d.ts +16 -3
- package/dist-cjs/sqlite/index.js +31 -10
- package/dist-cjs/sqlite/migrations.d.ts +26 -0
- package/dist-cjs/sqlite/migrations.js +71 -0
- package/dist-cjs/sqlite/operations.d.ts +14 -3
- package/dist-cjs/sqlite/operations.js +76 -15
- package/dist-cjs/sqlite/store.d.ts +9 -2
- package/dist-cjs/sqlite/store.js +47 -3
- package/dist-cjs/sqlite/vectors.d.ts +11 -2
- package/dist-cjs/sqlite/vectors.js +47 -2
- package/dist-cjs/store/tenant.d.ts +12 -0
- package/dist-cjs/store/tenant.js +33 -0
- package/dist-cjs/tenancy/index.d.ts +113 -0
- package/dist-cjs/tenancy/index.js +250 -0
- package/dist-cjs/testing/record.d.ts +42 -0
- package/dist-cjs/testing/record.js +57 -5
- package/dist-cjs/tracing/index.d.ts +3 -3
- package/dist-cjs/tracing/index.js +4 -1
- package/dist-cjs/tracing/instrument.js +30 -0
- package/dist-cjs/tracing/otlp.d.ts +91 -0
- package/dist-cjs/tracing/otlp.js +129 -0
- package/dist-cjs/tracing/rollups.d.ts +100 -0
- package/dist-cjs/tracing/rollups.js +147 -0
- package/dist-cjs/tracing/stores.d.ts +17 -0
- package/dist-cjs/tracing/stores.js +24 -0
- package/dist-cjs/tracing/tracer.d.ts +50 -4
- package/dist-cjs/tracing/tracer.js +87 -6
- package/dist-cjs/types/config.d.ts +33 -2
- package/dist-cjs/types/evaluate.d.ts +37 -0
- package/dist-cjs/types/graph.d.ts +354 -9
- package/dist-cjs/types/graph.js +3 -1
- package/dist-cjs/types/messages.d.ts +5 -0
- package/dist-cjs/types/operations.d.ts +22 -2
- package/dist-cjs/types/response.d.ts +20 -0
- package/dist-cjs/types/server.d.ts +18 -0
- package/dist-cjs/types/tracing.d.ts +11 -0
- package/dist-cjs/utils/schema-migrations.d.ts +97 -0
- package/dist-cjs/utils/schema-migrations.js +102 -0
- package/dist-cjs/utils/signals.d.ts +17 -0
- package/dist-cjs/utils/signals.js +29 -0
- package/dist-cjs/utils/tenant.d.ts +14 -0
- package/dist-cjs/utils/tenant.js +22 -0
- package/dist-cjs/version.d.ts +5 -0
- package/dist-cjs/version.js +4 -0
- package/llms.txt +4 -3
- package/package.json +110 -2
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SchemaMigrationError = exports.migrationChecksum = void 0;
|
|
4
|
+
exports.postgresMigrationStatus = postgresMigrationStatus;
|
|
5
|
+
exports.applyPostgresMigrations = applyPostgresMigrations;
|
|
6
|
+
exports.migrationsTableStatements = migrationsTableStatements;
|
|
7
|
+
const schema_migrations_js_1 = require("../utils/schema-migrations.js");
|
|
8
|
+
const client_js_1 = require("./client.js");
|
|
9
|
+
var schema_migrations_js_2 = require("../utils/schema-migrations.js");
|
|
10
|
+
Object.defineProperty(exports, "migrationChecksum", { enumerable: true, get: function () { return schema_migrations_js_2.migrationChecksum; } });
|
|
11
|
+
Object.defineProperty(exports, "SchemaMigrationError", { enumerable: true, get: function () { return schema_migrations_js_2.SchemaMigrationError; } });
|
|
12
|
+
const LOCK_NAME = 'migrate';
|
|
13
|
+
const DB_NOW = '(extract(epoch from clock_timestamp()) * 1000)';
|
|
14
|
+
async function postgresMigrationStatus(client, migrations, options = {}) {
|
|
15
|
+
return (0, schema_migrations_js_1.planMigrations)(migrations, await readApplied(client, options.table ?? schema_migrations_js_1.MIGRATIONS_TABLE));
|
|
16
|
+
}
|
|
17
|
+
async function applyPostgresMigrations(client, migrations, options = {}) {
|
|
18
|
+
const tableName = options.table ?? schema_migrations_js_1.MIGRATIONS_TABLE;
|
|
19
|
+
if (options.dryRun) {
|
|
20
|
+
const status = await postgresMigrationStatus(client, migrations, options);
|
|
21
|
+
(0, schema_migrations_js_1.assertUnchanged)(status);
|
|
22
|
+
return { applied: status.pending, statements: status.pending.flatMap((m) => [...m.statements]), dryRun: true };
|
|
23
|
+
}
|
|
24
|
+
(0, schema_migrations_js_1.planMigrations)(migrations, []);
|
|
25
|
+
await bootstrap(client, tableName);
|
|
26
|
+
const owner = `migrator-${globalThis.crypto.randomUUID()}`;
|
|
27
|
+
const lockTtlMs = options.lockTtlMs ?? 600_000;
|
|
28
|
+
await acquire(client, tableName, owner, lockTtlMs, options.lockTimeoutMs ?? 120_000);
|
|
29
|
+
try {
|
|
30
|
+
const status = (0, schema_migrations_js_1.planMigrations)(migrations, await readApplied(client, tableName));
|
|
31
|
+
(0, schema_migrations_js_1.assertUnchanged)(status);
|
|
32
|
+
const statements = [];
|
|
33
|
+
for (const migration of status.pending) {
|
|
34
|
+
if (!(await claim(client, tableName, owner, lockTtlMs))) {
|
|
35
|
+
throw new schema_migrations_js_1.SchemaMigrationError('MIGRATION_LOCKED', `The migration lock lapsed before ${(0, schema_migrations_js_1.label)(migration)}`);
|
|
36
|
+
}
|
|
37
|
+
const apply = async (connection) => {
|
|
38
|
+
for (const statement of migration.statements)
|
|
39
|
+
await connection.query(statement);
|
|
40
|
+
await connection.query(`INSERT INTO ${(0, client_js_1.quoteTable)(tableName)} (component, version, name, checksum, applied_at)
|
|
41
|
+
VALUES ($1, $2, $3, $4, $5) ON CONFLICT (component, version) DO NOTHING`, [
|
|
42
|
+
migration.component,
|
|
43
|
+
migration.version,
|
|
44
|
+
migration.name,
|
|
45
|
+
(0, schema_migrations_js_1.migrationChecksum)(migration),
|
|
46
|
+
new Date().toISOString(),
|
|
47
|
+
]);
|
|
48
|
+
};
|
|
49
|
+
if (options.transaction)
|
|
50
|
+
await options.transaction(apply);
|
|
51
|
+
else
|
|
52
|
+
await apply(client);
|
|
53
|
+
statements.push(...migration.statements);
|
|
54
|
+
}
|
|
55
|
+
return { applied: status.pending, statements, dryRun: false };
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
await client
|
|
59
|
+
.query(`DELETE FROM ${lockTable(tableName)} WHERE name = $1 AND owner = $2`, [LOCK_NAME, owner])
|
|
60
|
+
.catch(() => undefined);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function migrationsTableStatements(table = schema_migrations_js_1.MIGRATIONS_TABLE) {
|
|
64
|
+
return [
|
|
65
|
+
`CREATE TABLE IF NOT EXISTS ${(0, client_js_1.quoteTable)(table)} (
|
|
66
|
+
component text NOT NULL,
|
|
67
|
+
version integer NOT NULL,
|
|
68
|
+
name text NOT NULL,
|
|
69
|
+
checksum text NOT NULL,
|
|
70
|
+
applied_at text COLLATE "C" NOT NULL,
|
|
71
|
+
PRIMARY KEY (component, version)
|
|
72
|
+
)`,
|
|
73
|
+
`CREATE TABLE IF NOT EXISTS ${lockTable(table)} (
|
|
74
|
+
name text PRIMARY KEY,
|
|
75
|
+
owner text NOT NULL,
|
|
76
|
+
expires_at double precision NOT NULL
|
|
77
|
+
)`,
|
|
78
|
+
];
|
|
79
|
+
}
|
|
80
|
+
async function bootstrap(client, table) {
|
|
81
|
+
for (const statement of migrationsTableStatements(table)) {
|
|
82
|
+
try {
|
|
83
|
+
await client.query(statement);
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
const code = error?.code;
|
|
87
|
+
if (code !== '23505' && code !== '42P07')
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async function readApplied(client, table) {
|
|
93
|
+
const { rows: exists } = await client.query('SELECT to_regclass($1) IS NOT NULL AS present', [(0, client_js_1.quoteTable)(table)]);
|
|
94
|
+
if (!exists[0]?.present)
|
|
95
|
+
return [];
|
|
96
|
+
const { rows } = await client.query(`SELECT component, version, name, checksum, applied_at FROM ${(0, client_js_1.quoteTable)(table)} ORDER BY applied_at, component, version`);
|
|
97
|
+
return rows.map((row) => {
|
|
98
|
+
const value = row;
|
|
99
|
+
return {
|
|
100
|
+
component: String(value.component),
|
|
101
|
+
version: Number(value.version),
|
|
102
|
+
name: String(value.name),
|
|
103
|
+
checksum: String(value.checksum),
|
|
104
|
+
appliedAt: String(value.applied_at),
|
|
105
|
+
};
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
async function acquire(client, table, owner, ttlMs, timeoutMs) {
|
|
109
|
+
const deadline = Date.now() + timeoutMs;
|
|
110
|
+
let wait = 50;
|
|
111
|
+
while (!(await claim(client, table, owner, ttlMs))) {
|
|
112
|
+
if (Date.now() >= deadline) {
|
|
113
|
+
throw new schema_migrations_js_1.SchemaMigrationError('MIGRATION_LOCKED', `Another migrator held the lock for ${timeoutMs} ms. It is released when that migrator finishes, or when its lease lapses.`);
|
|
114
|
+
}
|
|
115
|
+
await (0, schema_migrations_js_1.delay)(wait);
|
|
116
|
+
wait = Math.min(wait * 2, 1_000);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
async function claim(client, table, owner, ttlMs) {
|
|
120
|
+
const lock = lockTable(table);
|
|
121
|
+
const { rows } = await client.query(`INSERT INTO ${lock} (name, owner, expires_at) VALUES ($1, $2, ${DB_NOW} + $3::double precision)
|
|
122
|
+
ON CONFLICT (name) DO UPDATE SET owner = EXCLUDED.owner, expires_at = EXCLUDED.expires_at
|
|
123
|
+
WHERE ${lock}.owner = EXCLUDED.owner OR ${lock}.expires_at < ${DB_NOW}
|
|
124
|
+
RETURNING owner`, [LOCK_NAME, owner, ttlMs]);
|
|
125
|
+
return rows.length > 0;
|
|
126
|
+
}
|
|
127
|
+
function lockTable(table) {
|
|
128
|
+
return (0, client_js_1.quoteTable)(`${table}_lock`);
|
|
129
|
+
}
|
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
import type { OperationRecord, OperationStore, OperationStoreFilter, OperationStoreStats } from '../types/operations.js';
|
|
2
|
+
import type { MigrationResult, SchemaMigration } from '../utils/schema-migrations.js';
|
|
2
3
|
import { type PostgresLikeClient } from './client.js';
|
|
4
|
+
import type { PostgresMigrateOptions } from './migrations.js';
|
|
3
5
|
/** Options for the Postgres operation store. */
|
|
4
6
|
export interface PostgresOperationStoreOptions {
|
|
5
7
|
/** Table name, optionally schema-qualified. Defaults to `nexus_operations`. */
|
|
6
8
|
table?: string;
|
|
7
9
|
}
|
|
8
|
-
/** The schema, as statements
|
|
10
|
+
/** The schema, as statements: every migration's, in order. For `nexus db sql` or the application's own tooling. */
|
|
9
11
|
export declare function operationStoreMigration(options?: PostgresOperationStoreOptions): string[];
|
|
12
|
+
/**
|
|
13
|
+
* The versioned schema, which `migrate()` and `nexus db migrate` apply. Version 1 is the 2.0 table;
|
|
14
|
+
* version 2 indexes queued work by age, so a claim reads the oldest few rows instead of sorting the
|
|
15
|
+
* queue; version 3 indexes queued work by tenant.
|
|
16
|
+
*/
|
|
17
|
+
export declare function operationStoreMigrations(options?: PostgresOperationStoreOptions): SchemaMigration[];
|
|
10
18
|
/**
|
|
11
19
|
* Operation records in Postgres.
|
|
12
20
|
*
|
|
@@ -25,8 +33,11 @@ export declare class PostgresOperationStore<TResult = unknown> implements Operat
|
|
|
25
33
|
private readonly options;
|
|
26
34
|
private readonly table;
|
|
27
35
|
constructor(client: PostgresLikeClient, options?: PostgresOperationStoreOptions);
|
|
28
|
-
/**
|
|
29
|
-
|
|
36
|
+
/**
|
|
37
|
+
* Applies this store's pending migrations, recorded in `nexus_schema_migrations`, under a lock.
|
|
38
|
+
* Never runs implicitly. Safe on a database an older release created: what exists is kept.
|
|
39
|
+
*/
|
|
40
|
+
migrate(options?: PostgresMigrateOptions): Promise<MigrationResult>;
|
|
30
41
|
/**
|
|
31
42
|
* Inserts a new record. Throws `OperationDuplicateError` when its idempotency key is already
|
|
32
43
|
* claimed. Refuses records carrying raw bytes.
|
|
@@ -1,7 +1,41 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
36
|
exports.PostgresOperationStore = void 0;
|
|
4
37
|
exports.operationStoreMigration = operationStoreMigration;
|
|
38
|
+
exports.operationStoreMigrations = operationStoreMigrations;
|
|
5
39
|
const errors_js_1 = require("../operations/errors.js");
|
|
6
40
|
const serialization_js_1 = require("../operations/serialization.js");
|
|
7
41
|
const operations_js_1 = require("../types/operations.js");
|
|
@@ -9,8 +43,33 @@ const client_js_1 = require("./client.js");
|
|
|
9
43
|
const DEFAULT_TABLE = 'nexus_operations';
|
|
10
44
|
const TERMINAL = operations_js_1.TERMINAL_OPERATION_STATUSES.map((status) => `'${status}'`).join(', ');
|
|
11
45
|
function operationStoreMigration(options = {}) {
|
|
46
|
+
return operationStoreMigrations(options).flatMap((migration) => [...migration.statements]);
|
|
47
|
+
}
|
|
48
|
+
function operationStoreMigrations(options = {}) {
|
|
12
49
|
const name = options.table ?? DEFAULT_TABLE;
|
|
13
50
|
const table = (0, client_js_1.quoteTable)(name);
|
|
51
|
+
const component = `operations:${name}`;
|
|
52
|
+
return [
|
|
53
|
+
{ component, version: 1, name: 'create the operations table', statements: createStatements(name, table) },
|
|
54
|
+
{
|
|
55
|
+
component,
|
|
56
|
+
version: 2,
|
|
57
|
+
name: 'index queued work by age',
|
|
58
|
+
statements: [
|
|
59
|
+
`CREATE INDEX IF NOT EXISTS ${(0, client_js_1.quoteDerived)(name, 'queued')} ON ${table} (created_at, id) WHERE status = 'queued'`,
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
component,
|
|
64
|
+
version: 3,
|
|
65
|
+
name: 'index queued work by tenant',
|
|
66
|
+
statements: [
|
|
67
|
+
`CREATE INDEX IF NOT EXISTS ${(0, client_js_1.quoteDerived)(name, 'tenant_queued')} ON ${table} ((doc ->> 'tenantId'), created_at, id) WHERE status = 'queued'`,
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
function createStatements(name, table) {
|
|
14
73
|
return [
|
|
15
74
|
`CREATE TABLE IF NOT EXISTS ${table} (
|
|
16
75
|
id text PRIMARY KEY,
|
|
@@ -36,8 +95,9 @@ class PostgresOperationStore {
|
|
|
36
95
|
this.options = options;
|
|
37
96
|
this.table = (0, client_js_1.quoteTable)(options.table ?? DEFAULT_TABLE);
|
|
38
97
|
}
|
|
39
|
-
async migrate() {
|
|
40
|
-
await (
|
|
98
|
+
async migrate(options = {}) {
|
|
99
|
+
const { applyPostgresMigrations } = await Promise.resolve().then(() => __importStar(require('./migrations.js')));
|
|
100
|
+
return applyPostgresMigrations(this.client, operationStoreMigrations(this.options), options);
|
|
41
101
|
}
|
|
42
102
|
async create(record) {
|
|
43
103
|
(0, serialization_js_1.assertSerializableRecord)(record);
|
|
@@ -99,29 +159,21 @@ class PostgresOperationStore {
|
|
|
99
159
|
}
|
|
100
160
|
async listQueued(limit, filter) {
|
|
101
161
|
const params = [new Date().toISOString(), limit];
|
|
102
|
-
|
|
103
|
-
if (filter?.kindPrefix) {
|
|
104
|
-
params.push(filter.kindPrefix);
|
|
105
|
-
kind = ' AND substr(kind, 1, char_length($3)) = $3';
|
|
106
|
-
}
|
|
162
|
+
const narrowed = filterSql(filter, params);
|
|
107
163
|
const { rows } = await this.client.query(`SELECT doc::text AS doc FROM ${this.table}
|
|
108
|
-
WHERE status = 'queued' AND (lease_expires_at IS NULL OR lease_expires_at <= $1)${
|
|
164
|
+
WHERE status = 'queued' AND (lease_expires_at IS NULL OR lease_expires_at <= $1)${narrowed}
|
|
109
165
|
ORDER BY created_at, id
|
|
110
166
|
LIMIT $2`, params);
|
|
111
167
|
return rows.map((row) => (0, client_js_1.fromJson)(row.doc));
|
|
112
168
|
}
|
|
113
169
|
async stats(now, filter) {
|
|
114
170
|
const params = [now];
|
|
115
|
-
|
|
116
|
-
if (filter?.kindPrefix) {
|
|
117
|
-
params.push(filter.kindPrefix);
|
|
118
|
-
kind = ' AND substr(kind, 1, char_length($2)) = $2';
|
|
119
|
-
}
|
|
171
|
+
const narrowed = filterSql(filter, params);
|
|
120
172
|
const { rows } = await this.client.query(`SELECT status, count(*)::int AS count,
|
|
121
173
|
min(created_at) FILTER (WHERE status = 'queued') AS oldest,
|
|
122
174
|
count(*) FILTER (WHERE status = 'running' AND (lease_expires_at IS NULL OR lease_expires_at <= $1))::int AS lapsed
|
|
123
175
|
FROM ${this.table}
|
|
124
|
-
WHERE status NOT IN (${TERMINAL})${
|
|
176
|
+
WHERE status NOT IN (${TERMINAL})${narrowed}
|
|
125
177
|
GROUP BY status`, params);
|
|
126
178
|
return statsFromRows(rows);
|
|
127
179
|
}
|
|
@@ -144,6 +196,18 @@ class PostgresOperationStore {
|
|
|
144
196
|
}
|
|
145
197
|
}
|
|
146
198
|
exports.PostgresOperationStore = PostgresOperationStore;
|
|
199
|
+
function filterSql(filter, params) {
|
|
200
|
+
let sql = '';
|
|
201
|
+
if (filter?.kindPrefix) {
|
|
202
|
+
params.push(filter.kindPrefix);
|
|
203
|
+
sql += ` AND substr(kind, 1, char_length($${params.length})) = $${params.length}`;
|
|
204
|
+
}
|
|
205
|
+
if (filter?.tenantId !== undefined) {
|
|
206
|
+
params.push(filter.tenantId);
|
|
207
|
+
sql += ` AND doc ->> 'tenantId' = $${params.length}`;
|
|
208
|
+
}
|
|
209
|
+
return sql;
|
|
210
|
+
}
|
|
147
211
|
function statsFromRows(rows) {
|
|
148
212
|
const byStatus = {};
|
|
149
213
|
let oldestQueuedAt;
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import type { PromptHistoryEntry, PromptLabel, PromptStore, PromptVersion } from '../types/prompts.js';
|
|
2
|
+
import type { MigrationResult, SchemaMigration } from '../utils/schema-migrations.js';
|
|
2
3
|
import { type PostgresLikeClient } from './client.js';
|
|
4
|
+
import type { PostgresMigrateOptions } from './migrations.js';
|
|
3
5
|
/** Options for the Postgres prompt store. */
|
|
4
6
|
export interface PostgresPromptStoreOptions {
|
|
5
7
|
/** Table name prefix, optionally schema-qualified. Defaults to `nexus_prompt`, for `nexus_prompt_versions` and so on. */
|
|
6
8
|
table?: string;
|
|
7
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* The versioned schema, which `migrate()` and `nexus db migrate` apply. Version 1 is the 2.0 schema.
|
|
12
|
+
*/
|
|
13
|
+
export declare function promptStoreMigrations(options?: PostgresPromptStoreOptions): SchemaMigration[];
|
|
8
14
|
/** The schema for the prompt store, as statements. */
|
|
9
15
|
export declare function promptStoreMigration(options?: PostgresPromptStoreOptions): string[];
|
|
10
16
|
/**
|
|
@@ -20,8 +26,11 @@ export declare class PostgresPromptStore implements PromptStore {
|
|
|
20
26
|
private readonly labels;
|
|
21
27
|
private readonly history;
|
|
22
28
|
constructor(client: PostgresLikeClient, options?: PostgresPromptStoreOptions);
|
|
23
|
-
/**
|
|
24
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Applies this store's pending migrations, recorded in `nexus_schema_migrations`, under a lock.
|
|
31
|
+
* Never runs implicitly. Safe on a database an older release created: what exists is kept.
|
|
32
|
+
*/
|
|
33
|
+
migrate(options?: PostgresMigrateOptions): Promise<MigrationResult>;
|
|
25
34
|
/** Stores a version, unless one with the same content version exists. */
|
|
26
35
|
saveVersion(version: PromptVersion): Promise<void>;
|
|
27
36
|
/** Reads a version. */
|
|
@@ -1,12 +1,56 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
36
|
exports.PostgresPromptStore = void 0;
|
|
37
|
+
exports.promptStoreMigrations = promptStoreMigrations;
|
|
4
38
|
exports.promptStoreMigration = promptStoreMigration;
|
|
5
39
|
const client_js_1 = require("./client.js");
|
|
6
40
|
function tables(options) {
|
|
7
41
|
const base = options.table ?? 'nexus_prompt';
|
|
8
42
|
return { base, versions: `${base}_versions`, labels: `${base}_labels`, history: `${base}_history` };
|
|
9
43
|
}
|
|
44
|
+
function promptStoreMigrations(options = {}) {
|
|
45
|
+
return [
|
|
46
|
+
{
|
|
47
|
+
component: `prompts:${tables(options).versions}`,
|
|
48
|
+
version: 1,
|
|
49
|
+
name: 'create the prompt tables',
|
|
50
|
+
statements: promptStoreMigration(options),
|
|
51
|
+
},
|
|
52
|
+
];
|
|
53
|
+
}
|
|
10
54
|
function promptStoreMigration(options = {}) {
|
|
11
55
|
const names = tables(options);
|
|
12
56
|
return [
|
|
@@ -48,8 +92,9 @@ class PostgresPromptStore {
|
|
|
48
92
|
this.labels = (0, client_js_1.quoteTable)(names.labels);
|
|
49
93
|
this.history = (0, client_js_1.quoteTable)(names.history);
|
|
50
94
|
}
|
|
51
|
-
async migrate() {
|
|
52
|
-
await (
|
|
95
|
+
async migrate(options = {}) {
|
|
96
|
+
const { applyPostgresMigrations } = await Promise.resolve().then(() => __importStar(require('./migrations.js')));
|
|
97
|
+
return applyPostgresMigrations(this.client, promptStoreMigrations(this.options), options);
|
|
53
98
|
}
|
|
54
99
|
async saveVersion(version) {
|
|
55
100
|
await this.client.query(`INSERT INTO ${this.versions} (name, version, created_at, doc) VALUES ($1, $2, $3, $4::jsonb) ON CONFLICT DO NOTHING`, [version.name, version.version, version.createdAt, JSON.stringify(version)]);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type RollupKey, type RollupQuery, type RollupRow, type RollupStore, type RollupTotals } from '../tracing/rollups.js';
|
|
2
|
+
import type { MigrationResult, SchemaMigration } from '../utils/schema-migrations.js';
|
|
3
|
+
import { type PostgresLikeClient } from './client.js';
|
|
4
|
+
import type { PostgresMigrateOptions } from './migrations.js';
|
|
5
|
+
/** Options for the Postgres rollup store. */
|
|
6
|
+
export interface PostgresRollupStoreOptions {
|
|
7
|
+
/** Table name, optionally schema-qualified. Defaults to `nexus_rollups`. */
|
|
8
|
+
table?: string;
|
|
9
|
+
}
|
|
10
|
+
/** The schema, as statements: every migration's, in order. */
|
|
11
|
+
export declare function rollupStoreMigration(options?: PostgresRollupStoreOptions): string[];
|
|
12
|
+
/** The versioned schema, which `migrate()` and `nexus db migrate` apply. */
|
|
13
|
+
export declare function rollupStoreMigrations(options?: PostgresRollupStoreOptions): SchemaMigration[];
|
|
14
|
+
/**
|
|
15
|
+
* Rollup rows in Postgres, so a dashboard's totals live beside its traces and survive a restart.
|
|
16
|
+
*
|
|
17
|
+
* Adding to a row is one `INSERT … ON CONFLICT DO UPDATE` that sums every total, latency buckets
|
|
18
|
+
* included, so two workers finishing runs in the same hour both count. A query reads only the rows
|
|
19
|
+
* of its range: a month of one tenant is a few hundred rows, however many runs it held.
|
|
20
|
+
*/
|
|
21
|
+
export declare class PostgresRollupStore implements RollupStore {
|
|
22
|
+
private readonly client;
|
|
23
|
+
private readonly options;
|
|
24
|
+
private readonly table;
|
|
25
|
+
constructor(client: PostgresLikeClient, options?: PostgresRollupStoreOptions);
|
|
26
|
+
/**
|
|
27
|
+
* Applies this store's pending migrations, recorded in `nexus_schema_migrations`, under a lock.
|
|
28
|
+
* Never runs implicitly.
|
|
29
|
+
*/
|
|
30
|
+
migrate(options?: PostgresMigrateOptions): Promise<MigrationResult>;
|
|
31
|
+
/** Adds totals to the row for `key`, creating it, in one statement. */
|
|
32
|
+
add(key: RollupKey, totals: RollupTotals): Promise<void>;
|
|
33
|
+
/** Rows matching a query, oldest hour first, filtered as the in-memory store filters them. */
|
|
34
|
+
query(query?: RollupQuery): Promise<RollupRow[]>;
|
|
35
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.PostgresRollupStore = void 0;
|
|
37
|
+
exports.rollupStoreMigration = rollupStoreMigration;
|
|
38
|
+
exports.rollupStoreMigrations = rollupStoreMigrations;
|
|
39
|
+
const rollups_js_1 = require("../tracing/rollups.js");
|
|
40
|
+
const client_js_1 = require("./client.js");
|
|
41
|
+
const sql_js_1 = require("./sql.js");
|
|
42
|
+
const DEFAULT_TABLE = 'nexus_rollups';
|
|
43
|
+
function rollupStoreMigration(options = {}) {
|
|
44
|
+
return rollupStoreMigrations(options).flatMap((migration) => [...migration.statements]);
|
|
45
|
+
}
|
|
46
|
+
function rollupStoreMigrations(options = {}) {
|
|
47
|
+
const name = options.table ?? DEFAULT_TABLE;
|
|
48
|
+
const table = (0, client_js_1.quoteTable)(name);
|
|
49
|
+
return [
|
|
50
|
+
{
|
|
51
|
+
component: `rollups:${name}`,
|
|
52
|
+
version: 1,
|
|
53
|
+
name: 'create the rollups table',
|
|
54
|
+
statements: [
|
|
55
|
+
`CREATE TABLE IF NOT EXISTS ${table} (
|
|
56
|
+
hour text COLLATE "C" NOT NULL,
|
|
57
|
+
kind text NOT NULL,
|
|
58
|
+
name text NOT NULL,
|
|
59
|
+
model text NOT NULL,
|
|
60
|
+
provider text NOT NULL,
|
|
61
|
+
tenant text NOT NULL,
|
|
62
|
+
runs bigint NOT NULL,
|
|
63
|
+
errors bigint NOT NULL,
|
|
64
|
+
cost double precision NOT NULL,
|
|
65
|
+
input_tokens bigint NOT NULL,
|
|
66
|
+
output_tokens bigint NOT NULL,
|
|
67
|
+
latency bigint[] NOT NULL,
|
|
68
|
+
PRIMARY KEY (hour, kind, name, model, provider, tenant)
|
|
69
|
+
)`,
|
|
70
|
+
`CREATE INDEX IF NOT EXISTS ${(0, client_js_1.quoteDerived)(name, 'tenant_hour')} ON ${table} (tenant, hour)`,
|
|
71
|
+
],
|
|
72
|
+
},
|
|
73
|
+
];
|
|
74
|
+
}
|
|
75
|
+
class PostgresRollupStore {
|
|
76
|
+
client;
|
|
77
|
+
options;
|
|
78
|
+
table;
|
|
79
|
+
constructor(client, options = {}) {
|
|
80
|
+
this.client = client;
|
|
81
|
+
this.options = options;
|
|
82
|
+
this.table = (0, client_js_1.quoteTable)(options.table ?? DEFAULT_TABLE);
|
|
83
|
+
}
|
|
84
|
+
async migrate(options = {}) {
|
|
85
|
+
const { applyPostgresMigrations } = await Promise.resolve().then(() => __importStar(require('./migrations.js')));
|
|
86
|
+
return applyPostgresMigrations(this.client, rollupStoreMigrations(this.options), options);
|
|
87
|
+
}
|
|
88
|
+
async add(key, totals) {
|
|
89
|
+
const t = this.table;
|
|
90
|
+
await this.client.query(`INSERT INTO ${t} (hour, kind, name, model, provider, tenant, runs, errors, cost, input_tokens, output_tokens, latency)
|
|
91
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7::bigint, $8::bigint, $9::double precision, $10::bigint, $11::bigint, $12::bigint[])
|
|
92
|
+
ON CONFLICT (hour, kind, name, model, provider, tenant) DO UPDATE SET
|
|
93
|
+
runs = ${t}.runs + EXCLUDED.runs,
|
|
94
|
+
errors = ${t}.errors + EXCLUDED.errors,
|
|
95
|
+
cost = ${t}.cost + EXCLUDED.cost,
|
|
96
|
+
input_tokens = ${t}.input_tokens + EXCLUDED.input_tokens,
|
|
97
|
+
output_tokens = ${t}.output_tokens + EXCLUDED.output_tokens,
|
|
98
|
+
latency = ARRAY(
|
|
99
|
+
SELECT coalesce(stored, 0) + coalesce(added, 0)
|
|
100
|
+
FROM unnest(${t}.latency, EXCLUDED.latency) WITH ORDINALITY AS bucket(stored, added, position)
|
|
101
|
+
ORDER BY position
|
|
102
|
+
)`, [
|
|
103
|
+
key.hour,
|
|
104
|
+
key.kind,
|
|
105
|
+
key.name,
|
|
106
|
+
key.model,
|
|
107
|
+
key.provider,
|
|
108
|
+
key.tenant,
|
|
109
|
+
totals.runs,
|
|
110
|
+
totals.errors,
|
|
111
|
+
totals.cost,
|
|
112
|
+
totals.inputTokens,
|
|
113
|
+
totals.outputTokens,
|
|
114
|
+
`{${bucketsOf(totals.latency).join(',')}}`,
|
|
115
|
+
]);
|
|
116
|
+
}
|
|
117
|
+
async query(query = {}) {
|
|
118
|
+
const params = new sql_js_1.SqlParams();
|
|
119
|
+
const where = [];
|
|
120
|
+
if (query.since)
|
|
121
|
+
where.push(`hour >= ${params.add(hourOf(query.since))}`);
|
|
122
|
+
if (query.until)
|
|
123
|
+
where.push(`hour <= ${params.add(query.until)}`);
|
|
124
|
+
if (query.kind !== undefined) {
|
|
125
|
+
const kinds = Array.isArray(query.kind) ? query.kind : [query.kind];
|
|
126
|
+
where.push(kinds.length ? `kind IN (${kinds.map((kind) => params.add(kind)).join(', ')})` : 'FALSE');
|
|
127
|
+
}
|
|
128
|
+
if (query.model !== undefined)
|
|
129
|
+
where.push(`model = ${params.add(query.model)}`);
|
|
130
|
+
if (query.provider !== undefined)
|
|
131
|
+
where.push(`provider = ${params.add(query.provider)}`);
|
|
132
|
+
if (query.tenant !== undefined)
|
|
133
|
+
where.push(`tenant = ${params.add(query.tenant)}`);
|
|
134
|
+
if (query.name !== undefined)
|
|
135
|
+
where.push(`name = ${params.add(query.name)}`);
|
|
136
|
+
const { rows } = await this.client.query(`SELECT hour, kind, name, model, provider, tenant, runs::text AS runs, errors::text AS errors, cost,
|
|
137
|
+
input_tokens::text AS input_tokens, output_tokens::text AS output_tokens, latency::text AS latency
|
|
138
|
+
FROM ${this.table}
|
|
139
|
+
${where.length ? `WHERE ${where.join(' AND ')}` : ''}
|
|
140
|
+
ORDER BY hour, kind, name, model, provider, tenant`, params.values);
|
|
141
|
+
return rows.map((raw) => {
|
|
142
|
+
const row = raw;
|
|
143
|
+
return {
|
|
144
|
+
hour: String(row.hour),
|
|
145
|
+
kind: row.kind,
|
|
146
|
+
name: String(row.name),
|
|
147
|
+
model: String(row.model),
|
|
148
|
+
provider: String(row.provider),
|
|
149
|
+
tenant: String(row.tenant),
|
|
150
|
+
runs: Number(row.runs),
|
|
151
|
+
errors: Number(row.errors),
|
|
152
|
+
cost: Number(row.cost),
|
|
153
|
+
inputTokens: Number(row.input_tokens),
|
|
154
|
+
outputTokens: Number(row.output_tokens),
|
|
155
|
+
latency: String(row.latency).replace(/[{}]/g, '').split(',').filter(Boolean).map(Number),
|
|
156
|
+
};
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
exports.PostgresRollupStore = PostgresRollupStore;
|
|
161
|
+
function bucketsOf(latency) {
|
|
162
|
+
return Array.from({ length: rollups_js_1.ROLLUP_LATENCY_BOUNDS_MS.length + 1 }, (_, index) => Math.round(latency[index] ?? 0));
|
|
163
|
+
}
|
|
164
|
+
function hourOf(iso) {
|
|
165
|
+
const date = new Date(iso);
|
|
166
|
+
date.setUTCMinutes(0, 0, 0);
|
|
167
|
+
return date.toISOString();
|
|
168
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { Store, StoreIndexOptions, StoreItem, StoreNamespace, StorePutOptions, StoreSearchOptions } from '../types/store.js';
|
|
2
|
+
import type { MigrationResult, SchemaMigration } from '../utils/schema-migrations.js';
|
|
2
3
|
import { type PostgresLikeClient } from './client.js';
|
|
4
|
+
import type { PostgresMigrateOptions } from './migrations.js';
|
|
3
5
|
/** Options for the Postgres store. */
|
|
4
6
|
export interface PostgresStoreOptions {
|
|
5
7
|
/** Table name, optionally schema-qualified. Defaults to `nexus_store`. */
|
|
@@ -15,6 +17,10 @@ export interface PostgresStoreOptions {
|
|
|
15
17
|
/** Replaces the system clock, for tests. */
|
|
16
18
|
now?: () => Date;
|
|
17
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* The versioned schema, which `migrate()` and `nexus db migrate` apply. Version 1 is the 2.0 schema.
|
|
22
|
+
*/
|
|
23
|
+
export declare function storeMigrations(options?: Pick<PostgresStoreOptions, 'table' | 'vectorDimensions'>): SchemaMigration[];
|
|
18
24
|
/** The schema, as statements. With `vectorDimensions`, pgvector's extension is created too. */
|
|
19
25
|
export declare function storeMigration(options?: Pick<PostgresStoreOptions, 'table' | 'vectorDimensions'>): string[];
|
|
20
26
|
/**
|
|
@@ -31,8 +37,11 @@ export declare class PostgresStore implements Store {
|
|
|
31
37
|
private readonly table;
|
|
32
38
|
private readonly now;
|
|
33
39
|
constructor(client: PostgresLikeClient, options?: PostgresStoreOptions);
|
|
34
|
-
/**
|
|
35
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Applies this store's pending migrations, recorded in `nexus_schema_migrations`, under a lock.
|
|
42
|
+
* Never runs implicitly. Safe on a database an older release created: what exists is kept.
|
|
43
|
+
*/
|
|
44
|
+
migrate(options?: PostgresMigrateOptions): Promise<MigrationResult>;
|
|
36
45
|
/** Stores an item, keeping its original `createdAt` when it replaces one. */
|
|
37
46
|
put<V>(namespace: StoreNamespace, key: string, value: V, options?: StorePutOptions): Promise<void>;
|
|
38
47
|
/** Reads an item, or `undefined` when it does not exist or has expired. */
|