@tanstack/ai 0.59.0 → 0.63.0
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/README.md +1 -0
- package/dist/esm/activities/chat/adapter.d.ts +9 -0
- package/dist/esm/activities/chat/adapter.js +1 -0
- package/dist/esm/activities/chat/adapter.js.map +1 -1
- package/dist/esm/activities/chat/agents/define-agent.d.ts +17 -5
- package/dist/esm/activities/chat/agents/define-agent.js.map +1 -1
- package/dist/esm/activities/chat/agents/spawn.d.ts +2 -0
- package/dist/esm/activities/chat/agents/spawn.js +8 -5
- package/dist/esm/activities/chat/agents/spawn.js.map +1 -1
- package/dist/esm/activities/chat/index.js +289 -78
- package/dist/esm/activities/chat/index.js.map +1 -1
- package/dist/esm/activities/chat/messages.js +35 -19
- package/dist/esm/activities/chat/messages.js.map +1 -1
- package/dist/esm/activities/chat/middleware/types.d.ts +1 -0
- package/dist/esm/activities/chat/middleware/types.js.map +1 -1
- package/dist/esm/activities/chat/stream/message-updaters.d.ts +2 -2
- package/dist/esm/activities/chat/stream/message-updaters.js +11 -3
- package/dist/esm/activities/chat/stream/message-updaters.js.map +1 -1
- package/dist/esm/activities/chat/stream/processor.d.ts +11 -10
- package/dist/esm/activities/chat/stream/processor.js +51 -28
- package/dist/esm/activities/chat/stream/processor.js.map +1 -1
- package/dist/esm/activities/chat/tools/tool-calls.d.ts +16 -2
- package/dist/esm/activities/chat/tools/tool-calls.js +57 -16
- package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
- package/dist/esm/activities/chat/tools/tool-definition.d.ts +4 -0
- package/dist/esm/activities/chat/tools/tool-definition.js +4 -0
- package/dist/esm/activities/chat/tools/tool-definition.js.map +1 -1
- package/dist/esm/activities/embed/adapter.d.ts +7 -0
- package/dist/esm/activities/embed/adapter.js +1 -0
- package/dist/esm/activities/embed/adapter.js.map +1 -1
- package/dist/esm/activities/embed/index.js +2 -0
- package/dist/esm/activities/embed/index.js.map +1 -1
- package/dist/esm/activities/evaluate/adapter.d.ts +4 -0
- package/dist/esm/activities/evaluate/adapter.js.map +1 -1
- package/dist/esm/activities/evaluate/index.d.ts +4 -0
- package/dist/esm/activities/evaluate/index.js +3 -1
- package/dist/esm/activities/evaluate/index.js.map +1 -1
- package/dist/esm/activities/files/adapter.d.ts +97 -0
- package/dist/esm/activities/files/adapter.js +45 -0
- package/dist/esm/activities/files/adapter.js.map +1 -0
- package/dist/esm/activities/files/index.d.ts +66 -0
- package/dist/esm/activities/files/index.js +78 -0
- package/dist/esm/activities/files/index.js.map +1 -0
- package/dist/esm/activities/generateImage/adapter.d.ts +8 -0
- package/dist/esm/activities/generateImage/adapter.js +1 -0
- package/dist/esm/activities/generateImage/adapter.js.map +1 -1
- package/dist/esm/activities/generateImage/index.js +2 -0
- package/dist/esm/activities/generateImage/index.js.map +1 -1
- package/dist/esm/activities/generateVideo/adapter.d.ts +8 -0
- package/dist/esm/activities/generateVideo/adapter.js +1 -0
- package/dist/esm/activities/generateVideo/adapter.js.map +1 -1
- package/dist/esm/activities/generateVideo/index.js +3 -0
- package/dist/esm/activities/generateVideo/index.js.map +1 -1
- package/dist/esm/activities/generateWorld/adapter.d.ts +4 -2
- package/dist/esm/activities/generateWorld/adapter.js.map +1 -1
- package/dist/esm/activities/generateWorld/index.d.ts +4 -3
- package/dist/esm/activities/generateWorld/index.js +5 -4
- package/dist/esm/activities/generateWorld/index.js.map +1 -1
- package/dist/esm/activities/index.d.ts +6 -3
- package/dist/esm/activities/index.js +13 -11
- package/dist/esm/activities/summarize/chat-stream-summarize.d.ts +2 -0
- package/dist/esm/activities/summarize/chat-stream-summarize.js +8 -8
- package/dist/esm/activities/summarize/chat-stream-summarize.js.map +1 -1
- package/dist/esm/client.d.ts +3 -1
- package/dist/esm/client.js +2 -1
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/index.d.ts +4 -3
- package/dist/esm/index.js +5 -3
- package/dist/esm/interrupt-resume.js +29 -4
- package/dist/esm/interrupt-resume.js.map +1 -1
- package/dist/esm/middlewares/otel.d.ts +5 -2
- package/dist/esm/middlewares/otel.js +114 -0
- package/dist/esm/middlewares/otel.js.map +1 -1
- package/dist/esm/types.d.ts +114 -14
- package/dist/esm/utilities/ag-ui-wire.js +39 -16
- package/dist/esm/utilities/ag-ui-wire.js.map +1 -1
- package/dist/esm/utilities/content-source.d.ts +60 -0
- package/dist/esm/utilities/content-source.js +85 -0
- package/dist/esm/utilities/content-source.js.map +1 -0
- package/dist/esm/utilities/provider-executed.d.ts +7 -0
- package/dist/esm/utilities/provider-executed.js +10 -1
- package/dist/esm/utilities/provider-executed.js.map +1 -1
- package/dist/esm/utilities/tool-result.d.ts +14 -3
- package/dist/esm/utilities/tool-result.js +26 -3
- package/dist/esm/utilities/tool-result.js.map +1 -1
- package/package.json +4 -4
- package/skills/ai-core/adapter-configuration/SKILL.md +62 -0
- package/skills/ai-core/chat-experience/SKILL.md +134 -0
- package/skills/ai-core/media-generation/SKILL.md +8 -0
- package/skills/ai-core/tool-calling/SKILL.md +103 -0
- package/src/activities/chat/adapter.ts +10 -0
- package/src/activities/chat/agents/define-agent.ts +20 -3
- package/src/activities/chat/agents/spawn.ts +20 -12
- package/src/activities/chat/index.ts +458 -99
- package/src/activities/chat/messages.ts +52 -6
- package/src/activities/chat/middleware/types.ts +1 -0
- package/src/activities/chat/stream/message-updaters.ts +27 -2
- package/src/activities/chat/stream/processor.ts +81 -49
- package/src/activities/chat/tools/tool-calls.ts +104 -9
- package/src/activities/chat/tools/tool-definition.ts +8 -0
- package/src/activities/embed/adapter.ts +7 -0
- package/src/activities/embed/index.ts +5 -0
- package/src/activities/evaluate/adapter.ts +4 -0
- package/src/activities/evaluate/index.ts +6 -0
- package/src/activities/files/adapter.ts +120 -0
- package/src/activities/files/index.ts +113 -0
- package/src/activities/generateImage/adapter.ts +8 -0
- package/src/activities/generateImage/index.ts +4 -0
- package/src/activities/generateVideo/adapter.ts +8 -0
- package/src/activities/generateVideo/index.ts +7 -0
- package/src/activities/generateWorld/adapter.ts +4 -2
- package/src/activities/generateWorld/index.ts +7 -6
- package/src/activities/index.ts +25 -1
- package/src/activities/summarize/chat-stream-summarize.ts +22 -12
- package/src/client.ts +8 -0
- package/src/index.ts +17 -0
- package/src/interrupt-resume.ts +55 -4
- package/src/middlewares/otel.ts +161 -3
- package/src/types.ts +114 -14
- package/src/utilities/ag-ui-wire.ts +72 -17
- package/src/utilities/content-source.ts +138 -0
- package/src/utilities/provider-executed.ts +13 -0
- package/src/utilities/tool-result.ts +45 -3
|
@@ -17,12 +17,13 @@ import { hashSchemaInput, normalizeApprovalSchema } from "./tools/approval-schem
|
|
|
17
17
|
import { INTERRUPT_BINDING_METADATA_KEY, InterruptResumeValidationError, readInterruptBinding, readUnopenedInterruptBinding, validateInterruptResumeBatch } from "../../interrupt-resume.js";
|
|
18
18
|
import { INTERRUPT_PAYLOAD_METADATA_KEY, createInterruptBinding, rehydrateInterruptRequest } from "../../interrupt-definition.js";
|
|
19
19
|
import { readGenericInterruptContinuation } from "../../generic-interrupt-continuation.js";
|
|
20
|
-
import { normalizeToolResult } from "../../utilities/tool-result.js";
|
|
21
|
-
import { subagentHostMessageId } from "../../utilities/subagent-wire.js";
|
|
22
20
|
import { isProviderExecutedToolCall } from "../../utilities/provider-executed.js";
|
|
21
|
+
import { normalizeToolResult, parseToolOutput, toolResultErrorText } from "../../utilities/tool-result.js";
|
|
22
|
+
import { subagentHostMessageId } from "../../utilities/subagent-wire.js";
|
|
23
23
|
import { appendUiResourceToModelMessages, convertMessagesToModelMessages, generateMessageId, modelMessagesToUIMessages, safeJsonStringify, uiResourcePartFromCustomValue } from "./messages.js";
|
|
24
24
|
import { uiMessagesToWire } from "../../utilities/ag-ui-wire.js";
|
|
25
25
|
import { restorePublicUsage } from "../../utilities/restore-inbound-chunk.js";
|
|
26
|
+
import { assertMessagesFileSourceSupport } from "../../utilities/content-source.js";
|
|
26
27
|
import { LazyToolManager } from "./tools/lazy-tool-manager.js";
|
|
27
28
|
import { assertUniqueToolNames } from "./tools/unique-tool-names.js";
|
|
28
29
|
import { MiddlewareAbortError, ToolCallManager, executeToolCalls } from "./tools/tool-calls.js";
|
|
@@ -50,12 +51,6 @@ var kind = "text";
|
|
|
50
51
|
var interruptBindingMetadataKey = INTERRUPT_BINDING_METADATA_KEY;
|
|
51
52
|
/** Resume entries a subagent tool call owns. The parent run skips them. */
|
|
52
53
|
var CHILD_RESUME_IDS = Symbol("tanstack.ai.childResumeIds");
|
|
53
|
-
function assertNoFileSources(adapterName, messages) {
|
|
54
|
-
for (const message of messages) {
|
|
55
|
-
if (!Array.isArray(message.content)) continue;
|
|
56
|
-
for (const part of message.content) if ("source" in part && part.source.type === "file") throw new Error(`${adapterName} does not support provider file-handle sources ({ type: 'file' }). Pass a data or url source.`);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
54
|
function isInterruptSubmissionError(value) {
|
|
60
55
|
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
61
56
|
if (!("scope" in value) || !("code" in value) || !("message" in value) || !("source" in value) || !("retryable" in value) || !("threadId" in value) || !("interruptedRunId" in value) || !("generation" in value) || typeof value.code !== "string" || typeof value.message !== "string" || typeof value.retryable !== "boolean" || typeof value.threadId !== "string" || typeof value.interruptedRunId !== "string" || typeof value.generation !== "number") return false;
|
|
@@ -143,6 +138,15 @@ var TextEngine = class {
|
|
|
143
138
|
streamIdentityCaptured = false;
|
|
144
139
|
accumulatedContent = "";
|
|
145
140
|
accumulatedThinking = [];
|
|
141
|
+
/**
|
|
142
|
+
* Arrival order of this iteration's thinking steps, text and tool calls.
|
|
143
|
+
* A ModelMessage keeps `thinking` apart from `content`/`toolCalls`, so a
|
|
144
|
+
* provider turn that thinks between provider-executed tools would otherwise
|
|
145
|
+
* be recorded as "all thinking, then text, then tools" and the provider
|
|
146
|
+
* rejects the replay (signed thinking must keep its position). `null` once
|
|
147
|
+
* the order could no longer be tracked (callers fall back to one message).
|
|
148
|
+
*/
|
|
149
|
+
turnParts = [];
|
|
146
150
|
currentThinkingContent = "";
|
|
147
151
|
currentThinkingSignature = "";
|
|
148
152
|
eventOptions;
|
|
@@ -159,8 +163,10 @@ var TextEngine = class {
|
|
|
159
163
|
initialClientToolResults;
|
|
160
164
|
resumeApprovals = /* @__PURE__ */ new Map();
|
|
161
165
|
resumeClientToolResults = /* @__PURE__ */ new Map();
|
|
166
|
+
resumeClientToolErrors = /* @__PURE__ */ new Map();
|
|
162
167
|
resumeDeniedToolResults = /* @__PURE__ */ new Map();
|
|
163
168
|
resumeCancelledToolCallIds = /* @__PURE__ */ new Set();
|
|
169
|
+
resumeInputResponses = /* @__PURE__ */ new Map();
|
|
164
170
|
resumeGenericInterrupts = /* @__PURE__ */ new Map();
|
|
165
171
|
resumeGenericInterruptRequests = /* @__PURE__ */ new Map();
|
|
166
172
|
threadId;
|
|
@@ -326,6 +332,33 @@ var TextEngine = class {
|
|
|
326
332
|
getFinalizationError() {
|
|
327
333
|
return this.finalizationError;
|
|
328
334
|
}
|
|
335
|
+
async runTerminalHook() {
|
|
336
|
+
if (this.terminalHookCalled || this.isCancelled()) return;
|
|
337
|
+
this.terminalHookCalled = true;
|
|
338
|
+
if (this.finalizationError) {
|
|
339
|
+
const errForHook = new Error(this.finalizationError.message, this.finalizationError.cause !== void 0 ? { cause: this.finalizationError.cause } : void 0);
|
|
340
|
+
if (this.finalizationError.code !== void 0) Object.defineProperty(errForHook, "code", {
|
|
341
|
+
value: this.finalizationError.code,
|
|
342
|
+
enumerable: true
|
|
343
|
+
});
|
|
344
|
+
if (this.finalizationError.rawText !== void 0) Object.defineProperty(errForHook, "rawText", {
|
|
345
|
+
value: this.finalizationError.rawText,
|
|
346
|
+
enumerable: true
|
|
347
|
+
});
|
|
348
|
+
await this.middlewareRunner.runOnError(this.middlewareCtx, {
|
|
349
|
+
error: errForHook,
|
|
350
|
+
duration: Date.now() - this.streamStartTime
|
|
351
|
+
});
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
this.addTerminalAssistantMessages();
|
|
355
|
+
await this.middlewareRunner.runOnFinish(this.middlewareCtx, {
|
|
356
|
+
finishReason: this.lastFinishReason,
|
|
357
|
+
duration: Date.now() - this.streamStartTime,
|
|
358
|
+
content: this.accumulatedContent,
|
|
359
|
+
usage: rebuildTokenUsage(this.finishedEvent?.usage, tanstackMetadata(this.finishedEvent ?? void 0)?.usage)
|
|
360
|
+
});
|
|
361
|
+
}
|
|
329
362
|
async *run() {
|
|
330
363
|
this.beforeRun();
|
|
331
364
|
this.logger.agentLoop("run started", { threadId: this.middlewareCtx.threadId });
|
|
@@ -351,7 +384,11 @@ var TextEngine = class {
|
|
|
351
384
|
}
|
|
352
385
|
return;
|
|
353
386
|
}
|
|
354
|
-
|
|
387
|
+
const pendingPhase = yield* this.checkForPendingToolCalls();
|
|
388
|
+
if (pendingPhase === "stop" || pendingPhase === "wait") {
|
|
389
|
+
await this.runTerminalHook();
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
355
392
|
if (!(!!this.finalStructuredOutput && this.tools.length === 0 && this.finalStructuredOutput.nativeCombined !== true)) do {
|
|
356
393
|
if (this.earlyTermination) break;
|
|
357
394
|
if (this.isCancelled()) return;
|
|
@@ -387,29 +424,7 @@ var TextEngine = class {
|
|
|
387
424
|
if (!this.finalizationError && !this.isCancelled()) yield* this.flushDeferredModelRunFinishedChunks();
|
|
388
425
|
} else yield* this.runStructuredFinalization();
|
|
389
426
|
}
|
|
390
|
-
|
|
391
|
-
if (this.finalizationError) {
|
|
392
|
-
this.terminalHookCalled = true;
|
|
393
|
-
const errForHook = new Error(this.finalizationError.message, this.finalizationError.cause !== void 0 ? { cause: this.finalizationError.cause } : void 0);
|
|
394
|
-
if (this.finalizationError.code !== void 0) Object.defineProperty(errForHook, "code", {
|
|
395
|
-
value: this.finalizationError.code,
|
|
396
|
-
enumerable: true
|
|
397
|
-
});
|
|
398
|
-
await this.middlewareRunner.runOnError(this.middlewareCtx, {
|
|
399
|
-
error: errForHook,
|
|
400
|
-
duration: Date.now() - this.streamStartTime
|
|
401
|
-
});
|
|
402
|
-
} else {
|
|
403
|
-
this.addTerminalAssistantMessages();
|
|
404
|
-
this.terminalHookCalled = true;
|
|
405
|
-
await this.middlewareRunner.runOnFinish(this.middlewareCtx, {
|
|
406
|
-
finishReason: this.lastFinishReason,
|
|
407
|
-
duration: Date.now() - this.streamStartTime,
|
|
408
|
-
content: this.accumulatedContent,
|
|
409
|
-
usage: rebuildTokenUsage(this.finishedEvent?.usage, tanstackMetadata(this.finishedEvent ?? void 0)?.usage)
|
|
410
|
-
});
|
|
411
|
-
}
|
|
412
|
-
}
|
|
427
|
+
await this.runTerminalHook();
|
|
413
428
|
} catch (error) {
|
|
414
429
|
if (error instanceof Error && error.name === "InterruptReplaySignal" && "continuationRunId" in error && typeof error.continuationRunId === "string") {
|
|
415
430
|
this.terminalHookCalled = true;
|
|
@@ -501,6 +516,7 @@ var TextEngine = class {
|
|
|
501
516
|
this.streamIdentityCaptured = false;
|
|
502
517
|
this.accumulatedContent = "";
|
|
503
518
|
this.accumulatedThinking = [];
|
|
519
|
+
this.turnParts = [];
|
|
504
520
|
this.currentThinkingContent = "";
|
|
505
521
|
this.currentThinkingSignature = "";
|
|
506
522
|
this.finishedEvent = null;
|
|
@@ -531,7 +547,7 @@ var TextEngine = class {
|
|
|
531
547
|
const { approvals } = this.collectClientState();
|
|
532
548
|
const adapterApprovals = /* @__PURE__ */ new Map();
|
|
533
549
|
for (const [approvalId, resolution] of approvals) adapterApprovals.set(approvalId, typeof resolution === "boolean" ? resolution : resolution.approved);
|
|
534
|
-
|
|
550
|
+
assertMessagesFileSourceSupport(this.adapter, this.messages);
|
|
535
551
|
for await (const raw of this.adapter.chatStream({
|
|
536
552
|
model: this.params.model,
|
|
537
553
|
messages: this.providerMessages,
|
|
@@ -666,9 +682,23 @@ var TextEngine = class {
|
|
|
666
682
|
}
|
|
667
683
|
handleTextMessageContentEvent(chunk) {
|
|
668
684
|
const extra = chunk;
|
|
685
|
+
const before = this.accumulatedContent;
|
|
669
686
|
if (typeof extra.content === "string" && extra.content !== "") this.accumulatedContent = extra.content;
|
|
670
687
|
else this.accumulatedContent += chunk.delta;
|
|
671
688
|
this.middlewareCtx.accumulatedContent = this.accumulatedContent;
|
|
689
|
+
if (!this.turnParts) return;
|
|
690
|
+
if (!this.accumulatedContent.startsWith(before)) {
|
|
691
|
+
this.turnParts = null;
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
const delta = this.accumulatedContent.slice(before.length);
|
|
695
|
+
if (delta === "") return;
|
|
696
|
+
const last = this.turnParts[this.turnParts.length - 1];
|
|
697
|
+
if (last && last.type === "text") last.content += delta;
|
|
698
|
+
else this.turnParts.push({
|
|
699
|
+
type: "text",
|
|
700
|
+
content: delta
|
|
701
|
+
});
|
|
672
702
|
}
|
|
673
703
|
captureStreamMessageIdentity(messageId) {
|
|
674
704
|
this.currentMessageId = messageId;
|
|
@@ -685,6 +715,11 @@ var TextEngine = class {
|
|
|
685
715
|
handleToolCallStartEvent(chunk) {
|
|
686
716
|
if (typeof chunk.parentMessageId === "string" && chunk.parentMessageId !== "") this.captureStreamMessageIdentity(chunk.parentMessageId);
|
|
687
717
|
this.toolCallManager.addToolCallStartEvent(chunk);
|
|
718
|
+
if (this.turnParts && !this.turnParts.some((part) => part.type === "call" && part.id === chunk.toolCallId)) this.turnParts.push({
|
|
719
|
+
type: "call",
|
|
720
|
+
id: chunk.toolCallId,
|
|
721
|
+
providerExecuted: isProviderExecutedToolCall({ metadata: chunk.metadata })
|
|
722
|
+
});
|
|
688
723
|
const metadata = chunk.metadata;
|
|
689
724
|
const thoughtSignature = metadata != null && typeof metadata === "object" && "thoughtSignature" in metadata && typeof metadata.thoughtSignature === "string" && metadata.thoughtSignature !== "" ? metadata.thoughtSignature : void 0;
|
|
690
725
|
if (thoughtSignature === void 0) return;
|
|
@@ -746,17 +781,42 @@ var TextEngine = class {
|
|
|
746
781
|
content: this.currentThinkingContent,
|
|
747
782
|
...this.currentThinkingSignature && { signature: this.currentThinkingSignature }
|
|
748
783
|
});
|
|
784
|
+
if (this.turnParts) {
|
|
785
|
+
const placeholder = [...this.turnParts].reverse().find((part) => part.type === "thinking" && part.index === -1);
|
|
786
|
+
const index = this.accumulatedThinking.length - 1;
|
|
787
|
+
if (placeholder) placeholder.index = index;
|
|
788
|
+
else this.turnParts.push({
|
|
789
|
+
type: "thinking",
|
|
790
|
+
index
|
|
791
|
+
});
|
|
792
|
+
}
|
|
749
793
|
this.currentThinkingContent = "";
|
|
750
794
|
this.currentThinkingSignature = "";
|
|
751
795
|
}
|
|
752
796
|
}
|
|
797
|
+
/**
|
|
798
|
+
* Record where the current thinking step sits among this turn's parts. A
|
|
799
|
+
* step is finalized only when the next step starts (or the turn ends), by
|
|
800
|
+
* which time later tool calls have already arrived, so the position has to
|
|
801
|
+
* be noted when the step's first content or signature shows up.
|
|
802
|
+
*/
|
|
803
|
+
noteThinkingStepPosition() {
|
|
804
|
+
if (this.turnParts && this.currentThinkingContent === "" && this.currentThinkingSignature === "") this.turnParts.push({
|
|
805
|
+
type: "thinking",
|
|
806
|
+
index: -1
|
|
807
|
+
});
|
|
808
|
+
}
|
|
753
809
|
handleStepStartedEvent() {
|
|
754
810
|
this.finalizeCurrentThinkingStep();
|
|
755
811
|
}
|
|
756
812
|
handleStepFinishedEvent(chunk) {
|
|
757
|
-
if (typeof chunk.signature === "string" && chunk.signature !== "")
|
|
813
|
+
if (typeof chunk.signature === "string" && chunk.signature !== "") {
|
|
814
|
+
this.noteThinkingStepPosition();
|
|
815
|
+
this.currentThinkingSignature = chunk.signature;
|
|
816
|
+
}
|
|
758
817
|
}
|
|
759
818
|
handleReasoningMessageContentEvent(chunk) {
|
|
819
|
+
this.noteThinkingStepPosition();
|
|
760
820
|
this.currentThinkingContent += chunk.delta;
|
|
761
821
|
}
|
|
762
822
|
handleReasoningEncryptedValueEvent(chunk) {
|
|
@@ -768,6 +828,7 @@ var TextEngine = class {
|
|
|
768
828
|
};
|
|
769
829
|
return;
|
|
770
830
|
}
|
|
831
|
+
this.noteThinkingStepPosition();
|
|
771
832
|
this.currentThinkingSignature = chunk.encryptedValue;
|
|
772
833
|
}
|
|
773
834
|
/**
|
|
@@ -835,8 +896,10 @@ var TextEngine = class {
|
|
|
835
896
|
await this.middlewareRunner.runOnAfterToolCall(this.middlewareCtx, info);
|
|
836
897
|
}
|
|
837
898
|
}, this.middlewareCtx.context, this.toolAbortSignal, {
|
|
899
|
+
clientToolErrors: this.resumeClientToolErrors,
|
|
838
900
|
deniedToolResults: this.resumeDeniedToolResults,
|
|
839
|
-
cancelledToolCallIds: this.resumeCancelledToolCallIds
|
|
901
|
+
cancelledToolCallIds: this.resumeCancelledToolCallIds,
|
|
902
|
+
inputResponses: this.resumeInputResponses
|
|
840
903
|
});
|
|
841
904
|
const executionResult = yield* this.drainToolCallGenerator(generator);
|
|
842
905
|
if (this.isMiddlewareAborted()) {
|
|
@@ -850,10 +913,10 @@ var TextEngine = class {
|
|
|
850
913
|
needsApproval: executionResult.needsApproval,
|
|
851
914
|
needsClientExecution: executionResult.needsClientExecution
|
|
852
915
|
}));
|
|
853
|
-
if (executionResult.needsApproval.length > 0 || executionResult.needsClientExecution.length > 0 || executionResult.subagentInterrupts.length > 0) {
|
|
916
|
+
if (executionResult.needsApproval.length > 0 || executionResult.needsClientExecution.length > 0 || executionResult.inputRequired.length > 0 || executionResult.subagentInterrupts.length > 0) {
|
|
854
917
|
this.discardDeferredToolCallRunFinishedChunks();
|
|
855
918
|
if (allResults.length > 0) for (const chunk of this.buildToolResultChunks(allResults, finishEvent)) yield* this.pipeThroughMiddleware(chunk);
|
|
856
|
-
const emitted = yield* this.emitActionableInterruptBoundary(finishEvent, executionResult.needsApproval, executionResult.needsClientExecution, [], executionResult.subagentInterrupts);
|
|
919
|
+
const emitted = yield* this.emitActionableInterruptBoundary(finishEvent, executionResult.needsApproval, executionResult.needsClientExecution, [], executionResult.inputRequired, executionResult.subagentInterrupts);
|
|
857
920
|
this.setToolPhase(emitted ? "wait" : "stop");
|
|
858
921
|
return emitted ? "wait" : "stop";
|
|
859
922
|
}
|
|
@@ -927,8 +990,10 @@ var TextEngine = class {
|
|
|
927
990
|
await this.middlewareRunner.runOnAfterToolCall(this.middlewareCtx, info);
|
|
928
991
|
}
|
|
929
992
|
}, this.middlewareCtx.context, this.toolAbortSignal, {
|
|
993
|
+
clientToolErrors: this.resumeClientToolErrors,
|
|
930
994
|
deniedToolResults: this.resumeDeniedToolResults,
|
|
931
|
-
cancelledToolCallIds: this.resumeCancelledToolCallIds
|
|
995
|
+
cancelledToolCallIds: this.resumeCancelledToolCallIds,
|
|
996
|
+
inputResponses: this.resumeInputResponses
|
|
932
997
|
});
|
|
933
998
|
const executionResult = yield* this.drainToolCallGenerator(generator);
|
|
934
999
|
this.middlewareCtx.phase = "afterTools";
|
|
@@ -947,13 +1012,13 @@ var TextEngine = class {
|
|
|
947
1012
|
const afterToolRequests = yield* this.runWhileYielding(this.middlewareRunner.runOnInterruptBoundary(this.middlewareCtx));
|
|
948
1013
|
if (afterToolRequests.length > 0) {
|
|
949
1014
|
for (const chunk of afterToolBoundaryChunks) yield* this.pipeThroughMiddleware(chunk);
|
|
950
|
-
yield* this.emitBoundaryInterrupts("afterTools", finishEvent, toolCalls, afterToolRequests);
|
|
1015
|
+
yield* this.emitBoundaryInterrupts("afterTools", finishEvent, toolCalls, afterToolRequests, executionResult.inputRequired);
|
|
951
1016
|
this.setToolPhase("wait");
|
|
952
1017
|
return;
|
|
953
1018
|
}
|
|
954
|
-
if (executionResult.needsApproval.length > 0 || executionResult.needsClientExecution.length > 0 || executionResult.subagentInterrupts.length > 0) {
|
|
1019
|
+
if (executionResult.needsApproval.length > 0 || executionResult.needsClientExecution.length > 0 || executionResult.inputRequired.length > 0 || executionResult.subagentInterrupts.length > 0) {
|
|
955
1020
|
if (allResults.length > 0) for (const chunk of afterToolBoundaryChunks) yield* this.pipeThroughMiddleware(chunk);
|
|
956
|
-
const emitted = yield* this.emitActionableInterruptBoundary(finishEvent, executionResult.needsApproval, executionResult.needsClientExecution, [], executionResult.subagentInterrupts);
|
|
1021
|
+
const emitted = yield* this.emitActionableInterruptBoundary(finishEvent, executionResult.needsApproval, executionResult.needsClientExecution, [], executionResult.inputRequired, executionResult.subagentInterrupts);
|
|
957
1022
|
this.setToolPhase(emitted ? "wait" : "stop");
|
|
958
1023
|
return;
|
|
959
1024
|
}
|
|
@@ -1013,16 +1078,67 @@ var TextEngine = class {
|
|
|
1013
1078
|
shouldExecuteToolPhase() {
|
|
1014
1079
|
return this.lastFinishReason === "tool_calls" && this.tools.length > 0 && this.toolCallManager.hasToolCalls();
|
|
1015
1080
|
}
|
|
1081
|
+
/**
|
|
1082
|
+
* Split this iteration into assistant ModelMessages that keep the provider's
|
|
1083
|
+
* block order: a new segment starts at every thinking step that follows a
|
|
1084
|
+
* provider-executed tool call (the rule buildAssistantMessages applies to
|
|
1085
|
+
* UIMessages). Segments after the first get `${id}-segment-${n}` ids.
|
|
1086
|
+
* Returns null when no split is needed or the order could not be tracked,
|
|
1087
|
+
* so callers fall back to the single-message shape.
|
|
1088
|
+
*/
|
|
1089
|
+
buildOrderedAssistantSegments(toolCalls, id, createdAt) {
|
|
1090
|
+
const parts = this.turnParts;
|
|
1091
|
+
if (!parts) return null;
|
|
1092
|
+
const providerCallIds = new Set(parts.flatMap((part) => part.type === "call" && part.providerExecuted ? [part.id] : []));
|
|
1093
|
+
let current = {
|
|
1094
|
+
thinking: [],
|
|
1095
|
+
text: "",
|
|
1096
|
+
callIds: []
|
|
1097
|
+
};
|
|
1098
|
+
const segments = [current];
|
|
1099
|
+
let split = false;
|
|
1100
|
+
for (const part of parts) if (part.type === "thinking") {
|
|
1101
|
+
const thinking = this.accumulatedThinking[part.index];
|
|
1102
|
+
if (!thinking) return null;
|
|
1103
|
+
if (current.callIds.some((callId) => providerCallIds.has(callId))) {
|
|
1104
|
+
current = {
|
|
1105
|
+
thinking: [thinking],
|
|
1106
|
+
text: "",
|
|
1107
|
+
callIds: []
|
|
1108
|
+
};
|
|
1109
|
+
segments.push(current);
|
|
1110
|
+
split = true;
|
|
1111
|
+
} else current.thinking.push(thinking);
|
|
1112
|
+
} else if (part.type === "text") current.text += part.content;
|
|
1113
|
+
else current.callIds.push(part.id);
|
|
1114
|
+
if (!split) return null;
|
|
1115
|
+
if (segments.map((segment) => segment.text).join("") !== this.accumulatedContent) return null;
|
|
1116
|
+
if (segments.reduce((n, segment) => n + segment.thinking.length, 0) !== this.accumulatedThinking.length) return null;
|
|
1117
|
+
const placed = new Set(segments.flatMap((segment) => segment.callIds));
|
|
1118
|
+
for (const toolCall of toolCalls) if (!placed.has(toolCall.id)) current.callIds.push(toolCall.id);
|
|
1119
|
+
return segments.map((segment, index) => {
|
|
1120
|
+
const segmentCalls = toolCalls.filter((toolCall) => segment.callIds.includes(toolCall.id));
|
|
1121
|
+
return {
|
|
1122
|
+
role: "assistant",
|
|
1123
|
+
content: segment.text || null,
|
|
1124
|
+
...segmentCalls.length > 0 && { toolCalls: segmentCalls },
|
|
1125
|
+
id: id === void 0 ? void 0 : index === 0 ? id : `${id}-segment-${index}`,
|
|
1126
|
+
createdAt,
|
|
1127
|
+
...segment.thinking.length > 0 && { thinking: segment.thinking }
|
|
1128
|
+
};
|
|
1129
|
+
});
|
|
1130
|
+
}
|
|
1016
1131
|
addAssistantToolCallMessage(toolCalls) {
|
|
1017
1132
|
this.finalizeCurrentThinkingStep();
|
|
1018
|
-
|
|
1133
|
+
const segments = this.buildOrderedAssistantSegments(toolCalls, this.currentMessageId ?? void 0, this.currentMessageCreatedAt ?? void 0);
|
|
1134
|
+
this.messages = [...this.messages, ...segments ?? [{
|
|
1019
1135
|
role: "assistant",
|
|
1020
1136
|
content: this.accumulatedContent || null,
|
|
1021
1137
|
toolCalls,
|
|
1022
1138
|
id: this.currentMessageId ?? void 0,
|
|
1023
1139
|
createdAt: this.currentMessageCreatedAt ?? void 0,
|
|
1024
1140
|
...this.accumulatedThinking.length > 0 && { thinking: this.accumulatedThinking }
|
|
1025
|
-
}];
|
|
1141
|
+
}]];
|
|
1026
1142
|
this.middlewareCtx.messages = this.messages;
|
|
1027
1143
|
}
|
|
1028
1144
|
addTerminalAssistantMessages() {
|
|
@@ -1063,13 +1179,17 @@ var TextEngine = class {
|
|
|
1063
1179
|
...thinking ? { thinking } : {}
|
|
1064
1180
|
});
|
|
1065
1181
|
} else {
|
|
1066
|
-
if (!currentTurnAlreadyRecorded && (this.accumulatedContent !== "" || thinking))
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1182
|
+
if (!currentTurnAlreadyRecorded && (this.accumulatedContent !== "" || thinking)) {
|
|
1183
|
+
const id = this.currentMessageId ?? this.createId("msg");
|
|
1184
|
+
const createdAt = this.currentMessageCreatedAt ?? /* @__PURE__ */ new Date();
|
|
1185
|
+
messages.push(...this.buildOrderedAssistantSegments(this.toolCallManager.getToolCalls(), id, createdAt) ?? [{
|
|
1186
|
+
role: "assistant",
|
|
1187
|
+
content: this.accumulatedContent || null,
|
|
1188
|
+
id,
|
|
1189
|
+
createdAt,
|
|
1190
|
+
...thinking ? { thinking } : {}
|
|
1191
|
+
}]);
|
|
1192
|
+
}
|
|
1073
1193
|
if (structuredOutput) messages.push({
|
|
1074
1194
|
role: "assistant",
|
|
1075
1195
|
content: raw || null,
|
|
@@ -1125,7 +1245,7 @@ var TextEngine = class {
|
|
|
1125
1245
|
genericInterruptId() {
|
|
1126
1246
|
return this.createId("interrupt");
|
|
1127
1247
|
}
|
|
1128
|
-
buildActionableInterrupts(approvals, clientRequests, genericRequests = [], genericInterruptIds = [], childInterrupts = []) {
|
|
1248
|
+
buildActionableInterrupts(approvals, clientRequests, genericRequests = [], genericInterruptIds = [], inputRequired = [], childInterrupts = []) {
|
|
1129
1249
|
const interrupts = [];
|
|
1130
1250
|
for (const approval of approvals) {
|
|
1131
1251
|
const tool = this.tools.find((candidate) => candidate.name === approval.toolName);
|
|
@@ -1206,6 +1326,27 @@ var TextEngine = class {
|
|
|
1206
1326
|
}
|
|
1207
1327
|
});
|
|
1208
1328
|
}
|
|
1329
|
+
for (const pendingInput of inputRequired) {
|
|
1330
|
+
const id = `mcp_input_${pendingInput.toolCallId}`;
|
|
1331
|
+
interrupts.push({
|
|
1332
|
+
id,
|
|
1333
|
+
reason: "mcp_input",
|
|
1334
|
+
message: `Input required to run ${pendingInput.toolName}`,
|
|
1335
|
+
toolCallId: pendingInput.toolCallId,
|
|
1336
|
+
metadata: {
|
|
1337
|
+
toolName: pendingInput.toolName,
|
|
1338
|
+
[interruptBindingMetadataKey]: {
|
|
1339
|
+
v: 1,
|
|
1340
|
+
kind: "generic",
|
|
1341
|
+
interruptId: id
|
|
1342
|
+
},
|
|
1343
|
+
[INTERRUPT_PAYLOAD_METADATA_KEY]: {
|
|
1344
|
+
kind: pendingInput.kind,
|
|
1345
|
+
request: pendingInput.request
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
});
|
|
1349
|
+
}
|
|
1209
1350
|
interrupts.push(...childInterrupts);
|
|
1210
1351
|
const ids = /* @__PURE__ */ new Set();
|
|
1211
1352
|
for (const interrupt of interrupts) {
|
|
@@ -1214,13 +1355,13 @@ var TextEngine = class {
|
|
|
1214
1355
|
}
|
|
1215
1356
|
return interrupts;
|
|
1216
1357
|
}
|
|
1217
|
-
buildInterruptFinishedChunk(finishEvent, approvals, clientRequests, genericRequests = [], genericInterruptIds, childInterrupts) {
|
|
1358
|
+
buildInterruptFinishedChunk(finishEvent, approvals, clientRequests, genericRequests = [], genericInterruptIds, inputRequired = [], childInterrupts) {
|
|
1218
1359
|
return {
|
|
1219
1360
|
...finishEvent,
|
|
1220
1361
|
timestamp: Date.now(),
|
|
1221
1362
|
outcome: {
|
|
1222
1363
|
type: "interrupt",
|
|
1223
|
-
interrupts: this.buildActionableInterrupts(approvals, clientRequests, genericRequests, genericInterruptIds, childInterrupts)
|
|
1364
|
+
interrupts: this.buildActionableInterrupts(approvals, clientRequests, genericRequests, genericInterruptIds, inputRequired, childInterrupts)
|
|
1224
1365
|
}
|
|
1225
1366
|
};
|
|
1226
1367
|
}
|
|
@@ -1314,10 +1455,10 @@ var TextEngine = class {
|
|
|
1314
1455
|
};
|
|
1315
1456
|
yield* this.pipeThroughMiddleware(this.buildInterruptRunErrorChunk(error));
|
|
1316
1457
|
}
|
|
1317
|
-
async *emitActionableInterruptBoundary(finishEvent, approvals, clientRequests, genericRequests = [], childInterrupts = []) {
|
|
1458
|
+
async *emitActionableInterruptBoundary(finishEvent, approvals, clientRequests, genericRequests = [], inputRequired = [], childInterrupts = []) {
|
|
1318
1459
|
yield* this.emitSyntheticRunStarted(finishEvent);
|
|
1319
1460
|
const genericInterruptIds = genericRequests.map(() => this.genericInterruptId());
|
|
1320
|
-
const terminal = this.completeEphemeralInterruptBindings(this.buildInterruptFinishedChunk(finishEvent, approvals, clientRequests, genericRequests, genericInterruptIds, childInterrupts));
|
|
1461
|
+
const terminal = this.completeEphemeralInterruptBindings(this.buildInterruptFinishedChunk(finishEvent, approvals, clientRequests, genericRequests, genericInterruptIds, inputRequired, childInterrupts));
|
|
1321
1462
|
let terminalOutputs;
|
|
1322
1463
|
try {
|
|
1323
1464
|
terminalOutputs = [...this.emitPublicChunks(await this.middlewareRunner.runOnChunk(this.middlewareCtx, terminal))];
|
|
@@ -1334,7 +1475,7 @@ var TextEngine = class {
|
|
|
1334
1475
|
for (const output of terminalOutputs) yield this.publicInterruptTerminal(output);
|
|
1335
1476
|
return true;
|
|
1336
1477
|
}
|
|
1337
|
-
async *emitBoundaryInterrupts(phase, finishEvent, toolCalls = [], requests) {
|
|
1478
|
+
async *emitBoundaryInterrupts(phase, finishEvent, toolCalls = [], requests, inputRequired = []) {
|
|
1338
1479
|
this.middlewareCtx.phase = phase;
|
|
1339
1480
|
const boundaryRequests = requests ?? (yield* this.runWhileYielding(this.middlewareRunner.runOnInterruptBoundary(this.middlewareCtx)));
|
|
1340
1481
|
if (boundaryRequests.length === 0) return false;
|
|
@@ -1344,7 +1485,7 @@ var TextEngine = class {
|
|
|
1344
1485
|
else this.addAssistantTextMessageForInterrupt();
|
|
1345
1486
|
}
|
|
1346
1487
|
const actionable = this.getBoundaryActionableToolRequests(toolCalls);
|
|
1347
|
-
yield* this.emitActionableInterruptBoundary(finishEvent, actionable.approvals, actionable.clientRequests, boundaryRequests);
|
|
1488
|
+
yield* this.emitActionableInterruptBoundary(finishEvent, actionable.approvals, actionable.clientRequests, boundaryRequests, inputRequired);
|
|
1348
1489
|
return true;
|
|
1349
1490
|
}
|
|
1350
1491
|
addAssistantTextMessageForInterrupt() {
|
|
@@ -1360,6 +1501,7 @@ var TextEngine = class {
|
|
|
1360
1501
|
const approvalRequests = [];
|
|
1361
1502
|
const clientRequests = [];
|
|
1362
1503
|
for (const toolCall of toolCalls) {
|
|
1504
|
+
if (isProviderExecutedToolCall(toolCall)) continue;
|
|
1363
1505
|
const tool = this.resolveExecutableTools([toolCall]).find((candidate) => candidate.name === toolCall.function.name);
|
|
1364
1506
|
if (!tool) continue;
|
|
1365
1507
|
let input = {};
|
|
@@ -1376,7 +1518,7 @@ var TextEngine = class {
|
|
|
1376
1518
|
input,
|
|
1377
1519
|
approvalId
|
|
1378
1520
|
});
|
|
1379
|
-
else if (!tool.execute && !clientToolResults.has(toolCall.id) && !this.resumeCancelledToolCallIds.has(toolCall.id)) clientRequests.push({
|
|
1521
|
+
else if (!tool.execute && !clientToolResults.has(toolCall.id) && !this.resumeClientToolErrors.has(toolCall.id) && !this.resumeCancelledToolCallIds.has(toolCall.id)) clientRequests.push({
|
|
1380
1522
|
toolCallId: toolCall.id,
|
|
1381
1523
|
toolName: toolCall.function.name,
|
|
1382
1524
|
input
|
|
@@ -1447,7 +1589,10 @@ var TextEngine = class {
|
|
|
1447
1589
|
content: wireContent,
|
|
1448
1590
|
role: "tool"
|
|
1449
1591
|
};
|
|
1450
|
-
chunks.push(result.state === "output-error" ? withTanstackMetadata(resultChunk, {
|
|
1592
|
+
chunks.push(result.state === "output-error" ? withTanstackMetadata(resultChunk, {
|
|
1593
|
+
state: result.state,
|
|
1594
|
+
...result.outcome !== void 0 && { toolResultOutcome: result.outcome }
|
|
1595
|
+
}) : resultChunk);
|
|
1451
1596
|
const placeholderIdx = this.messages.findIndex((m) => {
|
|
1452
1597
|
if (m.role !== "tool" || m.toolCallId !== result.toolCallId) return false;
|
|
1453
1598
|
if (typeof m.content !== "string") return false;
|
|
@@ -1457,17 +1602,31 @@ var TextEngine = class {
|
|
|
1457
1602
|
return false;
|
|
1458
1603
|
}
|
|
1459
1604
|
});
|
|
1460
|
-
const
|
|
1605
|
+
const isDeniedResult = result.outcome === "denied";
|
|
1606
|
+
const existingToolResultIdx = isDeniedResult ? this.messages.findIndex((message) => message.role === "tool" && message.toolCallId === result.toolCallId) : -1;
|
|
1607
|
+
const resultMessageIdx = existingToolResultIdx >= 0 ? existingToolResultIdx : placeholderIdx;
|
|
1608
|
+
const existingToolMessage = existingToolResultIdx >= 0 ? this.messages[existingToolResultIdx] : void 0;
|
|
1609
|
+
const errorField = result.state === "output-error" && { error: toolResultErrorText(parseToolOutput(wireContent)) };
|
|
1610
|
+
const replacementMessage = existingToolMessage?.role === "tool" ? {
|
|
1611
|
+
...existingToolMessage,
|
|
1612
|
+
content,
|
|
1613
|
+
toolCallId: result.toolCallId,
|
|
1614
|
+
...errorField
|
|
1615
|
+
} : {
|
|
1461
1616
|
role: "tool",
|
|
1462
1617
|
content,
|
|
1463
|
-
toolCallId: result.toolCallId
|
|
1618
|
+
toolCallId: result.toolCallId,
|
|
1619
|
+
...errorField
|
|
1464
1620
|
};
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1621
|
+
const newToolMessage = result.outcome !== void 0 ? withTanstackMetadata(replacementMessage, { toolResultOutcome: result.outcome }) : replacementMessage;
|
|
1622
|
+
if (resultMessageIdx >= 0) {
|
|
1623
|
+
const replacedMessages = [
|
|
1624
|
+
...this.messages.slice(0, resultMessageIdx),
|
|
1625
|
+
newToolMessage,
|
|
1626
|
+
...this.messages.slice(resultMessageIdx + 1)
|
|
1627
|
+
];
|
|
1628
|
+
this.messages = isDeniedResult ? replacedMessages.filter((message, index) => index === resultMessageIdx || !(message.role === "tool" && message.toolCallId === result.toolCallId)) : replacedMessages;
|
|
1629
|
+
} else this.messages = [...this.messages, newToolMessage];
|
|
1471
1630
|
this.middlewareCtx.messages = this.messages;
|
|
1472
1631
|
}
|
|
1473
1632
|
return chunks;
|
|
@@ -1479,7 +1638,7 @@ var TextEngine = class {
|
|
|
1479
1638
|
if (typeof message.content === "string") try {
|
|
1480
1639
|
if (JSON.parse(message.content).pendingExecution === true) hasPendingExecution = true;
|
|
1481
1640
|
} catch {}
|
|
1482
|
-
if (!hasPendingExecution) completedToolIds.add(message.toolCallId);
|
|
1641
|
+
if (!hasPendingExecution && !this.resumeDeniedToolResults.has(message.toolCallId)) completedToolIds.add(message.toolCallId);
|
|
1483
1642
|
}
|
|
1484
1643
|
const pending = [];
|
|
1485
1644
|
for (const message of this.messages) if (message.role === "assistant" && message.toolCalls) for (const toolCall of message.toolCalls) {
|
|
@@ -1682,7 +1841,7 @@ var TextEngine = class {
|
|
|
1682
1841
|
tools: baseConfig.tools
|
|
1683
1842
|
}));
|
|
1684
1843
|
this.applyMiddlewareConfig(postOnConfig);
|
|
1685
|
-
|
|
1844
|
+
assertMessagesFileSourceSupport(this.adapter, this.messages);
|
|
1686
1845
|
const structuredCallOptions = {
|
|
1687
1846
|
chatOptions: {
|
|
1688
1847
|
model: this.params.model,
|
|
@@ -1721,6 +1880,7 @@ var TextEngine = class {
|
|
|
1721
1880
|
};
|
|
1722
1881
|
const runChunkMiddleware = (synthChunk) => this.middlewareRunner.runOnChunk(this.middlewareCtx, synthChunk);
|
|
1723
1882
|
let runErrorYielded = false;
|
|
1883
|
+
let rawText = "";
|
|
1724
1884
|
for await (const raw of providerStream) {
|
|
1725
1885
|
if (this.isCancelled()) break;
|
|
1726
1886
|
{
|
|
@@ -1766,11 +1926,16 @@ var TextEngine = class {
|
|
|
1766
1926
|
}
|
|
1767
1927
|
}
|
|
1768
1928
|
if (chunk.type === EventType.RUN_FINISHED) await this.runOnUsageFromChunk(chunk);
|
|
1769
|
-
if (chunk.type === EventType.
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1929
|
+
if (chunk.type === EventType.TEXT_MESSAGE_CONTENT) rawText += chunk.delta;
|
|
1930
|
+
if (chunk.type === EventType.RUN_ERROR) {
|
|
1931
|
+
const cause = fallbackAdapterError ?? chunk.rawEvent;
|
|
1932
|
+
this.finalizationError = {
|
|
1933
|
+
message: chunk.message,
|
|
1934
|
+
...chunk.code ? { code: chunk.code } : {},
|
|
1935
|
+
...cause !== void 0 ? { cause } : {},
|
|
1936
|
+
...rawText ? { rawText } : {}
|
|
1937
|
+
};
|
|
1938
|
+
}
|
|
1774
1939
|
const outputChunks = await this.middlewareRunner.runOnChunk(this.middlewareCtx, outboundChunk);
|
|
1775
1940
|
if (this.finalStructuredOutput.yieldChunks) for (const spec of this.emitPublicChunks(outputChunks)) {
|
|
1776
1941
|
if (spec.type === EventType.RUN_ERROR) runErrorYielded = true;
|
|
@@ -1832,7 +1997,12 @@ var TextEngine = class {
|
|
|
1832
1997
|
async *harvestCombinedStructuredOutput() {
|
|
1833
1998
|
if (!this.finalStructuredOutput) throw new Error("harvestCombinedStructuredOutput called without finalStructuredOutput config");
|
|
1834
1999
|
const yieldChunks = this.finalStructuredOutput.yieldChunks;
|
|
1835
|
-
|
|
2000
|
+
const source = this.finalStructuredOutput.source ?? "text";
|
|
2001
|
+
if (this.lastFinishReason === "length") this.finalizationError = {
|
|
2002
|
+
message: "The response was cut off because the maximum token limit was reached (finish_reason=length); raise the output token limit.",
|
|
2003
|
+
code: "max_tokens"
|
|
2004
|
+
};
|
|
2005
|
+
else if (source === "event") {
|
|
1836
2006
|
if (!this.structuredOutputResult) this.finalizationError = {
|
|
1837
2007
|
message: "missing structured result",
|
|
1838
2008
|
code: "structured-output-missing-result"
|
|
@@ -1855,7 +2025,8 @@ var TextEngine = class {
|
|
|
1855
2025
|
this.finalizationError = {
|
|
1856
2026
|
message: `Failed to parse structured output as JSON. Content: ${detail}`,
|
|
1857
2027
|
code: "structured-output-parse-failed",
|
|
1858
|
-
cause: err
|
|
2028
|
+
cause: err,
|
|
2029
|
+
rawText
|
|
1859
2030
|
};
|
|
1860
2031
|
}
|
|
1861
2032
|
}
|
|
@@ -1917,6 +2088,7 @@ var TextEngine = class {
|
|
|
1917
2088
|
resumeToolState: {
|
|
1918
2089
|
approvals: this.resumeApprovals,
|
|
1919
2090
|
clientToolResults: this.resumeClientToolResults,
|
|
2091
|
+
clientToolErrors: this.resumeClientToolErrors,
|
|
1920
2092
|
deniedToolResults: this.resumeDeniedToolResults,
|
|
1921
2093
|
cancelledToolCallIds: this.resumeCancelledToolCallIds
|
|
1922
2094
|
},
|
|
@@ -1996,6 +2168,24 @@ var TextEngine = class {
|
|
|
1996
2168
|
}] : [];
|
|
1997
2169
|
});
|
|
1998
2170
|
pending.push(...genericPending);
|
|
2171
|
+
const mcpInputCallIds = /* @__PURE__ */ new Map();
|
|
2172
|
+
for (const toolCall of pendingToolCalls) {
|
|
2173
|
+
const interruptId = `mcp_input_${toolCall.id}`;
|
|
2174
|
+
if (!resumeInterruptIds.has(interruptId)) continue;
|
|
2175
|
+
if (!toolsByCallId.get(toolCall.id)?.execute) continue;
|
|
2176
|
+
mcpInputCallIds.set(interruptId, toolCall.id);
|
|
2177
|
+
pending.push({
|
|
2178
|
+
interruptId,
|
|
2179
|
+
payload: { id: interruptId },
|
|
2180
|
+
binding: {
|
|
2181
|
+
v: 1,
|
|
2182
|
+
kind: "generic",
|
|
2183
|
+
interruptId,
|
|
2184
|
+
interruptedRunId,
|
|
2185
|
+
generation: 0
|
|
2186
|
+
}
|
|
2187
|
+
});
|
|
2188
|
+
}
|
|
1999
2189
|
const validated = await validateInterruptResumeBatch({
|
|
2000
2190
|
threadId: this.threadId,
|
|
2001
2191
|
interruptedRunId,
|
|
@@ -2012,6 +2202,14 @@ var TextEngine = class {
|
|
|
2012
2202
|
approvals
|
|
2013
2203
|
});
|
|
2014
2204
|
const genericResolutions = validated.resumeToolState.genericInterrupts;
|
|
2205
|
+
for (const [interruptId, toolCallId] of mcpInputCallIds) {
|
|
2206
|
+
const resolution = genericResolutions?.get(interruptId);
|
|
2207
|
+
if (!resolution) continue;
|
|
2208
|
+
this.resumeInputResponses.set(toolCallId, resolution.status === "resolved" ? {
|
|
2209
|
+
status: "resolved",
|
|
2210
|
+
payload: resolution.payload
|
|
2211
|
+
} : { status: "cancelled" });
|
|
2212
|
+
}
|
|
2015
2213
|
if (genericPending.length > 0 && genericResolutions) {
|
|
2016
2214
|
const resolutions = genericPending.sort((left, right) => {
|
|
2017
2215
|
return (left.binding.kind === "generic" ? left.binding.batchIndex ?? 0 : 0) - (right.binding.kind === "generic" ? right.binding.batchIndex ?? 0 : 0);
|
|
@@ -2032,7 +2230,10 @@ var TextEngine = class {
|
|
|
2032
2230
|
all: (...definitions) => definitions.length === 0 ? resolutions : resolutions.filter((resolution) => definitions.includes(resolution.request.definition))
|
|
2033
2231
|
});
|
|
2034
2232
|
if (policy.toolResume === "stop") this.earlyTermination = true;
|
|
2035
|
-
else if (policy.toolResume === "cancel") for (const request of pendingToolCalls)
|
|
2233
|
+
else if (policy.toolResume === "cancel") for (const request of pendingToolCalls) {
|
|
2234
|
+
if (this.resumeDeniedToolResults.has(request.id)) continue;
|
|
2235
|
+
this.resumeCancelledToolCallIds.add(request.id);
|
|
2236
|
+
}
|
|
2036
2237
|
}
|
|
2037
2238
|
}
|
|
2038
2239
|
getGenericContinuationPending(interruptedRunId) {
|
|
@@ -2104,6 +2305,7 @@ var TextEngine = class {
|
|
|
2104
2305
|
applyResumeToolState(state) {
|
|
2105
2306
|
if (state?.approvals) for (const [approvalId, resolution] of state.approvals) this.resumeApprovals.set(approvalId, resolution);
|
|
2106
2307
|
if (state?.clientToolResults) for (const [toolCallId, result] of state.clientToolResults) this.resumeClientToolResults.set(toolCallId, result);
|
|
2308
|
+
if (state?.clientToolErrors) for (const [toolCallId, errorText] of state.clientToolErrors) this.resumeClientToolErrors.set(toolCallId, errorText);
|
|
2107
2309
|
if (state?.deniedToolResults) for (const [toolCallId, result] of state.deniedToolResults) this.resumeDeniedToolResults.set(toolCallId, result);
|
|
2108
2310
|
if (state?.cancelledToolCallIds) for (const toolCallId of state.cancelledToolCallIds) this.resumeCancelledToolCallIds.add(toolCallId);
|
|
2109
2311
|
if (state?.genericInterrupts) for (const [interruptId, resolution] of state.genericInterrupts) this.resumeGenericInterrupts.set(interruptId, resolution);
|
|
@@ -2128,7 +2330,10 @@ var TextEngine = class {
|
|
|
2128
2330
|
all: (...definitions) => definitions.length === 0 ? resolutions : resolutions.filter((resolution) => definitions.includes(resolution.request.definition))
|
|
2129
2331
|
});
|
|
2130
2332
|
if (policy.toolResume === "stop") this.earlyTermination = true;
|
|
2131
|
-
else if (policy.toolResume === "cancel") for (const toolCall of this.getPendingToolCallsFromMessages())
|
|
2333
|
+
else if (policy.toolResume === "cancel") for (const toolCall of this.getPendingToolCallsFromMessages()) {
|
|
2334
|
+
if (this.resumeDeniedToolResults.has(toolCall.id)) continue;
|
|
2335
|
+
this.resumeCancelledToolCallIds.add(toolCall.id);
|
|
2336
|
+
}
|
|
2132
2337
|
}
|
|
2133
2338
|
applyMiddlewareConfig(config) {
|
|
2134
2339
|
this.applyResumeToolState(config.resumeToolState);
|
|
@@ -2465,6 +2670,8 @@ async function* runRoutedSubagents(options, engineRef) {
|
|
|
2465
2670
|
yield* runChatEngine(options, engineRef);
|
|
2466
2671
|
return;
|
|
2467
2672
|
}
|
|
2673
|
+
const withInput = bag.agents.find((agent) => agent.inputSchema !== void 0);
|
|
2674
|
+
if (withInput) throw new Error(`Subagent "${withInput.name}" has an inputSchema. inputSchema needs tool mode: remove subagents.router so the model writes the input.`);
|
|
2468
2675
|
const threadId = options.threadId ?? `thread-${Date.now()}`;
|
|
2469
2676
|
const runId = options.runId ?? `run-${Date.now()}`;
|
|
2470
2677
|
const messages = options.messages ?? [];
|
|
@@ -2777,6 +2984,10 @@ async function runAgenticStructuredOutput(options) {
|
|
|
2777
2984
|
value: finalizationError.code,
|
|
2778
2985
|
enumerable: true
|
|
2779
2986
|
});
|
|
2987
|
+
if (finalizationError.rawText !== void 0) Object.defineProperty(err, "rawText", {
|
|
2988
|
+
value: finalizationError.rawText,
|
|
2989
|
+
enumerable: true
|
|
2990
|
+
});
|
|
2780
2991
|
throw err;
|
|
2781
2992
|
}
|
|
2782
2993
|
const validated = engine.getValidatedStructuredOutput();
|