@axiom-lattice/local-stores 3.1.6 → 3.1.9
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 +10 -10
- package/CHANGELOG.md +29 -0
- package/dist/index.d.mts +40 -2
- package/dist/index.d.ts +40 -2
- package/dist/index.js +303 -36
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +301 -36
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/LocalA2AApiKeyStore.test.ts +9 -0
- package/src/__tests__/LocalMcpServerConfigStore.test.ts +77 -0
- package/src/__tests__/LocalOpenAuditStore.test.ts +116 -0
- package/src/__tests__/LocalProjectRoomReadStateStore.test.ts +101 -0
- package/src/__tests__/LocalProjectRoomStores.test.ts +61 -0
- package/src/createLocalStoreConfig.ts +4 -0
- package/src/index.ts +3 -0
- package/src/stores/LocalA2AApiKeyStore.ts +41 -3
- package/src/stores/LocalMcpServerConfigStore.ts +22 -0
- package/src/stores/LocalOpenAuditStore.ts +110 -0
- package/src/stores/LocalProjectRoomMessageStore.ts +35 -1
- package/src/stores/LocalProjectRoomReadStateStore.ts +50 -0
- package/src/stores/project-room-schema.ts +30 -0
package/dist/index.js
CHANGED
|
@@ -44,9 +44,11 @@ __export(index_exports, {
|
|
|
44
44
|
LocalEvalStore: () => LocalEvalStore,
|
|
45
45
|
LocalMcpServerConfigStore: () => LocalMcpServerConfigStore,
|
|
46
46
|
LocalMetricsServerConfigStore: () => LocalMetricsServerConfigStore,
|
|
47
|
+
LocalOpenAuditStore: () => LocalOpenAuditStore,
|
|
47
48
|
LocalProjectBotMembershipStore: () => LocalProjectBotMembershipStore,
|
|
48
49
|
LocalProjectMembershipStore: () => LocalProjectMembershipStore,
|
|
49
50
|
LocalProjectRoomMessageStore: () => LocalProjectRoomMessageStore,
|
|
51
|
+
LocalProjectRoomReadStateStore: () => LocalProjectRoomReadStateStore,
|
|
50
52
|
LocalProjectRoomStore: () => LocalProjectRoomStore,
|
|
51
53
|
LocalProjectStore: () => LocalProjectStore,
|
|
52
54
|
LocalScheduleStorage: () => LocalScheduleStorage,
|
|
@@ -886,12 +888,20 @@ CREATE UNIQUE INDEX IF NOT EXISTS uq_lt_project_room_messages_idempotency
|
|
|
886
888
|
ON lt_project_room_messages (tenant_id, room_id, idempotency_key) WHERE idempotency_key IS NOT NULL;
|
|
887
889
|
CREATE INDEX IF NOT EXISTS idx_lt_project_room_messages_room_created
|
|
888
890
|
ON lt_project_room_messages (tenant_id, room_id, created_at DESC, id DESC);
|
|
891
|
+
CREATE TABLE IF NOT EXISTS lt_project_room_read_states (
|
|
892
|
+
tenant_id TEXT NOT NULL, room_id TEXT NOT NULL, user_id TEXT NOT NULL,
|
|
893
|
+
last_read_at TEXT NOT NULL, updated_at TEXT NOT NULL,
|
|
894
|
+
PRIMARY KEY (tenant_id, room_id, user_id)
|
|
895
|
+
);
|
|
896
|
+
CREATE INDEX IF NOT EXISTS idx_lt_project_room_read_states_user
|
|
897
|
+
ON lt_project_room_read_states (tenant_id, user_id);
|
|
889
898
|
`;
|
|
890
899
|
var tableColumns = {
|
|
891
900
|
lt_project_rooms: ["id", "tenant_id", "workspace_id", "project_id", "type", "name", "created_at", "updated_at"],
|
|
892
901
|
lt_project_memberships: ["id", "tenant_id", "project_id", "user_id", "role", "status", "joined_at", "updated_at"],
|
|
893
902
|
lt_project_bot_memberships: ["id", "tenant_id", "workspace_id", "project_id", "room_id", "assistant_id", "role", "title", "responsibility", "mention_name", "status", "room_thread_id", "joined_at", "updated_at"],
|
|
894
|
-
lt_project_room_messages: ["id", "tenant_id", "workspace_id", "project_id", "room_id", "author", "content", "mentions", "reply_to_message_id", "source", "source_id", "idempotency_key", "created_at"]
|
|
903
|
+
lt_project_room_messages: ["id", "tenant_id", "workspace_id", "project_id", "room_id", "author", "content", "mentions", "reply_to_message_id", "source", "source_id", "idempotency_key", "created_at"],
|
|
904
|
+
lt_project_room_read_states: ["tenant_id", "room_id", "user_id", "last_read_at", "updated_at"]
|
|
895
905
|
};
|
|
896
906
|
var indexes = {
|
|
897
907
|
idx_lt_project_memberships_project: { table: "lt_project_memberships", columns: ["tenant_id", "project_id"], unique: false, partial: false },
|
|
@@ -900,13 +910,15 @@ var indexes = {
|
|
|
900
910
|
idx_lt_project_bot_memberships_project: { table: "lt_project_bot_memberships", columns: ["tenant_id", "project_id"], unique: false, partial: false },
|
|
901
911
|
idx_lt_project_bot_memberships_room: { table: "lt_project_bot_memberships", columns: ["tenant_id", "room_id"], unique: false, partial: false },
|
|
902
912
|
uq_lt_project_room_messages_idempotency: { table: "lt_project_room_messages", columns: ["tenant_id", "room_id", "idempotency_key"], unique: true, partial: true, sql: ["idempotency_key is not null"] },
|
|
903
|
-
idx_lt_project_room_messages_room_created: { table: "lt_project_room_messages", columns: ["tenant_id", "room_id", "created_at", "id"], unique: false, partial: false, sql: ["created_at desc", "id desc"] }
|
|
913
|
+
idx_lt_project_room_messages_room_created: { table: "lt_project_room_messages", columns: ["tenant_id", "room_id", "created_at", "id"], unique: false, partial: false, sql: ["created_at desc", "id desc"] },
|
|
914
|
+
idx_lt_project_room_read_states_user: { table: "lt_project_room_read_states", columns: ["tenant_id", "user_id"], unique: false, partial: false }
|
|
904
915
|
};
|
|
905
916
|
var uniqueConstraints = {
|
|
906
917
|
lt_project_rooms: [["tenant_id", "id"], ["tenant_id", "project_id", "type"]],
|
|
907
918
|
lt_project_memberships: [["tenant_id", "id"], ["tenant_id", "project_id", "user_id"]],
|
|
908
919
|
lt_project_bot_memberships: [["tenant_id", "id"], ["tenant_id", "project_id", "assistant_id"]],
|
|
909
|
-
lt_project_room_messages: [["tenant_id", "id"]]
|
|
920
|
+
lt_project_room_messages: [["tenant_id", "id"]],
|
|
921
|
+
lt_project_room_read_states: [["tenant_id", "room_id", "user_id"]]
|
|
910
922
|
};
|
|
911
923
|
var checkConstraints = {
|
|
912
924
|
lt_project_rooms: [{ name: "type", fragment: "type='main'" }],
|
|
@@ -918,7 +930,8 @@ var checkConstraints = {
|
|
|
918
930
|
{ name: "role", fragment: "role in ('coordinator','specialist')" },
|
|
919
931
|
{ name: "status", fragment: "status in ('active','paused','removed')" }
|
|
920
932
|
],
|
|
921
|
-
lt_project_room_messages: [{ name: "source", fragment: "source in ('user','agent','task','routine','system')" }]
|
|
933
|
+
lt_project_room_messages: [{ name: "source", fragment: "source in ('user','agent','task','routine','system')" }],
|
|
934
|
+
lt_project_room_read_states: []
|
|
922
935
|
};
|
|
923
936
|
function rows(db, sql) {
|
|
924
937
|
const result = db.getRawDb().exec(sql);
|
|
@@ -990,10 +1003,10 @@ function validateProjectRoomSchema(db) {
|
|
|
990
1003
|
}
|
|
991
1004
|
for (const [name, expected] of Object.entries(indexes)) {
|
|
992
1005
|
const listed = rows(db, `PRAGMA index_list(${expected.table})`).find((index) => index.name === name);
|
|
993
|
-
const
|
|
1006
|
+
const columns6 = rows(db, `PRAGMA index_info(${name})`).map((column) => column.name);
|
|
994
1007
|
const definition = rows(db, `SELECT sql FROM sqlite_master WHERE type = 'index' AND name = '${name}'`)[0]?.sql;
|
|
995
1008
|
const normalized = typeof definition === "string" ? definition.toLowerCase().replace(/\s+/g, " ") : "";
|
|
996
|
-
if (!listed || listed.unique !== Number(expected.unique) || listed.partial !== Number(expected.partial) ||
|
|
1009
|
+
if (!listed || listed.unique !== Number(expected.unique) || listed.partial !== Number(expected.partial) || columns6.join(",") !== expected.columns.join(",") || expected.sql?.some((fragment) => !normalized.includes(fragment))) {
|
|
997
1010
|
throw new Error(`Invalid project room schema: index '${name}' is incompatible`);
|
|
998
1011
|
}
|
|
999
1012
|
}
|
|
@@ -1006,6 +1019,30 @@ function ensureProjectRoomSchema(db) {
|
|
|
1006
1019
|
const applied = hasMigrationTable ? rows(db, `SELECT name, version FROM lattice_schema_migrations WHERE store_name = 'project_room' AND name = '${migrationName}'`)[0] : void 0;
|
|
1007
1020
|
if (applied) {
|
|
1008
1021
|
if (applied.version !== 1) throw new Error(`Invalid project room schema migration version: ${String(applied.version)}`);
|
|
1022
|
+
const hasReadStates = rows(db, "SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'lt_project_room_read_states'").length > 0;
|
|
1023
|
+
if (!hasReadStates) {
|
|
1024
|
+
raw.exec("BEGIN IMMEDIATE");
|
|
1025
|
+
try {
|
|
1026
|
+
raw.exec(`CREATE TABLE IF NOT EXISTS lt_project_room_read_states (
|
|
1027
|
+
tenant_id TEXT NOT NULL, room_id TEXT NOT NULL, user_id TEXT NOT NULL,
|
|
1028
|
+
last_read_at TEXT NOT NULL, updated_at TEXT NOT NULL,
|
|
1029
|
+
PRIMARY KEY (tenant_id, room_id, user_id)
|
|
1030
|
+
); CREATE INDEX IF NOT EXISTS idx_lt_project_room_read_states_user
|
|
1031
|
+
ON lt_project_room_read_states (tenant_id, user_id);`);
|
|
1032
|
+
raw.run(
|
|
1033
|
+
"INSERT INTO lattice_schema_migrations (store_name, name, version, applied_at) VALUES (?, ?, ?, ?)",
|
|
1034
|
+
["project_room", "create_project_room_read_states", 2, (/* @__PURE__ */ new Date()).toISOString()]
|
|
1035
|
+
);
|
|
1036
|
+
raw.exec("COMMIT");
|
|
1037
|
+
db.save();
|
|
1038
|
+
} catch (error) {
|
|
1039
|
+
try {
|
|
1040
|
+
raw.exec("ROLLBACK");
|
|
1041
|
+
} catch {
|
|
1042
|
+
}
|
|
1043
|
+
throw error;
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1009
1046
|
validateProjectRoomSchema(db);
|
|
1010
1047
|
marked[schemaMarker] = true;
|
|
1011
1048
|
return;
|
|
@@ -1424,6 +1461,22 @@ function mapRow4(row) {
|
|
|
1424
1461
|
createdAt
|
|
1425
1462
|
};
|
|
1426
1463
|
}
|
|
1464
|
+
function mapRowsTolerant(rows2, scope) {
|
|
1465
|
+
const messages = [];
|
|
1466
|
+
for (const row of rows2) {
|
|
1467
|
+
try {
|
|
1468
|
+
messages.push(mapRow4(row));
|
|
1469
|
+
} catch (error) {
|
|
1470
|
+
console.warn("[ProjectRoomMessageStore] Skipping invalid message row", {
|
|
1471
|
+
tenantId: scope.tenantId,
|
|
1472
|
+
roomId: scope.roomId,
|
|
1473
|
+
rowId: typeof row.id === "string" ? row.id : void 0,
|
|
1474
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
1475
|
+
});
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
return messages;
|
|
1479
|
+
}
|
|
1427
1480
|
var LocalProjectRoomMessageStore = class {
|
|
1428
1481
|
constructor(db) {
|
|
1429
1482
|
this.db = db;
|
|
@@ -1439,12 +1492,24 @@ var LocalProjectRoomMessageStore = class {
|
|
|
1439
1492
|
if (input.before && !validDate(input.before.createdAt)) throw new RangeError("Project room message cursor date is invalid");
|
|
1440
1493
|
const limit = Math.min(100, Math.max(1, Math.trunc(Number.isFinite(input.limit) ? input.limit : 1)));
|
|
1441
1494
|
const rows2 = input.before ? this.db.prepare(`SELECT ${columns4} FROM lt_project_room_messages WHERE tenant_id = ? AND room_id = ? AND (created_at < ? OR (created_at = ? AND id < ?)) ORDER BY created_at DESC, id DESC LIMIT ?`).all(input.tenantId, input.roomId, input.before.createdAt.toISOString(), input.before.createdAt.toISOString(), input.before.id, limit) : this.db.prepare(`SELECT ${columns4} FROM lt_project_room_messages WHERE tenant_id = ? AND room_id = ? ORDER BY created_at DESC, id DESC LIMIT ?`).all(input.tenantId, input.roomId, limit);
|
|
1442
|
-
return rows2.
|
|
1495
|
+
return mapRowsTolerant(rows2, { tenantId: input.tenantId, roomId: input.roomId });
|
|
1443
1496
|
}
|
|
1444
1497
|
async findById(tenantId, id) {
|
|
1445
1498
|
const row = this.byId(tenantId, id);
|
|
1446
1499
|
return row ? mapRow4(row) : null;
|
|
1447
1500
|
}
|
|
1501
|
+
async countAfter(input) {
|
|
1502
|
+
if (!validDate(input.after)) throw new RangeError("Project room message count horizon date is invalid");
|
|
1503
|
+
const rows2 = this.db.prepare(
|
|
1504
|
+
`SELECT author FROM lt_project_room_messages
|
|
1505
|
+
WHERE tenant_id = ? AND room_id = ? AND created_at > ?`
|
|
1506
|
+
).all(input.tenantId, input.roomId, input.after.toISOString());
|
|
1507
|
+
return rows2.filter((row) => {
|
|
1508
|
+
if (input.excludeAuthorUserId === void 0) return true;
|
|
1509
|
+
const parsed = parseJson(row.author);
|
|
1510
|
+
return !(record(parsed) && parsed.type === "human" && parsed.userId === input.excludeAuthorUserId);
|
|
1511
|
+
}).length;
|
|
1512
|
+
}
|
|
1448
1513
|
insert(input, idempotent) {
|
|
1449
1514
|
return transaction(this.db, () => {
|
|
1450
1515
|
if (idempotent && input.idempotencyKey) {
|
|
@@ -1475,6 +1540,50 @@ var LocalProjectRoomMessageStore = class {
|
|
|
1475
1540
|
}
|
|
1476
1541
|
};
|
|
1477
1542
|
|
|
1543
|
+
// src/stores/LocalProjectRoomReadStateStore.ts
|
|
1544
|
+
var columns5 = "tenant_id, room_id, user_id, last_read_at, updated_at";
|
|
1545
|
+
function mapRow5(row) {
|
|
1546
|
+
const lastReadAt = new Date(row.last_read_at);
|
|
1547
|
+
const updatedAt = new Date(row.updated_at);
|
|
1548
|
+
if (Number.isNaN(lastReadAt.getTime()) || Number.isNaN(updatedAt.getTime())) throw new Error("Invalid project room read state row");
|
|
1549
|
+
return { tenantId: row.tenant_id, roomId: row.room_id, userId: row.user_id, lastReadAt, updatedAt };
|
|
1550
|
+
}
|
|
1551
|
+
var LocalProjectRoomReadStateStore = class {
|
|
1552
|
+
/** Creates a store over a managed local database wrapper. */
|
|
1553
|
+
constructor(db) {
|
|
1554
|
+
this.db = db;
|
|
1555
|
+
ensureProjectRoomSchema(db);
|
|
1556
|
+
}
|
|
1557
|
+
/** Returns the user's read marker for a room, or null when never reported. */
|
|
1558
|
+
async get(tenantId, roomId, userId) {
|
|
1559
|
+
const row = this.byKey(tenantId, roomId, userId);
|
|
1560
|
+
return row ? mapRow5(row) : null;
|
|
1561
|
+
}
|
|
1562
|
+
/** Upserts the marker monotonically (an older report never regresses the horizon). */
|
|
1563
|
+
async markRead(input) {
|
|
1564
|
+
if (!validDate(input.lastReadAt)) throw new RangeError("Project room read state lastReadAt is invalid");
|
|
1565
|
+
return transaction(this.db, () => {
|
|
1566
|
+
const existing = this.byKey(input.tenantId, input.roomId, input.userId);
|
|
1567
|
+
const lastReadAt = existing !== void 0 && new Date(existing.last_read_at).getTime() > input.lastReadAt.getTime() ? new Date(existing.last_read_at) : input.lastReadAt;
|
|
1568
|
+
write(
|
|
1569
|
+
this.db,
|
|
1570
|
+
`INSERT INTO lt_project_room_read_states (${columns5})
|
|
1571
|
+
VALUES (?, ?, ?, ?, ?)
|
|
1572
|
+
ON CONFLICT (tenant_id, room_id, user_id) DO UPDATE
|
|
1573
|
+
SET last_read_at = excluded.last_read_at, updated_at = excluded.updated_at`,
|
|
1574
|
+
[input.tenantId, input.roomId, input.userId, lastReadAt.toISOString(), timestamp()]
|
|
1575
|
+
);
|
|
1576
|
+
const row = this.byKey(input.tenantId, input.roomId, input.userId);
|
|
1577
|
+
return mapRow5(row);
|
|
1578
|
+
});
|
|
1579
|
+
}
|
|
1580
|
+
byKey(tenantId, roomId, userId) {
|
|
1581
|
+
return this.db.prepare(
|
|
1582
|
+
`SELECT ${columns5} FROM lt_project_room_read_states WHERE tenant_id = ? AND room_id = ? AND user_id = ?`
|
|
1583
|
+
).get(tenantId, roomId, userId);
|
|
1584
|
+
}
|
|
1585
|
+
};
|
|
1586
|
+
|
|
1478
1587
|
// src/stores/LocalUserStore.ts
|
|
1479
1588
|
var DDL5 = `
|
|
1480
1589
|
CREATE TABLE IF NOT EXISTS lt_users (
|
|
@@ -2302,6 +2411,18 @@ function mapRowToEntry3(row) {
|
|
|
2302
2411
|
throw new Error("Failed to decrypt MCP server configuration");
|
|
2303
2412
|
}
|
|
2304
2413
|
}
|
|
2414
|
+
if (config.headers && row.is_env_encrypted) {
|
|
2415
|
+
try {
|
|
2416
|
+
const decryptedHeaders = {};
|
|
2417
|
+
for (const [key, value] of Object.entries(config.headers)) {
|
|
2418
|
+
decryptedHeaders[key] = (0, import_core2.decrypt)(value);
|
|
2419
|
+
}
|
|
2420
|
+
config.headers = decryptedHeaders;
|
|
2421
|
+
} catch (error) {
|
|
2422
|
+
console.error("Failed to decrypt MCP server headers:", error);
|
|
2423
|
+
throw new Error("Failed to decrypt MCP server configuration");
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2305
2426
|
return {
|
|
2306
2427
|
id: row.id,
|
|
2307
2428
|
tenantId: row.tenant_id,
|
|
@@ -2327,6 +2448,14 @@ function encryptEnvInConfig(config) {
|
|
|
2327
2448
|
configCopy.env = encryptedEnv;
|
|
2328
2449
|
isEnvEncrypted = true;
|
|
2329
2450
|
}
|
|
2451
|
+
if (configCopy.headers && Object.keys(configCopy.headers).length > 0) {
|
|
2452
|
+
const encryptedHeaders = {};
|
|
2453
|
+
for (const [key, value] of Object.entries(configCopy.headers)) {
|
|
2454
|
+
encryptedHeaders[key] = (0, import_core2.encrypt)(value);
|
|
2455
|
+
}
|
|
2456
|
+
configCopy.headers = encryptedHeaders;
|
|
2457
|
+
isEnvEncrypted = true;
|
|
2458
|
+
}
|
|
2330
2459
|
return { config: configCopy, isEnvEncrypted };
|
|
2331
2460
|
}
|
|
2332
2461
|
|
|
@@ -3636,7 +3765,7 @@ var LocalChannelInstallationStore = class {
|
|
|
3636
3765
|
const row = this.db.prepare(
|
|
3637
3766
|
`SELECT * FROM lt_channel_installations WHERE id = ?`
|
|
3638
3767
|
).get(installationId);
|
|
3639
|
-
return row ?
|
|
3768
|
+
return row ? mapRow6(row) : null;
|
|
3640
3769
|
}
|
|
3641
3770
|
async getInstallationsByTenant(tenantId, channel) {
|
|
3642
3771
|
let rows2;
|
|
@@ -3649,7 +3778,7 @@ var LocalChannelInstallationStore = class {
|
|
|
3649
3778
|
`SELECT * FROM lt_channel_installations WHERE tenant_id = ? ORDER BY created_at DESC`
|
|
3650
3779
|
).all(tenantId);
|
|
3651
3780
|
}
|
|
3652
|
-
return rows2.map(
|
|
3781
|
+
return rows2.map(mapRow6);
|
|
3653
3782
|
}
|
|
3654
3783
|
async getAllInstallations(channel) {
|
|
3655
3784
|
let rows2;
|
|
@@ -3662,7 +3791,7 @@ var LocalChannelInstallationStore = class {
|
|
|
3662
3791
|
`SELECT * FROM lt_channel_installations ORDER BY created_at DESC`
|
|
3663
3792
|
).all();
|
|
3664
3793
|
}
|
|
3665
|
-
return rows2.map(
|
|
3794
|
+
return rows2.map(mapRow6);
|
|
3666
3795
|
}
|
|
3667
3796
|
async createInstallation(tenantId, installationId, data) {
|
|
3668
3797
|
const now = nowISO();
|
|
@@ -3738,7 +3867,7 @@ var LocalChannelInstallationStore = class {
|
|
|
3738
3867
|
return result.changes > 0;
|
|
3739
3868
|
}
|
|
3740
3869
|
};
|
|
3741
|
-
function
|
|
3870
|
+
function mapRow6(row) {
|
|
3742
3871
|
return {
|
|
3743
3872
|
id: row.id,
|
|
3744
3873
|
tenantId: row.tenant_id,
|
|
@@ -3763,6 +3892,7 @@ CREATE TABLE IF NOT EXISTS lt_a2a_api_keys (
|
|
|
3763
3892
|
tenant_id TEXT NOT NULL,
|
|
3764
3893
|
project_id TEXT,
|
|
3765
3894
|
assistant_ids TEXT,
|
|
3895
|
+
grants TEXT,
|
|
3766
3896
|
label TEXT,
|
|
3767
3897
|
enabled INTEGER NOT NULL DEFAULT 1,
|
|
3768
3898
|
created_at TEXT NOT NULL,
|
|
@@ -3772,6 +3902,15 @@ CREATE TABLE IF NOT EXISTS lt_a2a_api_keys (
|
|
|
3772
3902
|
function generateApiKey() {
|
|
3773
3903
|
return `a2a_${(0, import_crypto3.randomUUID)().replace(/-/g, "")}`;
|
|
3774
3904
|
}
|
|
3905
|
+
function parseGrants(raw) {
|
|
3906
|
+
if (!raw) return void 0;
|
|
3907
|
+
try {
|
|
3908
|
+
const parsed = JSON.parse(raw);
|
|
3909
|
+
return Array.isArray(parsed) ? parsed : void 0;
|
|
3910
|
+
} catch {
|
|
3911
|
+
return void 0;
|
|
3912
|
+
}
|
|
3913
|
+
}
|
|
3775
3914
|
function parseAssistantIds(raw) {
|
|
3776
3915
|
if (!raw) return void 0;
|
|
3777
3916
|
try {
|
|
@@ -3786,6 +3925,7 @@ var LocalA2AApiKeyStore = class {
|
|
|
3786
3925
|
this.db = db;
|
|
3787
3926
|
ensureTable(db, DDL16);
|
|
3788
3927
|
this.ensureColumn("lt_a2a_api_keys", "assistant_ids", "assistant_ids TEXT");
|
|
3928
|
+
this.ensureColumn("lt_a2a_api_keys", "grants", "grants TEXT");
|
|
3789
3929
|
this.repairManagementIds();
|
|
3790
3930
|
}
|
|
3791
3931
|
/** Add a column if it does not exist (SQLite version compatible). */
|
|
@@ -3846,9 +3986,9 @@ var LocalA2AApiKeyStore = class {
|
|
|
3846
3986
|
const key = generateApiKey();
|
|
3847
3987
|
const now = nowISO();
|
|
3848
3988
|
this.db.prepare(
|
|
3849
|
-
`INSERT INTO lt_a2a_api_keys (id, key_value, tenant_id, project_id, assistant_ids, label, created_at, updated_at)
|
|
3850
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`
|
|
3851
|
-
).run(id, (0, import_core3.encrypt)(key), input.tenantId, input.projectId, input.assistantIds ? JSON.stringify(input.assistantIds) : null, input.label || null, now, now);
|
|
3989
|
+
`INSERT INTO lt_a2a_api_keys (id, key_value, tenant_id, project_id, assistant_ids, grants, label, created_at, updated_at)
|
|
3990
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
3991
|
+
).run(id, (0, import_core3.encrypt)(key), input.tenantId, input.projectId, input.assistantIds ? JSON.stringify(input.assistantIds) : null, input.grants ? JSON.stringify(input.grants) : null, input.label || null, now, now);
|
|
3852
3992
|
const record2 = {
|
|
3853
3993
|
id,
|
|
3854
3994
|
key,
|
|
@@ -3880,6 +4020,38 @@ var LocalA2AApiKeyStore = class {
|
|
|
3880
4020
|
if (!row) throw new Error(`A2A API key not found: ${id}`);
|
|
3881
4021
|
return mapRowToRecord(row);
|
|
3882
4022
|
}
|
|
4023
|
+
async update(id, input) {
|
|
4024
|
+
const sets = [];
|
|
4025
|
+
const values = [];
|
|
4026
|
+
if (input.label !== void 0) {
|
|
4027
|
+
sets.push("label = ?");
|
|
4028
|
+
values.push(input.label || null);
|
|
4029
|
+
}
|
|
4030
|
+
if (input.projectId !== void 0) {
|
|
4031
|
+
sets.push("project_id = ?");
|
|
4032
|
+
values.push(input.projectId);
|
|
4033
|
+
}
|
|
4034
|
+
if (input.assistantIds !== void 0) {
|
|
4035
|
+
sets.push("assistant_ids = ?");
|
|
4036
|
+
values.push(input.assistantIds ? JSON.stringify(input.assistantIds) : null);
|
|
4037
|
+
}
|
|
4038
|
+
if (input.grants !== void 0) {
|
|
4039
|
+
sets.push("grants = ?");
|
|
4040
|
+
values.push(input.grants ? JSON.stringify(input.grants) : null);
|
|
4041
|
+
}
|
|
4042
|
+
if (sets.length === 0) {
|
|
4043
|
+
const row2 = this.db.prepare("SELECT * FROM lt_a2a_api_keys WHERE id = ?").get(id);
|
|
4044
|
+
if (!row2) throw new Error(`A2A API key not found: ${id}`);
|
|
4045
|
+
return mapRowToRecord(row2);
|
|
4046
|
+
}
|
|
4047
|
+
sets.push("updated_at = ?");
|
|
4048
|
+
values.push(nowISO());
|
|
4049
|
+
values.push(id);
|
|
4050
|
+
this.db.prepare(`UPDATE lt_a2a_api_keys SET ${sets.join(", ")} WHERE id = ?`).run(...values);
|
|
4051
|
+
const row = this.db.prepare("SELECT * FROM lt_a2a_api_keys WHERE id = ?").get(id);
|
|
4052
|
+
if (!row) throw new Error(`A2A API key not found: ${id}`);
|
|
4053
|
+
return mapRowToRecord(row);
|
|
4054
|
+
}
|
|
3883
4055
|
async rotate(id) {
|
|
3884
4056
|
const key = generateApiKey();
|
|
3885
4057
|
const now = nowISO();
|
|
@@ -3928,6 +4100,7 @@ function mapRowToRecord(row) {
|
|
|
3928
4100
|
tenantId: row.tenant_id,
|
|
3929
4101
|
projectId: row.project_id,
|
|
3930
4102
|
assistantIds: parseAssistantIds(row.assistant_ids),
|
|
4103
|
+
grants: parseGrants(row.grants),
|
|
3931
4104
|
label: row.label || void 0,
|
|
3932
4105
|
enabled: row.enabled === 1,
|
|
3933
4106
|
createdAt: parseISO(row.created_at),
|
|
@@ -3935,10 +4108,100 @@ function mapRowToRecord(row) {
|
|
|
3935
4108
|
};
|
|
3936
4109
|
}
|
|
3937
4110
|
|
|
3938
|
-
// src/stores/
|
|
3939
|
-
var import_protocols4 = require("@axiom-lattice/protocols");
|
|
4111
|
+
// src/stores/LocalOpenAuditStore.ts
|
|
3940
4112
|
var import_crypto4 = require("crypto");
|
|
3941
4113
|
var DDL17 = `
|
|
4114
|
+
CREATE TABLE IF NOT EXISTS lt_open_audit (
|
|
4115
|
+
id TEXT PRIMARY KEY,
|
|
4116
|
+
tenant_id TEXT NOT NULL,
|
|
4117
|
+
credential_id TEXT NOT NULL,
|
|
4118
|
+
credential_kind TEXT NOT NULL,
|
|
4119
|
+
project_id TEXT NOT NULL,
|
|
4120
|
+
domain TEXT NOT NULL,
|
|
4121
|
+
action TEXT NOT NULL,
|
|
4122
|
+
args TEXT,
|
|
4123
|
+
status TEXT NOT NULL,
|
|
4124
|
+
error_code TEXT,
|
|
4125
|
+
duration_ms INTEGER NOT NULL,
|
|
4126
|
+
created_at TEXT NOT NULL
|
|
4127
|
+
);
|
|
4128
|
+
`;
|
|
4129
|
+
var LocalOpenAuditStore = class {
|
|
4130
|
+
constructor(db) {
|
|
4131
|
+
this.db = db;
|
|
4132
|
+
ensureTable(db, DDL17);
|
|
4133
|
+
}
|
|
4134
|
+
async query(params) {
|
|
4135
|
+
const clauses = ["tenant_id = ?"];
|
|
4136
|
+
const values = [params.tenantId];
|
|
4137
|
+
if (params.credentialId) {
|
|
4138
|
+
clauses.push("credential_id = ?");
|
|
4139
|
+
values.push(params.credentialId);
|
|
4140
|
+
}
|
|
4141
|
+
if (params.domain) {
|
|
4142
|
+
clauses.push("domain = ?");
|
|
4143
|
+
values.push(params.domain);
|
|
4144
|
+
}
|
|
4145
|
+
if (params.status) {
|
|
4146
|
+
clauses.push("status = ?");
|
|
4147
|
+
values.push(params.status);
|
|
4148
|
+
}
|
|
4149
|
+
if (params.from) {
|
|
4150
|
+
clauses.push("created_at >= ?");
|
|
4151
|
+
values.push(params.from);
|
|
4152
|
+
}
|
|
4153
|
+
if (params.to) {
|
|
4154
|
+
clauses.push("created_at < ?");
|
|
4155
|
+
values.push(params.to);
|
|
4156
|
+
}
|
|
4157
|
+
const limit = params.limit ?? 100;
|
|
4158
|
+
const offset = params.offset ?? 0;
|
|
4159
|
+
values.push(limit, offset);
|
|
4160
|
+
const rows2 = this.db.prepare(
|
|
4161
|
+
`SELECT * FROM lt_open_audit WHERE ${clauses.join(" AND ")}
|
|
4162
|
+
ORDER BY created_at DESC LIMIT ? OFFSET ?`
|
|
4163
|
+
).all(...values);
|
|
4164
|
+
return rows2.map((row) => ({
|
|
4165
|
+
id: row.id,
|
|
4166
|
+
tenantId: row.tenant_id,
|
|
4167
|
+
credentialId: row.credential_id,
|
|
4168
|
+
credentialKind: row.credential_kind,
|
|
4169
|
+
projectId: row.project_id,
|
|
4170
|
+
domain: row.domain,
|
|
4171
|
+
action: row.action,
|
|
4172
|
+
args: row.args ? JSON.parse(row.args) : void 0,
|
|
4173
|
+
status: row.status,
|
|
4174
|
+
errorCode: row.error_code ?? void 0,
|
|
4175
|
+
durationMs: row.duration_ms,
|
|
4176
|
+
createdAt: parseISO(row.created_at)
|
|
4177
|
+
}));
|
|
4178
|
+
}
|
|
4179
|
+
async append(record2) {
|
|
4180
|
+
this.db.prepare(
|
|
4181
|
+
`INSERT INTO lt_open_audit
|
|
4182
|
+
(id, tenant_id, credential_id, credential_kind, project_id, domain, action, args, status, error_code, duration_ms, created_at)
|
|
4183
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
4184
|
+
).run(
|
|
4185
|
+
(0, import_crypto4.randomUUID)(),
|
|
4186
|
+
record2.tenantId,
|
|
4187
|
+
record2.credentialId,
|
|
4188
|
+
record2.credentialKind,
|
|
4189
|
+
record2.projectId,
|
|
4190
|
+
record2.domain,
|
|
4191
|
+
record2.action,
|
|
4192
|
+
record2.args === void 0 ? null : JSON.stringify(record2.args),
|
|
4193
|
+
record2.status,
|
|
4194
|
+
record2.errorCode ?? null,
|
|
4195
|
+
Math.max(0, Math.round(record2.durationMs)),
|
|
4196
|
+
nowISO()
|
|
4197
|
+
);
|
|
4198
|
+
}
|
|
4199
|
+
};
|
|
4200
|
+
|
|
4201
|
+
// src/stores/LocalThreadMessageQueueStore.ts
|
|
4202
|
+
var import_protocols4 = require("@axiom-lattice/protocols");
|
|
4203
|
+
var import_crypto5 = require("crypto");
|
|
4204
|
+
var DDL18 = `
|
|
3942
4205
|
CREATE TABLE IF NOT EXISTS lt_thread_message_queue (
|
|
3943
4206
|
id TEXT PRIMARY KEY,
|
|
3944
4207
|
thread_id TEXT NOT NULL,
|
|
@@ -3964,9 +4227,9 @@ var LocalThreadMessageQueueStore = class {
|
|
|
3964
4227
|
constructor(db) {
|
|
3965
4228
|
this.capacityTail = Promise.resolve();
|
|
3966
4229
|
this.db = db;
|
|
3967
|
-
ensureTable(db,
|
|
3968
|
-
const
|
|
3969
|
-
const names = new Set(
|
|
4230
|
+
ensureTable(db, DDL18);
|
|
4231
|
+
const columns6 = db.prepare("PRAGMA table_info(lt_thread_message_queue)").all();
|
|
4232
|
+
const names = new Set(columns6.map(({ name }) => name));
|
|
3970
4233
|
if (!names.has("trusted_run_context")) {
|
|
3971
4234
|
db.run("ALTER TABLE lt_thread_message_queue ADD COLUMN trusted_run_context TEXT");
|
|
3972
4235
|
}
|
|
@@ -3977,7 +4240,7 @@ var LocalThreadMessageQueueStore = class {
|
|
|
3977
4240
|
async addMessage(params) {
|
|
3978
4241
|
const trusted = validateQueueTrust(params);
|
|
3979
4242
|
const now = nowISO();
|
|
3980
|
-
const id = params.id || (0,
|
|
4243
|
+
const id = params.id || (0, import_crypto5.randomUUID)();
|
|
3981
4244
|
const seqRow = this.db.prepare(
|
|
3982
4245
|
`SELECT COALESCE(MAX(sequence_order), 0) + 1 as next_seq FROM lt_thread_message_queue WHERE thread_id = ?`
|
|
3983
4246
|
).get(params.threadId);
|
|
@@ -4020,7 +4283,7 @@ var LocalThreadMessageQueueStore = class {
|
|
|
4020
4283
|
projectId: params.projectId
|
|
4021
4284
|
};
|
|
4022
4285
|
const filter = scopeClause(scope);
|
|
4023
|
-
const id = params.id || (0,
|
|
4286
|
+
const id = params.id || (0, import_crypto5.randomUUID)();
|
|
4024
4287
|
const limit = maxSize === Infinity ? -1 : maxSize;
|
|
4025
4288
|
const result = this.db.prepare(
|
|
4026
4289
|
`INSERT INTO lt_thread_message_queue (id, thread_id, tenant_id, assistant_id, workspace_id, project_id, message_content, message_type, sequence_order, priority, command, custom_run_config, trusted_run_context, execution_mode, created_at)
|
|
@@ -4058,7 +4321,7 @@ var LocalThreadMessageQueueStore = class {
|
|
|
4058
4321
|
async addMessageAtHead(params) {
|
|
4059
4322
|
const trusted = validateQueueTrust(params);
|
|
4060
4323
|
const now = nowISO();
|
|
4061
|
-
const id = params.id || (0,
|
|
4324
|
+
const id = params.id || (0, import_crypto5.randomUUID)();
|
|
4062
4325
|
const seqRow = this.db.prepare(
|
|
4063
4326
|
`SELECT COALESCE(MAX(sequence_order), 0) + 1 as next_seq FROM lt_thread_message_queue WHERE thread_id = ?`
|
|
4064
4327
|
).get(params.threadId);
|
|
@@ -4177,7 +4440,7 @@ function rowToMessage(row) {
|
|
|
4177
4440
|
}
|
|
4178
4441
|
|
|
4179
4442
|
// src/stores/LocalSkillStore.ts
|
|
4180
|
-
var
|
|
4443
|
+
var DDL19 = `
|
|
4181
4444
|
CREATE TABLE IF NOT EXISTS lt_skills (
|
|
4182
4445
|
id TEXT NOT NULL,
|
|
4183
4446
|
tenant_id TEXT NOT NULL,
|
|
@@ -4196,7 +4459,7 @@ CREATE TABLE IF NOT EXISTS lt_skills (
|
|
|
4196
4459
|
var LocalSkillStore = class {
|
|
4197
4460
|
constructor(db) {
|
|
4198
4461
|
this.db = db;
|
|
4199
|
-
ensureTable(db,
|
|
4462
|
+
ensureTable(db, DDL19);
|
|
4200
4463
|
}
|
|
4201
4464
|
async getAllSkills(tenantId, _context) {
|
|
4202
4465
|
const rows2 = this.db.prepare(
|
|
@@ -4346,7 +4609,7 @@ function mapRowToSkill(row) {
|
|
|
4346
4609
|
}
|
|
4347
4610
|
|
|
4348
4611
|
// src/stores/LocalScheduleStorage.ts
|
|
4349
|
-
var
|
|
4612
|
+
var DDL20 = `
|
|
4350
4613
|
CREATE TABLE IF NOT EXISTS lt_scheduled_tasks (
|
|
4351
4614
|
task_id TEXT PRIMARY KEY,
|
|
4352
4615
|
task_type TEXT NOT NULL,
|
|
@@ -4379,7 +4642,7 @@ CREATE INDEX IF NOT EXISTS idx_lt_st_tenant ON lt_scheduled_tasks(tenant_id);
|
|
|
4379
4642
|
var LocalScheduleStorage = class {
|
|
4380
4643
|
constructor(db) {
|
|
4381
4644
|
this.db = db;
|
|
4382
|
-
ensureTable(db,
|
|
4645
|
+
ensureTable(db, DDL20);
|
|
4383
4646
|
}
|
|
4384
4647
|
async save(task) {
|
|
4385
4648
|
this.db.prepare(
|
|
@@ -4673,7 +4936,7 @@ function mapRowToTask(row) {
|
|
|
4673
4936
|
}
|
|
4674
4937
|
|
|
4675
4938
|
// src/stores/LocalTaskStore.ts
|
|
4676
|
-
var
|
|
4939
|
+
var import_crypto6 = require("crypto");
|
|
4677
4940
|
var MAX_CANONICAL_TASK_TIME = "9999-12-31T23:59:59.999Z";
|
|
4678
4941
|
var TASK_STATUSES = /* @__PURE__ */ new Set([
|
|
4679
4942
|
"pending",
|
|
@@ -4689,7 +4952,7 @@ var NEXT_UPDATED_AT_SQL = `updated_at = CASE
|
|
|
4689
4952
|
THEN strftime('%Y-%m-%dT%H:%M:%fZ', updated_at, '+0.001 seconds')
|
|
4690
4953
|
ELSE ?
|
|
4691
4954
|
END`;
|
|
4692
|
-
var
|
|
4955
|
+
var DDL21 = `
|
|
4693
4956
|
CREATE TABLE IF NOT EXISTS lt_tasks (
|
|
4694
4957
|
id TEXT NOT NULL,
|
|
4695
4958
|
tenant_id TEXT NOT NULL,
|
|
@@ -4762,7 +5025,7 @@ function assertPage(limit, offset = 0) {
|
|
|
4762
5025
|
var LocalTaskStore = class {
|
|
4763
5026
|
constructor(db) {
|
|
4764
5027
|
this.db = db;
|
|
4765
|
-
ensureTable(db,
|
|
5028
|
+
ensureTable(db, DDL21);
|
|
4766
5029
|
this.ensureColumn("lt_tasks", "require_review", "require_review INTEGER DEFAULT 0");
|
|
4767
5030
|
this.ensureColumn("lt_tasks", "dependencies", "dependencies TEXT");
|
|
4768
5031
|
this.ensureColumn("lt_tasks", "result", "result TEXT");
|
|
@@ -4779,7 +5042,7 @@ var LocalTaskStore = class {
|
|
|
4779
5042
|
}
|
|
4780
5043
|
}
|
|
4781
5044
|
async create(params) {
|
|
4782
|
-
const id = params.id ?? (0,
|
|
5045
|
+
const id = params.id ?? (0, import_crypto6.randomUUID)();
|
|
4783
5046
|
const now = nowISO();
|
|
4784
5047
|
this.db.prepare(
|
|
4785
5048
|
`INSERT INTO lt_tasks (id, tenant_id, owner_type, owner_id, title, description, status, priority, due_date, metadata, parent_id, source_id, context, require_review, dependencies, result, failure_reason, workspace_id, project_id, files, created_at, updated_at)
|
|
@@ -5439,7 +5702,7 @@ var PROJECT_LIFECYCLE_ACTIONS = /* @__PURE__ */ new Set([
|
|
|
5439
5702
|
"cancelled",
|
|
5440
5703
|
"reassigned"
|
|
5441
5704
|
]);
|
|
5442
|
-
var
|
|
5705
|
+
var DDL22 = `
|
|
5443
5706
|
CREATE TABLE IF NOT EXISTS lt_task_work_items (
|
|
5444
5707
|
id TEXT NOT NULL,
|
|
5445
5708
|
tenant_id TEXT NOT NULL,
|
|
@@ -5513,7 +5776,7 @@ function assertLifecyclePage(query) {
|
|
|
5513
5776
|
var LocalTaskWorkItemStore = class {
|
|
5514
5777
|
constructor(db) {
|
|
5515
5778
|
this.db = db;
|
|
5516
|
-
ensureTable(db,
|
|
5779
|
+
ensureTable(db, DDL22);
|
|
5517
5780
|
this.ensureColumn("lt_task_work_items", "workspace_id", "workspace_id TEXT");
|
|
5518
5781
|
this.ensureColumn("lt_task_work_items", "project_id", "project_id TEXT");
|
|
5519
5782
|
this.ensureColumn("lt_task_work_items", "event_key", "event_key TEXT");
|
|
@@ -5709,8 +5972,8 @@ var LocalTaskWorkItemStore = class {
|
|
|
5709
5972
|
};
|
|
5710
5973
|
|
|
5711
5974
|
// src/stores/LocalCapabilityBundleStore.ts
|
|
5712
|
-
var
|
|
5713
|
-
var
|
|
5975
|
+
var import_crypto7 = require("crypto");
|
|
5976
|
+
var DDL23 = `CREATE TABLE IF NOT EXISTS lt_capability_bundles (id TEXT NOT NULL, tenant_id TEXT NOT NULL, bundle_key TEXT NOT NULL, name TEXT NOT NULL, description TEXT, capabilities TEXT NOT NULL DEFAULT '[]', created_at TEXT NOT NULL, updated_at TEXT NOT NULL, PRIMARY KEY (tenant_id, id), UNIQUE (tenant_id, bundle_key)); CREATE INDEX IF NOT EXISTS idx_lt_capability_bundles_tenant ON lt_capability_bundles(tenant_id);`;
|
|
5714
5977
|
var duplicateMessage = "Capability bundle key already exists for tenant";
|
|
5715
5978
|
function map(row) {
|
|
5716
5979
|
return { id: row.id, tenantId: row.tenant_id, key: row.bundle_key, name: row.name, description: row.description ?? void 0, capabilities: JSON.parse(row.capabilities), createdAt: parseISO(row.created_at).toISOString(), updatedAt: parseISO(row.updated_at).toISOString() };
|
|
@@ -5731,7 +5994,7 @@ var LocalCapabilityBundleStore = class {
|
|
|
5731
5994
|
*/
|
|
5732
5995
|
constructor(db) {
|
|
5733
5996
|
this.db = db;
|
|
5734
|
-
ensureTable(db,
|
|
5997
|
+
ensureTable(db, DDL23);
|
|
5735
5998
|
}
|
|
5736
5999
|
async listByTenant(tenantId) {
|
|
5737
6000
|
return this.db.prepare("SELECT * FROM lt_capability_bundles WHERE tenant_id = ? ORDER BY created_at").all(tenantId).map(map);
|
|
@@ -5748,7 +6011,7 @@ var LocalCapabilityBundleStore = class {
|
|
|
5748
6011
|
}
|
|
5749
6012
|
async create(tenantId, input) {
|
|
5750
6013
|
const now = nextTimestamp();
|
|
5751
|
-
const id = (0,
|
|
6014
|
+
const id = (0, import_crypto7.randomUUID)();
|
|
5752
6015
|
try {
|
|
5753
6016
|
this.db.prepare("INSERT INTO lt_capability_bundles (id, tenant_id, bundle_key, name, description, capabilities, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)").run(id, tenantId, input.key, input.name, input.description ?? null, JSON.stringify(input.capabilities), now, now);
|
|
5754
6017
|
} catch (error) {
|
|
@@ -5817,6 +6080,7 @@ async function createLocalStoreConfig(options = {}) {
|
|
|
5817
6080
|
projectMembership: new LocalProjectMembershipStore(db),
|
|
5818
6081
|
projectBotMembership: new LocalProjectBotMembershipStore(db),
|
|
5819
6082
|
projectRoomMessage: new LocalProjectRoomMessageStore(db),
|
|
6083
|
+
projectRoomReadState: new LocalProjectRoomReadStateStore(db),
|
|
5820
6084
|
user: new LocalUserStore(db),
|
|
5821
6085
|
tenant: new LocalTenantStore(db),
|
|
5822
6086
|
userTenantLink: new LocalUserTenantLinkStore(db),
|
|
@@ -5829,6 +6093,7 @@ async function createLocalStoreConfig(options = {}) {
|
|
|
5829
6093
|
channelBinding: new LocalChannelBindingStore(db),
|
|
5830
6094
|
channelInstallation: new LocalChannelInstallationStore(db),
|
|
5831
6095
|
a2aApiKey: new LocalA2AApiKeyStore(db),
|
|
6096
|
+
openAudit: new LocalOpenAuditStore(db),
|
|
5832
6097
|
threadMessageQueue: new LocalThreadMessageQueueStore(db),
|
|
5833
6098
|
skill: new LocalSkillStore(db),
|
|
5834
6099
|
schedule: new LocalScheduleStorage(db),
|
|
@@ -5891,9 +6156,11 @@ var InMemoryConversationStore = class {
|
|
|
5891
6156
|
LocalEvalStore,
|
|
5892
6157
|
LocalMcpServerConfigStore,
|
|
5893
6158
|
LocalMetricsServerConfigStore,
|
|
6159
|
+
LocalOpenAuditStore,
|
|
5894
6160
|
LocalProjectBotMembershipStore,
|
|
5895
6161
|
LocalProjectMembershipStore,
|
|
5896
6162
|
LocalProjectRoomMessageStore,
|
|
6163
|
+
LocalProjectRoomReadStateStore,
|
|
5897
6164
|
LocalProjectRoomStore,
|
|
5898
6165
|
LocalProjectStore,
|
|
5899
6166
|
LocalScheduleStorage,
|