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,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Versioned schema migrations, shared by the Postgres and SQLite adapters.
|
|
3
|
+
*
|
|
4
|
+
* Each adapter's tables form a component, such as `operations:nexus_operations`, with numbered
|
|
5
|
+
* migrations. The database records which ran, with a checksum of their statements, so an upgrade
|
|
6
|
+
* applies only what is new and an edited migration is refused instead of silently ignored.
|
|
7
|
+
*/
|
|
8
|
+
/** One numbered schema change to one adapter's tables. */
|
|
9
|
+
export interface SchemaMigration {
|
|
10
|
+
/**
|
|
11
|
+
* The tables it belongs to, such as `operations:nexus_operations`. Versions count per component,
|
|
12
|
+
* so two operation stores on two tables migrate independently.
|
|
13
|
+
*/
|
|
14
|
+
component: string;
|
|
15
|
+
/** Its number, from 1, in the order it applies. */
|
|
16
|
+
version: number;
|
|
17
|
+
/** What it does, in a few words. */
|
|
18
|
+
name: string;
|
|
19
|
+
/**
|
|
20
|
+
* Its statements, in order. Every bundled statement is idempotent (`IF NOT EXISTS`), so a migration
|
|
21
|
+
* interrupted between statements on a database without transactional DDL runs again safely.
|
|
22
|
+
*/
|
|
23
|
+
statements: readonly string[];
|
|
24
|
+
}
|
|
25
|
+
/** A migration the database has recorded as applied. */
|
|
26
|
+
export interface AppliedMigration {
|
|
27
|
+
/** Its component. */
|
|
28
|
+
component: string;
|
|
29
|
+
/** Its version. */
|
|
30
|
+
version: number;
|
|
31
|
+
/** Its name when it ran. */
|
|
32
|
+
name: string;
|
|
33
|
+
/** The checksum of its statements when it ran. */
|
|
34
|
+
checksum: string;
|
|
35
|
+
/** ISO-8601 time it was applied. */
|
|
36
|
+
appliedAt: string;
|
|
37
|
+
}
|
|
38
|
+
/** Where a database stands against the migrations this code knows. */
|
|
39
|
+
export interface MigrationStatus {
|
|
40
|
+
/** Recorded migrations, oldest first. */
|
|
41
|
+
applied: AppliedMigration[];
|
|
42
|
+
/** Known migrations not yet applied, in the order `migrate()` would apply them. */
|
|
43
|
+
pending: SchemaMigration[];
|
|
44
|
+
/**
|
|
45
|
+
* Applied migrations whose statements have changed since: an edited migration, or adapter options,
|
|
46
|
+
* such as a vector width, that differ from those it ran with. `migrate()` refuses to run while any
|
|
47
|
+
* remain.
|
|
48
|
+
*/
|
|
49
|
+
changed: Array<{
|
|
50
|
+
migration: SchemaMigration;
|
|
51
|
+
applied: AppliedMigration;
|
|
52
|
+
}>;
|
|
53
|
+
/**
|
|
54
|
+
* Recorded migrations this code does not know, written by a newer release. Expected while a rollout
|
|
55
|
+
* runs two versions side by side, since every migration only adds.
|
|
56
|
+
*/
|
|
57
|
+
unknown: AppliedMigration[];
|
|
58
|
+
/** True when nothing is pending or changed. */
|
|
59
|
+
current: boolean;
|
|
60
|
+
}
|
|
61
|
+
/** What one `migrate()` call did, or with `dryRun`, would do. */
|
|
62
|
+
export interface MigrationResult {
|
|
63
|
+
/** Migrations applied, or with `dryRun`, pending. */
|
|
64
|
+
applied: SchemaMigration[];
|
|
65
|
+
/** The statements run, or with `dryRun`, that would run, in order. */
|
|
66
|
+
statements: string[];
|
|
67
|
+
/** Whether nothing was written. */
|
|
68
|
+
dryRun: boolean;
|
|
69
|
+
}
|
|
70
|
+
/** Raised when migrations cannot run safely: a changed migration, a bad list, or a lock held too long. */
|
|
71
|
+
export declare class SchemaMigrationError extends Error {
|
|
72
|
+
/** A stable code: `MIGRATION_CHANGED`, `MIGRATION_INVALID`, or `MIGRATION_LOCKED`. */
|
|
73
|
+
readonly code: 'MIGRATION_CHANGED' | 'MIGRATION_INVALID' | 'MIGRATION_LOCKED';
|
|
74
|
+
constructor(code: SchemaMigrationError['code'], message: string);
|
|
75
|
+
}
|
|
76
|
+
/** The default table that records applied migrations. */
|
|
77
|
+
export declare const MIGRATIONS_TABLE = "nexus_schema_migrations";
|
|
78
|
+
/**
|
|
79
|
+
* A checksum of a migration's statements: cyrb53, a fast 53-bit hash, as 14 hex digits.
|
|
80
|
+
*
|
|
81
|
+
* It detects a migration edited after it ran; it is not a security boundary, so it needs no crypto
|
|
82
|
+
* module and runs anywhere a driver does. Line endings are normalized, so a checkout on Windows
|
|
83
|
+
* computes the same value as one on Linux.
|
|
84
|
+
*/
|
|
85
|
+
export declare function migrationChecksum(migration: Pick<SchemaMigration, 'statements'>): string;
|
|
86
|
+
/** @internal Refuses a list with a gap, a duplicate, or an empty migration, before anything runs. */
|
|
87
|
+
export declare function validateMigrations(migrations: readonly SchemaMigration[]): void;
|
|
88
|
+
/** @internal Compares known migrations with recorded ones. */
|
|
89
|
+
export declare function planMigrations(known: readonly SchemaMigration[], applied: readonly AppliedMigration[]): MigrationStatus;
|
|
90
|
+
/** @internal Refuses to migrate while an applied migration has changed. */
|
|
91
|
+
export declare function assertUnchanged(status: MigrationStatus): void;
|
|
92
|
+
/** @internal A SQL string literal. Values here are component names and checksums, never user input. */
|
|
93
|
+
export declare function sqlLiteral(value: string): string;
|
|
94
|
+
/** @internal */
|
|
95
|
+
export declare function label(migration: Pick<SchemaMigration, 'component' | 'version' | 'name'>): string;
|
|
96
|
+
/** @internal Waits, for lock polling. */
|
|
97
|
+
export declare function delay(ms: number): Promise<void>;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
export class SchemaMigrationError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
constructor(code, message) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = 'SchemaMigrationError';
|
|
6
|
+
this.code = code;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export const MIGRATIONS_TABLE = 'nexus_schema_migrations';
|
|
10
|
+
export function migrationChecksum(migration) {
|
|
11
|
+
const text = migration.statements.map((statement) => statement.replace(/\r\n/g, '\n').trim()).join('\n;\n');
|
|
12
|
+
let h1 = 0xdeadbeef;
|
|
13
|
+
let h2 = 0x41c6ce57;
|
|
14
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
15
|
+
const code = text.charCodeAt(index);
|
|
16
|
+
h1 = Math.imul(h1 ^ code, 2654435761);
|
|
17
|
+
h2 = Math.imul(h2 ^ code, 1597334677);
|
|
18
|
+
}
|
|
19
|
+
h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);
|
|
20
|
+
h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);
|
|
21
|
+
return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(16).padStart(14, '0');
|
|
22
|
+
}
|
|
23
|
+
export function validateMigrations(migrations) {
|
|
24
|
+
const versions = new Map();
|
|
25
|
+
for (const migration of migrations) {
|
|
26
|
+
if (!migration.component)
|
|
27
|
+
throw new SchemaMigrationError('MIGRATION_INVALID', 'A migration has no component');
|
|
28
|
+
if (!Number.isInteger(migration.version) || migration.version < 1) {
|
|
29
|
+
throw new SchemaMigrationError('MIGRATION_INVALID', `${migration.component} has version ${migration.version}; versions are integers from 1`);
|
|
30
|
+
}
|
|
31
|
+
if (migration.statements.length === 0) {
|
|
32
|
+
throw new SchemaMigrationError('MIGRATION_INVALID', `${label(migration)} has no statements`);
|
|
33
|
+
}
|
|
34
|
+
const list = versions.get(migration.component) ?? [];
|
|
35
|
+
if (list.includes(migration.version)) {
|
|
36
|
+
throw new SchemaMigrationError('MIGRATION_INVALID', `${label(migration)} is listed twice`);
|
|
37
|
+
}
|
|
38
|
+
list.push(migration.version);
|
|
39
|
+
versions.set(migration.component, list);
|
|
40
|
+
}
|
|
41
|
+
for (const [component, list] of versions) {
|
|
42
|
+
const sorted = [...list].sort((a, b) => a - b);
|
|
43
|
+
sorted.forEach((version, index) => {
|
|
44
|
+
if (version !== index + 1) {
|
|
45
|
+
throw new SchemaMigrationError('MIGRATION_INVALID', `${component} skips version ${index + 1}`);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
export function planMigrations(known, applied) {
|
|
51
|
+
validateMigrations(known);
|
|
52
|
+
const recorded = new Map(applied.map((row) => [`${row.component}@${row.version}`, row]));
|
|
53
|
+
const knownKeys = new Set(known.map((migration) => `${migration.component}@${migration.version}`));
|
|
54
|
+
const pending = [];
|
|
55
|
+
const changed = [];
|
|
56
|
+
for (const migration of known) {
|
|
57
|
+
const row = recorded.get(`${migration.component}@${migration.version}`);
|
|
58
|
+
if (!row)
|
|
59
|
+
pending.push(migration);
|
|
60
|
+
else if (row.checksum !== migrationChecksum(migration))
|
|
61
|
+
changed.push({ migration, applied: row });
|
|
62
|
+
}
|
|
63
|
+
const order = new Map();
|
|
64
|
+
for (const migration of known)
|
|
65
|
+
if (!order.has(migration.component))
|
|
66
|
+
order.set(migration.component, order.size);
|
|
67
|
+
pending.sort((a, b) => order.get(a.component) - order.get(b.component) || a.version - b.version);
|
|
68
|
+
const sortedApplied = [...applied].sort((a, b) => a.appliedAt.localeCompare(b.appliedAt) || a.component.localeCompare(b.component) || a.version - b.version);
|
|
69
|
+
return {
|
|
70
|
+
applied: sortedApplied,
|
|
71
|
+
pending,
|
|
72
|
+
changed,
|
|
73
|
+
unknown: sortedApplied.filter((row) => !knownKeys.has(`${row.component}@${row.version}`)),
|
|
74
|
+
current: pending.length === 0 && changed.length === 0,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
export function assertUnchanged(status) {
|
|
78
|
+
if (status.changed.length === 0)
|
|
79
|
+
return;
|
|
80
|
+
const names = status.changed.map(({ migration }) => label(migration)).join(', ');
|
|
81
|
+
throw new SchemaMigrationError('MIGRATION_CHANGED', `${names} changed after it was applied. A migration is never edited once it runs; add a new one, or check the adapter options (a table or vector width) match those it ran with.`);
|
|
82
|
+
}
|
|
83
|
+
export function sqlLiteral(value) {
|
|
84
|
+
return `'${value.replace(/'/g, "''")}'`;
|
|
85
|
+
}
|
|
86
|
+
export function label(migration) {
|
|
87
|
+
return `${migration.component} v${migration.version} (${migration.name})`;
|
|
88
|
+
}
|
|
89
|
+
export function delay(ms) {
|
|
90
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
91
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A signal that aborts when any of its sources does, and can be let go of.
|
|
3
|
+
*
|
|
4
|
+
* `AbortSignal.any()` cannot be undone: in Node 22 a source signal keeps a reference for every signal
|
|
5
|
+
* ever composed from it, about half a kilobyte each, for as long as the source lives. A graph composes
|
|
6
|
+
* one per task attempt from the run's signal, so a long-lived signal shared by many runs — a server's,
|
|
7
|
+
* a worker's — grew without bound. A linked signal listens to its sources directly and `dispose()`
|
|
8
|
+
* removes the listeners, so a finished attempt keeps nothing.
|
|
9
|
+
*/
|
|
10
|
+
export interface LinkedSignal {
|
|
11
|
+
/** Aborts, with that source's reason, when any source aborts. */
|
|
12
|
+
readonly signal: AbortSignal;
|
|
13
|
+
/** Stops listening to the sources. Safe to call more than once. */
|
|
14
|
+
dispose(): void;
|
|
15
|
+
}
|
|
16
|
+
/** Links the given signals; missing ones are ignored, and one signal is returned as it is. */
|
|
17
|
+
export declare function linkSignals(sources: ReadonlyArray<AbortSignal | undefined>): LinkedSignal;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const NOTHING_TO_DISPOSE = () => undefined;
|
|
2
|
+
export function linkSignals(sources) {
|
|
3
|
+
const present = sources.filter((source) => source !== undefined);
|
|
4
|
+
if (present.length === 1)
|
|
5
|
+
return { signal: present[0], dispose: NOTHING_TO_DISPOSE };
|
|
6
|
+
const controller = new AbortController();
|
|
7
|
+
const aborted = present.find((source) => source.aborted);
|
|
8
|
+
if (aborted) {
|
|
9
|
+
controller.abort(aborted.reason);
|
|
10
|
+
return { signal: controller.signal, dispose: NOTHING_TO_DISPOSE };
|
|
11
|
+
}
|
|
12
|
+
const listeners = [];
|
|
13
|
+
const dispose = () => {
|
|
14
|
+
for (const [source, listener] of listeners.splice(0))
|
|
15
|
+
source.removeEventListener('abort', listener);
|
|
16
|
+
};
|
|
17
|
+
for (const source of present) {
|
|
18
|
+
const listener = () => {
|
|
19
|
+
controller.abort(source.reason);
|
|
20
|
+
dispose();
|
|
21
|
+
};
|
|
22
|
+
source.addEventListener('abort', listener, { once: true });
|
|
23
|
+
listeners.push([source, listener]);
|
|
24
|
+
}
|
|
25
|
+
return { signal: controller.signal, dispose };
|
|
26
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The tenant id rule every scope shares. An id is letters, digits, `_`, and `-`, so it can never hold
|
|
3
|
+
* the `/` a scoped name or key is built with: no tenant's prefix is a prefix of another's.
|
|
4
|
+
*/
|
|
5
|
+
/** Refused when a tenant id is empty, too long, or holds a character a scoped key could be split on. */
|
|
6
|
+
export declare class TenantIdError extends RangeError {
|
|
7
|
+
/** Always `TENANT_ID_INVALID`. */
|
|
8
|
+
readonly code = "TENANT_ID_INVALID";
|
|
9
|
+
constructor(tenantId: unknown);
|
|
10
|
+
}
|
|
11
|
+
/** Returns a tenant id unchanged, or throws `TenantIdError` when it is not one. */
|
|
12
|
+
export declare function assertTenantId(tenantId: string): string;
|
|
13
|
+
/** @internal The prefix a tenant's names and keys carry in a shared store. */
|
|
14
|
+
export declare function tenantPrefix(tenantId: string): string;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export class TenantIdError extends RangeError {
|
|
2
|
+
code = 'TENANT_ID_INVALID';
|
|
3
|
+
constructor(tenantId) {
|
|
4
|
+
super(`"${String(tenantId)}" is not a valid tenant id: use 1 to 128 letters, digits, underscores, and hyphens`);
|
|
5
|
+
this.name = 'TenantIdError';
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
const TENANT_ID = /^[A-Za-z0-9_-]{1,128}$/;
|
|
9
|
+
export function assertTenantId(tenantId) {
|
|
10
|
+
if (typeof tenantId !== 'string' || !TENANT_ID.test(tenantId))
|
|
11
|
+
throw new TenantIdError(tenantId);
|
|
12
|
+
return tenantId;
|
|
13
|
+
}
|
|
14
|
+
export function tenantPrefix(tenantId) {
|
|
15
|
+
return `tenant/${assertTenantId(tenantId)}/`;
|
|
16
|
+
}
|
package/dist/version.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const NEXUS_VERSION = '2.2.0';
|
|
@@ -2,7 +2,7 @@ import type { OperationLifecycleLike } from '../types/lifecycle.js';
|
|
|
2
2
|
import { type CompiledGraph } from '../graph/graph.js';
|
|
3
3
|
import type { GraphCheckpointer, NodeContext } from '../types/graph.js';
|
|
4
4
|
import type { CompletionRequest, Message, ToolDefinition } from '../types/messages.js';
|
|
5
|
-
import type { NexusResponse } from '../types/response.js';
|
|
5
|
+
import type { NexusResponse, StreamChunk } from '../types/response.js';
|
|
6
6
|
import type { Store } from '../types/store.js';
|
|
7
7
|
/**
|
|
8
8
|
* An agent as a graph.
|
|
@@ -17,6 +17,8 @@ import type { Store } from '../types/store.js';
|
|
|
17
17
|
export interface AgentModelClient {
|
|
18
18
|
/** Runs one completion. */
|
|
19
19
|
complete(request: CompletionRequest): Promise<NexusResponse>;
|
|
20
|
+
/** Streams one completion. Used when the agent is created with `streamTokens`. */
|
|
21
|
+
stream?(request: CompletionRequest): AsyncIterable<StreamChunk>;
|
|
20
22
|
}
|
|
21
23
|
/** A tool call the agent is about to make. */
|
|
22
24
|
export interface AgentToolCall {
|
|
@@ -108,6 +110,12 @@ export interface CreateAgentOptions {
|
|
|
108
110
|
* `ai.lifecycle`. Its model calls are operations of their own.
|
|
109
111
|
*/
|
|
110
112
|
lifecycle?: OperationLifecycleLike;
|
|
113
|
+
/**
|
|
114
|
+
* Streams the model's output token by token onto the run's `messages` events, through the client's
|
|
115
|
+
* `stream()`. Without it, or with a client that cannot stream, each answer arrives as one message
|
|
116
|
+
* event once the model returns. Middleware sees the assembled response either way.
|
|
117
|
+
*/
|
|
118
|
+
streamTokens?: boolean;
|
|
111
119
|
}
|
|
112
120
|
declare const agentChannels: () => {
|
|
113
121
|
messages: import("../types/graph.js").Channel<Message[]>;
|
|
@@ -42,7 +42,12 @@ function createAgent(options) {
|
|
|
42
42
|
for (const item of middleware) {
|
|
43
43
|
request = (await item.beforeModel?.({ request, state, store: options.store })) ?? request;
|
|
44
44
|
}
|
|
45
|
-
let response =
|
|
45
|
+
let response = options.streamTokens && options.client.stream
|
|
46
|
+
? await streamed(options.client.stream(request), (chunk) => context.message(chunk))
|
|
47
|
+
: await options.client.complete(request);
|
|
48
|
+
if (!(options.streamTokens && options.client.stream) && response.content) {
|
|
49
|
+
context.message({ content: response.content });
|
|
50
|
+
}
|
|
46
51
|
for (const item of middleware) {
|
|
47
52
|
response = (await item.afterModel?.({ response, state, store: options.store })) ?? response;
|
|
48
53
|
}
|
|
@@ -93,9 +98,13 @@ function createAgent(options) {
|
|
|
93
98
|
args = verdict.args;
|
|
94
99
|
}
|
|
95
100
|
const run = async () => executor.execute(description.name, args);
|
|
101
|
+
context.tool({ phase: 'start', id: call.id, name: description.name, args });
|
|
96
102
|
const result = await middleware.reduceRight((next, item) => item.wrapToolCall
|
|
97
103
|
? () => Promise.resolve(item.wrapToolCall?.({ ...description, args }, next))
|
|
98
104
|
: next, run)();
|
|
105
|
+
context.tool(result.ok
|
|
106
|
+
? { phase: 'result', id: call.id, name: description.name, result: result.result }
|
|
107
|
+
: { phase: 'error', id: call.id, name: description.name, error: result.error ?? 'The tool failed' });
|
|
99
108
|
return { messages: [toolMessage(call, result)] };
|
|
100
109
|
}, { ends: ['model'] })
|
|
101
110
|
.setEntry('model')
|
|
@@ -161,3 +170,33 @@ function parseArguments(raw) {
|
|
|
161
170
|
return { ok: false, error: `Tool arguments are not valid JSON (${reason}); the tool was not run` };
|
|
162
171
|
}
|
|
163
172
|
}
|
|
173
|
+
async function streamed(chunks, onChunk) {
|
|
174
|
+
let content = '';
|
|
175
|
+
const toolCalls = [];
|
|
176
|
+
let meta = {};
|
|
177
|
+
for await (const chunk of chunks) {
|
|
178
|
+
if (chunk.type === 'text' && chunk.content) {
|
|
179
|
+
content += chunk.content;
|
|
180
|
+
onChunk({ kind: 'text', content: chunk.content });
|
|
181
|
+
}
|
|
182
|
+
else if (chunk.type === 'reasoning' && chunk.content) {
|
|
183
|
+
onChunk({ kind: 'reasoning', content: chunk.content });
|
|
184
|
+
}
|
|
185
|
+
else if (chunk.type === 'tool_call' && chunk.toolCall) {
|
|
186
|
+
toolCalls.push(chunk.toolCall);
|
|
187
|
+
}
|
|
188
|
+
else if (chunk.type === 'done') {
|
|
189
|
+
meta = chunk.meta ?? meta;
|
|
190
|
+
}
|
|
191
|
+
else if (chunk.type === 'error') {
|
|
192
|
+
throw new Error(chunk.error ?? 'The model stream failed');
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return {
|
|
196
|
+
content,
|
|
197
|
+
role: 'assistant',
|
|
198
|
+
...(toolCalls.length ? { toolCalls } : {}),
|
|
199
|
+
finishReason: toolCalls.length ? 'tool_calls' : 'stop',
|
|
200
|
+
meta: meta,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
@@ -15,6 +15,14 @@ export declare class MemoryCache<T> {
|
|
|
15
15
|
constructor(maxEntries?: number);
|
|
16
16
|
/** Returns a value, or `undefined` for a miss or an expired entry. A hit counts as recent use. */
|
|
17
17
|
get(key: string): T | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* Like `get()`, also saying whether an entry was there but had expired, which a caller can report
|
|
20
|
+
* as stale rather than missing. The expired entry is removed either way.
|
|
21
|
+
*/
|
|
22
|
+
lookup(key: string): {
|
|
23
|
+
value?: T;
|
|
24
|
+
stale: boolean;
|
|
25
|
+
};
|
|
18
26
|
/** Stores a value. Defaults to 5 minutes. */
|
|
19
27
|
set(key: string, value: T, ttlSeconds?: number): void;
|
|
20
28
|
/** Removes every entry. */
|
|
@@ -20,6 +20,15 @@ class MemoryCache {
|
|
|
20
20
|
this.entries.set(key, entry);
|
|
21
21
|
return entry.value;
|
|
22
22
|
}
|
|
23
|
+
lookup(key) {
|
|
24
|
+
const entry = this.entries.get(key);
|
|
25
|
+
if (entry && entry.expiresAt < Date.now()) {
|
|
26
|
+
this.entries.delete(key);
|
|
27
|
+
return { stale: true };
|
|
28
|
+
}
|
|
29
|
+
const value = this.get(key);
|
|
30
|
+
return value === undefined ? { stale: false } : { value, stale: false };
|
|
31
|
+
}
|
|
23
32
|
set(key, value, ttlSeconds = 300) {
|
|
24
33
|
if (this.entries.size >= this.maxEntries) {
|
|
25
34
|
const oldest = this.entries.keys().next().value;
|
|
@@ -25,10 +25,13 @@ export declare class SemanticCache {
|
|
|
25
25
|
constructor(options?: SemanticCacheOptions);
|
|
26
26
|
/**
|
|
27
27
|
* The cached response for the most similar earlier request above the threshold, or `undefined`.
|
|
28
|
+
* Only entries stored under the same `scope` are compared: the client passes the request's tenant
|
|
29
|
+
* and cache namespace, so one tenant is never answered from another's entry however alike the
|
|
30
|
+
* questions are.
|
|
28
31
|
*/
|
|
29
|
-
get(request: CompletionRequest): Promise<NexusResponse | undefined>;
|
|
30
|
-
/** Caches a response under its request's embedding. */
|
|
31
|
-
set(key: string, request: CompletionRequest, response: NexusResponse): Promise<void>;
|
|
32
|
+
get(request: CompletionRequest, scope?: string): Promise<NexusResponse | undefined>;
|
|
33
|
+
/** Caches a response under its request's embedding, in a `scope` lookups must match. */
|
|
34
|
+
set(key: string, request: CompletionRequest, response: NexusResponse, scope?: string): Promise<void>;
|
|
32
35
|
/** Removes every entry. */
|
|
33
36
|
clear(): void;
|
|
34
37
|
}
|
|
@@ -10,7 +10,7 @@ class SemanticCache {
|
|
|
10
10
|
this.options = options;
|
|
11
11
|
this.embed = options.embed || retrieval_js_1.createHashEmbeddings;
|
|
12
12
|
}
|
|
13
|
-
async get(request) {
|
|
13
|
+
async get(request, scope = '') {
|
|
14
14
|
if (!this.options.enabled)
|
|
15
15
|
return undefined;
|
|
16
16
|
const text = requestToSearchText(request);
|
|
@@ -20,6 +20,8 @@ class SemanticCache {
|
|
|
20
20
|
let best;
|
|
21
21
|
this.entries = this.entries.filter((entry) => entry.expiresAt > now);
|
|
22
22
|
for (const entry of this.entries) {
|
|
23
|
+
if (entry.scope !== scope)
|
|
24
|
+
continue;
|
|
23
25
|
const score = (0, retrieval_js_1.cosineSimilarity)(embedding, entry.embedding);
|
|
24
26
|
if (score >= threshold && (!best || score > best.score)) {
|
|
25
27
|
best = { entry, score };
|
|
@@ -40,7 +42,7 @@ class SemanticCache {
|
|
|
40
42
|
},
|
|
41
43
|
};
|
|
42
44
|
}
|
|
43
|
-
async set(key, request, response) {
|
|
45
|
+
async set(key, request, response, scope = '') {
|
|
44
46
|
if (!this.options.enabled)
|
|
45
47
|
return;
|
|
46
48
|
const text = requestToSearchText(request);
|
|
@@ -50,6 +52,7 @@ class SemanticCache {
|
|
|
50
52
|
this.entries.shift();
|
|
51
53
|
this.entries.push({
|
|
52
54
|
key,
|
|
55
|
+
scope,
|
|
53
56
|
text,
|
|
54
57
|
embedding,
|
|
55
58
|
response,
|
package/dist-cjs/cli/args.js
CHANGED
|
@@ -53,12 +53,15 @@ exports.BOOLEAN_FLAGS = new Set([
|
|
|
53
53
|
'allow-dataset-mismatch',
|
|
54
54
|
'check',
|
|
55
55
|
'densify',
|
|
56
|
+
'dry-run',
|
|
56
57
|
'fail',
|
|
57
58
|
'fail-on-regression',
|
|
58
59
|
'help',
|
|
59
60
|
'json',
|
|
60
61
|
'print',
|
|
62
|
+
'record',
|
|
61
63
|
'reveal-values',
|
|
64
|
+
'strict',
|
|
62
65
|
'write',
|
|
63
66
|
]);
|
|
64
67
|
function parseArgs(args) {
|
package/dist-cjs/cli/db.d.ts
CHANGED
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
import { type ParsedArgs } from './args.js';
|
|
2
2
|
/**
|
|
3
|
-
* `nexus db sql
|
|
3
|
+
* `nexus db sql | status | migrate`.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* `sql` prints the Postgres schema, so the CLI needs no driver and the schema can go through the
|
|
6
|
+
* application's own review and tooling: `nexus db sql | psql "$URL"`. `status` and `migrate` reach
|
|
7
|
+
* the database through a module the application writes, which exports its own client:
|
|
8
|
+
*
|
|
9
|
+
* ```js
|
|
10
|
+
* // db.mjs
|
|
11
|
+
* import pg from 'pg';
|
|
12
|
+
* export const client = new pg.Pool({ connectionString: process.env.DATABASE_URL });
|
|
13
|
+
* export const close = () => client.end();
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* The module may also export `dialect` (`postgres` or `sqlite`), a `transaction` function (see
|
|
17
|
+
* `PostgresMigrateOptions`), and `migrations`, a list replacing the bundled ones, for stores on
|
|
18
|
+
* custom tables.
|
|
7
19
|
*/
|
|
8
|
-
export declare function runDbCommand(subcommand: string | undefined,
|
|
20
|
+
export declare function runDbCommand(subcommand: string | undefined, args: ParsedArgs): Promise<void>;
|