@axiom-lattice/core 3.0.3 → 3.0.5

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
@@ -9035,7 +9035,7 @@ var createReactAgentSchema = (schema6) => {
9035
9035
  };
9036
9036
 
9037
9037
  // src/agent_lattice/builders/ReActAgentGraphBuilder.ts
9038
- var import_langchain45 = require("langchain");
9038
+ var import_langchain47 = require("langchain");
9039
9039
 
9040
9040
  // src/middlewares/codeEvalMiddleware.ts
9041
9041
  var import_langchain37 = require("langchain");
@@ -11249,8 +11249,11 @@ Please select a valid tool from the list above.`
11249
11249
  * The only place to access request.tools (all available tools).
11250
11250
  * Identifies unknown tools and stores error info in metadata.
11251
11251
  *
11252
- * Key: Preserve all tool_calls in original AIMessage, including unknown ones.
11253
- * This allows the model to see what it selected in the next round.
11252
+ * Key: Strip valid tool_calls and only keep unknown ones in the returned
11253
+ * AIMessage. Valid calls must NOT be preserved: afterModel jumps to "model"
11254
+ * and skips ToolNode, so a preserved valid call would have no ToolMessage
11255
+ * and the next model call would be rejected with a 400 dangling tool_calls
11256
+ * error. Stripped valid calls are re-issued by the model in the next round.
11254
11257
  */
11255
11258
  wrapModelCall: async (request, handler) => {
11256
11259
  const availableTools = request.tools || [];
@@ -11280,10 +11283,11 @@ Please select a valid tool from the list above.`
11280
11283
  toolCallId: toolCall.id,
11281
11284
  errorMessage: errorMessageTemplate(toolCall.name, availableToolNames)
11282
11285
  }));
11286
+ const unknownToolIds = new Set(unknownToolCalls.map((toolCall) => toolCall.id));
11287
+ const remainingToolCalls = aiResponse.tool_calls.filter((toolCall) => unknownToolIds.has(toolCall.id));
11283
11288
  const modifiedResponse = new import_messages2.AIMessage({
11284
11289
  content: aiResponse.content,
11285
- tool_calls: aiResponse.tool_calls,
11286
- // Key: preserve all tool_calls, don't delete unknown
11290
+ tool_calls: remainingToolCalls,
11287
11291
  response_metadata: {
11288
11292
  ...aiResponse.response_metadata,
11289
11293
  _unknownToolErrors: unknownToolErrors
@@ -11336,6 +11340,64 @@ Please select a valid tool from the list above.`
11336
11340
  });
11337
11341
  }
11338
11342
 
11343
+ // src/deep_agent_new/middleware/patch_tool_calls.ts
11344
+ var import_langchain45 = require("langchain");
11345
+ function createPatchToolCallsMiddleware() {
11346
+ return (0, import_langchain45.createMiddleware)({
11347
+ name: "patchToolCallsMiddleware",
11348
+ beforeAgent: async (state) => {
11349
+ const messages = state.messages;
11350
+ if (!messages || messages.length === 0) {
11351
+ return;
11352
+ }
11353
+ const replacements = [];
11354
+ for (let i = 0; i < messages.length; i++) {
11355
+ const msg = messages[i];
11356
+ if (import_langchain45.AIMessage.isInstance(msg) && msg.tool_calls != null) {
11357
+ const respondedIds = /* @__PURE__ */ new Set();
11358
+ for (const toolCall of msg.tool_calls) {
11359
+ if (!toolCall.id) continue;
11360
+ const correspondingToolMsg = messages.slice(i).find(
11361
+ (m) => import_langchain45.ToolMessage.isInstance(m) && m.tool_call_id === toolCall.id
11362
+ );
11363
+ if (correspondingToolMsg) {
11364
+ respondedIds.add(toolCall.id);
11365
+ }
11366
+ }
11367
+ const remainingToolCalls = msg.tool_calls.filter(
11368
+ (toolCall) => toolCall.id && respondedIds.has(toolCall.id)
11369
+ );
11370
+ if (remainingToolCalls.length === msg.tool_calls.length) {
11371
+ continue;
11372
+ }
11373
+ const additionalKwargs = { ...msg.additional_kwargs };
11374
+ delete additionalKwargs.tool_calls;
11375
+ if (!msg.id) continue;
11376
+ replacements.push(
11377
+ new import_langchain45.AIMessage({
11378
+ id: msg.id,
11379
+ content: msg.content,
11380
+ name: msg.name,
11381
+ tool_calls: remainingToolCalls,
11382
+ additional_kwargs: additionalKwargs,
11383
+ response_metadata: msg.response_metadata
11384
+ })
11385
+ );
11386
+ }
11387
+ }
11388
+ if (replacements.length === 0) {
11389
+ return;
11390
+ }
11391
+ return {
11392
+ messages: replacements
11393
+ };
11394
+ }
11395
+ });
11396
+ }
11397
+
11398
+ // src/agent_lattice/builders/commonMiddleware.ts
11399
+ var import_langchain46 = require("langchain");
11400
+
11339
11401
  // src/plugin/metaSerializer.ts
11340
11402
  function tryExtractTools(plugin) {
11341
11403
  if (!plugin.middleware) return [];
@@ -12572,6 +12634,12 @@ actually achieve, not just what to build:
12572
12634
 
12573
12635
  Record the goal model in the parent task's description ([[task-tracking]]).
12574
12636
 
12637
+ **HARD RULE \u2014 never guess the target.** If the goal, expected output,
12638
+ consumer, or usable state is unclear at ANY point before writing test
12639
+ cases, you MUST ask the user via ask_user_to_clarify \u2014 never proceed
12640
+ with an assumed expectation. A test case written against a guessed
12641
+ expectation validates the wrong thing. When in doubt, ask.
12642
+
12575
12643
  ## Goal-Driven Validation (apply to EVERY sub-skill workflow)
12576
12644
 
12577
12645
  The agent evaluates goal achievement ITSELF via multi-dimensional test
@@ -12657,16 +12725,29 @@ Do NOT use reviewer as:
12657
12725
  verification. If findings show config errors, fix and re-check.`,
12658
12726
  "task-tracking": `---
12659
12727
  name: task-tracking
12660
- description: Manage persistent tasks for agent creation workflows. Use
12661
- manage_task to create parent/subtasks, track progress, and resume
12662
- interrupted runs. Applies to ALL agent building processes.
12728
+ description: Manage persistent tasks with manage_task. Universal rule:
12729
+ once the goal is clear and you know what to do, create the task FIRST
12730
+ then execute. Track parent/subtasks, update status to reflect reality,
12731
+ resume interrupted work. Applies to ANY multi-step agent work \u2014 not
12732
+ just agent building.
12663
12733
  metadata:
12664
12734
  domain: agent-building
12665
12735
  verified: unverified
12666
12736
  ---
12667
12737
  # Task Tracking \u2014 manage_task for Agent Workflows
12668
12738
 
12669
- Every agent creation workflow is a multi-step process \u2014 track it.
12739
+ **Task management is the ongoing record of a goal and its acceptance
12740
+ criteria** \u2014 it answers at any moment: what are we achieving, and what
12741
+ does "done" look like. Create a task when the goal is clear; keep its
12742
+ Objective and Acceptance Criteria current as work proceeds; change
12743
+ status only when the criteria are actually met.
12744
+
12745
+ **Universal principle**: whenever the goal is understood and the work
12746
+ is about to start, create a task BEFORE executing. If you can write an
12747
+ Objective and Acceptance Criteria, it deserves a task. This is not
12748
+ optional and not limited to agent-building \u2014 it applies to any
12749
+ multi-step work (learning, building, modifying skills, fixing, anything
12750
+ with a clear goal).
12670
12751
 
12671
12752
  ## When to create (and when NOT)
12672
12753
 
@@ -12683,13 +12764,29 @@ Do NOT create tasks for:
12683
12764
 
12684
12765
  ## Setup
12685
12766
 
12767
+ **A task is a living record of the GOAL + ACCEPTANCE CRITERIA** \u2014 not a
12768
+ todo label. Every task's description must carry:
12769
+
12770
+ - **Objective** \u2014 one measurable sentence: what result to achieve
12771
+ - **Acceptance Criteria** \u2014 checkboxes that define "done": when ALL
12772
+ are checked, the task is verifiably complete
12773
+
12774
+ The task is created when the goal is confirmed, and its description is
12775
+ CONTINUALLY UPDATED as the work progresses (spec evolves, criteria are
12776
+ met, new criteria emerge). Status changes only when the criteria are
12777
+ truly met \u2014 never as a workaround.
12778
+
12686
12779
  - **Create the parent task when the scope is confirmed** \u2014 before
12687
12780
  starting the first real work phase (probe/design/build):
12688
- \`manage_task create(title: <goal>, description: <summary>, ownerType: "agent")\`
12781
+ \`manage_task create(title: <goal>, description: <Objective + Acceptance Criteria>, ownerType: "agent")\`
12689
12782
  Record the returned parent task id.
12690
12783
  - **Create a subtask per phase** as you start each phase (probe /
12691
12784
  design / build / eval / retro):
12692
- \`manage_task create(title: <phase>, parentId: <parent>, ownerType: "agent")\`
12785
+ \`manage_task create(title: <phase>, description: <Objective + Acceptance Criteria>, parentId: <parent>, ownerType: "agent")\`
12786
+ - **Update the description as work proceeds**: append progress, mark
12787
+ criteria \`[x]\`, revise criteria when the goal model/spec changes.
12788
+ The task tracks the target and its acceptance \u2014 read it to know what
12789
+ "done" means, keep it current so it always reflects reality.
12693
12790
 
12694
12791
  ## Status discipline \u2014 MANDATORY
12695
12792
 
@@ -12878,6 +12975,10 @@ Always set metadata on agent creation. At minimum:
12878
12975
  - verified: "unverified" (upgraded after eval passes)
12879
12976
  - version: "1.0" (bump on each update_agent)
12880
12977
  - source: the material name or "user-description"
12978
+ - role: "orchestrator" | "sub-agent" \u2014 set when the agent is part of a
12979
+ parent+subAgents structure (role clarity, User Interaction Rules).
12980
+ The eval project is NOT recorded \u2014 it is derived by naming convention
12981
+ (eval-{agent-id}, see [[eval-verify]] Setup).
12881
12982
  When trust upgrades, update both the skill's verified frontmatter and
12882
12983
  the agent's metadata.verified \u2014 they must stay in sync.
12883
12984
 
@@ -12993,16 +13094,32 @@ description: Run agent evaluations, interpret results, fix failures, and
12993
13094
  metadata:
12994
13095
  domain: agent-building
12995
13096
  verified: unverified
13097
+ subSkills:
13098
+ - eval-design-tests
13099
+ - eval-run-and-govern
12996
13100
  ---
12997
13101
  # Eval Verify \u2014 Run Evaluations and Upgrade Trust
12998
13102
 
12999
13103
  ## Setup
13000
13104
 
13001
13105
  0. Load [[eval-design-tests]] for case design guidance
13002
- 1. \`read_eval list_projects\` \u2192 find "eval-{domain}"
13003
- Exists \u2192 reuse projectId. New \u2192 create_project(name: "eval-{domain}")
13106
+ 1. **One eval project per agent**, named \`eval-{agent-id}\`:
13107
+ \`read_eval list_projects\` \u2192 find "eval-{agent-id}"
13108
+ Exists \u2192 reuse projectId. New \u2192 create_project(name: "eval-{agent-id}")
13109
+ - The agent-id is the eval project's subject. Observability: from an
13110
+ agent's id you can find its eval project by naming convention.
13111
+ - Orchestrator + subAgents \u2192 one eval project per sub-agent
13112
+ (eval-{sub-agent-id}) PLUS one integration eval project for the
13113
+ parent (eval-{parent-id}) \u2014 see Layered verification below.
13004
13114
  2. \`manage_eval create_case(suiteId, ...)\` per sample or scenario
13005
13115
  Required: inputMessage, steps=[{agent_id}], outputType, contentAssertion
13116
+ **contentAssertion MUST come from the confirmed expected output spec**
13117
+ (learn-capability Phase 2.6) \u2014 never invent expectations at
13118
+ case-writing time. If a needed expectation is not in the spec, extend
13119
+ the spec with user confirmation first.
13120
+ **HARD RULE**: if the target/expected output is unclear at this
13121
+ point, STOP and ask the user (ask_user_to_clarify) \u2014 do not write a
13122
+ case with a guessed expectation.
13006
13123
 
13007
13124
  ## Suites per skill, by source
13008
13125
 
@@ -13346,10 +13463,20 @@ async function resolveConnections(type, connections, tenantId2) {
13346
13463
  throw err;
13347
13464
  }
13348
13465
  }
13349
- async function createCommonMiddlewares(middlewareConfigs, filesystemBackend, fsIsExised, tenantId2) {
13466
+ async function createCommonMiddlewares(middlewareConfigs, filesystemBackend, fsIsExised, tenantId2, model) {
13350
13467
  const middlewares = [];
13351
13468
  middlewares.push(createUnknownToolHandlerMiddleware());
13352
13469
  middlewares.push(createModelSelectorMiddleware());
13470
+ middlewares.push(createPatchToolCallsMiddleware());
13471
+ if (model) {
13472
+ middlewares.push(
13473
+ (0, import_langchain46.summarizationMiddleware)({
13474
+ model,
13475
+ trigger: { tokens: 17e4 },
13476
+ keep: { messages: 6 }
13477
+ })
13478
+ );
13479
+ }
13353
13480
  const filesystemConfig = middlewareConfigs.find((m) => m.type === "filesystem");
13354
13481
  const clawConfig = middlewareConfigs.find((m) => m.type === "claw");
13355
13482
  const needsFilesystemBackend = filesystemConfig?.enabled || clawConfig?.enabled;
@@ -13681,8 +13808,8 @@ var ReActAgentGraphBuilder = class {
13681
13808
  const stateSchema2 = createReactAgentSchema(params.stateSchema);
13682
13809
  const middlewareConfigs = params.middleware || [];
13683
13810
  const filesystemBackend = createFilesystemBackendFactory(middlewareConfigs);
13684
- const middlewares = await createCommonMiddlewares(middlewareConfigs, filesystemBackend, void 0, params.tenantId);
13685
- return (0, import_langchain45.createAgent)({
13811
+ const middlewares = await createCommonMiddlewares(middlewareConfigs, filesystemBackend, void 0, params.tenantId, params.model);
13812
+ return (0, import_langchain47.createAgent)({
13686
13813
  model: params.model,
13687
13814
  tools,
13688
13815
  systemPrompt: params.prompt,
@@ -13696,11 +13823,11 @@ var ReActAgentGraphBuilder = class {
13696
13823
  };
13697
13824
 
13698
13825
  // src/deep_agent_new/agent.ts
13699
- var import_langchain53 = require("langchain");
13826
+ var import_langchain54 = require("langchain");
13700
13827
 
13701
13828
  // src/deep_agent_new/middleware/subagents.ts
13702
13829
  var import_v32 = require("zod/v3");
13703
- var import_langchain48 = require("langchain");
13830
+ var import_langchain50 = require("langchain");
13704
13831
  var import_langgraph8 = require("@langchain/langgraph");
13705
13832
  var import_messages3 = require("@langchain/core/messages");
13706
13833
 
@@ -14115,7 +14242,7 @@ var QueueMode = /* @__PURE__ */ ((QueueMode2) => {
14115
14242
 
14116
14243
  // src/services/Agent.ts
14117
14244
  var import_langgraph6 = require("@langchain/langgraph");
14118
- var import_langchain46 = require("langchain");
14245
+ var import_langchain48 = require("langchain");
14119
14246
 
14120
14247
  // src/chunk_buffer_lattice/ChunkBuffer.ts
14121
14248
  var ChunkBuffer = class {
@@ -14612,7 +14739,7 @@ var Agent = class {
14612
14739
  });
14613
14740
  const humanContent = p.content;
14614
14741
  const input = {
14615
- messages: [new import_langchain46.HumanMessage({ id: humanContent.id, content: humanContent.message })]
14742
+ messages: [new import_langchain48.HumanMessage({ id: humanContent.id, content: humanContent.message })]
14616
14743
  };
14617
14744
  if (files) {
14618
14745
  input.files = files;
@@ -14686,7 +14813,7 @@ var Agent = class {
14686
14813
  remainingPendings.forEach((p) => {
14687
14814
  this.queueStore?.markProcessing(p.id);
14688
14815
  const humanContent = p.content;
14689
- userMessages.push(new import_langchain46.HumanMessage({ id: humanContent.id, content: humanContent.message }));
14816
+ userMessages.push(new import_langchain48.HumanMessage({ id: humanContent.id, content: humanContent.message }));
14690
14817
  this.publish("message:started", {
14691
14818
  type: "message:started",
14692
14819
  messageId: humanContent.id,
@@ -14766,7 +14893,7 @@ var Agent = class {
14766
14893
  if (signal?.aborted) break;
14767
14894
  await this.queueStore?.markProcessing(p.id);
14768
14895
  const humanContent = p.content;
14769
- const message = new import_langchain46.HumanMessage({ id: humanContent.id, content: humanContent.message });
14896
+ const message = new import_langchain48.HumanMessage({ id: humanContent.id, content: humanContent.message });
14770
14897
  const startTime = Date.now();
14771
14898
  this.publish("message:started", {
14772
14899
  type: "message:started",
@@ -14937,7 +15064,7 @@ var Agent = class {
14937
15064
  const messageId = (0, import_uuid4.v4)();
14938
15065
  const input = {
14939
15066
  ...queueMessage.input,
14940
- messages: [new import_langchain46.HumanMessage({ id: messageId, content: queueMessage.input.message })]
15067
+ messages: [new import_langchain48.HumanMessage({ id: messageId, content: queueMessage.input.message })]
14941
15068
  };
14942
15069
  const inputMessage = { ...queueMessage, input };
14943
15070
  return this.agentExecutor(inputMessage, signal);
@@ -14956,7 +15083,7 @@ var Agent = class {
14956
15083
  const messageId = (0, import_uuid4.v4)();
14957
15084
  const input = {
14958
15085
  ...queueMessage.input,
14959
- messages: [new import_langchain46.HumanMessage({ id: messageId, content: queueMessage.input.message })]
15086
+ messages: [new import_langchain48.HumanMessage({ id: messageId, content: queueMessage.input.message })]
14960
15087
  };
14961
15088
  const inputMessage = { ...queueMessage, input };
14962
15089
  const { runnable_agent, runConfig } = await this.getLatticeClientAndRuntimeConfig(inputMessage.custom_run_config);
@@ -15319,7 +15446,7 @@ var Agent = class {
15319
15446
  async getCurrentMessages() {
15320
15447
  const state = await this.getCurrentState();
15321
15448
  const messages = state.values.messages || [];
15322
- const filteredMessages = (0, import_langchain46.filterMessages)(messages, {
15449
+ const filteredMessages = (0, import_langchain48.filterMessages)(messages, {
15323
15450
  includeTypes: ["ai", "human", "tool"]
15324
15451
  //["human", "ai", "tool"],
15325
15452
  });
@@ -15638,7 +15765,7 @@ var AgentInstanceManager = class _AgentInstanceManager {
15638
15765
  var agentInstanceManager = AgentInstanceManager.getInstance();
15639
15766
 
15640
15767
  // src/middlewares/taskMiddleware.ts
15641
- var import_langchain47 = require("langchain");
15768
+ var import_langchain49 = require("langchain");
15642
15769
  var import_zod43 = require("zod");
15643
15770
  var import_langgraph7 = require("@langchain/langgraph");
15644
15771
  function getRunConfig(config) {
@@ -15946,26 +16073,37 @@ function createTaskMiddleware() {
15946
16073
  });
15947
16074
  }
15948
16075
  };
15949
- return (0, import_langchain47.createMiddleware)({
16076
+ return (0, import_langchain49.createMiddleware)({
15950
16077
  name: "TaskMiddleware",
15951
16078
  contextSchema,
15952
16079
  wrapModelCall: async (request, handler) => {
15953
16080
  const taskPrompt = `## Task Management
15954
16081
 
15955
- You can use the \`manage_task\` tool to create persistent tasks for user-visible work tracking.
16082
+ You have the \`manage_task\` tool to track work. Task management is the
16083
+ ongoing record of a GOAL and its ACCEPTANCE CRITERIA.
15956
16084
 
15957
- ### When to create a task
16085
+ ### When to create a task (universal rule)
16086
+ - The goal is clear and you are about to start real work \u2192 create the
16087
+ parent task FIRST (with Objective + Acceptance Criteria in the
16088
+ description), then execute. This is a core duty, not optional.
15958
16089
  - The user explicitly asks you to track, manage, or follow up on work
15959
16090
  - The work spans multiple sessions or might need resumption later
15960
16091
  - The user needs to review or approve output before it is considered done
15961
16092
  - There are multiple independent work items the user wants visibility into
15962
16093
 
15963
16094
  ### When NOT to create a task
16095
+ - Goal not yet clear (still clarifying) \u2014 clarify first, then create
15964
16096
  - One-shot lookups or simple Q&A ("what is X?", "search for Y")
15965
16097
  - Internal exploration steps you take to understand the problem (use \`write_todos\` for your execution plan instead)
15966
16098
  - Trivial single-step actions that complete in the same turn
15967
16099
  - Conversational or informational requests with no deliverable
15968
16100
 
16101
+ ### Keep the task current
16102
+ A task is the living record of the goal + its acceptance criteria.
16103
+ Update the description as work proceeds: check off criteria as met,
16104
+ revise criteria when scope changes, append progress. Status changes
16105
+ only when the criteria are truly met.
16106
+
15969
16107
  ### Ownership defaults
15970
16108
  - No params: ownerType defaults to "user" with current user's ID
15971
16109
  - ownerType="agent": auto-fills ownerId from current agent (subtask for yourself)
@@ -15976,7 +16114,7 @@ You can use the \`manage_task\` tool to create persistent tasks for user-visible
15976
16114
  });
15977
16115
  },
15978
16116
  tools: [
15979
- (0, import_langchain47.tool)(
16117
+ (0, import_langchain49.tool)(
15980
16118
  handleManageTask,
15981
16119
  {
15982
16120
  name: "manage_task",
@@ -16019,6 +16157,29 @@ var taskPlugin = {
16019
16157
  skills: {
16020
16158
  "task-definition": `## Using manage_task
16021
16159
 
16160
+ ### When to create a task (universal rule)
16161
+
16162
+ Create a task BEFORE executing whenever the goal is clear and you know
16163
+ what to do \u2014 not just for long or complex work:
16164
+
16165
+ - Goal is understood and you are about to start real work \u2192 create the
16166
+ parent task FIRST, then execute. The task tracks the work.
16167
+ - Goal is NOT yet clear (still clarifying, gathering requirements) \u2192
16168
+ do NOT create a task yet. Clarify first, create the task once scope
16169
+ is defined.
16170
+ - One-shot lookups, trivial single-step actions, or internal reasoning
16171
+ \u2192 no task needed.
16172
+
16173
+ Rule of thumb: if you can write an Objective and Acceptance Criteria
16174
+ for it, create the task before doing it. Work without a task = work
16175
+ without a contract.
16176
+
16177
+ **A task is the living record of the goal + its acceptance criteria.**
16178
+ Keep the description current as work proceeds: update the Objective
16179
+ when the target evolves, check off criteria as they are met, revise
16180
+ criteria when scope changes. Reading the task always tells you what
16181
+ "done" means; an outdated task is a broken contract.
16182
+
16022
16183
  ### Task description format
16023
16184
 
16024
16185
  When creating a task with manage_task, write the description in this Markdown structure:
@@ -16220,7 +16381,7 @@ function returnCommandWithStateUpdate(result, toolCallId) {
16220
16381
  update: {
16221
16382
  ...stateUpdate,
16222
16383
  messages: [
16223
- new import_langchain48.ToolMessage({
16384
+ new import_langchain50.ToolMessage({
16224
16385
  content: lastMessage?.content || "Task Failed to complete",
16225
16386
  tool_call_id: toolCallId,
16226
16387
  name: "task"
@@ -16249,10 +16410,10 @@ function getSubagents(options) {
16249
16410
  const generalPurposeMiddleware = [...defaultSubagentMiddleware, ...taskMiddleware];
16250
16411
  if (defaultInterruptOn) {
16251
16412
  generalPurposeMiddleware.push(
16252
- (0, import_langchain48.humanInTheLoopMiddleware)({ interruptOn: defaultInterruptOn })
16413
+ (0, import_langchain50.humanInTheLoopMiddleware)({ interruptOn: defaultInterruptOn })
16253
16414
  );
16254
16415
  }
16255
- const generalPurposeSubagent = (0, import_langchain48.createAgent)({
16416
+ const generalPurposeSubagent = (0, import_langchain50.createAgent)({
16256
16417
  model: defaultModel,
16257
16418
  systemPrompt: DEFAULT_SUBAGENT_PROMPT,
16258
16419
  tools: defaultTools,
@@ -16275,8 +16436,8 @@ function getSubagents(options) {
16275
16436
  const middleware = agentParams.middleware ? [...defaultSubagentMiddleware, ...taskMiddleware, ...agentParams.middleware] : [...defaultSubagentMiddleware, ...taskMiddleware];
16276
16437
  const interruptOn = agentParams.interruptOn || defaultInterruptOn;
16277
16438
  if (interruptOn)
16278
- middleware.push((0, import_langchain48.humanInTheLoopMiddleware)({ interruptOn }));
16279
- agents[agentParams.key] = (0, import_langchain48.createAgent)({
16439
+ middleware.push((0, import_langchain50.humanInTheLoopMiddleware)({ interruptOn }));
16440
+ agents[agentParams.key] = (0, import_langchain50.createAgent)({
16280
16441
  model: agentParams.model ?? defaultModel,
16281
16442
  systemPrompt: agentParams.systemPrompt,
16282
16443
  tools: agentParams.tools ?? defaultTools,
@@ -16326,7 +16487,7 @@ function createTaskTool(options) {
16326
16487
  generalPurposeAgent
16327
16488
  });
16328
16489
  const finalTaskDescription = taskDescription ? taskDescription : getTaskToolDescription(subagentDescriptions);
16329
- return (0, import_langchain48.tool)(
16490
+ return (0, import_langchain50.tool)(
16330
16491
  async (input, config) => {
16331
16492
  const { description, subagent_type, async } = input;
16332
16493
  let assistant_id = subagent_type;
@@ -16413,7 +16574,7 @@ You are executing a persistent task (ID: ${input.taskId}). Use manage_task.updat
16413
16574
  return new import_langgraph8.Command({
16414
16575
  update: {
16415
16576
  messages: [
16416
- new import_langchain48.ToolMessage({
16577
+ new import_langchain50.ToolMessage({
16417
16578
  content: `Async task started: ${subagent_thread_id}
16418
16579
  ${description}
16419
16580
  The result will be delivered as a notification when complete. Do not poll.`,
@@ -16447,7 +16608,7 @@ The result will be delivered as a notification when complete. Do not poll.`,
16447
16608
  return new import_langgraph8.Command({
16448
16609
  update: {
16449
16610
  messages: [
16450
- new import_langchain48.ToolMessage({
16611
+ new import_langchain50.ToolMessage({
16451
16612
  content: error instanceof Error ? error.message : "Task Failed to complete",
16452
16613
  tool_call_id: config.toolCall.id,
16453
16614
  name: "task"
@@ -16490,7 +16651,7 @@ function getMainAgentFromConfig(config) {
16490
16651
  });
16491
16652
  }
16492
16653
  function createCheckAsyncTaskTool() {
16493
- return (0, import_langchain48.tool)(
16654
+ return (0, import_langchain50.tool)(
16494
16655
  async (input, config) => {
16495
16656
  const { task_id } = input;
16496
16657
  const mainAgent = getMainAgentFromConfig(config);
@@ -16557,7 +16718,7 @@ Description: ${cached.description}`;
16557
16718
  );
16558
16719
  }
16559
16720
  function createListAsyncTasksTool() {
16560
- return (0, import_langchain48.tool)(
16721
+ return (0, import_langchain50.tool)(
16561
16722
  async (_input, config) => {
16562
16723
  const mainAgent = getMainAgentFromConfig(config);
16563
16724
  if (!mainAgent) {
@@ -16608,7 +16769,7 @@ function createListAsyncTasksTool() {
16608
16769
  );
16609
16770
  }
16610
16771
  function createCancelAsyncTaskTool() {
16611
- return (0, import_langchain48.tool)(
16772
+ return (0, import_langchain50.tool)(
16612
16773
  async (input, config) => {
16613
16774
  const { task_id } = input;
16614
16775
  const mainAgent = getMainAgentFromConfig(config);
@@ -16684,7 +16845,7 @@ function createSubAgentMiddleware(options) {
16684
16845
  );
16685
16846
  }
16686
16847
  const effectiveSystemPrompt = allowAsync ? systemPrompt + getAsyncPromptText() : systemPrompt;
16687
- return (0, import_langchain48.createMiddleware)({
16848
+ return (0, import_langchain50.createMiddleware)({
16688
16849
  name: "subAgentMiddleware",
16689
16850
  tools: allTools,
16690
16851
  wrapModelCall: async (request, handler) => {
@@ -16703,51 +16864,8 @@ ${effectiveSystemPrompt}` : effectiveSystemPrompt;
16703
16864
  });
16704
16865
  }
16705
16866
 
16706
- // src/deep_agent_new/middleware/patch_tool_calls.ts
16707
- var import_langchain49 = require("langchain");
16708
- function createPatchToolCallsMiddleware() {
16709
- return (0, import_langchain49.createMiddleware)({
16710
- name: "patchToolCallsMiddleware",
16711
- beforeAgent: async (state) => {
16712
- const messages = state.messages;
16713
- if (!messages || messages.length === 0) {
16714
- return;
16715
- }
16716
- const patchedMessages = [];
16717
- for (let i = 0; i < messages.length; i++) {
16718
- const msg = messages[i];
16719
- patchedMessages.push(msg);
16720
- if (import_langchain49.AIMessage.isInstance(msg) && msg.tool_calls != null) {
16721
- for (const toolCall of msg.tool_calls) {
16722
- const correspondingToolMsg = messages.slice(i).find(
16723
- (m) => import_langchain49.ToolMessage.isInstance(m) && m.tool_call_id === toolCall.id
16724
- );
16725
- if (!correspondingToolMsg) {
16726
- const toolMsg = `Tool call ${toolCall.name} with id ${toolCall.id} was cancelled - another message came in before it could be completed.`;
16727
- patchedMessages.push(
16728
- new import_langchain49.ToolMessage({
16729
- content: toolMsg,
16730
- name: toolCall.name,
16731
- tool_call_id: toolCall.id
16732
- })
16733
- );
16734
- }
16735
- }
16736
- }
16737
- }
16738
- if (patchedMessages.length === messages.length) {
16739
- return;
16740
- }
16741
- return {
16742
- messages: patchedMessages.slice(messages.length)
16743
- // only the new ToolMessage patches
16744
- };
16745
- }
16746
- });
16747
- }
16748
-
16749
16867
  // src/deep_agent_new/middleware/date.ts
16750
- var import_langchain50 = require("langchain");
16868
+ var import_langchain51 = require("langchain");
16751
16869
  var import_zod44 = require("zod");
16752
16870
  function formatCurrentDate(timezone = "UTC") {
16753
16871
  const now = /* @__PURE__ */ new Date();
@@ -16776,10 +16894,10 @@ function generateDateContext(timezone = "UTC") {
16776
16894
  function createDateMiddleware(options = {}) {
16777
16895
  const timezone = options.timezone || "UTC";
16778
16896
  const dateContext = generateDateContext(timezone);
16779
- return (0, import_langchain50.createMiddleware)({
16897
+ return (0, import_langchain51.createMiddleware)({
16780
16898
  name: "DateMiddleware",
16781
16899
  tools: [
16782
- (0, import_langchain50.tool)(
16900
+ (0, import_langchain51.tool)(
16783
16901
  async () => {
16784
16902
  const now = /* @__PURE__ */ new Date();
16785
16903
  let validTimezone = timezone;
@@ -16875,7 +16993,7 @@ var datePlugin = {
16875
16993
  };
16876
16994
 
16877
16995
  // src/deep_agent_new/middleware/scheduler.ts
16878
- var import_langchain51 = require("langchain");
16996
+ var import_langchain52 = require("langchain");
16879
16997
  var import_zod45 = require("zod");
16880
16998
  var import_uuid5 = require("uuid");
16881
16999
  var import_protocols8 = require("@axiom-lattice/protocols");
@@ -17944,10 +18062,10 @@ function registerAgentAddMessageHandler() {
17944
18062
  function createSchedulerMiddleware(options = {}) {
17945
18063
  const defaultMaxRetries = options.defaultMaxRetries ?? 0;
17946
18064
  registerAgentAddMessageHandler();
17947
- return (0, import_langchain51.createMiddleware)({
18065
+ return (0, import_langchain52.createMiddleware)({
17948
18066
  name: "SchedulerMiddleware",
17949
18067
  tools: [
17950
- (0, import_langchain51.tool)(
18068
+ (0, import_langchain52.tool)(
17951
18069
  async (input, config) => {
17952
18070
  const runConfig = getRunConfig2(config);
17953
18071
  const scheduleLattice = getScheduleLattice(SCHEDULE_LATTICE_KEY);
@@ -17982,7 +18100,7 @@ function createSchedulerMiddleware(options = {}) {
17982
18100
  })
17983
18101
  }
17984
18102
  ),
17985
- (0, import_langchain51.tool)(
18103
+ (0, import_langchain52.tool)(
17986
18104
  async (input, config) => {
17987
18105
  const runConfig = getRunConfig2(config);
17988
18106
  const scheduleLattice = getScheduleLattice(SCHEDULE_LATTICE_KEY);
@@ -18017,7 +18135,7 @@ function createSchedulerMiddleware(options = {}) {
18017
18135
  })
18018
18136
  }
18019
18137
  ),
18020
- (0, import_langchain51.tool)(
18138
+ (0, import_langchain52.tool)(
18021
18139
  async (input, config) => {
18022
18140
  const runConfig = getRunConfig2(config);
18023
18141
  const scheduleLattice = getScheduleLattice(SCHEDULE_LATTICE_KEY);
@@ -18061,7 +18179,7 @@ function createSchedulerMiddleware(options = {}) {
18061
18179
  })
18062
18180
  }
18063
18181
  ),
18064
- (0, import_langchain51.tool)(
18182
+ (0, import_langchain52.tool)(
18065
18183
  async (input) => {
18066
18184
  const scheduleLattice = getScheduleLattice(SCHEDULE_LATTICE_KEY);
18067
18185
  const success = await scheduleLattice.client.cancel(input.taskId);
@@ -18075,7 +18193,7 @@ function createSchedulerMiddleware(options = {}) {
18075
18193
  })
18076
18194
  }
18077
18195
  ),
18078
- (0, import_langchain51.tool)(
18196
+ (0, import_langchain52.tool)(
18079
18197
  async (input, config) => {
18080
18198
  const runConfig = getRunConfig2(config);
18081
18199
  const scheduleLattice = getScheduleLattice(SCHEDULE_LATTICE_KEY);
@@ -19345,7 +19463,7 @@ var MemoryBackend = class {
19345
19463
  // src/deep_agent_new/middleware/todos.ts
19346
19464
  var import_langgraph9 = require("@langchain/langgraph");
19347
19465
  var import_zod46 = require("zod");
19348
- var import_langchain52 = require("langchain");
19466
+ var import_langchain53 = require("langchain");
19349
19467
  var WRITE_TODOS_DESCRIPTION = `Use this tool to create and manage a structured task list for your current work session. This helps you track progress, organize complex tasks, and demonstrate thoroughness to the user.
19350
19468
  It also helps the user understand the progress of the task and overall progress of their requests.
19351
19469
  Only use this tool if you think it will be helpful in staying organized. If the user's request is trivial and takes less than 3 steps, it is better to NOT use this tool and just do the taks directly.
@@ -19579,13 +19697,13 @@ var TodoSchema = import_zod46.z.object({
19579
19697
  });
19580
19698
  var stateSchema = import_zod46.z.object({ todos: import_zod46.z.array(TodoSchema).default([]) });
19581
19699
  function todoListMiddleware(options) {
19582
- const writeTodos = (0, import_langchain52.tool)(
19700
+ const writeTodos = (0, import_langchain53.tool)(
19583
19701
  ({ todos }, config) => {
19584
19702
  return new import_langgraph9.Command({
19585
19703
  update: {
19586
19704
  todos,
19587
19705
  messages: [
19588
- new import_langchain52.ToolMessage({
19706
+ new import_langchain53.ToolMessage({
19589
19707
  content: genUIMarkdown("todo_list", todos),
19590
19708
  tool_call_id: config.toolCall?.id
19591
19709
  })
@@ -19601,7 +19719,7 @@ function todoListMiddleware(options) {
19601
19719
  })
19602
19720
  }
19603
19721
  );
19604
- return (0, import_langchain52.createMiddleware)({
19722
+ return (0, import_langchain53.createMiddleware)({
19605
19723
  name: "todoListMiddleware",
19606
19724
  stateSchema,
19607
19725
  tools: [writeTodos],
@@ -19652,42 +19770,26 @@ ${BASE_PROMPT}` : BASE_PROMPT;
19652
19770
  createFilesystemMiddleware({
19653
19771
  backend: filesystemBackend
19654
19772
  }),
19655
- // Subagent middleware: Automatic conversation summarization when token limits are approached
19656
- (0, import_langchain53.summarizationMiddleware)({
19657
- model,
19658
- trigger: { tokens: 17e4 },
19659
- keep: { messages: 6 }
19660
- }),
19661
19773
  // Subagent middleware: Anthropic prompt caching for improved performance
19662
- (0, import_langchain53.anthropicPromptCachingMiddleware)({
19774
+ (0, import_langchain54.anthropicPromptCachingMiddleware)({
19663
19775
  unsupportedModelBehavior: "ignore"
19664
19776
  }),
19665
- // Subagent middleware: Patches tool calls for compatibility
19666
- createPatchToolCallsMiddleware(),
19667
19777
  ...customMiddleware
19668
19778
  ],
19669
19779
  defaultInterruptOn: interruptOn,
19670
19780
  subagents,
19671
19781
  generalPurposeAgent: true
19672
19782
  }),
19673
- // Automatically summarizes conversation history when token limits are approached
19674
- (0, import_langchain53.summarizationMiddleware)({
19675
- model,
19676
- trigger: { tokens: 17e4 },
19677
- keep: { messages: 6 }
19678
- }),
19679
19783
  // Enables Anthropic prompt caching for improved performance and reduced costs
19680
- (0, import_langchain53.anthropicPromptCachingMiddleware)({
19784
+ (0, import_langchain54.anthropicPromptCachingMiddleware)({
19681
19785
  unsupportedModelBehavior: "ignore"
19682
- }),
19683
- // Patches tool calls to ensure compatibility across different model providers
19684
- createPatchToolCallsMiddleware()
19786
+ })
19685
19787
  ];
19686
19788
  if (interruptOn) {
19687
- middleware.push((0, import_langchain53.humanInTheLoopMiddleware)({ interruptOn }));
19789
+ middleware.push((0, import_langchain54.humanInTheLoopMiddleware)({ interruptOn }));
19688
19790
  }
19689
19791
  middleware.push(...customMiddleware);
19690
- return (0, import_langchain53.createAgent)({
19792
+ return (0, import_langchain54.createAgent)({
19691
19793
  model,
19692
19794
  systemPrompt: finalSystemPrompt,
19693
19795
  tools,
@@ -19737,7 +19839,7 @@ var DeepAgentGraphBuilder = class {
19737
19839
  }));
19738
19840
  const middlewareConfigs = params.middleware || [];
19739
19841
  const filesystemBackend = createFilesystemBackendFactory(middlewareConfigs);
19740
- const middlewares = await createCommonMiddlewares(middlewareConfigs, filesystemBackend, true, params.tenantId);
19842
+ const middlewares = await createCommonMiddlewares(middlewareConfigs, filesystemBackend, true, params.tenantId, params.model);
19741
19843
  const deepAgent = createDeepAgent({
19742
19844
  tools,
19743
19845
  model: params.model,
@@ -19759,7 +19861,7 @@ init_MemoryLatticeManager();
19759
19861
 
19760
19862
  // src/agent_team/agent_team.ts
19761
19863
  var import_v35 = require("zod/v3");
19762
- var import_langchain56 = require("langchain");
19864
+ var import_langchain57 = require("langchain");
19763
19865
 
19764
19866
  // src/agent_team/types.ts
19765
19867
  var TaskStatus = /* @__PURE__ */ ((TaskStatus3) => {
@@ -20195,13 +20297,13 @@ var InMemoryMailboxStore = class {
20195
20297
 
20196
20298
  // src/agent_team/middleware/team.ts
20197
20299
  var import_v34 = require("zod/v3");
20198
- var import_langchain55 = require("langchain");
20300
+ var import_langchain56 = require("langchain");
20199
20301
  var import_langgraph11 = require("@langchain/langgraph");
20200
20302
  var import_uuid6 = require("uuid");
20201
20303
 
20202
20304
  // src/agent_team/middleware/teammate_tools.ts
20203
20305
  var import_v33 = require("zod/v3");
20204
- var import_langchain54 = require("langchain");
20306
+ var import_langchain55 = require("langchain");
20205
20307
  var import_langgraph10 = require("@langchain/langgraph");
20206
20308
 
20207
20309
  // src/agent_team/middleware/formatMessages.ts
@@ -20226,7 +20328,7 @@ ${meta}${body}`;
20226
20328
  // src/agent_team/middleware/teammate_tools.ts
20227
20329
  function createTeammateTools(options) {
20228
20330
  const { teamId, agentId, taskListStore, mailboxStore } = options;
20229
- const claimTaskTool = (0, import_langchain54.tool)(
20331
+ const claimTaskTool = (0, import_langchain55.tool)(
20230
20332
  async (input) => {
20231
20333
  const task = await taskListStore.claimTaskById(
20232
20334
  teamId,
@@ -20256,7 +20358,7 @@ function createTeammateTools(options) {
20256
20358
  })
20257
20359
  }
20258
20360
  );
20259
- const completeTaskTool = (0, import_langchain54.tool)(
20361
+ const completeTaskTool = (0, import_langchain55.tool)(
20260
20362
  async (input) => {
20261
20363
  const task = await taskListStore.completeTask(
20262
20364
  teamId,
@@ -20283,7 +20385,7 @@ function createTeammateTools(options) {
20283
20385
  })
20284
20386
  }
20285
20387
  );
20286
- const failTaskTool = (0, import_langchain54.tool)(
20388
+ const failTaskTool = (0, import_langchain55.tool)(
20287
20389
  async (input) => {
20288
20390
  const task = await taskListStore.failTask(
20289
20391
  teamId,
@@ -20310,7 +20412,7 @@ function createTeammateTools(options) {
20310
20412
  })
20311
20413
  }
20312
20414
  );
20313
- const sendMessageTool = (0, import_langchain54.tool)(
20415
+ const sendMessageTool = (0, import_langchain55.tool)(
20314
20416
  async (input) => {
20315
20417
  await mailboxStore.sendMessage(
20316
20418
  teamId,
@@ -20348,7 +20450,7 @@ function createTeammateTools(options) {
20348
20450
  read: msg.read
20349
20451
  }));
20350
20452
  };
20351
- const readMessagesTool = (0, import_langchain54.tool)(
20453
+ const readMessagesTool = (0, import_langchain55.tool)(
20352
20454
  async (input, config) => {
20353
20455
  const formatAndMarkAsRead = async (msgs2) => {
20354
20456
  for (const msg of msgs2) {
@@ -20360,7 +20462,7 @@ function createTeammateTools(options) {
20360
20462
  if (msgs.length > 0) {
20361
20463
  const formatted2 = await formatAndMarkAsRead(msgs);
20362
20464
  const relevantMsgs2 = await getRelevantMessagesForState();
20363
- const toolMessage2 = new import_langchain54.ToolMessage({
20465
+ const toolMessage2 = new import_langchain55.ToolMessage({
20364
20466
  content: formatted2,
20365
20467
  tool_call_id: config.toolCall?.id,
20366
20468
  name: "read_messages"
@@ -20385,7 +20487,7 @@ function createTeammateTools(options) {
20385
20487
  });
20386
20488
  const relevantMsgs = await getRelevantMessagesForState();
20387
20489
  if (msgs.length === 0) {
20388
- const toolMessage2 = new import_langchain54.ToolMessage({
20490
+ const toolMessage2 = new import_langchain55.ToolMessage({
20389
20491
  content: "No unread messages.",
20390
20492
  tool_call_id: config.toolCall?.id,
20391
20493
  name: "read_messages"
@@ -20395,7 +20497,7 @@ function createTeammateTools(options) {
20395
20497
  });
20396
20498
  }
20397
20499
  const formatted = await formatAndMarkAsRead(msgs);
20398
- const toolMessage = new import_langchain54.ToolMessage({
20500
+ const toolMessage = new import_langchain55.ToolMessage({
20399
20501
  content: formatted,
20400
20502
  tool_call_id: config.toolCall?.id,
20401
20503
  name: "read_messages"
@@ -20410,7 +20512,7 @@ function createTeammateTools(options) {
20410
20512
  schema: import_v33.z.object({})
20411
20513
  }
20412
20514
  );
20413
- const checkTasksTool = (0, import_langchain54.tool)(
20515
+ const checkTasksTool = (0, import_langchain55.tool)(
20414
20516
  async () => {
20415
20517
  const tasks = await taskListStore.getAllTasks(teamId);
20416
20518
  return formatTaskSummary(tasks);
@@ -20421,7 +20523,7 @@ function createTeammateTools(options) {
20421
20523
  schema: import_v33.z.object({})
20422
20524
  }
20423
20525
  );
20424
- const broadcastMessageTool = (0, import_langchain54.tool)(
20526
+ const broadcastMessageTool = (0, import_langchain55.tool)(
20425
20527
  async (input) => {
20426
20528
  const allAgents = await mailboxStore.getRegisteredAgents(teamId);
20427
20529
  const recipients = allAgents.filter((a) => a !== agentId);
@@ -20607,7 +20709,7 @@ You have access to these tools:
20607
20709
  - \`read_messages\`: Read messages from team_lead or teammates
20608
20710
  - \`check_tasks\`: Get current status of all tasks in the team`;
20609
20711
  const assistantId = getTeammateAssistantId(ctx.teamId, spec.name);
20610
- agent = (0, import_langchain55.createAgent)({
20712
+ agent = (0, import_langchain56.createAgent)({
20611
20713
  model: spec.model ?? ctx.defaultModel,
20612
20714
  systemPrompt: teammatePrompt,
20613
20715
  tools: allTools,
@@ -20676,12 +20778,12 @@ async function spawnTeammate(options) {
20676
20778
  function createTeamMiddleware(options) {
20677
20779
  const { teamConfig, taskListStore, mailboxStore, tenantId: tenantId2 } = options;
20678
20780
  const defaultModel = teamConfig.model ?? "claude-sonnet-4-5-20250929";
20679
- const createTeamTool = (0, import_langchain55.tool)(
20781
+ const createTeamTool = (0, import_langchain56.tool)(
20680
20782
  async (input, config) => {
20681
20783
  const state = (0, import_langgraph11.getCurrentTaskInput)();
20682
20784
  if (state?.team?.teamId) {
20683
20785
  const existingId = state.team.teamId;
20684
- const msg = new import_langchain55.ToolMessage({
20786
+ const msg = new import_langchain56.ToolMessage({
20685
20787
  content: `A team is already active (id: ${existingId}). Use this team_id for \`check_tasks\`, \`read_messages\`, \`add_tasks\`, \`send_message\`, \`assign_task\`, \`set_task_status\`, and \`set_task_dependencies\`. Do not call \`create_team\` again unless you need a fresh team for a new objective.`,
20686
20788
  tool_call_id: config.toolCall?.id,
20687
20789
  name: "create_team"
@@ -20770,7 +20872,7 @@ Teammates are now working in the background. Keep calling \`check_tasks\` and \`
20770
20872
  \`\`\`json
20771
20873
  ${teamJson}
20772
20874
  \`\`\``;
20773
- const toolMessage = new import_langchain55.ToolMessage({
20875
+ const toolMessage = new import_langchain56.ToolMessage({
20774
20876
  content: summary,
20775
20877
  tool_call_id: config.toolCall?.id,
20776
20878
  name: "create_team"
@@ -20855,7 +20957,7 @@ After calling create_team, you MUST:
20855
20957
  if (state?.team?.teamId) return state.team.teamId;
20856
20958
  throw new Error("No team_id provided and no team in state. Call create_team first.");
20857
20959
  };
20858
- const addTasksTool = (0, import_langchain55.tool)(
20960
+ const addTasksTool = (0, import_langchain56.tool)(
20859
20961
  async (input, config) => {
20860
20962
  const teamId = resolveTeamId();
20861
20963
  const created = await taskListStore.addTasks(
@@ -20869,7 +20971,7 @@ After calling create_team, you MUST:
20869
20971
  }))
20870
20972
  );
20871
20973
  const summary = created.map((t) => `- ${t.id}: "${t.title}"`).join("\n");
20872
- return new import_langchain55.ToolMessage({
20974
+ return new import_langchain56.ToolMessage({
20873
20975
  content: `Added ${created.length} task(s) to team ${teamId}:
20874
20976
  ${summary}
20875
20977
  Sleeping teammates will wake up and claim these.`,
@@ -20920,20 +21022,20 @@ IMPORTANT: Assigning to a specific teammate
20920
21022
  })
20921
21023
  }
20922
21024
  );
20923
- const assignTaskTool = (0, import_langchain55.tool)(
21025
+ const assignTaskTool = (0, import_langchain56.tool)(
20924
21026
  async (input, config) => {
20925
21027
  const teamId = resolveTeamId();
20926
21028
  const task = await taskListStore.updateTask(teamId, input.task_id, {
20927
21029
  assignee: input.assignee
20928
21030
  });
20929
21031
  if (!task) {
20930
- return new import_langchain55.ToolMessage({
21032
+ return new import_langchain56.ToolMessage({
20931
21033
  content: `Task ${input.task_id} not found in team ${teamId}.`,
20932
21034
  tool_call_id: config.toolCall?.id,
20933
21035
  name: "assign_task"
20934
21036
  });
20935
21037
  }
20936
- return new import_langchain55.ToolMessage({
21038
+ return new import_langchain56.ToolMessage({
20937
21039
  content: `Task "${task.title}" (${task.id}) assigned to ${input.assignee}.`,
20938
21040
  tool_call_id: config.toolCall?.id,
20939
21041
  name: "assign_task"
@@ -20948,20 +21050,20 @@ IMPORTANT: Assigning to a specific teammate
20948
21050
  })
20949
21051
  }
20950
21052
  );
20951
- const setTaskStatusTool = (0, import_langchain55.tool)(
21053
+ const setTaskStatusTool = (0, import_langchain56.tool)(
20952
21054
  async (input, config) => {
20953
21055
  const teamId = resolveTeamId();
20954
21056
  const task = await taskListStore.updateTask(teamId, input.task_id, {
20955
21057
  status: input.status
20956
21058
  });
20957
21059
  if (!task) {
20958
- return new import_langchain55.ToolMessage({
21060
+ return new import_langchain56.ToolMessage({
20959
21061
  content: `Task ${input.task_id} not found in team ${teamId}.`,
20960
21062
  tool_call_id: config.toolCall?.id,
20961
21063
  name: "set_task_status"
20962
21064
  });
20963
21065
  }
20964
- return new import_langchain55.ToolMessage({
21066
+ return new import_langchain56.ToolMessage({
20965
21067
  content: `Task "${task.title}" (${task.id}) status set to ${input.status}.`,
20966
21068
  tool_call_id: config.toolCall?.id,
20967
21069
  name: "set_task_status"
@@ -20976,20 +21078,20 @@ IMPORTANT: Assigning to a specific teammate
20976
21078
  })
20977
21079
  }
20978
21080
  );
20979
- const setTaskDependenciesTool = (0, import_langchain55.tool)(
21081
+ const setTaskDependenciesTool = (0, import_langchain56.tool)(
20980
21082
  async (input, config) => {
20981
21083
  const teamId = resolveTeamId();
20982
21084
  const task = await taskListStore.updateTask(teamId, input.task_id, {
20983
21085
  dependencies: input.dependencies
20984
21086
  });
20985
21087
  if (!task) {
20986
- return new import_langchain55.ToolMessage({
21088
+ return new import_langchain56.ToolMessage({
20987
21089
  content: `Task ${input.task_id} not found in team ${teamId}.`,
20988
21090
  tool_call_id: config.toolCall?.id,
20989
21091
  name: "set_task_dependencies"
20990
21092
  });
20991
21093
  }
20992
- return new import_langchain55.ToolMessage({
21094
+ return new import_langchain56.ToolMessage({
20993
21095
  content: `Task "${task.title}" (${task.id}) dependencies set to [${input.dependencies.join(", ")}].`,
20994
21096
  tool_call_id: config.toolCall?.id,
20995
21097
  name: "set_task_dependencies"
@@ -21004,7 +21106,7 @@ IMPORTANT: Assigning to a specific teammate
21004
21106
  })
21005
21107
  }
21006
21108
  );
21007
- const checkTasksTool = (0, import_langchain55.tool)(
21109
+ const checkTasksTool = (0, import_langchain56.tool)(
21008
21110
  async (input, config) => {
21009
21111
  const teamId = resolveTeamId();
21010
21112
  const tasks = await taskListStore.getAllTasks(teamId);
@@ -21013,7 +21115,7 @@ IMPORTANT: Assigning to a specific teammate
21013
21115
  update: {
21014
21116
  tasks: tasksSnapshot,
21015
21117
  messages: [
21016
- new import_langchain55.ToolMessage({
21118
+ new import_langchain56.ToolMessage({
21017
21119
  content: formatTaskSummary(tasks),
21018
21120
  tool_call_id: config.toolCall?.id,
21019
21121
  name: "check_tasks"
@@ -21049,7 +21151,7 @@ Task Status Values:
21049
21151
  })
21050
21152
  }
21051
21153
  );
21052
- const sendMessageTool = (0, import_langchain55.tool)(
21154
+ const sendMessageTool = (0, import_langchain56.tool)(
21053
21155
  async (input, config) => {
21054
21156
  const teamId = resolveTeamId();
21055
21157
  await mailboxStore.sendMessage(
@@ -21059,7 +21161,7 @@ Task Status Values:
21059
21161
  input.content,
21060
21162
  "direct_message" /* DIRECT_MESSAGE */
21061
21163
  );
21062
- return new import_langchain55.ToolMessage({
21164
+ return new import_langchain56.ToolMessage({
21063
21165
  content: `Message sent to ${input.to}.`,
21064
21166
  tool_call_id: config.toolCall?.id,
21065
21167
  name: "send_message"
@@ -21074,7 +21176,7 @@ Task Status Values:
21074
21176
  })
21075
21177
  }
21076
21178
  );
21077
- const readMessagesTool = (0, import_langchain55.tool)(
21179
+ const readMessagesTool = (0, import_langchain56.tool)(
21078
21180
  async (input, config) => {
21079
21181
  const teamId = resolveTeamId();
21080
21182
  const formatAndMarkAsRead = async (msgs2) => {
@@ -21102,7 +21204,7 @@ Task Status Values:
21102
21204
  if (msgs.length > 0) {
21103
21205
  const formatted2 = await formatAndMarkAsRead(msgs);
21104
21206
  const allTeamMessages2 = await getAllTeamMessagesForState();
21105
- const toolMessage2 = new import_langchain55.ToolMessage({
21207
+ const toolMessage2 = new import_langchain56.ToolMessage({
21106
21208
  content: formatted2,
21107
21209
  tool_call_id: config.toolCall?.id,
21108
21210
  name: "read_messages"
@@ -21134,7 +21236,7 @@ Task Status Values:
21134
21236
  );
21135
21237
  const allTeamMessages = await getAllTeamMessagesForState();
21136
21238
  if (msgs.length === 0) {
21137
- const toolMessage2 = new import_langchain55.ToolMessage({
21239
+ const toolMessage2 = new import_langchain56.ToolMessage({
21138
21240
  content: "No unread messages from teammates.",
21139
21241
  tool_call_id: config.toolCall?.id,
21140
21242
  name: "read_messages"
@@ -21144,7 +21246,7 @@ Task Status Values:
21144
21246
  });
21145
21247
  }
21146
21248
  const formatted = await formatAndMarkAsRead(msgs);
21147
- const toolMessage = new import_langchain55.ToolMessage({
21249
+ const toolMessage = new import_langchain56.ToolMessage({
21148
21250
  content: formatted,
21149
21251
  tool_call_id: config.toolCall?.id,
21150
21252
  name: "read_messages"
@@ -21161,7 +21263,7 @@ Task Status Values:
21161
21263
  })
21162
21264
  }
21163
21265
  );
21164
- const disbandTeamTool = (0, import_langchain55.tool)(
21266
+ const disbandTeamTool = (0, import_langchain56.tool)(
21165
21267
  async (input, config) => {
21166
21268
  const teamId = resolveTeamId();
21167
21269
  await mailboxStore.broadcastMessage(
@@ -21171,7 +21273,7 @@ Task Status Values:
21171
21273
  "shutdown_request" /* SHUTDOWN_REQUEST */
21172
21274
  );
21173
21275
  await new Promise((r) => setTimeout(r, 2e3));
21174
- return new import_langchain55.ToolMessage({
21276
+ return new import_langchain56.ToolMessage({
21175
21277
  content: `Team ${teamId} has been disbanded. All teammates notified and resources cleaned up.`,
21176
21278
  tool_call_id: config.toolCall?.id,
21177
21279
  name: "disband_team"
@@ -21182,7 +21284,7 @@ Task Status Values:
21182
21284
  description: "Disband a team when all work is done. Before calling: (1) Call check_tasks to verify no tasks are still pending/in_progress; (2) if any are, discuss with the team via read_messages and broadcast_message/send_message whether to continue or stop/cancel them; (3) only after alignment (all tasks completed/failed or explicitly stopped), then call this tool. This will: 1) Send a shutdown message to all teammates, 2) Wait briefly for them to clean up, 3) Clear all tasks and messages. Omit team_id to use the active team from state."
21183
21285
  }
21184
21286
  );
21185
- const broadcastMessageTool = (0, import_langchain55.tool)(
21287
+ const broadcastMessageTool = (0, import_langchain56.tool)(
21186
21288
  async (input, config) => {
21187
21289
  const teamId = resolveTeamId();
21188
21290
  await mailboxStore.broadcastMessage(
@@ -21191,7 +21293,7 @@ Task Status Values:
21191
21293
  input.content,
21192
21294
  "broadcast" /* BROADCAST */
21193
21295
  );
21194
- return new import_langchain55.ToolMessage({
21296
+ return new import_langchain56.ToolMessage({
21195
21297
  content: `Broadcast message sent to all teammates.`,
21196
21298
  tool_call_id: config.toolCall?.id,
21197
21299
  name: "broadcast_message"
@@ -21205,7 +21307,7 @@ Task Status Values:
21205
21307
  })
21206
21308
  }
21207
21309
  );
21208
- return (0, import_langchain55.createMiddleware)({
21310
+ return (0, import_langchain56.createMiddleware)({
21209
21311
  name: "teamMiddleware",
21210
21312
  tools: [
21211
21313
  createTeamTool,
@@ -21314,7 +21416,7 @@ function createAgentTeam(config) {
21314
21416
  ];
21315
21417
  const systemPrompt = config.systemPrompt + "\n\n" + TEAM_LEAD_BASE_PROMPT;
21316
21418
  const stateSchema2 = createReactAgentSchema(TEAM_STATE_SCHEMA);
21317
- return (0, import_langchain56.createAgent)({
21419
+ return (0, import_langchain57.createAgent)({
21318
21420
  model: config.model ?? "claude-sonnet-4-5-20250929",
21319
21421
  systemPrompt,
21320
21422
  tools: [],
@@ -21357,7 +21459,7 @@ var TeamAgentGraphBuilder = class {
21357
21459
  });
21358
21460
  const middlewareConfigs = params.middleware || [];
21359
21461
  let filesystemBackend = createFilesystemBackendFactory(middlewareConfigs);
21360
- const middlewares = await createCommonMiddlewares(middlewareConfigs);
21462
+ const middlewares = await createCommonMiddlewares(middlewareConfigs, void 0, void 0, void 0, params.model);
21361
21463
  if (!filesystemBackend) {
21362
21464
  filesystemBackend = async (config2) => {
21363
21465
  return new StateBackend(config2);
@@ -21726,7 +21828,7 @@ function extractLastHumanMessage(messages) {
21726
21828
  }
21727
21829
 
21728
21830
  // src/agent_lattice/builders/WorkflowAgentGraphBuilder.ts
21729
- var import_langchain57 = require("langchain");
21831
+ var import_langchain58 = require("langchain");
21730
21832
  init_MemoryLatticeManager();
21731
21833
  var import_protocols10 = require("@axiom-lattice/protocols");
21732
21834
  init_compile();
@@ -21777,7 +21879,7 @@ var WorkflowAgentGraphBuilder = class {
21777
21879
  const checkpointer = getCheckpointSaver("default");
21778
21880
  const tools = params.tools.map((t) => t.executor).filter(Boolean);
21779
21881
  const middlewareConfigs = params.middleware || [];
21780
- const middlewares = await createCommonMiddlewares(middlewareConfigs, void 0, false, params.tenantId);
21882
+ const middlewares = await createCommonMiddlewares(middlewareConfigs, void 0, false, params.tenantId, params.model);
21781
21883
  const askMiddlewares = await createCommonMiddlewares([
21782
21884
  {
21783
21885
  id: "ask_user_to_clarify",
@@ -21787,11 +21889,11 @@ var WorkflowAgentGraphBuilder = class {
21787
21889
  enabled: true,
21788
21890
  config: {}
21789
21891
  }
21790
- ], void 0, false);
21892
+ ], void 0, false, void 0, params.model);
21791
21893
  const noWrapMiddlewares = stripWrapModelCallHook(middlewares);
21792
21894
  const noWrapAskMiddlewares = stripWrapModelCallHook(askMiddlewares);
21793
21895
  console.log(`[WF BUILDER] building default agent | toolCount=${tools.length} | middlewareCount=${middlewares.length}`);
21794
- const defaultAgent = (0, import_langchain57.createAgent)({
21896
+ const defaultAgent = (0, import_langchain58.createAgent)({
21795
21897
  model: params.model,
21796
21898
  tools,
21797
21899
  systemPrompt: buildStepSystemPrompt(false, params.prompt),
@@ -21811,7 +21913,7 @@ var WorkflowAgentGraphBuilder = class {
21811
21913
  console.log(`[WF BUILDER] resolveAgent: cacheKey=${key4.slice(0, 80)}... | cached=${agentCache.has(key4)}`);
21812
21914
  if (!agentCache.has(key4)) {
21813
21915
  console.log(`[WF BUILDER] creating ${isAsk ? "ask" : "agent"} with responseFormat`);
21814
- const agent = (0, import_langchain57.createAgent)({
21916
+ const agent = (0, import_langchain58.createAgent)({
21815
21917
  model: params.model,
21816
21918
  tools,
21817
21919
  systemPrompt: buildStepSystemPrompt(isAsk, params.prompt),
@@ -21827,7 +21929,7 @@ var WorkflowAgentGraphBuilder = class {
21827
21929
  const key4 = "ask:default";
21828
21930
  if (!agentCache.has(key4)) {
21829
21931
  console.log(`[WF BUILDER] creating ask default agent`);
21830
- const agent = (0, import_langchain57.createAgent)({
21932
+ const agent = (0, import_langchain58.createAgent)({
21831
21933
  model: params.model,
21832
21934
  tools,
21833
21935
  systemPrompt: buildStepSystemPrompt(true, params.prompt),
@@ -23466,10 +23568,19 @@ Call the \`skill\` tool with skill_name: "agent-architecture" to load the
23466
23568
  authoritative workflow. Never announce that you will follow a skill \u2014
23467
23569
  load it and follow its content. If the load fails, retry once, then report it.
23468
23570
 
23571
+ TASK MANAGEMENT IS A CORE DUTY, not a per-skill option. Whenever the
23572
+ goal is clear and you know what to do, create a task FIRST (manage_task)
23573
+ before executing \u2014 for any multi-step work: learning, building,
23574
+ modifying, fixing, anything with an Objective and Acceptance Criteria.
23575
+ Subtasks per work item. Status must reflect reality. See [[task-tracking]].
23576
+ The sub-skills below only ADD their own task details on top of this
23577
+ universal duty.
23578
+
23469
23579
  Your sub-skills (accessible via the MOC or direct loading):
23470
23580
  - [[learn-capability]] \u2014 Learn from any source material \u2192 skills + agents
23471
23581
  - [[agent-build]] \u2014 Design and build single agents (REACT/DEEP_AGENT)
23472
23582
  - [[design-workflow]] \u2014 Design workflow agents
23583
+ - [[eval-verify]] \u2014 Run evaluations with fix loop, hold-out, trust upgrade
23473
23584
  - [[task-tracking]] \u2014 Manage persistent tasks (manage_task)
23474
23585
  - [[completion-gate]] \u2014 THE rule: no agent is "done" without eval
23475
23586
  - [[domain-moc]] \u2014 Create the domain MOC (mandatory per learning run)
@@ -23629,7 +23740,15 @@ var agentArchitectConfig = {
23629
23740
  id: "task",
23630
23741
  type: "task",
23631
23742
  name: "Task",
23632
- description: "Track learning processes and fix loops with approval gates",
23743
+ description: "Core architect duty: once the goal is clear, create tasks to track every multi-step piece of work (learning, building, modifying, fixing). Subtasks per work item; status reflects reality.",
23744
+ enabled: true,
23745
+ config: {}
23746
+ },
23747
+ {
23748
+ id: "code_eval",
23749
+ type: "code_eval",
23750
+ name: "Code Evaluation",
23751
+ description: "Execute shell commands in the sandbox to support agent creation: unzip files, process data, run helper scripts. Distinct from the eval assessment system (run_eval).",
23633
23752
  enabled: true,
23634
23753
  config: {}
23635
23754
  },
@@ -27256,6 +27375,15 @@ function parseJudgeVerdict(raw) {
27256
27375
  return { error: error instanceof Error ? error.message : String(error) };
27257
27376
  }
27258
27377
  }
27378
+ var MAX_INTERRUPT_RESUMES = 5;
27379
+ function resolveInterruptResponse(policy, interrupt5) {
27380
+ if (policy.mode === "auto-approve") return policy.value ?? "\u540C\u610F";
27381
+ if (policy.mode === "auto-reject") return policy.value ?? "\u62D2\u7EDD";
27382
+ return policy.value ?? "";
27383
+ }
27384
+ function interruptValueText(value) {
27385
+ return typeof value === "string" ? value : JSON.stringify(value ?? "");
27386
+ }
27259
27387
  var _LatticeEval = class _LatticeEval {
27260
27388
  constructor(config = {}) {
27261
27389
  this.inMemoryLogs = [];
@@ -27322,7 +27450,8 @@ var _LatticeEval = class _LatticeEval {
27322
27450
  return acc;
27323
27451
  }, {});
27324
27452
  }
27325
- async executeAgentStep(step, threadId, inputMessage, files) {
27453
+ async executeAgentStep(step, threadId, inputMessage, files, interruptPolicy) {
27454
+ const hitlEvents = [];
27326
27455
  this.log("Executing agent step", {
27327
27456
  agent_id: step.agent_id,
27328
27457
  thread_id: threadId,
@@ -27340,19 +27469,74 @@ var _LatticeEval = class _LatticeEval {
27340
27469
  };
27341
27470
  const agent = agentInstanceManager.getAgent(agentParams);
27342
27471
  try {
27343
- const result = await agent.invoke({
27344
- input: {
27345
- message: step.override_message || inputMessage,
27346
- files: this.buildFileEntries(files)
27472
+ const stepInput = {
27473
+ message: step.override_message || inputMessage,
27474
+ files: this.buildFileEntries(files)
27475
+ };
27476
+ let result = await agent.invokeWithState({ input: stepInput });
27477
+ let resumeCount = 0;
27478
+ let pendingInterrupt;
27479
+ let interrupts = Array.isArray(result?.__interrupt__) ? result.__interrupt__ : [];
27480
+ while (interrupts.length > 0) {
27481
+ const interrupt5 = interrupts[0];
27482
+ if (!interrupt5) break;
27483
+ const policy = interruptPolicy;
27484
+ if (!policy || policy.mode === "stop" || resumeCount >= MAX_INTERRUPT_RESUMES) {
27485
+ pendingInterrupt = interrupt5;
27486
+ break;
27347
27487
  }
27348
- });
27488
+ const response = resolveInterruptResponse(policy, interrupt5);
27489
+ hitlEvents.push({
27490
+ type: "interrupt",
27491
+ id: interrupt5.id,
27492
+ value: interrupt5.value
27493
+ });
27494
+ this.log("Auto-resolving HITL interrupt", {
27495
+ agent_id: step.agent_id,
27496
+ thread_id: threadId,
27497
+ mode: policy.mode,
27498
+ interrupt_id: interrupt5.id,
27499
+ response,
27500
+ resume_count: resumeCount + 1
27501
+ });
27502
+ result = await agent.invokeWithState({ input: stepInput, command: { resume: response } });
27503
+ hitlEvents.push({
27504
+ type: "interrupt_response",
27505
+ id: interrupt5.id,
27506
+ mode: policy.mode,
27507
+ response
27508
+ });
27509
+ resumeCount++;
27510
+ interrupts = Array.isArray(result?.__interrupt__) ? result.__interrupt__ : [];
27511
+ }
27512
+ if (pendingInterrupt) {
27513
+ hitlEvents.push({
27514
+ type: "interrupt",
27515
+ id: pendingInterrupt.id,
27516
+ value: pendingInterrupt.value
27517
+ });
27518
+ this.log("Agent step interrupted by HITL (human input requested)", {
27519
+ agent_id: step.agent_id,
27520
+ thread_id: threadId,
27521
+ interrupt_id: pendingInterrupt.id,
27522
+ auto_resolved: resumeCount
27523
+ });
27524
+ } else {
27525
+ this.log("Agent step completed", {
27526
+ agent_id: step.agent_id,
27527
+ thread_id: threadId,
27528
+ response_keys: result ? Object.keys(result) : [],
27529
+ auto_resolved: resumeCount
27530
+ });
27531
+ }
27349
27532
  const responseData = { success: true, ...result };
27350
- this.log("Agent step completed", {
27351
- agent_id: step.agent_id,
27352
- thread_id: threadId,
27353
- response_keys: result ? Object.keys(result) : []
27354
- });
27355
- return { threadId, responseData };
27533
+ return {
27534
+ threadId,
27535
+ responseData,
27536
+ interrupted: pendingInterrupt ? true : void 0,
27537
+ interrupt: pendingInterrupt,
27538
+ hitlEvents
27539
+ };
27356
27540
  } catch (error) {
27357
27541
  const message = error instanceof Error ? error.message : String(error);
27358
27542
  this.log("Agent step failed", {
@@ -27415,15 +27599,32 @@ var _LatticeEval = class _LatticeEval {
27415
27599
  });
27416
27600
  let currentThreadId = threadId;
27417
27601
  let lastResponseData = null;
27602
+ let interrupt5;
27418
27603
  for (const step of evalCase.steps) {
27419
27604
  const result = await this.executeAgentStep(
27420
27605
  step,
27421
27606
  currentThreadId,
27422
27607
  evalCase.input.message,
27423
- evalCase.input.files || {}
27608
+ evalCase.input.files || {},
27609
+ evalCase.interruptPolicy
27424
27610
  );
27425
27611
  currentThreadId = result.threadId;
27426
27612
  lastResponseData = result.responseData;
27613
+ for (const evt of result.hitlEvents) {
27614
+ if (evt.type === "interrupt") {
27615
+ this.lastMessages.push({
27616
+ role: "interrupt",
27617
+ content: `HITL \u6682\u505C\uFF1AAgent \u8BF7\u6C42\u4EBA\u5DE5\u8F93\u5165 \u2014 ${interruptValueText(evt.value)}`,
27618
+ id: evt.id
27619
+ });
27620
+ } else {
27621
+ this.lastMessages.push({
27622
+ role: "interrupt_response",
27623
+ content: `\u5DF2\u81EA\u52A8\u54CD\u5E94\uFF08\u6D4B\u8BD5\u7B56\u7565 ${evt.mode}\uFF09\uFF1A${evt.response}`,
27624
+ id: evt.id
27625
+ });
27626
+ }
27627
+ }
27427
27628
  const existingIds = new Set(this.lastMessages.map((m) => m.id).filter(Boolean));
27428
27629
  if (result.responseData?.messages && Array.isArray(result.responseData.messages)) {
27429
27630
  for (const msg of result.responseData.messages) {
@@ -27445,6 +27646,13 @@ var _LatticeEval = class _LatticeEval {
27445
27646
  } else {
27446
27647
  content = String(msg.content || "");
27447
27648
  }
27649
+ if (Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0) {
27650
+ const toolCallStr = msg.tool_calls.map(
27651
+ (tc) => `tool_call: ${tc.name}(${JSON.stringify(tc.args ?? {})})`
27652
+ ).join("\n");
27653
+ content = content ? `${content}
27654
+ ${toolCallStr}` : toolCallStr;
27655
+ }
27448
27656
  this.lastMessages.push({
27449
27657
  role,
27450
27658
  content,
@@ -27456,13 +27664,21 @@ var _LatticeEval = class _LatticeEval {
27456
27664
  }
27457
27665
  }
27458
27666
  }
27667
+ if (result.interrupted) {
27668
+ interrupt5 = result.interrupt;
27669
+ this.log("Case paused for HITL \u2014 remaining steps skipped; judge will evaluate the pause", {
27670
+ case_id: evalCase.caseId,
27671
+ interrupt_id: interrupt5?.id
27672
+ });
27673
+ break;
27674
+ }
27459
27675
  }
27460
27676
  this.log("All agent steps completed", {
27461
27677
  case_id: evalCase.caseId,
27462
27678
  final_thread_id: currentThreadId,
27463
27679
  message_count: this.lastMessages.length
27464
27680
  });
27465
- const finalOutput = this.extractFinalMessage(lastResponseData);
27681
+ const finalOutput = interrupt5 ? typeof interrupt5.value === "string" ? interrupt5.value : JSON.stringify(interrupt5.value ?? "") : this.extractFinalMessage(lastResponseData);
27466
27682
  this.lastFinalOutput = finalOutput;
27467
27683
  const trajectory = this.buildTrajectory();
27468
27684
  this.log("Final output extracted", {
@@ -27521,6 +27737,8 @@ ${rubricsSection}
27521
27737
  3. **\u8FC7\u7A0B\u6821\u9A8C**\uFF1A\u5982\u679C"\u6267\u884C\u8FC7\u7A0B"\u663E\u793A Agent \u672A\u6267\u884C\u5FC5\u8981\u7684\u4E2D\u95F4\u6B65\u9AA4\uFF08\u5982\u5E94\u8C03\u7528\u5DE5\u5177\u800C\u672A\u8C03\u7528\uFF09\uFF0C\u5373\u4F7F\u6700\u7EC8\u8F93\u51FA\u770B\u4F3C\u5408\u7406\uFF0C\u4E5F\u5E94\u5728\u5BF9\u5E94\u6307\u6807\u4E0A\u6263\u5206\u3002
27522
27738
  4. **\u8BC1\u636E\u5BFC\u5411**\uFF1A\u5728\u7ED9\u51FA\u539F\u56E0\uFF08reason\uFF09\u65F6\uFF0C\u5FC5\u987B\u5F15\u7528\u6267\u884C\u8FC7\u7A0B\u6216\u6700\u7EC8\u8F93\u51FA\u4E2D\u7684\u5177\u4F53\u5185\u5BB9\u3002
27523
27739
  5. **\u52A0\u6743\u8BA1\u7B97**\uFF1A\u6700\u7EC8\u5206\u6570\u4E3A\u5404\u9879\u6307\u6807\u5F97\u5206\u4E0E\u5176\u6743\u91CD\u7684\u4E58\u79EF\u4E4B\u548C\uFF080-100\u5206\u5236\uFF09\u3002
27740
+ 6. **HITL \u4E2D\u65AD\u5224\u5B9A**\uFF1A\u5982\u679C\u6267\u884C\u8FC7\u7A0B\u4E2D\u51FA\u73B0\u300CHITL \u6682\u505C\uFF1AAgent \u8BF7\u6C42\u4EBA\u5DE5\u8F93\u5165\u300D\u6761\u76EE\uFF0C\u8BF4\u660E Agent \u5728\u7B49\u5F85\u4EBA\u5DE5\u786E\u8BA4\u3002\u8BF7\u628A\u5B83\u5F53\u4F5C\u88AB\u6D4B\u4E1A\u52A1\u884C\u4E3A\u6765\u8BC4\u5224\uFF1A\u82E5\u671F\u671B\u8F93\u51FA\u8981\u6C42\u81EA\u4E3B\u5B8C\u6210\uFF08\u5982"\u65E0\u9700\u786E\u8BA4\u81EA\u52A8\u6267\u884C"\uFF09\uFF0C\u8BF7\u6C42\u4EBA\u5DE5\u8F93\u5165\u5E94\u5224\u5931\u8D25\uFF1B\u82E5\u671F\u671B\u8F93\u51FA\u8981\u6C42\u5148\u83B7\u5F97\u786E\u8BA4\u6216\u6279\u51C6\uFF08\u5982"\u6267\u884C\u524D\u5FC5\u987B\u8BF7\u6C42\u6279\u51C6"\uFF09\uFF0C\u8BF7\u6C42\u4EBA\u5DE5\u8F93\u5165\u662F\u6B63\u786E\u884C\u4E3A\uFF0C\u5E94\u7ED3\u5408\u5176\u65F6\u673A\u4E0E\u5185\u5BB9\u5224\u5B9A\u4E3A\u901A\u8FC7\u6216\u6309\u6307\u6807\u7ED9\u5206\u3002
27741
+ 7. **HITL \u81EA\u52A8\u54CD\u5E94\u5224\u5B9A**\uFF1A\u5982\u679C\u300CHITL \u6682\u505C\u300D\u6761\u76EE\u4E4B\u540E\u51FA\u73B0\u300C\u5DF2\u81EA\u52A8\u54CD\u5E94\uFF08\u6D4B\u8BD5\u7B56\u7565 auto-approve/auto-reject/canned-response\uFF09\u300D\u6761\u76EE\uFF0C\u8BF4\u660E\u6D4B\u8BD5\u6846\u67B6\u6CE8\u5165\u4E86\u4EBA\u5DE5\u56DE\u590D\u3001\u6D41\u7A0B\u5DF2\u7EE7\u7EED\u2014\u2014\u8BF7\u6309**\u5B8C\u6574\u6D41\u7A0B**\u8BC4\u5224\u6682\u505C\u4E4B\u540E\u7684\u884C\u4E3A\uFF08\u5982\u6279\u51C6\u540E\u662F\u5426\u6B63\u786E\u6267\u884C\u4E86\u64CD\u4F5C\uFF09\uFF0C\u5E76\u6838\u5BF9\u81EA\u52A8\u54CD\u5E94\u5185\u5BB9\u662F\u5426\u7B26\u5408\u4EBA\u5DE5\u56DE\u590D\u7684\u5408\u7406\u9884\u671F\u3002
27524
27742
 
27525
27743
  # \u8F93\u51FA\u683C\u5F0F\uFF08\u4EC5JSON\uFF09
27526
27744
  \u4F60\u5FC5\u987B\u4EC5\u4EE5 JSON \u683C\u5F0F\u56DE\u590D\uFF0C\u7ED3\u6784\u5982\u4E0B\uFF1A
@@ -27675,7 +27893,9 @@ ${rubricsSection}
27675
27893
  pass,
27676
27894
  final_score: finalScore,
27677
27895
  dimension_results: dimensionResults,
27678
- summary: parsedResult.summary || testResultContent
27896
+ summary: parsedResult.summary || testResultContent,
27897
+ interrupted: interrupt5 ? true : void 0,
27898
+ interrupt: interrupt5 ? { id: interrupt5.id, value: interrupt5.value } : void 0
27679
27899
  };
27680
27900
  }
27681
27901
  };
@@ -27690,6 +27910,8 @@ async function evaluateLatticeCaseWithLogs(evalCase, config) {
27690
27910
  return {
27691
27911
  caseId: evalCase.caseId,
27692
27912
  result,
27913
+ interrupted: result?.interrupted,
27914
+ interrupt: result?.interrupt,
27693
27915
  duration_ms: meta.duration_ms,
27694
27916
  thread_id: meta.thread_id,
27695
27917
  judge_thread_id: meta.judge_thread_id,
@@ -27772,7 +27994,8 @@ function resolveTemplateCase(templateCase, templates) {
27772
27994
  eval: {
27773
27995
  content_assertion: templateCase.eval.content_assertion,
27774
27996
  eval_rubrics: templateCase.eval.eval_rubrics || template.default_case.eval?.eval_rubrics
27775
- }
27997
+ },
27998
+ interruptPolicy: templateCase.interruptPolicy ?? template.default_case.interruptPolicy
27776
27999
  };
27777
28000
  return resolvedCase;
27778
28001
  }
@@ -27838,6 +28061,8 @@ var LatticeEvalSuite = class {
27838
28061
  result: run.result,
27839
28062
  error: run.error,
27840
28063
  error_stack: run.error_stack,
28064
+ interrupted: run.interrupted,
28065
+ interrupt: run.interrupt,
27841
28066
  duration_ms: run.duration_ms,
27842
28067
  thread_id: run.thread_id,
27843
28068
  judge_thread_id: run.judge_thread_id,
@@ -27870,6 +28095,8 @@ var LatticeEvalSuite = class {
27870
28095
  result: run.result,
27871
28096
  error: run.error,
27872
28097
  error_stack: run.error_stack,
28098
+ interrupted: run.interrupted,
28099
+ interrupt: run.interrupt,
27873
28100
  duration_ms: run.duration_ms,
27874
28101
  thread_id: run.thread_id,
27875
28102
  judge_thread_id: run.judge_thread_id,
@@ -28079,24 +28306,29 @@ Running batch: ${this.project.projectName} (${this.getSuiteNames().length} suite
28079
28306
  let total_cases = 0;
28080
28307
  let passed_cases = 0;
28081
28308
  let failed_cases = 0;
28309
+ let interrupted_cases = 0;
28082
28310
  const suites = [];
28083
28311
  for (const [suiteName, caseResults] of results.entries()) {
28084
28312
  const suiteTotal = caseResults.length;
28085
28313
  const suitePassed = caseResults.filter((r) => r.result?.pass).length;
28314
+ const suiteInterrupted = caseResults.filter((r) => r.interrupted).length;
28086
28315
  const suiteFailed = suiteTotal - suitePassed;
28087
28316
  total_cases += suiteTotal;
28088
28317
  passed_cases += suitePassed;
28089
28318
  failed_cases += suiteFailed;
28319
+ interrupted_cases += suiteInterrupted;
28090
28320
  suites.push({
28091
28321
  suiteName,
28092
28322
  total_cases: suiteTotal,
28093
28323
  passed_cases: suitePassed,
28094
28324
  failed_cases: suiteFailed,
28325
+ interrupted_cases: suiteInterrupted,
28095
28326
  cases: caseResults.map((r) => ({
28096
28327
  caseId: r.caseId,
28097
28328
  pass: r.result?.pass,
28098
28329
  final_score: r.result?.final_score,
28099
- error: r.error
28330
+ error: r.error,
28331
+ interrupted: r.interrupted
28100
28332
  }))
28101
28333
  });
28102
28334
  }
@@ -28114,13 +28346,14 @@ Running batch: ${this.project.projectName} (${this.getSuiteNames().length} suite
28114
28346
  total_cases,
28115
28347
  passed_cases,
28116
28348
  failed_cases,
28349
+ interrupted_cases,
28117
28350
  pass_rate: total_cases > 0 ? passed_cases / total_cases : 0
28118
28351
  },
28119
28352
  suites
28120
28353
  };
28121
28354
  console.log(`
28122
28355
  === Summary ===`);
28123
- console.log(`Total: ${report.summary.total_cases} | Passed: ${report.summary.passed_cases} | Failed: ${report.summary.failed_cases} | Pass Rate: ${(report.summary.pass_rate * 100).toFixed(2)}%`);
28356
+ console.log(`Total: ${report.summary.total_cases} | Passed: ${report.summary.passed_cases} | Failed: ${report.summary.failed_cases} | Interrupted: ${report.summary.interrupted_cases} | Pass Rate: ${(report.summary.pass_rate * 100).toFixed(2)}%`);
28124
28357
  return { batch_id, results, report };
28125
28358
  }
28126
28359
  };
@@ -28205,11 +28438,11 @@ function clearEncryptionKeyCache() {
28205
28438
  }
28206
28439
 
28207
28440
  // src/middlewares/skillMiddleware.ts
28208
- var import_langchain61 = require("langchain");
28441
+ var import_langchain62 = require("langchain");
28209
28442
 
28210
28443
  // src/tool_lattice/skill/load_skills.ts
28211
28444
  var import_zod48 = __toESM(require("zod"));
28212
- var import_langchain58 = require("langchain");
28445
+ var import_langchain59 = require("langchain");
28213
28446
  var LOAD_SKILLS_DESCRIPTION = `Load all available skills and return their metadata (name, description, license, compatibility, metadata, and subSkills) without the content. This tool returns skill information including hierarchical relationships (subSkills). Use this to discover what skills are available and their structure.`;
28214
28447
  function getSandboxFromExeConfig(_exe_config) {
28215
28448
  const runConfig = _exe_config?.configurable?.runConfig || {};
@@ -28224,7 +28457,7 @@ function getSandboxFromExeConfig(_exe_config) {
28224
28457
  });
28225
28458
  }
28226
28459
  var createLoadSkillsTool = ({ skills } = {}) => {
28227
- return (0, import_langchain58.tool)(
28460
+ return (0, import_langchain59.tool)(
28228
28461
  async (_input, _exe_config) => {
28229
28462
  try {
28230
28463
  const sandbox = await getSandboxFromExeConfig(_exe_config);
@@ -28265,7 +28498,7 @@ var createLoadSkillsTool = ({ skills } = {}) => {
28265
28498
 
28266
28499
  // src/tool_lattice/skill/load_skill_content.ts
28267
28500
  var import_zod49 = __toESM(require("zod"));
28268
- var import_langchain59 = require("langchain");
28501
+ var import_langchain60 = require("langchain");
28269
28502
  var LOAD_SKILL_CONTENT_DESCRIPTION = `
28270
28503
  Execute a skill within the main conversation
28271
28504
 
@@ -28303,7 +28536,7 @@ function getSandboxFromExeConfig2(_exe_config) {
28303
28536
  });
28304
28537
  }
28305
28538
  var createLoadSkillContentTool = (pluginSkillContents) => {
28306
- return (0, import_langchain59.tool)(
28539
+ return (0, import_langchain60.tool)(
28307
28540
  async (input, _exe_config) => {
28308
28541
  try {
28309
28542
  if (pluginSkillContents?.[input.skill_name]) {
@@ -28361,7 +28594,7 @@ var createLoadSkillContentTool = (pluginSkillContents) => {
28361
28594
 
28362
28595
  // src/tool_lattice/skill/delete_skill.ts
28363
28596
  var import_zod50 = __toESM(require("zod"));
28364
- var import_langchain60 = require("langchain");
28597
+ var import_langchain61 = require("langchain");
28365
28598
  var DELETE_SKILL_DESCRIPTION = `
28366
28599
  Delete a skill by name from the skill system.
28367
28600
  This permanently removes the skill and its SKILL.md file.
@@ -28388,7 +28621,7 @@ function validateSkillName2(name) {
28388
28621
  }
28389
28622
  }
28390
28623
  var createDeleteSkillTool = () => {
28391
- return (0, import_langchain60.tool)(
28624
+ return (0, import_langchain61.tool)(
28392
28625
  async (input, _exe_config) => {
28393
28626
  try {
28394
28627
  validateSkillName2(input.skill_name);
@@ -28430,7 +28663,7 @@ function createSkillMiddleware(params = {}) {
28430
28663
  } = params;
28431
28664
  const skills = params.skills;
28432
28665
  let latestSkills = [];
28433
- return (0, import_langchain61.createMiddleware)({
28666
+ return (0, import_langchain62.createMiddleware)({
28434
28667
  name: "skillMiddleware",
28435
28668
  contextSchema,
28436
28669
  tools: [
@@ -28565,17 +28798,17 @@ var skillPlugin = {
28565
28798
  };
28566
28799
 
28567
28800
  // src/middlewares/collectionMiddleware.ts
28568
- var import_langchain72 = require("langchain");
28801
+ var import_langchain73 = require("langchain");
28569
28802
 
28570
28803
  // src/tool_lattice/collection/list_collections.ts
28571
28804
  var import_zod51 = __toESM(require("zod"));
28572
- var import_langchain62 = require("langchain");
28805
+ var import_langchain63 = require("langchain");
28573
28806
  var LIST_COLLECTIONS_DESCRIPTION = `List all available collections for the current tenant. Returns collection names, labels, and field definitions (including field types and enum values). Use this tool to discover what collections are available before searching.`;
28574
28807
  var createListCollectionsTool = ({
28575
28808
  collectionKeys,
28576
28809
  connectAll
28577
28810
  }) => {
28578
- return (0, import_langchain62.tool)(
28811
+ return (0, import_langchain63.tool)(
28579
28812
  async (_input, _exeConfig) => {
28580
28813
  try {
28581
28814
  const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
@@ -28616,7 +28849,7 @@ var createListCollectionsTool = ({
28616
28849
 
28617
28850
  // src/tool_lattice/collection/search_collection.ts
28618
28851
  var import_zod52 = __toESM(require("zod"));
28619
- var import_langchain63 = require("langchain");
28852
+ var import_langchain64 = require("langchain");
28620
28853
  var SEARCH_COLLECTION_DESCRIPTION = `Search for content within a specific collection using semantic (vector) similarity. Use the 'filter' parameter to narrow results by metadata fields (e.g., {"category": "cardiovascular"}). Returns the most relevant content entries with similarity scores.`;
28621
28854
  var searchSchema = import_zod52.default.object({
28622
28855
  collection: import_zod52.default.string().describe("The collection name to search in"),
@@ -28625,7 +28858,7 @@ var searchSchema = import_zod52.default.object({
28625
28858
  top_k: import_zod52.default.number().optional().default(5).describe("Number of results to return")
28626
28859
  });
28627
28860
  var createSearchCollectionTool = () => {
28628
- return (0, import_langchain63.tool)(
28861
+ return (0, import_langchain64.tool)(
28629
28862
  async (input, _exeConfig) => {
28630
28863
  try {
28631
28864
  const { collection, query, filter: filter2, top_k } = input;
@@ -28676,9 +28909,9 @@ var createSearchCollectionTool = () => {
28676
28909
 
28677
28910
  // src/tool_lattice/collection/get_collection.ts
28678
28911
  var import_zod53 = __toESM(require("zod"));
28679
- var import_langchain64 = require("langchain");
28912
+ var import_langchain65 = require("langchain");
28680
28913
  var GET_COLLECTION_DESCRIPTION = `Get a collection's full definition including its custom fields schema. Use this to discover what metadata fields are available before adding entries.`;
28681
- var createGetCollectionTool = () => (0, import_langchain64.tool)(
28914
+ var createGetCollectionTool = () => (0, import_langchain65.tool)(
28682
28915
  async (input, _exeConfig) => {
28683
28916
  try {
28684
28917
  const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
@@ -28706,7 +28939,7 @@ Embedding: ${c.embeddingKey}${fieldsDesc}`;
28706
28939
 
28707
28940
  // src/tool_lattice/collection/create_collection.ts
28708
28941
  var import_zod54 = __toESM(require("zod"));
28709
- var import_langchain65 = require("langchain");
28942
+ var import_langchain66 = require("langchain");
28710
28943
  var createSchema = import_zod54.default.object({
28711
28944
  name: import_zod54.default.string().describe("Collection name (lowercase, underscores only)"),
28712
28945
  label: import_zod54.default.string().describe("Display name"),
@@ -28718,7 +28951,7 @@ var createSchema = import_zod54.default.object({
28718
28951
  required: import_zod54.default.boolean().optional().default(false).describe("Whether field is required")
28719
28952
  })).optional().describe("Custom field definitions for entries in this collection")
28720
28953
  });
28721
- var createCreateCollectionTool = () => (0, import_langchain65.tool)(
28954
+ var createCreateCollectionTool = () => (0, import_langchain66.tool)(
28722
28955
  async (input, _exeConfig) => {
28723
28956
  try {
28724
28957
  const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
@@ -28744,7 +28977,7 @@ var createCreateCollectionTool = () => (0, import_langchain65.tool)(
28744
28977
 
28745
28978
  // src/tool_lattice/collection/update_collection.ts
28746
28979
  var import_zod55 = __toESM(require("zod"));
28747
- var import_langchain66 = require("langchain");
28980
+ var import_langchain67 = require("langchain");
28748
28981
  var schema = import_zod55.default.object({
28749
28982
  name: import_zod55.default.string().describe("Collection name"),
28750
28983
  label: import_zod55.default.string().optional().describe("New display name"),
@@ -28756,7 +28989,7 @@ var schema = import_zod55.default.object({
28756
28989
  required: import_zod55.default.boolean().optional().default(false).describe("Whether field is required")
28757
28990
  })).optional().describe("Custom field definitions for entries (replaces existing schema)")
28758
28991
  });
28759
- var createUpdateCollectionTool = () => (0, import_langchain66.tool)(
28992
+ var createUpdateCollectionTool = () => (0, import_langchain67.tool)(
28760
28993
  async (input, _exeConfig) => {
28761
28994
  try {
28762
28995
  const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
@@ -28776,8 +29009,8 @@ var createUpdateCollectionTool = () => (0, import_langchain66.tool)(
28776
29009
 
28777
29010
  // src/tool_lattice/collection/delete_collection.ts
28778
29011
  var import_zod56 = __toESM(require("zod"));
28779
- var import_langchain67 = require("langchain");
28780
- var createDeleteCollectionTool = () => (0, import_langchain67.tool)(
29012
+ var import_langchain68 = require("langchain");
29013
+ var createDeleteCollectionTool = () => (0, import_langchain68.tool)(
28781
29014
  async (input, _exeConfig) => {
28782
29015
  try {
28783
29016
  const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
@@ -28792,14 +29025,14 @@ var createDeleteCollectionTool = () => (0, import_langchain67.tool)(
28792
29025
 
28793
29026
  // src/tool_lattice/collection/list_entries.ts
28794
29027
  var import_zod57 = __toESM(require("zod"));
28795
- var import_langchain68 = require("langchain");
29028
+ var import_langchain69 = require("langchain");
28796
29029
  var schema2 = import_zod57.default.object({
28797
29030
  collection: import_zod57.default.string().describe("Collection name")
28798
29031
  });
28799
29032
  function buildKey2(tenantId2, name) {
28800
29033
  return `${tenantId2}:${name}`;
28801
29034
  }
28802
- var createListEntriesTool = () => (0, import_langchain68.tool)(
29035
+ var createListEntriesTool = () => (0, import_langchain69.tool)(
28803
29036
  async (input, _exeConfig) => {
28804
29037
  try {
28805
29038
  const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
@@ -28827,7 +29060,7 @@ var createListEntriesTool = () => (0, import_langchain68.tool)(
28827
29060
 
28828
29061
  // src/tool_lattice/collection/add_entry.ts
28829
29062
  var import_zod58 = __toESM(require("zod"));
28830
- var import_langchain69 = require("langchain");
29063
+ var import_langchain70 = require("langchain");
28831
29064
  var import_documents = require("@langchain/core/documents");
28832
29065
  var import_uuid11 = require("uuid");
28833
29066
  var schema3 = import_zod58.default.object({
@@ -28838,7 +29071,7 @@ var schema3 = import_zod58.default.object({
28838
29071
  function key(t, n) {
28839
29072
  return `${t}:${n}`;
28840
29073
  }
28841
- var createAddEntryTool = () => (0, import_langchain69.tool)(
29074
+ var createAddEntryTool = () => (0, import_langchain70.tool)(
28842
29075
  async (input, _exeConfig) => {
28843
29076
  try {
28844
29077
  const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
@@ -28858,7 +29091,7 @@ var createAddEntryTool = () => (0, import_langchain69.tool)(
28858
29091
 
28859
29092
  // src/tool_lattice/collection/update_entry.ts
28860
29093
  var import_zod59 = __toESM(require("zod"));
28861
- var import_langchain70 = require("langchain");
29094
+ var import_langchain71 = require("langchain");
28862
29095
  var schema4 = import_zod59.default.object({
28863
29096
  collection: import_zod59.default.string().describe("Collection name"),
28864
29097
  entryId: import_zod59.default.string().describe("Entry ID to update"),
@@ -28868,7 +29101,7 @@ var schema4 = import_zod59.default.object({
28868
29101
  function key2(t, n) {
28869
29102
  return `${t}:${n}`;
28870
29103
  }
28871
- var createUpdateEntryTool = () => (0, import_langchain70.tool)(
29104
+ var createUpdateEntryTool = () => (0, import_langchain71.tool)(
28872
29105
  async (input, _exeConfig) => {
28873
29106
  try {
28874
29107
  const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
@@ -28888,7 +29121,7 @@ var createUpdateEntryTool = () => (0, import_langchain70.tool)(
28888
29121
 
28889
29122
  // src/tool_lattice/collection/delete_entry.ts
28890
29123
  var import_zod60 = __toESM(require("zod"));
28891
- var import_langchain71 = require("langchain");
29124
+ var import_langchain72 = require("langchain");
28892
29125
  var schema5 = import_zod60.default.object({
28893
29126
  collection: import_zod60.default.string().describe("Collection name"),
28894
29127
  entryId: import_zod60.default.string().describe("Entry ID to delete")
@@ -28896,7 +29129,7 @@ var schema5 = import_zod60.default.object({
28896
29129
  function key3(t, n) {
28897
29130
  return `${t}:${n}`;
28898
29131
  }
28899
- var createDeleteEntryTool = () => (0, import_langchain71.tool)(
29132
+ var createDeleteEntryTool = () => (0, import_langchain72.tool)(
28900
29133
  async (input, _exeConfig) => {
28901
29134
  try {
28902
29135
  const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
@@ -28914,7 +29147,7 @@ var createDeleteEntryTool = () => (0, import_langchain71.tool)(
28914
29147
  function createCollectionMiddleware(params) {
28915
29148
  const { collectionKeys, connectAll } = params;
28916
29149
  if (!connectAll && (!collectionKeys || collectionKeys.length === 0)) {
28917
- return (0, import_langchain72.createMiddleware)({
29150
+ return (0, import_langchain73.createMiddleware)({
28918
29151
  name: "collectionMiddleware",
28919
29152
  contextSchema,
28920
29153
  tools: [
@@ -28924,7 +29157,7 @@ function createCollectionMiddleware(params) {
28924
29157
  });
28925
29158
  }
28926
29159
  const listToolParams = { collectionKeys, connectAll };
28927
- return (0, import_langchain72.createMiddleware)({
29160
+ return (0, import_langchain73.createMiddleware)({
28928
29161
  name: "collectionMiddleware",
28929
29162
  contextSchema,
28930
29163
  tools: [
@@ -28986,11 +29219,11 @@ var collectionPlugin = {
28986
29219
  };
28987
29220
 
28988
29221
  // src/middlewares/askUserClarifyMiddleware.ts
28989
- var import_langchain74 = require("langchain");
29222
+ var import_langchain75 = require("langchain");
28990
29223
  var import_langgraph15 = require("@langchain/langgraph");
28991
29224
 
28992
29225
  // src/tool_lattice/ask_user_to_clarify/index.ts
28993
- var import_langchain73 = require("langchain");
29226
+ var import_langchain74 = require("langchain");
28994
29227
  var import_zod61 = __toESM(require("zod"));
28995
29228
  var questionSchema = import_zod61.default.object({
28996
29229
  question: import_zod61.default.string().describe("The question text to ask the user. MUST include the specific context, options, or details being clarified \u2014 never use a bare generic label. Good: 'Confirm the plan: use Redis cache + PostgreSQL primary, split microservices as needed?' Bad: 'Confirm the plan?'"),
@@ -29003,7 +29236,7 @@ var inputSchema = import_zod61.default.object({
29003
29236
  questions: import_zod61.default.array(questionSchema).min(1, "At least one question is required").describe("A structured sequence of clarification questions. Use these to gather missing parameters or disambiguate user intent before proceeding.")
29004
29237
  });
29005
29238
  function createAskUserToClarifyTool() {
29006
- return (0, import_langchain73.tool)(
29239
+ return (0, import_langchain74.tool)(
29007
29240
  async (input) => {
29008
29241
  return JSON.stringify(input);
29009
29242
  },
@@ -29017,7 +29250,7 @@ function createAskUserToClarifyTool() {
29017
29250
 
29018
29251
  // src/middlewares/askUserClarifyMiddleware.ts
29019
29252
  function createAskUserClarifyMiddleware() {
29020
- return (0, import_langchain74.createMiddleware)({
29253
+ return (0, import_langchain75.createMiddleware)({
29021
29254
  name: "AskUserClarifyMiddleware",
29022
29255
  tools: [createAskUserToClarifyTool()],
29023
29256
  wrapToolCall: async (request, handler) => {
@@ -29031,7 +29264,7 @@ function createAskUserClarifyMiddleware() {
29031
29264
  throw error;
29032
29265
  }
29033
29266
  console.error(`Error executing tool "${toolName}":`, error);
29034
- return new import_langchain74.ToolMessage({
29267
+ return new import_langchain75.ToolMessage({
29035
29268
  content: `Error executing tool: ${error instanceof Error ? error.message : "Unknown error"}`,
29036
29269
  tool_call_id: toolCall?.id,
29037
29270
  name: toolName
@@ -29040,7 +29273,7 @@ function createAskUserClarifyMiddleware() {
29040
29273
  }
29041
29274
  const parsed = inputSchema.safeParse(toolCall?.args);
29042
29275
  if (!parsed.success) {
29043
- return new import_langchain74.ToolMessage({
29276
+ return new import_langchain75.ToolMessage({
29044
29277
  content: `Invalid clarify tool arguments: ${parsed.error.message}`,
29045
29278
  tool_call_id: toolCall?.id,
29046
29279
  name: toolName
@@ -29060,7 +29293,7 @@ function createAskUserClarifyMiddleware() {
29060
29293
  const result = await (0, import_langgraph15.interrupt)(md);
29061
29294
  const response = result.data;
29062
29295
  if (!response?.answers || response.answers.length === 0) {
29063
- return new import_langchain74.ToolMessage({
29296
+ return new import_langchain75.ToolMessage({
29064
29297
  content: "No clarification questions were answered.",
29065
29298
  tool_call_id: toolCall?.id,
29066
29299
  name: toolName
@@ -29070,7 +29303,7 @@ function createAskUserClarifyMiddleware() {
29070
29303
  (answer) => (answer.selectedOptions?.length ?? 0) > 0 || answer.otherText && answer.otherText.trim() !== "" || answer.filePath && answer.filePath.trim() !== ""
29071
29304
  );
29072
29305
  if (answeredQuestions.length === 0) {
29073
- return new import_langchain74.ToolMessage({
29306
+ return new import_langchain75.ToolMessage({
29074
29307
  content: "No clarification questions were answered.",
29075
29308
  tool_call_id: toolCall?.id,
29076
29309
  name: toolName
@@ -29100,7 +29333,7 @@ function createAskUserClarifyMiddleware() {
29100
29333
  }
29101
29334
  lines.push("");
29102
29335
  }
29103
- return new import_langchain74.ToolMessage({
29336
+ return new import_langchain75.ToolMessage({
29104
29337
  content: lines.join("\n"),
29105
29338
  tool_call_id: toolCall?.id,
29106
29339
  name: toolName
@@ -29126,10 +29359,10 @@ var askUserClarifyPlugin = {
29126
29359
  };
29127
29360
 
29128
29361
  // src/middlewares/widgetMiddleware.ts
29129
- var import_langchain77 = require("langchain");
29362
+ var import_langchain78 = require("langchain");
29130
29363
 
29131
29364
  // src/tool_lattice/widget/loadGuidelines.ts
29132
- var import_langchain75 = require("langchain");
29365
+ var import_langchain76 = require("langchain");
29133
29366
  var import_zod62 = require("zod");
29134
29367
 
29135
29368
  // src/middlewares/guidelines/index.ts
@@ -29927,7 +30160,7 @@ var LoadGuidelinesInputSchema = import_zod62.z.object({
29927
30160
  )
29928
30161
  });
29929
30162
  function createLoadGuidelinesTool() {
29930
- return (0, import_langchain75.tool)(
30163
+ return (0, import_langchain76.tool)(
29931
30164
  async (input) => {
29932
30165
  const result = getGuidelines(input.modules);
29933
30166
  return result;
@@ -29941,7 +30174,7 @@ function createLoadGuidelinesTool() {
29941
30174
  }
29942
30175
 
29943
30176
  // src/tool_lattice/widget/showWidget.ts
29944
- var import_langchain76 = require("langchain");
30177
+ var import_langchain77 = require("langchain");
29945
30178
  var import_zod63 = require("zod");
29946
30179
  function containsForbiddenTags(code) {
29947
30180
  const forbiddenPatterns = [
@@ -29977,7 +30210,7 @@ var ShowWidgetInputSchema = import_zod63.z.object({
29977
30210
  )
29978
30211
  });
29979
30212
  function createShowWidgetTool() {
29980
- return (0, import_langchain76.tool)(
30213
+ return (0, import_langchain77.tool)(
29981
30214
  async (input) => {
29982
30215
  if (!input.i_have_seen_guidelines) {
29983
30216
  return "Error: You must call load_guidelines before using show_widget. Set i_have_seen_guidelines to true only after loading guidelines.";
@@ -30008,7 +30241,7 @@ function createWidgetMiddleware() {
30008
30241
  createLoadGuidelinesTool(),
30009
30242
  createShowWidgetTool()
30010
30243
  ];
30011
- return (0, import_langchain77.createMiddleware)({
30244
+ return (0, import_langchain78.createMiddleware)({
30012
30245
  name: "widgetMiddleware",
30013
30246
  contextSchema,
30014
30247
  tools
@@ -30032,7 +30265,7 @@ var widgetPlugin = {
30032
30265
  };
30033
30266
 
30034
30267
  // src/middlewares/evalMiddleware.ts
30035
- var import_langchain78 = require("langchain");
30268
+ var import_langchain79 = require("langchain");
30036
30269
  var import_zod64 = require("zod");
30037
30270
  var import_uuid12 = require("uuid");
30038
30271
 
@@ -30069,10 +30302,21 @@ Write assertions as objective, verifiable natural language:
30069
30302
  - steps: [{agent_id: "a"}, {agent_id: "b", override_message: "Based on..."}] for chain
30070
30303
  - outputType: "message_content" or "file_content"
30071
30304
 
30305
+ ## Designing HITL Cases
30306
+ If the flow under test PAUSES for human input (HITL \u2014 the agent requests approval/confirmation), configure interruptPolicy on the case \u2014 otherwise the run stops at the pause and the flow AFTER the human input is never tested:
30307
+
30308
+ - interruptPolicy: {mode: "auto-approve"} \u2014 inject "\u540C\u610F"; tests the full flow after approval (e.g. payment executed after approval). Use value to override the injected text.
30309
+ - interruptPolicy: {mode: "auto-reject"} \u2014 inject "\u62D2\u7EDD"; tests the rejection path.
30310
+ - interruptPolicy: {mode: "canned-response", value: "..."} \u2014 inject an exact human reply; tests behavior under a specific response.
30311
+ - Omit (default "stop") \u2014 the case pauses at the request; the judge evaluates whether pausing was the correct behavior (e.g. "must request approval" PASSES; "must be autonomous" FAILS).
30312
+
30313
+ Choose per the assertion: if the assertion describes what happens AFTER the human input, you MUST set an auto-resolve policy.
30314
+
30072
30315
  ## Checklist
30073
30316
  1. Check existing assets with read_eval to avoid duplication
30074
30317
  2. Start with 3-5 high-signal cases
30075
- 3. Confirm with user before calling manage_eval
30318
+ 3. If the flow contains a human-approval step and the assertion covers what happens AFTER it, set interruptPolicy (auto-approve / auto-reject / canned-response) \u2014 never leave it unset in that case
30319
+ 4. Confirm with user before calling manage_eval
30076
30320
  `,
30077
30321
  "eval-run-and-govern": `---
30078
30322
  name: eval-run-and-govern
@@ -30082,8 +30326,11 @@ description: Run agent evaluations, interpret results, diagnose failures, and re
30082
30326
  # Agent Governance Loop
30083
30327
 
30084
30328
  1. Discover project \u2192 read_eval list_projects
30085
- 2. Start evaluation \u2192 run_eval start(projectId) \u2014 ASYNC, may take minutes
30086
- 3. Poll status \u2192 run_eval status(runId) with backoff: 15s, 30s, 60s, max 120s
30329
+ 2. Start evaluation \u2192 run_eval start(projectId) \u2014 SYNCHRONOUS by default:
30330
+ blocks up to ~150s and returns the FINAL RESULTS in one call.
30331
+ Hold-out (validation) runs return aggregates only.
30332
+ 3. If still running (or use wait: false for fire-and-forget) \u2192 poll
30333
+ run_eval status(runId, sleepMs) \u2014 pass sleepMs to pace (15s, 30s, 60s, max 120s)
30087
30334
  4. If runnerAlive=false and status=running \u2192 ORPHANED (gateway restart).
30088
30335
  resume(runId) marks it failed automatically \u2014 then start a new run.
30089
30336
  5. Get results \u2192 read_eval get_run_results(runId) for per-case dimension scores
@@ -30104,7 +30351,26 @@ Use read_eval get_run_results for multiple runs and present comparison.
30104
30351
  `
30105
30352
  };
30106
30353
 
30354
+ // src/tool_lattice/withToolTimeout.ts
30355
+ function withToolTimeout(executor, timeoutMs = 18e4) {
30356
+ return async (input, exeConfig) => {
30357
+ return new Promise((resolve4, reject) => {
30358
+ const timer = setTimeout(() => {
30359
+ reject(new Error(`Tool execution timed out after ${timeoutMs}ms`));
30360
+ }, timeoutMs);
30361
+ executor(input, exeConfig).then((result) => {
30362
+ clearTimeout(timer);
30363
+ resolve4(result);
30364
+ }).catch((err) => {
30365
+ clearTimeout(timer);
30366
+ reject(err);
30367
+ });
30368
+ });
30369
+ };
30370
+ }
30371
+
30107
30372
  // src/middlewares/evalMiddleware.ts
30373
+ var RUN_EVAL_SYNC_WAIT_MS = 15e4;
30108
30374
  function getStore() {
30109
30375
  return getStoreLattice("default", "eval").store;
30110
30376
  }
@@ -30131,6 +30397,25 @@ function sanitize(obj) {
30131
30397
  }
30132
30398
  return out;
30133
30399
  }
30400
+ function aggregateHoldoutResults(results) {
30401
+ const passed = results.filter((r) => r.pass).length;
30402
+ const interrupted = results.filter((r) => r.interrupted).length;
30403
+ return {
30404
+ holdout: true,
30405
+ passedCases: passed,
30406
+ failedCases: results.length - passed,
30407
+ interruptedCases: interrupted,
30408
+ passRate: results.length > 0 ? passed / results.length : 0,
30409
+ totalCases: results.length
30410
+ };
30411
+ }
30412
+ async function runWithResults(tid, store, svc, run, runnerAlive) {
30413
+ const results = run.status === "completed" ? await store.getResultsByRun(tid, run.id) : void 0;
30414
+ if (run.holdout && results) {
30415
+ return { ...run, runnerAlive, results: aggregateHoldoutResults(results) };
30416
+ }
30417
+ return { ...run, runnerAlive, results };
30418
+ }
30134
30419
  function createReadEvalTool() {
30135
30420
  const schema6 = import_zod64.z.object({
30136
30421
  action: import_zod64.z.enum([
@@ -30151,7 +30436,7 @@ function createReadEvalTool() {
30151
30436
  runId: import_zod64.z.string().optional(),
30152
30437
  status: import_zod64.z.string().optional().describe("Filter: running|completed|failed|aborted")
30153
30438
  });
30154
- return (0, import_langchain78.tool)(
30439
+ return (0, import_langchain79.tool)(
30155
30440
  async (input, exeConfig) => {
30156
30441
  const tid = tenantId(exeConfig);
30157
30442
  if (!tid) {
@@ -30190,13 +30475,8 @@ function createReadEvalTool() {
30190
30475
  if (!run) return JSON.stringify({ success: false, error: "Run not found" });
30191
30476
  const results = await store.getResultsByRun(tid, input.runId);
30192
30477
  if (run.holdout) {
30193
- const passed = results.filter((r) => r.pass).length;
30194
30478
  data = {
30195
- holdout: true,
30196
- passedCases: passed,
30197
- failedCases: results.length - passed,
30198
- passRate: results.length > 0 ? passed / results.length : 0,
30199
- totalCases: results.length,
30479
+ ...aggregateHoldoutResults(results),
30200
30480
  message: "Hold-out run \u2014 per-case results withheld. Only aggregates are available."
30201
30481
  };
30202
30482
  } else {
@@ -30231,6 +30511,7 @@ ACTIONS:
30231
30511
  - get_run_results(runId) \u2014 per-case results with dimension scores.
30232
30512
  For HOLD-OUT (validation-only) runs: returns AGGREGATES ONLY
30233
30513
  (passRate, counts) \u2014 per-case details are withheld by design.
30514
+ Cases paused for human input (HITL) carry interrupted=true and are judged \u2014 the judge evaluates whether pausing was correct business behavior.
30234
30515
  - get_project_report(projectId) \u2014 aggregated stats across all runs`,
30235
30516
  schema: schema6
30236
30517
  }
@@ -30261,9 +30542,13 @@ function createManageEvalTool() {
30261
30542
  steps: import_zod64.z.array(import_zod64.z.object({ agent_id: import_zod64.z.string(), override_message: import_zod64.z.string().optional() })).optional(),
30262
30543
  outputType: import_zod64.z.enum(["file_content", "message_content"]).optional(),
30263
30544
  contentAssertion: import_zod64.z.string().optional(),
30264
- rubrics: import_zod64.z.array(import_zod64.z.object({ name: import_zod64.z.string(), weight: import_zod64.z.number(), description: import_zod64.z.string() })).optional()
30545
+ rubrics: import_zod64.z.array(import_zod64.z.object({ name: import_zod64.z.string(), weight: import_zod64.z.number(), description: import_zod64.z.string() })).optional(),
30546
+ interruptPolicy: import_zod64.z.object({
30547
+ mode: import_zod64.z.enum(["stop", "auto-approve", "auto-reject", "canned-response"]).describe("stop=judge the pause; auto-approve/auto-reject/canned-response=resume the agent to test the flow after the human input"),
30548
+ value: import_zod64.z.string().optional().describe("Response to inject (defaults: \u540C\u610F / \u62D2\u7EDD; required for canned-response)")
30549
+ }).optional().describe("Optional for create_case/update_case \u2014 how HITL interrupts are handled")
30265
30550
  });
30266
- return (0, import_langchain78.tool)(
30551
+ return (0, import_langchain79.tool)(
30267
30552
  async (input, exeConfig) => {
30268
30553
  const tid = tenantId(exeConfig);
30269
30554
  if (!tid) {
@@ -30319,7 +30604,8 @@ function createManageEvalTool() {
30319
30604
  steps: input.steps,
30320
30605
  outputType: input.outputType,
30321
30606
  contentAssertion: input.contentAssertion,
30322
- rubrics: input.rubrics
30607
+ rubrics: input.rubrics,
30608
+ interruptPolicy: input.interruptPolicy
30323
30609
  });
30324
30610
  break;
30325
30611
  case "update_case":
@@ -30327,7 +30613,8 @@ function createManageEvalTool() {
30327
30613
  inputMessage: input.inputMessage,
30328
30614
  contentAssertion: input.contentAssertion,
30329
30615
  steps: input.steps,
30330
- rubrics: input.rubrics
30616
+ rubrics: input.rubrics,
30617
+ interruptPolicy: input.interruptPolicy
30331
30618
  });
30332
30619
  break;
30333
30620
  case "delete_case":
@@ -30352,9 +30639,13 @@ Project: create_project(name, description?, judgeModelKey?, concurrency?) | upda
30352
30639
  **When creating a project from within a workspace, the workspace/project context is
30353
30640
  automatically bound \u2014 eval runs will execute in the same workspace.**
30354
30641
  Suite: create_suite(projectId, name) | update_suite | delete_suite
30355
- Case: create_case(suiteId, inputMessage, steps, outputType, contentAssertion, inputFiles?, rubrics?)
30642
+ Case: create_case(suiteId, inputMessage, steps, outputType, contentAssertion, inputFiles?, rubrics?, interruptPolicy?)
30356
30643
  steps is [{agent_id, override_message?}]. outputType is "file_content" or "message_content".
30357
- rubrics is [{name, weight, description}]. | update_case | delete_case`,
30644
+ rubrics is [{name, weight, description}]. | update_case | delete_case
30645
+ interruptPolicy: {mode: "stop"|"auto-approve"|"auto-reject"|"canned-response", value?} \u2014 how HITL interrupts are handled:
30646
+ stop (default): case pauses at the human-input request; the judge evaluates the pause as business behavior.
30647
+ auto-approve / auto-reject: the runner injects approval/rejection and tests the FULL flow after the pause.
30648
+ canned-response: injects the exact value (simulates a specific human reply).`,
30358
30649
  schema: schema6
30359
30650
  }
30360
30651
  );
@@ -30365,100 +30656,121 @@ function createRunEvalTool() {
30365
30656
  projectId: import_zod64.z.string().optional().describe("Required for start"),
30366
30657
  suiteIds: import_zod64.z.array(import_zod64.z.string()).optional().describe("Optional for start \u2014 only run these suites (e.g. dev set only). Omit to run all."),
30367
30658
  caseIds: import_zod64.z.array(import_zod64.z.string()).optional().describe("Optional for start \u2014 only run these cases across the selected suites. Omit to run all cases in those suites."),
30368
- runId: import_zod64.z.string().optional().describe("Required for status, resume, abort")
30659
+ runId: import_zod64.z.string().optional().describe("Required for status, resume, abort"),
30660
+ sleepMs: import_zod64.z.number().int().min(0).max(12e4).optional().describe("Optional for status \u2014 sleep this many ms BEFORE checking the run, to pace polling (e.g. 15000 \u2192 30000 \u2192 60000 \u2192 120000). Omit to check immediately."),
30661
+ wait: import_zod64.z.boolean().optional().describe("Optional for start \u2014 defaults to true: block synchronously (up to ~150s) and return final results in one call. Set false to return the runId immediately and poll.")
30369
30662
  });
30370
- return (0, import_langchain78.tool)(
30371
- async (input, exeConfig) => {
30372
- const tid = tenantId(exeConfig);
30373
- if (!tid) {
30374
- return JSON.stringify({ success: false, error: "No tenant context. Agent must be invoked through gateway." });
30375
- }
30376
- try {
30377
- const store = getStore();
30378
- const svc = getEvalRunService();
30379
- let data;
30380
- switch (input.action) {
30381
- case "start": {
30382
- const ctx = workspaceContext(exeConfig);
30383
- const runId = await svc.startRun(tid, input.projectId, input.suiteIds, input.caseIds, {
30384
- workspaceId: ctx.workspaceId,
30385
- projectId: ctx.projectId
30386
- });
30387
- data = sanitize({ runId, message: "Run started. Poll with run_eval status (backoff: 15s\u219230s\u219260s\u2192max 120s)." });
30388
- break;
30389
- }
30390
- case "status": {
30391
- const run = await store.getRunById(tid, input.runId);
30392
- if (!run) return JSON.stringify({ success: false, error: "Run not found" });
30393
- data = sanitize({ ...run, runnerAlive: svc.isRunning(input.runId) });
30394
- break;
30395
- }
30396
- case "resume": {
30397
- const run = await store.getRunById(tid, input.runId);
30398
- if (!run) return JSON.stringify({ success: false, error: "Run not found" });
30399
- const runnerAlive = svc.isRunning(input.runId);
30400
- if (run.status === "running" && !runnerAlive) {
30401
- await store.updateRunStatus(tid, run.id, {
30402
- status: "failed",
30403
- error: "Gateway restarted \u2014 run orphaned",
30404
- completedAt: /* @__PURE__ */ new Date()
30405
- });
30406
- data = sanitize({
30407
- ...run,
30408
- status: "failed",
30409
- runnerAlive: false,
30410
- message: "Run was orphaned \u2014 marked failed. Start a new run."
30411
- });
30663
+ return (0, import_langchain79.tool)(
30664
+ withToolTimeout(
30665
+ async (input, exeConfig) => {
30666
+ const tid = tenantId(exeConfig);
30667
+ if (!tid) {
30668
+ return JSON.stringify({ success: false, error: "No tenant context. Agent must be invoked through gateway." });
30669
+ }
30670
+ try {
30671
+ const store = getStore();
30672
+ const svc = getEvalRunService();
30673
+ let data;
30674
+ switch (input.action) {
30675
+ case "start": {
30676
+ const ctx = workspaceContext(exeConfig);
30677
+ const runId = await svc.startRun(tid, input.projectId, input.suiteIds, input.caseIds, ctx);
30678
+ if (input.wait === false) {
30679
+ data = sanitize({ runId, message: "Run started. Poll with run_eval status (backoff: 15s\u219230s\u219260s\u2192max 120s)." });
30680
+ break;
30681
+ }
30682
+ let timer;
30683
+ try {
30684
+ await Promise.race([
30685
+ svc.waitForRun(runId).catch(() => {
30686
+ }),
30687
+ new Promise((resolve4) => {
30688
+ timer = setTimeout(resolve4, RUN_EVAL_SYNC_WAIT_MS);
30689
+ })
30690
+ ]);
30691
+ } finally {
30692
+ if (timer) clearTimeout(timer);
30693
+ }
30694
+ const run = await store.getRunById(tid, runId);
30695
+ if (!run) return JSON.stringify({ success: false, error: "Run not found" });
30696
+ if (run.status === "running") {
30697
+ data = sanitize({
30698
+ runId,
30699
+ status: "running",
30700
+ runnerAlive: svc.isRunning(runId),
30701
+ message: `Run not finished within ${RUN_EVAL_SYNC_WAIT_MS / 1e3}s \u2014 poll with run_eval status(runId, sleepMs) (e.g. 15000, doubling up to 120000), or abort with run_eval abort.`
30702
+ });
30703
+ break;
30704
+ }
30705
+ data = sanitize({ synced: true, ...await runWithResults(tid, store, svc, run, svc.isRunning(runId)) });
30412
30706
  break;
30413
30707
  }
30414
- const results = run.status === "completed" ? await store.getResultsByRun(tid, run.id) : void 0;
30415
- if (run.holdout && results) {
30416
- const passed = results.filter((r) => r.pass).length;
30417
- data = sanitize({
30418
- ...run,
30419
- runnerAlive,
30420
- results: {
30421
- holdout: true,
30422
- passedCases: passed,
30423
- failedCases: results.length - passed,
30424
- passRate: results.length > 0 ? passed / results.length : 0,
30425
- totalCases: results.length
30426
- }
30427
- });
30708
+ case "status": {
30709
+ if (input.sleepMs && input.sleepMs > 0) {
30710
+ await new Promise((resolve4) => setTimeout(resolve4, input.sleepMs));
30711
+ }
30712
+ const run = await store.getRunById(tid, input.runId);
30713
+ if (!run) return JSON.stringify({ success: false, error: "Run not found" });
30714
+ data = sanitize({ ...run, runnerAlive: svc.isRunning(input.runId) });
30428
30715
  break;
30429
30716
  }
30430
- data = sanitize({ ...run, runnerAlive, results });
30431
- break;
30432
- }
30433
- case "abort": {
30434
- const run = await store.getRunById(tid, input.runId);
30435
- if (!run) return JSON.stringify({ success: false, error: "Run not found" });
30436
- const ok = await svc.abortRun(input.runId);
30437
- data = sanitize({ aborted: ok });
30438
- break;
30717
+ case "resume": {
30718
+ const run = await store.getRunById(tid, input.runId);
30719
+ if (!run) return JSON.stringify({ success: false, error: "Run not found" });
30720
+ const runnerAlive = svc.isRunning(input.runId);
30721
+ if (run.status === "running" && !runnerAlive) {
30722
+ await store.updateRunStatus(tid, run.id, {
30723
+ status: "failed",
30724
+ error: "Gateway restarted \u2014 run orphaned",
30725
+ completedAt: /* @__PURE__ */ new Date()
30726
+ });
30727
+ data = sanitize({
30728
+ ...run,
30729
+ status: "failed",
30730
+ runnerAlive: false,
30731
+ message: "Run was orphaned \u2014 marked failed. Start a new run."
30732
+ });
30733
+ break;
30734
+ }
30735
+ data = sanitize(await runWithResults(tid, store, svc, run, runnerAlive));
30736
+ break;
30737
+ }
30738
+ case "abort": {
30739
+ const run = await store.getRunById(tid, input.runId);
30740
+ if (!run) return JSON.stringify({ success: false, error: "Run not found" });
30741
+ const ok = await svc.abortRun(input.runId);
30742
+ data = sanitize({ aborted: ok });
30743
+ break;
30744
+ }
30745
+ default:
30746
+ return JSON.stringify({ success: false, error: `Unknown action: ${input.action}` });
30439
30747
  }
30440
- default:
30441
- return JSON.stringify({ success: false, error: `Unknown action: ${input.action}` });
30748
+ return JSON.stringify({ success: true, data });
30749
+ } catch (e) {
30750
+ return JSON.stringify({ success: false, error: e.message });
30442
30751
  }
30443
- return JSON.stringify({ success: true, data });
30444
- } catch (e) {
30445
- return JSON.stringify({ success: false, error: e.message });
30446
30752
  }
30447
- },
30753
+ ),
30448
30754
  {
30449
30755
  name: "run_eval",
30450
- description: `Execute and manage evaluation runs. ASYNCHRONOUS \u2014 may take minutes.
30756
+ description: `Execute and manage evaluation runs.
30451
30757
 
30452
30758
  ACTIONS:
30453
- - start(projectId, suiteIds?, caseIds?) \u2014 begin evaluation (optionally only the listed suites, and/or only the listed cases). Returns runId.
30454
- - status(runId) \u2014 current status + runnerAlive flag:
30455
- \u2022 runnerAlive=true, status=running: keep polling
30759
+ - start(projectId, suiteIds?, caseIds?, wait?) \u2014 begin evaluation (optionally only the listed suites, and/or only the listed cases).
30760
+ wait=true (DEFAULT): SYNCHRONOUS \u2014 blocks up to ~150s and returns the FINAL RESULTS in one call:
30761
+ { status, results } with per-case pass/score (hold-out/validation runs: aggregates only \u2014 per-case details withheld by design).
30762
+ Cases paused for human input (HITL) carry interrupted=true and ARE judged \u2014 the judge evaluates whether requesting
30763
+ the human was the correct behavior (assertions like "must approve first" PASS; "must be autonomous" FAIL). interruptedCases counts these.
30764
+ If the run exceeds 150s: returns { runId, status: "running" } \u2014 NOT an error \u2014 then poll with status/resume until completed.
30765
+ wait=false: fire-and-forget \u2014 returns { runId } immediately; poll with status.
30766
+ - status(runId, sleepMs?) \u2014 sleep sleepMs first (to pace polling), then return current status + runnerAlive flag:
30767
+ \u2022 runnerAlive=true, status=running: keep polling \u2014 call status(runId, sleepMs) with backoff 15s\u219230s\u219260s\u2192max 120s
30456
30768
  \u2022 runnerAlive=false, status=running: ORPHANED \u2014 resume marks it failed automatically; then start a new run
30457
30769
  \u2022 status=completed: get results with read_eval get_run_results or run_eval resume
30458
30770
  - resume(runId) \u2014 reconnect from new conversation. Returns status + results if completed.
30459
30771
  - abort(runId) \u2014 cancel running evaluation.
30460
30772
 
30461
- Polling: start at 15s, double each time, max 120s between polls. Batch reports.`,
30773
+ Polling (only needed with wait=false or after a sync timeout): call status(runId, sleepMs) so the tool sleeps before checking; start at 15s, double each time, max 120s between polls. Batch reports.`,
30462
30774
  schema: schema6
30463
30775
  }
30464
30776
  );
@@ -30479,7 +30791,7 @@ var evalPlugin = {
30479
30791
  defaultConfig: {}
30480
30792
  },
30481
30793
  skills: EVAL_SKILLS,
30482
- middleware: () => (0, import_langchain78.createMiddleware)({
30794
+ middleware: () => (0, import_langchain79.createMiddleware)({
30483
30795
  name: "EvalMiddleware",
30484
30796
  tools: [createReadEvalTool(), createManageEvalTool(), createRunEvalTool()]
30485
30797
  })
@@ -30754,67 +31066,64 @@ verification choice, then start benchmarking.
30754
31066
 
30755
31067
  ## Task Tracking \u2014 see [[task-tracking]]
30756
31068
 
30757
- **Create the parent task when the task is actually defined** \u2014 after
30758
- Phase 0 clarification is complete and the user confirmed the path
30759
- (fresh vs incremental). Do NOT create tasks during clarification:
30760
- while asking questions (0.0-0.4) you don't know what the task is yet.
30761
- Once the scope is clear (end of 0.5), that is the moment to create:
30762
- manage_task create("Learn [material]", ownerType: "agent"). Then a
30763
- subtask per phase as you start it. Update status to reflect reality \u2014
30764
- never mark a subtask completed while eval fails. Resume interrupted
30765
- runs with manage_task list.
31069
+ **Universal principle**: once the goal is clear and you know what to
31070
+ do, create the parent task BEFORE executing (manage_task create, see
31071
+ [[task-tracking]]). In this workflow: after Phase 0 clarification
31072
+ completes and the user confirmed the path (end of 0.5), create the
31073
+ parent task; then a subtask per phase as you start it. The parent task
31074
+ description carries the GOAL MODEL (0.1.5) as Objective + Acceptance
31075
+ Criteria; the expected output spec (2.6) updates the criteria. Update
31076
+ status to reflect reality \u2014 never mark a subtask completed while eval
31077
+ fails. Resume interrupted runs with manage_task list.
30766
31078
 
30767
31079
  Widgets: call \`load_guidelines\` ONCE before your first \`show_widget\`
30768
31080
  (show_widget hard-requires it), then reuse.
30769
31081
 
30770
31082
  ---
30771
31083
 
30772
- ## Phase 1: Probe (material-dependent)
30773
-
30774
- The probing strategy depends on the material type from Phase 0.0:
30775
-
30776
- **User-description material**: the requirements come from the
30777
- conversation itself \u2014 no probing needed. Extract the agent's goal,
30778
- inputs, outputs, and constraints from what the user described. Go
30779
- straight to design.
30780
-
30781
- **Document material** (PDF / spec / manual):
30782
- If the engine was chosen in Phase 0 (0.3 \u2460-\u2464): skip the comparison \u2014
30783
- parse directly with \`parse_document\` using the chosen engine
30784
- (file_path, engine, output_path per file).
30785
- Otherwise: run the document-parser-benchmark subagent via \`task\` on each file.
30786
- Collect engine scores, parsed output (via \`read_file\`), and feature signatures.
30787
-
30788
- **Engine selection IS distilled knowledge, not just setup.** For document
30789
- material, the benchmark answers "which engine parses THIS document (or
30790
- this class of document) best?" \u2014 that answer is knowledge that drives
30791
- the whole rest of the run:
30792
- - **Builds the agent**: the chosen engine's \`parse_document\` goes into
30793
- the production agent's middleware/tools.
30794
- - **Designs the tests**: the chosen engine's parsed output becomes the
30795
- baseline input for eval cases \u2014 cases feed parsed output to the agent
30796
- and assert correct extraction from it.
30797
- - **Seeds the skill**: the feature signature (tables? scans? mixed
30798
- zh/en?) plus the winning engine becomes a skill note ("for PO PDFs
30799
- with tables, use textin") reusable for future similar documents.
30800
- So when the user wants an agent whose purpose is document PARSING (not
30801
- extraction), the workflow is the same: benchmark to learn the engine
30802
- choice, then build the agent around that engine and test against its
30803
- output. Do NOT treat parsing as a pure tool-assembly task \u2014 the engine
30804
- choice is unknown knowledge until probed.
30805
-
30806
- **API spec material**: read the spec directly \u2014 no parsing engine needed.
30807
- Extract endpoints, schemas, request/response examples from the text.
30808
-
30809
- **Conversation material**: extract the workflow, decisions, and corrections
30810
- from the conversation context \u2014 no parsing engine needed.
30811
-
30812
- **Spreadsheet material**: parse cells directly \u2014 structured data needs
30813
- no engine comparison.
30814
- If verification will happen (0.2 \u2460 or \u2461): concurrently, \`list_agents\` to
30815
- discover existing agents with relevant capabilities (see \xA75).
30816
- For \u2460, look for agents with data-access tools (SQL / API). For \u2461, look
30817
- for agents with independence.
31084
+ ## Phase 1: Explore (goal-driven path finding)
31085
+
31086
+ The goal model (0.1.5) is set. Now EXPLORE how to achieve it \u2014 actively
31087
+ hunt for the path, do not passively read. Three exploration fronts:
31088
+
31089
+ **A. Existing assets (reuse, don't rebuild):**
31090
+ - \`list_agents\` / \`load_skills\` \u2192 are there existing agents or skills
31091
+ that already do part of this? Reuse them (update_agent if needed)
31092
+ instead of building from scratch. This is a goal-relevant check, not
31093
+ a materials step.
31094
+ - \`list_tools\` / \`list_middleware_types\` \u2192 what capabilities exist
31095
+ that the goal needs (parsing, data access, browser...)?
31096
+ - \`list_connections\` \u2192 are the data sources the goal depends on
31097
+ already connected?
31098
+ - If verification will happen (0.2 \u2460 or \u2461): concurrently discover
31099
+ executor candidates (see \xA75). \u2460 \u2192 data-access tools; \u2461 \u2192 independence.
31100
+
31101
+ **B. Material probing (by material type):**
31102
+ - **User-description**: the requirements come from the conversation.
31103
+ Extract goal, inputs, outputs, constraints \u2014 then explore the
31104
+ implementation path (A + feasibility): what assets exist, what tools
31105
+ are needed, what blockers stand between the goal and its achievement.
31106
+ - **Document** (PDF / spec / manual): benchmark engines as needed \u2014
31107
+ parse directly with the chosen engine (0.3 \u2460-\u2464) or run
31108
+ document-parser-benchmark. Engine selection IS distilled knowledge:
31109
+ it builds the agent (engine's parse_document into middleware), seeds
31110
+ the skill (feature signature + winning engine), and designs the tests
31111
+ (engine output as case baseline input).
31112
+ - **API spec**: read directly \u2014 endpoints, schemas, examples.
31113
+ - **Conversation**: extract workflow, decisions, corrections.
31114
+ - **Spreadsheet**: parse cells directly.
31115
+
31116
+ **C. Feasibility (path blockers):**
31117
+ - What stands between the goal and achievement? Missing tools, missing
31118
+ connections, data access, permission constraints, ambiguous
31119
+ requirements.
31120
+ - Does the goal require orchestration (\u2192 Phase 2 split decision)?
31121
+ - Surface these in the recommendation (Phase 1.5) \u2014 the user decides
31122
+ the path, informed by what exploration found.
31123
+
31124
+ Exploration is COMPLETE when you can answer: what exists to reuse,
31125
+ what must be built, what tools/connections are needed, and what blocks
31126
+ the goal. Do not go to design without this map.
30818
31127
 
30819
31128
  ---
30820
31129
 
@@ -30829,17 +31138,21 @@ candidate and assess (Validation Agent Design \xA70) \u2014 state which are
30829
31138
  usable and which are not, with reasons. For \u2460, the executor needs data
30830
31139
  tools + independence. For \u2461, independence only. If no candidate fits,
30831
31140
  plan to build one via \xA75.
30832
- Present probe results as widget, then MUST call
31141
+ Present the EXPLORATION map as widget \u2014 what exists to reuse, what
31142
+ must be built, tools/connections needed, blockers found \u2014 then
31143
+ recommend the IMPLEMENTATION PATH: reuse existing X, build new Y,
31144
+ split or single agent (Phase 2 input). MUST call
30833
31145
  \`ask_user_to_clarify\` NOW:
30834
31146
  {
30835
31147
  "questions": [{
30836
- "question": "Confirm the recommendation?",
31148
+ "question": "Confirm the recommended path?",
30837
31149
  "options": ["Confirm", "Adjust"],
30838
31150
  "type": "single",
30839
31151
  "required": true
30840
31152
  }]
30841
31153
  }
30842
- Skills planning belongs to Phase 2 \u2014 this phase presents data, not plans.
31154
+ Skills planning belongs to Phase 2 \u2014 this phase presents the path, not
31155
+ the detailed plan.
30843
31156
 
30844
31157
  ---
30845
31158
 
@@ -30907,9 +31220,53 @@ user-description material this IS the core phase; for material-based
30907
31220
  learning it designs the agent that runs the learned skill. Agent
30908
31221
  metadata (verified/version/source) must be set on creation.
30909
31222
 
31223
+ ## Phase 2.6: Expected Output Specification (mandatory \u2014 goal-driven)
31224
+
31225
+ **Expectations come FIRST, before writing the skill.** You cannot write
31226
+ a skill (or test cases) without a target. Define the expected output
31227
+ specification from the goal model (0.1.5: real goal / consumer / usable
31228
+ state) BEFORE Phase 3:
31229
+
31230
+ **HARD RULE \u2014 never guess the target.** If the goal, the expected
31231
+ output, the consumer, or the usable state is unclear at ANY point
31232
+ before writing test cases, you MUST ask the user via
31233
+ \`ask_user_to_clarify\` \u2014 do NOT proceed with an assumed expectation.
31234
+ A test case written against a guessed expectation is worthless: it
31235
+ validates the wrong thing. When in doubt, ask.
31236
+
31237
+ Per skill, define the EXPECTED OUTPUT SPEC (based on intent 0.1 and
31238
+ consumer 0.1.5):
31239
+ - Extract data \u2192 expected fields (names, types, formats), required vs
31240
+ optional, output structure (JSON schema shape, table columns)
31241
+ - Validate rules \u2192 expected judgment outcomes (pass/fail conditions),
31242
+ boundary values, and the reason format
31243
+ - Execute workflow \u2192 expected step sequence, decision points, final
31244
+ outcome shape
31245
+ - Answer knowledge \u2192 expected answer form (with/without sources,
31246
+ length, structure)
31247
+
31248
+ This spec IS the acceptance standard. Phase 4 contentAssertion must be
31249
+ derived from it (not invented at case-writing time). Present the
31250
+ expected output spec to the user and MUST call \`ask_user_to_clarify\`
31251
+ NOW per skill:
31252
+ {
31253
+ "questions": [{
31254
+ "question": "Confirm the expected output spec for {skill-name}?",
31255
+ "options": ["Confirm", "Adjust"],
31256
+ "type": "single",
31257
+ "required": true,
31258
+ "allowOther": true
31259
+ }]
31260
+ }
31261
+ Record the confirmed spec in the parent task description. This replaces
31262
+ guess-then-confirm: the skill is written TO MEET the spec, and test
31263
+ cases assert AGAINST the spec \u2014 no expectation is invented later.
31264
+
30910
31265
  ## Phase 3: Create Skills
30911
31266
 
30912
- Write SKILL.md to \`/root/.agents/skills/{name}/SKILL.md\` one at a time.
31267
+ Write SKILL.md to \`/root/.agents/skills/{name}/SKILL.md\` one at a time,
31268
+ designed TO MEET the expected output spec confirmed in Phase 2.6 \u2014 the
31269
+ skill encodes how to produce the spec's expected output.
30913
31270
  Show the skill content in text first, then MUST call
30914
31271
  \`ask_user_to_clarify\` NOW per skill:
30915
31272
  {
@@ -31138,7 +31495,8 @@ Both modes use the same agent type \u2014 skill only, no domain tools:
31138
31495
  verified: "unverified", # upgraded after eval passes
31139
31496
  version: "1.0", # bump on each update_agent
31140
31497
  source: "{material name}", # provenance
31141
- skill: "skill-name"
31498
+ skill: "skill-name",
31499
+ role: "orchestrator" | "sub-agent" # only for parent+subAgents structure
31142
31500
  }
31143
31501
  )
31144
31502
 
@@ -31202,7 +31560,8 @@ This learning loop adds its own scenario rules:
31202
31560
  - Business usability (output reaches the goal's "usable state")
31203
31561
  - Consumer fit (format/contract satisfies who uses the result)
31204
31562
  contentAssertion must encode the usable state from the goal model
31205
- (0.1.5), not just technical correctness.
31563
+ (0.1.5), derived from the EXPECTED OUTPUT SPEC (Phase 2.6) \u2014 never
31564
+ invented at case-writing time.
31206
31565
 
31207
31566
  1. One suite per skill per source: cases test "can this skill do it" \u2014
31208
31567
  never mix skills in one suite
@@ -31234,12 +31593,23 @@ Run evaluation, fix loop, hold-out validation, trust upgrade. See
31234
31593
  [[eval-verify]] for the full workflow. The eval-design-tests and
31235
31594
  eval-run-and-govern skills cover case design and run governance.
31236
31595
 
31596
+ **One eval project per agent**, named \`eval-{agent-id}\` \u2014 every agent
31597
+ built by this workflow gets its own eval project (see eval-verify
31598
+ Setup). Orchestrator + subAgents \u2192 one eval project per sub-agent plus
31599
+ one integration eval for the parent.
31600
+
31237
31601
  Learning-specific suite guidance:
31238
31602
  - 0.2 \u2461 \u2192 {skill}-user-sample; samples \u22658 \u2192 also {skill}-validation
31239
31603
  - 0.2 \u2460 \u2192 {skill}-api-verified (single step, \xA74.1)
31240
31604
  - User-description material: {skill}-requirement-derived \u2014 cases from
31241
31605
  user's described requirements
31242
31606
 
31607
+ **Case expectations come from the confirmed spec** (Phase 2.6): the
31608
+ contentAssertion of every case must be derived from the expected output
31609
+ spec, NOT invented at case-writing time. If a case needs an expectation
31610
+ not in the spec, go back and extend the spec with user confirmation
31611
+ first \u2014 never guess expectations on the fly.
31612
+
31243
31613
  [[completion-gate]] applies \u2014 eval must pass before declaring done.
31244
31614
 
31245
31615
  ## Phase 5: Retrospective
@@ -31272,11 +31642,12 @@ base is wanted (it is extra work beyond the skill).
31272
31642
  ## Fallback
31273
31643
 
31274
31644
  - All engines fail \u2192 suggest text version or different format.
31275
- - No eval agent \u2192 judge-only scoring, or build a production agent via \xA75
31276
- (generic or API-verified variant, thin prompt) \u2014 never reuse an agent
31277
- whose knowledge derives from the learning material.
31278
- Judge-only scoring does NOT unlock machine-confirmed \u2014 trust caps at
31279
- human-reviewed; say so explicitly.
31645
+ - Eval runtime unavailable (no eval agent / service down) \u2192 still
31646
+ DESIGN and CREATE the eval project with test cases (every agent MUST
31647
+ have an eval \u2014 no skip). If the eval cannot RUN now, deliver with
31648
+ trust capped at human-reviewed and state: "Test framework created;
31649
+ run the evaluation once the eval service is available." Judge-only
31650
+ scoring (when run) does NOT unlock machine-confirmed.
31280
31651
  - No test files \u2192 user-described scenarios as contentAssertion.
31281
31652
  - run_eval orphaned (resume shows runnerAlive=false) \u2192 \`run_eval resume(runId)\`
31282
31653
  marks it failed automatically; then \`run_eval start(projectId)\` to restart.
@@ -31381,12 +31752,12 @@ var documentLearningPlugin = {
31381
31752
  };
31382
31753
 
31383
31754
  // src/middlewares/documentParserMiddleware.ts
31384
- var import_langchain80 = require("langchain");
31755
+ var import_langchain81 = require("langchain");
31385
31756
 
31386
31757
  // src/tool_lattice/document_parser/index.ts
31387
31758
  var path7 = __toESM(require("path"));
31388
31759
  var import_zod65 = __toESM(require("zod"));
31389
- var import_langchain79 = require("langchain");
31760
+ var import_langchain80 = require("langchain");
31390
31761
  var PARSE_DOCUMENT_DESCRIPTION = `Parse a document file (docx, pdf) into structured Markdown using a remote document parsing service.
31391
31762
  This tool handles the full pipeline internally: file upload \u2192 document parsing \u2192 polling until complete \u2192 download result \u2192 save to filesystem.
31392
31763
 
@@ -31508,7 +31879,7 @@ function createParseDocumentTool({
31508
31879
  baseUrl = "",
31509
31880
  apiKey = ""
31510
31881
  }) {
31511
- return (0, import_langchain79.tool)(
31882
+ return (0, import_langchain80.tool)(
31512
31883
  async (input, exe_config) => {
31513
31884
  try {
31514
31885
  const runConfig = exe_config?.configurable?.runConfig ?? { assistant_id: "", thread_id: "" };
@@ -31772,7 +32143,7 @@ function createDocumentParserMiddleware(config) {
31772
32143
  const connectAll = config.connectAll === true;
31773
32144
  const baseUrl = config.baseUrl || "";
31774
32145
  const apiKey = config.apiKey || "";
31775
- return (0, import_langchain80.createMiddleware)({
32146
+ return (0, import_langchain81.createMiddleware)({
31776
32147
  name: "DocumentParser",
31777
32148
  contextSchema,
31778
32149
  tools: [createParseDocumentTool({ connectAll, baseUrl, apiKey })]