@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.js
CHANGED
|
@@ -42,6 +42,7 @@ __export(index_exports, {
|
|
|
42
42
|
CompositeBackend: () => CompositeBackend,
|
|
43
43
|
ConsoleLoggerClient: () => ConsoleLoggerClient,
|
|
44
44
|
CustomMetricsClient: () => CustomMetricsClient,
|
|
45
|
+
CustomMiddlewareRegistry: () => CustomMiddlewareRegistry,
|
|
45
46
|
DaytonaInstance: () => DaytonaInstance,
|
|
46
47
|
DaytonaProvider: () => DaytonaProvider,
|
|
47
48
|
DefaultScheduleClient: () => DefaultScheduleClient,
|
|
@@ -2691,14 +2692,35 @@ var InMemoryChannelInstallationStore = class {
|
|
|
2691
2692
|
constructor() {
|
|
2692
2693
|
this.installations = /* @__PURE__ */ new Map();
|
|
2693
2694
|
}
|
|
2695
|
+
/**
|
|
2696
|
+
* Retrieves a channel installation by its unique ID.
|
|
2697
|
+
*
|
|
2698
|
+
* @param installationId - The installation identifier
|
|
2699
|
+
* @returns The {@link ChannelInstallation} or `null` if not found
|
|
2700
|
+
*/
|
|
2694
2701
|
async getInstallationById(installationId) {
|
|
2695
2702
|
return this.installations.get(installationId) || null;
|
|
2696
2703
|
}
|
|
2704
|
+
/**
|
|
2705
|
+
* Lists all channel installations for a tenant, optionally filtered by channel type.
|
|
2706
|
+
*
|
|
2707
|
+
* @param tenantId - Tenant identifier
|
|
2708
|
+
* @param channel - Optional channel type filter (`"lark"`, `"email"`, `"slack"`)
|
|
2709
|
+
* @returns Array of matching {@link ChannelInstallation} objects
|
|
2710
|
+
*/
|
|
2697
2711
|
async getInstallationsByTenant(tenantId, channel) {
|
|
2698
2712
|
return Array.from(this.installations.values()).filter(
|
|
2699
2713
|
(inst) => inst.tenantId === tenantId && (!channel || inst.channel === channel)
|
|
2700
2714
|
);
|
|
2701
2715
|
}
|
|
2716
|
+
/**
|
|
2717
|
+
* Creates a new channel installation for a tenant.
|
|
2718
|
+
*
|
|
2719
|
+
* @param tenantId - Tenant identifier
|
|
2720
|
+
* @param installationId - Unique installation ID (caller-defined)
|
|
2721
|
+
* @param data - {@link CreateChannelInstallationRequest} containing channel type, name, config, and fallback settings
|
|
2722
|
+
* @returns The created {@link ChannelInstallation}
|
|
2723
|
+
*/
|
|
2702
2724
|
async createInstallation(tenantId, installationId, data) {
|
|
2703
2725
|
const now = /* @__PURE__ */ new Date();
|
|
2704
2726
|
const installation = {
|
|
@@ -2716,6 +2738,14 @@ var InMemoryChannelInstallationStore = class {
|
|
|
2716
2738
|
this.installations.set(installationId, installation);
|
|
2717
2739
|
return installation;
|
|
2718
2740
|
}
|
|
2741
|
+
/**
|
|
2742
|
+
* Updates an existing channel installation. Config fields are shallow-merged.
|
|
2743
|
+
*
|
|
2744
|
+
* @param tenantId - Tenant identifier (used for isolation check)
|
|
2745
|
+
* @param installationId - Installation ID to update
|
|
2746
|
+
* @param updates - {@link UpdateChannelInstallationRequest} with fields to patch
|
|
2747
|
+
* @returns The updated {@link ChannelInstallation} or `null` if not found or tenant mismatch
|
|
2748
|
+
*/
|
|
2719
2749
|
async updateInstallation(tenantId, installationId, updates) {
|
|
2720
2750
|
const existing = this.installations.get(installationId);
|
|
2721
2751
|
if (!existing || existing.tenantId !== tenantId) return null;
|
|
@@ -2731,11 +2761,21 @@ var InMemoryChannelInstallationStore = class {
|
|
|
2731
2761
|
this.installations.set(installationId, updated);
|
|
2732
2762
|
return updated;
|
|
2733
2763
|
}
|
|
2764
|
+
/**
|
|
2765
|
+
* Deletes a channel installation.
|
|
2766
|
+
*
|
|
2767
|
+
* @param tenantId - Tenant identifier (used for isolation check)
|
|
2768
|
+
* @param installationId - Installation ID to delete
|
|
2769
|
+
* @returns `true` if deleted, `false` if not found or tenant mismatch
|
|
2770
|
+
*/
|
|
2734
2771
|
async deleteInstallation(tenantId, installationId) {
|
|
2735
2772
|
const existing = this.installations.get(installationId);
|
|
2736
2773
|
if (!existing || existing.tenantId !== tenantId) return false;
|
|
2737
2774
|
return this.installations.delete(installationId);
|
|
2738
2775
|
}
|
|
2776
|
+
/**
|
|
2777
|
+
* Clears all in-memory installations. Primarily used in tests.
|
|
2778
|
+
*/
|
|
2739
2779
|
clear() {
|
|
2740
2780
|
this.installations.clear();
|
|
2741
2781
|
}
|
|
@@ -2747,6 +2787,16 @@ var InMemoryBindingStore = class {
|
|
|
2747
2787
|
constructor() {
|
|
2748
2788
|
this.bindings = /* @__PURE__ */ new Map();
|
|
2749
2789
|
}
|
|
2790
|
+
/**
|
|
2791
|
+
* Resolves a binding for the given sender across a specific channel installation.
|
|
2792
|
+
*
|
|
2793
|
+
* Called by `MessageRouter.dispatch()` during inbound message processing.
|
|
2794
|
+
* Matches on `channel + senderId + channelInstallationId + tenantId` and
|
|
2795
|
+
* requires `enabled === true`.
|
|
2796
|
+
*
|
|
2797
|
+
* @param params - Resolution parameters
|
|
2798
|
+
* @returns The matching {@link Binding} or `null` if none found.
|
|
2799
|
+
*/
|
|
2750
2800
|
async resolve(params) {
|
|
2751
2801
|
for (const binding of this.bindings.values()) {
|
|
2752
2802
|
if (binding.channel === params.channel && binding.senderId === params.senderId && binding.channelInstallationId === params.channelInstallationId && binding.tenantId === params.tenantId && binding.enabled) {
|
|
@@ -2755,6 +2805,12 @@ var InMemoryBindingStore = class {
|
|
|
2755
2805
|
}
|
|
2756
2806
|
return null;
|
|
2757
2807
|
}
|
|
2808
|
+
/**
|
|
2809
|
+
* Creates a new sender-to-agent binding.
|
|
2810
|
+
*
|
|
2811
|
+
* @param input - {@link CreateBindingInput} defining channel, sender, target agent, and thread mode.
|
|
2812
|
+
* @returns The newly created {@link Binding}.
|
|
2813
|
+
*/
|
|
2758
2814
|
async create(input) {
|
|
2759
2815
|
const now = /* @__PURE__ */ new Date();
|
|
2760
2816
|
const binding = {
|
|
@@ -2777,6 +2833,14 @@ var InMemoryBindingStore = class {
|
|
|
2777
2833
|
this.bindings.set(binding.id, binding);
|
|
2778
2834
|
return binding;
|
|
2779
2835
|
}
|
|
2836
|
+
/**
|
|
2837
|
+
* Updates an existing binding (e.g. changing the target agent or thread mode).
|
|
2838
|
+
*
|
|
2839
|
+
* @param id - Binding ID
|
|
2840
|
+
* @param patch - Partial {@link Binding} fields to update
|
|
2841
|
+
* @returns The updated {@link Binding}
|
|
2842
|
+
* @throws {Error} If the binding does not exist
|
|
2843
|
+
*/
|
|
2780
2844
|
async update(id, patch) {
|
|
2781
2845
|
const existing = this.bindings.get(id);
|
|
2782
2846
|
if (!existing) throw new Error(`Binding ${id} not found`);
|
|
@@ -2788,9 +2852,20 @@ var InMemoryBindingStore = class {
|
|
|
2788
2852
|
this.bindings.set(id, updated);
|
|
2789
2853
|
return updated;
|
|
2790
2854
|
}
|
|
2855
|
+
/**
|
|
2856
|
+
* Deletes a binding by ID.
|
|
2857
|
+
*
|
|
2858
|
+
* @param id - Binding ID
|
|
2859
|
+
*/
|
|
2791
2860
|
async delete(id) {
|
|
2792
2861
|
this.bindings.delete(id);
|
|
2793
2862
|
}
|
|
2863
|
+
/**
|
|
2864
|
+
* Lists bindings filtered by tenant and optional channel/agent/installation.
|
|
2865
|
+
*
|
|
2866
|
+
* @param params - Filter and pagination parameters
|
|
2867
|
+
* @returns Array of matching {@link Binding} objects
|
|
2868
|
+
*/
|
|
2794
2869
|
async list(params) {
|
|
2795
2870
|
let results = Array.from(this.bindings.values()).filter((b) => {
|
|
2796
2871
|
if (b.tenantId !== params.tenantId) return false;
|
|
@@ -2803,6 +2878,12 @@ var InMemoryBindingStore = class {
|
|
|
2803
2878
|
const limit = params.limit ?? 50;
|
|
2804
2879
|
return results.slice(offset, offset + limit);
|
|
2805
2880
|
}
|
|
2881
|
+
/**
|
|
2882
|
+
* Bulk-imports bindings.
|
|
2883
|
+
*
|
|
2884
|
+
* @param bindings - Array of {@link CreateBindingInput}
|
|
2885
|
+
* @returns Array of created {@link Binding} objects
|
|
2886
|
+
*/
|
|
2806
2887
|
async import(bindings) {
|
|
2807
2888
|
const result = [];
|
|
2808
2889
|
for (const input of bindings) {
|
|
@@ -2810,9 +2891,18 @@ var InMemoryBindingStore = class {
|
|
|
2810
2891
|
}
|
|
2811
2892
|
return result;
|
|
2812
2893
|
}
|
|
2894
|
+
/**
|
|
2895
|
+
* Exports all bindings for a tenant.
|
|
2896
|
+
*
|
|
2897
|
+
* @param params - Filter by tenantId
|
|
2898
|
+
* @returns Array of {@link Binding} objects
|
|
2899
|
+
*/
|
|
2813
2900
|
async export(params) {
|
|
2814
2901
|
return this.list({ tenantId: params.tenantId, limit: 1e4 });
|
|
2815
2902
|
}
|
|
2903
|
+
/**
|
|
2904
|
+
* Clears all in-memory bindings. Primarily used in tests.
|
|
2905
|
+
*/
|
|
2816
2906
|
clear() {
|
|
2817
2907
|
this.bindings.clear();
|
|
2818
2908
|
}
|
|
@@ -12113,6 +12203,14 @@ var ThreadStatus2 = /* @__PURE__ */ ((ThreadStatus3) => {
|
|
|
12113
12203
|
return ThreadStatus3;
|
|
12114
12204
|
})(ThreadStatus2 || {});
|
|
12115
12205
|
var Agent = class {
|
|
12206
|
+
/**
|
|
12207
|
+
* Constructs an Agent instance.
|
|
12208
|
+
*
|
|
12209
|
+
* Prefer {@link AgentInstanceManager.getAgent} over direct construction — it
|
|
12210
|
+
* ensures a single instance per thread.
|
|
12211
|
+
*
|
|
12212
|
+
* @param params - {@link AgentThreadInterface}
|
|
12213
|
+
*/
|
|
12116
12214
|
constructor({
|
|
12117
12215
|
assistant_id,
|
|
12118
12216
|
thread_id,
|
|
@@ -12325,6 +12423,7 @@ var Agent = class {
|
|
|
12325
12423
|
await this.queueStore?.removeMessage(p.id);
|
|
12326
12424
|
const runStatus = await this.getRunStatus();
|
|
12327
12425
|
const state = await this.getCurrentState();
|
|
12426
|
+
const customRunConfig = p.custom_run_config ?? queueMessageData.custom_run_config;
|
|
12328
12427
|
if (runStatus === "interrupted" /* INTERRUPTED */) {
|
|
12329
12428
|
this.publish("message:interrupted", {
|
|
12330
12429
|
type: "message:interrupted",
|
|
@@ -12349,6 +12448,12 @@ var Agent = class {
|
|
|
12349
12448
|
state
|
|
12350
12449
|
});
|
|
12351
12450
|
}
|
|
12451
|
+
this.publish("reply:ready", {
|
|
12452
|
+
type: "reply:ready",
|
|
12453
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
12454
|
+
state,
|
|
12455
|
+
customRunConfig
|
|
12456
|
+
});
|
|
12352
12457
|
} catch (error) {
|
|
12353
12458
|
console.error(`STEER/Command message ${p.id} execution failed:`, error);
|
|
12354
12459
|
this.addChunk({
|
|
@@ -12427,6 +12532,12 @@ var Agent = class {
|
|
|
12427
12532
|
});
|
|
12428
12533
|
}
|
|
12429
12534
|
}
|
|
12535
|
+
this.publish("reply:ready", {
|
|
12536
|
+
type: "reply:ready",
|
|
12537
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
12538
|
+
state,
|
|
12539
|
+
customRunConfig: remainingPendings[0]?.custom_run_config ?? firstQueueMessage?.custom_run_config
|
|
12540
|
+
});
|
|
12430
12541
|
} catch (error) {
|
|
12431
12542
|
console.error(`COLLECT mode execution failed:`, error);
|
|
12432
12543
|
for (const p of remainingPendings) {
|
|
@@ -12475,6 +12586,7 @@ var Agent = class {
|
|
|
12475
12586
|
await this.queueStore?.removeMessage(p.id);
|
|
12476
12587
|
const runStatus = await this.getRunStatus();
|
|
12477
12588
|
const state = await this.getCurrentState();
|
|
12589
|
+
const customRunConfig = p.custom_run_config ?? queueMessageData.custom_run_config;
|
|
12478
12590
|
if (runStatus === "interrupted" /* INTERRUPTED */) {
|
|
12479
12591
|
this.publish("message:interrupted", {
|
|
12480
12592
|
type: "message:interrupted",
|
|
@@ -12499,6 +12611,12 @@ var Agent = class {
|
|
|
12499
12611
|
state
|
|
12500
12612
|
});
|
|
12501
12613
|
}
|
|
12614
|
+
this.publish("reply:ready", {
|
|
12615
|
+
type: "reply:ready",
|
|
12616
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
12617
|
+
state,
|
|
12618
|
+
customRunConfig
|
|
12619
|
+
});
|
|
12502
12620
|
} catch (error) {
|
|
12503
12621
|
console.error(`FOLLOWUP mode message ${p.id} execution failed:`, error);
|
|
12504
12622
|
this.addChunk({
|
|
@@ -12541,9 +12659,25 @@ var Agent = class {
|
|
|
12541
12659
|
setQueueStore(store) {
|
|
12542
12660
|
this.queueStore = store;
|
|
12543
12661
|
}
|
|
12662
|
+
/**
|
|
12663
|
+
* Push a chunk into the streaming buffer for this thread.
|
|
12664
|
+
*
|
|
12665
|
+
* Consumers read chunks via {@link chunkStream}.
|
|
12666
|
+
*
|
|
12667
|
+
* @param content - The message chunk to buffer
|
|
12668
|
+
*/
|
|
12544
12669
|
addChunk(content) {
|
|
12545
12670
|
return this.chunkBuffer.addChunk(this.thread_id, content);
|
|
12546
12671
|
}
|
|
12672
|
+
/**
|
|
12673
|
+
* Returns an async iterator over new chunks since the given message ID.
|
|
12674
|
+
*
|
|
12675
|
+
* Used by SSE endpoints to stream agent output to clients in real time.
|
|
12676
|
+
*
|
|
12677
|
+
* @param message_id - The client message ID to start streaming from
|
|
12678
|
+
* @param stopTypes - Optional chunk types that terminate the stream
|
|
12679
|
+
* @returns An async iterable yielding {@link MessageChunk} objects
|
|
12680
|
+
*/
|
|
12547
12681
|
chunkStream(message_id, stopTypes) {
|
|
12548
12682
|
const stream = this.chunkBuffer.getNewChunksSinceContentIterator(
|
|
12549
12683
|
this.thread_id,
|
|
@@ -12632,13 +12766,21 @@ var Agent = class {
|
|
|
12632
12766
|
};
|
|
12633
12767
|
}
|
|
12634
12768
|
/**
|
|
12635
|
-
*
|
|
12769
|
+
* Override the thread's queue processing mode.
|
|
12770
|
+
*
|
|
12771
|
+
* @param config - Partial {@link ThreadQueueConfig} (e.g. `{ mode: QueueMode.FOLLOWUP }`)
|
|
12636
12772
|
*/
|
|
12637
12773
|
async setQueueConfig(config) {
|
|
12638
12774
|
this.queueMode = { ...this.queueMode, ...config };
|
|
12639
12775
|
}
|
|
12640
12776
|
/**
|
|
12641
|
-
*
|
|
12777
|
+
* Abort any ongoing queue processing without clearing the queue.
|
|
12778
|
+
*
|
|
12779
|
+
* Used internally by STEER mode to interrupt the current execution so the
|
|
12780
|
+
* steer message can be processed next. For a full abort that also clears
|
|
12781
|
+
* pending messages, use {@link abort}.
|
|
12782
|
+
*
|
|
12783
|
+
* @see {@link abort}
|
|
12642
12784
|
*/
|
|
12643
12785
|
stopQueueProcessor() {
|
|
12644
12786
|
if (this.abortController) {
|
|
@@ -12647,14 +12789,34 @@ var Agent = class {
|
|
|
12647
12789
|
}
|
|
12648
12790
|
}
|
|
12649
12791
|
/**
|
|
12650
|
-
*
|
|
12651
|
-
*
|
|
12652
|
-
*
|
|
12653
|
-
*
|
|
12654
|
-
*
|
|
12655
|
-
*
|
|
12656
|
-
* -
|
|
12657
|
-
* -
|
|
12792
|
+
* Enqueue a message for this thread.
|
|
12793
|
+
*
|
|
12794
|
+
* Messages are always queued; the queue processor starts automatically if idle.
|
|
12795
|
+
* Returns immediately with the message ID — execution is asynchronous.
|
|
12796
|
+
*
|
|
12797
|
+
* **Queue modes** (via the optional `mode` param):
|
|
12798
|
+
* - `COLLECT` (default) — Batch multiple pending messages into one agent call.
|
|
12799
|
+
* - `FOLLOWUP` — Process messages one at a time in order.
|
|
12800
|
+
* - `STEER` — High-priority, inserted at queue head, interrupts current processing.
|
|
12801
|
+
*
|
|
12802
|
+
* **Format**: Supports both `input.message` (legacy string) and `input.messages[]`
|
|
12803
|
+
* (array of `{ role, content }` objects). The array form takes precedence.
|
|
12804
|
+
*
|
|
12805
|
+
* The `custom_run_config` field is round-tripped through the queue and emitted
|
|
12806
|
+
* back in {@link ReplyReadyEvent}, enabling callers to attach routing metadata
|
|
12807
|
+
* (e.g. `_replyTarget` for channel reply).
|
|
12808
|
+
*
|
|
12809
|
+
* @param queueMessage - The message to enqueue
|
|
12810
|
+
* @param mode - Optional queue mode override (defaults to thread's current mode)
|
|
12811
|
+
* @returns `{ queued: true, executed: false, messageId }` — execution happens asynchronously
|
|
12812
|
+
*
|
|
12813
|
+
* @example
|
|
12814
|
+
* ```ts
|
|
12815
|
+
* await agent.addMessage({
|
|
12816
|
+
* input: { message: "Hello" },
|
|
12817
|
+
* custom_run_config: { _replyTarget: { adapterChannel: "lark", rawTarget: { chatId: "xxx" } } },
|
|
12818
|
+
* });
|
|
12819
|
+
* ```
|
|
12658
12820
|
*/
|
|
12659
12821
|
async addMessage(queueMessage, mode) {
|
|
12660
12822
|
const useMode = mode ?? this.queueMode.mode;
|
|
@@ -12748,8 +12910,13 @@ var Agent = class {
|
|
|
12748
12910
|
return { queued: true, executed: false, messageId };
|
|
12749
12911
|
}
|
|
12750
12912
|
/**
|
|
12751
|
-
* Start queue processor if not already running
|
|
12752
|
-
*
|
|
12913
|
+
* Start the queue processor if it is not already running.
|
|
12914
|
+
*
|
|
12915
|
+
* Called automatically by {@link addMessage} and {@link resumeTask}.
|
|
12916
|
+
* Safe to call externally — it is a no-op if processing is already active.
|
|
12917
|
+
*
|
|
12918
|
+
* Emits `thread:busy` before starting, and starts the {@link waitingForQueueEnd}
|
|
12919
|
+
* loop with a fresh {@link AbortController}.
|
|
12753
12920
|
*/
|
|
12754
12921
|
async startQueueProcessorIfNeeded() {
|
|
12755
12922
|
const store = this.getQueueStore();
|
|
@@ -12797,6 +12964,12 @@ var Agent = class {
|
|
|
12797
12964
|
type: "system"
|
|
12798
12965
|
});
|
|
12799
12966
|
}
|
|
12967
|
+
/**
|
|
12968
|
+
* Returns a LangGraph StateSnapshot for this thread.
|
|
12969
|
+
*
|
|
12970
|
+
* Includes `state.values.messages` (full conversation history) and
|
|
12971
|
+
* `state.tasks` / `state.next` (execution progress).
|
|
12972
|
+
*/
|
|
12800
12973
|
async getCurrentState() {
|
|
12801
12974
|
const { runnable_agent } = await this.getLatticeClientAndRuntimeConfig();
|
|
12802
12975
|
const state = await runnable_agent.getState({
|
|
@@ -12804,6 +12977,14 @@ var Agent = class {
|
|
|
12804
12977
|
});
|
|
12805
12978
|
return state;
|
|
12806
12979
|
}
|
|
12980
|
+
/**
|
|
12981
|
+
* Returns the conversation history as normalized message objects.
|
|
12982
|
+
*
|
|
12983
|
+
* Filters to `human`, `ai`, and `tool` message types. Each entry has
|
|
12984
|
+
* `{ id, role, content }` plus any LangChain kwargs.
|
|
12985
|
+
*
|
|
12986
|
+
* @returns Array of message objects with `id`, `role`, and `content`
|
|
12987
|
+
*/
|
|
12807
12988
|
async getCurrentMessages() {
|
|
12808
12989
|
const state = await this.getCurrentState();
|
|
12809
12990
|
const messages = state.values.messages || [];
|
|
@@ -12826,6 +13007,14 @@ var Agent = class {
|
|
|
12826
13007
|
const image = await drawableGraph.drawMermaid();
|
|
12827
13008
|
return image;
|
|
12828
13009
|
}
|
|
13010
|
+
/**
|
|
13011
|
+
* Determine the current thread execution status.
|
|
13012
|
+
*
|
|
13013
|
+
* Checks LangGraph's `state.tasks` for interrupts and `state.next` for
|
|
13014
|
+
* pending steps.
|
|
13015
|
+
*
|
|
13016
|
+
* @returns {@link ThreadStatus} — `IDLE`, `BUSY`, or `INTERRUPTED`
|
|
13017
|
+
*/
|
|
12829
13018
|
async getRunStatus() {
|
|
12830
13019
|
const state = await this.getCurrentState();
|
|
12831
13020
|
const isInterrupted = state.tasks?.some(
|
|
@@ -12840,9 +13029,14 @@ var Agent = class {
|
|
|
12840
13029
|
return "idle" /* IDLE */;
|
|
12841
13030
|
}
|
|
12842
13031
|
/**
|
|
12843
|
-
* Resume
|
|
12844
|
-
*
|
|
12845
|
-
*
|
|
13032
|
+
* Resume processing after a server restart.
|
|
13033
|
+
*
|
|
13034
|
+
* Resets any stuck "processing" messages back to "pending" and restarts the
|
|
13035
|
+
* queue processor. Skips threads that are in `INTERRUPTED` state (the
|
|
13036
|
+
* interruption was intentional).
|
|
13037
|
+
*
|
|
13038
|
+
* Called during gateway startup to recover threads that were mid-execution
|
|
13039
|
+
* when the server went down.
|
|
12846
13040
|
*/
|
|
12847
13041
|
async resumeTask() {
|
|
12848
13042
|
try {
|
|
@@ -12864,9 +13058,14 @@ var Agent = class {
|
|
|
12864
13058
|
await this.startQueueProcessorIfNeeded();
|
|
12865
13059
|
}
|
|
12866
13060
|
/**
|
|
12867
|
-
*
|
|
12868
|
-
*
|
|
12869
|
-
*
|
|
13061
|
+
* Fully abort all activity on this thread.
|
|
13062
|
+
*
|
|
13063
|
+
* Aborts any in-flight agent execution (via {@link AbortController}) and
|
|
13064
|
+
* clears all pending and processing messages from the queue. Also marks
|
|
13065
|
+
* the chunk buffer thread as aborted so streaming consumers can detect it.
|
|
13066
|
+
*
|
|
13067
|
+
* Unlike {@link stopQueueProcessor}, this is a destructive abort — the
|
|
13068
|
+
* queue is drained.
|
|
12870
13069
|
*/
|
|
12871
13070
|
async abort() {
|
|
12872
13071
|
if (this.abortController) {
|
|
@@ -12884,22 +13083,44 @@ var Agent = class {
|
|
|
12884
13083
|
return this.abortController?.signal.aborted ?? false;
|
|
12885
13084
|
}
|
|
12886
13085
|
/**
|
|
12887
|
-
* Subscribe to lifecycle
|
|
12888
|
-
*
|
|
13086
|
+
* Subscribe to a lifecycle event for this specific thread.
|
|
13087
|
+
*
|
|
13088
|
+
* Event names are namespaced as `{eventName}:{tenantId}:{threadId}` so
|
|
13089
|
+
* listeners only receive events for this agent instance.
|
|
13090
|
+
*
|
|
13091
|
+
* @param eventName - One of {@link AgentLifecycleEventName}
|
|
13092
|
+
* @param callback - Handler receiving the event data payload
|
|
13093
|
+
*
|
|
13094
|
+
* @example
|
|
13095
|
+
* ```ts
|
|
13096
|
+
* agent.subscribe("message:completed", (evt) => {
|
|
13097
|
+
* console.log("AI response:", evt.state?.values?.messages);
|
|
13098
|
+
* });
|
|
13099
|
+
* ```
|
|
12889
13100
|
*/
|
|
12890
13101
|
subscribe(eventName, callback) {
|
|
12891
13102
|
const namespacedEvent = `${eventName}:${this.tenant_id}:${this.thread_id}`;
|
|
12892
13103
|
event_bus_default.subscribe(namespacedEvent, callback);
|
|
12893
13104
|
}
|
|
12894
13105
|
/**
|
|
12895
|
-
*
|
|
13106
|
+
* Remove a previously registered event listener.
|
|
13107
|
+
*
|
|
13108
|
+
* @param eventName - The event that was subscribed to
|
|
13109
|
+
* @param callback - The same function reference used in {@link subscribe}
|
|
12896
13110
|
*/
|
|
12897
13111
|
unsubscribe(eventName, callback) {
|
|
12898
13112
|
const namespacedEvent = `${eventName}:${this.tenant_id}:${this.thread_id}`;
|
|
12899
13113
|
event_bus_default.unsubscribe(namespacedEvent, callback);
|
|
12900
13114
|
}
|
|
12901
13115
|
/**
|
|
12902
|
-
* Subscribe to lifecycle
|
|
13116
|
+
* Subscribe to a lifecycle event once — the listener is removed after the
|
|
13117
|
+
* first invocation.
|
|
13118
|
+
*
|
|
13119
|
+
* Ideal for one-shot async patterns (e.g. waiting for `reply:ready` before
|
|
13120
|
+
* sending a channel reply).
|
|
13121
|
+
*
|
|
13122
|
+
* @param eventName - One of {@link AgentLifecycleEventName}
|
|
13123
|
+
* @param callback - Handler receiving the event data payload
|
|
12903
13124
|
*/
|
|
12904
13125
|
subscribeOnce(eventName, callback) {
|
|
12905
13126
|
const namespacedEvent = `${eventName}:${this.tenant_id}:${this.thread_id}`;
|
|
@@ -12913,6 +13134,12 @@ var Agent = class {
|
|
|
12913
13134
|
console.log(namespacedEvent);
|
|
12914
13135
|
event_bus_default.publish(namespacedEvent, data);
|
|
12915
13136
|
}
|
|
13137
|
+
/**
|
|
13138
|
+
* Track a sub-agent async task spawned by this agent.
|
|
13139
|
+
*
|
|
13140
|
+
* Tasks are monitored by the agent task consumer in `packages/gateway`
|
|
13141
|
+
* and their status can be polled via {@link getAsyncTasks}.
|
|
13142
|
+
*/
|
|
12916
13143
|
addAsyncTask(task) {
|
|
12917
13144
|
this.asyncTasks.push(task);
|
|
12918
13145
|
}
|
|
@@ -12922,6 +13149,12 @@ var Agent = class {
|
|
|
12922
13149
|
getAsyncTask(taskId) {
|
|
12923
13150
|
return this.asyncTasks.find((t) => t.taskId === taskId);
|
|
12924
13151
|
}
|
|
13152
|
+
/**
|
|
13153
|
+
* Update the status of a tracked async task.
|
|
13154
|
+
*
|
|
13155
|
+
* Terminal states (`completed`, `failed`, `cancelled`) automatically
|
|
13156
|
+
* set `completedAt` to the current timestamp.
|
|
13157
|
+
*/
|
|
12925
13158
|
updateAsyncTaskStatus(taskId, status) {
|
|
12926
13159
|
const task = this.getAsyncTask(taskId);
|
|
12927
13160
|
if (!task) return;
|
|
@@ -13287,6 +13520,65 @@ function createSchedulerMiddleware(options = {}) {
|
|
|
13287
13520
|
});
|
|
13288
13521
|
}
|
|
13289
13522
|
|
|
13523
|
+
// src/agent_lattice/builders/CustomMiddlewareRegistry.ts
|
|
13524
|
+
var CustomMiddlewareRegistry = class {
|
|
13525
|
+
/**
|
|
13526
|
+
* Register a custom middleware factory under the given key.
|
|
13527
|
+
*
|
|
13528
|
+
* The key is referenced by `config.key` in the database middleware configuration.
|
|
13529
|
+
* When an agent is built, the framework looks up this key and calls the factory
|
|
13530
|
+
* with the remaining config fields.
|
|
13531
|
+
*
|
|
13532
|
+
* @param key - Unique identifier, referenced in database config as `config.key`
|
|
13533
|
+
* @param factory - Function that receives config (minus `key`) and returns an AgentMiddleware
|
|
13534
|
+
*
|
|
13535
|
+
* @example
|
|
13536
|
+
* ```ts
|
|
13537
|
+
* CustomMiddlewareRegistry.register("my-logger", (config) =>
|
|
13538
|
+
* createMiddleware({ name: "Logger", beforeAgent: async () => { ... } }),
|
|
13539
|
+
* );
|
|
13540
|
+
* ```
|
|
13541
|
+
*/
|
|
13542
|
+
static register(key, factory) {
|
|
13543
|
+
this.factories.set(key, factory);
|
|
13544
|
+
}
|
|
13545
|
+
/**
|
|
13546
|
+
* Remove a previously registered factory.
|
|
13547
|
+
*
|
|
13548
|
+
* @param key - The factory key to unregister
|
|
13549
|
+
* @returns `true` if a factory was removed, `false` if the key was not found
|
|
13550
|
+
*/
|
|
13551
|
+
static unregister(key) {
|
|
13552
|
+
return this.factories.delete(key);
|
|
13553
|
+
}
|
|
13554
|
+
/**
|
|
13555
|
+
* Look up a factory by key.
|
|
13556
|
+
*
|
|
13557
|
+
* @param key - The factory key
|
|
13558
|
+
* @returns The factory function, or `undefined` if not registered
|
|
13559
|
+
*/
|
|
13560
|
+
static get(key) {
|
|
13561
|
+
return this.factories.get(key);
|
|
13562
|
+
}
|
|
13563
|
+
/**
|
|
13564
|
+
* Check whether a factory is registered under the given key.
|
|
13565
|
+
*
|
|
13566
|
+
* @param key - The factory key to check
|
|
13567
|
+
*/
|
|
13568
|
+
static has(key) {
|
|
13569
|
+
return this.factories.has(key);
|
|
13570
|
+
}
|
|
13571
|
+
/**
|
|
13572
|
+
* Get all currently registered factory keys.
|
|
13573
|
+
*
|
|
13574
|
+
* @returns Array of registered key strings
|
|
13575
|
+
*/
|
|
13576
|
+
static list() {
|
|
13577
|
+
return Array.from(this.factories.keys());
|
|
13578
|
+
}
|
|
13579
|
+
};
|
|
13580
|
+
CustomMiddlewareRegistry.factories = /* @__PURE__ */ new Map();
|
|
13581
|
+
|
|
13290
13582
|
// src/agent_lattice/builders/commonMiddleware.ts
|
|
13291
13583
|
async function createCommonMiddlewares(middlewareConfigs, filesystemBackend, fsIsExised) {
|
|
13292
13584
|
const middlewares = [];
|
|
@@ -13363,6 +13655,21 @@ async function createCommonMiddlewares(middlewareConfigs, filesystemBackend, fsI
|
|
|
13363
13655
|
case "scheduler":
|
|
13364
13656
|
middlewares.push(createSchedulerMiddleware(config.config));
|
|
13365
13657
|
break;
|
|
13658
|
+
case "custom":
|
|
13659
|
+
{
|
|
13660
|
+
const customConfig = config.config;
|
|
13661
|
+
const { key, ...rest } = customConfig;
|
|
13662
|
+
const factory = CustomMiddlewareRegistry.get(key);
|
|
13663
|
+
if (factory) {
|
|
13664
|
+
const middleware = factory(rest);
|
|
13665
|
+
middlewares.push(middleware instanceof Promise ? await middleware : middleware);
|
|
13666
|
+
} else {
|
|
13667
|
+
console.warn(
|
|
13668
|
+
`[custom middleware] No factory registered for key "${key}". Use CustomMiddlewareRegistry.register("${key}", factory) before building the agent.`
|
|
13669
|
+
);
|
|
13670
|
+
}
|
|
13671
|
+
}
|
|
13672
|
+
break;
|
|
13366
13673
|
}
|
|
13367
13674
|
}
|
|
13368
13675
|
return middlewares;
|
|
@@ -22708,6 +23015,7 @@ function clearEncryptionKeyCache() {
|
|
|
22708
23015
|
CompositeBackend,
|
|
22709
23016
|
ConsoleLoggerClient,
|
|
22710
23017
|
CustomMetricsClient,
|
|
23018
|
+
CustomMiddlewareRegistry,
|
|
22711
23019
|
DaytonaInstance,
|
|
22712
23020
|
DaytonaProvider,
|
|
22713
23021
|
DefaultScheduleClient,
|