@axiom-lattice/pg-stores 3.3.4 → 3.3.5
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
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @axiom-lattice/pg-stores@3.3.
|
|
2
|
+
> @axiom-lattice/pg-stores@3.3.5 build /home/runner/work/agentic/agentic/packages/pg-stores
|
|
3
3
|
> tsup src/index.ts --format cjs,esm --dts --sourcemap
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
[34mESM[39m Build start
|
|
11
11
|
[32mCJS[39m [1mdist/index.js [22m[32m443.09 KB[39m
|
|
12
12
|
[32mCJS[39m [1mdist/index.js.map [22m[32m807.74 KB[39m
|
|
13
|
-
[32mCJS[39m ⚡️ Build success in
|
|
13
|
+
[32mCJS[39m ⚡️ Build success in 694ms
|
|
14
14
|
[32mESM[39m [1mdist/index.mjs [22m[32m434.40 KB[39m
|
|
15
15
|
[32mESM[39m [1mdist/index.mjs.map [22m[32m807.39 KB[39m
|
|
16
|
-
[32mESM[39m ⚡️ Build success in
|
|
16
|
+
[32mESM[39m ⚡️ Build success in 695ms
|
|
17
17
|
[34mDTS[39m Build start
|
|
18
|
-
[32mDTS[39m ⚡️ Build success in
|
|
18
|
+
[32mDTS[39m ⚡️ Build success in 10825ms
|
|
19
19
|
[32mDTS[39m [1mdist/index.d.ts [22m[32m93.36 KB[39m
|
|
20
20
|
[32mDTS[39m [1mdist/index.d.mts [22m[32m93.36 KB[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @axiom-lattice/pg-stores
|
|
2
2
|
|
|
3
|
+
## 3.3.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [cb75780]
|
|
8
|
+
- Updated dependencies [c0f75e2]
|
|
9
|
+
- Updated dependencies [48e3ce3]
|
|
10
|
+
- Updated dependencies [3e923d0]
|
|
11
|
+
- Updated dependencies [99bf609]
|
|
12
|
+
- Updated dependencies [92bffbb]
|
|
13
|
+
- Updated dependencies [a19e0aa]
|
|
14
|
+
- @axiom-lattice/core@6.4.1
|
|
15
|
+
|
|
3
16
|
## 3.3.4
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@axiom-lattice/pg-stores",
|
|
3
|
-
"version": "3.3.
|
|
3
|
+
"version": "3.3.5",
|
|
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": "6.4.
|
|
28
|
+
"@axiom-lattice/core": "6.4.1",
|
|
29
29
|
"@axiom-lattice/protocols": "4.8.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
package/src/__tests__/PostgreSQLProjectRoomMessageStore.correlatedInterrupt.integration.test.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { Pool } from "pg";
|
|
3
|
+
import { PostgreSQLProjectRoomMessageStore } from "../stores/PostgreSQLProjectRoomMessageStore";
|
|
4
|
+
import { MigrationManager } from "../migrations/migration";
|
|
5
|
+
import { createProjectRoomTables } from "../migrations/project_room_migration";
|
|
6
|
+
|
|
7
|
+
const databaseUrl = process.env.TEST_DATABASE_URL;
|
|
8
|
+
const describeIfDatabase = databaseUrl ? describe : describe.skip;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Real-PostgreSQL contract for the source-less correlated interrupt write path
|
|
12
|
+
* used by Project Task HITL cards: a bot-authored message with no human source
|
|
13
|
+
* (`reply_to_message_id` NULL) that is idempotent on the caller key.
|
|
14
|
+
*/
|
|
15
|
+
describeIfDatabase("PostgreSQLProjectRoomMessageStore correlated interrupt", () => {
|
|
16
|
+
let pool: Pool;
|
|
17
|
+
let store: PostgreSQLProjectRoomMessageStore;
|
|
18
|
+
const tenantId = `correlated-interrupt-${randomUUID()}`;
|
|
19
|
+
|
|
20
|
+
beforeAll(async () => {
|
|
21
|
+
pool = new Pool({ connectionString: databaseUrl });
|
|
22
|
+
const mm = new MigrationManager(pool);
|
|
23
|
+
mm.register(createProjectRoomTables);
|
|
24
|
+
await mm.migrate();
|
|
25
|
+
store = new PostgreSQLProjectRoomMessageStore({ pool });
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
afterEach(async () => {
|
|
29
|
+
await pool.query("DELETE FROM lattice_project_room_messages WHERE tenant_id = $1", [tenantId]);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
afterAll(async () => {
|
|
33
|
+
await pool.end();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("round-trips a source-less bot interrupt without a reply target", async () => {
|
|
37
|
+
const candidate = {
|
|
38
|
+
id: randomUUID(), tenantId, workspaceId: "w1", projectId: "p1", roomId: "r1",
|
|
39
|
+
author: { type: "bot" as const, membershipId: "m1", assistantId: "a1" },
|
|
40
|
+
content: { type: "text" as const, text: "```clarify\n{}\n```" }, mentions: [],
|
|
41
|
+
source: "agent" as const, sourceId: "interrupt:task:t1:run1", idempotencyKey: "room-interrupt:m1:task:t1:run1",
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const first = await store.createIdempotent(candidate);
|
|
45
|
+
expect(first.author).toEqual({ type: "bot", membershipId: "m1", assistantId: "a1" });
|
|
46
|
+
expect(first.source).toBe("agent");
|
|
47
|
+
expect(first.sourceId).toBe("interrupt:task:t1:run1");
|
|
48
|
+
expect(first.replyToMessageId).toBeUndefined();
|
|
49
|
+
expect(first.idempotencyKey).toBe("room-interrupt:m1:task:t1:run1");
|
|
50
|
+
|
|
51
|
+
const reloaded = await store.findById(tenantId, first.id);
|
|
52
|
+
expect(reloaded).toMatchObject({ id: first.id, source: "agent", sourceId: "interrupt:task:t1:run1" });
|
|
53
|
+
expect(reloaded?.replyToMessageId).toBeUndefined();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("is idempotent on the caller correlation key", async () => {
|
|
57
|
+
const base = {
|
|
58
|
+
tenantId, workspaceId: "w1", projectId: "p1", roomId: "r1",
|
|
59
|
+
author: { type: "bot" as const, membershipId: "m1", assistantId: "a1" },
|
|
60
|
+
content: { type: "text" as const, text: "```clarify\n{}\n```" }, mentions: [],
|
|
61
|
+
source: "agent" as const, sourceId: "interrupt:task:t2:run1", idempotencyKey: "room-interrupt:m1:task:t2:run1",
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const first = await store.createIdempotent({ ...base, id: randomUUID() });
|
|
65
|
+
const second = await store.createIdempotent({ ...base, id: randomUUID() });
|
|
66
|
+
expect(second.id).toBe(first.id);
|
|
67
|
+
|
|
68
|
+
const rows = await pool.query<{ count: string }>(
|
|
69
|
+
"SELECT COUNT(*)::text AS count FROM lattice_project_room_messages WHERE tenant_id = $1 AND idempotency_key = $2",
|
|
70
|
+
[tenantId, base.idempotencyKey],
|
|
71
|
+
);
|
|
72
|
+
expect(rows.rows[0]?.count).toBe("1");
|
|
73
|
+
});
|
|
74
|
+
});
|
|
@@ -139,4 +139,27 @@ describe("PostgreSQLProjectRoomMessageStore", () => {
|
|
|
139
139
|
await store.deleteChatOlderThan({ before: now, limit: 99_999 });
|
|
140
140
|
expect(query.mock.calls[0][1]).toEqual([now, 1_000]);
|
|
141
141
|
});
|
|
142
|
+
|
|
143
|
+
it("maps a source-less bot interrupt with a NULL reply target and caller idempotency", async () => {
|
|
144
|
+
const botAuthor = { type: "bot", membershipId: "m1", assistantId: "a1" };
|
|
145
|
+
query.mockResolvedValueOnce({
|
|
146
|
+
rows: [{
|
|
147
|
+
...row, author: botAuthor, content: { type: "text", text: "```clarify\n{}\n```" },
|
|
148
|
+
mentions: [], reply_to_message_id: null, source: "agent",
|
|
149
|
+
source_id: "interrupt:task:t1:run1", idempotency_key: "room-interrupt:m1:task:t1:run1",
|
|
150
|
+
}],
|
|
151
|
+
});
|
|
152
|
+
const store = new PostgreSQLProjectRoomMessageStore({ pool });
|
|
153
|
+
await store.createIdempotent({
|
|
154
|
+
id: "candidate", tenantId: "tenant-1", workspaceId: "workspace-1", projectId: "project-1", roomId: "room-1",
|
|
155
|
+
author: botAuthor, content: { type: "text", text: "```clarify\n{}\n```" }, mentions: [],
|
|
156
|
+
source: "agent", sourceId: "interrupt:task:t1:run1", idempotencyKey: "room-interrupt:m1:task:t1:run1",
|
|
157
|
+
});
|
|
158
|
+
const params = query.mock.calls[0][1] as unknown[];
|
|
159
|
+
expect(params[8]).toBeNull();
|
|
160
|
+
expect(params[5]).toBe(JSON.stringify(botAuthor));
|
|
161
|
+
expect(params[9]).toBe("agent");
|
|
162
|
+
expect(params[10]).toBe("interrupt:task:t1:run1");
|
|
163
|
+
expect(params[11]).toBe("room-interrupt:m1:task:t1:run1");
|
|
164
|
+
});
|
|
142
165
|
});
|