@axiom-lattice/pg-stores 1.0.37 → 1.0.39
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 +16 -0
- package/dist/index.d.mts +103 -3
- package/dist/index.d.ts +103 -3
- package/dist/index.js +502 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +498 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/ChannelIdentityMappingStore.test.ts +219 -0
- package/src/__tests__/PostgreSQLChannelInstallationStore.test.ts +54 -0
- package/src/index.ts +11 -0
- package/src/migrations/channel_identity_mapping_migration.ts +59 -0
- package/src/migrations/channel_installation_migrations.ts +31 -0
- package/src/stores/ChannelIdentityMappingStore.ts +334 -0
- package/src/stores/PostgreSQLChannelInstallationStore.ts +304 -0
package/dist/index.js
CHANGED
|
@@ -31,11 +31,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
AddMessageParams: () => import_core4.AddMessageParams,
|
|
34
|
+
ChannelIdentityMappingStore: () => ChannelIdentityMappingStore,
|
|
34
35
|
MigrationManager: () => MigrationManager,
|
|
35
36
|
PendingMessage: () => import_core4.PendingMessage,
|
|
36
|
-
Pool: () =>
|
|
37
|
-
PoolConfig: () =>
|
|
37
|
+
Pool: () => import_pg15.Pool,
|
|
38
|
+
PoolConfig: () => import_pg15.PoolConfig,
|
|
38
39
|
PostgreSQLAssistantStore: () => PostgreSQLAssistantStore,
|
|
40
|
+
PostgreSQLChannelInstallationStore: () => PostgreSQLChannelInstallationStore,
|
|
39
41
|
PostgreSQLDatabaseConfigStore: () => PostgreSQLDatabaseConfigStore,
|
|
40
42
|
PostgreSQLMcpServerConfigStore: () => PostgreSQLMcpServerConfigStore,
|
|
41
43
|
PostgreSQLMetricsServerConfigStore: () => PostgreSQLMetricsServerConfigStore,
|
|
@@ -57,6 +59,8 @@ __export(index_exports, {
|
|
|
57
59
|
changeSkillPrimaryKey: () => changeSkillPrimaryKey,
|
|
58
60
|
changeThreadPrimaryKey: () => changeThreadPrimaryKey,
|
|
59
61
|
createAssistantsTable: () => createAssistantsTable,
|
|
62
|
+
createChannelIdentityMappingTables: () => createChannelIdentityMappingTables,
|
|
63
|
+
createChannelInstallationsTable: () => createChannelInstallationsTable,
|
|
60
64
|
createDatabaseConfigsTable: () => createDatabaseConfigsTable,
|
|
61
65
|
createMcpServerConfigsTable: () => createMcpServerConfigsTable,
|
|
62
66
|
createMetricsConfigsTable: () => createMetricsConfigsTable,
|
|
@@ -71,7 +75,7 @@ __export(index_exports, {
|
|
|
71
75
|
getThreadMessageQueueStore: () => getThreadMessageQueueStore
|
|
72
76
|
});
|
|
73
77
|
module.exports = __toCommonJS(index_exports);
|
|
74
|
-
var
|
|
78
|
+
var import_pg15 = require("pg");
|
|
75
79
|
|
|
76
80
|
// src/stores/PostgreSQLThreadStore.ts
|
|
77
81
|
var import_pg = require("pg");
|
|
@@ -4084,6 +4088,90 @@ var createThreadMessageQueueTable = {
|
|
|
4084
4088
|
}
|
|
4085
4089
|
};
|
|
4086
4090
|
|
|
4091
|
+
// src/migrations/channel_identity_mapping_migration.ts
|
|
4092
|
+
var createChannelIdentityMappingTables = {
|
|
4093
|
+
version: 20,
|
|
4094
|
+
name: "create_channel_identity_mapping_tables",
|
|
4095
|
+
up: async (client) => {
|
|
4096
|
+
await client.query(`
|
|
4097
|
+
CREATE TABLE IF NOT EXISTS channel_identity_mappings (
|
|
4098
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
4099
|
+
channel VARCHAR(50) NOT NULL,
|
|
4100
|
+
channel_app_id VARCHAR(255) NOT NULL,
|
|
4101
|
+
tenant_id VARCHAR(255) NOT NULL,
|
|
4102
|
+
assistant_id VARCHAR(255) NOT NULL,
|
|
4103
|
+
mapping_mode VARCHAR(20) NOT NULL CHECK (mapping_mode IN ('user', 'group', 'hybrid')),
|
|
4104
|
+
external_subject_type VARCHAR(20) NOT NULL CHECK (external_subject_type IN ('user', 'chat')),
|
|
4105
|
+
external_subject_key VARCHAR(512) NOT NULL,
|
|
4106
|
+
lark_open_id VARCHAR(255),
|
|
4107
|
+
lark_chat_id VARCHAR(255) NOT NULL,
|
|
4108
|
+
lark_message_id VARCHAR(255),
|
|
4109
|
+
thread_id VARCHAR(255) NOT NULL,
|
|
4110
|
+
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
4111
|
+
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
4112
|
+
last_activity_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
4113
|
+
UNIQUE (channel, channel_app_id, tenant_id, assistant_id, external_subject_key)
|
|
4114
|
+
)
|
|
4115
|
+
`);
|
|
4116
|
+
await client.query(`
|
|
4117
|
+
CREATE INDEX IF NOT EXISTS idx_channel_identity_lookup
|
|
4118
|
+
ON channel_identity_mappings(channel, channel_app_id, tenant_id, assistant_id, external_subject_key)
|
|
4119
|
+
`);
|
|
4120
|
+
await client.query(`
|
|
4121
|
+
CREATE INDEX IF NOT EXISTS idx_channel_identity_thread
|
|
4122
|
+
ON channel_identity_mappings(thread_id, tenant_id)
|
|
4123
|
+
`);
|
|
4124
|
+
await client.query(`
|
|
4125
|
+
CREATE TABLE IF NOT EXISTS channel_inbound_message_receipts (
|
|
4126
|
+
channel VARCHAR(50) NOT NULL,
|
|
4127
|
+
channel_app_id VARCHAR(255) NOT NULL,
|
|
4128
|
+
external_message_id VARCHAR(255) NOT NULL,
|
|
4129
|
+
tenant_id VARCHAR(255) NOT NULL,
|
|
4130
|
+
status VARCHAR(20) NOT NULL DEFAULT 'processing' CHECK (status IN ('processing', 'completed', 'failed')),
|
|
4131
|
+
thread_id VARCHAR(255),
|
|
4132
|
+
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
4133
|
+
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
4134
|
+
PRIMARY KEY (channel, channel_app_id, external_message_id)
|
|
4135
|
+
)
|
|
4136
|
+
`);
|
|
4137
|
+
},
|
|
4138
|
+
down: async (client) => {
|
|
4139
|
+
await client.query("DROP TABLE IF EXISTS channel_inbound_message_receipts");
|
|
4140
|
+
await client.query("DROP INDEX IF EXISTS idx_channel_identity_thread");
|
|
4141
|
+
await client.query("DROP INDEX IF EXISTS idx_channel_identity_lookup");
|
|
4142
|
+
await client.query("DROP TABLE IF EXISTS channel_identity_mappings");
|
|
4143
|
+
}
|
|
4144
|
+
};
|
|
4145
|
+
|
|
4146
|
+
// src/migrations/channel_installation_migrations.ts
|
|
4147
|
+
var createChannelInstallationsTable = {
|
|
4148
|
+
version: 21,
|
|
4149
|
+
name: "create_channel_installations_table",
|
|
4150
|
+
up: async (client) => {
|
|
4151
|
+
await client.query(`
|
|
4152
|
+
CREATE TABLE IF NOT EXISTS lattice_channel_installations (
|
|
4153
|
+
id UUID PRIMARY KEY,
|
|
4154
|
+
tenant_id VARCHAR(255) NOT NULL,
|
|
4155
|
+
channel VARCHAR(50) NOT NULL,
|
|
4156
|
+
name VARCHAR(255),
|
|
4157
|
+
config JSONB NOT NULL,
|
|
4158
|
+
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
4159
|
+
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
4160
|
+
)
|
|
4161
|
+
`);
|
|
4162
|
+
await client.query(`
|
|
4163
|
+
CREATE INDEX IF NOT EXISTS idx_channel_installations_tenant_channel
|
|
4164
|
+
ON lattice_channel_installations(tenant_id, channel)
|
|
4165
|
+
`);
|
|
4166
|
+
},
|
|
4167
|
+
down: async (client) => {
|
|
4168
|
+
await client.query(
|
|
4169
|
+
"DROP INDEX IF EXISTS idx_channel_installations_tenant_channel"
|
|
4170
|
+
);
|
|
4171
|
+
await client.query("DROP TABLE IF EXISTS lattice_channel_installations");
|
|
4172
|
+
}
|
|
4173
|
+
};
|
|
4174
|
+
|
|
4087
4175
|
// src/stores/ThreadMessageQueueStore.ts
|
|
4088
4176
|
var import_crypto = __toESM(require("crypto"));
|
|
4089
4177
|
var import_core4 = require("@axiom-lattice/core");
|
|
@@ -4373,14 +4461,423 @@ var ThreadMessageQueueStore = class _ThreadMessageQueueStore {
|
|
|
4373
4461
|
}
|
|
4374
4462
|
};
|
|
4375
4463
|
var getThreadMessageQueueStore = () => ThreadMessageQueueStore.getInstance();
|
|
4464
|
+
|
|
4465
|
+
// src/stores/ChannelIdentityMappingStore.ts
|
|
4466
|
+
var import_pg13 = require("pg");
|
|
4467
|
+
var ChannelIdentityMappingStore = class {
|
|
4468
|
+
constructor(options) {
|
|
4469
|
+
this.initialized = false;
|
|
4470
|
+
this.initPromise = null;
|
|
4471
|
+
this.pool = typeof options.poolConfig === "string" ? new import_pg13.Pool({ connectionString: options.poolConfig }) : new import_pg13.Pool(options.poolConfig);
|
|
4472
|
+
this.migrationManager = new MigrationManager(this.pool);
|
|
4473
|
+
this.migrationManager.register(createChannelIdentityMappingTables);
|
|
4474
|
+
if (options.autoMigrate !== false) {
|
|
4475
|
+
this.initialize().catch((error) => {
|
|
4476
|
+
console.error("Failed to initialize ChannelIdentityMappingStore:", error);
|
|
4477
|
+
throw error;
|
|
4478
|
+
});
|
|
4479
|
+
}
|
|
4480
|
+
}
|
|
4481
|
+
async initialize() {
|
|
4482
|
+
if (this.initialized) {
|
|
4483
|
+
return;
|
|
4484
|
+
}
|
|
4485
|
+
if (this.initPromise) {
|
|
4486
|
+
return this.initPromise;
|
|
4487
|
+
}
|
|
4488
|
+
this.initPromise = (async () => {
|
|
4489
|
+
try {
|
|
4490
|
+
await this.migrationManager.migrate();
|
|
4491
|
+
this.initialized = true;
|
|
4492
|
+
} finally {
|
|
4493
|
+
this.initPromise = null;
|
|
4494
|
+
}
|
|
4495
|
+
})();
|
|
4496
|
+
return this.initPromise;
|
|
4497
|
+
}
|
|
4498
|
+
async createMapping(input) {
|
|
4499
|
+
await this.ensureInitialized();
|
|
4500
|
+
const result = await this.pool.query(
|
|
4501
|
+
`
|
|
4502
|
+
INSERT INTO channel_identity_mappings (
|
|
4503
|
+
channel,
|
|
4504
|
+
channel_app_id,
|
|
4505
|
+
tenant_id,
|
|
4506
|
+
assistant_id,
|
|
4507
|
+
mapping_mode,
|
|
4508
|
+
external_subject_type,
|
|
4509
|
+
external_subject_key,
|
|
4510
|
+
lark_open_id,
|
|
4511
|
+
lark_chat_id,
|
|
4512
|
+
lark_message_id,
|
|
4513
|
+
thread_id
|
|
4514
|
+
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
|
|
4515
|
+
RETURNING *
|
|
4516
|
+
`,
|
|
4517
|
+
[
|
|
4518
|
+
input.channel,
|
|
4519
|
+
input.channelAppId,
|
|
4520
|
+
input.tenantId,
|
|
4521
|
+
input.assistantId,
|
|
4522
|
+
input.mappingMode,
|
|
4523
|
+
input.externalSubjectType,
|
|
4524
|
+
input.externalSubjectKey,
|
|
4525
|
+
input.larkOpenId || null,
|
|
4526
|
+
input.larkChatId,
|
|
4527
|
+
input.larkMessageId || null,
|
|
4528
|
+
input.threadId
|
|
4529
|
+
]
|
|
4530
|
+
);
|
|
4531
|
+
return mapRowToChannelIdentityMapping(result.rows[0]);
|
|
4532
|
+
}
|
|
4533
|
+
async getMappingBySubject(input) {
|
|
4534
|
+
await this.ensureInitialized();
|
|
4535
|
+
const result = await this.pool.query(
|
|
4536
|
+
`
|
|
4537
|
+
SELECT *
|
|
4538
|
+
FROM channel_identity_mappings
|
|
4539
|
+
WHERE channel = $1
|
|
4540
|
+
AND channel_app_id = $2
|
|
4541
|
+
AND tenant_id = $3
|
|
4542
|
+
AND assistant_id = $4
|
|
4543
|
+
AND external_subject_key = $5
|
|
4544
|
+
LIMIT 1
|
|
4545
|
+
`,
|
|
4546
|
+
[
|
|
4547
|
+
input.channel,
|
|
4548
|
+
input.channelAppId,
|
|
4549
|
+
input.tenantId,
|
|
4550
|
+
input.assistantId,
|
|
4551
|
+
input.externalSubjectKey
|
|
4552
|
+
]
|
|
4553
|
+
);
|
|
4554
|
+
if (result.rows.length === 0) {
|
|
4555
|
+
return null;
|
|
4556
|
+
}
|
|
4557
|
+
return mapRowToChannelIdentityMapping(result.rows[0]);
|
|
4558
|
+
}
|
|
4559
|
+
async claimInboundReceipt(input) {
|
|
4560
|
+
await this.ensureInitialized();
|
|
4561
|
+
const result = await this.pool.query(
|
|
4562
|
+
`
|
|
4563
|
+
WITH existing AS (
|
|
4564
|
+
SELECT status
|
|
4565
|
+
FROM channel_inbound_message_receipts
|
|
4566
|
+
WHERE channel = $1
|
|
4567
|
+
AND channel_app_id = $2
|
|
4568
|
+
AND external_message_id = $3
|
|
4569
|
+
AND tenant_id = $4
|
|
4570
|
+
),
|
|
4571
|
+
inserted AS (
|
|
4572
|
+
INSERT INTO channel_inbound_message_receipts (
|
|
4573
|
+
channel,
|
|
4574
|
+
channel_app_id,
|
|
4575
|
+
external_message_id,
|
|
4576
|
+
tenant_id,
|
|
4577
|
+
status
|
|
4578
|
+
)
|
|
4579
|
+
SELECT $1, $2, $3, $4, 'processing'
|
|
4580
|
+
WHERE NOT EXISTS (SELECT 1 FROM existing)
|
|
4581
|
+
RETURNING 'inserted'::text AS source, status
|
|
4582
|
+
),
|
|
4583
|
+
retried AS (
|
|
4584
|
+
UPDATE channel_inbound_message_receipts
|
|
4585
|
+
SET status = 'processing', updated_at = CURRENT_TIMESTAMP
|
|
4586
|
+
WHERE channel = $1
|
|
4587
|
+
AND channel_app_id = $2
|
|
4588
|
+
AND external_message_id = $3
|
|
4589
|
+
AND tenant_id = $4
|
|
4590
|
+
AND EXISTS (SELECT 1 FROM existing WHERE status = 'failed')
|
|
4591
|
+
RETURNING 'retried'::text AS source, status
|
|
4592
|
+
)
|
|
4593
|
+
SELECT source, status FROM inserted
|
|
4594
|
+
UNION ALL
|
|
4595
|
+
SELECT source, status FROM retried
|
|
4596
|
+
UNION ALL
|
|
4597
|
+
SELECT 'existing'::text AS source, status FROM existing
|
|
4598
|
+
WHERE EXISTS (SELECT 1 FROM existing WHERE status IN ('processing', 'completed'))
|
|
4599
|
+
LIMIT 1
|
|
4600
|
+
`,
|
|
4601
|
+
[
|
|
4602
|
+
input.channel,
|
|
4603
|
+
input.channelAppId,
|
|
4604
|
+
input.externalMessageId,
|
|
4605
|
+
input.tenantId
|
|
4606
|
+
]
|
|
4607
|
+
);
|
|
4608
|
+
const source = result.rows[0]?.source;
|
|
4609
|
+
const status = result.rows[0]?.status || "processing";
|
|
4610
|
+
if (source === "inserted" || source === "retried") {
|
|
4611
|
+
return { accepted: true, status: "processing" };
|
|
4612
|
+
}
|
|
4613
|
+
if (status === "completed") {
|
|
4614
|
+
return { accepted: false, status: "completed" };
|
|
4615
|
+
}
|
|
4616
|
+
return { accepted: false, status: "processing" };
|
|
4617
|
+
}
|
|
4618
|
+
async markInboundReceiptCompleted(input) {
|
|
4619
|
+
await this.ensureInitialized();
|
|
4620
|
+
await this.pool.query(
|
|
4621
|
+
`
|
|
4622
|
+
UPDATE channel_inbound_message_receipts
|
|
4623
|
+
SET status = 'completed', thread_id = $1, updated_at = CURRENT_TIMESTAMP
|
|
4624
|
+
WHERE channel = $2
|
|
4625
|
+
AND channel_app_id = $3
|
|
4626
|
+
AND external_message_id = $4
|
|
4627
|
+
AND tenant_id = $5
|
|
4628
|
+
`,
|
|
4629
|
+
[
|
|
4630
|
+
input.threadId,
|
|
4631
|
+
input.channel,
|
|
4632
|
+
input.channelAppId,
|
|
4633
|
+
input.externalMessageId,
|
|
4634
|
+
input.tenantId
|
|
4635
|
+
]
|
|
4636
|
+
);
|
|
4637
|
+
}
|
|
4638
|
+
async markInboundReceiptFailed(input) {
|
|
4639
|
+
await this.ensureInitialized();
|
|
4640
|
+
await this.pool.query(
|
|
4641
|
+
`
|
|
4642
|
+
UPDATE channel_inbound_message_receipts
|
|
4643
|
+
SET status = 'failed', updated_at = CURRENT_TIMESTAMP
|
|
4644
|
+
WHERE channel = $1
|
|
4645
|
+
AND channel_app_id = $2
|
|
4646
|
+
AND external_message_id = $3
|
|
4647
|
+
AND tenant_id = $4
|
|
4648
|
+
`,
|
|
4649
|
+
[
|
|
4650
|
+
input.channel,
|
|
4651
|
+
input.channelAppId,
|
|
4652
|
+
input.externalMessageId,
|
|
4653
|
+
input.tenantId
|
|
4654
|
+
]
|
|
4655
|
+
);
|
|
4656
|
+
}
|
|
4657
|
+
async ensureInitialized() {
|
|
4658
|
+
if (!this.initialized) {
|
|
4659
|
+
await this.initialize();
|
|
4660
|
+
}
|
|
4661
|
+
}
|
|
4662
|
+
};
|
|
4663
|
+
function mapRowToChannelIdentityMapping(row) {
|
|
4664
|
+
return {
|
|
4665
|
+
id: row.id,
|
|
4666
|
+
channel: row.channel,
|
|
4667
|
+
channelAppId: row.channel_app_id,
|
|
4668
|
+
tenantId: row.tenant_id,
|
|
4669
|
+
assistantId: row.assistant_id,
|
|
4670
|
+
mappingMode: row.mapping_mode,
|
|
4671
|
+
externalSubjectType: row.external_subject_type,
|
|
4672
|
+
externalSubjectKey: row.external_subject_key,
|
|
4673
|
+
larkOpenId: row.lark_open_id || void 0,
|
|
4674
|
+
larkChatId: row.lark_chat_id,
|
|
4675
|
+
larkMessageId: row.lark_message_id || void 0,
|
|
4676
|
+
threadId: row.thread_id,
|
|
4677
|
+
createdAt: row.created_at,
|
|
4678
|
+
updatedAt: row.updated_at,
|
|
4679
|
+
lastActivityAt: row.last_activity_at
|
|
4680
|
+
};
|
|
4681
|
+
}
|
|
4682
|
+
|
|
4683
|
+
// src/stores/PostgreSQLChannelInstallationStore.ts
|
|
4684
|
+
var import_pg14 = require("pg");
|
|
4685
|
+
var import_core5 = require("@axiom-lattice/core");
|
|
4686
|
+
var PostgreSQLChannelInstallationStore = class {
|
|
4687
|
+
constructor(options) {
|
|
4688
|
+
this.initialized = false;
|
|
4689
|
+
this.initPromise = null;
|
|
4690
|
+
this.pool = typeof options.poolConfig === "string" ? new import_pg14.Pool({ connectionString: options.poolConfig }) : new import_pg14.Pool(options.poolConfig);
|
|
4691
|
+
this.migrationManager = new MigrationManager(this.pool);
|
|
4692
|
+
this.migrationManager.register(createChannelInstallationsTable);
|
|
4693
|
+
if (options.autoMigrate !== false) {
|
|
4694
|
+
this.initialize().catch((error) => {
|
|
4695
|
+
console.error(
|
|
4696
|
+
"Failed to initialize PostgreSQLChannelInstallationStore:",
|
|
4697
|
+
error
|
|
4698
|
+
);
|
|
4699
|
+
throw error;
|
|
4700
|
+
});
|
|
4701
|
+
}
|
|
4702
|
+
}
|
|
4703
|
+
async initialize() {
|
|
4704
|
+
if (this.initialized) {
|
|
4705
|
+
return;
|
|
4706
|
+
}
|
|
4707
|
+
if (this.initPromise) {
|
|
4708
|
+
return this.initPromise;
|
|
4709
|
+
}
|
|
4710
|
+
this.initPromise = (async () => {
|
|
4711
|
+
try {
|
|
4712
|
+
await this.migrationManager.migrate();
|
|
4713
|
+
this.initialized = true;
|
|
4714
|
+
} finally {
|
|
4715
|
+
this.initPromise = null;
|
|
4716
|
+
}
|
|
4717
|
+
})();
|
|
4718
|
+
return this.initPromise;
|
|
4719
|
+
}
|
|
4720
|
+
async getInstallationById(installationId) {
|
|
4721
|
+
await this.ensureInitialized();
|
|
4722
|
+
const result = await this.pool.query(
|
|
4723
|
+
`
|
|
4724
|
+
SELECT id, tenant_id, channel, name, config, created_at, updated_at
|
|
4725
|
+
FROM lattice_channel_installations
|
|
4726
|
+
WHERE id = $1
|
|
4727
|
+
LIMIT 1
|
|
4728
|
+
`,
|
|
4729
|
+
[installationId]
|
|
4730
|
+
);
|
|
4731
|
+
if (result.rows.length === 0) {
|
|
4732
|
+
return null;
|
|
4733
|
+
}
|
|
4734
|
+
return this.mapRowToInstallation(result.rows[0]);
|
|
4735
|
+
}
|
|
4736
|
+
async getInstallationsByTenant(tenantId, channel) {
|
|
4737
|
+
await this.ensureInitialized();
|
|
4738
|
+
const result = channel ? await this.pool.query(
|
|
4739
|
+
`
|
|
4740
|
+
SELECT id, tenant_id, channel, name, config, created_at, updated_at
|
|
4741
|
+
FROM lattice_channel_installations
|
|
4742
|
+
WHERE tenant_id = $1 AND channel = $2
|
|
4743
|
+
ORDER BY created_at DESC
|
|
4744
|
+
`,
|
|
4745
|
+
[tenantId, channel]
|
|
4746
|
+
) : await this.pool.query(
|
|
4747
|
+
`
|
|
4748
|
+
SELECT id, tenant_id, channel, name, config, created_at, updated_at
|
|
4749
|
+
FROM lattice_channel_installations
|
|
4750
|
+
WHERE tenant_id = $1
|
|
4751
|
+
ORDER BY created_at DESC
|
|
4752
|
+
`,
|
|
4753
|
+
[tenantId]
|
|
4754
|
+
);
|
|
4755
|
+
return result.rows.map((row) => this.mapRowToInstallation(row));
|
|
4756
|
+
}
|
|
4757
|
+
async createInstallation(tenantId, installationId, data) {
|
|
4758
|
+
await this.ensureInitialized();
|
|
4759
|
+
const now = /* @__PURE__ */ new Date();
|
|
4760
|
+
const encryptedConfig = this.encryptSecrets(data.config);
|
|
4761
|
+
await this.pool.query(
|
|
4762
|
+
`
|
|
4763
|
+
INSERT INTO lattice_channel_installations (
|
|
4764
|
+
id, tenant_id, channel, name, config, created_at, updated_at
|
|
4765
|
+
) VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
4766
|
+
`,
|
|
4767
|
+
[
|
|
4768
|
+
installationId,
|
|
4769
|
+
tenantId,
|
|
4770
|
+
data.channel,
|
|
4771
|
+
data.name || null,
|
|
4772
|
+
JSON.stringify(encryptedConfig),
|
|
4773
|
+
now,
|
|
4774
|
+
now
|
|
4775
|
+
]
|
|
4776
|
+
);
|
|
4777
|
+
return {
|
|
4778
|
+
id: installationId,
|
|
4779
|
+
tenantId,
|
|
4780
|
+
channel: data.channel,
|
|
4781
|
+
name: data.name,
|
|
4782
|
+
config: data.config,
|
|
4783
|
+
createdAt: now,
|
|
4784
|
+
updatedAt: now
|
|
4785
|
+
};
|
|
4786
|
+
}
|
|
4787
|
+
async updateInstallation(tenantId, installationId, updates) {
|
|
4788
|
+
await this.ensureInitialized();
|
|
4789
|
+
const existing = await this.getInstallationById(installationId);
|
|
4790
|
+
if (!existing || existing.tenantId !== tenantId) {
|
|
4791
|
+
return null;
|
|
4792
|
+
}
|
|
4793
|
+
const mergedConfig = {
|
|
4794
|
+
...existing.config,
|
|
4795
|
+
...updates.config || {}
|
|
4796
|
+
};
|
|
4797
|
+
const now = /* @__PURE__ */ new Date();
|
|
4798
|
+
await this.pool.query(
|
|
4799
|
+
`
|
|
4800
|
+
UPDATE lattice_channel_installations
|
|
4801
|
+
SET name = $1,
|
|
4802
|
+
config = $2,
|
|
4803
|
+
updated_at = $3
|
|
4804
|
+
WHERE tenant_id = $4 AND id = $5
|
|
4805
|
+
`,
|
|
4806
|
+
[
|
|
4807
|
+
updates.name ?? existing.name ?? null,
|
|
4808
|
+
JSON.stringify(this.encryptSecrets(mergedConfig)),
|
|
4809
|
+
now,
|
|
4810
|
+
tenantId,
|
|
4811
|
+
installationId
|
|
4812
|
+
]
|
|
4813
|
+
);
|
|
4814
|
+
return {
|
|
4815
|
+
...existing,
|
|
4816
|
+
name: updates.name ?? existing.name,
|
|
4817
|
+
config: mergedConfig,
|
|
4818
|
+
updatedAt: now
|
|
4819
|
+
};
|
|
4820
|
+
}
|
|
4821
|
+
async deleteInstallation(tenantId, installationId) {
|
|
4822
|
+
await this.ensureInitialized();
|
|
4823
|
+
const result = await this.pool.query(
|
|
4824
|
+
`
|
|
4825
|
+
DELETE FROM lattice_channel_installations
|
|
4826
|
+
WHERE tenant_id = $1 AND id = $2
|
|
4827
|
+
`,
|
|
4828
|
+
[tenantId, installationId]
|
|
4829
|
+
);
|
|
4830
|
+
return (result.rowCount || 0) > 0;
|
|
4831
|
+
}
|
|
4832
|
+
async ensureInitialized() {
|
|
4833
|
+
if (!this.initialized) {
|
|
4834
|
+
await this.initialize();
|
|
4835
|
+
}
|
|
4836
|
+
}
|
|
4837
|
+
mapRowToInstallation(row) {
|
|
4838
|
+
return {
|
|
4839
|
+
id: row.id,
|
|
4840
|
+
tenantId: row.tenant_id,
|
|
4841
|
+
channel: row.channel,
|
|
4842
|
+
name: row.name || void 0,
|
|
4843
|
+
config: this.decryptSecrets(
|
|
4844
|
+
typeof row.config === "string" ? JSON.parse(row.config) : row.config
|
|
4845
|
+
),
|
|
4846
|
+
createdAt: row.created_at,
|
|
4847
|
+
updatedAt: row.updated_at
|
|
4848
|
+
};
|
|
4849
|
+
}
|
|
4850
|
+
encryptSecrets(config) {
|
|
4851
|
+
return {
|
|
4852
|
+
...config,
|
|
4853
|
+
appSecret: typeof config.appSecret === "string" ? (0, import_core5.encrypt)(config.appSecret) : config.appSecret,
|
|
4854
|
+
verificationToken: typeof config.verificationToken === "string" ? (0, import_core5.encrypt)(config.verificationToken) : config.verificationToken,
|
|
4855
|
+
encryptKey: typeof config.encryptKey === "string" ? (0, import_core5.encrypt)(config.encryptKey) : config.encryptKey
|
|
4856
|
+
};
|
|
4857
|
+
}
|
|
4858
|
+
decryptSecrets(config) {
|
|
4859
|
+
return {
|
|
4860
|
+
appId: String(config.appId || ""),
|
|
4861
|
+
appSecret: typeof config.appSecret === "string" ? (0, import_core5.decrypt)(config.appSecret) : "",
|
|
4862
|
+
verificationToken: typeof config.verificationToken === "string" ? (0, import_core5.decrypt)(config.verificationToken) : void 0,
|
|
4863
|
+
encryptKey: typeof config.encryptKey === "string" ? (0, import_core5.decrypt)(config.encryptKey) : void 0,
|
|
4864
|
+
mappingMode: config.mappingMode === "user" || config.mappingMode === "group" || config.mappingMode === "hybrid" ? config.mappingMode : "hybrid",
|
|
4865
|
+
assistantId: String(config.assistantId || ""),
|
|
4866
|
+
workspaceId: typeof config.workspaceId === "string" ? config.workspaceId : void 0,
|
|
4867
|
+
projectId: typeof config.projectId === "string" ? config.projectId : void 0
|
|
4868
|
+
};
|
|
4869
|
+
}
|
|
4870
|
+
};
|
|
4376
4871
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4377
4872
|
0 && (module.exports = {
|
|
4378
4873
|
AddMessageParams,
|
|
4874
|
+
ChannelIdentityMappingStore,
|
|
4379
4875
|
MigrationManager,
|
|
4380
4876
|
PendingMessage,
|
|
4381
4877
|
Pool,
|
|
4382
4878
|
PoolConfig,
|
|
4383
4879
|
PostgreSQLAssistantStore,
|
|
4880
|
+
PostgreSQLChannelInstallationStore,
|
|
4384
4881
|
PostgreSQLDatabaseConfigStore,
|
|
4385
4882
|
PostgreSQLMcpServerConfigStore,
|
|
4386
4883
|
PostgreSQLMetricsServerConfigStore,
|
|
@@ -4402,6 +4899,8 @@ var getThreadMessageQueueStore = () => ThreadMessageQueueStore.getInstance();
|
|
|
4402
4899
|
changeSkillPrimaryKey,
|
|
4403
4900
|
changeThreadPrimaryKey,
|
|
4404
4901
|
createAssistantsTable,
|
|
4902
|
+
createChannelIdentityMappingTables,
|
|
4903
|
+
createChannelInstallationsTable,
|
|
4405
4904
|
createDatabaseConfigsTable,
|
|
4406
4905
|
createMcpServerConfigsTable,
|
|
4407
4906
|
createMetricsConfigsTable,
|