@axiom-lattice/core 2.1.76 → 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 +258 -0
- package/dist/index.d.mts +521 -29
- package/dist/index.d.ts +521 -29
- package/dist/index.js +330 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +329 -22
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2463,14 +2463,35 @@ var InMemoryChannelInstallationStore = class {
|
|
|
2463
2463
|
constructor() {
|
|
2464
2464
|
this.installations = /* @__PURE__ */ new Map();
|
|
2465
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
|
+
*/
|
|
2466
2472
|
async getInstallationById(installationId) {
|
|
2467
2473
|
return this.installations.get(installationId) || null;
|
|
2468
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
|
+
*/
|
|
2469
2482
|
async getInstallationsByTenant(tenantId, channel) {
|
|
2470
2483
|
return Array.from(this.installations.values()).filter(
|
|
2471
2484
|
(inst) => inst.tenantId === tenantId && (!channel || inst.channel === channel)
|
|
2472
2485
|
);
|
|
2473
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
|
+
*/
|
|
2474
2495
|
async createInstallation(tenantId, installationId, data) {
|
|
2475
2496
|
const now = /* @__PURE__ */ new Date();
|
|
2476
2497
|
const installation = {
|
|
@@ -2488,6 +2509,14 @@ var InMemoryChannelInstallationStore = class {
|
|
|
2488
2509
|
this.installations.set(installationId, installation);
|
|
2489
2510
|
return installation;
|
|
2490
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
|
+
*/
|
|
2491
2520
|
async updateInstallation(tenantId, installationId, updates) {
|
|
2492
2521
|
const existing = this.installations.get(installationId);
|
|
2493
2522
|
if (!existing || existing.tenantId !== tenantId) return null;
|
|
@@ -2503,11 +2532,21 @@ var InMemoryChannelInstallationStore = class {
|
|
|
2503
2532
|
this.installations.set(installationId, updated);
|
|
2504
2533
|
return updated;
|
|
2505
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
|
+
*/
|
|
2506
2542
|
async deleteInstallation(tenantId, installationId) {
|
|
2507
2543
|
const existing = this.installations.get(installationId);
|
|
2508
2544
|
if (!existing || existing.tenantId !== tenantId) return false;
|
|
2509
2545
|
return this.installations.delete(installationId);
|
|
2510
2546
|
}
|
|
2547
|
+
/**
|
|
2548
|
+
* Clears all in-memory installations. Primarily used in tests.
|
|
2549
|
+
*/
|
|
2511
2550
|
clear() {
|
|
2512
2551
|
this.installations.clear();
|
|
2513
2552
|
}
|
|
@@ -2519,6 +2558,16 @@ var InMemoryBindingStore = class {
|
|
|
2519
2558
|
constructor() {
|
|
2520
2559
|
this.bindings = /* @__PURE__ */ new Map();
|
|
2521
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
|
+
*/
|
|
2522
2571
|
async resolve(params) {
|
|
2523
2572
|
for (const binding of this.bindings.values()) {
|
|
2524
2573
|
if (binding.channel === params.channel && binding.senderId === params.senderId && binding.channelInstallationId === params.channelInstallationId && binding.tenantId === params.tenantId && binding.enabled) {
|
|
@@ -2527,6 +2576,12 @@ var InMemoryBindingStore = class {
|
|
|
2527
2576
|
}
|
|
2528
2577
|
return null;
|
|
2529
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
|
+
*/
|
|
2530
2585
|
async create(input) {
|
|
2531
2586
|
const now = /* @__PURE__ */ new Date();
|
|
2532
2587
|
const binding = {
|
|
@@ -2549,6 +2604,14 @@ var InMemoryBindingStore = class {
|
|
|
2549
2604
|
this.bindings.set(binding.id, binding);
|
|
2550
2605
|
return binding;
|
|
2551
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
|
+
*/
|
|
2552
2615
|
async update(id, patch) {
|
|
2553
2616
|
const existing = this.bindings.get(id);
|
|
2554
2617
|
if (!existing) throw new Error(`Binding ${id} not found`);
|
|
@@ -2560,9 +2623,20 @@ var InMemoryBindingStore = class {
|
|
|
2560
2623
|
this.bindings.set(id, updated);
|
|
2561
2624
|
return updated;
|
|
2562
2625
|
}
|
|
2626
|
+
/**
|
|
2627
|
+
* Deletes a binding by ID.
|
|
2628
|
+
*
|
|
2629
|
+
* @param id - Binding ID
|
|
2630
|
+
*/
|
|
2563
2631
|
async delete(id) {
|
|
2564
2632
|
this.bindings.delete(id);
|
|
2565
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
|
+
*/
|
|
2566
2640
|
async list(params) {
|
|
2567
2641
|
let results = Array.from(this.bindings.values()).filter((b) => {
|
|
2568
2642
|
if (b.tenantId !== params.tenantId) return false;
|
|
@@ -2575,6 +2649,12 @@ var InMemoryBindingStore = class {
|
|
|
2575
2649
|
const limit = params.limit ?? 50;
|
|
2576
2650
|
return results.slice(offset, offset + limit);
|
|
2577
2651
|
}
|
|
2652
|
+
/**
|
|
2653
|
+
* Bulk-imports bindings.
|
|
2654
|
+
*
|
|
2655
|
+
* @param bindings - Array of {@link CreateBindingInput}
|
|
2656
|
+
* @returns Array of created {@link Binding} objects
|
|
2657
|
+
*/
|
|
2578
2658
|
async import(bindings) {
|
|
2579
2659
|
const result = [];
|
|
2580
2660
|
for (const input of bindings) {
|
|
@@ -2582,9 +2662,18 @@ var InMemoryBindingStore = class {
|
|
|
2582
2662
|
}
|
|
2583
2663
|
return result;
|
|
2584
2664
|
}
|
|
2665
|
+
/**
|
|
2666
|
+
* Exports all bindings for a tenant.
|
|
2667
|
+
*
|
|
2668
|
+
* @param params - Filter by tenantId
|
|
2669
|
+
* @returns Array of {@link Binding} objects
|
|
2670
|
+
*/
|
|
2585
2671
|
async export(params) {
|
|
2586
2672
|
return this.list({ tenantId: params.tenantId, limit: 1e4 });
|
|
2587
2673
|
}
|
|
2674
|
+
/**
|
|
2675
|
+
* Clears all in-memory bindings. Primarily used in tests.
|
|
2676
|
+
*/
|
|
2588
2677
|
clear() {
|
|
2589
2678
|
this.bindings.clear();
|
|
2590
2679
|
}
|
|
@@ -11906,6 +11995,14 @@ var ThreadStatus2 = /* @__PURE__ */ ((ThreadStatus3) => {
|
|
|
11906
11995
|
return ThreadStatus3;
|
|
11907
11996
|
})(ThreadStatus2 || {});
|
|
11908
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
|
+
*/
|
|
11909
12006
|
constructor({
|
|
11910
12007
|
assistant_id,
|
|
11911
12008
|
thread_id,
|
|
@@ -12118,6 +12215,7 @@ var Agent = class {
|
|
|
12118
12215
|
await this.queueStore?.removeMessage(p.id);
|
|
12119
12216
|
const runStatus = await this.getRunStatus();
|
|
12120
12217
|
const state = await this.getCurrentState();
|
|
12218
|
+
const customRunConfig = p.custom_run_config ?? queueMessageData.custom_run_config;
|
|
12121
12219
|
if (runStatus === "interrupted" /* INTERRUPTED */) {
|
|
12122
12220
|
this.publish("message:interrupted", {
|
|
12123
12221
|
type: "message:interrupted",
|
|
@@ -12142,6 +12240,12 @@ var Agent = class {
|
|
|
12142
12240
|
state
|
|
12143
12241
|
});
|
|
12144
12242
|
}
|
|
12243
|
+
this.publish("reply:ready", {
|
|
12244
|
+
type: "reply:ready",
|
|
12245
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
12246
|
+
state,
|
|
12247
|
+
customRunConfig
|
|
12248
|
+
});
|
|
12145
12249
|
} catch (error) {
|
|
12146
12250
|
console.error(`STEER/Command message ${p.id} execution failed:`, error);
|
|
12147
12251
|
this.addChunk({
|
|
@@ -12220,6 +12324,12 @@ var Agent = class {
|
|
|
12220
12324
|
});
|
|
12221
12325
|
}
|
|
12222
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
|
+
});
|
|
12223
12333
|
} catch (error) {
|
|
12224
12334
|
console.error(`COLLECT mode execution failed:`, error);
|
|
12225
12335
|
for (const p of remainingPendings) {
|
|
@@ -12268,6 +12378,7 @@ var Agent = class {
|
|
|
12268
12378
|
await this.queueStore?.removeMessage(p.id);
|
|
12269
12379
|
const runStatus = await this.getRunStatus();
|
|
12270
12380
|
const state = await this.getCurrentState();
|
|
12381
|
+
const customRunConfig = p.custom_run_config ?? queueMessageData.custom_run_config;
|
|
12271
12382
|
if (runStatus === "interrupted" /* INTERRUPTED */) {
|
|
12272
12383
|
this.publish("message:interrupted", {
|
|
12273
12384
|
type: "message:interrupted",
|
|
@@ -12292,6 +12403,12 @@ var Agent = class {
|
|
|
12292
12403
|
state
|
|
12293
12404
|
});
|
|
12294
12405
|
}
|
|
12406
|
+
this.publish("reply:ready", {
|
|
12407
|
+
type: "reply:ready",
|
|
12408
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
12409
|
+
state,
|
|
12410
|
+
customRunConfig
|
|
12411
|
+
});
|
|
12295
12412
|
} catch (error) {
|
|
12296
12413
|
console.error(`FOLLOWUP mode message ${p.id} execution failed:`, error);
|
|
12297
12414
|
this.addChunk({
|
|
@@ -12334,9 +12451,25 @@ var Agent = class {
|
|
|
12334
12451
|
setQueueStore(store) {
|
|
12335
12452
|
this.queueStore = store;
|
|
12336
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
|
+
*/
|
|
12337
12461
|
addChunk(content) {
|
|
12338
12462
|
return this.chunkBuffer.addChunk(this.thread_id, content);
|
|
12339
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
|
+
*/
|
|
12340
12473
|
chunkStream(message_id, stopTypes) {
|
|
12341
12474
|
const stream = this.chunkBuffer.getNewChunksSinceContentIterator(
|
|
12342
12475
|
this.thread_id,
|
|
@@ -12425,13 +12558,21 @@ var Agent = class {
|
|
|
12425
12558
|
};
|
|
12426
12559
|
}
|
|
12427
12560
|
/**
|
|
12428
|
-
*
|
|
12561
|
+
* Override the thread's queue processing mode.
|
|
12562
|
+
*
|
|
12563
|
+
* @param config - Partial {@link ThreadQueueConfig} (e.g. `{ mode: QueueMode.FOLLOWUP }`)
|
|
12429
12564
|
*/
|
|
12430
12565
|
async setQueueConfig(config) {
|
|
12431
12566
|
this.queueMode = { ...this.queueMode, ...config };
|
|
12432
12567
|
}
|
|
12433
12568
|
/**
|
|
12434
|
-
*
|
|
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}
|
|
12435
12576
|
*/
|
|
12436
12577
|
stopQueueProcessor() {
|
|
12437
12578
|
if (this.abortController) {
|
|
@@ -12440,14 +12581,34 @@ var Agent = class {
|
|
|
12440
12581
|
}
|
|
12441
12582
|
}
|
|
12442
12583
|
/**
|
|
12443
|
-
*
|
|
12444
|
-
*
|
|
12445
|
-
*
|
|
12446
|
-
*
|
|
12447
|
-
*
|
|
12448
|
-
*
|
|
12449
|
-
* -
|
|
12450
|
-
* -
|
|
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
|
+
* ```
|
|
12451
12612
|
*/
|
|
12452
12613
|
async addMessage(queueMessage, mode) {
|
|
12453
12614
|
const useMode = mode ?? this.queueMode.mode;
|
|
@@ -12541,8 +12702,13 @@ var Agent = class {
|
|
|
12541
12702
|
return { queued: true, executed: false, messageId };
|
|
12542
12703
|
}
|
|
12543
12704
|
/**
|
|
12544
|
-
* Start queue processor if not already running
|
|
12545
|
-
*
|
|
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}.
|
|
12546
12712
|
*/
|
|
12547
12713
|
async startQueueProcessorIfNeeded() {
|
|
12548
12714
|
const store = this.getQueueStore();
|
|
@@ -12590,6 +12756,12 @@ var Agent = class {
|
|
|
12590
12756
|
type: "system"
|
|
12591
12757
|
});
|
|
12592
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
|
+
*/
|
|
12593
12765
|
async getCurrentState() {
|
|
12594
12766
|
const { runnable_agent } = await this.getLatticeClientAndRuntimeConfig();
|
|
12595
12767
|
const state = await runnable_agent.getState({
|
|
@@ -12597,6 +12769,14 @@ var Agent = class {
|
|
|
12597
12769
|
});
|
|
12598
12770
|
return state;
|
|
12599
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
|
+
*/
|
|
12600
12780
|
async getCurrentMessages() {
|
|
12601
12781
|
const state = await this.getCurrentState();
|
|
12602
12782
|
const messages = state.values.messages || [];
|
|
@@ -12619,6 +12799,14 @@ var Agent = class {
|
|
|
12619
12799
|
const image = await drawableGraph.drawMermaid();
|
|
12620
12800
|
return image;
|
|
12621
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
|
+
*/
|
|
12622
12810
|
async getRunStatus() {
|
|
12623
12811
|
const state = await this.getCurrentState();
|
|
12624
12812
|
const isInterrupted = state.tasks?.some(
|
|
@@ -12633,9 +12821,14 @@ var Agent = class {
|
|
|
12633
12821
|
return "idle" /* IDLE */;
|
|
12634
12822
|
}
|
|
12635
12823
|
/**
|
|
12636
|
-
* Resume
|
|
12637
|
-
*
|
|
12638
|
-
*
|
|
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.
|
|
12639
12832
|
*/
|
|
12640
12833
|
async resumeTask() {
|
|
12641
12834
|
try {
|
|
@@ -12657,9 +12850,14 @@ var Agent = class {
|
|
|
12657
12850
|
await this.startQueueProcessorIfNeeded();
|
|
12658
12851
|
}
|
|
12659
12852
|
/**
|
|
12660
|
-
*
|
|
12661
|
-
*
|
|
12662
|
-
*
|
|
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.
|
|
12663
12861
|
*/
|
|
12664
12862
|
async abort() {
|
|
12665
12863
|
if (this.abortController) {
|
|
@@ -12677,22 +12875,44 @@ var Agent = class {
|
|
|
12677
12875
|
return this.abortController?.signal.aborted ?? false;
|
|
12678
12876
|
}
|
|
12679
12877
|
/**
|
|
12680
|
-
* Subscribe to lifecycle
|
|
12681
|
-
*
|
|
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
|
+
* ```
|
|
12682
12892
|
*/
|
|
12683
12893
|
subscribe(eventName, callback) {
|
|
12684
12894
|
const namespacedEvent = `${eventName}:${this.tenant_id}:${this.thread_id}`;
|
|
12685
12895
|
event_bus_default.subscribe(namespacedEvent, callback);
|
|
12686
12896
|
}
|
|
12687
12897
|
/**
|
|
12688
|
-
*
|
|
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}
|
|
12689
12902
|
*/
|
|
12690
12903
|
unsubscribe(eventName, callback) {
|
|
12691
12904
|
const namespacedEvent = `${eventName}:${this.tenant_id}:${this.thread_id}`;
|
|
12692
12905
|
event_bus_default.unsubscribe(namespacedEvent, callback);
|
|
12693
12906
|
}
|
|
12694
12907
|
/**
|
|
12695
|
-
* 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
|
|
12696
12916
|
*/
|
|
12697
12917
|
subscribeOnce(eventName, callback) {
|
|
12698
12918
|
const namespacedEvent = `${eventName}:${this.tenant_id}:${this.thread_id}`;
|
|
@@ -12706,6 +12926,12 @@ var Agent = class {
|
|
|
12706
12926
|
console.log(namespacedEvent);
|
|
12707
12927
|
event_bus_default.publish(namespacedEvent, data);
|
|
12708
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
|
+
*/
|
|
12709
12935
|
addAsyncTask(task) {
|
|
12710
12936
|
this.asyncTasks.push(task);
|
|
12711
12937
|
}
|
|
@@ -12715,6 +12941,12 @@ var Agent = class {
|
|
|
12715
12941
|
getAsyncTask(taskId) {
|
|
12716
12942
|
return this.asyncTasks.find((t) => t.taskId === taskId);
|
|
12717
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
|
+
*/
|
|
12718
12950
|
updateAsyncTaskStatus(taskId, status) {
|
|
12719
12951
|
const task = this.getAsyncTask(taskId);
|
|
12720
12952
|
if (!task) return;
|
|
@@ -13080,6 +13312,65 @@ function createSchedulerMiddleware(options = {}) {
|
|
|
13080
13312
|
});
|
|
13081
13313
|
}
|
|
13082
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
|
+
|
|
13083
13374
|
// src/agent_lattice/builders/commonMiddleware.ts
|
|
13084
13375
|
async function createCommonMiddlewares(middlewareConfigs, filesystemBackend, fsIsExised) {
|
|
13085
13376
|
const middlewares = [];
|
|
@@ -13156,6 +13447,21 @@ async function createCommonMiddlewares(middlewareConfigs, filesystemBackend, fsI
|
|
|
13156
13447
|
case "scheduler":
|
|
13157
13448
|
middlewares.push(createSchedulerMiddleware(config.config));
|
|
13158
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;
|
|
13159
13465
|
}
|
|
13160
13466
|
}
|
|
13161
13467
|
return middlewares;
|
|
@@ -22532,6 +22838,7 @@ export {
|
|
|
22532
22838
|
CompositeBackend,
|
|
22533
22839
|
ConsoleLoggerClient,
|
|
22534
22840
|
CustomMetricsClient,
|
|
22841
|
+
CustomMiddlewareRegistry,
|
|
22535
22842
|
DaytonaInstance,
|
|
22536
22843
|
DaytonaProvider,
|
|
22537
22844
|
DefaultScheduleClient,
|