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
package/dist-cjs/sqlite/store.js
CHANGED
|
@@ -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.SqliteStore = void 0;
|
|
4
37
|
exports.sqliteStoreMigration = sqliteStoreMigration;
|
|
38
|
+
exports.sqliteStoreMigrations = sqliteStoreMigrations;
|
|
5
39
|
const helpers_js_1 = require("../store/helpers.js");
|
|
6
40
|
const client_js_1 = require("./client.js");
|
|
7
41
|
const DEFAULT_TABLE = 'nexus_store';
|
|
@@ -25,6 +59,16 @@ function sqliteStoreMigration(options = {}) {
|
|
|
25
59
|
`CREATE INDEX IF NOT EXISTS "${name}_expiry" ON ${table} (expires_at) WHERE expires_at IS NOT NULL`,
|
|
26
60
|
];
|
|
27
61
|
}
|
|
62
|
+
function sqliteStoreMigrations(options = {}) {
|
|
63
|
+
return [
|
|
64
|
+
{
|
|
65
|
+
component: `store:${options.table ?? DEFAULT_TABLE}`,
|
|
66
|
+
version: 1,
|
|
67
|
+
name: 'create the store table',
|
|
68
|
+
statements: sqliteStoreMigration(options),
|
|
69
|
+
},
|
|
70
|
+
];
|
|
71
|
+
}
|
|
28
72
|
class SqliteStore {
|
|
29
73
|
options;
|
|
30
74
|
client;
|
|
@@ -36,9 +80,9 @@ class SqliteStore {
|
|
|
36
80
|
this.table = (0, client_js_1.quoteSqliteTable)(options.table ?? DEFAULT_TABLE);
|
|
37
81
|
this.now = options.now ?? (() => new Date());
|
|
38
82
|
}
|
|
39
|
-
async migrate() {
|
|
40
|
-
|
|
41
|
-
|
|
83
|
+
async migrate(options = {}) {
|
|
84
|
+
const { applySqliteMigrations } = await Promise.resolve().then(() => __importStar(require('./migrations.js')));
|
|
85
|
+
return applySqliteMigrations(this.client, sqliteStoreMigrations(this.options), options);
|
|
42
86
|
}
|
|
43
87
|
async put(namespace, key, value, options = {}) {
|
|
44
88
|
if (!key.trim())
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type EmbeddingProvider, type VectorDocument, type VectorSearchOptions, type VectorSearchResult, type VectorStore } from '../hallucination/retrieval.js';
|
|
2
|
+
import type { MigrationResult, SchemaMigration } from '../utils/schema-migrations.js';
|
|
2
3
|
import { type SqliteDatabaseLike, type SqliteLikeClient } from './client.js';
|
|
4
|
+
import type { SqliteMigrateOptions } from './migrations.js';
|
|
3
5
|
/** Options for the SQLite vector store. */
|
|
4
6
|
export interface SqliteVectorStoreOptions {
|
|
5
7
|
/** Width of every vector. Must match the embedding function's output. */
|
|
@@ -20,6 +22,10 @@ export interface SqliteVectorStoreOptions {
|
|
|
20
22
|
export declare function sqliteVectorStoreMigration(options?: {
|
|
21
23
|
table?: string;
|
|
22
24
|
}): string;
|
|
25
|
+
/** The versioned schema, which `migrate()` applies. Version 1 is the 2.0 table. */
|
|
26
|
+
export declare function sqliteVectorStoreMigrations(options?: {
|
|
27
|
+
table?: string;
|
|
28
|
+
}): SchemaMigration[];
|
|
23
29
|
/**
|
|
24
30
|
* Retrieval chunks in SQLite: one file, no server, the same contract as every other store.
|
|
25
31
|
*
|
|
@@ -34,8 +40,11 @@ export declare class SqliteVectorStore implements VectorStore {
|
|
|
34
40
|
private readonly table;
|
|
35
41
|
private readonly embed;
|
|
36
42
|
constructor(database: SqliteLikeClient | SqliteDatabaseLike, options: SqliteVectorStoreOptions);
|
|
37
|
-
/**
|
|
38
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Applies this store's pending migrations, recorded in `nexus_schema_migrations`, each inside
|
|
45
|
+
* `BEGIN IMMEDIATE`. Never runs implicitly. Safe on a file an older release created.
|
|
46
|
+
*/
|
|
47
|
+
migrate(options?: SqliteMigrateOptions): Promise<MigrationResult>;
|
|
39
48
|
/** Adds chunks, or replaces those whose id exists, embedding those without a vector in one batch. */
|
|
40
49
|
add(documents: VectorDocument[]): Promise<void>;
|
|
41
50
|
/** The chunks most similar to a query, best first. */
|
|
@@ -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.SqliteVectorStore = void 0;
|
|
4
37
|
exports.sqliteVectorStoreMigration = sqliteVectorStoreMigration;
|
|
38
|
+
exports.sqliteVectorStoreMigrations = sqliteVectorStoreMigrations;
|
|
5
39
|
const retrieval_js_1 = require("../hallucination/retrieval.js");
|
|
6
40
|
const vector_helpers_js_1 = require("../rag/vector-helpers.js");
|
|
7
41
|
const client_js_1 = require("./client.js");
|
|
@@ -9,6 +43,16 @@ function sqliteVectorStoreMigration(options = {}) {
|
|
|
9
43
|
const table = (0, client_js_1.quoteSqliteTable)(options.table ?? 'nexus_vectors');
|
|
10
44
|
return `CREATE TABLE IF NOT EXISTS ${table} (id TEXT PRIMARY KEY, content TEXT NOT NULL, source TEXT, metadata TEXT, embedding BLOB NOT NULL)`;
|
|
11
45
|
}
|
|
46
|
+
function sqliteVectorStoreMigrations(options = {}) {
|
|
47
|
+
return [
|
|
48
|
+
{
|
|
49
|
+
component: `vectors:${options.table ?? 'nexus_vectors'}`,
|
|
50
|
+
version: 1,
|
|
51
|
+
name: 'create the vectors table',
|
|
52
|
+
statements: [sqliteVectorStoreMigration(options)],
|
|
53
|
+
},
|
|
54
|
+
];
|
|
55
|
+
}
|
|
12
56
|
class SqliteVectorStore {
|
|
13
57
|
options;
|
|
14
58
|
client;
|
|
@@ -21,8 +65,9 @@ class SqliteVectorStore {
|
|
|
21
65
|
this.table = (0, client_js_1.quoteSqliteTable)(options.table ?? 'nexus_vectors');
|
|
22
66
|
this.embed = options.embed ?? ((texts) => (0, retrieval_js_1.createHashEmbeddings)(texts, options.dimensions));
|
|
23
67
|
}
|
|
24
|
-
async migrate() {
|
|
25
|
-
await
|
|
68
|
+
async migrate(options = {}) {
|
|
69
|
+
const { applySqliteMigrations } = await Promise.resolve().then(() => __importStar(require('./migrations.js')));
|
|
70
|
+
return applySqliteMigrations(this.client, sqliteVectorStoreMigrations(this.options), options);
|
|
26
71
|
}
|
|
27
72
|
async add(documents) {
|
|
28
73
|
if (documents.length === 0)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Store } from '../types/store.js';
|
|
2
|
+
/** The first namespace part under which every tenant's items live, so they never meet an application's own. */
|
|
3
|
+
export declare const TENANT_NAMESPACE = "nexus:tenant";
|
|
4
|
+
/**
|
|
5
|
+
* One tenant's view of a long-term store: every namespace it reads or writes is placed under
|
|
6
|
+
* `['nexus:tenant', tenantId]`, and every item it returns has that prefix taken off again. A search
|
|
7
|
+
* or a namespace listing cannot reach past it, so another tenant's items are not merely filtered out
|
|
8
|
+
* but never read. Works over any store — memory, Redis, Postgres, SQLite — with no schema change.
|
|
9
|
+
*
|
|
10
|
+
* A graph run given a `tenantId` sees its store through this view as `context.store`.
|
|
11
|
+
*/
|
|
12
|
+
export declare function tenantStore(store: Store, tenantId: string): Store;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TENANT_NAMESPACE = void 0;
|
|
4
|
+
exports.tenantStore = tenantStore;
|
|
5
|
+
const tenant_js_1 = require("../utils/tenant.js");
|
|
6
|
+
exports.TENANT_NAMESPACE = 'nexus:tenant';
|
|
7
|
+
function tenantStore(store, tenantId) {
|
|
8
|
+
const root = [exports.TENANT_NAMESPACE, (0, tenant_js_1.assertTenantId)(tenantId)];
|
|
9
|
+
const scope = (namespace) => [...root, ...namespace];
|
|
10
|
+
const unscope = (item) => ({ ...item, namespace: item.namespace.slice(root.length) });
|
|
11
|
+
return {
|
|
12
|
+
put(namespace, key, value, options) {
|
|
13
|
+
return store.put(scope(namespace), key, value, options);
|
|
14
|
+
},
|
|
15
|
+
async get(namespace, key) {
|
|
16
|
+
const item = await store.get(scope(namespace), key);
|
|
17
|
+
return item ? unscope(item) : undefined;
|
|
18
|
+
},
|
|
19
|
+
delete(namespace, key) {
|
|
20
|
+
return store.delete(scope(namespace), key);
|
|
21
|
+
},
|
|
22
|
+
async search(namespacePrefix, options) {
|
|
23
|
+
return (await store.search(scope(namespacePrefix), options)).map(unscope);
|
|
24
|
+
},
|
|
25
|
+
async listNamespaces(options = {}) {
|
|
26
|
+
const namespaces = await store.listNamespaces({
|
|
27
|
+
prefix: scope(options.prefix ?? []),
|
|
28
|
+
...(options.limit === undefined ? {} : { limit: options.limit }),
|
|
29
|
+
});
|
|
30
|
+
return namespaces.map((namespace) => namespace.slice(root.length)).filter((namespace) => namespace.length > 0);
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One tenant model for every store.
|
|
3
|
+
*
|
|
4
|
+
* Each function returns one tenant's view of a shared store, implementing the same contract as the
|
|
5
|
+
* store itself, so a tenant's code takes a `TraceStore`, a `PromptStore`, or a `VectorStore` as it
|
|
6
|
+
* always did and cannot reach past its tenant. Names and keys are placed under the tenant's prefix
|
|
7
|
+
* (`tenant/<id>/`) and records carry `tenantId`, so the views work over the memory, Redis, Postgres,
|
|
8
|
+
* SQLite, and file stores alike, with no schema change. A tenant id is letters, digits, `_`, and `-`,
|
|
9
|
+
* so no tenant's prefix is the start of another's.
|
|
10
|
+
*/
|
|
11
|
+
import type { CacheAdapter } from '../cache/adapters.js';
|
|
12
|
+
import type { VectorStore } from '../hallucination/retrieval.js';
|
|
13
|
+
import type { AssetPutOptions, AssetSignOptions, AssetStore } from '../images/asset-support.js';
|
|
14
|
+
import type { RollupStore } from '../tracing/rollups.js';
|
|
15
|
+
import type { DatasetStore, ExperimentStore } from '../types/evaluate.js';
|
|
16
|
+
import type { OperationStore } from '../types/operations.js';
|
|
17
|
+
import type { PromptStore } from '../types/prompts.js';
|
|
18
|
+
import type { Store } from '../types/store.js';
|
|
19
|
+
import type { TraceStore } from '../types/tracing.js';
|
|
20
|
+
export { TENANT_NAMESPACE, tenantStore } from '../store/tenant.js';
|
|
21
|
+
export { assertTenantId, TenantIdError } from '../utils/tenant.js';
|
|
22
|
+
/**
|
|
23
|
+
* One tenant's traces. Every run saved through it is stamped `metadata.tenantId`, the field rollups,
|
|
24
|
+
* the studio, and the Postgres tenant index read; `get()`, `query()`, and `tree()` return only runs so
|
|
25
|
+
* stamped, and feedback reaches only the tenant's own runs. `prune()` is left out, since it would
|
|
26
|
+
* remove every tenant's old runs.
|
|
27
|
+
*/
|
|
28
|
+
export declare function tenantTraceStore(store: TraceStore, tenantId: string): TraceStore;
|
|
29
|
+
/**
|
|
30
|
+
* One tenant's operations. Records it creates carry `tenantId`, and their idempotency keys are
|
|
31
|
+
* placed under the tenant's prefix, so two tenants using the same key never collide. Reads, updates,
|
|
32
|
+
* deletes, recovery, and queue listings see only the tenant's records; `listQueued()` and `stats()`
|
|
33
|
+
* pass the tenant to the store as a filter, which Postgres and SQLite answer from an index.
|
|
34
|
+
*/
|
|
35
|
+
export declare function tenantOperationStore<TResult = unknown>(store: OperationStore<TResult>, tenantId: string): OperationStore<TResult>;
|
|
36
|
+
/**
|
|
37
|
+
* One tenant's prompts. Every prompt name is placed under the tenant's prefix on the way in and
|
|
38
|
+
* taken off on the way out, so the tenant sees its own names and `listNames()` lists only them. A
|
|
39
|
+
* `ContextHub` given this store keeps the tenant's context bundles apart the same way.
|
|
40
|
+
*/
|
|
41
|
+
export declare function tenantPromptStore(store: PromptStore, tenantId: string): PromptStore;
|
|
42
|
+
/** One tenant's datasets: names placed under the tenant's prefix, and `list()` showing only its own. */
|
|
43
|
+
export declare function tenantDatasetStore(store: DatasetStore, tenantId: string): DatasetStore;
|
|
44
|
+
/**
|
|
45
|
+
* One tenant's experiments. Ids, names, and dataset names are placed under the tenant's prefix, so
|
|
46
|
+
* `get()` of another tenant's experiment id finds nothing and `list()` returns only the tenant's.
|
|
47
|
+
*/
|
|
48
|
+
export declare function tenantExperimentStore(store: ExperimentStore, tenantId: string): ExperimentStore;
|
|
49
|
+
/**
|
|
50
|
+
* One tenant's retrieval chunks. Each chunk's id is placed under the tenant's prefix and its metadata
|
|
51
|
+
* stamped `tenantId`, and every search adds `tenantId` to its filter, which every vector store applies
|
|
52
|
+
* natively. A search never ranks another tenant's chunks, and `delete()` reaches only the tenant's.
|
|
53
|
+
*/
|
|
54
|
+
export declare function tenantVectorStore(store: VectorStore, tenantId: string): VectorStore;
|
|
55
|
+
/**
|
|
56
|
+
* One tenant's cache: every key placed under the tenant's prefix, so a tenant can never read what
|
|
57
|
+
* another cached. `clear()` is left out, since it would clear every tenant's entries.
|
|
58
|
+
*/
|
|
59
|
+
export declare function tenantCache<T = unknown>(cache: CacheAdapter<T>, tenantId: string): CacheAdapter<T>;
|
|
60
|
+
/** An asset store with the tenant bound, so no call can name another. Returned by `tenantAssetStore()`. */
|
|
61
|
+
export interface TenantAssetStore {
|
|
62
|
+
/** The tenant every call acts for. */
|
|
63
|
+
readonly tenantId: string;
|
|
64
|
+
/** Stores an asset for the tenant. */
|
|
65
|
+
put(input: Parameters<AssetStore['put']>[0], options: Omit<AssetPutOptions, 'tenantId'>): ReturnType<AssetStore['put']>;
|
|
66
|
+
/** Reads one of the tenant's assets with its bytes. */
|
|
67
|
+
get(assetId: string): ReturnType<AssetStore['get']>;
|
|
68
|
+
/** Describes one of the tenant's assets. */
|
|
69
|
+
stat(assetId: string): ReturnType<AssetStore['stat']>;
|
|
70
|
+
/** Deletes one of the tenant's assets. */
|
|
71
|
+
delete(assetId: string): ReturnType<AssetStore['delete']>;
|
|
72
|
+
/** Signs a URL for one of the tenant's assets. */
|
|
73
|
+
sign(assetId: string, options?: AssetSignOptions): ReturnType<AssetStore['sign']>;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* One tenant's assets. Asset stores already treat another tenant's asset as missing; this binds the
|
|
77
|
+
* tenant once, so code handed the view cannot pass a different one.
|
|
78
|
+
*/
|
|
79
|
+
export declare function tenantAssetStore(store: AssetStore, tenantId: string): TenantAssetStore;
|
|
80
|
+
/** One tenant's rollups: rows it adds are counted for the tenant, and queries read only the tenant's rows. */
|
|
81
|
+
export declare function tenantRollupStore(store: RollupStore, tenantId: string): RollupStore;
|
|
82
|
+
/** The stores `tenantScope()` can scope. Each is optional. */
|
|
83
|
+
export interface TenantStores {
|
|
84
|
+
/** Long-term memory. */
|
|
85
|
+
store?: Store;
|
|
86
|
+
/** Traces. */
|
|
87
|
+
traces?: TraceStore;
|
|
88
|
+
/** Operation records. */
|
|
89
|
+
operations?: OperationStore<unknown>;
|
|
90
|
+
/** Prompt versions and labels, and the context hub's bundles. */
|
|
91
|
+
prompts?: PromptStore;
|
|
92
|
+
/** Datasets. */
|
|
93
|
+
datasets?: DatasetStore;
|
|
94
|
+
/** Experiments. */
|
|
95
|
+
experiments?: ExperimentStore;
|
|
96
|
+
/** Retrieval chunks. */
|
|
97
|
+
vectors?: VectorStore;
|
|
98
|
+
/** A cache. */
|
|
99
|
+
cache?: CacheAdapter<unknown>;
|
|
100
|
+
/** Dashboard rollups. */
|
|
101
|
+
rollups?: RollupStore;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Scopes every given store to one tenant at once, keeping each one's type, so a request handler
|
|
105
|
+
* builds its tenant's view in one line.
|
|
106
|
+
*
|
|
107
|
+
* ```ts
|
|
108
|
+
* const scoped = tenantScope(principal.tenantId, { store, traces, prompts, vectors });
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
export declare function tenantScope<T extends TenantStores>(tenantId: string, stores: T): T & {
|
|
112
|
+
readonly tenantId: string;
|
|
113
|
+
};
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TenantIdError = exports.assertTenantId = exports.tenantStore = exports.TENANT_NAMESPACE = void 0;
|
|
4
|
+
exports.tenantTraceStore = tenantTraceStore;
|
|
5
|
+
exports.tenantOperationStore = tenantOperationStore;
|
|
6
|
+
exports.tenantPromptStore = tenantPromptStore;
|
|
7
|
+
exports.tenantDatasetStore = tenantDatasetStore;
|
|
8
|
+
exports.tenantExperimentStore = tenantExperimentStore;
|
|
9
|
+
exports.tenantVectorStore = tenantVectorStore;
|
|
10
|
+
exports.tenantCache = tenantCache;
|
|
11
|
+
exports.tenantAssetStore = tenantAssetStore;
|
|
12
|
+
exports.tenantRollupStore = tenantRollupStore;
|
|
13
|
+
exports.tenantScope = tenantScope;
|
|
14
|
+
const tenant_js_1 = require("../utils/tenant.js");
|
|
15
|
+
const tenant_js_2 = require("../store/tenant.js");
|
|
16
|
+
var tenant_js_3 = require("../store/tenant.js");
|
|
17
|
+
Object.defineProperty(exports, "TENANT_NAMESPACE", { enumerable: true, get: function () { return tenant_js_3.TENANT_NAMESPACE; } });
|
|
18
|
+
Object.defineProperty(exports, "tenantStore", { enumerable: true, get: function () { return tenant_js_3.tenantStore; } });
|
|
19
|
+
var tenant_js_4 = require("../utils/tenant.js");
|
|
20
|
+
Object.defineProperty(exports, "assertTenantId", { enumerable: true, get: function () { return tenant_js_4.assertTenantId; } });
|
|
21
|
+
Object.defineProperty(exports, "TenantIdError", { enumerable: true, get: function () { return tenant_js_4.TenantIdError; } });
|
|
22
|
+
function names(tenantId) {
|
|
23
|
+
const prefix = (0, tenant_js_1.tenantPrefix)(tenantId);
|
|
24
|
+
return {
|
|
25
|
+
prefix,
|
|
26
|
+
in: (name) => `${prefix}${name}`,
|
|
27
|
+
owns: (name) => name.startsWith(prefix),
|
|
28
|
+
out: (name) => name.slice(prefix.length),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function stamped(metadata, tenantId) {
|
|
32
|
+
return metadata?.tenantId === tenantId;
|
|
33
|
+
}
|
|
34
|
+
function tenantTraceStore(store, tenantId) {
|
|
35
|
+
(0, tenant_js_1.tenantPrefix)(tenantId);
|
|
36
|
+
const own = (run) => (run && stamped(run.metadata, tenantId) ? run : undefined);
|
|
37
|
+
const prune = (tree) => ({
|
|
38
|
+
...tree,
|
|
39
|
+
children: tree.children.filter((child) => stamped(child.metadata, tenantId)).map(prune),
|
|
40
|
+
});
|
|
41
|
+
return {
|
|
42
|
+
save: (run) => store.save({ ...run, metadata: { ...run.metadata, tenantId } }),
|
|
43
|
+
get: async (runId) => own(await store.get(runId)),
|
|
44
|
+
query: (query = {}) => store.query({ ...query, metadata: { ...query.metadata, tenantId } }),
|
|
45
|
+
async tree(traceId) {
|
|
46
|
+
const tree = await store.tree(traceId);
|
|
47
|
+
return tree && stamped(tree.metadata, tenantId) ? prune(tree) : undefined;
|
|
48
|
+
},
|
|
49
|
+
async addFeedback(runId, feedback) {
|
|
50
|
+
const run = own(await store.get(runId));
|
|
51
|
+
if (!run)
|
|
52
|
+
return;
|
|
53
|
+
if (store.addFeedback)
|
|
54
|
+
await store.addFeedback(runId, feedback);
|
|
55
|
+
else
|
|
56
|
+
await store.save({ ...run, feedback: [...(run.feedback ?? []), feedback] });
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function tenantOperationStore(store, tenantId) {
|
|
61
|
+
const keys = names(tenantId);
|
|
62
|
+
const inward = (record) => ({
|
|
63
|
+
...record,
|
|
64
|
+
tenantId,
|
|
65
|
+
...(record.idempotencyKey ? { idempotencyKey: keys.in(record.idempotencyKey) } : {}),
|
|
66
|
+
});
|
|
67
|
+
const outward = (record) => {
|
|
68
|
+
if (!record || record.tenantId !== tenantId)
|
|
69
|
+
return undefined;
|
|
70
|
+
return record.idempotencyKey && keys.owns(record.idempotencyKey)
|
|
71
|
+
? { ...record, idempotencyKey: keys.out(record.idempotencyKey) }
|
|
72
|
+
: record;
|
|
73
|
+
};
|
|
74
|
+
const own = (records) => records.map(outward).filter((record) => record !== undefined);
|
|
75
|
+
const filtered = (filter) => ({ ...filter, tenantId });
|
|
76
|
+
const view = {
|
|
77
|
+
create: (record) => store.create(inward(record)),
|
|
78
|
+
read: async (id) => outward(await store.read(id)),
|
|
79
|
+
async update(record, expectedSequence) {
|
|
80
|
+
if (record.tenantId !== undefined && record.tenantId !== tenantId)
|
|
81
|
+
return false;
|
|
82
|
+
if (!outward(await store.read(record.id)))
|
|
83
|
+
return false;
|
|
84
|
+
return store.update(inward(record), expectedSequence);
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
if (store.delete) {
|
|
88
|
+
const remove = store.delete.bind(store);
|
|
89
|
+
view.delete = async (id) => (outward(await store.read(id)) ? remove(id) : false);
|
|
90
|
+
}
|
|
91
|
+
if (store.claimExpired) {
|
|
92
|
+
const claim = store.claimExpired.bind(store);
|
|
93
|
+
view.claimExpired = async (now, limit) => own(await claim(now, limit));
|
|
94
|
+
}
|
|
95
|
+
if (store.findByIdempotencyKey) {
|
|
96
|
+
const find = store.findByIdempotencyKey.bind(store);
|
|
97
|
+
view.findByIdempotencyKey = async (key) => outward(await find(keys.in(key)));
|
|
98
|
+
}
|
|
99
|
+
if (store.list) {
|
|
100
|
+
const list = store.list.bind(store);
|
|
101
|
+
view.list = async () => own(await list());
|
|
102
|
+
}
|
|
103
|
+
if (store.listQueued) {
|
|
104
|
+
const listQueued = store.listQueued.bind(store);
|
|
105
|
+
view.listQueued = async (limit, filter) => own(await listQueued(limit, filtered(filter)));
|
|
106
|
+
}
|
|
107
|
+
if (store.stats) {
|
|
108
|
+
const stats = store.stats.bind(store);
|
|
109
|
+
view.stats = (now, filter) => stats(now, filtered(filter));
|
|
110
|
+
}
|
|
111
|
+
return view;
|
|
112
|
+
}
|
|
113
|
+
function tenantPromptStore(store, tenantId) {
|
|
114
|
+
const scoped = names(tenantId);
|
|
115
|
+
const named = (value) => ({ ...value, name: scoped.in(value.name) });
|
|
116
|
+
const unnamed = (value) => value && scoped.owns(value.name) ? { ...value, name: scoped.out(value.name) } : undefined;
|
|
117
|
+
const all = (values) => values.map(unnamed).filter((value) => value !== undefined);
|
|
118
|
+
return {
|
|
119
|
+
saveVersion: (version) => store.saveVersion(named(version)),
|
|
120
|
+
getVersion: async (name, version) => unnamed(await store.getVersion(scoped.in(name), version)),
|
|
121
|
+
listVersions: async (name, options) => all(await store.listVersions(scoped.in(name), options)),
|
|
122
|
+
getLabel: async (name, label) => unnamed(await store.getLabel(scoped.in(name), label)),
|
|
123
|
+
listLabels: async (name) => all(await store.listLabels(scoped.in(name))),
|
|
124
|
+
setLabel: (label, expected) => store.setLabel(named(label), expected),
|
|
125
|
+
deleteLabel: (name, label) => store.deleteLabel(scoped.in(name), label),
|
|
126
|
+
appendHistory: (entry) => store.appendHistory(named(entry)),
|
|
127
|
+
listHistory: async (name, options) => all(await store.listHistory(scoped.in(name), options)),
|
|
128
|
+
listNames: async () => (await store.listNames()).filter(scoped.owns).map(scoped.out).sort(),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function tenantDatasetStore(store, tenantId) {
|
|
132
|
+
const scoped = names(tenantId);
|
|
133
|
+
return {
|
|
134
|
+
save: (dataset) => store.save({ ...dataset, name: scoped.in(dataset.name) }),
|
|
135
|
+
async get(name, version) {
|
|
136
|
+
const dataset = await store.get(scoped.in(name), version);
|
|
137
|
+
return dataset ? { ...dataset, name: name } : undefined;
|
|
138
|
+
},
|
|
139
|
+
async list() {
|
|
140
|
+
return (await store.list())
|
|
141
|
+
.filter((entry) => scoped.owns(entry.name))
|
|
142
|
+
.map((entry) => ({ ...entry, name: scoped.out(entry.name) }));
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
function tenantExperimentStore(store, tenantId) {
|
|
147
|
+
const scoped = names(tenantId);
|
|
148
|
+
const inward = (experiment) => ({
|
|
149
|
+
...experiment,
|
|
150
|
+
id: scoped.in(experiment.id),
|
|
151
|
+
name: scoped.in(experiment.name),
|
|
152
|
+
dataset: { ...experiment.dataset, name: scoped.in(experiment.dataset.name) },
|
|
153
|
+
});
|
|
154
|
+
const outward = (experiment) => experiment && scoped.owns(experiment.id)
|
|
155
|
+
? {
|
|
156
|
+
...experiment,
|
|
157
|
+
id: scoped.out(experiment.id),
|
|
158
|
+
name: scoped.out(experiment.name),
|
|
159
|
+
dataset: { ...experiment.dataset, name: scoped.out(experiment.dataset.name) },
|
|
160
|
+
}
|
|
161
|
+
: undefined;
|
|
162
|
+
return {
|
|
163
|
+
save: (experiment) => store.save(inward(experiment)),
|
|
164
|
+
get: async (id) => outward(await store.get(scoped.in(id))),
|
|
165
|
+
async list(filter = {}) {
|
|
166
|
+
const experiments = await store.list({
|
|
167
|
+
...filter,
|
|
168
|
+
...(filter.name === undefined ? {} : { name: scoped.in(filter.name) }),
|
|
169
|
+
...(filter.dataset === undefined ? {} : { dataset: scoped.in(filter.dataset) }),
|
|
170
|
+
});
|
|
171
|
+
return experiments.map(outward).filter((experiment) => experiment !== undefined);
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
function tenantVectorStore(store, tenantId) {
|
|
176
|
+
const scoped = names(tenantId);
|
|
177
|
+
const outward = (results) => results
|
|
178
|
+
.filter((result) => scoped.owns(result.id) && stamped(result.metadata, tenantId))
|
|
179
|
+
.map((result) => {
|
|
180
|
+
const { tenantId: _owner, ...metadata } = result.metadata ?? {};
|
|
181
|
+
return { ...result, id: scoped.out(result.id), metadata };
|
|
182
|
+
});
|
|
183
|
+
const filtered = (options = {}) => ({
|
|
184
|
+
...options,
|
|
185
|
+
filter: { ...options.filter, tenantId },
|
|
186
|
+
});
|
|
187
|
+
return {
|
|
188
|
+
add: (documents) => store.add(documents.map((document) => ({
|
|
189
|
+
...document,
|
|
190
|
+
id: scoped.in(document.id),
|
|
191
|
+
metadata: { ...document.metadata, tenantId },
|
|
192
|
+
}))),
|
|
193
|
+
search: async (query, options) => outward(await store.search(query, filtered(options))),
|
|
194
|
+
searchVector: async (vector, options) => outward(await store.searchVector(vector, filtered(options))),
|
|
195
|
+
delete: (ids) => store.delete(ids.map(scoped.in)),
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
function tenantCache(cache, tenantId) {
|
|
199
|
+
const scoped = names(tenantId);
|
|
200
|
+
const view = {
|
|
201
|
+
get: (key) => cache.get(scoped.in(key)),
|
|
202
|
+
set: (key, value, ttlSeconds) => cache.set(scoped.in(key), value, ttlSeconds),
|
|
203
|
+
};
|
|
204
|
+
if (cache.delete) {
|
|
205
|
+
const remove = cache.delete.bind(cache);
|
|
206
|
+
view.delete = (key) => remove(scoped.in(key));
|
|
207
|
+
}
|
|
208
|
+
return view;
|
|
209
|
+
}
|
|
210
|
+
function tenantAssetStore(store, tenantId) {
|
|
211
|
+
(0, tenant_js_1.tenantPrefix)(tenantId);
|
|
212
|
+
return {
|
|
213
|
+
tenantId,
|
|
214
|
+
put: (input, options) => store.put(input, { ...options, tenantId }),
|
|
215
|
+
get: (assetId) => store.get(assetId, tenantId),
|
|
216
|
+
stat: (assetId) => store.stat(assetId, tenantId),
|
|
217
|
+
delete: (assetId) => store.delete(assetId, tenantId),
|
|
218
|
+
sign: (assetId, options) => store.sign(assetId, tenantId, options),
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
function tenantRollupStore(store, tenantId) {
|
|
222
|
+
(0, tenant_js_1.tenantPrefix)(tenantId);
|
|
223
|
+
return {
|
|
224
|
+
add: (key, totals) => store.add({ ...key, tenant: tenantId }, totals),
|
|
225
|
+
query: (query = {}) => store.query({ ...query, tenant: tenantId }),
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
function tenantScope(tenantId, stores) {
|
|
229
|
+
(0, tenant_js_1.tenantPrefix)(tenantId);
|
|
230
|
+
const scoped = {};
|
|
231
|
+
if (stores.store)
|
|
232
|
+
scoped.store = (0, tenant_js_2.tenantStore)(stores.store, tenantId);
|
|
233
|
+
if (stores.traces)
|
|
234
|
+
scoped.traces = tenantTraceStore(stores.traces, tenantId);
|
|
235
|
+
if (stores.operations)
|
|
236
|
+
scoped.operations = tenantOperationStore(stores.operations, tenantId);
|
|
237
|
+
if (stores.prompts)
|
|
238
|
+
scoped.prompts = tenantPromptStore(stores.prompts, tenantId);
|
|
239
|
+
if (stores.datasets)
|
|
240
|
+
scoped.datasets = tenantDatasetStore(stores.datasets, tenantId);
|
|
241
|
+
if (stores.experiments)
|
|
242
|
+
scoped.experiments = tenantExperimentStore(stores.experiments, tenantId);
|
|
243
|
+
if (stores.vectors)
|
|
244
|
+
scoped.vectors = tenantVectorStore(stores.vectors, tenantId);
|
|
245
|
+
if (stores.cache)
|
|
246
|
+
scoped.cache = tenantCache(stores.cache, tenantId);
|
|
247
|
+
if (stores.rollups)
|
|
248
|
+
scoped.rollups = tenantRollupStore(stores.rollups, tenantId);
|
|
249
|
+
return { ...stores, ...scoped, tenantId };
|
|
250
|
+
}
|
|
@@ -32,6 +32,40 @@ export interface RecordedResponse {
|
|
|
32
32
|
body: string;
|
|
33
33
|
/** How `body` is encoded. */
|
|
34
34
|
bodyEncoding: 'utf8' | 'base64';
|
|
35
|
+
/**
|
|
36
|
+
* The body as it arrived, chunk by chunk, with when each came, when recorded with `timing`. A
|
|
37
|
+
* paced replay sends these; an instant one sends `body`, which holds the same bytes.
|
|
38
|
+
*/
|
|
39
|
+
chunks?: RecordedChunk[];
|
|
40
|
+
}
|
|
41
|
+
/** One piece of a streamed response, and when it arrived. */
|
|
42
|
+
export interface RecordedChunk {
|
|
43
|
+
/** Milliseconds after the response started. */
|
|
44
|
+
atMs: number;
|
|
45
|
+
/** The bytes, as text or base64. */
|
|
46
|
+
body: string;
|
|
47
|
+
/** How `body` is encoded. */
|
|
48
|
+
bodyEncoding: 'utf8' | 'base64';
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* How a replayed stream is paced, for a recording made with `timing`.
|
|
52
|
+
*
|
|
53
|
+
* - `instant` (the default) sends the whole body at once, as a recording without timing does.
|
|
54
|
+
* - `original` sends each chunk when it arrived, relative to the first.
|
|
55
|
+
* - A number scales the gaps: `0.1` is ten times faster, `2` twice as slow.
|
|
56
|
+
* - A function is awaited before each chunk, so a test can release them one at a time.
|
|
57
|
+
*/
|
|
58
|
+
export type ReplayPace = 'instant' | 'original' | number | ((chunk: ReplayChunkInfo) => Promise<void> | void);
|
|
59
|
+
/** What a pacing function is told about the chunk it releases. */
|
|
60
|
+
export interface ReplayChunkInfo {
|
|
61
|
+
/** Its position, from 0. */
|
|
62
|
+
index: number;
|
|
63
|
+
/** How many chunks the response has. */
|
|
64
|
+
count: number;
|
|
65
|
+
/** When it arrived when recorded, in milliseconds after the response started. */
|
|
66
|
+
atMs: number;
|
|
67
|
+
/** The recorded gap since the chunk before it, in milliseconds. */
|
|
68
|
+
delayMs: number;
|
|
35
69
|
}
|
|
36
70
|
/** One request and the response it got, as written to a fixture file. */
|
|
37
71
|
export interface RecordedExchange {
|
|
@@ -86,6 +120,12 @@ export interface RecordOptions extends FixtureOptions {
|
|
|
86
120
|
redact?: (exchange: RecordedExchange) => RecordedExchange;
|
|
87
121
|
/** Replaces the system clock, for `recordedAt`. */
|
|
88
122
|
now?: () => Date;
|
|
123
|
+
/**
|
|
124
|
+
* Keeps each chunk of a response and when it arrived, so a replay can reproduce a stream's pace
|
|
125
|
+
* as well as its bytes: for testing idle timeouts, cancellation, backpressure, and streaming UIs.
|
|
126
|
+
* Defaults to false.
|
|
127
|
+
*/
|
|
128
|
+
timing?: boolean;
|
|
89
129
|
}
|
|
90
130
|
/** Options for replaying. */
|
|
91
131
|
export interface ReplayOptions extends FixtureOptions {
|
|
@@ -96,6 +136,8 @@ export interface ReplayOptions extends FixtureOptions {
|
|
|
96
136
|
onMissing?: 'throw' | 'live';
|
|
97
137
|
/** The real fetch, for `onMissing: 'live'`. */
|
|
98
138
|
fetch?: typeof globalThis.fetch;
|
|
139
|
+
/** How a stream recorded with `timing` is paced. Defaults to `instant`. */
|
|
140
|
+
pace?: ReplayPace;
|
|
99
141
|
}
|
|
100
142
|
/** A fetch that also lets a test wait for every fixture it has written. */
|
|
101
143
|
export type RecordingFetch = typeof globalThis.fetch & {
|