@axiom-lattice/pg-stores 4.0.0 → 4.0.1
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/.turbo/turbo-build.log +8 -8
- package/CHANGELOG.md +7 -0
- package/dist/index.js +59 -23
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +46 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/PGVectorStoreProvider.ts +16 -5
- package/src/__tests__/AgentRunRetention.migrations.test.ts +3 -1
- package/src/createPgStoreConfig.ts +2 -0
- package/src/migrations/model_provider_migrations.ts +38 -0
- package/src/stores/PostgreSQLModelProviderStore.ts +28 -14
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@axiom-lattice/pg-stores",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.1",
|
|
4
4
|
"description": "PG stores implementation for Axiom Lattice framework",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"@langchain/core": "1.1.30",
|
|
26
26
|
"pg": "^8.16.3",
|
|
27
27
|
"uuid": "^9.0.1",
|
|
28
|
-
"@axiom-lattice/core": "10.0.
|
|
28
|
+
"@axiom-lattice/core": "10.0.1",
|
|
29
29
|
"@axiom-lattice/protocols": "6.0.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
@@ -9,7 +9,11 @@ import { Pool } from "pg";
|
|
|
9
9
|
import { PGVectorStore } from "@langchain/community/vectorstores/pgvector";
|
|
10
10
|
import { Document } from "@langchain/core/documents";
|
|
11
11
|
import { embeddingsLatticeManager } from "@axiom-lattice/core";
|
|
12
|
-
import
|
|
12
|
+
import {
|
|
13
|
+
EMBEDDING_DEFAULT_KEY,
|
|
14
|
+
type VectorStoreProvider,
|
|
15
|
+
type VectorStoreCreateParams,
|
|
16
|
+
} from "@axiom-lattice/protocols";
|
|
13
17
|
import type { DocumentInterface } from "@langchain/core/documents";
|
|
14
18
|
|
|
15
19
|
function safeTableName(name: string): string {
|
|
@@ -31,15 +35,22 @@ export class PGVectorStoreProvider implements VectorStoreProvider {
|
|
|
31
35
|
async create(params: VectorStoreCreateParams): Promise<any> {
|
|
32
36
|
const { tableName, embeddingKey } = params;
|
|
33
37
|
const tenantId = params.tenantId ?? "default";
|
|
38
|
+
const requestedKey = embeddingKey || EMBEDDING_DEFAULT_KEY;
|
|
34
39
|
|
|
35
40
|
// Tenant first, deployment second — the same order every model resolver
|
|
36
|
-
// uses. A
|
|
37
|
-
//
|
|
41
|
+
// uses. A concrete key that misses falls back to the tenant's embedding
|
|
42
|
+
// default, then to the deployment registration.
|
|
38
43
|
const embeddings =
|
|
39
44
|
(await embeddingsLatticeManager.getEmbeddingsClientWithTenant(
|
|
40
45
|
tenantId,
|
|
41
|
-
|
|
46
|
+
requestedKey
|
|
42
47
|
)) ??
|
|
48
|
+
(requestedKey === EMBEDDING_DEFAULT_KEY
|
|
49
|
+
? undefined
|
|
50
|
+
: await embeddingsLatticeManager.getEmbeddingsClientWithTenant(
|
|
51
|
+
tenantId,
|
|
52
|
+
EMBEDDING_DEFAULT_KEY
|
|
53
|
+
)) ??
|
|
43
54
|
(await embeddingsLatticeManager.getEmbeddingsClientWithTenant(
|
|
44
55
|
tenantId,
|
|
45
56
|
"default"
|
|
@@ -48,7 +59,7 @@ export class PGVectorStoreProvider implements VectorStoreProvider {
|
|
|
48
59
|
if (!embeddings) {
|
|
49
60
|
throw new Error(
|
|
50
61
|
`No embedding model "${embeddingKey}" registered for tenant "${tenantId}", ` +
|
|
51
|
-
`and no deployment default. Configure one in the model
|
|
62
|
+
`and no tenant or deployment default. Configure one in the model service panel.`
|
|
52
63
|
);
|
|
53
64
|
}
|
|
54
65
|
|
|
@@ -34,7 +34,9 @@ describe("agent run retention migration", () => {
|
|
|
34
34
|
(name) => name === createAgentRunRetentionMigration.name,
|
|
35
35
|
),
|
|
36
36
|
).toHaveLength(1);
|
|
37
|
-
|
|
37
|
+
// Registration order is not the apply order — the manager sorts by version —
|
|
38
|
+
// so assert presence rather than that this is the last line registered.
|
|
39
|
+
expect(registeredMigrationNames).toContain(
|
|
38
40
|
agentRunProjectTaskRunningIndexMigration.name,
|
|
39
41
|
);
|
|
40
42
|
});
|
|
@@ -109,6 +109,7 @@ import {
|
|
|
109
109
|
addModelProviderModelExtra,
|
|
110
110
|
addModelProviderModelDefault,
|
|
111
111
|
addModelProviderModelKind,
|
|
112
|
+
addModelProviderKindDefault,
|
|
112
113
|
} from "./migrations/model_provider_migrations";
|
|
113
114
|
import { PostgreSQLCapabilityBundleStore } from "./stores/PostgreSQLCapabilityBundleStore";
|
|
114
115
|
import { PostgreSQLProjectRoomStore } from "./stores/PostgreSQLProjectRoomStore";
|
|
@@ -222,6 +223,7 @@ export async function createPgStoreConfig(connectionString: string) {
|
|
|
222
223
|
mm.register(createAgentRunRetentionMigration); // v201
|
|
223
224
|
mm.register(createAgentRunProjectTaskMigration); // v203
|
|
224
225
|
mm.register(agentRunProjectTaskRunningIndexMigration); // v204
|
|
226
|
+
mm.register(addModelProviderKindDefault); // v207
|
|
225
227
|
|
|
226
228
|
await mm.migrate();
|
|
227
229
|
|
|
@@ -256,3 +256,41 @@ export const addModelProviderModelKind: Migration = {
|
|
|
256
256
|
`);
|
|
257
257
|
},
|
|
258
258
|
};
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* One default per tenant **per kind**.
|
|
262
|
+
*
|
|
263
|
+
* v192's index was tenant-wide, so a tenant could have a default chat model
|
|
264
|
+
* *or* a default embedding model, never both. Each kind publishes its own
|
|
265
|
+
* alias key (`default`, `default:embedding`, `default:asr`), so the uniqueness
|
|
266
|
+
* constraint has to be per kind too.
|
|
267
|
+
*
|
|
268
|
+
* Existing rows satisfy the wider index unchanged: before this, at most one
|
|
269
|
+
* row per tenant could be the default.
|
|
270
|
+
*
|
|
271
|
+
* Note the `down` migration can legitimately fail once a tenant has one
|
|
272
|
+
* default per kind — the narrower index cannot represent that state. That is a
|
|
273
|
+
* deliberate one-way step.
|
|
274
|
+
*/
|
|
275
|
+
export const addModelProviderKindDefault: Migration = {
|
|
276
|
+
version: 207,
|
|
277
|
+
name: 'add_model_provider_kind_default',
|
|
278
|
+
up: async (client: PoolClient) => {
|
|
279
|
+
await client.query(`
|
|
280
|
+
DROP INDEX IF EXISTS uk_lattice_model_provider_models_tenant_default
|
|
281
|
+
`);
|
|
282
|
+
await client.query(`
|
|
283
|
+
CREATE UNIQUE INDEX IF NOT EXISTS uk_lattice_model_provider_models_tenant_kind_default
|
|
284
|
+
ON lattice_model_provider_models (tenant_id, kind) WHERE is_default
|
|
285
|
+
`);
|
|
286
|
+
},
|
|
287
|
+
down: async (client: PoolClient) => {
|
|
288
|
+
await client.query(`
|
|
289
|
+
DROP INDEX IF EXISTS uk_lattice_model_provider_models_tenant_kind_default
|
|
290
|
+
`);
|
|
291
|
+
await client.query(`
|
|
292
|
+
CREATE UNIQUE INDEX IF NOT EXISTS uk_lattice_model_provider_models_tenant_default
|
|
293
|
+
ON lattice_model_provider_models (tenant_id) WHERE is_default
|
|
294
|
+
`);
|
|
295
|
+
},
|
|
296
|
+
};
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
addModelProviderModelExtra,
|
|
27
27
|
addModelProviderModelDefault,
|
|
28
28
|
addModelProviderModelKind,
|
|
29
|
+
addModelProviderKindDefault,
|
|
29
30
|
} from '../migrations/model_provider_migrations';
|
|
30
31
|
import { encrypt, safeDecrypt } from '@axiom-lattice/core';
|
|
31
32
|
|
|
@@ -148,6 +149,7 @@ export class PostgreSQLModelProviderStore implements ModelProviderStore {
|
|
|
148
149
|
this.migrationManager.register(addModelProviderModelExtra); // v191
|
|
149
150
|
this.migrationManager.register(addModelProviderModelDefault); // v192
|
|
150
151
|
this.migrationManager.register(addModelProviderModelKind); // v193
|
|
152
|
+
this.migrationManager.register(addModelProviderKindDefault); // v207
|
|
151
153
|
|
|
152
154
|
// Auto-migrate by default
|
|
153
155
|
if (options.autoMigrate !== false) {
|
|
@@ -610,30 +612,42 @@ export class PostgreSQLModelProviderStore implements ModelProviderStore {
|
|
|
610
612
|
(model) => model.kind ?? currentKind.get(model.id) ?? "chat"
|
|
611
613
|
);
|
|
612
614
|
|
|
613
|
-
//
|
|
615
|
+
// Which kinds this write names a default for.
|
|
614
616
|
//
|
|
615
|
-
// The unique index
|
|
617
|
+
// The unique index is per *(tenant, kind)*, while this method writes one
|
|
616
618
|
// provider. Two consequences:
|
|
617
619
|
//
|
|
618
|
-
// 1. A swap (A was
|
|
619
|
-
// mid-statement — PostgreSQL checks a unique index per row, so
|
|
620
|
-
// it fails would depend on which row the batch happened to
|
|
621
|
-
// first. Clearing
|
|
620
|
+
// 1. A swap (A was kind K's default, B now is) would see two true rows of
|
|
621
|
+
// kind K mid-statement — PostgreSQL checks a unique index per row, so
|
|
622
|
+
// whether it fails would depend on which row the batch happened to
|
|
623
|
+
// process first. Clearing that kind before the upsert makes order
|
|
622
624
|
// irrelevant.
|
|
623
|
-
// 2. Once cleared, an omitted flag must resolve to `false
|
|
624
|
-
// keeping it would restore the old default
|
|
625
|
-
|
|
626
|
-
|
|
625
|
+
// 2. Once cleared, an omitted flag must resolve to `false` for the kinds
|
|
626
|
+
// this write names — keeping it would restore the old default
|
|
627
|
+
// alongside the new one. Other kinds keep their stored flag, so a chat
|
|
628
|
+
// write cannot drop the tenant's embedding default.
|
|
629
|
+
const namedDefaultKinds = new Set<ModelKind>();
|
|
630
|
+
rows.forEach((model, index) => {
|
|
631
|
+
if (model.isDefault === true) {
|
|
632
|
+
namedDefaultKinds.add(effectiveKind[index] as ModelKind);
|
|
633
|
+
}
|
|
634
|
+
});
|
|
635
|
+
|
|
636
|
+
for (const kind of namedDefaultKinds) {
|
|
627
637
|
await client.query(
|
|
628
|
-
`UPDATE lattice_model_provider_models
|
|
629
|
-
|
|
638
|
+
`UPDATE lattice_model_provider_models
|
|
639
|
+
SET is_default = FALSE
|
|
640
|
+
WHERE tenant_id = $1 AND kind = $2 AND is_default`,
|
|
641
|
+
[tenantId, kind]
|
|
630
642
|
);
|
|
631
643
|
}
|
|
632
644
|
|
|
633
645
|
const effectiveIsDefault = rows.map(
|
|
634
|
-
(model) =>
|
|
646
|
+
(model, index) =>
|
|
635
647
|
model.isDefault ??
|
|
636
|
-
(
|
|
648
|
+
(namedDefaultKinds.has(effectiveKind[index] as ModelKind)
|
|
649
|
+
? false
|
|
650
|
+
: currentIsDefault.get(model.id)) ??
|
|
637
651
|
false
|
|
638
652
|
);
|
|
639
653
|
|