@axiom-lattice/core 2.1.76 → 2.1.78

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/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,
@@ -51,7 +52,8 @@ __export(index_exports, {
51
52
  EmbeddingsLatticeManager: () => EmbeddingsLatticeManager,
52
53
  FileSystemSkillStore: () => FileSystemSkillStore,
53
54
  FilesystemBackend: () => FilesystemBackend,
54
- HumanMessage: () => import_messages5.HumanMessage,
55
+ HumanMessage: () => import_messages6.HumanMessage,
56
+ InMemoryA2AApiKeyStore: () => InMemoryA2AApiKeyStore,
55
57
  InMemoryAssistantStore: () => InMemoryAssistantStore,
56
58
  InMemoryBindingStore: () => InMemoryBindingStore,
57
59
  InMemoryChannelInstallationStore: () => InMemoryChannelInstallationStore,
@@ -1893,6 +1895,7 @@ var InMemoryProjectStore = class {
1893
1895
  workspaceId,
1894
1896
  name: data.name,
1895
1897
  description: data.description,
1898
+ config: data.config,
1896
1899
  createdAt: now,
1897
1900
  updatedAt: now
1898
1901
  };
@@ -1900,6 +1903,13 @@ var InMemoryProjectStore = class {
1900
1903
  this.projects.set(key, project);
1901
1904
  return project;
1902
1905
  }
1906
+ /**
1907
+ * Update an existing project
1908
+ *
1909
+ * @remarks
1910
+ * - The `config` field uses **replace** semantics: if provided, it completely
1911
+ * overwrites the existing config. To preserve the current config, omit this field.
1912
+ */
1903
1913
  async updateProject(tenantId, id, updates) {
1904
1914
  const key = this.getKey(tenantId, id);
1905
1915
  const existing = this.projects.get(key);
@@ -2691,14 +2701,35 @@ var InMemoryChannelInstallationStore = class {
2691
2701
  constructor() {
2692
2702
  this.installations = /* @__PURE__ */ new Map();
2693
2703
  }
2704
+ /**
2705
+ * Retrieves a channel installation by its unique ID.
2706
+ *
2707
+ * @param installationId - The installation identifier
2708
+ * @returns The {@link ChannelInstallation} or `null` if not found
2709
+ */
2694
2710
  async getInstallationById(installationId) {
2695
2711
  return this.installations.get(installationId) || null;
2696
2712
  }
2713
+ /**
2714
+ * Lists all channel installations for a tenant, optionally filtered by channel type.
2715
+ *
2716
+ * @param tenantId - Tenant identifier
2717
+ * @param channel - Optional channel type filter (`"lark"`, `"email"`, `"slack"`)
2718
+ * @returns Array of matching {@link ChannelInstallation} objects
2719
+ */
2697
2720
  async getInstallationsByTenant(tenantId, channel) {
2698
2721
  return Array.from(this.installations.values()).filter(
2699
2722
  (inst) => inst.tenantId === tenantId && (!channel || inst.channel === channel)
2700
2723
  );
2701
2724
  }
2725
+ /**
2726
+ * Creates a new channel installation for a tenant.
2727
+ *
2728
+ * @param tenantId - Tenant identifier
2729
+ * @param installationId - Unique installation ID (caller-defined)
2730
+ * @param data - {@link CreateChannelInstallationRequest} containing channel type, name, config, and fallback settings
2731
+ * @returns The created {@link ChannelInstallation}
2732
+ */
2702
2733
  async createInstallation(tenantId, installationId, data) {
2703
2734
  const now = /* @__PURE__ */ new Date();
2704
2735
  const installation = {
@@ -2716,6 +2747,14 @@ var InMemoryChannelInstallationStore = class {
2716
2747
  this.installations.set(installationId, installation);
2717
2748
  return installation;
2718
2749
  }
2750
+ /**
2751
+ * Updates an existing channel installation. Config fields are shallow-merged.
2752
+ *
2753
+ * @param tenantId - Tenant identifier (used for isolation check)
2754
+ * @param installationId - Installation ID to update
2755
+ * @param updates - {@link UpdateChannelInstallationRequest} with fields to patch
2756
+ * @returns The updated {@link ChannelInstallation} or `null` if not found or tenant mismatch
2757
+ */
2719
2758
  async updateInstallation(tenantId, installationId, updates) {
2720
2759
  const existing = this.installations.get(installationId);
2721
2760
  if (!existing || existing.tenantId !== tenantId) return null;
@@ -2731,11 +2770,21 @@ var InMemoryChannelInstallationStore = class {
2731
2770
  this.installations.set(installationId, updated);
2732
2771
  return updated;
2733
2772
  }
2773
+ /**
2774
+ * Deletes a channel installation.
2775
+ *
2776
+ * @param tenantId - Tenant identifier (used for isolation check)
2777
+ * @param installationId - Installation ID to delete
2778
+ * @returns `true` if deleted, `false` if not found or tenant mismatch
2779
+ */
2734
2780
  async deleteInstallation(tenantId, installationId) {
2735
2781
  const existing = this.installations.get(installationId);
2736
2782
  if (!existing || existing.tenantId !== tenantId) return false;
2737
2783
  return this.installations.delete(installationId);
2738
2784
  }
2785
+ /**
2786
+ * Clears all in-memory installations. Primarily used in tests.
2787
+ */
2739
2788
  clear() {
2740
2789
  this.installations.clear();
2741
2790
  }
@@ -2747,6 +2796,16 @@ var InMemoryBindingStore = class {
2747
2796
  constructor() {
2748
2797
  this.bindings = /* @__PURE__ */ new Map();
2749
2798
  }
2799
+ /**
2800
+ * Resolves a binding for the given sender across a specific channel installation.
2801
+ *
2802
+ * Called by `MessageRouter.dispatch()` during inbound message processing.
2803
+ * Matches on `channel + senderId + channelInstallationId + tenantId` and
2804
+ * requires `enabled === true`.
2805
+ *
2806
+ * @param params - Resolution parameters
2807
+ * @returns The matching {@link Binding} or `null` if none found.
2808
+ */
2750
2809
  async resolve(params) {
2751
2810
  for (const binding of this.bindings.values()) {
2752
2811
  if (binding.channel === params.channel && binding.senderId === params.senderId && binding.channelInstallationId === params.channelInstallationId && binding.tenantId === params.tenantId && binding.enabled) {
@@ -2755,6 +2814,12 @@ var InMemoryBindingStore = class {
2755
2814
  }
2756
2815
  return null;
2757
2816
  }
2817
+ /**
2818
+ * Creates a new sender-to-agent binding.
2819
+ *
2820
+ * @param input - {@link CreateBindingInput} defining channel, sender, target agent, and thread mode.
2821
+ * @returns The newly created {@link Binding}.
2822
+ */
2758
2823
  async create(input) {
2759
2824
  const now = /* @__PURE__ */ new Date();
2760
2825
  const binding = {
@@ -2777,6 +2842,14 @@ var InMemoryBindingStore = class {
2777
2842
  this.bindings.set(binding.id, binding);
2778
2843
  return binding;
2779
2844
  }
2845
+ /**
2846
+ * Updates an existing binding (e.g. changing the target agent or thread mode).
2847
+ *
2848
+ * @param id - Binding ID
2849
+ * @param patch - Partial {@link Binding} fields to update
2850
+ * @returns The updated {@link Binding}
2851
+ * @throws {Error} If the binding does not exist
2852
+ */
2780
2853
  async update(id, patch) {
2781
2854
  const existing = this.bindings.get(id);
2782
2855
  if (!existing) throw new Error(`Binding ${id} not found`);
@@ -2788,9 +2861,20 @@ var InMemoryBindingStore = class {
2788
2861
  this.bindings.set(id, updated);
2789
2862
  return updated;
2790
2863
  }
2864
+ /**
2865
+ * Deletes a binding by ID.
2866
+ *
2867
+ * @param id - Binding ID
2868
+ */
2791
2869
  async delete(id) {
2792
2870
  this.bindings.delete(id);
2793
2871
  }
2872
+ /**
2873
+ * Lists bindings filtered by tenant and optional channel/agent/installation.
2874
+ *
2875
+ * @param params - Filter and pagination parameters
2876
+ * @returns Array of matching {@link Binding} objects
2877
+ */
2794
2878
  async list(params) {
2795
2879
  let results = Array.from(this.bindings.values()).filter((b) => {
2796
2880
  if (b.tenantId !== params.tenantId) return false;
@@ -2803,6 +2887,12 @@ var InMemoryBindingStore = class {
2803
2887
  const limit = params.limit ?? 50;
2804
2888
  return results.slice(offset, offset + limit);
2805
2889
  }
2890
+ /**
2891
+ * Bulk-imports bindings.
2892
+ *
2893
+ * @param bindings - Array of {@link CreateBindingInput}
2894
+ * @returns Array of created {@link Binding} objects
2895
+ */
2806
2896
  async import(bindings) {
2807
2897
  const result = [];
2808
2898
  for (const input of bindings) {
@@ -2810,14 +2900,104 @@ var InMemoryBindingStore = class {
2810
2900
  }
2811
2901
  return result;
2812
2902
  }
2903
+ /**
2904
+ * Exports all bindings for a tenant.
2905
+ *
2906
+ * @param params - Filter by tenantId
2907
+ * @returns Array of {@link Binding} objects
2908
+ */
2813
2909
  async export(params) {
2814
2910
  return this.list({ tenantId: params.tenantId, limit: 1e4 });
2815
2911
  }
2912
+ /**
2913
+ * Clears all in-memory bindings. Primarily used in tests.
2914
+ */
2816
2915
  clear() {
2817
2916
  this.bindings.clear();
2818
2917
  }
2819
2918
  };
2820
2919
 
2920
+ // src/store_lattice/InMemoryA2AApiKeyStore.ts
2921
+ var import_crypto2 = require("crypto");
2922
+ function generateApiKey() {
2923
+ return `a2a_${(0, import_crypto2.randomUUID)().replace(/-/g, "")}`;
2924
+ }
2925
+ var InMemoryA2AApiKeyStore = class {
2926
+ constructor() {
2927
+ this.keys = /* @__PURE__ */ new Map();
2928
+ }
2929
+ async findByKey(key) {
2930
+ for (const record of this.keys.values()) {
2931
+ if (record.key === key && record.enabled) return record;
2932
+ }
2933
+ return null;
2934
+ }
2935
+ async list(params) {
2936
+ let records = Array.from(this.keys.values());
2937
+ if (params.tenantId) {
2938
+ records = records.filter((r) => r.tenantId === params.tenantId);
2939
+ }
2940
+ const offset = params.offset || 0;
2941
+ const limit = params.limit;
2942
+ records = records.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
2943
+ return limit ? records.slice(offset, offset + limit) : records.slice(offset);
2944
+ }
2945
+ async create(input) {
2946
+ const now = /* @__PURE__ */ new Date();
2947
+ const record = {
2948
+ id: (0, import_crypto2.randomUUID)(),
2949
+ key: generateApiKey(),
2950
+ tenantId: input.tenantId,
2951
+ projectId: input.projectId,
2952
+ workspaceId: input.workspaceId,
2953
+ label: input.label,
2954
+ enabled: true,
2955
+ createdAt: now,
2956
+ updatedAt: now
2957
+ };
2958
+ this.keys.set(record.id, record);
2959
+ return record;
2960
+ }
2961
+ async disable(id) {
2962
+ const record = this.keys.get(id);
2963
+ if (!record) throw new Error(`A2A API key not found: ${id}`);
2964
+ const updated = { ...record, enabled: false, updatedAt: /* @__PURE__ */ new Date() };
2965
+ this.keys.set(id, updated);
2966
+ return updated;
2967
+ }
2968
+ async enable(id) {
2969
+ const record = this.keys.get(id);
2970
+ if (!record) throw new Error(`A2A API key not found: ${id}`);
2971
+ const updated = { ...record, enabled: true, updatedAt: /* @__PURE__ */ new Date() };
2972
+ this.keys.set(id, updated);
2973
+ return updated;
2974
+ }
2975
+ async rotate(id) {
2976
+ const record = this.keys.get(id);
2977
+ if (!record) throw new Error(`A2A API key not found: ${id}`);
2978
+ const updated = { ...record, key: generateApiKey(), updatedAt: /* @__PURE__ */ new Date() };
2979
+ this.keys.set(id, updated);
2980
+ return updated;
2981
+ }
2982
+ async delete(id) {
2983
+ this.keys.delete(id);
2984
+ }
2985
+ async loadIntoMap() {
2986
+ const map = /* @__PURE__ */ new Map();
2987
+ for (const record of this.keys.values()) {
2988
+ if (record.enabled) {
2989
+ map.set(record.key, {
2990
+ key: record.key,
2991
+ tenantId: record.tenantId,
2992
+ projectId: record.projectId,
2993
+ workspaceId: record.workspaceId
2994
+ });
2995
+ }
2996
+ }
2997
+ return map;
2998
+ }
2999
+ };
3000
+
2821
3001
  // src/store_lattice/StoreLatticeManager.ts
2822
3002
  var StoreLatticeManager = class _StoreLatticeManager extends BaseLatticeManager {
2823
3003
  /**
@@ -2992,6 +3172,12 @@ storeLatticeManager.registerLattice(
2992
3172
  "channelBinding",
2993
3173
  defaultChannelBindingStore
2994
3174
  );
3175
+ var defaultA2AApiKeyStore = new InMemoryA2AApiKeyStore();
3176
+ storeLatticeManager.registerLattice(
3177
+ "default",
3178
+ "a2aApiKey",
3179
+ defaultA2AApiKeyStore
3180
+ );
2995
3181
 
2996
3182
  // src/tool_lattice/manage_binding/index.ts
2997
3183
  function getInstallationStore() {
@@ -7079,7 +7265,7 @@ var createBrowserGetInfoTool = ({ vmIsolation }) => {
7079
7265
  };
7080
7266
 
7081
7267
  // src/index.ts
7082
- var import_messages5 = require("@langchain/core/messages");
7268
+ var import_messages6 = require("@langchain/core/messages");
7083
7269
 
7084
7270
  // src/agent_lattice/types.ts
7085
7271
  var import_protocols = require("@axiom-lattice/protocols");
@@ -12113,6 +12299,14 @@ var ThreadStatus2 = /* @__PURE__ */ ((ThreadStatus3) => {
12113
12299
  return ThreadStatus3;
12114
12300
  })(ThreadStatus2 || {});
12115
12301
  var Agent = class {
12302
+ /**
12303
+ * Constructs an Agent instance.
12304
+ *
12305
+ * Prefer {@link AgentInstanceManager.getAgent} over direct construction — it
12306
+ * ensures a single instance per thread.
12307
+ *
12308
+ * @param params - {@link AgentThreadInterface}
12309
+ */
12116
12310
  constructor({
12117
12311
  assistant_id,
12118
12312
  thread_id,
@@ -12325,6 +12519,7 @@ var Agent = class {
12325
12519
  await this.queueStore?.removeMessage(p.id);
12326
12520
  const runStatus = await this.getRunStatus();
12327
12521
  const state = await this.getCurrentState();
12522
+ const customRunConfig = p.custom_run_config ?? queueMessageData.custom_run_config;
12328
12523
  if (runStatus === "interrupted" /* INTERRUPTED */) {
12329
12524
  this.publish("message:interrupted", {
12330
12525
  type: "message:interrupted",
@@ -12349,6 +12544,12 @@ var Agent = class {
12349
12544
  state
12350
12545
  });
12351
12546
  }
12547
+ this.publish("reply:ready", {
12548
+ type: "reply:ready",
12549
+ timestamp: /* @__PURE__ */ new Date(),
12550
+ state,
12551
+ customRunConfig
12552
+ });
12352
12553
  } catch (error) {
12353
12554
  console.error(`STEER/Command message ${p.id} execution failed:`, error);
12354
12555
  this.addChunk({
@@ -12427,6 +12628,12 @@ var Agent = class {
12427
12628
  });
12428
12629
  }
12429
12630
  }
12631
+ this.publish("reply:ready", {
12632
+ type: "reply:ready",
12633
+ timestamp: /* @__PURE__ */ new Date(),
12634
+ state,
12635
+ customRunConfig: remainingPendings[0]?.custom_run_config ?? firstQueueMessage?.custom_run_config
12636
+ });
12430
12637
  } catch (error) {
12431
12638
  console.error(`COLLECT mode execution failed:`, error);
12432
12639
  for (const p of remainingPendings) {
@@ -12475,6 +12682,7 @@ var Agent = class {
12475
12682
  await this.queueStore?.removeMessage(p.id);
12476
12683
  const runStatus = await this.getRunStatus();
12477
12684
  const state = await this.getCurrentState();
12685
+ const customRunConfig = p.custom_run_config ?? queueMessageData.custom_run_config;
12478
12686
  if (runStatus === "interrupted" /* INTERRUPTED */) {
12479
12687
  this.publish("message:interrupted", {
12480
12688
  type: "message:interrupted",
@@ -12499,6 +12707,12 @@ var Agent = class {
12499
12707
  state
12500
12708
  });
12501
12709
  }
12710
+ this.publish("reply:ready", {
12711
+ type: "reply:ready",
12712
+ timestamp: /* @__PURE__ */ new Date(),
12713
+ state,
12714
+ customRunConfig
12715
+ });
12502
12716
  } catch (error) {
12503
12717
  console.error(`FOLLOWUP mode message ${p.id} execution failed:`, error);
12504
12718
  this.addChunk({
@@ -12541,9 +12755,25 @@ var Agent = class {
12541
12755
  setQueueStore(store) {
12542
12756
  this.queueStore = store;
12543
12757
  }
12758
+ /**
12759
+ * Push a chunk into the streaming buffer for this thread.
12760
+ *
12761
+ * Consumers read chunks via {@link chunkStream}.
12762
+ *
12763
+ * @param content - The message chunk to buffer
12764
+ */
12544
12765
  addChunk(content) {
12545
12766
  return this.chunkBuffer.addChunk(this.thread_id, content);
12546
12767
  }
12768
+ /**
12769
+ * Returns an async iterator over new chunks since the given message ID.
12770
+ *
12771
+ * Used by SSE endpoints to stream agent output to clients in real time.
12772
+ *
12773
+ * @param message_id - The client message ID to start streaming from
12774
+ * @param stopTypes - Optional chunk types that terminate the stream
12775
+ * @returns An async iterable yielding {@link MessageChunk} objects
12776
+ */
12547
12777
  chunkStream(message_id, stopTypes) {
12548
12778
  const stream = this.chunkBuffer.getNewChunksSinceContentIterator(
12549
12779
  this.thread_id,
@@ -12632,13 +12862,21 @@ var Agent = class {
12632
12862
  };
12633
12863
  }
12634
12864
  /**
12635
- * Set queue configuration for thread
12865
+ * Override the thread's queue processing mode.
12866
+ *
12867
+ * @param config - Partial {@link ThreadQueueConfig} (e.g. `{ mode: QueueMode.FOLLOWUP }`)
12636
12868
  */
12637
12869
  async setQueueConfig(config) {
12638
12870
  this.queueMode = { ...this.queueMode, ...config };
12639
12871
  }
12640
12872
  /**
12641
- * Stop queue processor
12873
+ * Abort any ongoing queue processing without clearing the queue.
12874
+ *
12875
+ * Used internally by STEER mode to interrupt the current execution so the
12876
+ * steer message can be processed next. For a full abort that also clears
12877
+ * pending messages, use {@link abort}.
12878
+ *
12879
+ * @see {@link abort}
12642
12880
  */
12643
12881
  stopQueueProcessor() {
12644
12882
  if (this.abortController) {
@@ -12647,14 +12885,34 @@ var Agent = class {
12647
12885
  }
12648
12886
  }
12649
12887
  /**
12650
- * Add message to queue
12651
- * All messages go to queue, processor auto-starts if not running
12652
- * STEER/Command messages are inserted at head of queue for immediate processing
12653
- *
12654
- * Supports both legacy single message format and new messages[] format:
12655
- * - Legacy: input.message (single human message)
12656
- * - New: input.messages[] (array of mixed human/system messages)
12657
- * - When input.messages is provided, it takes precedence over input.message
12888
+ * Enqueue a message for this thread.
12889
+ *
12890
+ * Messages are always queued; the queue processor starts automatically if idle.
12891
+ * Returns immediately with the message ID — execution is asynchronous.
12892
+ *
12893
+ * **Queue modes** (via the optional `mode` param):
12894
+ * - `COLLECT` (default) Batch multiple pending messages into one agent call.
12895
+ * - `FOLLOWUP` — Process messages one at a time in order.
12896
+ * - `STEER` — High-priority, inserted at queue head, interrupts current processing.
12897
+ *
12898
+ * **Format**: Supports both `input.message` (legacy string) and `input.messages[]`
12899
+ * (array of `{ role, content }` objects). The array form takes precedence.
12900
+ *
12901
+ * The `custom_run_config` field is round-tripped through the queue and emitted
12902
+ * back in {@link ReplyReadyEvent}, enabling callers to attach routing metadata
12903
+ * (e.g. `_replyTarget` for channel reply).
12904
+ *
12905
+ * @param queueMessage - The message to enqueue
12906
+ * @param mode - Optional queue mode override (defaults to thread's current mode)
12907
+ * @returns `{ queued: true, executed: false, messageId }` — execution happens asynchronously
12908
+ *
12909
+ * @example
12910
+ * ```ts
12911
+ * await agent.addMessage({
12912
+ * input: { message: "Hello" },
12913
+ * custom_run_config: { _replyTarget: { adapterChannel: "lark", rawTarget: { chatId: "xxx" } } },
12914
+ * });
12915
+ * ```
12658
12916
  */
12659
12917
  async addMessage(queueMessage, mode) {
12660
12918
  const useMode = mode ?? this.queueMode.mode;
@@ -12748,8 +13006,13 @@ var Agent = class {
12748
13006
  return { queued: true, executed: false, messageId };
12749
13007
  }
12750
13008
  /**
12751
- * Start queue processor if not already running
12752
- * Public method to allow external triggering (e.g., from recovery)
13009
+ * Start the queue processor if it is not already running.
13010
+ *
13011
+ * Called automatically by {@link addMessage} and {@link resumeTask}.
13012
+ * Safe to call externally — it is a no-op if processing is already active.
13013
+ *
13014
+ * Emits `thread:busy` before starting, and starts the {@link waitingForQueueEnd}
13015
+ * loop with a fresh {@link AbortController}.
12753
13016
  */
12754
13017
  async startQueueProcessorIfNeeded() {
12755
13018
  const store = this.getQueueStore();
@@ -12797,6 +13060,12 @@ var Agent = class {
12797
13060
  type: "system"
12798
13061
  });
12799
13062
  }
13063
+ /**
13064
+ * Returns a LangGraph StateSnapshot for this thread.
13065
+ *
13066
+ * Includes `state.values.messages` (full conversation history) and
13067
+ * `state.tasks` / `state.next` (execution progress).
13068
+ */
12800
13069
  async getCurrentState() {
12801
13070
  const { runnable_agent } = await this.getLatticeClientAndRuntimeConfig();
12802
13071
  const state = await runnable_agent.getState({
@@ -12804,6 +13073,14 @@ var Agent = class {
12804
13073
  });
12805
13074
  return state;
12806
13075
  }
13076
+ /**
13077
+ * Returns the conversation history as normalized message objects.
13078
+ *
13079
+ * Filters to `human`, `ai`, and `tool` message types. Each entry has
13080
+ * `{ id, role, content }` plus any LangChain kwargs.
13081
+ *
13082
+ * @returns Array of message objects with `id`, `role`, and `content`
13083
+ */
12807
13084
  async getCurrentMessages() {
12808
13085
  const state = await this.getCurrentState();
12809
13086
  const messages = state.values.messages || [];
@@ -12826,6 +13103,14 @@ var Agent = class {
12826
13103
  const image = await drawableGraph.drawMermaid();
12827
13104
  return image;
12828
13105
  }
13106
+ /**
13107
+ * Determine the current thread execution status.
13108
+ *
13109
+ * Checks LangGraph's `state.tasks` for interrupts and `state.next` for
13110
+ * pending steps.
13111
+ *
13112
+ * @returns {@link ThreadStatus} — `IDLE`, `BUSY`, or `INTERRUPTED`
13113
+ */
12829
13114
  async getRunStatus() {
12830
13115
  const state = await this.getCurrentState();
12831
13116
  const isInterrupted = state.tasks?.some(
@@ -12840,9 +13125,14 @@ var Agent = class {
12840
13125
  return "idle" /* IDLE */;
12841
13126
  }
12842
13127
  /**
12843
- * Resume task processing after server restart
12844
- * Resets any stuck processing messages to pending and starts queue processing
12845
- * Note: Does not rely on LangGraph state as it may be stale after crash/restart
13128
+ * Resume processing after a server restart.
13129
+ *
13130
+ * Resets any stuck "processing" messages back to "pending" and restarts the
13131
+ * queue processor. Skips threads that are in `INTERRUPTED` state (the
13132
+ * interruption was intentional).
13133
+ *
13134
+ * Called during gateway startup to recover threads that were mid-execution
13135
+ * when the server went down.
12846
13136
  */
12847
13137
  async resumeTask() {
12848
13138
  try {
@@ -12864,9 +13154,14 @@ var Agent = class {
12864
13154
  await this.startQueueProcessorIfNeeded();
12865
13155
  }
12866
13156
  /**
12867
- * Abort the current agent execution
12868
- * This will cancel any ongoing invoke or stream operations
12869
- * and clear all queued messages (pending + processing)
13157
+ * Fully abort all activity on this thread.
13158
+ *
13159
+ * Aborts any in-flight agent execution (via {@link AbortController}) and
13160
+ * clears all pending and processing messages from the queue. Also marks
13161
+ * the chunk buffer thread as aborted so streaming consumers can detect it.
13162
+ *
13163
+ * Unlike {@link stopQueueProcessor}, this is a destructive abort — the
13164
+ * queue is drained.
12870
13165
  */
12871
13166
  async abort() {
12872
13167
  if (this.abortController) {
@@ -12884,22 +13179,44 @@ var Agent = class {
12884
13179
  return this.abortController?.signal.aborted ?? false;
12885
13180
  }
12886
13181
  /**
12887
- * Subscribe to lifecycle events for this agent/thread
12888
- * Events are automatically namespaced by tenantId and threadId
13182
+ * Subscribe to a lifecycle event for this specific thread.
13183
+ *
13184
+ * Event names are namespaced as `{eventName}:{tenantId}:{threadId}` so
13185
+ * listeners only receive events for this agent instance.
13186
+ *
13187
+ * @param eventName - One of {@link AgentLifecycleEventName}
13188
+ * @param callback - Handler receiving the event data payload
13189
+ *
13190
+ * @example
13191
+ * ```ts
13192
+ * agent.subscribe("message:completed", (evt) => {
13193
+ * console.log("AI response:", evt.state?.values?.messages);
13194
+ * });
13195
+ * ```
12889
13196
  */
12890
13197
  subscribe(eventName, callback) {
12891
13198
  const namespacedEvent = `${eventName}:${this.tenant_id}:${this.thread_id}`;
12892
13199
  event_bus_default.subscribe(namespacedEvent, callback);
12893
13200
  }
12894
13201
  /**
12895
- * Unsubscribe from lifecycle events
13202
+ * Remove a previously registered event listener.
13203
+ *
13204
+ * @param eventName - The event that was subscribed to
13205
+ * @param callback - The same function reference used in {@link subscribe}
12896
13206
  */
12897
13207
  unsubscribe(eventName, callback) {
12898
13208
  const namespacedEvent = `${eventName}:${this.tenant_id}:${this.thread_id}`;
12899
13209
  event_bus_default.unsubscribe(namespacedEvent, callback);
12900
13210
  }
12901
13211
  /**
12902
- * Subscribe to lifecycle events once (auto-unsubscribe after first event)
13212
+ * Subscribe to a lifecycle event once the listener is removed after the
13213
+ * first invocation.
13214
+ *
13215
+ * Ideal for one-shot async patterns (e.g. waiting for `reply:ready` before
13216
+ * sending a channel reply).
13217
+ *
13218
+ * @param eventName - One of {@link AgentLifecycleEventName}
13219
+ * @param callback - Handler receiving the event data payload
12903
13220
  */
12904
13221
  subscribeOnce(eventName, callback) {
12905
13222
  const namespacedEvent = `${eventName}:${this.tenant_id}:${this.thread_id}`;
@@ -12913,6 +13230,12 @@ var Agent = class {
12913
13230
  console.log(namespacedEvent);
12914
13231
  event_bus_default.publish(namespacedEvent, data);
12915
13232
  }
13233
+ /**
13234
+ * Track a sub-agent async task spawned by this agent.
13235
+ *
13236
+ * Tasks are monitored by the agent task consumer in `packages/gateway`
13237
+ * and their status can be polled via {@link getAsyncTasks}.
13238
+ */
12916
13239
  addAsyncTask(task) {
12917
13240
  this.asyncTasks.push(task);
12918
13241
  }
@@ -12922,6 +13245,12 @@ var Agent = class {
12922
13245
  getAsyncTask(taskId) {
12923
13246
  return this.asyncTasks.find((t) => t.taskId === taskId);
12924
13247
  }
13248
+ /**
13249
+ * Update the status of a tracked async task.
13250
+ *
13251
+ * Terminal states (`completed`, `failed`, `cancelled`) automatically
13252
+ * set `completedAt` to the current timestamp.
13253
+ */
12925
13254
  updateAsyncTaskStatus(taskId, status) {
12926
13255
  const task = this.getAsyncTask(taskId);
12927
13256
  if (!task) return;
@@ -13287,6 +13616,65 @@ function createSchedulerMiddleware(options = {}) {
13287
13616
  });
13288
13617
  }
13289
13618
 
13619
+ // src/agent_lattice/builders/CustomMiddlewareRegistry.ts
13620
+ var CustomMiddlewareRegistry = class {
13621
+ /**
13622
+ * Register a custom middleware factory under the given key.
13623
+ *
13624
+ * The key is referenced by `config.key` in the database middleware configuration.
13625
+ * When an agent is built, the framework looks up this key and calls the factory
13626
+ * with the remaining config fields.
13627
+ *
13628
+ * @param key - Unique identifier, referenced in database config as `config.key`
13629
+ * @param factory - Function that receives config (minus `key`) and returns an AgentMiddleware
13630
+ *
13631
+ * @example
13632
+ * ```ts
13633
+ * CustomMiddlewareRegistry.register("my-logger", (config) =>
13634
+ * createMiddleware({ name: "Logger", beforeAgent: async () => { ... } }),
13635
+ * );
13636
+ * ```
13637
+ */
13638
+ static register(key, factory) {
13639
+ this.factories.set(key, factory);
13640
+ }
13641
+ /**
13642
+ * Remove a previously registered factory.
13643
+ *
13644
+ * @param key - The factory key to unregister
13645
+ * @returns `true` if a factory was removed, `false` if the key was not found
13646
+ */
13647
+ static unregister(key) {
13648
+ return this.factories.delete(key);
13649
+ }
13650
+ /**
13651
+ * Look up a factory by key.
13652
+ *
13653
+ * @param key - The factory key
13654
+ * @returns The factory function, or `undefined` if not registered
13655
+ */
13656
+ static get(key) {
13657
+ return this.factories.get(key);
13658
+ }
13659
+ /**
13660
+ * Check whether a factory is registered under the given key.
13661
+ *
13662
+ * @param key - The factory key to check
13663
+ */
13664
+ static has(key) {
13665
+ return this.factories.has(key);
13666
+ }
13667
+ /**
13668
+ * Get all currently registered factory keys.
13669
+ *
13670
+ * @returns Array of registered key strings
13671
+ */
13672
+ static list() {
13673
+ return Array.from(this.factories.keys());
13674
+ }
13675
+ };
13676
+ CustomMiddlewareRegistry.factories = /* @__PURE__ */ new Map();
13677
+
13290
13678
  // src/agent_lattice/builders/commonMiddleware.ts
13291
13679
  async function createCommonMiddlewares(middlewareConfigs, filesystemBackend, fsIsExised) {
13292
13680
  const middlewares = [];
@@ -13363,6 +13751,21 @@ async function createCommonMiddlewares(middlewareConfigs, filesystemBackend, fsI
13363
13751
  case "scheduler":
13364
13752
  middlewares.push(createSchedulerMiddleware(config.config));
13365
13753
  break;
13754
+ case "custom":
13755
+ {
13756
+ const customConfig = config.config;
13757
+ const { key, ...rest } = customConfig;
13758
+ const factory = CustomMiddlewareRegistry.get(key);
13759
+ if (factory) {
13760
+ const middleware = factory(rest);
13761
+ middlewares.push(middleware instanceof Promise ? await middleware : middleware);
13762
+ } else {
13763
+ console.warn(
13764
+ `[custom middleware] No factory registered for key "${key}". Use CustomMiddlewareRegistry.register("${key}", factory) before building the agent.`
13765
+ );
13766
+ }
13767
+ }
13768
+ break;
13366
13769
  }
13367
13770
  }
13368
13771
  return middlewares;
@@ -17969,6 +18372,227 @@ var ProcessingAgentGraphBuilder = class {
17969
18372
  }
17970
18373
  };
17971
18374
 
18375
+ // src/agent_lattice/builders/RemoteAgentGraphBuilder.ts
18376
+ var import_langgraph14 = require("@langchain/langgraph");
18377
+ var import_messages5 = require("@langchain/core/messages");
18378
+
18379
+ // src/services/a2a-client.ts
18380
+ var import_uuid4 = require("uuid");
18381
+ var A2ARemoteError = class extends Error {
18382
+ constructor(message, statusCode, body) {
18383
+ super(message);
18384
+ this.statusCode = statusCode;
18385
+ this.body = body;
18386
+ this.name = "A2ARemoteError";
18387
+ }
18388
+ };
18389
+ var A2ARemoteClient = class {
18390
+ constructor(config) {
18391
+ this.config = config;
18392
+ this.jsonRpcUrl = null;
18393
+ this.card = null;
18394
+ }
18395
+ // ── Resolution ───────────────────────────────────────────────────────────
18396
+ /**
18397
+ * Fetch the agent card and resolve the JSON-RPC endpoint.
18398
+ */
18399
+ async resolve() {
18400
+ if (this.card) return this.card;
18401
+ const resp = await fetch(this.config.agentCardUrl, {
18402
+ signal: AbortSignal.timeout(this.config.timeout ?? 3e4)
18403
+ });
18404
+ if (!resp.ok) {
18405
+ throw new A2ARemoteError(
18406
+ `Failed to fetch agent card: HTTP ${resp.status}`,
18407
+ resp.status
18408
+ );
18409
+ }
18410
+ this.card = await resp.json();
18411
+ const card = this.card;
18412
+ const jsonRpc = card.additionalInterfaces?.find(
18413
+ (i) => i.transport === "JSONRPC"
18414
+ );
18415
+ this.jsonRpcUrl = jsonRpc?.url ?? card.url;
18416
+ return this.card;
18417
+ }
18418
+ // ── Execute ──────────────────────────────────────────────────────────────
18419
+ /**
18420
+ * Send a text prompt to the remote A2A agent and return the response.
18421
+ *
18422
+ * Supports SSE streaming (parses status-update events) and falls back
18423
+ * to polling the task status for non-streaming agents.
18424
+ */
18425
+ async sendMessage(text) {
18426
+ await this.resolve();
18427
+ const taskId = (0, import_uuid4.v4)();
18428
+ const body = JSON.stringify({
18429
+ jsonrpc: "2.0",
18430
+ method: "tasks/send",
18431
+ params: {
18432
+ id: taskId,
18433
+ message: {
18434
+ role: "user",
18435
+ parts: [{ kind: "text", text }]
18436
+ }
18437
+ },
18438
+ id: taskId
18439
+ });
18440
+ const headers = {
18441
+ "Content-Type": "application/json",
18442
+ "Accept": "text/event-stream"
18443
+ };
18444
+ if (this.config.apiKey) {
18445
+ headers["Authorization"] = `Bearer ${this.config.apiKey}`;
18446
+ }
18447
+ const resp = await fetch(this.jsonRpcUrl, {
18448
+ method: "POST",
18449
+ headers,
18450
+ body,
18451
+ signal: AbortSignal.timeout(this.config.timeout ?? 3e5)
18452
+ });
18453
+ if (!resp.ok) {
18454
+ const text2 = await resp.text().catch(() => "");
18455
+ throw new A2ARemoteError(
18456
+ `A2A request failed: HTTP ${resp.status}`,
18457
+ resp.status,
18458
+ text2
18459
+ );
18460
+ }
18461
+ const contentType = resp.headers.get("content-type") ?? "";
18462
+ if (contentType.includes("text/event-stream")) {
18463
+ return this.parseSSE(resp);
18464
+ }
18465
+ const json = await resp.json();
18466
+ return this.extractArtifactText(json);
18467
+ }
18468
+ // ── SSE Parsing ──────────────────────────────────────────────────────────
18469
+ async parseSSE(resp) {
18470
+ if (!resp.body) {
18471
+ throw new A2ARemoteError("Empty response body");
18472
+ }
18473
+ const reader = resp.body.getReader();
18474
+ const decoder = new TextDecoder();
18475
+ let buffer2 = "";
18476
+ let accumulatedText = "";
18477
+ try {
18478
+ while (true) {
18479
+ const { done, value } = await reader.read();
18480
+ if (done) break;
18481
+ buffer2 += decoder.decode(value, { stream: true });
18482
+ const lines = buffer2.split("\n");
18483
+ buffer2 = lines.pop() ?? "";
18484
+ for (const line of lines) {
18485
+ if (line.startsWith("data: ")) {
18486
+ const data = line.slice(6).trim();
18487
+ if (!data) continue;
18488
+ try {
18489
+ const event = JSON.parse(data);
18490
+ this.handleSSEEvent(event, (t) => {
18491
+ accumulatedText += t;
18492
+ });
18493
+ } catch {
18494
+ }
18495
+ }
18496
+ }
18497
+ }
18498
+ if (buffer2.startsWith("data: ")) {
18499
+ const data = buffer2.slice(6).trim();
18500
+ if (data) {
18501
+ try {
18502
+ const event = JSON.parse(data);
18503
+ this.handleSSEEvent(event, (t) => {
18504
+ accumulatedText += t;
18505
+ });
18506
+ } catch {
18507
+ }
18508
+ }
18509
+ }
18510
+ } finally {
18511
+ reader.releaseLock();
18512
+ }
18513
+ return accumulatedText;
18514
+ }
18515
+ handleSSEEvent(event, onText) {
18516
+ const e = event;
18517
+ const messageParts = e.status?.message?.parts;
18518
+ if (messageParts) {
18519
+ for (const part of messageParts) {
18520
+ if (part.text) onText(part.text);
18521
+ }
18522
+ }
18523
+ }
18524
+ // ── Artifact Extraction ──────────────────────────────────────────────────
18525
+ extractArtifactText(task) {
18526
+ const artifacts = task.artifacts ?? [];
18527
+ return artifacts.flatMap((a) => a.parts ?? []).filter((p) => p.text).map((p) => p.text).join("\n");
18528
+ }
18529
+ };
18530
+
18531
+ // src/agent_lattice/builders/RemoteAgentGraphBuilder.ts
18532
+ var import_protocols9 = require("@axiom-lattice/protocols");
18533
+ var RemoteAgentGraphBuilder = class {
18534
+ async build(agentLattice, params) {
18535
+ if (agentLattice.config.type !== import_protocols9.AgentType.A2A_REMOTE) {
18536
+ throw new Error(
18537
+ `RemoteAgentGraphBuilder received wrong agent type: ${agentLattice.config.type}`
18538
+ );
18539
+ }
18540
+ const config = agentLattice.config;
18541
+ const client = new A2ARemoteClient({
18542
+ agentCardUrl: config.agentCardUrl,
18543
+ apiKey: config.apiKey,
18544
+ timeout: config.timeout
18545
+ });
18546
+ await client.resolve();
18547
+ const remoteCallNode = async (state) => {
18548
+ const messages = state.messages ?? [];
18549
+ const text = extractLastHumanMessage(messages);
18550
+ if (!text) {
18551
+ return {
18552
+ messages: [
18553
+ new import_messages5.AIMessage("No text input provided to remote agent.")
18554
+ ]
18555
+ };
18556
+ }
18557
+ try {
18558
+ const fullPrompt = params.prompt ? `${params.prompt}
18559
+
18560
+ User request:
18561
+ ${text}` : text;
18562
+ const response = await client.sendMessage(fullPrompt);
18563
+ return {
18564
+ messages: [new import_messages5.AIMessage(response)]
18565
+ };
18566
+ } catch (error) {
18567
+ const msg = error.message ?? String(error);
18568
+ return {
18569
+ messages: [
18570
+ new import_messages5.AIMessage(`Remote A2A agent error: ${msg}`)
18571
+ ]
18572
+ };
18573
+ }
18574
+ };
18575
+ const workflow = new import_langgraph14.StateGraph(import_langgraph14.MessagesAnnotation).addNode("remote_call", remoteCallNode).addEdge("__start__", "remote_call").addEdge("remote_call", "__end__");
18576
+ return workflow.compile();
18577
+ }
18578
+ };
18579
+ function extractLastHumanMessage(messages) {
18580
+ for (let i = messages.length - 1; i >= 0; i--) {
18581
+ const msg = messages[i];
18582
+ if (msg._getType() === "human") {
18583
+ const content = msg.content;
18584
+ if (typeof content === "string") return content;
18585
+ if (Array.isArray(content)) {
18586
+ return content.filter(
18587
+ (c) => typeof c === "object" && c !== null && c.type === "text"
18588
+ ).map((c) => c.text).join("\n");
18589
+ }
18590
+ return String(content);
18591
+ }
18592
+ }
18593
+ return "";
18594
+ }
18595
+
17972
18596
  // src/agent_lattice/builders/AgentGraphBuilderFactory.ts
17973
18597
  var AgentGraphBuilderFactory = class _AgentGraphBuilderFactory {
17974
18598
  constructor() {
@@ -17992,6 +18616,7 @@ var AgentGraphBuilderFactory = class _AgentGraphBuilderFactory {
17992
18616
  this.builders.set(import_protocols.AgentType.DEEP_AGENT, new DeepAgentGraphBuilder());
17993
18617
  this.builders.set(import_protocols.AgentType.TEAM, new TeamAgentGraphBuilder());
17994
18618
  this.builders.set(import_protocols.AgentType.PROCESSING, new ProcessingAgentGraphBuilder());
18619
+ this.builders.set(import_protocols.AgentType.A2A_REMOTE, new RemoteAgentGraphBuilder());
17995
18620
  }
17996
18621
  /**
17997
18622
  * 注册自定义Builder
@@ -18018,7 +18643,7 @@ var AgentGraphBuilderFactory = class _AgentGraphBuilderFactory {
18018
18643
  };
18019
18644
 
18020
18645
  // src/agent_lattice/builders/AgentParamsBuilder.ts
18021
- var import_protocols9 = require("@axiom-lattice/protocols");
18646
+ var import_protocols10 = require("@axiom-lattice/protocols");
18022
18647
  var AgentParamsBuilder = class {
18023
18648
  /**
18024
18649
  * constructor
@@ -18036,8 +18661,8 @@ var AgentParamsBuilder = class {
18036
18661
  * @returns Agent build parameters
18037
18662
  */
18038
18663
  async buildParams(agentLattice, options) {
18039
- const skills = (0, import_protocols9.isDeepAgentConfig)(agentLattice.config) || (0, import_protocols9.isProcessingAgentConfig)(agentLattice.config) ? agentLattice.config.skillCategories : void 0;
18040
- const toolKeys = options?.overrideTools || (0, import_protocols9.getToolsFromConfig)(agentLattice.config);
18664
+ const skills = (0, import_protocols10.isDeepAgentConfig)(agentLattice.config) || (0, import_protocols10.isProcessingAgentConfig)(agentLattice.config) ? agentLattice.config.skillCategories : void 0;
18665
+ const toolKeys = options?.overrideTools || (0, import_protocols10.getToolsFromConfig)(agentLattice.config);
18041
18666
  const tools = toolKeys.map((toolKey) => {
18042
18667
  const toolLattice = toolLatticeManager.getToolLattice(toolKey);
18043
18668
  if (!toolLattice) {
@@ -18054,7 +18679,7 @@ var AgentParamsBuilder = class {
18054
18679
  if (!model) {
18055
18680
  throw new Error(`Model "${modelKey}" does not exist`);
18056
18681
  }
18057
- const subAgentKeys = (0, import_protocols9.getSubAgentsFromConfig)(agentLattice.config);
18682
+ const subAgentKeys = (0, import_protocols10.getSubAgentsFromConfig)(agentLattice.config);
18058
18683
  const subAgents = await Promise.all(subAgentKeys.map(async (agentKey) => {
18059
18684
  const subAgentLattice = await this.getAgentLatticeFunc(agentKey);
18060
18685
  if (!subAgentLattice) {
@@ -18067,7 +18692,7 @@ var AgentParamsBuilder = class {
18067
18692
  };
18068
18693
  }));
18069
18694
  let internalSubAgents = [];
18070
- if ((0, import_protocols9.isDeepAgentConfig)(agentLattice.config) || (0, import_protocols9.isProcessingAgentConfig)(agentLattice.config)) {
18695
+ if ((0, import_protocols10.isDeepAgentConfig)(agentLattice.config) || (0, import_protocols10.isProcessingAgentConfig)(agentLattice.config)) {
18071
18696
  internalSubAgents = agentLattice.config.internalSubAgents?.map((i) => ({
18072
18697
  key: i.key,
18073
18698
  config: i
@@ -18663,8 +19288,8 @@ ${body}` : `${frontmatter}
18663
19288
 
18664
19289
  // src/agent_lattice/agentArchitectTools.ts
18665
19290
  var import_zod53 = __toESM(require("zod"));
18666
- var import_uuid4 = require("uuid");
18667
- var import_protocols10 = require("@axiom-lattice/protocols");
19291
+ var import_uuid5 = require("uuid");
19292
+ var import_protocols11 = require("@axiom-lattice/protocols");
18668
19293
  function getTenantId(exeConfig) {
18669
19294
  const runConfig = exeConfig?.configurable?.runConfig || {};
18670
19295
  return runConfig.tenantId || "default";
@@ -18772,7 +19397,7 @@ registerToolLattice(
18772
19397
  key: id,
18773
19398
  name: input.name,
18774
19399
  description: input.description || "",
18775
- type: input.type === "deep_agent" ? import_protocols10.AgentType.DEEP_AGENT : import_protocols10.AgentType.REACT,
19400
+ type: input.type === "deep_agent" ? import_protocols11.AgentType.DEEP_AGENT : import_protocols11.AgentType.REACT,
18776
19401
  prompt: input.prompt,
18777
19402
  ...input.tools && input.tools.length > 0 ? { tools: input.tools } : {},
18778
19403
  ...input.middleware && input.middleware.length > 0 ? { middleware: input.middleware } : {},
@@ -18861,7 +19486,7 @@ registerToolLattice(
18861
19486
  key: id,
18862
19487
  name: input.name,
18863
19488
  description: input.description || "",
18864
- type: import_protocols10.AgentType.PROCESSING,
19489
+ type: import_protocols11.AgentType.PROCESSING,
18865
19490
  prompt: input.prompt,
18866
19491
  ...input.tools && input.tools.length > 0 ? { tools: input.tools } : {},
18867
19492
  middleware,
@@ -18929,7 +19554,7 @@ registerToolLattice(
18929
19554
  return JSON.stringify({ error: `Agent '${input.id}' not found` });
18930
19555
  }
18931
19556
  const existingConfig = existing.graphDefinition || {};
18932
- if (existingConfig.type !== import_protocols10.AgentType.PROCESSING) {
19557
+ if (existingConfig.type !== import_protocols11.AgentType.PROCESSING) {
18933
19558
  return JSON.stringify({ error: `Agent '${input.id}' is not a PROCESSING agent (type: ${existingConfig.type})` });
18934
19559
  }
18935
19560
  const normalize = (s) => s.toLowerCase().replace(/[_\-\s]/g, "");
@@ -19137,7 +19762,7 @@ registerToolLattice(
19137
19762
  if (!existing) {
19138
19763
  return JSON.stringify({ error: `Agent '${id}' not found` });
19139
19764
  }
19140
- const threadId = (0, import_uuid4.v4)();
19765
+ const threadId = (0, import_uuid5.v4)();
19141
19766
  const agent = new Agent({
19142
19767
  tenant_id: tenantId,
19143
19768
  assistant_id: id,
@@ -19161,7 +19786,7 @@ registerToolLattice(
19161
19786
  );
19162
19787
 
19163
19788
  // src/agent_lattice/agentArchitectConfig.ts
19164
- var import_protocols12 = require("@axiom-lattice/protocols");
19789
+ var import_protocols13 = require("@axiom-lattice/protocols");
19165
19790
 
19166
19791
  // src/agent_lattice/agentArchitectPrompt.ts
19167
19792
  var AGENT_ARCHITECT_PROMPT = `# Agent Architect
@@ -19801,7 +20426,7 @@ Updates a PROCESSING agent's topology edges, name, prompt, or sub-agents. Unlike
19801
20426
  `;
19802
20427
 
19803
20428
  // src/agent_lattice/agentReviewerConfig.ts
19804
- var import_protocols11 = require("@axiom-lattice/protocols");
20429
+ var import_protocols12 = require("@axiom-lattice/protocols");
19805
20430
 
19806
20431
  // src/agent_lattice/agentReviewerPrompt.ts
19807
20432
  var AGENT_REVIEWER_PROMPT = `# Agent Reviewer
@@ -19864,7 +20489,7 @@ var agentReviewerConfig = {
19864
20489
  key: AGENT_REVIEWER_KEY,
19865
20490
  name: "Agent Reviewer",
19866
20491
  description: "Review and test AI agents. Use this agent to check agent configurations for correctness and to test agents by invoking them with realistic messages.",
19867
- type: import_protocols11.AgentType.REACT,
20492
+ type: import_protocols12.AgentType.REACT,
19868
20493
  prompt: AGENT_REVIEWER_PROMPT,
19869
20494
  tools: [
19870
20495
  "invoke_agent",
@@ -19890,7 +20515,7 @@ var agentArchitectConfig = {
19890
20515
  key: AGENT_ARCHITECT_KEY,
19891
20516
  name: "Agent Architect",
19892
20517
  description: "Design and manage AI agents through natural language conversation. Use this agent when you want to create a new agent, modify an existing agent, or manage your agent collection (list, view, update, delete).",
19893
- type: import_protocols12.AgentType.DEEP_AGENT,
20518
+ type: import_protocols13.AgentType.DEEP_AGENT,
19894
20519
  prompt: AGENT_ARCHITECT_PROMPT,
19895
20520
  tools: [
19896
20521
  "list_agents",
@@ -20556,7 +21181,7 @@ var getVectorStoreLattice = (key) => vectorStoreLatticeManager.getVectorStoreLat
20556
21181
  var getVectorStoreClient = (key) => vectorStoreLatticeManager.getVectorStoreClient(key);
20557
21182
 
20558
21183
  // src/logger_lattice/LoggerLatticeManager.ts
20559
- var import_protocols13 = require("@axiom-lattice/protocols");
21184
+ var import_protocols14 = require("@axiom-lattice/protocols");
20560
21185
 
20561
21186
  // src/logger_lattice/PinoLoggerClient.ts
20562
21187
  var import_pino = __toESM(require("pino"));
@@ -20778,11 +21403,11 @@ var LoggerLatticeManager = class _LoggerLatticeManager extends BaseLatticeManage
20778
21403
  if (client) {
20779
21404
  loggerClient = client;
20780
21405
  } else {
20781
- if (config.type === import_protocols13.LoggerType.PINO) {
21406
+ if (config.type === import_protocols14.LoggerType.PINO) {
20782
21407
  loggerClient = new PinoLoggerClient(config);
20783
- } else if (config.type === import_protocols13.LoggerType.CONSOLE) {
21408
+ } else if (config.type === import_protocols14.LoggerType.CONSOLE) {
20784
21409
  loggerClient = new ConsoleLoggerClient(config);
20785
- } else if (config.type === import_protocols13.LoggerType.CUSTOM) {
21410
+ } else if (config.type === import_protocols14.LoggerType.CUSTOM) {
20786
21411
  throw new Error(
20787
21412
  `Custom logger client must be provided. Please pass the client to registerLattice.`
20788
21413
  );
@@ -22632,7 +23257,7 @@ function createSandboxProvider(config) {
22632
23257
  var Protocols = __toESM(require("@axiom-lattice/protocols"));
22633
23258
 
22634
23259
  // src/util/encryption.ts
22635
- var import_crypto2 = require("crypto");
23260
+ var import_crypto3 = require("crypto");
22636
23261
  var ALGORITHM = "aes-256-gcm";
22637
23262
  var IV_LENGTH = 16;
22638
23263
  var SALT_LENGTH = 32;
@@ -22645,7 +23270,7 @@ function getEncryptionKey() {
22645
23270
  return cachedKey;
22646
23271
  }
22647
23272
  const key = process.env.LATTICE_ENCRYPTION_KEY || DEFAULT_ENCRYPTION_KEY;
22648
- cachedKey = (0, import_crypto2.pbkdf2Sync)(key, "lattice-encryption-salt", ITERATIONS, 32, "sha256");
23273
+ cachedKey = (0, import_crypto3.pbkdf2Sync)(key, "lattice-encryption-salt", ITERATIONS, 32, "sha256");
22649
23274
  if (!keyValidated) {
22650
23275
  keyValidated = true;
22651
23276
  validateEncryptionKey();
@@ -22654,10 +23279,10 @@ function getEncryptionKey() {
22654
23279
  }
22655
23280
  function encrypt(plaintext, key) {
22656
23281
  const actualKey = key || getEncryptionKey();
22657
- const salt = (0, import_crypto2.randomBytes)(SALT_LENGTH);
22658
- const iv = (0, import_crypto2.randomBytes)(IV_LENGTH);
22659
- const derivedKey = (0, import_crypto2.pbkdf2Sync)(actualKey, salt, ITERATIONS, 32, "sha256");
22660
- const cipher = (0, import_crypto2.createCipheriv)(ALGORITHM, derivedKey, iv);
23282
+ const salt = (0, import_crypto3.randomBytes)(SALT_LENGTH);
23283
+ const iv = (0, import_crypto3.randomBytes)(IV_LENGTH);
23284
+ const derivedKey = (0, import_crypto3.pbkdf2Sync)(actualKey, salt, ITERATIONS, 32, "sha256");
23285
+ const cipher = (0, import_crypto3.createCipheriv)(ALGORITHM, derivedKey, iv);
22661
23286
  const encrypted = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
22662
23287
  const authTag = cipher.getAuthTag();
22663
23288
  return Buffer.concat([salt, iv, encrypted, authTag]).toString("base64");
@@ -22669,8 +23294,8 @@ function decrypt(encrypted, key) {
22669
23294
  const iv = data.subarray(SALT_LENGTH, SALT_LENGTH + IV_LENGTH);
22670
23295
  const authTag = data.subarray(-16);
22671
23296
  const ciphertext = data.subarray(SALT_LENGTH + IV_LENGTH, -16);
22672
- const derivedKey = (0, import_crypto2.pbkdf2Sync)(actualKey, salt, ITERATIONS, 32, "sha256");
22673
- const decipher = (0, import_crypto2.createDecipheriv)(ALGORITHM, derivedKey, iv);
23297
+ const derivedKey = (0, import_crypto3.pbkdf2Sync)(actualKey, salt, ITERATIONS, 32, "sha256");
23298
+ const decipher = (0, import_crypto3.createDecipheriv)(ALGORITHM, derivedKey, iv);
22674
23299
  decipher.setAuthTag(authTag);
22675
23300
  return Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString("utf8");
22676
23301
  }
@@ -22708,6 +23333,7 @@ function clearEncryptionKeyCache() {
22708
23333
  CompositeBackend,
22709
23334
  ConsoleLoggerClient,
22710
23335
  CustomMetricsClient,
23336
+ CustomMiddlewareRegistry,
22711
23337
  DaytonaInstance,
22712
23338
  DaytonaProvider,
22713
23339
  DefaultScheduleClient,
@@ -22718,6 +23344,7 @@ function clearEncryptionKeyCache() {
22718
23344
  FileSystemSkillStore,
22719
23345
  FilesystemBackend,
22720
23346
  HumanMessage,
23347
+ InMemoryA2AApiKeyStore,
22721
23348
  InMemoryAssistantStore,
22722
23349
  InMemoryBindingStore,
22723
23350
  InMemoryChannelInstallationStore,