@axiom-lattice/core 3.0.4 → 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
 
@@ -12997,6 +13094,9 @@ description: Run agent evaluations, interpret results, fix failures, and
12997
13094
  metadata:
12998
13095
  domain: agent-building
12999
13096
  verified: unverified
13097
+ subSkills:
13098
+ - eval-design-tests
13099
+ - eval-run-and-govern
13000
13100
  ---
13001
13101
  # Eval Verify \u2014 Run Evaluations and Upgrade Trust
13002
13102
 
@@ -13013,6 +13113,13 @@ verified: unverified
13013
13113
  parent (eval-{parent-id}) \u2014 see Layered verification below.
13014
13114
  2. \`manage_eval create_case(suiteId, ...)\` per sample or scenario
13015
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.
13016
13123
 
13017
13124
  ## Suites per skill, by source
13018
13125
 
@@ -13356,10 +13463,20 @@ async function resolveConnections(type, connections, tenantId2) {
13356
13463
  throw err;
13357
13464
  }
13358
13465
  }
13359
- async function createCommonMiddlewares(middlewareConfigs, filesystemBackend, fsIsExised, tenantId2) {
13466
+ async function createCommonMiddlewares(middlewareConfigs, filesystemBackend, fsIsExised, tenantId2, model) {
13360
13467
  const middlewares = [];
13361
13468
  middlewares.push(createUnknownToolHandlerMiddleware());
13362
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
+ }
13363
13480
  const filesystemConfig = middlewareConfigs.find((m) => m.type === "filesystem");
13364
13481
  const clawConfig = middlewareConfigs.find((m) => m.type === "claw");
13365
13482
  const needsFilesystemBackend = filesystemConfig?.enabled || clawConfig?.enabled;
@@ -13691,8 +13808,8 @@ var ReActAgentGraphBuilder = class {
13691
13808
  const stateSchema2 = createReactAgentSchema(params.stateSchema);
13692
13809
  const middlewareConfigs = params.middleware || [];
13693
13810
  const filesystemBackend = createFilesystemBackendFactory(middlewareConfigs);
13694
- const middlewares = await createCommonMiddlewares(middlewareConfigs, filesystemBackend, void 0, params.tenantId);
13695
- return (0, import_langchain45.createAgent)({
13811
+ const middlewares = await createCommonMiddlewares(middlewareConfigs, filesystemBackend, void 0, params.tenantId, params.model);
13812
+ return (0, import_langchain47.createAgent)({
13696
13813
  model: params.model,
13697
13814
  tools,
13698
13815
  systemPrompt: params.prompt,
@@ -13706,11 +13823,11 @@ var ReActAgentGraphBuilder = class {
13706
13823
  };
13707
13824
 
13708
13825
  // src/deep_agent_new/agent.ts
13709
- var import_langchain53 = require("langchain");
13826
+ var import_langchain54 = require("langchain");
13710
13827
 
13711
13828
  // src/deep_agent_new/middleware/subagents.ts
13712
13829
  var import_v32 = require("zod/v3");
13713
- var import_langchain48 = require("langchain");
13830
+ var import_langchain50 = require("langchain");
13714
13831
  var import_langgraph8 = require("@langchain/langgraph");
13715
13832
  var import_messages3 = require("@langchain/core/messages");
13716
13833
 
@@ -14125,7 +14242,7 @@ var QueueMode = /* @__PURE__ */ ((QueueMode2) => {
14125
14242
 
14126
14243
  // src/services/Agent.ts
14127
14244
  var import_langgraph6 = require("@langchain/langgraph");
14128
- var import_langchain46 = require("langchain");
14245
+ var import_langchain48 = require("langchain");
14129
14246
 
14130
14247
  // src/chunk_buffer_lattice/ChunkBuffer.ts
14131
14248
  var ChunkBuffer = class {
@@ -14622,7 +14739,7 @@ var Agent = class {
14622
14739
  });
14623
14740
  const humanContent = p.content;
14624
14741
  const input = {
14625
- messages: [new import_langchain46.HumanMessage({ id: humanContent.id, content: humanContent.message })]
14742
+ messages: [new import_langchain48.HumanMessage({ id: humanContent.id, content: humanContent.message })]
14626
14743
  };
14627
14744
  if (files) {
14628
14745
  input.files = files;
@@ -14696,7 +14813,7 @@ var Agent = class {
14696
14813
  remainingPendings.forEach((p) => {
14697
14814
  this.queueStore?.markProcessing(p.id);
14698
14815
  const humanContent = p.content;
14699
- 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 }));
14700
14817
  this.publish("message:started", {
14701
14818
  type: "message:started",
14702
14819
  messageId: humanContent.id,
@@ -14776,7 +14893,7 @@ var Agent = class {
14776
14893
  if (signal?.aborted) break;
14777
14894
  await this.queueStore?.markProcessing(p.id);
14778
14895
  const humanContent = p.content;
14779
- 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 });
14780
14897
  const startTime = Date.now();
14781
14898
  this.publish("message:started", {
14782
14899
  type: "message:started",
@@ -14947,7 +15064,7 @@ var Agent = class {
14947
15064
  const messageId = (0, import_uuid4.v4)();
14948
15065
  const input = {
14949
15066
  ...queueMessage.input,
14950
- messages: [new import_langchain46.HumanMessage({ id: messageId, content: queueMessage.input.message })]
15067
+ messages: [new import_langchain48.HumanMessage({ id: messageId, content: queueMessage.input.message })]
14951
15068
  };
14952
15069
  const inputMessage = { ...queueMessage, input };
14953
15070
  return this.agentExecutor(inputMessage, signal);
@@ -14966,7 +15083,7 @@ var Agent = class {
14966
15083
  const messageId = (0, import_uuid4.v4)();
14967
15084
  const input = {
14968
15085
  ...queueMessage.input,
14969
- messages: [new import_langchain46.HumanMessage({ id: messageId, content: queueMessage.input.message })]
15086
+ messages: [new import_langchain48.HumanMessage({ id: messageId, content: queueMessage.input.message })]
14970
15087
  };
14971
15088
  const inputMessage = { ...queueMessage, input };
14972
15089
  const { runnable_agent, runConfig } = await this.getLatticeClientAndRuntimeConfig(inputMessage.custom_run_config);
@@ -15329,7 +15446,7 @@ var Agent = class {
15329
15446
  async getCurrentMessages() {
15330
15447
  const state = await this.getCurrentState();
15331
15448
  const messages = state.values.messages || [];
15332
- const filteredMessages = (0, import_langchain46.filterMessages)(messages, {
15449
+ const filteredMessages = (0, import_langchain48.filterMessages)(messages, {
15333
15450
  includeTypes: ["ai", "human", "tool"]
15334
15451
  //["human", "ai", "tool"],
15335
15452
  });
@@ -15648,7 +15765,7 @@ var AgentInstanceManager = class _AgentInstanceManager {
15648
15765
  var agentInstanceManager = AgentInstanceManager.getInstance();
15649
15766
 
15650
15767
  // src/middlewares/taskMiddleware.ts
15651
- var import_langchain47 = require("langchain");
15768
+ var import_langchain49 = require("langchain");
15652
15769
  var import_zod43 = require("zod");
15653
15770
  var import_langgraph7 = require("@langchain/langgraph");
15654
15771
  function getRunConfig(config) {
@@ -15956,26 +16073,37 @@ function createTaskMiddleware() {
15956
16073
  });
15957
16074
  }
15958
16075
  };
15959
- return (0, import_langchain47.createMiddleware)({
16076
+ return (0, import_langchain49.createMiddleware)({
15960
16077
  name: "TaskMiddleware",
15961
16078
  contextSchema,
15962
16079
  wrapModelCall: async (request, handler) => {
15963
16080
  const taskPrompt = `## Task Management
15964
16081
 
15965
- 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.
15966
16084
 
15967
- ### 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.
15968
16089
  - The user explicitly asks you to track, manage, or follow up on work
15969
16090
  - The work spans multiple sessions or might need resumption later
15970
16091
  - The user needs to review or approve output before it is considered done
15971
16092
  - There are multiple independent work items the user wants visibility into
15972
16093
 
15973
16094
  ### When NOT to create a task
16095
+ - Goal not yet clear (still clarifying) \u2014 clarify first, then create
15974
16096
  - One-shot lookups or simple Q&A ("what is X?", "search for Y")
15975
16097
  - Internal exploration steps you take to understand the problem (use \`write_todos\` for your execution plan instead)
15976
16098
  - Trivial single-step actions that complete in the same turn
15977
16099
  - Conversational or informational requests with no deliverable
15978
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
+
15979
16107
  ### Ownership defaults
15980
16108
  - No params: ownerType defaults to "user" with current user's ID
15981
16109
  - ownerType="agent": auto-fills ownerId from current agent (subtask for yourself)
@@ -15986,7 +16114,7 @@ You can use the \`manage_task\` tool to create persistent tasks for user-visible
15986
16114
  });
15987
16115
  },
15988
16116
  tools: [
15989
- (0, import_langchain47.tool)(
16117
+ (0, import_langchain49.tool)(
15990
16118
  handleManageTask,
15991
16119
  {
15992
16120
  name: "manage_task",
@@ -16029,6 +16157,29 @@ var taskPlugin = {
16029
16157
  skills: {
16030
16158
  "task-definition": `## Using manage_task
16031
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
+
16032
16183
  ### Task description format
16033
16184
 
16034
16185
  When creating a task with manage_task, write the description in this Markdown structure:
@@ -16230,7 +16381,7 @@ function returnCommandWithStateUpdate(result, toolCallId) {
16230
16381
  update: {
16231
16382
  ...stateUpdate,
16232
16383
  messages: [
16233
- new import_langchain48.ToolMessage({
16384
+ new import_langchain50.ToolMessage({
16234
16385
  content: lastMessage?.content || "Task Failed to complete",
16235
16386
  tool_call_id: toolCallId,
16236
16387
  name: "task"
@@ -16259,10 +16410,10 @@ function getSubagents(options) {
16259
16410
  const generalPurposeMiddleware = [...defaultSubagentMiddleware, ...taskMiddleware];
16260
16411
  if (defaultInterruptOn) {
16261
16412
  generalPurposeMiddleware.push(
16262
- (0, import_langchain48.humanInTheLoopMiddleware)({ interruptOn: defaultInterruptOn })
16413
+ (0, import_langchain50.humanInTheLoopMiddleware)({ interruptOn: defaultInterruptOn })
16263
16414
  );
16264
16415
  }
16265
- const generalPurposeSubagent = (0, import_langchain48.createAgent)({
16416
+ const generalPurposeSubagent = (0, import_langchain50.createAgent)({
16266
16417
  model: defaultModel,
16267
16418
  systemPrompt: DEFAULT_SUBAGENT_PROMPT,
16268
16419
  tools: defaultTools,
@@ -16285,8 +16436,8 @@ function getSubagents(options) {
16285
16436
  const middleware = agentParams.middleware ? [...defaultSubagentMiddleware, ...taskMiddleware, ...agentParams.middleware] : [...defaultSubagentMiddleware, ...taskMiddleware];
16286
16437
  const interruptOn = agentParams.interruptOn || defaultInterruptOn;
16287
16438
  if (interruptOn)
16288
- middleware.push((0, import_langchain48.humanInTheLoopMiddleware)({ interruptOn }));
16289
- agents[agentParams.key] = (0, import_langchain48.createAgent)({
16439
+ middleware.push((0, import_langchain50.humanInTheLoopMiddleware)({ interruptOn }));
16440
+ agents[agentParams.key] = (0, import_langchain50.createAgent)({
16290
16441
  model: agentParams.model ?? defaultModel,
16291
16442
  systemPrompt: agentParams.systemPrompt,
16292
16443
  tools: agentParams.tools ?? defaultTools,
@@ -16336,7 +16487,7 @@ function createTaskTool(options) {
16336
16487
  generalPurposeAgent
16337
16488
  });
16338
16489
  const finalTaskDescription = taskDescription ? taskDescription : getTaskToolDescription(subagentDescriptions);
16339
- return (0, import_langchain48.tool)(
16490
+ return (0, import_langchain50.tool)(
16340
16491
  async (input, config) => {
16341
16492
  const { description, subagent_type, async } = input;
16342
16493
  let assistant_id = subagent_type;
@@ -16423,7 +16574,7 @@ You are executing a persistent task (ID: ${input.taskId}). Use manage_task.updat
16423
16574
  return new import_langgraph8.Command({
16424
16575
  update: {
16425
16576
  messages: [
16426
- new import_langchain48.ToolMessage({
16577
+ new import_langchain50.ToolMessage({
16427
16578
  content: `Async task started: ${subagent_thread_id}
16428
16579
  ${description}
16429
16580
  The result will be delivered as a notification when complete. Do not poll.`,
@@ -16457,7 +16608,7 @@ The result will be delivered as a notification when complete. Do not poll.`,
16457
16608
  return new import_langgraph8.Command({
16458
16609
  update: {
16459
16610
  messages: [
16460
- new import_langchain48.ToolMessage({
16611
+ new import_langchain50.ToolMessage({
16461
16612
  content: error instanceof Error ? error.message : "Task Failed to complete",
16462
16613
  tool_call_id: config.toolCall.id,
16463
16614
  name: "task"
@@ -16500,7 +16651,7 @@ function getMainAgentFromConfig(config) {
16500
16651
  });
16501
16652
  }
16502
16653
  function createCheckAsyncTaskTool() {
16503
- return (0, import_langchain48.tool)(
16654
+ return (0, import_langchain50.tool)(
16504
16655
  async (input, config) => {
16505
16656
  const { task_id } = input;
16506
16657
  const mainAgent = getMainAgentFromConfig(config);
@@ -16567,7 +16718,7 @@ Description: ${cached.description}`;
16567
16718
  );
16568
16719
  }
16569
16720
  function createListAsyncTasksTool() {
16570
- return (0, import_langchain48.tool)(
16721
+ return (0, import_langchain50.tool)(
16571
16722
  async (_input, config) => {
16572
16723
  const mainAgent = getMainAgentFromConfig(config);
16573
16724
  if (!mainAgent) {
@@ -16618,7 +16769,7 @@ function createListAsyncTasksTool() {
16618
16769
  );
16619
16770
  }
16620
16771
  function createCancelAsyncTaskTool() {
16621
- return (0, import_langchain48.tool)(
16772
+ return (0, import_langchain50.tool)(
16622
16773
  async (input, config) => {
16623
16774
  const { task_id } = input;
16624
16775
  const mainAgent = getMainAgentFromConfig(config);
@@ -16694,7 +16845,7 @@ function createSubAgentMiddleware(options) {
16694
16845
  );
16695
16846
  }
16696
16847
  const effectiveSystemPrompt = allowAsync ? systemPrompt + getAsyncPromptText() : systemPrompt;
16697
- return (0, import_langchain48.createMiddleware)({
16848
+ return (0, import_langchain50.createMiddleware)({
16698
16849
  name: "subAgentMiddleware",
16699
16850
  tools: allTools,
16700
16851
  wrapModelCall: async (request, handler) => {
@@ -16713,51 +16864,8 @@ ${effectiveSystemPrompt}` : effectiveSystemPrompt;
16713
16864
  });
16714
16865
  }
16715
16866
 
16716
- // src/deep_agent_new/middleware/patch_tool_calls.ts
16717
- var import_langchain49 = require("langchain");
16718
- function createPatchToolCallsMiddleware() {
16719
- return (0, import_langchain49.createMiddleware)({
16720
- name: "patchToolCallsMiddleware",
16721
- beforeAgent: async (state) => {
16722
- const messages = state.messages;
16723
- if (!messages || messages.length === 0) {
16724
- return;
16725
- }
16726
- const patchedMessages = [];
16727
- for (let i = 0; i < messages.length; i++) {
16728
- const msg = messages[i];
16729
- patchedMessages.push(msg);
16730
- if (import_langchain49.AIMessage.isInstance(msg) && msg.tool_calls != null) {
16731
- for (const toolCall of msg.tool_calls) {
16732
- const correspondingToolMsg = messages.slice(i).find(
16733
- (m) => import_langchain49.ToolMessage.isInstance(m) && m.tool_call_id === toolCall.id
16734
- );
16735
- if (!correspondingToolMsg) {
16736
- const toolMsg = `Tool call ${toolCall.name} with id ${toolCall.id} was cancelled - another message came in before it could be completed.`;
16737
- patchedMessages.push(
16738
- new import_langchain49.ToolMessage({
16739
- content: toolMsg,
16740
- name: toolCall.name,
16741
- tool_call_id: toolCall.id
16742
- })
16743
- );
16744
- }
16745
- }
16746
- }
16747
- }
16748
- if (patchedMessages.length === messages.length) {
16749
- return;
16750
- }
16751
- return {
16752
- messages: patchedMessages.slice(messages.length)
16753
- // only the new ToolMessage patches
16754
- };
16755
- }
16756
- });
16757
- }
16758
-
16759
16867
  // src/deep_agent_new/middleware/date.ts
16760
- var import_langchain50 = require("langchain");
16868
+ var import_langchain51 = require("langchain");
16761
16869
  var import_zod44 = require("zod");
16762
16870
  function formatCurrentDate(timezone = "UTC") {
16763
16871
  const now = /* @__PURE__ */ new Date();
@@ -16786,10 +16894,10 @@ function generateDateContext(timezone = "UTC") {
16786
16894
  function createDateMiddleware(options = {}) {
16787
16895
  const timezone = options.timezone || "UTC";
16788
16896
  const dateContext = generateDateContext(timezone);
16789
- return (0, import_langchain50.createMiddleware)({
16897
+ return (0, import_langchain51.createMiddleware)({
16790
16898
  name: "DateMiddleware",
16791
16899
  tools: [
16792
- (0, import_langchain50.tool)(
16900
+ (0, import_langchain51.tool)(
16793
16901
  async () => {
16794
16902
  const now = /* @__PURE__ */ new Date();
16795
16903
  let validTimezone = timezone;
@@ -16885,7 +16993,7 @@ var datePlugin = {
16885
16993
  };
16886
16994
 
16887
16995
  // src/deep_agent_new/middleware/scheduler.ts
16888
- var import_langchain51 = require("langchain");
16996
+ var import_langchain52 = require("langchain");
16889
16997
  var import_zod45 = require("zod");
16890
16998
  var import_uuid5 = require("uuid");
16891
16999
  var import_protocols8 = require("@axiom-lattice/protocols");
@@ -17954,10 +18062,10 @@ function registerAgentAddMessageHandler() {
17954
18062
  function createSchedulerMiddleware(options = {}) {
17955
18063
  const defaultMaxRetries = options.defaultMaxRetries ?? 0;
17956
18064
  registerAgentAddMessageHandler();
17957
- return (0, import_langchain51.createMiddleware)({
18065
+ return (0, import_langchain52.createMiddleware)({
17958
18066
  name: "SchedulerMiddleware",
17959
18067
  tools: [
17960
- (0, import_langchain51.tool)(
18068
+ (0, import_langchain52.tool)(
17961
18069
  async (input, config) => {
17962
18070
  const runConfig = getRunConfig2(config);
17963
18071
  const scheduleLattice = getScheduleLattice(SCHEDULE_LATTICE_KEY);
@@ -17992,7 +18100,7 @@ function createSchedulerMiddleware(options = {}) {
17992
18100
  })
17993
18101
  }
17994
18102
  ),
17995
- (0, import_langchain51.tool)(
18103
+ (0, import_langchain52.tool)(
17996
18104
  async (input, config) => {
17997
18105
  const runConfig = getRunConfig2(config);
17998
18106
  const scheduleLattice = getScheduleLattice(SCHEDULE_LATTICE_KEY);
@@ -18027,7 +18135,7 @@ function createSchedulerMiddleware(options = {}) {
18027
18135
  })
18028
18136
  }
18029
18137
  ),
18030
- (0, import_langchain51.tool)(
18138
+ (0, import_langchain52.tool)(
18031
18139
  async (input, config) => {
18032
18140
  const runConfig = getRunConfig2(config);
18033
18141
  const scheduleLattice = getScheduleLattice(SCHEDULE_LATTICE_KEY);
@@ -18071,7 +18179,7 @@ function createSchedulerMiddleware(options = {}) {
18071
18179
  })
18072
18180
  }
18073
18181
  ),
18074
- (0, import_langchain51.tool)(
18182
+ (0, import_langchain52.tool)(
18075
18183
  async (input) => {
18076
18184
  const scheduleLattice = getScheduleLattice(SCHEDULE_LATTICE_KEY);
18077
18185
  const success = await scheduleLattice.client.cancel(input.taskId);
@@ -18085,7 +18193,7 @@ function createSchedulerMiddleware(options = {}) {
18085
18193
  })
18086
18194
  }
18087
18195
  ),
18088
- (0, import_langchain51.tool)(
18196
+ (0, import_langchain52.tool)(
18089
18197
  async (input, config) => {
18090
18198
  const runConfig = getRunConfig2(config);
18091
18199
  const scheduleLattice = getScheduleLattice(SCHEDULE_LATTICE_KEY);
@@ -19355,7 +19463,7 @@ var MemoryBackend = class {
19355
19463
  // src/deep_agent_new/middleware/todos.ts
19356
19464
  var import_langgraph9 = require("@langchain/langgraph");
19357
19465
  var import_zod46 = require("zod");
19358
- var import_langchain52 = require("langchain");
19466
+ var import_langchain53 = require("langchain");
19359
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.
19360
19468
  It also helps the user understand the progress of the task and overall progress of their requests.
19361
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.
@@ -19589,13 +19697,13 @@ var TodoSchema = import_zod46.z.object({
19589
19697
  });
19590
19698
  var stateSchema = import_zod46.z.object({ todos: import_zod46.z.array(TodoSchema).default([]) });
19591
19699
  function todoListMiddleware(options) {
19592
- const writeTodos = (0, import_langchain52.tool)(
19700
+ const writeTodos = (0, import_langchain53.tool)(
19593
19701
  ({ todos }, config) => {
19594
19702
  return new import_langgraph9.Command({
19595
19703
  update: {
19596
19704
  todos,
19597
19705
  messages: [
19598
- new import_langchain52.ToolMessage({
19706
+ new import_langchain53.ToolMessage({
19599
19707
  content: genUIMarkdown("todo_list", todos),
19600
19708
  tool_call_id: config.toolCall?.id
19601
19709
  })
@@ -19611,7 +19719,7 @@ function todoListMiddleware(options) {
19611
19719
  })
19612
19720
  }
19613
19721
  );
19614
- return (0, import_langchain52.createMiddleware)({
19722
+ return (0, import_langchain53.createMiddleware)({
19615
19723
  name: "todoListMiddleware",
19616
19724
  stateSchema,
19617
19725
  tools: [writeTodos],
@@ -19662,42 +19770,26 @@ ${BASE_PROMPT}` : BASE_PROMPT;
19662
19770
  createFilesystemMiddleware({
19663
19771
  backend: filesystemBackend
19664
19772
  }),
19665
- // Subagent middleware: Automatic conversation summarization when token limits are approached
19666
- (0, import_langchain53.summarizationMiddleware)({
19667
- model,
19668
- trigger: { tokens: 17e4 },
19669
- keep: { messages: 6 }
19670
- }),
19671
19773
  // Subagent middleware: Anthropic prompt caching for improved performance
19672
- (0, import_langchain53.anthropicPromptCachingMiddleware)({
19774
+ (0, import_langchain54.anthropicPromptCachingMiddleware)({
19673
19775
  unsupportedModelBehavior: "ignore"
19674
19776
  }),
19675
- // Subagent middleware: Patches tool calls for compatibility
19676
- createPatchToolCallsMiddleware(),
19677
19777
  ...customMiddleware
19678
19778
  ],
19679
19779
  defaultInterruptOn: interruptOn,
19680
19780
  subagents,
19681
19781
  generalPurposeAgent: true
19682
19782
  }),
19683
- // Automatically summarizes conversation history when token limits are approached
19684
- (0, import_langchain53.summarizationMiddleware)({
19685
- model,
19686
- trigger: { tokens: 17e4 },
19687
- keep: { messages: 6 }
19688
- }),
19689
19783
  // Enables Anthropic prompt caching for improved performance and reduced costs
19690
- (0, import_langchain53.anthropicPromptCachingMiddleware)({
19784
+ (0, import_langchain54.anthropicPromptCachingMiddleware)({
19691
19785
  unsupportedModelBehavior: "ignore"
19692
- }),
19693
- // Patches tool calls to ensure compatibility across different model providers
19694
- createPatchToolCallsMiddleware()
19786
+ })
19695
19787
  ];
19696
19788
  if (interruptOn) {
19697
- middleware.push((0, import_langchain53.humanInTheLoopMiddleware)({ interruptOn }));
19789
+ middleware.push((0, import_langchain54.humanInTheLoopMiddleware)({ interruptOn }));
19698
19790
  }
19699
19791
  middleware.push(...customMiddleware);
19700
- return (0, import_langchain53.createAgent)({
19792
+ return (0, import_langchain54.createAgent)({
19701
19793
  model,
19702
19794
  systemPrompt: finalSystemPrompt,
19703
19795
  tools,
@@ -19747,7 +19839,7 @@ var DeepAgentGraphBuilder = class {
19747
19839
  }));
19748
19840
  const middlewareConfigs = params.middleware || [];
19749
19841
  const filesystemBackend = createFilesystemBackendFactory(middlewareConfigs);
19750
- const middlewares = await createCommonMiddlewares(middlewareConfigs, filesystemBackend, true, params.tenantId);
19842
+ const middlewares = await createCommonMiddlewares(middlewareConfigs, filesystemBackend, true, params.tenantId, params.model);
19751
19843
  const deepAgent = createDeepAgent({
19752
19844
  tools,
19753
19845
  model: params.model,
@@ -19769,7 +19861,7 @@ init_MemoryLatticeManager();
19769
19861
 
19770
19862
  // src/agent_team/agent_team.ts
19771
19863
  var import_v35 = require("zod/v3");
19772
- var import_langchain56 = require("langchain");
19864
+ var import_langchain57 = require("langchain");
19773
19865
 
19774
19866
  // src/agent_team/types.ts
19775
19867
  var TaskStatus = /* @__PURE__ */ ((TaskStatus3) => {
@@ -20205,13 +20297,13 @@ var InMemoryMailboxStore = class {
20205
20297
 
20206
20298
  // src/agent_team/middleware/team.ts
20207
20299
  var import_v34 = require("zod/v3");
20208
- var import_langchain55 = require("langchain");
20300
+ var import_langchain56 = require("langchain");
20209
20301
  var import_langgraph11 = require("@langchain/langgraph");
20210
20302
  var import_uuid6 = require("uuid");
20211
20303
 
20212
20304
  // src/agent_team/middleware/teammate_tools.ts
20213
20305
  var import_v33 = require("zod/v3");
20214
- var import_langchain54 = require("langchain");
20306
+ var import_langchain55 = require("langchain");
20215
20307
  var import_langgraph10 = require("@langchain/langgraph");
20216
20308
 
20217
20309
  // src/agent_team/middleware/formatMessages.ts
@@ -20236,7 +20328,7 @@ ${meta}${body}`;
20236
20328
  // src/agent_team/middleware/teammate_tools.ts
20237
20329
  function createTeammateTools(options) {
20238
20330
  const { teamId, agentId, taskListStore, mailboxStore } = options;
20239
- const claimTaskTool = (0, import_langchain54.tool)(
20331
+ const claimTaskTool = (0, import_langchain55.tool)(
20240
20332
  async (input) => {
20241
20333
  const task = await taskListStore.claimTaskById(
20242
20334
  teamId,
@@ -20266,7 +20358,7 @@ function createTeammateTools(options) {
20266
20358
  })
20267
20359
  }
20268
20360
  );
20269
- const completeTaskTool = (0, import_langchain54.tool)(
20361
+ const completeTaskTool = (0, import_langchain55.tool)(
20270
20362
  async (input) => {
20271
20363
  const task = await taskListStore.completeTask(
20272
20364
  teamId,
@@ -20293,7 +20385,7 @@ function createTeammateTools(options) {
20293
20385
  })
20294
20386
  }
20295
20387
  );
20296
- const failTaskTool = (0, import_langchain54.tool)(
20388
+ const failTaskTool = (0, import_langchain55.tool)(
20297
20389
  async (input) => {
20298
20390
  const task = await taskListStore.failTask(
20299
20391
  teamId,
@@ -20320,7 +20412,7 @@ function createTeammateTools(options) {
20320
20412
  })
20321
20413
  }
20322
20414
  );
20323
- const sendMessageTool = (0, import_langchain54.tool)(
20415
+ const sendMessageTool = (0, import_langchain55.tool)(
20324
20416
  async (input) => {
20325
20417
  await mailboxStore.sendMessage(
20326
20418
  teamId,
@@ -20358,7 +20450,7 @@ function createTeammateTools(options) {
20358
20450
  read: msg.read
20359
20451
  }));
20360
20452
  };
20361
- const readMessagesTool = (0, import_langchain54.tool)(
20453
+ const readMessagesTool = (0, import_langchain55.tool)(
20362
20454
  async (input, config) => {
20363
20455
  const formatAndMarkAsRead = async (msgs2) => {
20364
20456
  for (const msg of msgs2) {
@@ -20370,7 +20462,7 @@ function createTeammateTools(options) {
20370
20462
  if (msgs.length > 0) {
20371
20463
  const formatted2 = await formatAndMarkAsRead(msgs);
20372
20464
  const relevantMsgs2 = await getRelevantMessagesForState();
20373
- const toolMessage2 = new import_langchain54.ToolMessage({
20465
+ const toolMessage2 = new import_langchain55.ToolMessage({
20374
20466
  content: formatted2,
20375
20467
  tool_call_id: config.toolCall?.id,
20376
20468
  name: "read_messages"
@@ -20395,7 +20487,7 @@ function createTeammateTools(options) {
20395
20487
  });
20396
20488
  const relevantMsgs = await getRelevantMessagesForState();
20397
20489
  if (msgs.length === 0) {
20398
- const toolMessage2 = new import_langchain54.ToolMessage({
20490
+ const toolMessage2 = new import_langchain55.ToolMessage({
20399
20491
  content: "No unread messages.",
20400
20492
  tool_call_id: config.toolCall?.id,
20401
20493
  name: "read_messages"
@@ -20405,7 +20497,7 @@ function createTeammateTools(options) {
20405
20497
  });
20406
20498
  }
20407
20499
  const formatted = await formatAndMarkAsRead(msgs);
20408
- const toolMessage = new import_langchain54.ToolMessage({
20500
+ const toolMessage = new import_langchain55.ToolMessage({
20409
20501
  content: formatted,
20410
20502
  tool_call_id: config.toolCall?.id,
20411
20503
  name: "read_messages"
@@ -20420,7 +20512,7 @@ function createTeammateTools(options) {
20420
20512
  schema: import_v33.z.object({})
20421
20513
  }
20422
20514
  );
20423
- const checkTasksTool = (0, import_langchain54.tool)(
20515
+ const checkTasksTool = (0, import_langchain55.tool)(
20424
20516
  async () => {
20425
20517
  const tasks = await taskListStore.getAllTasks(teamId);
20426
20518
  return formatTaskSummary(tasks);
@@ -20431,7 +20523,7 @@ function createTeammateTools(options) {
20431
20523
  schema: import_v33.z.object({})
20432
20524
  }
20433
20525
  );
20434
- const broadcastMessageTool = (0, import_langchain54.tool)(
20526
+ const broadcastMessageTool = (0, import_langchain55.tool)(
20435
20527
  async (input) => {
20436
20528
  const allAgents = await mailboxStore.getRegisteredAgents(teamId);
20437
20529
  const recipients = allAgents.filter((a) => a !== agentId);
@@ -20617,7 +20709,7 @@ You have access to these tools:
20617
20709
  - \`read_messages\`: Read messages from team_lead or teammates
20618
20710
  - \`check_tasks\`: Get current status of all tasks in the team`;
20619
20711
  const assistantId = getTeammateAssistantId(ctx.teamId, spec.name);
20620
- agent = (0, import_langchain55.createAgent)({
20712
+ agent = (0, import_langchain56.createAgent)({
20621
20713
  model: spec.model ?? ctx.defaultModel,
20622
20714
  systemPrompt: teammatePrompt,
20623
20715
  tools: allTools,
@@ -20686,12 +20778,12 @@ async function spawnTeammate(options) {
20686
20778
  function createTeamMiddleware(options) {
20687
20779
  const { teamConfig, taskListStore, mailboxStore, tenantId: tenantId2 } = options;
20688
20780
  const defaultModel = teamConfig.model ?? "claude-sonnet-4-5-20250929";
20689
- const createTeamTool = (0, import_langchain55.tool)(
20781
+ const createTeamTool = (0, import_langchain56.tool)(
20690
20782
  async (input, config) => {
20691
20783
  const state = (0, import_langgraph11.getCurrentTaskInput)();
20692
20784
  if (state?.team?.teamId) {
20693
20785
  const existingId = state.team.teamId;
20694
- const msg = new import_langchain55.ToolMessage({
20786
+ const msg = new import_langchain56.ToolMessage({
20695
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.`,
20696
20788
  tool_call_id: config.toolCall?.id,
20697
20789
  name: "create_team"
@@ -20780,7 +20872,7 @@ Teammates are now working in the background. Keep calling \`check_tasks\` and \`
20780
20872
  \`\`\`json
20781
20873
  ${teamJson}
20782
20874
  \`\`\``;
20783
- const toolMessage = new import_langchain55.ToolMessage({
20875
+ const toolMessage = new import_langchain56.ToolMessage({
20784
20876
  content: summary,
20785
20877
  tool_call_id: config.toolCall?.id,
20786
20878
  name: "create_team"
@@ -20865,7 +20957,7 @@ After calling create_team, you MUST:
20865
20957
  if (state?.team?.teamId) return state.team.teamId;
20866
20958
  throw new Error("No team_id provided and no team in state. Call create_team first.");
20867
20959
  };
20868
- const addTasksTool = (0, import_langchain55.tool)(
20960
+ const addTasksTool = (0, import_langchain56.tool)(
20869
20961
  async (input, config) => {
20870
20962
  const teamId = resolveTeamId();
20871
20963
  const created = await taskListStore.addTasks(
@@ -20879,7 +20971,7 @@ After calling create_team, you MUST:
20879
20971
  }))
20880
20972
  );
20881
20973
  const summary = created.map((t) => `- ${t.id}: "${t.title}"`).join("\n");
20882
- return new import_langchain55.ToolMessage({
20974
+ return new import_langchain56.ToolMessage({
20883
20975
  content: `Added ${created.length} task(s) to team ${teamId}:
20884
20976
  ${summary}
20885
20977
  Sleeping teammates will wake up and claim these.`,
@@ -20930,20 +21022,20 @@ IMPORTANT: Assigning to a specific teammate
20930
21022
  })
20931
21023
  }
20932
21024
  );
20933
- const assignTaskTool = (0, import_langchain55.tool)(
21025
+ const assignTaskTool = (0, import_langchain56.tool)(
20934
21026
  async (input, config) => {
20935
21027
  const teamId = resolveTeamId();
20936
21028
  const task = await taskListStore.updateTask(teamId, input.task_id, {
20937
21029
  assignee: input.assignee
20938
21030
  });
20939
21031
  if (!task) {
20940
- return new import_langchain55.ToolMessage({
21032
+ return new import_langchain56.ToolMessage({
20941
21033
  content: `Task ${input.task_id} not found in team ${teamId}.`,
20942
21034
  tool_call_id: config.toolCall?.id,
20943
21035
  name: "assign_task"
20944
21036
  });
20945
21037
  }
20946
- return new import_langchain55.ToolMessage({
21038
+ return new import_langchain56.ToolMessage({
20947
21039
  content: `Task "${task.title}" (${task.id}) assigned to ${input.assignee}.`,
20948
21040
  tool_call_id: config.toolCall?.id,
20949
21041
  name: "assign_task"
@@ -20958,20 +21050,20 @@ IMPORTANT: Assigning to a specific teammate
20958
21050
  })
20959
21051
  }
20960
21052
  );
20961
- const setTaskStatusTool = (0, import_langchain55.tool)(
21053
+ const setTaskStatusTool = (0, import_langchain56.tool)(
20962
21054
  async (input, config) => {
20963
21055
  const teamId = resolveTeamId();
20964
21056
  const task = await taskListStore.updateTask(teamId, input.task_id, {
20965
21057
  status: input.status
20966
21058
  });
20967
21059
  if (!task) {
20968
- return new import_langchain55.ToolMessage({
21060
+ return new import_langchain56.ToolMessage({
20969
21061
  content: `Task ${input.task_id} not found in team ${teamId}.`,
20970
21062
  tool_call_id: config.toolCall?.id,
20971
21063
  name: "set_task_status"
20972
21064
  });
20973
21065
  }
20974
- return new import_langchain55.ToolMessage({
21066
+ return new import_langchain56.ToolMessage({
20975
21067
  content: `Task "${task.title}" (${task.id}) status set to ${input.status}.`,
20976
21068
  tool_call_id: config.toolCall?.id,
20977
21069
  name: "set_task_status"
@@ -20986,20 +21078,20 @@ IMPORTANT: Assigning to a specific teammate
20986
21078
  })
20987
21079
  }
20988
21080
  );
20989
- const setTaskDependenciesTool = (0, import_langchain55.tool)(
21081
+ const setTaskDependenciesTool = (0, import_langchain56.tool)(
20990
21082
  async (input, config) => {
20991
21083
  const teamId = resolveTeamId();
20992
21084
  const task = await taskListStore.updateTask(teamId, input.task_id, {
20993
21085
  dependencies: input.dependencies
20994
21086
  });
20995
21087
  if (!task) {
20996
- return new import_langchain55.ToolMessage({
21088
+ return new import_langchain56.ToolMessage({
20997
21089
  content: `Task ${input.task_id} not found in team ${teamId}.`,
20998
21090
  tool_call_id: config.toolCall?.id,
20999
21091
  name: "set_task_dependencies"
21000
21092
  });
21001
21093
  }
21002
- return new import_langchain55.ToolMessage({
21094
+ return new import_langchain56.ToolMessage({
21003
21095
  content: `Task "${task.title}" (${task.id}) dependencies set to [${input.dependencies.join(", ")}].`,
21004
21096
  tool_call_id: config.toolCall?.id,
21005
21097
  name: "set_task_dependencies"
@@ -21014,7 +21106,7 @@ IMPORTANT: Assigning to a specific teammate
21014
21106
  })
21015
21107
  }
21016
21108
  );
21017
- const checkTasksTool = (0, import_langchain55.tool)(
21109
+ const checkTasksTool = (0, import_langchain56.tool)(
21018
21110
  async (input, config) => {
21019
21111
  const teamId = resolveTeamId();
21020
21112
  const tasks = await taskListStore.getAllTasks(teamId);
@@ -21023,7 +21115,7 @@ IMPORTANT: Assigning to a specific teammate
21023
21115
  update: {
21024
21116
  tasks: tasksSnapshot,
21025
21117
  messages: [
21026
- new import_langchain55.ToolMessage({
21118
+ new import_langchain56.ToolMessage({
21027
21119
  content: formatTaskSummary(tasks),
21028
21120
  tool_call_id: config.toolCall?.id,
21029
21121
  name: "check_tasks"
@@ -21059,7 +21151,7 @@ Task Status Values:
21059
21151
  })
21060
21152
  }
21061
21153
  );
21062
- const sendMessageTool = (0, import_langchain55.tool)(
21154
+ const sendMessageTool = (0, import_langchain56.tool)(
21063
21155
  async (input, config) => {
21064
21156
  const teamId = resolveTeamId();
21065
21157
  await mailboxStore.sendMessage(
@@ -21069,7 +21161,7 @@ Task Status Values:
21069
21161
  input.content,
21070
21162
  "direct_message" /* DIRECT_MESSAGE */
21071
21163
  );
21072
- return new import_langchain55.ToolMessage({
21164
+ return new import_langchain56.ToolMessage({
21073
21165
  content: `Message sent to ${input.to}.`,
21074
21166
  tool_call_id: config.toolCall?.id,
21075
21167
  name: "send_message"
@@ -21084,7 +21176,7 @@ Task Status Values:
21084
21176
  })
21085
21177
  }
21086
21178
  );
21087
- const readMessagesTool = (0, import_langchain55.tool)(
21179
+ const readMessagesTool = (0, import_langchain56.tool)(
21088
21180
  async (input, config) => {
21089
21181
  const teamId = resolveTeamId();
21090
21182
  const formatAndMarkAsRead = async (msgs2) => {
@@ -21112,7 +21204,7 @@ Task Status Values:
21112
21204
  if (msgs.length > 0) {
21113
21205
  const formatted2 = await formatAndMarkAsRead(msgs);
21114
21206
  const allTeamMessages2 = await getAllTeamMessagesForState();
21115
- const toolMessage2 = new import_langchain55.ToolMessage({
21207
+ const toolMessage2 = new import_langchain56.ToolMessage({
21116
21208
  content: formatted2,
21117
21209
  tool_call_id: config.toolCall?.id,
21118
21210
  name: "read_messages"
@@ -21144,7 +21236,7 @@ Task Status Values:
21144
21236
  );
21145
21237
  const allTeamMessages = await getAllTeamMessagesForState();
21146
21238
  if (msgs.length === 0) {
21147
- const toolMessage2 = new import_langchain55.ToolMessage({
21239
+ const toolMessage2 = new import_langchain56.ToolMessage({
21148
21240
  content: "No unread messages from teammates.",
21149
21241
  tool_call_id: config.toolCall?.id,
21150
21242
  name: "read_messages"
@@ -21154,7 +21246,7 @@ Task Status Values:
21154
21246
  });
21155
21247
  }
21156
21248
  const formatted = await formatAndMarkAsRead(msgs);
21157
- const toolMessage = new import_langchain55.ToolMessage({
21249
+ const toolMessage = new import_langchain56.ToolMessage({
21158
21250
  content: formatted,
21159
21251
  tool_call_id: config.toolCall?.id,
21160
21252
  name: "read_messages"
@@ -21171,7 +21263,7 @@ Task Status Values:
21171
21263
  })
21172
21264
  }
21173
21265
  );
21174
- const disbandTeamTool = (0, import_langchain55.tool)(
21266
+ const disbandTeamTool = (0, import_langchain56.tool)(
21175
21267
  async (input, config) => {
21176
21268
  const teamId = resolveTeamId();
21177
21269
  await mailboxStore.broadcastMessage(
@@ -21181,7 +21273,7 @@ Task Status Values:
21181
21273
  "shutdown_request" /* SHUTDOWN_REQUEST */
21182
21274
  );
21183
21275
  await new Promise((r) => setTimeout(r, 2e3));
21184
- return new import_langchain55.ToolMessage({
21276
+ return new import_langchain56.ToolMessage({
21185
21277
  content: `Team ${teamId} has been disbanded. All teammates notified and resources cleaned up.`,
21186
21278
  tool_call_id: config.toolCall?.id,
21187
21279
  name: "disband_team"
@@ -21192,7 +21284,7 @@ Task Status Values:
21192
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."
21193
21285
  }
21194
21286
  );
21195
- const broadcastMessageTool = (0, import_langchain55.tool)(
21287
+ const broadcastMessageTool = (0, import_langchain56.tool)(
21196
21288
  async (input, config) => {
21197
21289
  const teamId = resolveTeamId();
21198
21290
  await mailboxStore.broadcastMessage(
@@ -21201,7 +21293,7 @@ Task Status Values:
21201
21293
  input.content,
21202
21294
  "broadcast" /* BROADCAST */
21203
21295
  );
21204
- return new import_langchain55.ToolMessage({
21296
+ return new import_langchain56.ToolMessage({
21205
21297
  content: `Broadcast message sent to all teammates.`,
21206
21298
  tool_call_id: config.toolCall?.id,
21207
21299
  name: "broadcast_message"
@@ -21215,7 +21307,7 @@ Task Status Values:
21215
21307
  })
21216
21308
  }
21217
21309
  );
21218
- return (0, import_langchain55.createMiddleware)({
21310
+ return (0, import_langchain56.createMiddleware)({
21219
21311
  name: "teamMiddleware",
21220
21312
  tools: [
21221
21313
  createTeamTool,
@@ -21324,7 +21416,7 @@ function createAgentTeam(config) {
21324
21416
  ];
21325
21417
  const systemPrompt = config.systemPrompt + "\n\n" + TEAM_LEAD_BASE_PROMPT;
21326
21418
  const stateSchema2 = createReactAgentSchema(TEAM_STATE_SCHEMA);
21327
- return (0, import_langchain56.createAgent)({
21419
+ return (0, import_langchain57.createAgent)({
21328
21420
  model: config.model ?? "claude-sonnet-4-5-20250929",
21329
21421
  systemPrompt,
21330
21422
  tools: [],
@@ -21367,7 +21459,7 @@ var TeamAgentGraphBuilder = class {
21367
21459
  });
21368
21460
  const middlewareConfigs = params.middleware || [];
21369
21461
  let filesystemBackend = createFilesystemBackendFactory(middlewareConfigs);
21370
- const middlewares = await createCommonMiddlewares(middlewareConfigs);
21462
+ const middlewares = await createCommonMiddlewares(middlewareConfigs, void 0, void 0, void 0, params.model);
21371
21463
  if (!filesystemBackend) {
21372
21464
  filesystemBackend = async (config2) => {
21373
21465
  return new StateBackend(config2);
@@ -21736,7 +21828,7 @@ function extractLastHumanMessage(messages) {
21736
21828
  }
21737
21829
 
21738
21830
  // src/agent_lattice/builders/WorkflowAgentGraphBuilder.ts
21739
- var import_langchain57 = require("langchain");
21831
+ var import_langchain58 = require("langchain");
21740
21832
  init_MemoryLatticeManager();
21741
21833
  var import_protocols10 = require("@axiom-lattice/protocols");
21742
21834
  init_compile();
@@ -21787,7 +21879,7 @@ var WorkflowAgentGraphBuilder = class {
21787
21879
  const checkpointer = getCheckpointSaver("default");
21788
21880
  const tools = params.tools.map((t) => t.executor).filter(Boolean);
21789
21881
  const middlewareConfigs = params.middleware || [];
21790
- const middlewares = await createCommonMiddlewares(middlewareConfigs, void 0, false, params.tenantId);
21882
+ const middlewares = await createCommonMiddlewares(middlewareConfigs, void 0, false, params.tenantId, params.model);
21791
21883
  const askMiddlewares = await createCommonMiddlewares([
21792
21884
  {
21793
21885
  id: "ask_user_to_clarify",
@@ -21797,11 +21889,11 @@ var WorkflowAgentGraphBuilder = class {
21797
21889
  enabled: true,
21798
21890
  config: {}
21799
21891
  }
21800
- ], void 0, false);
21892
+ ], void 0, false, void 0, params.model);
21801
21893
  const noWrapMiddlewares = stripWrapModelCallHook(middlewares);
21802
21894
  const noWrapAskMiddlewares = stripWrapModelCallHook(askMiddlewares);
21803
21895
  console.log(`[WF BUILDER] building default agent | toolCount=${tools.length} | middlewareCount=${middlewares.length}`);
21804
- const defaultAgent = (0, import_langchain57.createAgent)({
21896
+ const defaultAgent = (0, import_langchain58.createAgent)({
21805
21897
  model: params.model,
21806
21898
  tools,
21807
21899
  systemPrompt: buildStepSystemPrompt(false, params.prompt),
@@ -21821,7 +21913,7 @@ var WorkflowAgentGraphBuilder = class {
21821
21913
  console.log(`[WF BUILDER] resolveAgent: cacheKey=${key4.slice(0, 80)}... | cached=${agentCache.has(key4)}`);
21822
21914
  if (!agentCache.has(key4)) {
21823
21915
  console.log(`[WF BUILDER] creating ${isAsk ? "ask" : "agent"} with responseFormat`);
21824
- const agent = (0, import_langchain57.createAgent)({
21916
+ const agent = (0, import_langchain58.createAgent)({
21825
21917
  model: params.model,
21826
21918
  tools,
21827
21919
  systemPrompt: buildStepSystemPrompt(isAsk, params.prompt),
@@ -21837,7 +21929,7 @@ var WorkflowAgentGraphBuilder = class {
21837
21929
  const key4 = "ask:default";
21838
21930
  if (!agentCache.has(key4)) {
21839
21931
  console.log(`[WF BUILDER] creating ask default agent`);
21840
- const agent = (0, import_langchain57.createAgent)({
21932
+ const agent = (0, import_langchain58.createAgent)({
21841
21933
  model: params.model,
21842
21934
  tools,
21843
21935
  systemPrompt: buildStepSystemPrompt(true, params.prompt),
@@ -23476,6 +23568,14 @@ Call the \`skill\` tool with skill_name: "agent-architecture" to load the
23476
23568
  authoritative workflow. Never announce that you will follow a skill \u2014
23477
23569
  load it and follow its content. If the load fails, retry once, then report it.
23478
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
+
23479
23579
  Your sub-skills (accessible via the MOC or direct loading):
23480
23580
  - [[learn-capability]] \u2014 Learn from any source material \u2192 skills + agents
23481
23581
  - [[agent-build]] \u2014 Design and build single agents (REACT/DEEP_AGENT)
@@ -23640,7 +23740,15 @@ var agentArchitectConfig = {
23640
23740
  id: "task",
23641
23741
  type: "task",
23642
23742
  name: "Task",
23643
- 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).",
23644
23752
  enabled: true,
23645
23753
  config: {}
23646
23754
  },
@@ -27267,6 +27375,15 @@ function parseJudgeVerdict(raw) {
27267
27375
  return { error: error instanceof Error ? error.message : String(error) };
27268
27376
  }
27269
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
+ }
27270
27387
  var _LatticeEval = class _LatticeEval {
27271
27388
  constructor(config = {}) {
27272
27389
  this.inMemoryLogs = [];
@@ -27333,7 +27450,8 @@ var _LatticeEval = class _LatticeEval {
27333
27450
  return acc;
27334
27451
  }, {});
27335
27452
  }
27336
- async executeAgentStep(step, threadId, inputMessage, files) {
27453
+ async executeAgentStep(step, threadId, inputMessage, files, interruptPolicy) {
27454
+ const hitlEvents = [];
27337
27455
  this.log("Executing agent step", {
27338
27456
  agent_id: step.agent_id,
27339
27457
  thread_id: threadId,
@@ -27351,19 +27469,74 @@ var _LatticeEval = class _LatticeEval {
27351
27469
  };
27352
27470
  const agent = agentInstanceManager.getAgent(agentParams);
27353
27471
  try {
27354
- const result = await agent.invoke({
27355
- input: {
27356
- message: step.override_message || inputMessage,
27357
- 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;
27358
27487
  }
27359
- });
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
+ }
27360
27532
  const responseData = { success: true, ...result };
27361
- this.log("Agent step completed", {
27362
- agent_id: step.agent_id,
27363
- thread_id: threadId,
27364
- response_keys: result ? Object.keys(result) : []
27365
- });
27366
- return { threadId, responseData };
27533
+ return {
27534
+ threadId,
27535
+ responseData,
27536
+ interrupted: pendingInterrupt ? true : void 0,
27537
+ interrupt: pendingInterrupt,
27538
+ hitlEvents
27539
+ };
27367
27540
  } catch (error) {
27368
27541
  const message = error instanceof Error ? error.message : String(error);
27369
27542
  this.log("Agent step failed", {
@@ -27426,15 +27599,32 @@ var _LatticeEval = class _LatticeEval {
27426
27599
  });
27427
27600
  let currentThreadId = threadId;
27428
27601
  let lastResponseData = null;
27602
+ let interrupt5;
27429
27603
  for (const step of evalCase.steps) {
27430
27604
  const result = await this.executeAgentStep(
27431
27605
  step,
27432
27606
  currentThreadId,
27433
27607
  evalCase.input.message,
27434
- evalCase.input.files || {}
27608
+ evalCase.input.files || {},
27609
+ evalCase.interruptPolicy
27435
27610
  );
27436
27611
  currentThreadId = result.threadId;
27437
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
+ }
27438
27628
  const existingIds = new Set(this.lastMessages.map((m) => m.id).filter(Boolean));
27439
27629
  if (result.responseData?.messages && Array.isArray(result.responseData.messages)) {
27440
27630
  for (const msg of result.responseData.messages) {
@@ -27456,6 +27646,13 @@ var _LatticeEval = class _LatticeEval {
27456
27646
  } else {
27457
27647
  content = String(msg.content || "");
27458
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
+ }
27459
27656
  this.lastMessages.push({
27460
27657
  role,
27461
27658
  content,
@@ -27467,13 +27664,21 @@ var _LatticeEval = class _LatticeEval {
27467
27664
  }
27468
27665
  }
27469
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
+ }
27470
27675
  }
27471
27676
  this.log("All agent steps completed", {
27472
27677
  case_id: evalCase.caseId,
27473
27678
  final_thread_id: currentThreadId,
27474
27679
  message_count: this.lastMessages.length
27475
27680
  });
27476
- const finalOutput = this.extractFinalMessage(lastResponseData);
27681
+ const finalOutput = interrupt5 ? typeof interrupt5.value === "string" ? interrupt5.value : JSON.stringify(interrupt5.value ?? "") : this.extractFinalMessage(lastResponseData);
27477
27682
  this.lastFinalOutput = finalOutput;
27478
27683
  const trajectory = this.buildTrajectory();
27479
27684
  this.log("Final output extracted", {
@@ -27532,6 +27737,8 @@ ${rubricsSection}
27532
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
27533
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
27534
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
27535
27742
 
27536
27743
  # \u8F93\u51FA\u683C\u5F0F\uFF08\u4EC5JSON\uFF09
27537
27744
  \u4F60\u5FC5\u987B\u4EC5\u4EE5 JSON \u683C\u5F0F\u56DE\u590D\uFF0C\u7ED3\u6784\u5982\u4E0B\uFF1A
@@ -27686,7 +27893,9 @@ ${rubricsSection}
27686
27893
  pass,
27687
27894
  final_score: finalScore,
27688
27895
  dimension_results: dimensionResults,
27689
- 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
27690
27899
  };
27691
27900
  }
27692
27901
  };
@@ -27701,6 +27910,8 @@ async function evaluateLatticeCaseWithLogs(evalCase, config) {
27701
27910
  return {
27702
27911
  caseId: evalCase.caseId,
27703
27912
  result,
27913
+ interrupted: result?.interrupted,
27914
+ interrupt: result?.interrupt,
27704
27915
  duration_ms: meta.duration_ms,
27705
27916
  thread_id: meta.thread_id,
27706
27917
  judge_thread_id: meta.judge_thread_id,
@@ -27783,7 +27994,8 @@ function resolveTemplateCase(templateCase, templates) {
27783
27994
  eval: {
27784
27995
  content_assertion: templateCase.eval.content_assertion,
27785
27996
  eval_rubrics: templateCase.eval.eval_rubrics || template.default_case.eval?.eval_rubrics
27786
- }
27997
+ },
27998
+ interruptPolicy: templateCase.interruptPolicy ?? template.default_case.interruptPolicy
27787
27999
  };
27788
28000
  return resolvedCase;
27789
28001
  }
@@ -27849,6 +28061,8 @@ var LatticeEvalSuite = class {
27849
28061
  result: run.result,
27850
28062
  error: run.error,
27851
28063
  error_stack: run.error_stack,
28064
+ interrupted: run.interrupted,
28065
+ interrupt: run.interrupt,
27852
28066
  duration_ms: run.duration_ms,
27853
28067
  thread_id: run.thread_id,
27854
28068
  judge_thread_id: run.judge_thread_id,
@@ -27881,6 +28095,8 @@ var LatticeEvalSuite = class {
27881
28095
  result: run.result,
27882
28096
  error: run.error,
27883
28097
  error_stack: run.error_stack,
28098
+ interrupted: run.interrupted,
28099
+ interrupt: run.interrupt,
27884
28100
  duration_ms: run.duration_ms,
27885
28101
  thread_id: run.thread_id,
27886
28102
  judge_thread_id: run.judge_thread_id,
@@ -28090,24 +28306,29 @@ Running batch: ${this.project.projectName} (${this.getSuiteNames().length} suite
28090
28306
  let total_cases = 0;
28091
28307
  let passed_cases = 0;
28092
28308
  let failed_cases = 0;
28309
+ let interrupted_cases = 0;
28093
28310
  const suites = [];
28094
28311
  for (const [suiteName, caseResults] of results.entries()) {
28095
28312
  const suiteTotal = caseResults.length;
28096
28313
  const suitePassed = caseResults.filter((r) => r.result?.pass).length;
28314
+ const suiteInterrupted = caseResults.filter((r) => r.interrupted).length;
28097
28315
  const suiteFailed = suiteTotal - suitePassed;
28098
28316
  total_cases += suiteTotal;
28099
28317
  passed_cases += suitePassed;
28100
28318
  failed_cases += suiteFailed;
28319
+ interrupted_cases += suiteInterrupted;
28101
28320
  suites.push({
28102
28321
  suiteName,
28103
28322
  total_cases: suiteTotal,
28104
28323
  passed_cases: suitePassed,
28105
28324
  failed_cases: suiteFailed,
28325
+ interrupted_cases: suiteInterrupted,
28106
28326
  cases: caseResults.map((r) => ({
28107
28327
  caseId: r.caseId,
28108
28328
  pass: r.result?.pass,
28109
28329
  final_score: r.result?.final_score,
28110
- error: r.error
28330
+ error: r.error,
28331
+ interrupted: r.interrupted
28111
28332
  }))
28112
28333
  });
28113
28334
  }
@@ -28125,13 +28346,14 @@ Running batch: ${this.project.projectName} (${this.getSuiteNames().length} suite
28125
28346
  total_cases,
28126
28347
  passed_cases,
28127
28348
  failed_cases,
28349
+ interrupted_cases,
28128
28350
  pass_rate: total_cases > 0 ? passed_cases / total_cases : 0
28129
28351
  },
28130
28352
  suites
28131
28353
  };
28132
28354
  console.log(`
28133
28355
  === Summary ===`);
28134
- 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)}%`);
28135
28357
  return { batch_id, results, report };
28136
28358
  }
28137
28359
  };
@@ -28216,11 +28438,11 @@ function clearEncryptionKeyCache() {
28216
28438
  }
28217
28439
 
28218
28440
  // src/middlewares/skillMiddleware.ts
28219
- var import_langchain61 = require("langchain");
28441
+ var import_langchain62 = require("langchain");
28220
28442
 
28221
28443
  // src/tool_lattice/skill/load_skills.ts
28222
28444
  var import_zod48 = __toESM(require("zod"));
28223
- var import_langchain58 = require("langchain");
28445
+ var import_langchain59 = require("langchain");
28224
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.`;
28225
28447
  function getSandboxFromExeConfig(_exe_config) {
28226
28448
  const runConfig = _exe_config?.configurable?.runConfig || {};
@@ -28235,7 +28457,7 @@ function getSandboxFromExeConfig(_exe_config) {
28235
28457
  });
28236
28458
  }
28237
28459
  var createLoadSkillsTool = ({ skills } = {}) => {
28238
- return (0, import_langchain58.tool)(
28460
+ return (0, import_langchain59.tool)(
28239
28461
  async (_input, _exe_config) => {
28240
28462
  try {
28241
28463
  const sandbox = await getSandboxFromExeConfig(_exe_config);
@@ -28276,7 +28498,7 @@ var createLoadSkillsTool = ({ skills } = {}) => {
28276
28498
 
28277
28499
  // src/tool_lattice/skill/load_skill_content.ts
28278
28500
  var import_zod49 = __toESM(require("zod"));
28279
- var import_langchain59 = require("langchain");
28501
+ var import_langchain60 = require("langchain");
28280
28502
  var LOAD_SKILL_CONTENT_DESCRIPTION = `
28281
28503
  Execute a skill within the main conversation
28282
28504
 
@@ -28314,7 +28536,7 @@ function getSandboxFromExeConfig2(_exe_config) {
28314
28536
  });
28315
28537
  }
28316
28538
  var createLoadSkillContentTool = (pluginSkillContents) => {
28317
- return (0, import_langchain59.tool)(
28539
+ return (0, import_langchain60.tool)(
28318
28540
  async (input, _exe_config) => {
28319
28541
  try {
28320
28542
  if (pluginSkillContents?.[input.skill_name]) {
@@ -28372,7 +28594,7 @@ var createLoadSkillContentTool = (pluginSkillContents) => {
28372
28594
 
28373
28595
  // src/tool_lattice/skill/delete_skill.ts
28374
28596
  var import_zod50 = __toESM(require("zod"));
28375
- var import_langchain60 = require("langchain");
28597
+ var import_langchain61 = require("langchain");
28376
28598
  var DELETE_SKILL_DESCRIPTION = `
28377
28599
  Delete a skill by name from the skill system.
28378
28600
  This permanently removes the skill and its SKILL.md file.
@@ -28399,7 +28621,7 @@ function validateSkillName2(name) {
28399
28621
  }
28400
28622
  }
28401
28623
  var createDeleteSkillTool = () => {
28402
- return (0, import_langchain60.tool)(
28624
+ return (0, import_langchain61.tool)(
28403
28625
  async (input, _exe_config) => {
28404
28626
  try {
28405
28627
  validateSkillName2(input.skill_name);
@@ -28441,7 +28663,7 @@ function createSkillMiddleware(params = {}) {
28441
28663
  } = params;
28442
28664
  const skills = params.skills;
28443
28665
  let latestSkills = [];
28444
- return (0, import_langchain61.createMiddleware)({
28666
+ return (0, import_langchain62.createMiddleware)({
28445
28667
  name: "skillMiddleware",
28446
28668
  contextSchema,
28447
28669
  tools: [
@@ -28576,17 +28798,17 @@ var skillPlugin = {
28576
28798
  };
28577
28799
 
28578
28800
  // src/middlewares/collectionMiddleware.ts
28579
- var import_langchain72 = require("langchain");
28801
+ var import_langchain73 = require("langchain");
28580
28802
 
28581
28803
  // src/tool_lattice/collection/list_collections.ts
28582
28804
  var import_zod51 = __toESM(require("zod"));
28583
- var import_langchain62 = require("langchain");
28805
+ var import_langchain63 = require("langchain");
28584
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.`;
28585
28807
  var createListCollectionsTool = ({
28586
28808
  collectionKeys,
28587
28809
  connectAll
28588
28810
  }) => {
28589
- return (0, import_langchain62.tool)(
28811
+ return (0, import_langchain63.tool)(
28590
28812
  async (_input, _exeConfig) => {
28591
28813
  try {
28592
28814
  const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
@@ -28627,7 +28849,7 @@ var createListCollectionsTool = ({
28627
28849
 
28628
28850
  // src/tool_lattice/collection/search_collection.ts
28629
28851
  var import_zod52 = __toESM(require("zod"));
28630
- var import_langchain63 = require("langchain");
28852
+ var import_langchain64 = require("langchain");
28631
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.`;
28632
28854
  var searchSchema = import_zod52.default.object({
28633
28855
  collection: import_zod52.default.string().describe("The collection name to search in"),
@@ -28636,7 +28858,7 @@ var searchSchema = import_zod52.default.object({
28636
28858
  top_k: import_zod52.default.number().optional().default(5).describe("Number of results to return")
28637
28859
  });
28638
28860
  var createSearchCollectionTool = () => {
28639
- return (0, import_langchain63.tool)(
28861
+ return (0, import_langchain64.tool)(
28640
28862
  async (input, _exeConfig) => {
28641
28863
  try {
28642
28864
  const { collection, query, filter: filter2, top_k } = input;
@@ -28687,9 +28909,9 @@ var createSearchCollectionTool = () => {
28687
28909
 
28688
28910
  // src/tool_lattice/collection/get_collection.ts
28689
28911
  var import_zod53 = __toESM(require("zod"));
28690
- var import_langchain64 = require("langchain");
28912
+ var import_langchain65 = require("langchain");
28691
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.`;
28692
- var createGetCollectionTool = () => (0, import_langchain64.tool)(
28914
+ var createGetCollectionTool = () => (0, import_langchain65.tool)(
28693
28915
  async (input, _exeConfig) => {
28694
28916
  try {
28695
28917
  const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
@@ -28717,7 +28939,7 @@ Embedding: ${c.embeddingKey}${fieldsDesc}`;
28717
28939
 
28718
28940
  // src/tool_lattice/collection/create_collection.ts
28719
28941
  var import_zod54 = __toESM(require("zod"));
28720
- var import_langchain65 = require("langchain");
28942
+ var import_langchain66 = require("langchain");
28721
28943
  var createSchema = import_zod54.default.object({
28722
28944
  name: import_zod54.default.string().describe("Collection name (lowercase, underscores only)"),
28723
28945
  label: import_zod54.default.string().describe("Display name"),
@@ -28729,7 +28951,7 @@ var createSchema = import_zod54.default.object({
28729
28951
  required: import_zod54.default.boolean().optional().default(false).describe("Whether field is required")
28730
28952
  })).optional().describe("Custom field definitions for entries in this collection")
28731
28953
  });
28732
- var createCreateCollectionTool = () => (0, import_langchain65.tool)(
28954
+ var createCreateCollectionTool = () => (0, import_langchain66.tool)(
28733
28955
  async (input, _exeConfig) => {
28734
28956
  try {
28735
28957
  const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
@@ -28755,7 +28977,7 @@ var createCreateCollectionTool = () => (0, import_langchain65.tool)(
28755
28977
 
28756
28978
  // src/tool_lattice/collection/update_collection.ts
28757
28979
  var import_zod55 = __toESM(require("zod"));
28758
- var import_langchain66 = require("langchain");
28980
+ var import_langchain67 = require("langchain");
28759
28981
  var schema = import_zod55.default.object({
28760
28982
  name: import_zod55.default.string().describe("Collection name"),
28761
28983
  label: import_zod55.default.string().optional().describe("New display name"),
@@ -28767,7 +28989,7 @@ var schema = import_zod55.default.object({
28767
28989
  required: import_zod55.default.boolean().optional().default(false).describe("Whether field is required")
28768
28990
  })).optional().describe("Custom field definitions for entries (replaces existing schema)")
28769
28991
  });
28770
- var createUpdateCollectionTool = () => (0, import_langchain66.tool)(
28992
+ var createUpdateCollectionTool = () => (0, import_langchain67.tool)(
28771
28993
  async (input, _exeConfig) => {
28772
28994
  try {
28773
28995
  const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
@@ -28787,8 +29009,8 @@ var createUpdateCollectionTool = () => (0, import_langchain66.tool)(
28787
29009
 
28788
29010
  // src/tool_lattice/collection/delete_collection.ts
28789
29011
  var import_zod56 = __toESM(require("zod"));
28790
- var import_langchain67 = require("langchain");
28791
- var createDeleteCollectionTool = () => (0, import_langchain67.tool)(
29012
+ var import_langchain68 = require("langchain");
29013
+ var createDeleteCollectionTool = () => (0, import_langchain68.tool)(
28792
29014
  async (input, _exeConfig) => {
28793
29015
  try {
28794
29016
  const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
@@ -28803,14 +29025,14 @@ var createDeleteCollectionTool = () => (0, import_langchain67.tool)(
28803
29025
 
28804
29026
  // src/tool_lattice/collection/list_entries.ts
28805
29027
  var import_zod57 = __toESM(require("zod"));
28806
- var import_langchain68 = require("langchain");
29028
+ var import_langchain69 = require("langchain");
28807
29029
  var schema2 = import_zod57.default.object({
28808
29030
  collection: import_zod57.default.string().describe("Collection name")
28809
29031
  });
28810
29032
  function buildKey2(tenantId2, name) {
28811
29033
  return `${tenantId2}:${name}`;
28812
29034
  }
28813
- var createListEntriesTool = () => (0, import_langchain68.tool)(
29035
+ var createListEntriesTool = () => (0, import_langchain69.tool)(
28814
29036
  async (input, _exeConfig) => {
28815
29037
  try {
28816
29038
  const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
@@ -28838,7 +29060,7 @@ var createListEntriesTool = () => (0, import_langchain68.tool)(
28838
29060
 
28839
29061
  // src/tool_lattice/collection/add_entry.ts
28840
29062
  var import_zod58 = __toESM(require("zod"));
28841
- var import_langchain69 = require("langchain");
29063
+ var import_langchain70 = require("langchain");
28842
29064
  var import_documents = require("@langchain/core/documents");
28843
29065
  var import_uuid11 = require("uuid");
28844
29066
  var schema3 = import_zod58.default.object({
@@ -28849,7 +29071,7 @@ var schema3 = import_zod58.default.object({
28849
29071
  function key(t, n) {
28850
29072
  return `${t}:${n}`;
28851
29073
  }
28852
- var createAddEntryTool = () => (0, import_langchain69.tool)(
29074
+ var createAddEntryTool = () => (0, import_langchain70.tool)(
28853
29075
  async (input, _exeConfig) => {
28854
29076
  try {
28855
29077
  const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
@@ -28869,7 +29091,7 @@ var createAddEntryTool = () => (0, import_langchain69.tool)(
28869
29091
 
28870
29092
  // src/tool_lattice/collection/update_entry.ts
28871
29093
  var import_zod59 = __toESM(require("zod"));
28872
- var import_langchain70 = require("langchain");
29094
+ var import_langchain71 = require("langchain");
28873
29095
  var schema4 = import_zod59.default.object({
28874
29096
  collection: import_zod59.default.string().describe("Collection name"),
28875
29097
  entryId: import_zod59.default.string().describe("Entry ID to update"),
@@ -28879,7 +29101,7 @@ var schema4 = import_zod59.default.object({
28879
29101
  function key2(t, n) {
28880
29102
  return `${t}:${n}`;
28881
29103
  }
28882
- var createUpdateEntryTool = () => (0, import_langchain70.tool)(
29104
+ var createUpdateEntryTool = () => (0, import_langchain71.tool)(
28883
29105
  async (input, _exeConfig) => {
28884
29106
  try {
28885
29107
  const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
@@ -28899,7 +29121,7 @@ var createUpdateEntryTool = () => (0, import_langchain70.tool)(
28899
29121
 
28900
29122
  // src/tool_lattice/collection/delete_entry.ts
28901
29123
  var import_zod60 = __toESM(require("zod"));
28902
- var import_langchain71 = require("langchain");
29124
+ var import_langchain72 = require("langchain");
28903
29125
  var schema5 = import_zod60.default.object({
28904
29126
  collection: import_zod60.default.string().describe("Collection name"),
28905
29127
  entryId: import_zod60.default.string().describe("Entry ID to delete")
@@ -28907,7 +29129,7 @@ var schema5 = import_zod60.default.object({
28907
29129
  function key3(t, n) {
28908
29130
  return `${t}:${n}`;
28909
29131
  }
28910
- var createDeleteEntryTool = () => (0, import_langchain71.tool)(
29132
+ var createDeleteEntryTool = () => (0, import_langchain72.tool)(
28911
29133
  async (input, _exeConfig) => {
28912
29134
  try {
28913
29135
  const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
@@ -28925,7 +29147,7 @@ var createDeleteEntryTool = () => (0, import_langchain71.tool)(
28925
29147
  function createCollectionMiddleware(params) {
28926
29148
  const { collectionKeys, connectAll } = params;
28927
29149
  if (!connectAll && (!collectionKeys || collectionKeys.length === 0)) {
28928
- return (0, import_langchain72.createMiddleware)({
29150
+ return (0, import_langchain73.createMiddleware)({
28929
29151
  name: "collectionMiddleware",
28930
29152
  contextSchema,
28931
29153
  tools: [
@@ -28935,7 +29157,7 @@ function createCollectionMiddleware(params) {
28935
29157
  });
28936
29158
  }
28937
29159
  const listToolParams = { collectionKeys, connectAll };
28938
- return (0, import_langchain72.createMiddleware)({
29160
+ return (0, import_langchain73.createMiddleware)({
28939
29161
  name: "collectionMiddleware",
28940
29162
  contextSchema,
28941
29163
  tools: [
@@ -28997,11 +29219,11 @@ var collectionPlugin = {
28997
29219
  };
28998
29220
 
28999
29221
  // src/middlewares/askUserClarifyMiddleware.ts
29000
- var import_langchain74 = require("langchain");
29222
+ var import_langchain75 = require("langchain");
29001
29223
  var import_langgraph15 = require("@langchain/langgraph");
29002
29224
 
29003
29225
  // src/tool_lattice/ask_user_to_clarify/index.ts
29004
- var import_langchain73 = require("langchain");
29226
+ var import_langchain74 = require("langchain");
29005
29227
  var import_zod61 = __toESM(require("zod"));
29006
29228
  var questionSchema = import_zod61.default.object({
29007
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?'"),
@@ -29014,7 +29236,7 @@ var inputSchema = import_zod61.default.object({
29014
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.")
29015
29237
  });
29016
29238
  function createAskUserToClarifyTool() {
29017
- return (0, import_langchain73.tool)(
29239
+ return (0, import_langchain74.tool)(
29018
29240
  async (input) => {
29019
29241
  return JSON.stringify(input);
29020
29242
  },
@@ -29028,7 +29250,7 @@ function createAskUserToClarifyTool() {
29028
29250
 
29029
29251
  // src/middlewares/askUserClarifyMiddleware.ts
29030
29252
  function createAskUserClarifyMiddleware() {
29031
- return (0, import_langchain74.createMiddleware)({
29253
+ return (0, import_langchain75.createMiddleware)({
29032
29254
  name: "AskUserClarifyMiddleware",
29033
29255
  tools: [createAskUserToClarifyTool()],
29034
29256
  wrapToolCall: async (request, handler) => {
@@ -29042,7 +29264,7 @@ function createAskUserClarifyMiddleware() {
29042
29264
  throw error;
29043
29265
  }
29044
29266
  console.error(`Error executing tool "${toolName}":`, error);
29045
- return new import_langchain74.ToolMessage({
29267
+ return new import_langchain75.ToolMessage({
29046
29268
  content: `Error executing tool: ${error instanceof Error ? error.message : "Unknown error"}`,
29047
29269
  tool_call_id: toolCall?.id,
29048
29270
  name: toolName
@@ -29051,7 +29273,7 @@ function createAskUserClarifyMiddleware() {
29051
29273
  }
29052
29274
  const parsed = inputSchema.safeParse(toolCall?.args);
29053
29275
  if (!parsed.success) {
29054
- return new import_langchain74.ToolMessage({
29276
+ return new import_langchain75.ToolMessage({
29055
29277
  content: `Invalid clarify tool arguments: ${parsed.error.message}`,
29056
29278
  tool_call_id: toolCall?.id,
29057
29279
  name: toolName
@@ -29071,7 +29293,7 @@ function createAskUserClarifyMiddleware() {
29071
29293
  const result = await (0, import_langgraph15.interrupt)(md);
29072
29294
  const response = result.data;
29073
29295
  if (!response?.answers || response.answers.length === 0) {
29074
- return new import_langchain74.ToolMessage({
29296
+ return new import_langchain75.ToolMessage({
29075
29297
  content: "No clarification questions were answered.",
29076
29298
  tool_call_id: toolCall?.id,
29077
29299
  name: toolName
@@ -29081,7 +29303,7 @@ function createAskUserClarifyMiddleware() {
29081
29303
  (answer) => (answer.selectedOptions?.length ?? 0) > 0 || answer.otherText && answer.otherText.trim() !== "" || answer.filePath && answer.filePath.trim() !== ""
29082
29304
  );
29083
29305
  if (answeredQuestions.length === 0) {
29084
- return new import_langchain74.ToolMessage({
29306
+ return new import_langchain75.ToolMessage({
29085
29307
  content: "No clarification questions were answered.",
29086
29308
  tool_call_id: toolCall?.id,
29087
29309
  name: toolName
@@ -29111,7 +29333,7 @@ function createAskUserClarifyMiddleware() {
29111
29333
  }
29112
29334
  lines.push("");
29113
29335
  }
29114
- return new import_langchain74.ToolMessage({
29336
+ return new import_langchain75.ToolMessage({
29115
29337
  content: lines.join("\n"),
29116
29338
  tool_call_id: toolCall?.id,
29117
29339
  name: toolName
@@ -29137,10 +29359,10 @@ var askUserClarifyPlugin = {
29137
29359
  };
29138
29360
 
29139
29361
  // src/middlewares/widgetMiddleware.ts
29140
- var import_langchain77 = require("langchain");
29362
+ var import_langchain78 = require("langchain");
29141
29363
 
29142
29364
  // src/tool_lattice/widget/loadGuidelines.ts
29143
- var import_langchain75 = require("langchain");
29365
+ var import_langchain76 = require("langchain");
29144
29366
  var import_zod62 = require("zod");
29145
29367
 
29146
29368
  // src/middlewares/guidelines/index.ts
@@ -29938,7 +30160,7 @@ var LoadGuidelinesInputSchema = import_zod62.z.object({
29938
30160
  )
29939
30161
  });
29940
30162
  function createLoadGuidelinesTool() {
29941
- return (0, import_langchain75.tool)(
30163
+ return (0, import_langchain76.tool)(
29942
30164
  async (input) => {
29943
30165
  const result = getGuidelines(input.modules);
29944
30166
  return result;
@@ -29952,7 +30174,7 @@ function createLoadGuidelinesTool() {
29952
30174
  }
29953
30175
 
29954
30176
  // src/tool_lattice/widget/showWidget.ts
29955
- var import_langchain76 = require("langchain");
30177
+ var import_langchain77 = require("langchain");
29956
30178
  var import_zod63 = require("zod");
29957
30179
  function containsForbiddenTags(code) {
29958
30180
  const forbiddenPatterns = [
@@ -29988,7 +30210,7 @@ var ShowWidgetInputSchema = import_zod63.z.object({
29988
30210
  )
29989
30211
  });
29990
30212
  function createShowWidgetTool() {
29991
- return (0, import_langchain76.tool)(
30213
+ return (0, import_langchain77.tool)(
29992
30214
  async (input) => {
29993
30215
  if (!input.i_have_seen_guidelines) {
29994
30216
  return "Error: You must call load_guidelines before using show_widget. Set i_have_seen_guidelines to true only after loading guidelines.";
@@ -30019,7 +30241,7 @@ function createWidgetMiddleware() {
30019
30241
  createLoadGuidelinesTool(),
30020
30242
  createShowWidgetTool()
30021
30243
  ];
30022
- return (0, import_langchain77.createMiddleware)({
30244
+ return (0, import_langchain78.createMiddleware)({
30023
30245
  name: "widgetMiddleware",
30024
30246
  contextSchema,
30025
30247
  tools
@@ -30043,7 +30265,7 @@ var widgetPlugin = {
30043
30265
  };
30044
30266
 
30045
30267
  // src/middlewares/evalMiddleware.ts
30046
- var import_langchain78 = require("langchain");
30268
+ var import_langchain79 = require("langchain");
30047
30269
  var import_zod64 = require("zod");
30048
30270
  var import_uuid12 = require("uuid");
30049
30271
 
@@ -30080,10 +30302,21 @@ Write assertions as objective, verifiable natural language:
30080
30302
  - steps: [{agent_id: "a"}, {agent_id: "b", override_message: "Based on..."}] for chain
30081
30303
  - outputType: "message_content" or "file_content"
30082
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
+
30083
30315
  ## Checklist
30084
30316
  1. Check existing assets with read_eval to avoid duplication
30085
30317
  2. Start with 3-5 high-signal cases
30086
- 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
30087
30320
  `,
30088
30321
  "eval-run-and-govern": `---
30089
30322
  name: eval-run-and-govern
@@ -30093,8 +30326,11 @@ description: Run agent evaluations, interpret results, diagnose failures, and re
30093
30326
  # Agent Governance Loop
30094
30327
 
30095
30328
  1. Discover project \u2192 read_eval list_projects
30096
- 2. Start evaluation \u2192 run_eval start(projectId) \u2014 ASYNC, may take minutes
30097
- 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)
30098
30334
  4. If runnerAlive=false and status=running \u2192 ORPHANED (gateway restart).
30099
30335
  resume(runId) marks it failed automatically \u2014 then start a new run.
30100
30336
  5. Get results \u2192 read_eval get_run_results(runId) for per-case dimension scores
@@ -30163,10 +30399,12 @@ function sanitize(obj) {
30163
30399
  }
30164
30400
  function aggregateHoldoutResults(results) {
30165
30401
  const passed = results.filter((r) => r.pass).length;
30402
+ const interrupted = results.filter((r) => r.interrupted).length;
30166
30403
  return {
30167
30404
  holdout: true,
30168
30405
  passedCases: passed,
30169
30406
  failedCases: results.length - passed,
30407
+ interruptedCases: interrupted,
30170
30408
  passRate: results.length > 0 ? passed / results.length : 0,
30171
30409
  totalCases: results.length
30172
30410
  };
@@ -30198,7 +30436,7 @@ function createReadEvalTool() {
30198
30436
  runId: import_zod64.z.string().optional(),
30199
30437
  status: import_zod64.z.string().optional().describe("Filter: running|completed|failed|aborted")
30200
30438
  });
30201
- return (0, import_langchain78.tool)(
30439
+ return (0, import_langchain79.tool)(
30202
30440
  async (input, exeConfig) => {
30203
30441
  const tid = tenantId(exeConfig);
30204
30442
  if (!tid) {
@@ -30237,13 +30475,8 @@ function createReadEvalTool() {
30237
30475
  if (!run) return JSON.stringify({ success: false, error: "Run not found" });
30238
30476
  const results = await store.getResultsByRun(tid, input.runId);
30239
30477
  if (run.holdout) {
30240
- const passed = results.filter((r) => r.pass).length;
30241
30478
  data = {
30242
- holdout: true,
30243
- passedCases: passed,
30244
- failedCases: results.length - passed,
30245
- passRate: results.length > 0 ? passed / results.length : 0,
30246
- totalCases: results.length,
30479
+ ...aggregateHoldoutResults(results),
30247
30480
  message: "Hold-out run \u2014 per-case results withheld. Only aggregates are available."
30248
30481
  };
30249
30482
  } else {
@@ -30278,6 +30511,7 @@ ACTIONS:
30278
30511
  - get_run_results(runId) \u2014 per-case results with dimension scores.
30279
30512
  For HOLD-OUT (validation-only) runs: returns AGGREGATES ONLY
30280
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.
30281
30515
  - get_project_report(projectId) \u2014 aggregated stats across all runs`,
30282
30516
  schema: schema6
30283
30517
  }
@@ -30308,9 +30542,13 @@ function createManageEvalTool() {
30308
30542
  steps: import_zod64.z.array(import_zod64.z.object({ agent_id: import_zod64.z.string(), override_message: import_zod64.z.string().optional() })).optional(),
30309
30543
  outputType: import_zod64.z.enum(["file_content", "message_content"]).optional(),
30310
30544
  contentAssertion: import_zod64.z.string().optional(),
30311
- 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")
30312
30550
  });
30313
- return (0, import_langchain78.tool)(
30551
+ return (0, import_langchain79.tool)(
30314
30552
  async (input, exeConfig) => {
30315
30553
  const tid = tenantId(exeConfig);
30316
30554
  if (!tid) {
@@ -30366,7 +30604,8 @@ function createManageEvalTool() {
30366
30604
  steps: input.steps,
30367
30605
  outputType: input.outputType,
30368
30606
  contentAssertion: input.contentAssertion,
30369
- rubrics: input.rubrics
30607
+ rubrics: input.rubrics,
30608
+ interruptPolicy: input.interruptPolicy
30370
30609
  });
30371
30610
  break;
30372
30611
  case "update_case":
@@ -30374,7 +30613,8 @@ function createManageEvalTool() {
30374
30613
  inputMessage: input.inputMessage,
30375
30614
  contentAssertion: input.contentAssertion,
30376
30615
  steps: input.steps,
30377
- rubrics: input.rubrics
30616
+ rubrics: input.rubrics,
30617
+ interruptPolicy: input.interruptPolicy
30378
30618
  });
30379
30619
  break;
30380
30620
  case "delete_case":
@@ -30399,9 +30639,13 @@ Project: create_project(name, description?, judgeModelKey?, concurrency?) | upda
30399
30639
  **When creating a project from within a workspace, the workspace/project context is
30400
30640
  automatically bound \u2014 eval runs will execute in the same workspace.**
30401
30641
  Suite: create_suite(projectId, name) | update_suite | delete_suite
30402
- Case: create_case(suiteId, inputMessage, steps, outputType, contentAssertion, inputFiles?, rubrics?)
30642
+ Case: create_case(suiteId, inputMessage, steps, outputType, contentAssertion, inputFiles?, rubrics?, interruptPolicy?)
30403
30643
  steps is [{agent_id, override_message?}]. outputType is "file_content" or "message_content".
30404
- 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).`,
30405
30649
  schema: schema6
30406
30650
  }
30407
30651
  );
@@ -30416,7 +30660,7 @@ function createRunEvalTool() {
30416
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."),
30417
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.")
30418
30662
  });
30419
- return (0, import_langchain78.tool)(
30663
+ return (0, import_langchain79.tool)(
30420
30664
  withToolTimeout(
30421
30665
  async (input, exeConfig) => {
30422
30666
  const tid = tenantId(exeConfig);
@@ -30515,6 +30759,8 @@ ACTIONS:
30515
30759
  - start(projectId, suiteIds?, caseIds?, wait?) \u2014 begin evaluation (optionally only the listed suites, and/or only the listed cases).
30516
30760
  wait=true (DEFAULT): SYNCHRONOUS \u2014 blocks up to ~150s and returns the FINAL RESULTS in one call:
30517
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.
30518
30764
  If the run exceeds 150s: returns { runId, status: "running" } \u2014 NOT an error \u2014 then poll with status/resume until completed.
30519
30765
  wait=false: fire-and-forget \u2014 returns { runId } immediately; poll with status.
30520
30766
  - status(runId, sleepMs?) \u2014 sleep sleepMs first (to pace polling), then return current status + runnerAlive flag:
@@ -30545,7 +30791,7 @@ var evalPlugin = {
30545
30791
  defaultConfig: {}
30546
30792
  },
30547
30793
  skills: EVAL_SKILLS,
30548
- middleware: () => (0, import_langchain78.createMiddleware)({
30794
+ middleware: () => (0, import_langchain79.createMiddleware)({
30549
30795
  name: "EvalMiddleware",
30550
30796
  tools: [createReadEvalTool(), createManageEvalTool(), createRunEvalTool()]
30551
30797
  })
@@ -30820,67 +31066,64 @@ verification choice, then start benchmarking.
30820
31066
 
30821
31067
  ## Task Tracking \u2014 see [[task-tracking]]
30822
31068
 
30823
- **Create the parent task when the task is actually defined** \u2014 after
30824
- Phase 0 clarification is complete and the user confirmed the path
30825
- (fresh vs incremental). Do NOT create tasks during clarification:
30826
- while asking questions (0.0-0.4) you don't know what the task is yet.
30827
- Once the scope is clear (end of 0.5), that is the moment to create:
30828
- manage_task create("Learn [material]", ownerType: "agent"). Then a
30829
- subtask per phase as you start it. Update status to reflect reality \u2014
30830
- never mark a subtask completed while eval fails. Resume interrupted
30831
- 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.
30832
31078
 
30833
31079
  Widgets: call \`load_guidelines\` ONCE before your first \`show_widget\`
30834
31080
  (show_widget hard-requires it), then reuse.
30835
31081
 
30836
31082
  ---
30837
31083
 
30838
- ## Phase 1: Probe (material-dependent)
30839
-
30840
- The probing strategy depends on the material type from Phase 0.0:
30841
-
30842
- **User-description material**: the requirements come from the
30843
- conversation itself \u2014 no probing needed. Extract the agent's goal,
30844
- inputs, outputs, and constraints from what the user described. Go
30845
- straight to design.
30846
-
30847
- **Document material** (PDF / spec / manual):
30848
- If the engine was chosen in Phase 0 (0.3 \u2460-\u2464): skip the comparison \u2014
30849
- parse directly with \`parse_document\` using the chosen engine
30850
- (file_path, engine, output_path per file).
30851
- Otherwise: run the document-parser-benchmark subagent via \`task\` on each file.
30852
- Collect engine scores, parsed output (via \`read_file\`), and feature signatures.
30853
-
30854
- **Engine selection IS distilled knowledge, not just setup.** For document
30855
- material, the benchmark answers "which engine parses THIS document (or
30856
- this class of document) best?" \u2014 that answer is knowledge that drives
30857
- the whole rest of the run:
30858
- - **Builds the agent**: the chosen engine's \`parse_document\` goes into
30859
- the production agent's middleware/tools.
30860
- - **Designs the tests**: the chosen engine's parsed output becomes the
30861
- baseline input for eval cases \u2014 cases feed parsed output to the agent
30862
- and assert correct extraction from it.
30863
- - **Seeds the skill**: the feature signature (tables? scans? mixed
30864
- zh/en?) plus the winning engine becomes a skill note ("for PO PDFs
30865
- with tables, use textin") reusable for future similar documents.
30866
- So when the user wants an agent whose purpose is document PARSING (not
30867
- extraction), the workflow is the same: benchmark to learn the engine
30868
- choice, then build the agent around that engine and test against its
30869
- output. Do NOT treat parsing as a pure tool-assembly task \u2014 the engine
30870
- choice is unknown knowledge until probed.
30871
-
30872
- **API spec material**: read the spec directly \u2014 no parsing engine needed.
30873
- Extract endpoints, schemas, request/response examples from the text.
30874
-
30875
- **Conversation material**: extract the workflow, decisions, and corrections
30876
- from the conversation context \u2014 no parsing engine needed.
30877
-
30878
- **Spreadsheet material**: parse cells directly \u2014 structured data needs
30879
- no engine comparison.
30880
- If verification will happen (0.2 \u2460 or \u2461): concurrently, \`list_agents\` to
30881
- discover existing agents with relevant capabilities (see \xA75).
30882
- For \u2460, look for agents with data-access tools (SQL / API). For \u2461, look
30883
- 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.
30884
31127
 
30885
31128
  ---
30886
31129
 
@@ -30895,17 +31138,21 @@ candidate and assess (Validation Agent Design \xA70) \u2014 state which are
30895
31138
  usable and which are not, with reasons. For \u2460, the executor needs data
30896
31139
  tools + independence. For \u2461, independence only. If no candidate fits,
30897
31140
  plan to build one via \xA75.
30898
- 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
30899
31145
  \`ask_user_to_clarify\` NOW:
30900
31146
  {
30901
31147
  "questions": [{
30902
- "question": "Confirm the recommendation?",
31148
+ "question": "Confirm the recommended path?",
30903
31149
  "options": ["Confirm", "Adjust"],
30904
31150
  "type": "single",
30905
31151
  "required": true
30906
31152
  }]
30907
31153
  }
30908
- 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.
30909
31156
 
30910
31157
  ---
30911
31158
 
@@ -30973,9 +31220,53 @@ user-description material this IS the core phase; for material-based
30973
31220
  learning it designs the agent that runs the learned skill. Agent
30974
31221
  metadata (verified/version/source) must be set on creation.
30975
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
+
30976
31265
  ## Phase 3: Create Skills
30977
31266
 
30978
- 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.
30979
31270
  Show the skill content in text first, then MUST call
30980
31271
  \`ask_user_to_clarify\` NOW per skill:
30981
31272
  {
@@ -31269,7 +31560,8 @@ This learning loop adds its own scenario rules:
31269
31560
  - Business usability (output reaches the goal's "usable state")
31270
31561
  - Consumer fit (format/contract satisfies who uses the result)
31271
31562
  contentAssertion must encode the usable state from the goal model
31272
- (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.
31273
31565
 
31274
31566
  1. One suite per skill per source: cases test "can this skill do it" \u2014
31275
31567
  never mix skills in one suite
@@ -31312,6 +31604,12 @@ Learning-specific suite guidance:
31312
31604
  - User-description material: {skill}-requirement-derived \u2014 cases from
31313
31605
  user's described requirements
31314
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
+
31315
31613
  [[completion-gate]] applies \u2014 eval must pass before declaring done.
31316
31614
 
31317
31615
  ## Phase 5: Retrospective
@@ -31454,12 +31752,12 @@ var documentLearningPlugin = {
31454
31752
  };
31455
31753
 
31456
31754
  // src/middlewares/documentParserMiddleware.ts
31457
- var import_langchain80 = require("langchain");
31755
+ var import_langchain81 = require("langchain");
31458
31756
 
31459
31757
  // src/tool_lattice/document_parser/index.ts
31460
31758
  var path7 = __toESM(require("path"));
31461
31759
  var import_zod65 = __toESM(require("zod"));
31462
- var import_langchain79 = require("langchain");
31760
+ var import_langchain80 = require("langchain");
31463
31761
  var PARSE_DOCUMENT_DESCRIPTION = `Parse a document file (docx, pdf) into structured Markdown using a remote document parsing service.
31464
31762
  This tool handles the full pipeline internally: file upload \u2192 document parsing \u2192 polling until complete \u2192 download result \u2192 save to filesystem.
31465
31763
 
@@ -31581,7 +31879,7 @@ function createParseDocumentTool({
31581
31879
  baseUrl = "",
31582
31880
  apiKey = ""
31583
31881
  }) {
31584
- return (0, import_langchain79.tool)(
31882
+ return (0, import_langchain80.tool)(
31585
31883
  async (input, exe_config) => {
31586
31884
  try {
31587
31885
  const runConfig = exe_config?.configurable?.runConfig ?? { assistant_id: "", thread_id: "" };
@@ -31845,7 +32143,7 @@ function createDocumentParserMiddleware(config) {
31845
32143
  const connectAll = config.connectAll === true;
31846
32144
  const baseUrl = config.baseUrl || "";
31847
32145
  const apiKey = config.apiKey || "";
31848
- return (0, import_langchain80.createMiddleware)({
32146
+ return (0, import_langchain81.createMiddleware)({
31849
32147
  name: "DocumentParser",
31850
32148
  contextSchema,
31851
32149
  tools: [createParseDocumentTool({ connectAll, baseUrl, apiKey })]