@axiom-lattice/core 2.1.42 → 2.1.43

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.mjs CHANGED
@@ -6471,36 +6471,35 @@ var InMemoryThreadMessageQueueStore = class {
6471
6471
  }
6472
6472
  async addMessageAtHead(threadId, content, type = "system") {
6473
6473
  const threadMessages = this.getMessagesForThread(threadId);
6474
- threadMessages.forEach((msg) => {
6475
- msg.sequence += 1;
6476
- });
6477
6474
  let tenantId = "default";
6478
6475
  let assistantId = "";
6479
6476
  if (threadMessages.length > 0) {
6480
6477
  tenantId = threadMessages[0].tenantId || "default";
6481
6478
  assistantId = threadMessages[0].assistantId || "";
6482
6479
  }
6480
+ const nextSequence = threadMessages.length;
6483
6481
  const message = {
6484
6482
  id: this.generateId(),
6485
6483
  content,
6486
6484
  type,
6487
- sequence: 0,
6485
+ sequence: nextSequence,
6488
6486
  createdAt: /* @__PURE__ */ new Date(),
6489
6487
  status: "pending",
6490
6488
  tenantId,
6491
6489
  assistantId,
6492
- priority: 0
6490
+ priority: 100
6491
+ // High priority for head messages (STEER/Command)
6493
6492
  };
6494
- threadMessages.unshift(message);
6493
+ threadMessages.push(message);
6495
6494
  return message;
6496
6495
  }
6497
6496
  async getPendingMessages(threadId) {
6498
6497
  const threadMessages = this.getMessagesForThread(threadId);
6499
- return threadMessages.filter((msg) => msg.status === "pending" || !msg.status).sort((a, b) => a.sequence - b.sequence).map(({ status, tenantId, assistantId, ...message }) => message);
6498
+ return threadMessages.filter((msg) => msg.status === "pending" || !msg.status).sort((a, b) => (b.priority || 0) - (a.priority || 0) || a.sequence - b.sequence).map(({ status, tenantId, assistantId, ...message }) => message);
6500
6499
  }
6501
6500
  async getProcessingMessages(threadId) {
6502
6501
  const threadMessages = this.getMessagesForThread(threadId);
6503
- return threadMessages.filter((msg) => msg.status === "processing").sort((a, b) => a.sequence - b.sequence).map(({ status, tenantId, assistantId, ...message }) => message);
6502
+ return threadMessages.filter((msg) => msg.status === "processing").sort((a, b) => (b.priority || 0) - (a.priority || 0) || a.sequence - b.sequence).map(({ status, tenantId, assistantId, ...message }) => message);
6504
6503
  }
6505
6504
  async getQueueSize(threadId) {
6506
6505
  const pending = await this.getPendingMessages(threadId);
@@ -6509,11 +6508,11 @@ var InMemoryThreadMessageQueueStore = class {
6509
6508
  async getThreadsWithPendingMessages() {
6510
6509
  const result = [];
6511
6510
  for (const [threadId, messages] of this.messages.entries()) {
6512
- const pendingMessages = messages.filter(
6513
- (msg) => msg.status === "pending" || !msg.status
6511
+ const pendingOrProcessingMessages = messages.filter(
6512
+ (msg) => msg.status === "pending" || msg.status === "processing" || !msg.status
6514
6513
  );
6515
- if (pendingMessages.length > 0) {
6516
- const firstMessage = pendingMessages[0];
6514
+ if (pendingOrProcessingMessages.length > 0) {
6515
+ const firstMessage = pendingOrProcessingMessages[0];
6517
6516
  result.push({
6518
6517
  tenantId: firstMessage.tenantId || "default",
6519
6518
  assistantId: firstMessage.assistantId || "",
@@ -6563,6 +6562,20 @@ var InMemoryThreadMessageQueueStore = class {
6563
6562
  this.messages.set(threadId, filtered);
6564
6563
  }
6565
6564
  }
6565
+ async resetProcessingToPending(threadId) {
6566
+ const messages = this.messages.get(threadId);
6567
+ if (!messages) {
6568
+ return 0;
6569
+ }
6570
+ let count = 0;
6571
+ for (const msg of messages) {
6572
+ if (msg.status === "processing") {
6573
+ msg.status = "pending";
6574
+ count++;
6575
+ }
6576
+ }
6577
+ return count;
6578
+ }
6566
6579
  };
6567
6580
 
6568
6581
  // src/store_lattice/StoreLatticeManager.ts
@@ -9897,7 +9910,7 @@ import {
9897
9910
  ToolMessage as ToolMessage3,
9898
9911
  humanInTheLoopMiddleware
9899
9912
  } from "langchain";
9900
- import { Command as Command2, getCurrentTaskInput as getCurrentTaskInput2 } from "@langchain/langgraph";
9913
+ import { Command as Command2, getCurrentTaskInput as getCurrentTaskInput2, GraphInterrupt as GraphInterrupt3 } from "@langchain/langgraph";
9901
9914
  import { HumanMessage } from "@langchain/core/messages";
9902
9915
 
9903
9916
  // src/agent_worker/agent_worker_graph.ts
@@ -10595,6 +10608,9 @@ function createTaskTool(options) {
10595
10608
  }
10596
10609
  return returnCommandWithStateUpdate(result, config.toolCall.id);
10597
10610
  } catch (error) {
10611
+ if (error instanceof GraphInterrupt3) {
10612
+ throw error;
10613
+ }
10598
10614
  return new Command2({
10599
10615
  update: {
10600
10616
  messages: [
@@ -13948,7 +13964,7 @@ var AgentParamsBuilder = class {
13948
13964
  * @param options build options
13949
13965
  * @returns Agent build parameters
13950
13966
  */
13951
- buildParams(agentLattice, options) {
13967
+ async buildParams(agentLattice, options) {
13952
13968
  const skills = isDeepAgentConfig2(agentLattice.config) ? agentLattice.config.skillCategories : void 0;
13953
13969
  const toolKeys = options?.overrideTools || getToolsFromConfig2(agentLattice.config);
13954
13970
  const tools = toolKeys.map((toolKey) => {
@@ -13968,8 +13984,8 @@ var AgentParamsBuilder = class {
13968
13984
  throw new Error(`Model "${modelKey}" does not exist`);
13969
13985
  }
13970
13986
  const subAgentKeys = getSubAgentsFromConfig2(agentLattice.config);
13971
- const subAgents = subAgentKeys.map((agentKey) => {
13972
- const subAgentLattice = this.getAgentLatticeFunc(agentKey);
13987
+ const subAgents = await Promise.all(subAgentKeys.map(async (agentKey) => {
13988
+ const subAgentLattice = await this.getAgentLatticeFunc(agentKey);
13973
13989
  if (!subAgentLattice) {
13974
13990
  throw new Error(`SubAgent "${agentKey}" does not exist`);
13975
13991
  }
@@ -13978,7 +13994,7 @@ var AgentParamsBuilder = class {
13978
13994
  config: subAgentLattice.config,
13979
13995
  client: subAgentLattice.client
13980
13996
  };
13981
- });
13997
+ }));
13982
13998
  let internalSubAgents = [];
13983
13999
  if (isDeepAgentConfig2(agentLattice.config)) {
13984
14000
  internalSubAgents = agentLattice.config.internalSubAgents?.map((i) => ({
@@ -14056,7 +14072,7 @@ var AgentLatticeManager = class _AgentLatticeManager extends BaseLatticeManager
14056
14072
  }
14057
14073
  const config = assistantToConfig(assistant);
14058
14074
  const agentLattice = {
14059
- config,
14075
+ config: { ...config, tenantId },
14060
14076
  client: void 0
14061
14077
  };
14062
14078
  return agentLattice;
@@ -14363,13 +14379,13 @@ var AgentLatticeManager = class _AgentLatticeManager extends BaseLatticeManager
14363
14379
  * @param options 构建选项
14364
14380
  * @returns 返回Agent构建参数
14365
14381
  */
14366
- buildAgentParams(agentLattice, options) {
14382
+ async buildAgentParams(agentLattice, options) {
14367
14383
  const tenantId = agentLattice.config.tenantId || "default";
14368
- const paramsBuilder = new AgentParamsBuilder((key) => {
14369
- this.initializeClient(tenantId, key);
14384
+ const paramsBuilder = new AgentParamsBuilder(async (key) => {
14385
+ await this.initializeClientAsync(tenantId, key);
14370
14386
  return this.getAgentLatticeWithTenant(tenantId, key);
14371
14387
  });
14372
- const params = paramsBuilder.buildParams(agentLattice, options);
14388
+ const params = await paramsBuilder.buildParams(agentLattice, options);
14373
14389
  return {
14374
14390
  ...params,
14375
14391
  tenantId
@@ -14390,7 +14406,7 @@ var AgentLatticeManager = class _AgentLatticeManager extends BaseLatticeManager
14390
14406
  };
14391
14407
  const factory = AgentGraphBuilderFactory.getInstance();
14392
14408
  const builder = factory.getBuilder(resolvedConfig.type);
14393
- const params = this.buildAgentParams(resolvedLattice, options);
14409
+ const params = await this.buildAgentParams(resolvedLattice, options);
14394
14410
  return await builder.build(resolvedLattice, params);
14395
14411
  }
14396
14412
  /**
@@ -16818,7 +16834,7 @@ var Agent = class {
16818
16834
  command,
16819
16835
  custom_run_config
16820
16836
  }, signal) => {
16821
- const runnable_agent = await getAgentClient(this.tenant_id, this.assistant_id);
16837
+ const runnable_agent = await getAgentClientAsync(this.tenant_id, this.assistant_id);
16822
16838
  const agentLattice = agentLatticeManager.getAgentLatticeWithTenant(this.tenant_id, this.assistant_id);
16823
16839
  const { messages, ...rest } = input;
16824
16840
  const lifecycleManager = this;
@@ -16955,10 +16971,12 @@ var Agent = class {
16955
16971
  const input = {
16956
16972
  messages: [new HumanMessage2({ id: p.content.id, content: p.content.message })]
16957
16973
  };
16974
+ const queueMessageData = p.content.queueMessage || {};
16958
16975
  try {
16959
16976
  await this.agentStreamExecutor({
16960
16977
  input,
16961
- command: p.content.command
16978
+ command: queueMessageData.command || p.content.command,
16979
+ custom_run_config: queueMessageData.custom_run_config
16962
16980
  }, signal);
16963
16981
  await this.queueStore?.markCompleted(p.id);
16964
16982
  const runStatus = await this.getRunStatus();
@@ -17022,8 +17040,12 @@ var Agent = class {
17022
17040
  queueMode: "collect" /* COLLECT */
17023
17041
  });
17024
17042
  });
17043
+ const firstQueueMessage = remainingPendings[0]?.content?.queueMessage || {};
17025
17044
  try {
17026
- await this.agentStreamExecutor({ input: { messages: userMessages } }, signal);
17045
+ await this.agentStreamExecutor({
17046
+ input: { messages: userMessages },
17047
+ custom_run_config: firstQueueMessage.custom_run_config
17048
+ }, signal);
17027
17049
  const runStatus = await this.getRunStatus();
17028
17050
  const state = await this.getCurrentState();
17029
17051
  for (const p of remainingPendings) {
@@ -17085,8 +17107,12 @@ var Agent = class {
17085
17107
  timestamp: /* @__PURE__ */ new Date(),
17086
17108
  queueMode: "followup" /* FOLLOWUP */
17087
17109
  });
17110
+ const queueMessageData = p.content.queueMessage || {};
17088
17111
  try {
17089
- await this.agentStreamExecutor({ input: { messages: [message] } }, signal);
17112
+ await this.agentStreamExecutor({
17113
+ input: { messages: [message] },
17114
+ custom_run_config: queueMessageData.custom_run_config
17115
+ }, signal);
17090
17116
  await this.queueStore?.markCompleted(p.id);
17091
17117
  const runStatus = await this.getRunStatus();
17092
17118
  const state = await this.getCurrentState();
@@ -17267,11 +17293,14 @@ var Agent = class {
17267
17293
  }
17268
17294
  const content = {
17269
17295
  message: queueMessage.input.message,
17270
- id: messageId
17296
+ id: messageId,
17297
+ // Store complete queue message data for recovery
17298
+ queueMessage: {
17299
+ input: queueMessage.input,
17300
+ command: queueMessage.command,
17301
+ custom_run_config: queueMessage.custom_run_config
17302
+ }
17271
17303
  };
17272
- if (queueMessage.command) {
17273
- content.command = queueMessage.command;
17274
- }
17275
17304
  if (isHighPriority) {
17276
17305
  await store.addMessageAtHead(this.thread_id, content, "human");
17277
17306
  } else {
@@ -17299,7 +17328,7 @@ var Agent = class {
17299
17328
  }
17300
17329
  /**
17301
17330
  * Start queue processor if not already running
17302
- * Private method used internally by addMessage
17331
+ * Public method to allow external triggering (e.g., from recovery)
17303
17332
  */
17304
17333
  async startQueueProcessorIfNeeded() {
17305
17334
  const store = this.getQueueStore();
@@ -17387,6 +17416,30 @@ var Agent = class {
17387
17416
  }
17388
17417
  return "idle" /* IDLE */;
17389
17418
  }
17419
+ /**
17420
+ * Resume task processing after server restart
17421
+ * Resets any stuck processing messages to pending and starts queue processing
17422
+ * Note: Does not rely on LangGraph state as it may be stale after crash/restart
17423
+ */
17424
+ async resumeTask() {
17425
+ try {
17426
+ await agentLatticeManager.initializeClientAsync(this.tenant_id, this.assistant_id);
17427
+ } catch (error) {
17428
+ console.error(`[Agent] Failed to initialize agent lattice for ${this.assistant_id} (tenant: ${this.tenant_id}):`, error);
17429
+ throw error;
17430
+ }
17431
+ const runStatus = await this.getRunStatus();
17432
+ if (runStatus === "interrupted" /* INTERRUPTED */) {
17433
+ console.log(`[Agent] Skipping resume for ${this.assistant_id} (tenant: ${this.tenant_id}) - agent is in interrupted state`);
17434
+ return;
17435
+ }
17436
+ const store = this.getQueueStore();
17437
+ const resetCount = await store.resetProcessingToPending(this.thread_id);
17438
+ if (resetCount > 0) {
17439
+ console.log(`[Agent] Reset ${resetCount} processing messages to pending for thread ${this.thread_id}`);
17440
+ }
17441
+ await this.startQueueProcessorIfNeeded();
17442
+ }
17390
17443
  /**
17391
17444
  * Abort the current agent execution
17392
17445
  * This will cancel any ongoing invoke or stream operations
@@ -17496,6 +17549,57 @@ var AgentInstanceManager = class _AgentInstanceManager {
17496
17549
  });
17497
17550
  this.agents.clear();
17498
17551
  }
17552
+ /**
17553
+ * Restore agent instances for threads with pending messages after server restart
17554
+ * Queries the message queue store for threads with pending/processing messages
17555
+ * and recreates agent instances to resume processing
17556
+ */
17557
+ async restore() {
17558
+ const stats = { restored: 0, errors: 0 };
17559
+ try {
17560
+ const queueStoreLattice = storeLatticeManager.getStoreLattice("default", "threadMessageQueue");
17561
+ const queueStore = queueStoreLattice.store;
17562
+ const threadsWithPending = await queueStore.getThreadsWithPendingMessages();
17563
+ if (threadsWithPending.length === 0) {
17564
+ console.log("[AgentInstanceManager] No threads with pending messages found");
17565
+ return stats;
17566
+ }
17567
+ console.log(`[AgentInstanceManager] Found ${threadsWithPending.length} threads with pending messages, restoring...`);
17568
+ for (const threadInfo of threadsWithPending) {
17569
+ try {
17570
+ await this.restoreThread(threadInfo, queueStore);
17571
+ stats.restored++;
17572
+ } catch (error) {
17573
+ console.error(`[AgentInstanceManager] Failed to restore thread ${threadInfo.threadId}:`, error);
17574
+ stats.errors++;
17575
+ }
17576
+ }
17577
+ console.log(`[AgentInstanceManager] Restore complete: ${stats.restored} restored, ${stats.errors} errors`);
17578
+ return stats;
17579
+ } catch (error) {
17580
+ console.error("[AgentInstanceManager] Restore failed:", error);
17581
+ throw error;
17582
+ }
17583
+ }
17584
+ /**
17585
+ * Restore a single thread
17586
+ * Delegates actual recovery logic to Agent.resumeTask()
17587
+ */
17588
+ async restoreThread(threadInfo, queueStore) {
17589
+ const { tenantId, assistantId, threadId } = threadInfo;
17590
+ const threadParams = {
17591
+ tenant_id: tenantId,
17592
+ assistant_id: assistantId,
17593
+ thread_id: threadId,
17594
+ workspace_id: "default",
17595
+ // TODO: Get from thread store
17596
+ project_id: "default"
17597
+ // TODO: Get from thread store
17598
+ };
17599
+ const agent = this.getAgent(threadParams);
17600
+ await agent.resumeTask();
17601
+ console.log(`[AgentInstanceManager] Restored thread ${threadId}`);
17602
+ }
17499
17603
  };
17500
17604
  var agentInstanceManager = AgentInstanceManager.getInstance();
17501
17605