@axiom-lattice/core 2.1.75 → 2.1.77
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/README.md +340 -99
- package/dist/index.d.mts +558 -52
- package/dist/index.d.ts +558 -52
- package/dist/index.js +470 -96
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +468 -96
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -2319,24 +2319,6 @@ var InMemoryThreadMessageQueueStore = class {
|
|
|
2319
2319
|
}
|
|
2320
2320
|
}
|
|
2321
2321
|
}
|
|
2322
|
-
async markCompleted(messageId) {
|
|
2323
|
-
for (const messages of this.messages.values()) {
|
|
2324
|
-
const message = messages.find((msg) => msg.id === messageId);
|
|
2325
|
-
if (message) {
|
|
2326
|
-
message.status = "completed";
|
|
2327
|
-
return;
|
|
2328
|
-
}
|
|
2329
|
-
}
|
|
2330
|
-
}
|
|
2331
|
-
async clearCompletedMessages(threadId) {
|
|
2332
|
-
const messages = this.messages.get(threadId);
|
|
2333
|
-
if (messages) {
|
|
2334
|
-
const filtered = messages.filter(
|
|
2335
|
-
(msg) => msg.status !== "completed"
|
|
2336
|
-
);
|
|
2337
|
-
this.messages.set(threadId, filtered);
|
|
2338
|
-
}
|
|
2339
|
-
}
|
|
2340
2322
|
async resetProcessingToPending(threadId) {
|
|
2341
2323
|
const messages = this.messages.get(threadId);
|
|
2342
2324
|
if (!messages) {
|
|
@@ -2481,14 +2463,35 @@ var InMemoryChannelInstallationStore = class {
|
|
|
2481
2463
|
constructor() {
|
|
2482
2464
|
this.installations = /* @__PURE__ */ new Map();
|
|
2483
2465
|
}
|
|
2466
|
+
/**
|
|
2467
|
+
* Retrieves a channel installation by its unique ID.
|
|
2468
|
+
*
|
|
2469
|
+
* @param installationId - The installation identifier
|
|
2470
|
+
* @returns The {@link ChannelInstallation} or `null` if not found
|
|
2471
|
+
*/
|
|
2484
2472
|
async getInstallationById(installationId) {
|
|
2485
2473
|
return this.installations.get(installationId) || null;
|
|
2486
2474
|
}
|
|
2475
|
+
/**
|
|
2476
|
+
* Lists all channel installations for a tenant, optionally filtered by channel type.
|
|
2477
|
+
*
|
|
2478
|
+
* @param tenantId - Tenant identifier
|
|
2479
|
+
* @param channel - Optional channel type filter (`"lark"`, `"email"`, `"slack"`)
|
|
2480
|
+
* @returns Array of matching {@link ChannelInstallation} objects
|
|
2481
|
+
*/
|
|
2487
2482
|
async getInstallationsByTenant(tenantId, channel) {
|
|
2488
2483
|
return Array.from(this.installations.values()).filter(
|
|
2489
2484
|
(inst) => inst.tenantId === tenantId && (!channel || inst.channel === channel)
|
|
2490
2485
|
);
|
|
2491
2486
|
}
|
|
2487
|
+
/**
|
|
2488
|
+
* Creates a new channel installation for a tenant.
|
|
2489
|
+
*
|
|
2490
|
+
* @param tenantId - Tenant identifier
|
|
2491
|
+
* @param installationId - Unique installation ID (caller-defined)
|
|
2492
|
+
* @param data - {@link CreateChannelInstallationRequest} containing channel type, name, config, and fallback settings
|
|
2493
|
+
* @returns The created {@link ChannelInstallation}
|
|
2494
|
+
*/
|
|
2492
2495
|
async createInstallation(tenantId, installationId, data) {
|
|
2493
2496
|
const now = /* @__PURE__ */ new Date();
|
|
2494
2497
|
const installation = {
|
|
@@ -2506,6 +2509,14 @@ var InMemoryChannelInstallationStore = class {
|
|
|
2506
2509
|
this.installations.set(installationId, installation);
|
|
2507
2510
|
return installation;
|
|
2508
2511
|
}
|
|
2512
|
+
/**
|
|
2513
|
+
* Updates an existing channel installation. Config fields are shallow-merged.
|
|
2514
|
+
*
|
|
2515
|
+
* @param tenantId - Tenant identifier (used for isolation check)
|
|
2516
|
+
* @param installationId - Installation ID to update
|
|
2517
|
+
* @param updates - {@link UpdateChannelInstallationRequest} with fields to patch
|
|
2518
|
+
* @returns The updated {@link ChannelInstallation} or `null` if not found or tenant mismatch
|
|
2519
|
+
*/
|
|
2509
2520
|
async updateInstallation(tenantId, installationId, updates) {
|
|
2510
2521
|
const existing = this.installations.get(installationId);
|
|
2511
2522
|
if (!existing || existing.tenantId !== tenantId) return null;
|
|
@@ -2521,11 +2532,21 @@ var InMemoryChannelInstallationStore = class {
|
|
|
2521
2532
|
this.installations.set(installationId, updated);
|
|
2522
2533
|
return updated;
|
|
2523
2534
|
}
|
|
2535
|
+
/**
|
|
2536
|
+
* Deletes a channel installation.
|
|
2537
|
+
*
|
|
2538
|
+
* @param tenantId - Tenant identifier (used for isolation check)
|
|
2539
|
+
* @param installationId - Installation ID to delete
|
|
2540
|
+
* @returns `true` if deleted, `false` if not found or tenant mismatch
|
|
2541
|
+
*/
|
|
2524
2542
|
async deleteInstallation(tenantId, installationId) {
|
|
2525
2543
|
const existing = this.installations.get(installationId);
|
|
2526
2544
|
if (!existing || existing.tenantId !== tenantId) return false;
|
|
2527
2545
|
return this.installations.delete(installationId);
|
|
2528
2546
|
}
|
|
2547
|
+
/**
|
|
2548
|
+
* Clears all in-memory installations. Primarily used in tests.
|
|
2549
|
+
*/
|
|
2529
2550
|
clear() {
|
|
2530
2551
|
this.installations.clear();
|
|
2531
2552
|
}
|
|
@@ -2537,6 +2558,16 @@ var InMemoryBindingStore = class {
|
|
|
2537
2558
|
constructor() {
|
|
2538
2559
|
this.bindings = /* @__PURE__ */ new Map();
|
|
2539
2560
|
}
|
|
2561
|
+
/**
|
|
2562
|
+
* Resolves a binding for the given sender across a specific channel installation.
|
|
2563
|
+
*
|
|
2564
|
+
* Called by `MessageRouter.dispatch()` during inbound message processing.
|
|
2565
|
+
* Matches on `channel + senderId + channelInstallationId + tenantId` and
|
|
2566
|
+
* requires `enabled === true`.
|
|
2567
|
+
*
|
|
2568
|
+
* @param params - Resolution parameters
|
|
2569
|
+
* @returns The matching {@link Binding} or `null` if none found.
|
|
2570
|
+
*/
|
|
2540
2571
|
async resolve(params) {
|
|
2541
2572
|
for (const binding of this.bindings.values()) {
|
|
2542
2573
|
if (binding.channel === params.channel && binding.senderId === params.senderId && binding.channelInstallationId === params.channelInstallationId && binding.tenantId === params.tenantId && binding.enabled) {
|
|
@@ -2545,6 +2576,12 @@ var InMemoryBindingStore = class {
|
|
|
2545
2576
|
}
|
|
2546
2577
|
return null;
|
|
2547
2578
|
}
|
|
2579
|
+
/**
|
|
2580
|
+
* Creates a new sender-to-agent binding.
|
|
2581
|
+
*
|
|
2582
|
+
* @param input - {@link CreateBindingInput} defining channel, sender, target agent, and thread mode.
|
|
2583
|
+
* @returns The newly created {@link Binding}.
|
|
2584
|
+
*/
|
|
2548
2585
|
async create(input) {
|
|
2549
2586
|
const now = /* @__PURE__ */ new Date();
|
|
2550
2587
|
const binding = {
|
|
@@ -2567,6 +2604,14 @@ var InMemoryBindingStore = class {
|
|
|
2567
2604
|
this.bindings.set(binding.id, binding);
|
|
2568
2605
|
return binding;
|
|
2569
2606
|
}
|
|
2607
|
+
/**
|
|
2608
|
+
* Updates an existing binding (e.g. changing the target agent or thread mode).
|
|
2609
|
+
*
|
|
2610
|
+
* @param id - Binding ID
|
|
2611
|
+
* @param patch - Partial {@link Binding} fields to update
|
|
2612
|
+
* @returns The updated {@link Binding}
|
|
2613
|
+
* @throws {Error} If the binding does not exist
|
|
2614
|
+
*/
|
|
2570
2615
|
async update(id, patch) {
|
|
2571
2616
|
const existing = this.bindings.get(id);
|
|
2572
2617
|
if (!existing) throw new Error(`Binding ${id} not found`);
|
|
@@ -2578,9 +2623,20 @@ var InMemoryBindingStore = class {
|
|
|
2578
2623
|
this.bindings.set(id, updated);
|
|
2579
2624
|
return updated;
|
|
2580
2625
|
}
|
|
2626
|
+
/**
|
|
2627
|
+
* Deletes a binding by ID.
|
|
2628
|
+
*
|
|
2629
|
+
* @param id - Binding ID
|
|
2630
|
+
*/
|
|
2581
2631
|
async delete(id) {
|
|
2582
2632
|
this.bindings.delete(id);
|
|
2583
2633
|
}
|
|
2634
|
+
/**
|
|
2635
|
+
* Lists bindings filtered by tenant and optional channel/agent/installation.
|
|
2636
|
+
*
|
|
2637
|
+
* @param params - Filter and pagination parameters
|
|
2638
|
+
* @returns Array of matching {@link Binding} objects
|
|
2639
|
+
*/
|
|
2584
2640
|
async list(params) {
|
|
2585
2641
|
let results = Array.from(this.bindings.values()).filter((b) => {
|
|
2586
2642
|
if (b.tenantId !== params.tenantId) return false;
|
|
@@ -2593,6 +2649,12 @@ var InMemoryBindingStore = class {
|
|
|
2593
2649
|
const limit = params.limit ?? 50;
|
|
2594
2650
|
return results.slice(offset, offset + limit);
|
|
2595
2651
|
}
|
|
2652
|
+
/**
|
|
2653
|
+
* Bulk-imports bindings.
|
|
2654
|
+
*
|
|
2655
|
+
* @param bindings - Array of {@link CreateBindingInput}
|
|
2656
|
+
* @returns Array of created {@link Binding} objects
|
|
2657
|
+
*/
|
|
2596
2658
|
async import(bindings) {
|
|
2597
2659
|
const result = [];
|
|
2598
2660
|
for (const input of bindings) {
|
|
@@ -2600,9 +2662,18 @@ var InMemoryBindingStore = class {
|
|
|
2600
2662
|
}
|
|
2601
2663
|
return result;
|
|
2602
2664
|
}
|
|
2665
|
+
/**
|
|
2666
|
+
* Exports all bindings for a tenant.
|
|
2667
|
+
*
|
|
2668
|
+
* @param params - Filter by tenantId
|
|
2669
|
+
* @returns Array of {@link Binding} objects
|
|
2670
|
+
*/
|
|
2603
2671
|
async export(params) {
|
|
2604
2672
|
return this.list({ tenantId: params.tenantId, limit: 1e4 });
|
|
2605
2673
|
}
|
|
2674
|
+
/**
|
|
2675
|
+
* Clears all in-memory bindings. Primarily used in tests.
|
|
2676
|
+
*/
|
|
2606
2677
|
clear() {
|
|
2607
2678
|
this.bindings.clear();
|
|
2608
2679
|
}
|
|
@@ -3225,7 +3296,6 @@ var SqlDatabaseManager = class _SqlDatabaseManager {
|
|
|
3225
3296
|
constructor() {
|
|
3226
3297
|
this.databases = /* @__PURE__ */ new Map();
|
|
3227
3298
|
this.defaultDatabaseKeys = /* @__PURE__ */ new Map();
|
|
3228
|
-
this.configStore = null;
|
|
3229
3299
|
}
|
|
3230
3300
|
/**
|
|
3231
3301
|
* Get the singleton instance
|
|
@@ -3285,16 +3355,9 @@ var SqlDatabaseManager = class _SqlDatabaseManager {
|
|
|
3285
3355
|
}
|
|
3286
3356
|
this.defaultDatabaseKeys.set(tenantId, key);
|
|
3287
3357
|
}
|
|
3288
|
-
/**
|
|
3289
|
-
* Set the configuration store for on-demand database loading
|
|
3290
|
-
* @param store - The database configuration store
|
|
3291
|
-
*/
|
|
3292
|
-
setConfigStore(store) {
|
|
3293
|
-
this.configStore = store;
|
|
3294
|
-
}
|
|
3295
3358
|
/**
|
|
3296
3359
|
* Get a database by key for a specific tenant
|
|
3297
|
-
* If database is not registered
|
|
3360
|
+
* If database is not registered, tries to load from the store lattice
|
|
3298
3361
|
* @param tenantId - Tenant identifier (required)
|
|
3299
3362
|
* @param key - Database key (optional, uses default if not provided)
|
|
3300
3363
|
* @returns ISqlDatabase instance
|
|
@@ -3312,8 +3375,10 @@ var SqlDatabaseManager = class _SqlDatabaseManager {
|
|
|
3312
3375
|
return database;
|
|
3313
3376
|
}
|
|
3314
3377
|
}
|
|
3315
|
-
|
|
3316
|
-
const
|
|
3378
|
+
try {
|
|
3379
|
+
const { store } = getStoreLattice("default", "database");
|
|
3380
|
+
const configStore = store;
|
|
3381
|
+
const configEntry = await configStore.getConfigByKey(tenantId, dbKey);
|
|
3317
3382
|
if (configEntry) {
|
|
3318
3383
|
this.registerDatabase(tenantId, dbKey, configEntry.config);
|
|
3319
3384
|
if (!this.defaultDatabaseKeys.has(tenantId)) {
|
|
@@ -3327,6 +3392,7 @@ var SqlDatabaseManager = class _SqlDatabaseManager {
|
|
|
3327
3392
|
}
|
|
3328
3393
|
}
|
|
3329
3394
|
}
|
|
3395
|
+
} catch {
|
|
3330
3396
|
}
|
|
3331
3397
|
if (!tenantDbs) {
|
|
3332
3398
|
throw new Error(`No databases registered for tenant '${tenantId}'`);
|
|
@@ -4436,6 +4502,7 @@ var MetricsServerManager = class _MetricsServerManager {
|
|
|
4436
4502
|
this.clients = /* @__PURE__ */ new Map();
|
|
4437
4503
|
this.configs = /* @__PURE__ */ new Map();
|
|
4438
4504
|
this.defaultServerKeys = /* @__PURE__ */ new Map();
|
|
4505
|
+
this._loadingPromise = null;
|
|
4439
4506
|
}
|
|
4440
4507
|
/**
|
|
4441
4508
|
* Get the singleton instance
|
|
@@ -4446,6 +4513,32 @@ var MetricsServerManager = class _MetricsServerManager {
|
|
|
4446
4513
|
}
|
|
4447
4514
|
return _MetricsServerManager.instance;
|
|
4448
4515
|
}
|
|
4516
|
+
/**
|
|
4517
|
+
* Ensure configurations are loaded from the store lattice.
|
|
4518
|
+
* Uses a promise-lock to prevent concurrent loads.
|
|
4519
|
+
*/
|
|
4520
|
+
async _ensureLoaded() {
|
|
4521
|
+
if (this.clients.size > 0) {
|
|
4522
|
+
return;
|
|
4523
|
+
}
|
|
4524
|
+
if (this._loadingPromise) {
|
|
4525
|
+
return this._loadingPromise;
|
|
4526
|
+
}
|
|
4527
|
+
this._loadingPromise = (async () => {
|
|
4528
|
+
try {
|
|
4529
|
+
const { store } = getStoreLattice("default", "metrics");
|
|
4530
|
+
const configStore = store;
|
|
4531
|
+
const configs = await configStore.getAllConfigsWithoutTenant();
|
|
4532
|
+
for (const entry of configs) {
|
|
4533
|
+
const tenantId = entry.tenantId || "default";
|
|
4534
|
+
this.registerServer(tenantId, entry.key, entry.config);
|
|
4535
|
+
}
|
|
4536
|
+
} finally {
|
|
4537
|
+
this._loadingPromise = null;
|
|
4538
|
+
}
|
|
4539
|
+
})();
|
|
4540
|
+
return this._loadingPromise;
|
|
4541
|
+
}
|
|
4449
4542
|
/**
|
|
4450
4543
|
* Get or create tenant clients map
|
|
4451
4544
|
*/
|
|
@@ -4514,7 +4607,8 @@ var MetricsServerManager = class _MetricsServerManager {
|
|
|
4514
4607
|
* @param tenantId - Tenant identifier
|
|
4515
4608
|
* @param key - Server key (optional, uses default if not provided)
|
|
4516
4609
|
*/
|
|
4517
|
-
getClient(tenantId, key) {
|
|
4610
|
+
async getClient(tenantId, key) {
|
|
4611
|
+
await this._ensureLoaded();
|
|
4518
4612
|
const tenantClients = this.clients.get(tenantId);
|
|
4519
4613
|
if (!tenantClients) {
|
|
4520
4614
|
throw new Error(`No metrics servers registered for tenant '${tenantId}'`);
|
|
@@ -4534,7 +4628,8 @@ var MetricsServerManager = class _MetricsServerManager {
|
|
|
4534
4628
|
* @param tenantId - Tenant identifier
|
|
4535
4629
|
* @param key - Server key (optional, uses default if not provided)
|
|
4536
4630
|
*/
|
|
4537
|
-
getConfig(tenantId, key) {
|
|
4631
|
+
async getConfig(tenantId, key) {
|
|
4632
|
+
await this._ensureLoaded();
|
|
4538
4633
|
const tenantConfigs = this.configs.get(tenantId);
|
|
4539
4634
|
if (!tenantConfigs) {
|
|
4540
4635
|
throw new Error(`No metrics servers registered for tenant '${tenantId}'`);
|
|
@@ -4562,7 +4657,8 @@ var MetricsServerManager = class _MetricsServerManager {
|
|
|
4562
4657
|
* Get all registered metrics server keys with their types for a tenant
|
|
4563
4658
|
* @param tenantId - Tenant identifier
|
|
4564
4659
|
*/
|
|
4565
|
-
getServerKeys(tenantId) {
|
|
4660
|
+
async getServerKeys(tenantId) {
|
|
4661
|
+
await this._ensureLoaded();
|
|
4566
4662
|
const tenantConfigs = this.configs.get(tenantId);
|
|
4567
4663
|
if (!tenantConfigs) {
|
|
4568
4664
|
return [];
|
|
@@ -4629,20 +4725,6 @@ var MetricsServerManager = class _MetricsServerManager {
|
|
|
4629
4725
|
this.registerServer(tenantId, entry.key, entry.config);
|
|
4630
4726
|
}
|
|
4631
4727
|
}
|
|
4632
|
-
/**
|
|
4633
|
-
* Load all metrics server configurations from a store
|
|
4634
|
-
* across all tenants and register them with this manager
|
|
4635
|
-
*
|
|
4636
|
-
* @param store - The metrics server configuration store
|
|
4637
|
-
* @deprecated Use loadConfigsFromStore with specific tenant instead
|
|
4638
|
-
*/
|
|
4639
|
-
async loadAllConfigsFromStore(store) {
|
|
4640
|
-
const configs = await store.getAllConfigsWithoutTenant();
|
|
4641
|
-
for (const entry of configs) {
|
|
4642
|
-
const tenantId = entry.tenantId || "default";
|
|
4643
|
-
this.registerServer(tenantId, entry.key, entry.config);
|
|
4644
|
-
}
|
|
4645
|
-
}
|
|
4646
4728
|
};
|
|
4647
4729
|
var metricsServerManager = MetricsServerManager.getInstance();
|
|
4648
4730
|
|
|
@@ -4661,7 +4743,7 @@ ${serverKeys.map(
|
|
|
4661
4743
|
async (_input, _exeConfig) => {
|
|
4662
4744
|
try {
|
|
4663
4745
|
const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId2);
|
|
4664
|
-
const servers = metricsServerManager.getServerKeys(tenantId);
|
|
4746
|
+
const servers = await metricsServerManager.getServerKeys(tenantId);
|
|
4665
4747
|
if (servers.length === 0) {
|
|
4666
4748
|
return "No metrics servers registered.";
|
|
4667
4749
|
}
|
|
@@ -4700,7 +4782,7 @@ ${serverKeys.map(
|
|
|
4700
4782
|
const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId2);
|
|
4701
4783
|
let effectiveServerKeys = serverKeys;
|
|
4702
4784
|
if (connectAll) {
|
|
4703
|
-
effectiveServerKeys = metricsServerManager.getServerKeys(tenantId).map((s) => s.key);
|
|
4785
|
+
effectiveServerKeys = (await metricsServerManager.getServerKeys(tenantId)).map((s) => s.key);
|
|
4704
4786
|
}
|
|
4705
4787
|
const filteredServerKeys = filterServerKeysByTenant(effectiveServerKeys, tenantId);
|
|
4706
4788
|
const runConfig = _exeConfig?.configurable?.runConfig || {};
|
|
@@ -4723,12 +4805,12 @@ To view all available data sources, please clear the current selection or reopen
|
|
|
4723
4805
|
const allDataSources = [];
|
|
4724
4806
|
for (const serverKey of filteredServerKeys) {
|
|
4725
4807
|
try {
|
|
4726
|
-
const config = metricsServerManager.getConfig(tenantId, serverKey);
|
|
4808
|
+
const config = await metricsServerManager.getConfig(tenantId, serverKey);
|
|
4727
4809
|
if (config.type !== "semantic") {
|
|
4728
4810
|
console.warn(`Server "${serverKey}" is not a semantic metrics server, skipping.`);
|
|
4729
4811
|
continue;
|
|
4730
4812
|
}
|
|
4731
|
-
const client = metricsServerManager.getClient(tenantId, serverKey);
|
|
4813
|
+
const client = await metricsServerManager.getClient(tenantId, serverKey);
|
|
4732
4814
|
const dataSources = await client.getDataSources();
|
|
4733
4815
|
const selectedIds = config.selectedDataSources || [];
|
|
4734
4816
|
const filteredDataSources = selectedIds.length > 0 ? dataSources.filter((ds) => selectedIds.includes(String(ds.id))) : dataSources;
|
|
@@ -4819,7 +4901,7 @@ ${serverKeys.map(
|
|
|
4819
4901
|
const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId2);
|
|
4820
4902
|
let effectiveServerKeys = serverKeys;
|
|
4821
4903
|
if (connectAll) {
|
|
4822
|
-
effectiveServerKeys = metricsServerManager.getServerKeys(tenantId).map((s) => s.key);
|
|
4904
|
+
effectiveServerKeys = (await metricsServerManager.getServerKeys(tenantId)).map((s) => s.key);
|
|
4823
4905
|
}
|
|
4824
4906
|
const filteredServerKeys = filterServerKeysByTenant(effectiveServerKeys, tenantId);
|
|
4825
4907
|
const runConfig = _exeConfig?.configurable?.runConfig || {};
|
|
@@ -4831,11 +4913,11 @@ ${serverKeys.map(
|
|
|
4831
4913
|
if (!filteredServerKeys.includes(serverKey)) {
|
|
4832
4914
|
return `Error: serverKey "${serverKey}" is not available for tenant "${tenantId}". Available servers: [${filteredServerKeys.join(", ")}]`;
|
|
4833
4915
|
}
|
|
4834
|
-
const config = metricsServerManager.getConfig(tenantId, serverKey);
|
|
4916
|
+
const config = await metricsServerManager.getConfig(tenantId, serverKey);
|
|
4835
4917
|
if (config.type !== "semantic") {
|
|
4836
4918
|
return `Error: Server "${serverKey}" is not a semantic metrics server. This tool only works with semantic servers.`;
|
|
4837
4919
|
}
|
|
4838
|
-
const client = metricsServerManager.getClient(tenantId, serverKey);
|
|
4920
|
+
const client = await metricsServerManager.getClient(tenantId, serverKey);
|
|
4839
4921
|
const targetDatasourceIds = datasourceIds && datasourceIds.length > 0 ? datasourceIds : metricsDataSource?.datasourceId ? [metricsDataSource.datasourceId] : client.getSelectedDataSources();
|
|
4840
4922
|
if (targetDatasourceIds.length === 0) {
|
|
4841
4923
|
return `Error: No data sources specified and no default data sources configured for server "${serverKey}".`;
|
|
@@ -4977,7 +5059,7 @@ ${serverKeys.map(
|
|
|
4977
5059
|
const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId2);
|
|
4978
5060
|
let effectiveServerKeys = serverKeys;
|
|
4979
5061
|
if (connectAll) {
|
|
4980
|
-
effectiveServerKeys = metricsServerManager.getServerKeys(tenantId).map((s) => s.key);
|
|
5062
|
+
effectiveServerKeys = (await metricsServerManager.getServerKeys(tenantId)).map((s) => s.key);
|
|
4981
5063
|
}
|
|
4982
5064
|
const filteredServerKeys = filterServerKeysByTenant(effectiveServerKeys, tenantId);
|
|
4983
5065
|
const runConfig = _exeConfig?.configurable?.runConfig || {};
|
|
@@ -4993,11 +5075,11 @@ ${serverKeys.map(
|
|
|
4993
5075
|
if (!metricName) {
|
|
4994
5076
|
return "Error: metricName parameter is required.";
|
|
4995
5077
|
}
|
|
4996
|
-
const config = metricsServerManager.getConfig(tenantId, serverKey);
|
|
5078
|
+
const config = await metricsServerManager.getConfig(tenantId, serverKey);
|
|
4997
5079
|
if (config.type !== "semantic") {
|
|
4998
5080
|
return `Error: Server "${serverKey}" is not a semantic metrics server. This tool only works with semantic servers.`;
|
|
4999
5081
|
}
|
|
5000
|
-
const client = metricsServerManager.getClient(tenantId, serverKey);
|
|
5082
|
+
const client = await metricsServerManager.getClient(tenantId, serverKey);
|
|
5001
5083
|
const targetDatasourceIds = datasourceId ? [datasourceId] : client.getSelectedDataSources();
|
|
5002
5084
|
if (targetDatasourceIds.length === 0) {
|
|
5003
5085
|
return `Error: No datasourceId specified and no default data sources configured for server "${serverKey}".`;
|
|
@@ -5213,7 +5295,7 @@ ${serverKeys.map(
|
|
|
5213
5295
|
const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId2);
|
|
5214
5296
|
let effectiveServerKeys = serverKeys;
|
|
5215
5297
|
if (connectAll) {
|
|
5216
|
-
effectiveServerKeys = metricsServerManager.getServerKeys(tenantId).map((s) => s.key);
|
|
5298
|
+
effectiveServerKeys = (await metricsServerManager.getServerKeys(tenantId)).map((s) => s.key);
|
|
5217
5299
|
}
|
|
5218
5300
|
const filteredServerKeys = filterServerKeysByTenant(effectiveServerKeys, tenantId);
|
|
5219
5301
|
const runConfig = _exeConfig?.configurable?.runConfig || {};
|
|
@@ -5232,11 +5314,11 @@ ${serverKeys.map(
|
|
|
5232
5314
|
if (!metrics || metrics.length === 0) {
|
|
5233
5315
|
return "Error: metrics parameter is required (at least one metric name).";
|
|
5234
5316
|
}
|
|
5235
|
-
const config = metricsServerManager.getConfig(tenantId, serverKey);
|
|
5317
|
+
const config = await metricsServerManager.getConfig(tenantId, serverKey);
|
|
5236
5318
|
if (config.type !== "semantic") {
|
|
5237
5319
|
return `Error: Server "${serverKey}" is not a semantic metrics server. This tool only works with semantic servers.`;
|
|
5238
5320
|
}
|
|
5239
|
-
const client = metricsServerManager.getClient(tenantId, serverKey);
|
|
5321
|
+
const client = await metricsServerManager.getClient(tenantId, serverKey);
|
|
5240
5322
|
const semanticFilters = (filters || []).map((f) => ({
|
|
5241
5323
|
dimension: f.dimension,
|
|
5242
5324
|
operator: f.operator,
|
|
@@ -5294,7 +5376,7 @@ ${serverKeys.map(
|
|
|
5294
5376
|
const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId2);
|
|
5295
5377
|
let effectiveServerKeys = serverKeys;
|
|
5296
5378
|
if (connectAll) {
|
|
5297
|
-
effectiveServerKeys = metricsServerManager.getServerKeys(tenantId).map((s) => s.key);
|
|
5379
|
+
effectiveServerKeys = (await metricsServerManager.getServerKeys(tenantId)).map((s) => s.key);
|
|
5298
5380
|
}
|
|
5299
5381
|
const filteredServerKeys = filterServerKeysByTenant(effectiveServerKeys, tenantId);
|
|
5300
5382
|
const runConfig = _exeConfig?.configurable?.runConfig || {};
|
|
@@ -5306,11 +5388,11 @@ ${serverKeys.map(
|
|
|
5306
5388
|
if (!filteredServerKeys.includes(serverKey)) {
|
|
5307
5389
|
return `Error: serverKey "${serverKey}" is not available for tenant "${tenantId}". Available servers: [${filteredServerKeys.join(", ")}]`;
|
|
5308
5390
|
}
|
|
5309
|
-
const config = metricsServerManager.getConfig(tenantId, serverKey);
|
|
5391
|
+
const config = await metricsServerManager.getConfig(tenantId, serverKey);
|
|
5310
5392
|
if (config.type !== "semantic") {
|
|
5311
5393
|
return `Error: Server "${serverKey}" is not a semantic metrics server. This tool only works with semantic servers.`;
|
|
5312
5394
|
}
|
|
5313
|
-
const client = metricsServerManager.getClient(tenantId, serverKey);
|
|
5395
|
+
const client = await metricsServerManager.getClient(tenantId, serverKey);
|
|
5314
5396
|
const targetDatasourceIds = datasourceIds && datasourceIds.length > 0 ? datasourceIds : metricsDataSource?.datasourceId ? [metricsDataSource.datasourceId] : client.getSelectedDataSources();
|
|
5315
5397
|
if (targetDatasourceIds.length === 0) {
|
|
5316
5398
|
return `Error: No data sources specified and no default data sources configured for server "${serverKey}".`;
|
|
@@ -5399,7 +5481,7 @@ ${serverKeys.map(
|
|
|
5399
5481
|
const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId2);
|
|
5400
5482
|
let effectiveServerKeys = serverKeys;
|
|
5401
5483
|
if (connectAll) {
|
|
5402
|
-
effectiveServerKeys = metricsServerManager.getServerKeys(tenantId).map((s) => s.key);
|
|
5484
|
+
effectiveServerKeys = (await metricsServerManager.getServerKeys(tenantId)).map((s) => s.key);
|
|
5403
5485
|
}
|
|
5404
5486
|
const filteredServerKeys = filterServerKeysByTenant(effectiveServerKeys, tenantId);
|
|
5405
5487
|
const runConfig = _exeConfig?.configurable?.runConfig || {};
|
|
@@ -5415,11 +5497,11 @@ ${serverKeys.map(
|
|
|
5415
5497
|
if (!tableName) {
|
|
5416
5498
|
return "Error: tableName parameter is required.";
|
|
5417
5499
|
}
|
|
5418
|
-
const config = metricsServerManager.getConfig(tenantId, serverKey);
|
|
5500
|
+
const config = await metricsServerManager.getConfig(tenantId, serverKey);
|
|
5419
5501
|
if (config.type !== "semantic") {
|
|
5420
5502
|
return `Error: Server "${serverKey}" is not a semantic metrics server. This tool only works with semantic servers.`;
|
|
5421
5503
|
}
|
|
5422
|
-
const client = metricsServerManager.getClient(tenantId, serverKey);
|
|
5504
|
+
const client = await metricsServerManager.getClient(tenantId, serverKey);
|
|
5423
5505
|
const targetDatasourceIds = datasourceId ? [datasourceId] : client.getSelectedDataSources();
|
|
5424
5506
|
if (targetDatasourceIds.length === 0) {
|
|
5425
5507
|
return `Error: No datasourceId specified and no default data sources configured for server "${serverKey}".`;
|
|
@@ -5539,7 +5621,7 @@ ${serverKeys.map(
|
|
|
5539
5621
|
const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId2);
|
|
5540
5622
|
let effectiveServerKeys = serverKeys;
|
|
5541
5623
|
if (connectAll) {
|
|
5542
|
-
effectiveServerKeys = metricsServerManager.getServerKeys(tenantId).map((s) => s.key);
|
|
5624
|
+
effectiveServerKeys = (await metricsServerManager.getServerKeys(tenantId)).map((s) => s.key);
|
|
5543
5625
|
}
|
|
5544
5626
|
const filteredServerKeys = filterServerKeysByTenant(effectiveServerKeys, tenantId);
|
|
5545
5627
|
const runConfig = _exeConfig?.configurable?.runConfig || {};
|
|
@@ -5558,11 +5640,11 @@ ${serverKeys.map(
|
|
|
5558
5640
|
if (!customSql || customSql.trim().length === 0) {
|
|
5559
5641
|
return "Error: customSql parameter is required and cannot be empty.";
|
|
5560
5642
|
}
|
|
5561
|
-
const config = metricsServerManager.getConfig(tenantId, serverKey);
|
|
5643
|
+
const config = await metricsServerManager.getConfig(tenantId, serverKey);
|
|
5562
5644
|
if (config.type !== "semantic") {
|
|
5563
5645
|
return `Error: Server "${serverKey}" is not a semantic metrics server. This tool only works with semantic servers.`;
|
|
5564
5646
|
}
|
|
5565
|
-
const client = metricsServerManager.getClient(tenantId, serverKey);
|
|
5647
|
+
const client = await metricsServerManager.getClient(tenantId, serverKey);
|
|
5566
5648
|
const result = await client.executeSqlQuery({
|
|
5567
5649
|
datasourceId,
|
|
5568
5650
|
customSql,
|
|
@@ -11913,6 +11995,14 @@ var ThreadStatus2 = /* @__PURE__ */ ((ThreadStatus3) => {
|
|
|
11913
11995
|
return ThreadStatus3;
|
|
11914
11996
|
})(ThreadStatus2 || {});
|
|
11915
11997
|
var Agent = class {
|
|
11998
|
+
/**
|
|
11999
|
+
* Constructs an Agent instance.
|
|
12000
|
+
*
|
|
12001
|
+
* Prefer {@link AgentInstanceManager.getAgent} over direct construction — it
|
|
12002
|
+
* ensures a single instance per thread.
|
|
12003
|
+
*
|
|
12004
|
+
* @param params - {@link AgentThreadInterface}
|
|
12005
|
+
*/
|
|
11916
12006
|
constructor({
|
|
11917
12007
|
assistant_id,
|
|
11918
12008
|
thread_id,
|
|
@@ -12122,9 +12212,10 @@ var Agent = class {
|
|
|
12122
12212
|
command: p.command,
|
|
12123
12213
|
custom_run_config: p.custom_run_config ?? queueMessageData.custom_run_config
|
|
12124
12214
|
}, signal);
|
|
12125
|
-
await this.queueStore?.
|
|
12215
|
+
await this.queueStore?.removeMessage(p.id);
|
|
12126
12216
|
const runStatus = await this.getRunStatus();
|
|
12127
12217
|
const state = await this.getCurrentState();
|
|
12218
|
+
const customRunConfig = p.custom_run_config ?? queueMessageData.custom_run_config;
|
|
12128
12219
|
if (runStatus === "interrupted" /* INTERRUPTED */) {
|
|
12129
12220
|
this.publish("message:interrupted", {
|
|
12130
12221
|
type: "message:interrupted",
|
|
@@ -12149,6 +12240,12 @@ var Agent = class {
|
|
|
12149
12240
|
state
|
|
12150
12241
|
});
|
|
12151
12242
|
}
|
|
12243
|
+
this.publish("reply:ready", {
|
|
12244
|
+
type: "reply:ready",
|
|
12245
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
12246
|
+
state,
|
|
12247
|
+
customRunConfig
|
|
12248
|
+
});
|
|
12152
12249
|
} catch (error) {
|
|
12153
12250
|
console.error(`STEER/Command message ${p.id} execution failed:`, error);
|
|
12154
12251
|
this.addChunk({
|
|
@@ -12164,7 +12261,8 @@ var Agent = class {
|
|
|
12164
12261
|
error: error instanceof Error ? error.message : String(error),
|
|
12165
12262
|
timestamp: /* @__PURE__ */ new Date()
|
|
12166
12263
|
});
|
|
12167
|
-
|
|
12264
|
+
await this.queueStore?.removeMessage(p.id);
|
|
12265
|
+
continue;
|
|
12168
12266
|
}
|
|
12169
12267
|
}
|
|
12170
12268
|
}
|
|
@@ -12200,7 +12298,7 @@ var Agent = class {
|
|
|
12200
12298
|
const runStatus = await this.getRunStatus();
|
|
12201
12299
|
const state = await this.getCurrentState();
|
|
12202
12300
|
for (const p of remainingPendings) {
|
|
12203
|
-
await this.queueStore?.
|
|
12301
|
+
await this.queueStore?.removeMessage(p.id);
|
|
12204
12302
|
if (runStatus === "interrupted" /* INTERRUPTED */) {
|
|
12205
12303
|
this.publish("message:interrupted", {
|
|
12206
12304
|
type: "message:interrupted",
|
|
@@ -12226,6 +12324,12 @@ var Agent = class {
|
|
|
12226
12324
|
});
|
|
12227
12325
|
}
|
|
12228
12326
|
}
|
|
12327
|
+
this.publish("reply:ready", {
|
|
12328
|
+
type: "reply:ready",
|
|
12329
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
12330
|
+
state,
|
|
12331
|
+
customRunConfig: remainingPendings[0]?.custom_run_config ?? firstQueueMessage?.custom_run_config
|
|
12332
|
+
});
|
|
12229
12333
|
} catch (error) {
|
|
12230
12334
|
console.error(`COLLECT mode execution failed:`, error);
|
|
12231
12335
|
for (const p of remainingPendings) {
|
|
@@ -12242,8 +12346,8 @@ var Agent = class {
|
|
|
12242
12346
|
error: error instanceof Error ? error.message : String(error),
|
|
12243
12347
|
timestamp: /* @__PURE__ */ new Date()
|
|
12244
12348
|
});
|
|
12349
|
+
await this.queueStore?.removeMessage(p.id);
|
|
12245
12350
|
}
|
|
12246
|
-
throw error;
|
|
12247
12351
|
}
|
|
12248
12352
|
} else if (this.queueMode.mode === "followup" /* FOLLOWUP */) {
|
|
12249
12353
|
for (const p of remainingPendings) {
|
|
@@ -12271,9 +12375,10 @@ var Agent = class {
|
|
|
12271
12375
|
input,
|
|
12272
12376
|
custom_run_config: p.custom_run_config ?? queueMessageData.custom_run_config
|
|
12273
12377
|
}, signal);
|
|
12274
|
-
await this.queueStore?.
|
|
12378
|
+
await this.queueStore?.removeMessage(p.id);
|
|
12275
12379
|
const runStatus = await this.getRunStatus();
|
|
12276
12380
|
const state = await this.getCurrentState();
|
|
12381
|
+
const customRunConfig = p.custom_run_config ?? queueMessageData.custom_run_config;
|
|
12277
12382
|
if (runStatus === "interrupted" /* INTERRUPTED */) {
|
|
12278
12383
|
this.publish("message:interrupted", {
|
|
12279
12384
|
type: "message:interrupted",
|
|
@@ -12298,6 +12403,12 @@ var Agent = class {
|
|
|
12298
12403
|
state
|
|
12299
12404
|
});
|
|
12300
12405
|
}
|
|
12406
|
+
this.publish("reply:ready", {
|
|
12407
|
+
type: "reply:ready",
|
|
12408
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
12409
|
+
state,
|
|
12410
|
+
customRunConfig
|
|
12411
|
+
});
|
|
12301
12412
|
} catch (error) {
|
|
12302
12413
|
console.error(`FOLLOWUP mode message ${p.id} execution failed:`, error);
|
|
12303
12414
|
this.addChunk({
|
|
@@ -12313,7 +12424,8 @@ var Agent = class {
|
|
|
12313
12424
|
error: error instanceof Error ? error.message : String(error),
|
|
12314
12425
|
timestamp: /* @__PURE__ */ new Date()
|
|
12315
12426
|
});
|
|
12316
|
-
|
|
12427
|
+
await this.queueStore?.removeMessage(p.id);
|
|
12428
|
+
continue;
|
|
12317
12429
|
}
|
|
12318
12430
|
}
|
|
12319
12431
|
}
|
|
@@ -12339,9 +12451,25 @@ var Agent = class {
|
|
|
12339
12451
|
setQueueStore(store) {
|
|
12340
12452
|
this.queueStore = store;
|
|
12341
12453
|
}
|
|
12454
|
+
/**
|
|
12455
|
+
* Push a chunk into the streaming buffer for this thread.
|
|
12456
|
+
*
|
|
12457
|
+
* Consumers read chunks via {@link chunkStream}.
|
|
12458
|
+
*
|
|
12459
|
+
* @param content - The message chunk to buffer
|
|
12460
|
+
*/
|
|
12342
12461
|
addChunk(content) {
|
|
12343
12462
|
return this.chunkBuffer.addChunk(this.thread_id, content);
|
|
12344
12463
|
}
|
|
12464
|
+
/**
|
|
12465
|
+
* Returns an async iterator over new chunks since the given message ID.
|
|
12466
|
+
*
|
|
12467
|
+
* Used by SSE endpoints to stream agent output to clients in real time.
|
|
12468
|
+
*
|
|
12469
|
+
* @param message_id - The client message ID to start streaming from
|
|
12470
|
+
* @param stopTypes - Optional chunk types that terminate the stream
|
|
12471
|
+
* @returns An async iterable yielding {@link MessageChunk} objects
|
|
12472
|
+
*/
|
|
12345
12473
|
chunkStream(message_id, stopTypes) {
|
|
12346
12474
|
const stream = this.chunkBuffer.getNewChunksSinceContentIterator(
|
|
12347
12475
|
this.thread_id,
|
|
@@ -12430,13 +12558,21 @@ var Agent = class {
|
|
|
12430
12558
|
};
|
|
12431
12559
|
}
|
|
12432
12560
|
/**
|
|
12433
|
-
*
|
|
12561
|
+
* Override the thread's queue processing mode.
|
|
12562
|
+
*
|
|
12563
|
+
* @param config - Partial {@link ThreadQueueConfig} (e.g. `{ mode: QueueMode.FOLLOWUP }`)
|
|
12434
12564
|
*/
|
|
12435
12565
|
async setQueueConfig(config) {
|
|
12436
12566
|
this.queueMode = { ...this.queueMode, ...config };
|
|
12437
12567
|
}
|
|
12438
12568
|
/**
|
|
12439
|
-
*
|
|
12569
|
+
* Abort any ongoing queue processing without clearing the queue.
|
|
12570
|
+
*
|
|
12571
|
+
* Used internally by STEER mode to interrupt the current execution so the
|
|
12572
|
+
* steer message can be processed next. For a full abort that also clears
|
|
12573
|
+
* pending messages, use {@link abort}.
|
|
12574
|
+
*
|
|
12575
|
+
* @see {@link abort}
|
|
12440
12576
|
*/
|
|
12441
12577
|
stopQueueProcessor() {
|
|
12442
12578
|
if (this.abortController) {
|
|
@@ -12445,14 +12581,34 @@ var Agent = class {
|
|
|
12445
12581
|
}
|
|
12446
12582
|
}
|
|
12447
12583
|
/**
|
|
12448
|
-
*
|
|
12449
|
-
*
|
|
12450
|
-
*
|
|
12451
|
-
*
|
|
12452
|
-
*
|
|
12453
|
-
*
|
|
12454
|
-
* -
|
|
12455
|
-
* -
|
|
12584
|
+
* Enqueue a message for this thread.
|
|
12585
|
+
*
|
|
12586
|
+
* Messages are always queued; the queue processor starts automatically if idle.
|
|
12587
|
+
* Returns immediately with the message ID — execution is asynchronous.
|
|
12588
|
+
*
|
|
12589
|
+
* **Queue modes** (via the optional `mode` param):
|
|
12590
|
+
* - `COLLECT` (default) — Batch multiple pending messages into one agent call.
|
|
12591
|
+
* - `FOLLOWUP` — Process messages one at a time in order.
|
|
12592
|
+
* - `STEER` — High-priority, inserted at queue head, interrupts current processing.
|
|
12593
|
+
*
|
|
12594
|
+
* **Format**: Supports both `input.message` (legacy string) and `input.messages[]`
|
|
12595
|
+
* (array of `{ role, content }` objects). The array form takes precedence.
|
|
12596
|
+
*
|
|
12597
|
+
* The `custom_run_config` field is round-tripped through the queue and emitted
|
|
12598
|
+
* back in {@link ReplyReadyEvent}, enabling callers to attach routing metadata
|
|
12599
|
+
* (e.g. `_replyTarget` for channel reply).
|
|
12600
|
+
*
|
|
12601
|
+
* @param queueMessage - The message to enqueue
|
|
12602
|
+
* @param mode - Optional queue mode override (defaults to thread's current mode)
|
|
12603
|
+
* @returns `{ queued: true, executed: false, messageId }` — execution happens asynchronously
|
|
12604
|
+
*
|
|
12605
|
+
* @example
|
|
12606
|
+
* ```ts
|
|
12607
|
+
* await agent.addMessage({
|
|
12608
|
+
* input: { message: "Hello" },
|
|
12609
|
+
* custom_run_config: { _replyTarget: { adapterChannel: "lark", rawTarget: { chatId: "xxx" } } },
|
|
12610
|
+
* });
|
|
12611
|
+
* ```
|
|
12456
12612
|
*/
|
|
12457
12613
|
async addMessage(queueMessage, mode) {
|
|
12458
12614
|
const useMode = mode ?? this.queueMode.mode;
|
|
@@ -12546,8 +12702,13 @@ var Agent = class {
|
|
|
12546
12702
|
return { queued: true, executed: false, messageId };
|
|
12547
12703
|
}
|
|
12548
12704
|
/**
|
|
12549
|
-
* Start queue processor if not already running
|
|
12550
|
-
*
|
|
12705
|
+
* Start the queue processor if it is not already running.
|
|
12706
|
+
*
|
|
12707
|
+
* Called automatically by {@link addMessage} and {@link resumeTask}.
|
|
12708
|
+
* Safe to call externally — it is a no-op if processing is already active.
|
|
12709
|
+
*
|
|
12710
|
+
* Emits `thread:busy` before starting, and starts the {@link waitingForQueueEnd}
|
|
12711
|
+
* loop with a fresh {@link AbortController}.
|
|
12551
12712
|
*/
|
|
12552
12713
|
async startQueueProcessorIfNeeded() {
|
|
12553
12714
|
const store = this.getQueueStore();
|
|
@@ -12595,6 +12756,12 @@ var Agent = class {
|
|
|
12595
12756
|
type: "system"
|
|
12596
12757
|
});
|
|
12597
12758
|
}
|
|
12759
|
+
/**
|
|
12760
|
+
* Returns a LangGraph StateSnapshot for this thread.
|
|
12761
|
+
*
|
|
12762
|
+
* Includes `state.values.messages` (full conversation history) and
|
|
12763
|
+
* `state.tasks` / `state.next` (execution progress).
|
|
12764
|
+
*/
|
|
12598
12765
|
async getCurrentState() {
|
|
12599
12766
|
const { runnable_agent } = await this.getLatticeClientAndRuntimeConfig();
|
|
12600
12767
|
const state = await runnable_agent.getState({
|
|
@@ -12602,6 +12769,14 @@ var Agent = class {
|
|
|
12602
12769
|
});
|
|
12603
12770
|
return state;
|
|
12604
12771
|
}
|
|
12772
|
+
/**
|
|
12773
|
+
* Returns the conversation history as normalized message objects.
|
|
12774
|
+
*
|
|
12775
|
+
* Filters to `human`, `ai`, and `tool` message types. Each entry has
|
|
12776
|
+
* `{ id, role, content }` plus any LangChain kwargs.
|
|
12777
|
+
*
|
|
12778
|
+
* @returns Array of message objects with `id`, `role`, and `content`
|
|
12779
|
+
*/
|
|
12605
12780
|
async getCurrentMessages() {
|
|
12606
12781
|
const state = await this.getCurrentState();
|
|
12607
12782
|
const messages = state.values.messages || [];
|
|
@@ -12624,6 +12799,14 @@ var Agent = class {
|
|
|
12624
12799
|
const image = await drawableGraph.drawMermaid();
|
|
12625
12800
|
return image;
|
|
12626
12801
|
}
|
|
12802
|
+
/**
|
|
12803
|
+
* Determine the current thread execution status.
|
|
12804
|
+
*
|
|
12805
|
+
* Checks LangGraph's `state.tasks` for interrupts and `state.next` for
|
|
12806
|
+
* pending steps.
|
|
12807
|
+
*
|
|
12808
|
+
* @returns {@link ThreadStatus} — `IDLE`, `BUSY`, or `INTERRUPTED`
|
|
12809
|
+
*/
|
|
12627
12810
|
async getRunStatus() {
|
|
12628
12811
|
const state = await this.getCurrentState();
|
|
12629
12812
|
const isInterrupted = state.tasks?.some(
|
|
@@ -12638,9 +12821,14 @@ var Agent = class {
|
|
|
12638
12821
|
return "idle" /* IDLE */;
|
|
12639
12822
|
}
|
|
12640
12823
|
/**
|
|
12641
|
-
* Resume
|
|
12642
|
-
*
|
|
12643
|
-
*
|
|
12824
|
+
* Resume processing after a server restart.
|
|
12825
|
+
*
|
|
12826
|
+
* Resets any stuck "processing" messages back to "pending" and restarts the
|
|
12827
|
+
* queue processor. Skips threads that are in `INTERRUPTED` state (the
|
|
12828
|
+
* interruption was intentional).
|
|
12829
|
+
*
|
|
12830
|
+
* Called during gateway startup to recover threads that were mid-execution
|
|
12831
|
+
* when the server went down.
|
|
12644
12832
|
*/
|
|
12645
12833
|
async resumeTask() {
|
|
12646
12834
|
try {
|
|
@@ -12662,9 +12850,14 @@ var Agent = class {
|
|
|
12662
12850
|
await this.startQueueProcessorIfNeeded();
|
|
12663
12851
|
}
|
|
12664
12852
|
/**
|
|
12665
|
-
*
|
|
12666
|
-
*
|
|
12667
|
-
*
|
|
12853
|
+
* Fully abort all activity on this thread.
|
|
12854
|
+
*
|
|
12855
|
+
* Aborts any in-flight agent execution (via {@link AbortController}) and
|
|
12856
|
+
* clears all pending and processing messages from the queue. Also marks
|
|
12857
|
+
* the chunk buffer thread as aborted so streaming consumers can detect it.
|
|
12858
|
+
*
|
|
12859
|
+
* Unlike {@link stopQueueProcessor}, this is a destructive abort — the
|
|
12860
|
+
* queue is drained.
|
|
12668
12861
|
*/
|
|
12669
12862
|
async abort() {
|
|
12670
12863
|
if (this.abortController) {
|
|
@@ -12682,22 +12875,44 @@ var Agent = class {
|
|
|
12682
12875
|
return this.abortController?.signal.aborted ?? false;
|
|
12683
12876
|
}
|
|
12684
12877
|
/**
|
|
12685
|
-
* Subscribe to lifecycle
|
|
12686
|
-
*
|
|
12878
|
+
* Subscribe to a lifecycle event for this specific thread.
|
|
12879
|
+
*
|
|
12880
|
+
* Event names are namespaced as `{eventName}:{tenantId}:{threadId}` so
|
|
12881
|
+
* listeners only receive events for this agent instance.
|
|
12882
|
+
*
|
|
12883
|
+
* @param eventName - One of {@link AgentLifecycleEventName}
|
|
12884
|
+
* @param callback - Handler receiving the event data payload
|
|
12885
|
+
*
|
|
12886
|
+
* @example
|
|
12887
|
+
* ```ts
|
|
12888
|
+
* agent.subscribe("message:completed", (evt) => {
|
|
12889
|
+
* console.log("AI response:", evt.state?.values?.messages);
|
|
12890
|
+
* });
|
|
12891
|
+
* ```
|
|
12687
12892
|
*/
|
|
12688
12893
|
subscribe(eventName, callback) {
|
|
12689
12894
|
const namespacedEvent = `${eventName}:${this.tenant_id}:${this.thread_id}`;
|
|
12690
12895
|
event_bus_default.subscribe(namespacedEvent, callback);
|
|
12691
12896
|
}
|
|
12692
12897
|
/**
|
|
12693
|
-
*
|
|
12898
|
+
* Remove a previously registered event listener.
|
|
12899
|
+
*
|
|
12900
|
+
* @param eventName - The event that was subscribed to
|
|
12901
|
+
* @param callback - The same function reference used in {@link subscribe}
|
|
12694
12902
|
*/
|
|
12695
12903
|
unsubscribe(eventName, callback) {
|
|
12696
12904
|
const namespacedEvent = `${eventName}:${this.tenant_id}:${this.thread_id}`;
|
|
12697
12905
|
event_bus_default.unsubscribe(namespacedEvent, callback);
|
|
12698
12906
|
}
|
|
12699
12907
|
/**
|
|
12700
|
-
* Subscribe to lifecycle
|
|
12908
|
+
* Subscribe to a lifecycle event once — the listener is removed after the
|
|
12909
|
+
* first invocation.
|
|
12910
|
+
*
|
|
12911
|
+
* Ideal for one-shot async patterns (e.g. waiting for `reply:ready` before
|
|
12912
|
+
* sending a channel reply).
|
|
12913
|
+
*
|
|
12914
|
+
* @param eventName - One of {@link AgentLifecycleEventName}
|
|
12915
|
+
* @param callback - Handler receiving the event data payload
|
|
12701
12916
|
*/
|
|
12702
12917
|
subscribeOnce(eventName, callback) {
|
|
12703
12918
|
const namespacedEvent = `${eventName}:${this.tenant_id}:${this.thread_id}`;
|
|
@@ -12711,6 +12926,12 @@ var Agent = class {
|
|
|
12711
12926
|
console.log(namespacedEvent);
|
|
12712
12927
|
event_bus_default.publish(namespacedEvent, data);
|
|
12713
12928
|
}
|
|
12929
|
+
/**
|
|
12930
|
+
* Track a sub-agent async task spawned by this agent.
|
|
12931
|
+
*
|
|
12932
|
+
* Tasks are monitored by the agent task consumer in `packages/gateway`
|
|
12933
|
+
* and their status can be polled via {@link getAsyncTasks}.
|
|
12934
|
+
*/
|
|
12714
12935
|
addAsyncTask(task) {
|
|
12715
12936
|
this.asyncTasks.push(task);
|
|
12716
12937
|
}
|
|
@@ -12720,6 +12941,12 @@ var Agent = class {
|
|
|
12720
12941
|
getAsyncTask(taskId) {
|
|
12721
12942
|
return this.asyncTasks.find((t) => t.taskId === taskId);
|
|
12722
12943
|
}
|
|
12944
|
+
/**
|
|
12945
|
+
* Update the status of a tracked async task.
|
|
12946
|
+
*
|
|
12947
|
+
* Terminal states (`completed`, `failed`, `cancelled`) automatically
|
|
12948
|
+
* set `completedAt` to the current timestamp.
|
|
12949
|
+
*/
|
|
12723
12950
|
updateAsyncTaskStatus(taskId, status) {
|
|
12724
12951
|
const task = this.getAsyncTask(taskId);
|
|
12725
12952
|
if (!task) return;
|
|
@@ -13085,6 +13312,65 @@ function createSchedulerMiddleware(options = {}) {
|
|
|
13085
13312
|
});
|
|
13086
13313
|
}
|
|
13087
13314
|
|
|
13315
|
+
// src/agent_lattice/builders/CustomMiddlewareRegistry.ts
|
|
13316
|
+
var CustomMiddlewareRegistry = class {
|
|
13317
|
+
/**
|
|
13318
|
+
* Register a custom middleware factory under the given key.
|
|
13319
|
+
*
|
|
13320
|
+
* The key is referenced by `config.key` in the database middleware configuration.
|
|
13321
|
+
* When an agent is built, the framework looks up this key and calls the factory
|
|
13322
|
+
* with the remaining config fields.
|
|
13323
|
+
*
|
|
13324
|
+
* @param key - Unique identifier, referenced in database config as `config.key`
|
|
13325
|
+
* @param factory - Function that receives config (minus `key`) and returns an AgentMiddleware
|
|
13326
|
+
*
|
|
13327
|
+
* @example
|
|
13328
|
+
* ```ts
|
|
13329
|
+
* CustomMiddlewareRegistry.register("my-logger", (config) =>
|
|
13330
|
+
* createMiddleware({ name: "Logger", beforeAgent: async () => { ... } }),
|
|
13331
|
+
* );
|
|
13332
|
+
* ```
|
|
13333
|
+
*/
|
|
13334
|
+
static register(key, factory) {
|
|
13335
|
+
this.factories.set(key, factory);
|
|
13336
|
+
}
|
|
13337
|
+
/**
|
|
13338
|
+
* Remove a previously registered factory.
|
|
13339
|
+
*
|
|
13340
|
+
* @param key - The factory key to unregister
|
|
13341
|
+
* @returns `true` if a factory was removed, `false` if the key was not found
|
|
13342
|
+
*/
|
|
13343
|
+
static unregister(key) {
|
|
13344
|
+
return this.factories.delete(key);
|
|
13345
|
+
}
|
|
13346
|
+
/**
|
|
13347
|
+
* Look up a factory by key.
|
|
13348
|
+
*
|
|
13349
|
+
* @param key - The factory key
|
|
13350
|
+
* @returns The factory function, or `undefined` if not registered
|
|
13351
|
+
*/
|
|
13352
|
+
static get(key) {
|
|
13353
|
+
return this.factories.get(key);
|
|
13354
|
+
}
|
|
13355
|
+
/**
|
|
13356
|
+
* Check whether a factory is registered under the given key.
|
|
13357
|
+
*
|
|
13358
|
+
* @param key - The factory key to check
|
|
13359
|
+
*/
|
|
13360
|
+
static has(key) {
|
|
13361
|
+
return this.factories.has(key);
|
|
13362
|
+
}
|
|
13363
|
+
/**
|
|
13364
|
+
* Get all currently registered factory keys.
|
|
13365
|
+
*
|
|
13366
|
+
* @returns Array of registered key strings
|
|
13367
|
+
*/
|
|
13368
|
+
static list() {
|
|
13369
|
+
return Array.from(this.factories.keys());
|
|
13370
|
+
}
|
|
13371
|
+
};
|
|
13372
|
+
CustomMiddlewareRegistry.factories = /* @__PURE__ */ new Map();
|
|
13373
|
+
|
|
13088
13374
|
// src/agent_lattice/builders/commonMiddleware.ts
|
|
13089
13375
|
async function createCommonMiddlewares(middlewareConfigs, filesystemBackend, fsIsExised) {
|
|
13090
13376
|
const middlewares = [];
|
|
@@ -13161,6 +13447,21 @@ async function createCommonMiddlewares(middlewareConfigs, filesystemBackend, fsI
|
|
|
13161
13447
|
case "scheduler":
|
|
13162
13448
|
middlewares.push(createSchedulerMiddleware(config.config));
|
|
13163
13449
|
break;
|
|
13450
|
+
case "custom":
|
|
13451
|
+
{
|
|
13452
|
+
const customConfig = config.config;
|
|
13453
|
+
const { key, ...rest } = customConfig;
|
|
13454
|
+
const factory = CustomMiddlewareRegistry.get(key);
|
|
13455
|
+
if (factory) {
|
|
13456
|
+
const middleware = factory(rest);
|
|
13457
|
+
middlewares.push(middleware instanceof Promise ? await middleware : middleware);
|
|
13458
|
+
} else {
|
|
13459
|
+
console.warn(
|
|
13460
|
+
`[custom middleware] No factory registered for key "${key}". Use CustomMiddlewareRegistry.register("${key}", factory) before building the agent.`
|
|
13461
|
+
);
|
|
13462
|
+
}
|
|
13463
|
+
}
|
|
13464
|
+
break;
|
|
13164
13465
|
}
|
|
13165
13466
|
}
|
|
13166
13467
|
return middlewares;
|
|
@@ -17934,6 +18235,75 @@ function mergeAgentConfig(parent, child) {
|
|
|
17934
18235
|
return merged;
|
|
17935
18236
|
}
|
|
17936
18237
|
|
|
18238
|
+
// src/store_lattice/configureStores.ts
|
|
18239
|
+
var _disposables = [];
|
|
18240
|
+
var _cleanupRegistered = false;
|
|
18241
|
+
function registerSignalCleanup() {
|
|
18242
|
+
if (_cleanupRegistered) return;
|
|
18243
|
+
_cleanupRegistered = true;
|
|
18244
|
+
for (const sig of ["SIGINT", "SIGTERM"]) {
|
|
18245
|
+
process.once(sig, async () => {
|
|
18246
|
+
for (const s of _disposables) {
|
|
18247
|
+
if (s.dispose) await s.dispose();
|
|
18248
|
+
}
|
|
18249
|
+
});
|
|
18250
|
+
}
|
|
18251
|
+
}
|
|
18252
|
+
async function initAndRegister(store, localDisposables) {
|
|
18253
|
+
const initStore = store;
|
|
18254
|
+
if (typeof initStore.initialize === "function" && initStore.initialize.length === 0) {
|
|
18255
|
+
await initStore.initialize();
|
|
18256
|
+
}
|
|
18257
|
+
const dispStore = store;
|
|
18258
|
+
if (typeof dispStore.dispose === "function") {
|
|
18259
|
+
localDisposables.push(dispStore);
|
|
18260
|
+
}
|
|
18261
|
+
}
|
|
18262
|
+
async function configureStores(stores, options = {}) {
|
|
18263
|
+
const localDisposables = [];
|
|
18264
|
+
const { schedule, checkpoint, ...regularStores } = stores;
|
|
18265
|
+
for (const [type, store] of Object.entries(regularStores)) {
|
|
18266
|
+
await initAndRegister(store, localDisposables);
|
|
18267
|
+
if (storeLatticeManager.hasLattice("default", type)) {
|
|
18268
|
+
storeLatticeManager.removeLattice("default", type);
|
|
18269
|
+
}
|
|
18270
|
+
storeLatticeManager.registerLattice("default", type, store);
|
|
18271
|
+
}
|
|
18272
|
+
if (schedule !== void 0) {
|
|
18273
|
+
await initAndRegister(schedule, localDisposables);
|
|
18274
|
+
const scheduleConfig = {
|
|
18275
|
+
name: "Default Scheduler",
|
|
18276
|
+
description: "Auto-configured schedule storage",
|
|
18277
|
+
type: "postgres",
|
|
18278
|
+
storage: schedule
|
|
18279
|
+
};
|
|
18280
|
+
registerScheduleLattice("default", scheduleConfig);
|
|
18281
|
+
}
|
|
18282
|
+
if (checkpoint !== void 0) {
|
|
18283
|
+
MemoryLatticeManager.getInstance().removeCheckpointSaver("default");
|
|
18284
|
+
registerCheckpointSaver("default", checkpoint);
|
|
18285
|
+
}
|
|
18286
|
+
if (options.customStores) {
|
|
18287
|
+
for (const [type, store] of Object.entries(options.customStores)) {
|
|
18288
|
+
await initAndRegister(store, localDisposables);
|
|
18289
|
+
const t = type;
|
|
18290
|
+
if (storeLatticeManager.hasLattice("default", t)) {
|
|
18291
|
+
storeLatticeManager.removeLattice("default", t);
|
|
18292
|
+
}
|
|
18293
|
+
storeLatticeManager.registerLattice("default", t, store);
|
|
18294
|
+
}
|
|
18295
|
+
}
|
|
18296
|
+
if (options.autoDisposeStores) {
|
|
18297
|
+
registerSignalCleanup();
|
|
18298
|
+
_disposables.push(...localDisposables);
|
|
18299
|
+
}
|
|
18300
|
+
return async () => {
|
|
18301
|
+
for (const s of localDisposables.reverse()) {
|
|
18302
|
+
if (s.dispose) await s.dispose();
|
|
18303
|
+
}
|
|
18304
|
+
};
|
|
18305
|
+
}
|
|
18306
|
+
|
|
17937
18307
|
// src/store_lattice/SandboxSkillStore.ts
|
|
17938
18308
|
function parseFrontmatter2(content) {
|
|
17939
18309
|
const frontmatterRegex = /^---\s*\n([\s\S]*?)\n---\s*\n?([\s\S]*)$/;
|
|
@@ -22468,6 +22838,7 @@ export {
|
|
|
22468
22838
|
CompositeBackend,
|
|
22469
22839
|
ConsoleLoggerClient,
|
|
22470
22840
|
CustomMetricsClient,
|
|
22841
|
+
CustomMiddlewareRegistry,
|
|
22471
22842
|
DaytonaInstance,
|
|
22472
22843
|
DaytonaProvider,
|
|
22473
22844
|
DefaultScheduleClient,
|
|
@@ -22541,6 +22912,7 @@ export {
|
|
|
22541
22912
|
checkEmptyContent,
|
|
22542
22913
|
clearEncryptionKeyCache,
|
|
22543
22914
|
computeSandboxName,
|
|
22915
|
+
configureStores,
|
|
22544
22916
|
createAgentTeam,
|
|
22545
22917
|
createExecuteSqlQueryTool,
|
|
22546
22918
|
createFileData,
|