@cognipeer/agent-sdk 0.6.5 → 0.6.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -743,6 +743,7 @@ function createResolverNode() {
743
743
  toolHistory: state.toolHistory || [],
744
744
  toolHistoryArchived: state.toolHistoryArchived || [],
745
745
  pendingApprovals: state.pendingApprovals || [],
746
+ pendingUserQuestions: state.pendingUserQuestions || [],
746
747
  plan: state.plan || null,
747
748
  planVersion: state.planVersion || 0
748
749
  };
@@ -2584,13 +2585,16 @@ function createToolsNode(initialTools, opts) {
2584
2585
  const traceSession = state.ctx?.__traceSession;
2585
2586
  const pendingApprovals = Array.isArray(state.pendingApprovals) ? state.pendingApprovals.map((entry) => ({ ...entry })) : [];
2586
2587
  const pendingByCallId = new Map(pendingApprovals.map((entry) => [entry.toolCallId, entry]));
2588
+ const pendingUserQuestions = Array.isArray(state.pendingUserQuestions) ? state.pendingUserQuestions.map((entry) => ({ ...entry })) : [];
2587
2589
  let awaitingApproval = false;
2590
+ let awaitingUserQuestion = false;
2588
2591
  for (const tool of toolByName.values()) {
2589
2592
  const anyTool = tool;
2590
2593
  if (anyTool._stateRef && typeof anyTool._stateRef === "object") {
2591
2594
  anyTool._stateRef.toolHistory = state.toolHistory;
2592
2595
  anyTool._stateRef.toolHistoryArchived = state.toolHistoryArchived;
2593
2596
  anyTool._stateRef.pendingApprovals = pendingApprovals;
2597
+ anyTool._stateRef.pendingUserQuestions = pendingUserQuestions;
2594
2598
  anyTool._stateRef.messages = state.messages;
2595
2599
  anyTool._stateRef.ctx = state.ctx || (state.ctx = {});
2596
2600
  anyTool._stateRef.__onEvent = onEvent;
@@ -2664,6 +2668,7 @@ function createToolsNode(initialTools, opts) {
2664
2668
  const toolStateRef = tool._stateRef && typeof tool._stateRef === "object" ? tool._stateRef : null;
2665
2669
  if (toolStateRef) {
2666
2670
  toolStateRef.pendingApprovals = pendingApprovals;
2671
+ toolStateRef.pendingUserQuestions = pendingUserQuestions;
2667
2672
  toolStateRef.ctx = state.ctx || (state.ctx = {});
2668
2673
  toolStateRef.__currentToolCallId = toolCallId;
2669
2674
  delete toolStateRef.__awaitingApproval;
@@ -2875,6 +2880,22 @@ function createToolsNode(initialTools, opts) {
2875
2880
  approval: pendingApproval
2876
2881
  };
2877
2882
  }
2883
+ if (output && typeof output === "object" && output.__awaitingUserQuestion) {
2884
+ if (toolStateRef?.ctx && typeof toolStateRef.ctx === "object") {
2885
+ state.ctx = toolStateRef.ctx;
2886
+ }
2887
+ const pendingQuestion = pendingUserQuestions.find(
2888
+ (entry) => entry.toolCallId === output.toolCallId || entry.id === output.id
2889
+ );
2890
+ if (!pendingQuestion) {
2891
+ throw new Error(`Tool ${toolName} requested a user question but no pending question entry was recorded.`);
2892
+ }
2893
+ awaitingUserQuestion = true;
2894
+ return {
2895
+ status: "awaiting_user_question",
2896
+ userQuestion: pendingQuestion
2897
+ };
2898
+ }
2878
2899
  if (output && typeof output === "object" && output.__finalStructuredOutput) {
2879
2900
  if (!state.ctx) state.ctx = {};
2880
2901
  state.ctx.__structuredOutputParsed = output.data;
@@ -3012,15 +3033,19 @@ function createToolsNode(initialTools, opts) {
3012
3033
  return false;
3013
3034
  };
3014
3035
  for (const idx of approvalIndices) {
3015
- if (awaitingApproval || shouldStop) break;
3036
+ if (awaitingApproval || awaitingUserQuestion || shouldStop) break;
3016
3037
  if (checkCancellationStop()) break;
3017
3038
  const result = await runOne(planned[idx], orderedSlots[idx]);
3018
3039
  if (result.status === "awaiting_approval") {
3019
3040
  awaitingApproval = true;
3020
3041
  break;
3021
3042
  }
3043
+ if (result.status === "awaiting_user_question") {
3044
+ awaitingUserQuestion = true;
3045
+ break;
3046
+ }
3022
3047
  }
3023
- if (!awaitingApproval && !shouldStop && parallelIndices.length > 0) {
3048
+ if (!awaitingApproval && !awaitingUserQuestion && !shouldStop && parallelIndices.length > 0) {
3024
3049
  const concurrency = Math.max(1, Math.min(limits.maxParallelTools, parallelIndices.length));
3025
3050
  let cursor = 0;
3026
3051
  const workerError = {};
@@ -3028,7 +3053,7 @@ function createToolsNode(initialTools, opts) {
3028
3053
  for (let w = 0; w < concurrency; w++) {
3029
3054
  workers.push((async () => {
3030
3055
  while (true) {
3031
- if (workerError.err || shouldStop || awaitingApproval) return;
3056
+ if (workerError.err || shouldStop || awaitingApproval || awaitingUserQuestion) return;
3032
3057
  const i = cursor++;
3033
3058
  if (i >= parallelIndices.length) return;
3034
3059
  if (checkCancellationStop()) return;
@@ -3039,6 +3064,10 @@ function createToolsNode(initialTools, opts) {
3039
3064
  awaitingApproval = true;
3040
3065
  return;
3041
3066
  }
3067
+ if (result.status === "awaiting_user_question") {
3068
+ awaitingUserQuestion = true;
3069
+ return;
3070
+ }
3042
3071
  } catch (err) {
3043
3072
  workerError.err = err;
3044
3073
  return;
@@ -3101,11 +3130,12 @@ function createToolsNode(initialTools, opts) {
3101
3130
  toolCache: state.toolCache,
3102
3131
  // Explicitly propagate ctx so callers using `{ ...state, ...delta }`
3103
3132
  // do not silently capture a stale ctx reference. Mutations to
3104
- // __summarizationExhausted / __awaitingApproval / __structuredOutputParsed
3105
- // are made on this object during execution.
3133
+ // __summarizationExhausted / __awaitingApproval / __awaitingUserQuestion /
3134
+ // __structuredOutputParsed are made on this object during execution.
3106
3135
  ctx: state.ctx,
3107
3136
  agent: state.agent,
3108
- pendingApprovals
3137
+ pendingApprovals,
3138
+ pendingUserQuestions
3109
3139
  };
3110
3140
  };
3111
3141
  }
@@ -3571,6 +3601,226 @@ function resolveToolApprovalState(state, resolution) {
3571
3601
  };
3572
3602
  }
3573
3603
 
3604
+ // src/utils/userQuestions.ts
3605
+ var cloneQuestions = (questions) => Array.isArray(questions) ? questions.map((entry) => ({ ...entry })) : [];
3606
+ function validateAnswers(entry, answers, cancelled) {
3607
+ if (cancelled) {
3608
+ return answers || {};
3609
+ }
3610
+ const allowFreeText = entry.allowFreeText !== false;
3611
+ const out = {};
3612
+ const provided = answers || {};
3613
+ for (const question of entry.questions) {
3614
+ const required = question.required !== false;
3615
+ const key = question.question;
3616
+ const answer = provided[key] ?? provided[question.header || ""];
3617
+ if (!answer) {
3618
+ if (required) {
3619
+ throw new Error(`Missing answer for required question: "${key}".`);
3620
+ }
3621
+ continue;
3622
+ }
3623
+ const values = Array.isArray(answer.values) ? answer.values.filter((v) => typeof v === "string") : [];
3624
+ const freeText = typeof answer.freeText === "string" ? answer.freeText.trim() : "";
3625
+ const notes = typeof answer.notes === "string" ? answer.notes : void 0;
3626
+ if (freeText && !allowFreeText) {
3627
+ throw new Error(
3628
+ `Free-text answers are disabled for this agent (question: "${key}"). Pick one of the provided options.`
3629
+ );
3630
+ }
3631
+ if (values.length === 0 && !freeText) {
3632
+ if (required) {
3633
+ throw new Error(`Question "${key}" requires either a selected option or free-text answer.`);
3634
+ }
3635
+ continue;
3636
+ }
3637
+ if (values.length > 1 && !question.multiSelect) {
3638
+ throw new Error(`Question "${key}" is single-select but received multiple values.`);
3639
+ }
3640
+ if (Array.isArray(question.options) && question.options.length > 0 && values.length > 0) {
3641
+ const allowedValues = new Set(
3642
+ question.options.map((option) => option.value ?? option.label)
3643
+ );
3644
+ for (const value of values) {
3645
+ if (!allowedValues.has(value)) {
3646
+ if (!allowFreeText) {
3647
+ throw new Error(
3648
+ `Value "${value}" is not one of the allowed options for question "${key}".`
3649
+ );
3650
+ }
3651
+ }
3652
+ }
3653
+ }
3654
+ out[key] = { values, ...freeText ? { freeText } : {}, ...notes ? { notes } : {} };
3655
+ }
3656
+ return out;
3657
+ }
3658
+ function buildToolResponseContent(entry, answers, cancelled, notes) {
3659
+ if (cancelled) {
3660
+ return JSON.stringify({
3661
+ status: "cancelled",
3662
+ message: notes || "User dismissed the question without answering."
3663
+ });
3664
+ }
3665
+ const payload = {
3666
+ status: "answered",
3667
+ answers: entry.questions.map((question) => {
3668
+ const key = question.question;
3669
+ const ans = answers[key];
3670
+ return {
3671
+ question: key,
3672
+ header: question.header,
3673
+ values: ans?.values ?? [],
3674
+ freeText: ans?.freeText,
3675
+ notes: ans?.notes
3676
+ };
3677
+ }),
3678
+ ...notes ? { reviewerNotes: notes } : {}
3679
+ };
3680
+ return JSON.stringify(payload);
3681
+ }
3682
+ function resolveUserQuestionState(state, resolution) {
3683
+ const pending = cloneQuestions(state.pendingUserQuestions);
3684
+ const matchIndex = pending.findIndex(
3685
+ (entry2) => entry2.id === resolution.id || entry2.toolCallId === resolution.id
3686
+ );
3687
+ if (matchIndex === -1) {
3688
+ throw new Error(`Pending user question not found for id: ${resolution.id}`);
3689
+ }
3690
+ const entry = { ...pending[matchIndex] };
3691
+ if (entry.status === "answered" || entry.status === "executed" || entry.status === "cancelled") {
3692
+ throw new Error(`User question ${entry.id} already resolved (status: ${entry.status}).`);
3693
+ }
3694
+ const cancelled = resolution.cancelled === true;
3695
+ const validated = validateAnswers(entry, resolution.answers, cancelled);
3696
+ entry.status = cancelled ? "cancelled" : "answered";
3697
+ entry.answers = validated;
3698
+ entry.cancelled = cancelled || void 0;
3699
+ entry.answeredBy = resolution.answeredBy;
3700
+ entry.notes = resolution.notes;
3701
+ entry.answeredAt = (/* @__PURE__ */ new Date()).toISOString();
3702
+ pending[matchIndex] = entry;
3703
+ const ctx = { ...state.ctx || {} };
3704
+ delete ctx.__awaitingUserQuestion;
3705
+ if (ctx.__resumeStage === "tools") {
3706
+ delete ctx.__resumeStage;
3707
+ }
3708
+ ctx.__userQuestionResolved = { id: entry.id, status: entry.status };
3709
+ const toolMessage = {
3710
+ role: "tool",
3711
+ name: "ask_user_question",
3712
+ tool_call_id: entry.toolCallId,
3713
+ content: buildToolResponseContent(entry, validated, cancelled, resolution.notes)
3714
+ };
3715
+ return {
3716
+ ...state,
3717
+ pendingUserQuestions: pending,
3718
+ messages: [...state.messages || [], toolMessage],
3719
+ ctx
3720
+ };
3721
+ }
3722
+ var DEFAULT_DESCRIPTION_WITH_FREETEXT = "Pause the agent and surface a structured prompt to the human user when you genuinely cannot proceed without their input. Group up to 4 closely related questions into a single call. Prefer concrete options the user can pick over open-ended free-text \u2014 list `options` whenever you can anticipate the choices. The user may type a custom answer for any question. Do not use this tool for things you can deduce from the conversation, the system prompt, or another tool. After the user answers, their selections come back as the tool result.";
3723
+ var DEFAULT_DESCRIPTION_NO_FREETEXT = "Pause the agent and surface a structured multi-choice prompt to the human user when you genuinely cannot proceed without their input. Group up to 4 closely related questions into a single call. Every question MUST include at least two `options` \u2014 free-text answers are disabled for this agent. Do not use this tool for things you can deduce from the conversation, the system prompt, or another tool. After the user picks, their selections come back as the tool result.";
3724
+ function buildOptionSchema() {
3725
+ return z.object({
3726
+ label: z.string().min(1).describe("Display text the user sees"),
3727
+ value: z.string().min(1).optional().describe("Value returned in the answer; defaults to label"),
3728
+ description: z.string().optional(),
3729
+ preview: z.string().optional().describe("Optional code / ASCII preview rendered when this option is focused")
3730
+ }).strict();
3731
+ }
3732
+ function buildQuestionSchema(allowFreeText) {
3733
+ const optionSchema = buildOptionSchema();
3734
+ const baseShape = {
3735
+ question: z.string().min(1).describe("Full question shown to the user"),
3736
+ header: z.string().max(40).optional().describe("Short chip / tag rendered next to the question (max ~12 chars recommended)"),
3737
+ multiSelect: z.boolean().optional().describe("Allow multiple selections. Default: false"),
3738
+ placeholder: z.string().optional(),
3739
+ required: z.boolean().optional().describe("Default: true")
3740
+ };
3741
+ if (allowFreeText) {
3742
+ return z.object({
3743
+ ...baseShape,
3744
+ options: z.array(optionSchema).min(2).max(12).optional()
3745
+ }).strict();
3746
+ }
3747
+ return z.object({
3748
+ ...baseShape,
3749
+ options: z.array(optionSchema).min(2).max(12).describe("Required: free-text answers are disabled for this agent")
3750
+ }).strict();
3751
+ }
3752
+ function createAskUserQuestionTool(stateRef, config) {
3753
+ const allowFreeText = config.allowFreeText !== false;
3754
+ const description = config.promptOverride ?? (allowFreeText ? DEFAULT_DESCRIPTION_WITH_FREETEXT : DEFAULT_DESCRIPTION_NO_FREETEXT);
3755
+ const questionSchema = buildQuestionSchema(allowFreeText);
3756
+ const askUser = createTool({
3757
+ name: "ask_user_question",
3758
+ description,
3759
+ schema: z.object({
3760
+ questions: z.array(questionSchema).min(1).max(4).describe("1-4 related questions to ask in a single pause.")
3761
+ }).strict(),
3762
+ func: async ({ questions }) => {
3763
+ const ref = askUser._stateRef || (askUser._stateRef = {});
3764
+ const onEvent = ref.__onEvent;
3765
+ if (!ref.ctx) ref.ctx = {};
3766
+ const ctx = ref.ctx;
3767
+ const toolCallId = ref.__currentToolCallId || `ask_user_${nanoid(6)}`;
3768
+ if (!ref.pendingUserQuestions) ref.pendingUserQuestions = [];
3769
+ const pendingList = ref.pendingUserQuestions;
3770
+ const entry = {
3771
+ id: nanoid(),
3772
+ toolCallId,
3773
+ toolName: "ask_user_question",
3774
+ questions,
3775
+ status: "pending",
3776
+ requestedAt: (/* @__PURE__ */ new Date()).toISOString(),
3777
+ allowFreeText
3778
+ };
3779
+ pendingList.push(entry);
3780
+ ctx.__awaitingUserQuestion = {
3781
+ id: entry.id,
3782
+ toolCallId: entry.toolCallId,
3783
+ requestedAt: entry.requestedAt
3784
+ };
3785
+ ctx.__resumeStage = "tools";
3786
+ onEvent?.({
3787
+ type: "user_question",
3788
+ status: "pending",
3789
+ id: entry.id,
3790
+ toolCallId: entry.toolCallId,
3791
+ questions: entry.questions,
3792
+ allowFreeText
3793
+ });
3794
+ recordTraceEvent(ctx.__traceSession, {
3795
+ type: "user_question",
3796
+ label: "Ask User",
3797
+ actor: { scope: "agent", name: "ask_user_question", role: "user_interaction" },
3798
+ status: "success",
3799
+ sections: [
3800
+ {
3801
+ kind: "metadata",
3802
+ label: "Pending Question",
3803
+ data: {
3804
+ id: entry.id,
3805
+ toolCallId: entry.toolCallId,
3806
+ questions: entry.questions,
3807
+ allowFreeText
3808
+ }
3809
+ }
3810
+ ]
3811
+ });
3812
+ return {
3813
+ __awaitingUserQuestion: true,
3814
+ id: entry.id,
3815
+ toolCallId: entry.toolCallId
3816
+ };
3817
+ }
3818
+ });
3819
+ askUser._stateRef = stateRef;
3820
+ askUser.__source = "human-in-the-loop";
3821
+ return askUser;
3822
+ }
3823
+
3574
3824
  // src/agent.ts
3575
3825
  init_utilTokens();
3576
3826
 
@@ -3782,6 +4032,21 @@ function createAgent(opts) {
3782
4032
  const resolver = createResolverNode();
3783
4033
  const agentCore = createAgentCoreNode(opts);
3784
4034
  const toolsBase = [...opts.tools ?? []];
4035
+ const askUserConfig = (() => {
4036
+ const raw = opts.humanInTheLoop?.askUser;
4037
+ if (!raw) return void 0;
4038
+ if (raw === true) return { enabled: true, allowFreeText: true };
4039
+ return {
4040
+ enabled: true,
4041
+ allowFreeText: raw.allowFreeText !== false,
4042
+ promptOverride: raw.promptOverride
4043
+ };
4044
+ })();
4045
+ const askUserOnQuestion = typeof opts.humanInTheLoop?.askUser === "object" ? opts.humanInTheLoop?.askUser?.onQuestion : void 0;
4046
+ const askUserStateRef = askUserConfig ? { pendingUserQuestions: void 0, ctx: void 0, __onEvent: void 0, __currentToolCallId: void 0 } : void 0;
4047
+ if (askUserConfig && askUserStateRef) {
4048
+ toolsBase.push(createAskUserQuestionTool(askUserStateRef, askUserConfig));
4049
+ }
3785
4050
  const soManager = opts.outputSchema ? new StructuredOutputManager(opts.outputSchema, resolveStrategy(opts.model)) : void 0;
3786
4051
  if (soManager) {
3787
4052
  const modelCapabilities = getModelCapabilities(opts.model);
@@ -3826,7 +4091,8 @@ function createAgent(opts) {
3826
4091
  useTodoList: void 0,
3827
4092
  outputSchema: opts.outputSchema,
3828
4093
  responseFormat: soManager?.getResponseFormat(),
3829
- tracing: opts.tracing
4094
+ tracing: opts.tracing,
4095
+ humanInTheLoop: askUserConfig ? { askUser: askUserConfig } : void 0
3830
4096
  };
3831
4097
  const summarizationThreshold = getActiveSummarizationThreshold(opts);
3832
4098
  async function runLoop(initial, config, emit) {
@@ -4116,6 +4382,7 @@ function createAgent(opts) {
4116
4382
  state = { ...state, ...await toolsNode(state) };
4117
4383
  onProgress?.({ stage: "tools", message: "Tools finished" });
4118
4384
  if (state.ctx?.__awaitingApproval) break;
4385
+ if (state.ctx?.__awaitingUserQuestion) break;
4119
4386
  if (checkpointIfRequested("after_tools")) break;
4120
4387
  if (state.ctx?.__finalizedDueToStructuredOutput) break;
4121
4388
  if (reflectNode && resolvedReasoning?.reflection.enabled) {
@@ -4186,7 +4453,7 @@ function createAgent(opts) {
4186
4453
  }
4187
4454
  const lastAfterLoop = state.messages[state.messages.length - 1];
4188
4455
  if (lastAfterLoop?.role === "tool" && !pausedStage) {
4189
- const isExpectedExit = state.ctx?.__awaitingApproval || state.ctx?.__cancelled || state.ctx?.__finalizedDueToStructuredOutput || state.ctx?.__finalizedDueToToolLimit || state.ctx?.__needsSummarization || state.ctx?.__limitBreached;
4456
+ const isExpectedExit = state.ctx?.__awaitingApproval || state.ctx?.__awaitingUserQuestion || state.ctx?.__cancelled || state.ctx?.__finalizedDueToStructuredOutput || state.ctx?.__finalizedDueToToolLimit || state.ctx?.__needsSummarization || state.ctx?.__limitBreached;
4190
4457
  if (!isExpectedExit) {
4191
4458
  throw new Error(
4192
4459
  "Agent loop terminated with a pending tool response but no subsequent model invocation. This usually indicates a model provider error or exhausted iteration budget."
@@ -4204,7 +4471,17 @@ function createAgent(opts) {
4204
4471
  const { setTokenCounter: setTokenCounter2 } = await Promise.resolve().then(() => (init_utilTokens(), utilTokens_exports));
4205
4472
  setTokenCounter2(userTokenCounter);
4206
4473
  }
4207
- const onEvent = config?.onEvent;
4474
+ const callerOnEvent = config?.onEvent;
4475
+ const onEvent = askUserOnQuestion ? (event) => {
4476
+ if (event && event.type === "user_question") {
4477
+ try {
4478
+ askUserOnQuestion(event);
4479
+ } catch (err) {
4480
+ console.warn("[agent-sdk] humanInTheLoop.askUser.onQuestion error:", err);
4481
+ }
4482
+ }
4483
+ callerOnEvent?.(event);
4484
+ } : callerOnEvent;
4208
4485
  const onProgress = config?.onProgress;
4209
4486
  const onStream = config?.onStream;
4210
4487
  const streamEnabled = config?.stream === true;
@@ -4248,6 +4525,7 @@ function createAgent(opts) {
4248
4525
  metadata: input.metadata,
4249
4526
  ctx,
4250
4527
  pendingApprovals: input.pendingApprovals || [],
4528
+ pendingUserQuestions: input.pendingUserQuestions || [],
4251
4529
  agent: input.agent || runtimeWithInvokeLimits,
4252
4530
  usage: input.usage || { perRequest: [], totals: {} }
4253
4531
  };
@@ -4324,11 +4602,13 @@ function createAgent(opts) {
4324
4602
  return invokeAgent(restoredState, config);
4325
4603
  };
4326
4604
  const resolveToolApproval = (state, resolution) => resolveToolApprovalState(state, resolution);
4605
+ const resolveUserQuestion = (state, resolution) => resolveUserQuestionState(state, resolution);
4327
4606
  const instance = {
4328
4607
  invoke: invokeAgent,
4329
4608
  snapshot: snapshotState,
4330
4609
  resume: resumeAgent,
4331
4610
  resolveToolApproval,
4611
+ resolveUserQuestion,
4332
4612
  asTool: ({ toolName, description, inputDescription }) => {
4333
4613
  const schema = z.object({ input: z.string().describe(inputDescription || "Input for delegated agent") });
4334
4614
  const delegatedTool = createTool({
@@ -5645,7 +5925,20 @@ function createSmartAgent(opts) {
5645
5925
  const userTools = opts.tools ?? [];
5646
5926
  const factoryStateRef = { toolHistory: void 0, toolHistoryArchived: void 0, todoList: void 0, planVersion: 0, adherenceScore: 0 };
5647
5927
  const factoryContextTools = createContextTools(factoryStateRef, { planningEnabled, includeGetToolResponse: false });
5928
+ const askUserConfig = (() => {
5929
+ const raw = opts.humanInTheLoop?.askUser;
5930
+ if (!raw) return void 0;
5931
+ if (raw === true) return { enabled: true, allowFreeText: true };
5932
+ return {
5933
+ enabled: true,
5934
+ allowFreeText: raw.allowFreeText !== false,
5935
+ promptOverride: raw.promptOverride
5936
+ };
5937
+ })();
5648
5938
  const factoryToolsWithoutRecovery = [...userTools, ...factoryContextTools];
5939
+ if (askUserConfig) {
5940
+ factoryToolsWithoutRecovery.push(createAskUserQuestionTool(factoryStateRef, askUserConfig));
5941
+ }
5649
5942
  const soManagerFactory = opts.outputSchema ? new StructuredOutputManager(opts.outputSchema, resolveStrategy(opts.model)) : void 0;
5650
5943
  const modelCapabilities = opts.outputSchema ? getModelCapabilities(opts.model) : void 0;
5651
5944
  const responseFinalizeTool = soManagerFactory && modelCapabilities?.structuredOutput !== "native" ? soManagerFactory.getResponseTool() : void 0;
@@ -5655,6 +5948,7 @@ function createSmartAgent(opts) {
5655
5948
  const recoveryTool = createGetToolResponseTool(ref);
5656
5949
  const base2 = [...userTools, ...ctxTools];
5657
5950
  if (responseFinalizeTool) base2.push(responseFinalizeTool);
5951
+ if (askUserConfig) base2.push(createAskUserQuestionTool(ref, askUserConfig));
5658
5952
  const without = base2;
5659
5953
  const withRec = [...without, recoveryTool];
5660
5954
  return { stateRef: ref, toolsWithoutRecovery: without, toolsWithRecovery: withRec };
@@ -5839,6 +6133,7 @@ function createSmartAgent(opts) {
5839
6133
  snapshot: base.snapshot,
5840
6134
  resume: base.resume,
5841
6135
  resolveToolApproval: base.resolveToolApproval,
6136
+ resolveUserQuestion: base.resolveUserQuestion,
5842
6137
  asTool: base.asTool,
5843
6138
  asHandoff: base.asHandoff,
5844
6139
  __runtime: base.__runtime
@@ -8141,6 +8436,6 @@ function createProvider(config) {
8141
8436
  }
8142
8437
  }
8143
8438
 
8144
- export { AnthropicProvider, AzureProvider, BaseProvider, BedrockProvider, DEFAULT_PROFILE_CONFIGS, GuardrailPhase, InMemoryMemoryStore, NativeJsonSchemaStrategy, OpenAICompatibleProvider, OpenAIProvider, ProviderError, StructuredOutputManager, ToolBasedStrategy, VertexProvider, agentVerdictRule, buildSystemPrompt, captureSnapshot, codePresenceRule, cognipeerSink, countApproxTokens, countMessagesTokens, createAgent, createAgentNode, createCodeGuardrail, createContextSummarizeNode, createContextTools, createGetToolResponseTool, createGuardrail, createJsonGuardrail, createManageTodoTool, createProvider, createRegexGuardrail, createResolverNode, createSmartAgent, createTool, createToolLimitFinalizeNode, createToolsNode, customCallbackRule, customSink, defaultTokenCounter, emptyUsage, evaluateGuardrails, fileSink, formatZodError, fromLangchainModel, fromLangchainTools, fromNativeProvider, generateSpanId, generateTraceId, getModelCapabilities, getNestedValue, getResolvedSmartConfig, getTokenCounter, hasToolResponseRecoveryReference, httpSink, isSmartModel, jsonSchemaRule, normalizeSmartAgentOptions, otlpSink, readMemoryFacts, regexRule, resolveMemoryStore, resolveStrategy, resolveToolApprovalState, restoreSnapshot, runSmartAgentEvalHarness, setTokenCounter, startStreamingSession, traceSessionToOtlp, withTools, writeSummaryFactsToMemory };
8439
+ export { AnthropicProvider, AzureProvider, BaseProvider, BedrockProvider, DEFAULT_PROFILE_CONFIGS, GuardrailPhase, InMemoryMemoryStore, NativeJsonSchemaStrategy, OpenAICompatibleProvider, OpenAIProvider, ProviderError, StructuredOutputManager, ToolBasedStrategy, VertexProvider, agentVerdictRule, buildSystemPrompt, captureSnapshot, codePresenceRule, cognipeerSink, countApproxTokens, countMessagesTokens, createAgent, createAgentNode, createAskUserQuestionTool, createCodeGuardrail, createContextSummarizeNode, createContextTools, createGetToolResponseTool, createGuardrail, createJsonGuardrail, createManageTodoTool, createProvider, createRegexGuardrail, createResolverNode, createSmartAgent, createTool, createToolLimitFinalizeNode, createToolsNode, customCallbackRule, customSink, defaultTokenCounter, emptyUsage, evaluateGuardrails, fileSink, formatZodError, fromLangchainModel, fromLangchainTools, fromNativeProvider, generateSpanId, generateTraceId, getModelCapabilities, getNestedValue, getResolvedSmartConfig, getTokenCounter, hasToolResponseRecoveryReference, httpSink, isSmartModel, jsonSchemaRule, normalizeSmartAgentOptions, otlpSink, readMemoryFacts, regexRule, resolveMemoryStore, resolveStrategy, resolveToolApprovalState, resolveUserQuestionState, restoreSnapshot, runSmartAgentEvalHarness, setTokenCounter, startStreamingSession, traceSessionToOtlp, withTools, writeSummaryFactsToMemory };
8145
8440
  //# sourceMappingURL=index.mjs.map
8146
8441
  //# sourceMappingURL=index.mjs.map