langflower 0.1.1 → 0.1.2

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
@@ -28,7 +28,7 @@ import {
28
28
  mergeProjectAndNodePermissions,
29
29
  resolveProjectPath,
30
30
  walkFiles
31
- } from "./chunk-WQZHA5FM.js";
31
+ } from "./chunk-NIRPHJLO.js";
32
32
  import {
33
33
  __commonJS,
34
34
  __require,
@@ -59200,6 +59200,11 @@ var runnerConfig = {
59200
59200
  * (not a canvas HITL port — see `runner.permission.ask`).
59201
59201
  */
59202
59202
  "runner.permission.reply": message(),
59203
+ /**
59204
+ * Operator text for a runtime `ask_user` builtin wait inside the tool
59205
+ * loop (not a canvas HITL port — see `runner.askUser.ask`).
59206
+ */
59207
+ "runner.askUser.reply": message(),
59203
59208
  /**
59204
59209
  * Clear the execution feed (work log). Server drops the runner event
59205
59210
  * log and re-broadcasts an empty `executionFeed.snapshot`. No payload.
@@ -59257,6 +59262,16 @@ var runnerConfig = {
59257
59262
  * ask. Every client removes that ask from its UI only on this fact.
59258
59263
  */
59259
59264
  "runner.permission.accepted": message(),
59265
+ /**
59266
+ * Runtime `ask_user` wait for operator text (feed + composer textarea).
59267
+ * Stays inside the internal tool loop — not a graph HITL edge.
59268
+ */
59269
+ "runner.askUser.ask": message(),
59270
+ /**
59271
+ * Server accepted one text reply for a still-pending `ask_user`.
59272
+ * Every client removes that ask from its UI only on this fact.
59273
+ */
59274
+ "runner.askUser.accepted": message(),
59260
59275
  /**
59261
59276
  * Resumable checkpoints for the active workflow (bootstrap + after
59262
59277
  * Stop / discard / complete).
@@ -59916,6 +59931,11 @@ var runnerConfig2 = {
59916
59931
  * (not a canvas HITL port — see `runner.permission.ask`).
59917
59932
  */
59918
59933
  "runner.permission.reply": message(),
59934
+ /**
59935
+ * Operator text for a runtime `ask_user` builtin wait inside the tool
59936
+ * loop (not a canvas HITL port — see `runner.askUser.ask`).
59937
+ */
59938
+ "runner.askUser.reply": message(),
59919
59939
  /**
59920
59940
  * Clear the execution feed (work log). Server drops the runner event
59921
59941
  * log and re-broadcasts an empty `executionFeed.snapshot`. No payload.
@@ -59973,6 +59993,16 @@ var runnerConfig2 = {
59973
59993
  * ask. Every client removes that ask from its UI only on this fact.
59974
59994
  */
59975
59995
  "runner.permission.accepted": message(),
59996
+ /**
59997
+ * Runtime `ask_user` wait for operator text (feed + composer textarea).
59998
+ * Stays inside the internal tool loop — not a graph HITL edge.
59999
+ */
60000
+ "runner.askUser.ask": message(),
60001
+ /**
60002
+ * Server accepted one text reply for a still-pending `ask_user`.
60003
+ * Every client removes that ask from its UI only on this fact.
60004
+ */
60005
+ "runner.askUser.accepted": message(),
59976
60006
  /**
59977
60007
  * Resumable checkpoints for the active workflow (bootstrap + after
59978
60008
  * Stop / discard / complete).
@@ -61026,6 +61056,52 @@ var RunCheckpointSession = class {
61026
61056
  import { RuntimeFacade } from "@langflower/runtime";
61027
61057
  import { Subscription } from "rxjs";
61028
61058
 
61059
+ // packages/server/dist/harness/pending-ask-user-asks.js
61060
+ var ASK_USER_ABORTED = "ask_user aborted.";
61061
+ var PendingAskUserAsks = class {
61062
+ pending = /* @__PURE__ */ new Map();
61063
+ list() {
61064
+ return [...this.pending.values()].map((entry) => entry.payload);
61065
+ }
61066
+ requestAskUser = (runId, nodeId, request, emitAsk) => {
61067
+ const askId = crypto.randomUUID();
61068
+ const payload = {
61069
+ runId,
61070
+ askId,
61071
+ nodeId,
61072
+ question: request.question
61073
+ };
61074
+ return new Promise((resolve, reject) => {
61075
+ this.pending.set(askId, { payload, resolve, reject });
61076
+ emitAsk(payload);
61077
+ });
61078
+ };
61079
+ reply = (payload) => {
61080
+ const entry = this.pending.get(payload.askId);
61081
+ if (entry === void 0) {
61082
+ return false;
61083
+ }
61084
+ if (entry.payload.runId !== payload.runId) {
61085
+ return false;
61086
+ }
61087
+ const text = payload.text.trim();
61088
+ if (text.length === 0) {
61089
+ return false;
61090
+ }
61091
+ this.pending.delete(payload.askId);
61092
+ entry.resolve(text);
61093
+ return true;
61094
+ };
61095
+ /** Fail closed all outstanding asks (interrupt / run end). */
61096
+ failAll = (runId) => {
61097
+ const entries = [...this.pending.entries()].filter(([, entry]) => runId === void 0 || entry.payload.runId === runId);
61098
+ for (const [askId, entry] of entries) {
61099
+ this.pending.delete(askId);
61100
+ entry.reject(new Error(ASK_USER_ABORTED));
61101
+ }
61102
+ };
61103
+ };
61104
+
61029
61105
  // packages/server/dist/harness/pending-permission-asks.js
61030
61106
  var PendingPermissionAsks = class {
61031
61107
  pending = /* @__PURE__ */ new Map();
@@ -61147,6 +61223,8 @@ var LangflowerSession = class {
61147
61223
  runtime = new RuntimeFacade({ log: true });
61148
61224
  /** Feed permission.ask pause/resume for the internal tool loop. */
61149
61225
  permissionAsks = new PendingPermissionAsks();
61226
+ /** Feed ask_user pause/resume for the internal tool loop. */
61227
+ askUserAsks = new PendingAskUserAsks();
61150
61228
  activeWorkflow = null;
61151
61229
  activeWorkflowId;
61152
61230
  currentStatus = "pristine";
@@ -61175,6 +61253,7 @@ var LangflowerSession = class {
61175
61253
  this.subscriptions.add(this.runtime.runner.status$.subscribe((status) => {
61176
61254
  if (status !== "running") {
61177
61255
  this.permissionAsks.denyAll(this.runId !== void 0 ? String(this.runId) : void 0);
61256
+ this.askUserAsks.failAll(this.runId !== void 0 ? String(this.runId) : void 0);
61178
61257
  void this.releaseMcpRuntime();
61179
61258
  }
61180
61259
  this.runnerStatus = status;
@@ -61194,6 +61273,7 @@ var LangflowerSession = class {
61194
61273
  }
61195
61274
  dispose() {
61196
61275
  this.permissionAsks.denyAll();
61276
+ this.askUserAsks.failAll();
61197
61277
  void this.releaseMcpRuntime();
61198
61278
  this.runtime.runner.dispose();
61199
61279
  this.subscriptions.unsubscribe();
@@ -61522,7 +61602,8 @@ var HARNESS_BUILTIN_TOOL_IDS = [
61522
61602
  "write",
61523
61603
  "create",
61524
61604
  "delete",
61525
- "bash"
61605
+ "bash",
61606
+ "ask_user"
61526
61607
  ];
61527
61608
  var PLAN_AGENT_SYSTEM_PROMPT = [
61528
61609
  "You are the Plan agent in a Langflower workflow.",
@@ -61532,6 +61613,9 @@ var PLAN_AGENT_SYSTEM_PROMPT = [
61532
61613
  "",
61533
61614
  "Write plans in Markdown with sections: Goal, Context, Steps, Risks, Open questions.",
61534
61615
  "",
61616
+ "When memory tools are wired, call update_plan with that markdown so the operator",
61617
+ "sees the current plan in the work log. There is no separate Plan mode.",
61618
+ "",
61535
61619
  "When requirements are ambiguous, use ask_user before finalizing the plan."
61536
61620
  ].join("\n");
61537
61621
  var CODER_AGENT_SYSTEM_PROMPT = [
@@ -61541,7 +61625,9 @@ var CODER_AGENT_SYSTEM_PROMPT = [
61541
61625
  "edits. Prefer precise file edits over large rewrites.",
61542
61626
  "",
61543
61627
  "When tests are available, run them to verify your work. Summarize what you changed",
61544
- "in your final response."
61628
+ "in your final response.",
61629
+ "",
61630
+ "If you are not sure, call ask_user instead of guessing."
61545
61631
  ].join("\n");
61546
61632
  var EXPLORER_AGENT_SYSTEM_PROMPT = [
61547
61633
  "You are the Explorer agent in a Langflower workflow.",
@@ -61549,7 +61635,9 @@ var EXPLORER_AGENT_SYSTEM_PROMPT = [
61549
61635
  "Research the topic using web_fetch. Synthesize findings into clear Markdown notes.",
61550
61636
  "Do not modify application source code\u2014only *.md research notes.",
61551
61637
  "",
61552
- "Cite URLs. Separate facts from inference."
61638
+ "Cite URLs. Separate facts from inference.",
61639
+ "",
61640
+ "If you are not sure, call ask_user instead of guessing."
61553
61641
  ].join("\n");
61554
61642
  var allAllow = () => Object.fromEntries(HARNESS_BUILTIN_TOOL_IDS.map((id) => [id, "allow"]));
61555
61643
  var CUSTOM_TOOL_PERMISSIONS = allAllow();
@@ -61585,7 +61673,7 @@ var LLM_ROLE_PRESET_DEFAULTS = {
61585
61673
  },
61586
61674
  plan: {
61587
61675
  systemPrompt: PLAN_AGENT_SYSTEM_PROMPT,
61588
- skillId: "plan",
61676
+ skillId: "spec-architect",
61589
61677
  toolPermissions: PLAN_TOOL_PERMISSIONS
61590
61678
  },
61591
61679
  coder: {
@@ -61647,7 +61735,24 @@ var resolveEffectiveToolPermissions = (rolePreset, toolPermissionsParam, enabled
61647
61735
  }
61648
61736
  return LLM_ROLE_PRESET_DEFAULTS[rolePreset].toolPermissions;
61649
61737
  };
61650
- var toolPermissionsToEnabledIds = (toolPermissions) => Object.entries(toolPermissions).filter(([, decision]) => decision !== "deny").map(([toolId]) => toolId);
61738
+ var toolPermissionsToEnabledIds = (toolPermissions) => {
61739
+ const enabled = [];
61740
+ const seen = /* @__PURE__ */ new Set();
61741
+ for (const id of HARNESS_BUILTIN_TOOL_IDS) {
61742
+ if (toolPermissions[id] !== "deny") {
61743
+ enabled.push(id);
61744
+ seen.add(id);
61745
+ }
61746
+ }
61747
+ for (const [toolId, decision] of Object.entries(toolPermissions)) {
61748
+ if (decision === "deny" || seen.has(toolId)) {
61749
+ continue;
61750
+ }
61751
+ enabled.push(toolId);
61752
+ seen.add(toolId);
61753
+ }
61754
+ return enabled;
61755
+ };
61651
61756
 
61652
61757
  // packages/common-nodes/dist/ai/features/prompt/normalize-max-iterations.js
61653
61758
  var normalizeMaxIterations = (value, options) => {
@@ -62338,14 +62443,6 @@ var bindLlmAgentSession = (ctx, helpers, inventory, options) => {
62338
62443
  };
62339
62444
 
62340
62445
  // packages/common-nodes/dist/tools/inventory-tool-round.js
62341
- var TOOL_LOG_PREVIEW = 400;
62342
- var previewToolLogText = (text) => {
62343
- const trimmed = text.trim();
62344
- if (trimmed.length <= TOOL_LOG_PREVIEW) {
62345
- return trimmed;
62346
- }
62347
- return `${trimmed.slice(0, TOOL_LOG_PREVIEW - 1)}\u2026`;
62348
- };
62349
62446
  var toChatToolDefinitions = (tools) => tools.map((tool) => ({
62350
62447
  type: "function",
62351
62448
  function: {
@@ -63922,10 +64019,11 @@ var prepareAndStream = (state, options, cancel$, cancelSignal) => {
63922
64019
  });
63923
64020
  };
63924
64021
  var isSubAgentToolCall = (name) => name.endsWith("_subagent") || name.endsWith("(subagent)");
64022
+ var isUnboundedWaitToolCall = (name) => name === "ask_user" || isSubAgentToolCall(name);
63925
64023
  var invokeTool = (state, call, options, cancelSignal) => {
63926
64024
  const callLog = emit({
63927
64025
  kind: "toolLog",
63928
- text: `\u2192 ${call.name}(${previewToolLogText(call.arguments)})`
64026
+ text: `\u2192 ${call.name}(${call.arguments})`
63929
64027
  });
63930
64028
  const toolAbort = new AbortController();
63931
64029
  const abortTool = () => {
@@ -63949,7 +64047,7 @@ var invokeTool = (state, call, options, cancelSignal) => {
63949
64047
  })).pipe(finalize2(() => {
63950
64048
  cancelSignal.removeEventListener("abort", abortTool);
63951
64049
  }));
63952
- const toolTimeoutMs = isSubAgentToolCall(call.name) ? 0 : options.recovery.toolTimeoutMs;
64050
+ const toolTimeoutMs = isUnboundedWaitToolCall(call.name) ? 0 : options.recovery.toolTimeoutMs;
63953
64051
  const boundedInvocation$ = toolTimeoutMs > 0 ? invocation$.pipe(timeout2({
63954
64052
  first: toolTimeoutMs
63955
64053
  })) : invocation$;
@@ -63969,7 +64067,7 @@ var toolResultPackets = (state, call, result, options, prefix) => {
63969
64067
  ...prefix,
63970
64068
  emit({
63971
64069
  kind: "toolLog",
63972
- text: `\u2190 ${call.name}: ${previewToolLogText(normalized)}`
64070
+ text: `\u2190 ${call.name}: ${normalized}`
63973
64071
  }),
63974
64072
  transition(next)
63975
64073
  ]);
@@ -65317,7 +65415,7 @@ var PATH_CHOICE_POLICY = {
65317
65415
  { kind: "historySync", messages },
65318
65416
  {
65319
65417
  kind: "toolLog",
65320
- text: `\u2192 ${control.call.name}(${previewToolLogText(control.call.arguments)})`
65418
+ text: `\u2192 ${control.call.name}(${control.call.arguments})`
65321
65419
  },
65322
65420
  control.kind === "accept" ? { kind: "accept", notes } : { kind: "feedback", notes }
65323
65421
  ]
@@ -68256,6 +68354,8 @@ var topLevelHeadings = (text) => parseHeadings(text).filter((heading) => heading
68256
68354
  // packages/tools/dist/memory/memory-paths.js
68257
68355
  import path13 from "node:path";
68258
68356
  var MEMORY_ROOT_RELATIVE = ".langflower/memory";
68357
+ var MEMORY_PLAN_FILE = "history/plan.md";
68358
+ var MEMORY_PLAN_HEADING = "## Plan";
68259
68359
  var memoryRootAbsolute = (projectDir) => path13.join(path13.resolve(projectDir), MEMORY_ROOT_RELATIVE);
68260
68360
  var resolveMemoryFilePath = (projectDir, filePath) => {
68261
68361
  const trimmed = filePath.trim().replace(/\\/g, "/");
@@ -68760,6 +68860,58 @@ var MEMORY_TOOL_CONFIGS = [
68760
68860
  await createMemoryStore(ctx.projectDir).createFile(filePath, initial);
68761
68861
  return json({ file_path: filePath, ok: true });
68762
68862
  }
68863
+ },
68864
+ {
68865
+ toolId: "update_plan",
68866
+ description: "Replace the current plan shown to the operator in the work log. Writes the reserved ## Plan section in history/plan.md. There is no separate Plan mode \u2014 call this whenever the live plan changes. Pass only the markdown body under the heading (Goal, Context, Steps, Risks, Open questions).",
68867
+ inputSchema: {
68868
+ type: "object",
68869
+ properties: {
68870
+ content: {
68871
+ type: "string",
68872
+ description: "Markdown body under ## Plan. Do not include the heading itself."
68873
+ }
68874
+ },
68875
+ required: ["content"]
68876
+ },
68877
+ handler: async (args, ctx) => {
68878
+ const content = requireString(args, "content");
68879
+ await createMemoryStore(ctx.projectDir).updateSection(MEMORY_PLAN_FILE, MEMORY_PLAN_HEADING, content);
68880
+ return json({
68881
+ file_path: MEMORY_PLAN_FILE,
68882
+ heading: MEMORY_PLAN_HEADING,
68883
+ ok: true
68884
+ });
68885
+ }
68886
+ },
68887
+ {
68888
+ toolId: "read_plan",
68889
+ description: "Reads the current operator-visible plan from history/plan.md (## Plan). Returns empty content when the plan file or section does not exist.",
68890
+ inputSchema: {
68891
+ type: "object",
68892
+ properties: {},
68893
+ required: []
68894
+ },
68895
+ handler: async (_args, ctx) => {
68896
+ try {
68897
+ const content = await createMemoryStore(ctx.projectDir).readSection(MEMORY_PLAN_FILE, MEMORY_PLAN_HEADING);
68898
+ return json({
68899
+ file_path: MEMORY_PLAN_FILE,
68900
+ content,
68901
+ exists: true
68902
+ });
68903
+ } catch (error) {
68904
+ const message2 = error instanceof Error ? error.message : String(error);
68905
+ if (message2.includes("Memory file not found") || message2.includes("Heading")) {
68906
+ return json({
68907
+ file_path: MEMORY_PLAN_FILE,
68908
+ content: "",
68909
+ exists: false
68910
+ });
68911
+ }
68912
+ throw error;
68913
+ }
68914
+ }
68763
68915
  }
68764
68916
  ];
68765
68917
 
@@ -68956,25 +69108,68 @@ Typical uses:
68956
69108
  });
68957
69109
 
68958
69110
  // packages/common-nodes/dist/memory/memory-tools/node.js
68959
- import { defineToolRegistrations as defineToolRegistrations2 } from "@langflower/node-sdk";
68960
- var memoryToolsNode = defineToolRegistrations2({
69111
+ import { defineReactiveNode as defineReactiveNode32, TOOL_HANDLE_WIRE_TYPE as TOOL_HANDLE_WIRE_TYPE5 } from "@langflower/node-sdk";
69112
+ import { statefulConnection, statefulObservable as statefulObservable3 } from "@rx-evo/stateful-observable";
69113
+ import { of as of13 } from "rxjs";
69114
+ var memoryToolsNode = defineReactiveNode32({
68961
69115
  type: "common-memory-tools",
68962
69116
  displayName: "Memory Tools",
68963
69117
  category: "Tools",
68964
69118
  description: `
68965
- Give an agent tools to read and write the project wiki (tree, search, append, update, create).
69119
+ Give an agent tools to read and write the project wiki (tree, search, append, update, create) and to show the current plan in the work log.
68966
69120
 
68967
- Wire **tools** into an LLM. Notes live under the project's memory folder.
69121
+ Wire **tools** into an LLM. Notes live under the project's memory folder. Call **update_plan** to print the live plan \u2014 there is no separate Plan mode.
68968
69122
  `.trim(),
68969
- tools: MEMORY_TOOL_CONFIGS
69123
+ uiSchema: [],
69124
+ bind(_ctx, { configureOutput }) {
69125
+ const planOut = statefulConnection();
69126
+ const tools$ = statefulObservable3({
69127
+ loader: () => of13(MEMORY_TOOL_CONFIGS.map((tool) => {
69128
+ const handle = {
69129
+ toolId: tool.toolId,
69130
+ name: tool.name ?? tool.toolId,
69131
+ description: tool.description,
69132
+ inputSchema: tool.inputSchema,
69133
+ invoke: tool.handler
69134
+ };
69135
+ if (tool.toolId !== "update_plan") {
69136
+ return handle;
69137
+ }
69138
+ return {
69139
+ ...handle,
69140
+ invoke: async (args, ctx) => {
69141
+ const result = await tool.handler(args, ctx);
69142
+ try {
69143
+ const markdown = await createMemoryStore(ctx.projectDir).readSection(MEMORY_PLAN_FILE, MEMORY_PLAN_HEADING);
69144
+ planOut.connect(of13(markdown));
69145
+ } catch {
69146
+ }
69147
+ return result;
69148
+ }
69149
+ };
69150
+ }))
69151
+ });
69152
+ return {
69153
+ inputs: [],
69154
+ outputs: [
69155
+ configureOutput("tools", tools$, {
69156
+ wireType: TOOL_HANDLE_WIRE_TYPE5
69157
+ }),
69158
+ configureOutput("plan", planOut, {
69159
+ wireType: "string",
69160
+ feed: { role: "result" }
69161
+ })
69162
+ ]
69163
+ };
69164
+ }
68970
69165
  });
68971
69166
 
68972
69167
  // packages/common-nodes/dist/langflower-tools/node.js
68973
- import { defineReactiveNode as defineReactiveNode32, TOOL_HANDLE_WIRE_TYPE as TOOL_HANDLE_WIRE_TYPE5 } from "@langflower/node-sdk";
69168
+ import { defineReactiveNode as defineReactiveNode33, TOOL_HANDLE_WIRE_TYPE as TOOL_HANDLE_WIRE_TYPE6 } from "@langflower/node-sdk";
68974
69169
 
68975
69170
  // packages/common-nodes/dist/langflower-tools/emit-registration-tools.js
68976
- import { statefulObservable as statefulObservable3 } from "@rx-evo/stateful-observable";
68977
- import { of as of13 } from "rxjs";
69171
+ import { statefulObservable as statefulObservable4 } from "@rx-evo/stateful-observable";
69172
+ import { of as of14 } from "rxjs";
68978
69173
  var peekNodeContext = (source) => {
68979
69174
  let peeked;
68980
69175
  const sub = source.value$.subscribe((value) => {
@@ -68983,8 +69178,8 @@ var peekNodeContext = (source) => {
68983
69178
  sub.unsubscribe();
68984
69179
  return typeof peeked === "object" && peeked !== null ? peeked : void 0;
68985
69180
  };
68986
- var emitRegistrationTools = (ctx, tools) => statefulObservable3({
68987
- loader: () => of13(tools.map((tool) => ({
69181
+ var emitRegistrationTools = (ctx, tools) => statefulObservable4({
69182
+ loader: () => of14(tools.map((tool) => ({
68988
69183
  toolId: tool.toolId,
68989
69184
  name: tool.name ?? tool.toolId,
68990
69185
  description: tool.description,
@@ -69057,7 +69252,7 @@ ${message2}`;
69057
69252
  })
69058
69253
  }
69059
69254
  ];
69060
- var langflowerToolsNode = defineReactiveNode32({
69255
+ var langflowerToolsNode = defineReactiveNode33({
69061
69256
  type: "common-langflower-tools",
69062
69257
  displayName: "Langflower Tools",
69063
69258
  category: "Tools",
@@ -69071,14 +69266,14 @@ On starter, Helper and Writer already have this wired.
69071
69266
  return {
69072
69267
  inputs: [],
69073
69268
  outputs: [
69074
- configureOutput("tools", emitRegistrationTools(ctx, LANGFLOWER_BUS_TOOL_CONFIGS), { wireType: TOOL_HANDLE_WIRE_TYPE5 })
69269
+ configureOutput("tools", emitRegistrationTools(ctx, LANGFLOWER_BUS_TOOL_CONFIGS), { wireType: TOOL_HANDLE_WIRE_TYPE6 })
69075
69270
  ]
69076
69271
  };
69077
69272
  }
69078
69273
  });
69079
69274
 
69080
69275
  // packages/common-nodes/dist/tools/tool-collection/node.js
69081
- import { defineReactiveNode as defineReactiveNode33, TOOL_HANDLE_WIRE_TYPE as TOOL_HANDLE_WIRE_TYPE6 } from "@langflower/node-sdk";
69276
+ import { defineReactiveNode as defineReactiveNode34, TOOL_HANDLE_WIRE_TYPE as TOOL_HANDLE_WIRE_TYPE7 } from "@langflower/node-sdk";
69082
69277
  import { map as map19 } from "rxjs";
69083
69278
  var mergeToolHandlesLastWins = (wired) => {
69084
69279
  const flattened = Array.isArray(wired) ? flattenToolHandles(wired) : flattenToolHandles(wired === void 0 || wired === null ? [] : [wired]);
@@ -69088,7 +69283,7 @@ var mergeToolHandlesLastWins = (wired) => {
69088
69283
  }
69089
69284
  return [...byId.values()];
69090
69285
  };
69091
- var toolCollectionNode = defineReactiveNode33({
69286
+ var toolCollectionNode = defineReactiveNode34({
69092
69287
  type: "common-tool-collection",
69093
69288
  displayName: "Tool collection",
69094
69289
  category: "Tools",
@@ -69101,7 +69296,7 @@ Optional \u2014 you can still plug many tool packs straight into the agent.
69101
69296
  bind(_ctx, { makeInput, configureOutput }) {
69102
69297
  const tools = makeInput("tools", {
69103
69298
  name: "tools",
69104
- wireType: TOOL_HANDLE_WIRE_TYPE6,
69299
+ wireType: TOOL_HANDLE_WIRE_TYPE7,
69105
69300
  multi: "combine",
69106
69301
  defaultValue: []
69107
69302
  });
@@ -69110,7 +69305,7 @@ Optional \u2014 you can still plug many tool packs straight into the agent.
69110
69305
  inputs: [tools],
69111
69306
  outputs: [
69112
69307
  configureOutput("tools", merged$, {
69113
- wireType: TOOL_HANDLE_WIRE_TYPE6
69308
+ wireType: TOOL_HANDLE_WIRE_TYPE7
69114
69309
  })
69115
69310
  ]
69116
69311
  };
@@ -69118,8 +69313,8 @@ Optional \u2014 you can still plug many tool packs straight into the agent.
69118
69313
  });
69119
69314
 
69120
69315
  // packages/common-nodes/dist/tools/tool-invoke/node.js
69121
- import { defineReactiveNode as defineReactiveNode34, TOOL_HANDLE_WIRE_TYPE as TOOL_HANDLE_WIRE_TYPE7, withLoading as withLoading11 } from "@langflower/node-sdk";
69122
- import { concatMap as concatMap6, EMPTY as EMPTY7, from as from10, of as of14, throwError as throwError10 } from "rxjs";
69316
+ import { defineReactiveNode as defineReactiveNode35, TOOL_HANDLE_WIRE_TYPE as TOOL_HANDLE_WIRE_TYPE8, withLoading as withLoading11 } from "@langflower/node-sdk";
69317
+ import { concatMap as concatMap6, EMPTY as EMPTY7, from as from10, of as of15, throwError as throwError10 } from "rxjs";
69123
69318
  var isArgsObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
69124
69319
  var flattenWiredHandles = (wired) => {
69125
69320
  const flattened = Array.isArray(wired) ? flattenToolHandles(wired) : flattenToolHandles(wired === void 0 || wired === null ? [] : [wired]);
@@ -69163,7 +69358,7 @@ var parseInvokeArgs = (raw) => {
69163
69358
  return { ok: true, args: raw };
69164
69359
  };
69165
69360
  var findHandle = (tools, toolId) => tools.find((tool) => tool.toolId === toolId || tool.toolId.length === 0 && tool.name === toolId);
69166
- var toolInvokeNode = defineReactiveNode34({
69361
+ var toolInvokeNode = defineReactiveNode35({
69167
69362
  type: "common-tool-invoke",
69168
69363
  displayName: "Tool invoke",
69169
69364
  category: "Tools",
@@ -69179,7 +69374,7 @@ Typical uses:
69179
69374
  let lastCallKey;
69180
69375
  const tools = makeInput("tools", {
69181
69376
  name: "tools",
69182
- wireType: TOOL_HANDLE_WIRE_TYPE7,
69377
+ wireType: TOOL_HANDLE_WIRE_TYPE8,
69183
69378
  required: true
69184
69379
  });
69185
69380
  const toolId = makeInput("toolId", {
@@ -69226,7 +69421,7 @@ Typical uses:
69226
69421
  return throwError10(() => new Error(`Tool \xAB${payload.toolId}\xBB is not in the wired inventory.`));
69227
69422
  }
69228
69423
  lastCallKey = callKey;
69229
- return of14({
69424
+ return of15({
69230
69425
  handle,
69231
69426
  args: parsed.args,
69232
69427
  projectDir: payload.projectDir,
@@ -69249,7 +69444,7 @@ Typical uses:
69249
69444
  });
69250
69445
 
69251
69446
  // packages/common-nodes/dist/embeddings/embed-text/node.js
69252
- import { defineReactiveNode as defineReactiveNode35, withLoading as withLoading12 } from "@langflower/node-sdk";
69447
+ import { defineReactiveNode as defineReactiveNode36, withLoading as withLoading12 } from "@langflower/node-sdk";
69253
69448
  import { map as map20, switchMap as switchMap11 } from "rxjs";
69254
69449
 
69255
69450
  // packages/common-nodes/dist/embeddings/from-embedding.js
@@ -69307,7 +69502,7 @@ var formatEmbedPreview = (dim, vector) => {
69307
69502
  const suffix = vector.length > PREVIEW_FLOATS ? ", \u2026" : "";
69308
69503
  return `dim=${dim} [${shown.join(", ")}${suffix}]`;
69309
69504
  };
69310
- var embedTextNode = defineReactiveNode35({
69505
+ var embedTextNode = defineReactiveNode36({
69311
69506
  type: "common-embed-text",
69312
69507
  displayName: "Embed text",
69313
69508
  category: "Embeddings",
@@ -69365,7 +69560,7 @@ Typical uses:
69365
69560
  });
69366
69561
 
69367
69562
  // packages/common-nodes/dist/embeddings/embed-similarity/node.js
69368
- import { defineReactiveNode as defineReactiveNode36 } from "@langflower/node-sdk";
69563
+ import { defineReactiveNode as defineReactiveNode37 } from "@langflower/node-sdk";
69369
69564
  var toNumberVector = (value, label) => {
69370
69565
  if (!Array.isArray(value)) {
69371
69566
  throw new Error(`${label} must be a JSON number array`);
@@ -69408,7 +69603,7 @@ var cosineSimilarity = (left, right) => {
69408
69603
  }
69409
69604
  return sum;
69410
69605
  };
69411
- var embedSimilarityNode = defineReactiveNode36({
69606
+ var embedSimilarityNode = defineReactiveNode37({
69412
69607
  type: "common-embed-similarity",
69413
69608
  displayName: "Embed similarity",
69414
69609
  category: "Embeddings",
@@ -69444,7 +69639,7 @@ Typical uses:
69444
69639
  });
69445
69640
 
69446
69641
  // packages/common-nodes/dist/embeddings/embed-provider/node.js
69447
- import { defineReactiveNode as defineReactiveNode37, withLoading as withLoading13, EMBED_HANDLE_WIRE_TYPE } from "@langflower/node-sdk";
69642
+ import { defineReactiveNode as defineReactiveNode38, withLoading as withLoading13, EMBED_HANDLE_WIRE_TYPE } from "@langflower/node-sdk";
69448
69643
  import { distinctUntilChanged as distinctUntilChanged3, map as map21, switchMap as switchMap12 } from "rxjs";
69449
69644
  var embedPanelUiSchema2 = [
69450
69645
  {
@@ -69513,7 +69708,7 @@ var buildEmbedHandle = (options) => {
69513
69708
  }
69514
69709
  };
69515
69710
  };
69516
- var embedProviderNode = defineReactiveNode37({
69711
+ var embedProviderNode = defineReactiveNode38({
69517
69712
  type: "common-embed-provider",
69518
69713
  displayName: "Embed provider",
69519
69714
  category: "Embeddings",
@@ -69684,7 +69879,7 @@ async function buildSessionBootstrap(session, langflowerConfigService, resolveDe
69684
69879
  }
69685
69880
 
69686
69881
  // packages/server/dist/workflow/apply-editor-mutation.js
69687
- import { of as of15 } from "rxjs";
69882
+ import { of as of16 } from "rxjs";
69688
69883
 
69689
69884
  // packages/server/dist/workflow/workflow-persisted-inputs.js
69690
69885
  var valuesEqual = (left, right) => JSON.stringify(left) === JSON.stringify(right);
@@ -69859,7 +70054,7 @@ var materializeRuntimeNode = (projectDir, node, resolveDefinition) => {
69859
70054
  continue;
69860
70055
  }
69861
70056
  if (Object.hasOwn(node.inputs, config.portId)) {
69862
- input.connect(of15(node.inputs[config.portId]));
70057
+ input.connect(of16(node.inputs[config.portId]));
69863
70058
  continue;
69864
70059
  }
69865
70060
  if (config.defaultValue === void 0) {
@@ -69868,7 +70063,7 @@ var materializeRuntimeNode = (projectDir, node, resolveDefinition) => {
69868
70063
  if (config.defaultValue === null) {
69869
70064
  continue;
69870
70065
  }
69871
- input.connect(of15(config.defaultValue));
70066
+ input.connect(of16(config.defaultValue));
69872
70067
  }
69873
70068
  return {
69874
70069
  nodeId: node.id,
@@ -77207,6 +77402,9 @@ var emitBootstrap = async (client, context, session, checkpoints, draftControlle
77207
77402
  for (const ask of session.permissionAsks.list()) {
77208
77403
  clientEmit(client, "runner.permission.ask", ask);
77209
77404
  }
77405
+ for (const ask of session.askUserAsks.list()) {
77406
+ clientEmit(client, "runner.askUser.ask", ask);
77407
+ }
77210
77408
  const paletteResult = await context.paletteService.reload(context.projectDir);
77211
77409
  clientEmit(client, "palette.snapshot", paletteResult.payload);
77212
77410
  const customSnapshot = context.customPaletteService.getSnapshot();
@@ -78049,7 +78247,8 @@ var createToolHarness = (options) => {
78049
78247
  ...options.config.harness?.denyPaths !== void 0 ? { denyPaths: options.config.harness.denyPaths } : {},
78050
78248
  ...options.config.harness?.allowedRoots !== void 0 ? { allowedRoots: options.config.harness.allowedRoots } : {},
78051
78249
  ...hasPermissionRules ? { permission: options.permission } : {},
78052
- ...options.requestPermission !== void 0 ? { requestPermission: options.requestPermission } : {}
78250
+ ...options.requestPermission !== void 0 ? { requestPermission: options.requestPermission } : {},
78251
+ ...options.askUser !== void 0 ? { askUser: options.askUser } : {}
78053
78252
  });
78054
78253
  };
78055
78254
  var LIVE_WIRED_TOOLS_NODE_TYPES = /* @__PURE__ */ new Set([
@@ -78076,7 +78275,8 @@ var buildExecutionContext = async (context, runId, node, hooks, preloadedConfig,
78076
78275
  projectRoot: context.projectDir,
78077
78276
  config,
78078
78277
  permission,
78079
- requestPermission: (request) => hooks.requestPermission(hooks.runId, hooks.nodeId, request, hooks.emitPermissionAsk)
78278
+ requestPermission: (request) => hooks.requestPermission(hooks.runId, hooks.nodeId, request, hooks.emitPermissionAsk),
78279
+ askUser: (request) => hooks.requestAskUser(hooks.runId, hooks.nodeId, request, hooks.emitAskUserAsk)
78080
78280
  });
78081
78281
  const webFetch = createWebFetch({
78082
78282
  ...config.harness?.allowedHosts !== void 0 ? { allowedHosts: config.harness.allowedHosts } : {}
@@ -78160,7 +78360,7 @@ var applyObservableContextSeeds = (session, seeds) => {
78160
78360
  }
78161
78361
  return valueSeeds;
78162
78362
  };
78163
- var buildContextSeeds = async (session, context, runId, emitPermissionAsk, requestLangflowerBus, getLiveWiredTools2) => {
78363
+ var buildContextSeeds = async (session, context, runId, emitPermissionAsk, emitAskUserAsk, requestLangflowerBus, getLiveWiredTools2) => {
78164
78364
  const workflow = session.activeWorkflow;
78165
78365
  if (workflow === null) {
78166
78366
  return {};
@@ -78197,6 +78397,8 @@ var buildContextSeeds = async (session, context, runId, emitPermissionAsk, reque
78197
78397
  nodeId: node.id,
78198
78398
  requestPermission: session.permissionAsks.requestPermission,
78199
78399
  emitPermissionAsk,
78400
+ requestAskUser: session.askUserAsks.requestAskUser,
78401
+ emitAskUserAsk,
78200
78402
  ...requestLangflowerBus !== void 0 ? { requestLangflowerBus } : {},
78201
78403
  ...getLiveWiredTools2 !== void 0 ? { getLiveWiredTools: getLiveWiredTools2 } : {}
78202
78404
  }, config, runMcp?.handles, secrets);
@@ -78269,6 +78471,9 @@ var wireRunnerHandlers = (bridge, context, session, checkpoints) => {
78269
78471
  const emitPermissionAsk = (payload) => {
78270
78472
  bridgeEmit(bridge, "runner.permission.ask", payload);
78271
78473
  };
78474
+ const emitAskUserAsk = (payload) => {
78475
+ bridgeEmit(bridge, "runner.askUser.ask", payload);
78476
+ };
78272
78477
  const requestLangflowerBus = createLangflowerToolsRpc(bridge);
78273
78478
  const liveWiredTools = (agentNodeId) => getLiveWiredTools(session, agentNodeId);
78274
78479
  subscription.add(session.runtime.runner.events$.subscribe((event) => {
@@ -78304,7 +78509,7 @@ var wireRunnerHandlers = (bridge, context, session, checkpoints) => {
78304
78509
  const [clientInitialPayload, clientRunId] = raw.payload;
78305
78510
  const resolvedRunId = clientRunId ?? crypto.randomUUID();
78306
78511
  session.runnerStatus = "running";
78307
- const contextSeeds = applyObservableContextSeeds(session, await buildContextSeeds(session, context, resolvedRunId, emitPermissionAsk, requestLangflowerBus, liveWiredTools));
78512
+ const contextSeeds = applyObservableContextSeeds(session, await buildContextSeeds(session, context, resolvedRunId, emitPermissionAsk, emitAskUserAsk, requestLangflowerBus, liveWiredTools));
78308
78513
  const initialPayload = mergeSeeds(contextSeeds, clientInitialPayload);
78309
78514
  if (session.activeWorkflow !== null) {
78310
78515
  checkpoints.beginRun(resolvedRunId, session.activeWorkflow);
@@ -78331,7 +78536,7 @@ var wireRunnerHandlers = (bridge, context, session, checkpoints) => {
78331
78536
  const [nodeId, clientInitialPayload, clientRunId] = raw.payload;
78332
78537
  const resolvedRunId = clientRunId ?? crypto.randomUUID();
78333
78538
  session.runnerStatus = "running";
78334
- const contextSeeds = applyObservableContextSeeds(session, await buildContextSeeds(session, context, resolvedRunId, emitPermissionAsk, requestLangflowerBus, liveWiredTools));
78539
+ const contextSeeds = applyObservableContextSeeds(session, await buildContextSeeds(session, context, resolvedRunId, emitPermissionAsk, emitAskUserAsk, requestLangflowerBus, liveWiredTools));
78335
78540
  const initialPayload = mergeSeeds(contextSeeds, clientInitialPayload);
78336
78541
  if (session.activeWorkflow !== null) {
78337
78542
  checkpoints.beginRun(resolvedRunId, session.activeWorkflow);
@@ -78410,7 +78615,7 @@ var wireRunnerHandlers = (bridge, context, session, checkpoints) => {
78410
78615
  return;
78411
78616
  }
78412
78617
  session.runnerStatus = "running";
78413
- const contextSeeds = applyObservableContextSeeds(session, await buildContextSeeds(session, context, checkpoint.runId, emitPermissionAsk, requestLangflowerBus, liveWiredTools));
78618
+ const contextSeeds = applyObservableContextSeeds(session, await buildContextSeeds(session, context, checkpoint.runId, emitPermissionAsk, emitAskUserAsk, requestLangflowerBus, liveWiredTools));
78414
78619
  checkpoints.hydrateFromCheckpoint(checkpoint, workflow);
78415
78620
  const resumeOptions = checkpoints.resumeOptionsFromCheckpoint(checkpoint);
78416
78621
  const resumed = session.runtime.runner.resume({
@@ -78459,7 +78664,7 @@ var wireRunnerHandlers = (bridge, context, session, checkpoints) => {
78459
78664
  if (wasIdle) {
78460
78665
  const resolvedRunId = crypto.randomUUID();
78461
78666
  session.runnerStatus = "running";
78462
- const contextSeeds = applyObservableContextSeeds(session, await buildContextSeeds(session, context, resolvedRunId, emitPermissionAsk, requestLangflowerBus, liveWiredTools));
78667
+ const contextSeeds = applyObservableContextSeeds(session, await buildContextSeeds(session, context, resolvedRunId, emitPermissionAsk, emitAskUserAsk, requestLangflowerBus, liveWiredTools));
78463
78668
  if (session.activeWorkflow !== null) {
78464
78669
  checkpoints.beginRun(resolvedRunId, session.activeWorkflow);
78465
78670
  }
@@ -78487,6 +78692,18 @@ var wireRunnerHandlers = (bridge, context, session, checkpoints) => {
78487
78692
  bridgeEmit(bridge, "runner.permission.accepted", raw.payload);
78488
78693
  }
78489
78694
  }));
78695
+ subscription.add(bridge["runner.askUser.reply"].subscribe((raw) => {
78696
+ if (!isInboundEvent(raw)) {
78697
+ return;
78698
+ }
78699
+ const connected = findClientById(bridge, raw.clientId);
78700
+ if (connected === void 0) {
78701
+ return;
78702
+ }
78703
+ if (session.askUserAsks.reply(raw.payload)) {
78704
+ bridgeEmit(bridge, "runner.askUser.accepted", raw.payload);
78705
+ }
78706
+ }));
78490
78707
  subscription.add(bridge["runner.executionFeed.clear.requested"].subscribe((raw) => {
78491
78708
  if (!isInboundEvent(raw)) {
78492
78709
  return;
@@ -80221,7 +80438,7 @@ var registerStartCommand = (program2) => {
80221
80438
  // packages/cli/dist/cli.js
80222
80439
  var registerEvalCommand = (program2) => {
80223
80440
  program2.command("eval").description("Run a golden / fixture eval pack and fail closed when score < threshold").argument("<pack-dir>", "Directory containing pack.json").option("--project <dir>", "Project root for harness path fence (default: pack-dir)").option("--replay <file>", "JSON map of caseId \u2192 agent output (optional offline / CI agent)").action(async (packDirArg, opts) => {
80224
- const { runEvalCommand } = await import("./chunk-526FJL62.js");
80441
+ const { runEvalCommand } = await import("./chunk-AO33IM2J.js");
80225
80442
  await runEvalCommand(packDirArg, opts);
80226
80443
  });
80227
80444
  };