@librechat/agents 3.3.4 → 3.3.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/cjs/common/constants.cjs +21 -0
- package/dist/cjs/common/constants.cjs.map +1 -1
- package/dist/cjs/events.cjs +10 -1
- package/dist/cjs/events.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +456 -7
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/hooks/HookRegistry.cjs +25 -0
- package/dist/cjs/hooks/HookRegistry.cjs.map +1 -1
- package/dist/cjs/hooks/createWorkspacePolicyHook.cjs +1 -1
- package/dist/cjs/hooks/index.cjs +12 -0
- package/dist/cjs/hooks/index.cjs.map +1 -1
- package/dist/cjs/hooks/types.cjs +1 -0
- package/dist/cjs/hooks/types.cjs.map +1 -1
- package/dist/cjs/langfuse.cjs +8 -0
- package/dist/cjs/langfuse.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/utils/message_inputs.cjs +1 -3
- package/dist/cjs/llm/bedrock/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/invoke.cjs +268 -3
- package/dist/cjs/llm/invoke.cjs.map +1 -1
- package/dist/cjs/llm/openai/index.cjs +51 -6
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/llm/preempt.cjs +132 -0
- package/dist/cjs/llm/preempt.cjs.map +1 -0
- package/dist/cjs/main.cjs +31 -3
- package/dist/cjs/messages/alternation.cjs +92 -0
- package/dist/cjs/messages/alternation.cjs.map +1 -0
- package/dist/cjs/messages/format.cjs +72 -0
- package/dist/cjs/messages/format.cjs.map +1 -1
- package/dist/cjs/messages/handoffCue.cjs +63 -0
- package/dist/cjs/messages/handoffCue.cjs.map +1 -0
- package/dist/cjs/messages/index.cjs +3 -0
- package/dist/cjs/messages/injected.cjs +60 -0
- package/dist/cjs/messages/injected.cjs.map +1 -0
- package/dist/cjs/run.cjs +80 -7
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/session/JsonlSessionStore.cjs +1 -1
- package/dist/cjs/session/handlers.cjs +18 -9
- package/dist/cjs/session/handlers.cjs.map +1 -1
- package/dist/cjs/stream.cjs +34 -8
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/tools/BashExecutor.cjs +3 -1
- package/dist/cjs/tools/BashExecutor.cjs.map +1 -1
- package/dist/cjs/tools/BashProgrammaticToolCalling.cjs +2 -0
- package/dist/cjs/tools/BashProgrammaticToolCalling.cjs.map +1 -1
- package/dist/cjs/tools/CodeExecutor.cjs +19 -16
- package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
- package/dist/cjs/tools/ProgrammaticToolCalling.cjs +2 -0
- package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
- package/dist/cjs/tools/ReadFile.cjs +8 -4
- package/dist/cjs/tools/ReadFile.cjs.map +1 -1
- package/dist/cjs/tools/SkillTool.cjs +2 -0
- package/dist/cjs/tools/SkillTool.cjs.map +1 -1
- package/dist/cjs/tools/SubagentTool.cjs +3 -0
- package/dist/cjs/tools/SubagentTool.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +91 -50
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/ToolSearch.cjs +5 -1
- package/dist/cjs/tools/ToolSearch.cjs.map +1 -1
- package/dist/cjs/tools/intentArg.cjs +230 -0
- package/dist/cjs/tools/intentArg.cjs.map +1 -0
- package/dist/cjs/tools/local/CompileCheckTool.cjs +3 -2
- package/dist/cjs/tools/local/CompileCheckTool.cjs.map +1 -1
- package/dist/cjs/tools/local/LocalCodingTools.cjs +13 -12
- package/dist/cjs/tools/local/LocalCodingTools.cjs.map +1 -1
- package/dist/cjs/tools/local/LocalExecutionEngine.cjs +2 -2
- package/dist/cjs/tools/ptcTimeout.cjs.map +1 -1
- package/dist/cjs/tools/search/keenable-scraper.cjs +90 -0
- package/dist/cjs/tools/search/keenable-scraper.cjs.map +1 -0
- package/dist/cjs/tools/search/schema.cjs +2 -0
- package/dist/cjs/tools/search/schema.cjs.map +1 -1
- package/dist/cjs/tools/search/tool.cjs +40 -2
- package/dist/cjs/tools/search/tool.cjs.map +1 -1
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs +1 -0
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
- package/dist/cjs/tools/toolOutputReferences.cjs +41 -7
- package/dist/cjs/tools/toolOutputReferences.cjs.map +1 -1
- package/dist/esm/common/constants.mjs +19 -1
- package/dist/esm/common/constants.mjs.map +1 -1
- package/dist/esm/events.mjs +10 -1
- package/dist/esm/events.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +455 -6
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/hooks/HookRegistry.mjs +25 -0
- package/dist/esm/hooks/HookRegistry.mjs.map +1 -1
- package/dist/esm/hooks/createWorkspacePolicyHook.mjs +1 -1
- package/dist/esm/hooks/index.mjs +12 -1
- package/dist/esm/hooks/index.mjs.map +1 -1
- package/dist/esm/hooks/types.mjs +1 -0
- package/dist/esm/hooks/types.mjs.map +1 -1
- package/dist/esm/langfuse.mjs +9 -1
- package/dist/esm/langfuse.mjs.map +1 -1
- package/dist/esm/llm/bedrock/utils/message_inputs.mjs +1 -3
- package/dist/esm/llm/bedrock/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/invoke.mjs +270 -6
- package/dist/esm/llm/invoke.mjs.map +1 -1
- package/dist/esm/llm/openai/index.mjs +51 -6
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/llm/preempt.mjs +131 -0
- package/dist/esm/llm/preempt.mjs.map +1 -0
- package/dist/esm/main.mjs +11 -7
- package/dist/esm/messages/alternation.mjs +91 -0
- package/dist/esm/messages/alternation.mjs.map +1 -0
- package/dist/esm/messages/format.mjs +72 -0
- package/dist/esm/messages/format.mjs.map +1 -1
- package/dist/esm/messages/handoffCue.mjs +61 -0
- package/dist/esm/messages/handoffCue.mjs.map +1 -0
- package/dist/esm/messages/index.mjs +3 -0
- package/dist/esm/messages/injected.mjs +60 -0
- package/dist/esm/messages/injected.mjs.map +1 -0
- package/dist/esm/run.mjs +80 -7
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/session/JsonlSessionStore.mjs +1 -1
- package/dist/esm/session/handlers.mjs +19 -10
- package/dist/esm/session/handlers.mjs.map +1 -1
- package/dist/esm/stream.mjs +33 -9
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/tools/BashExecutor.mjs +3 -1
- package/dist/esm/tools/BashExecutor.mjs.map +1 -1
- package/dist/esm/tools/BashProgrammaticToolCalling.mjs +2 -0
- package/dist/esm/tools/BashProgrammaticToolCalling.mjs.map +1 -1
- package/dist/esm/tools/CodeExecutor.mjs +19 -16
- package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
- package/dist/esm/tools/ProgrammaticToolCalling.mjs +2 -0
- package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
- package/dist/esm/tools/ReadFile.mjs +8 -4
- package/dist/esm/tools/ReadFile.mjs.map +1 -1
- package/dist/esm/tools/SkillTool.mjs +2 -0
- package/dist/esm/tools/SkillTool.mjs.map +1 -1
- package/dist/esm/tools/SubagentTool.mjs +3 -0
- package/dist/esm/tools/SubagentTool.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +91 -51
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/ToolSearch.mjs +5 -1
- package/dist/esm/tools/ToolSearch.mjs.map +1 -1
- package/dist/esm/tools/intentArg.mjs +220 -0
- package/dist/esm/tools/intentArg.mjs.map +1 -0
- package/dist/esm/tools/local/CompileCheckTool.mjs +3 -2
- package/dist/esm/tools/local/CompileCheckTool.mjs.map +1 -1
- package/dist/esm/tools/local/LocalCodingTools.mjs +13 -12
- package/dist/esm/tools/local/LocalCodingTools.mjs.map +1 -1
- package/dist/esm/tools/local/LocalExecutionEngine.mjs +2 -2
- package/dist/esm/tools/ptcTimeout.mjs.map +1 -1
- package/dist/esm/tools/search/keenable-scraper.mjs +88 -0
- package/dist/esm/tools/search/keenable-scraper.mjs.map +1 -0
- package/dist/esm/tools/search/schema.mjs +2 -0
- package/dist/esm/tools/search/schema.mjs.map +1 -1
- package/dist/esm/tools/search/tool.mjs +40 -3
- package/dist/esm/tools/search/tool.mjs.map +1 -1
- package/dist/esm/tools/subagent/SubagentExecutor.mjs +1 -0
- package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
- package/dist/esm/tools/toolOutputReferences.mjs +41 -7
- package/dist/esm/tools/toolOutputReferences.mjs.map +1 -1
- package/dist/types/common/constants.d.ts +18 -0
- package/dist/types/graphs/Graph.d.ts +138 -1
- package/dist/types/hooks/HookRegistry.d.ts +15 -0
- package/dist/types/hooks/index.d.ts +12 -1
- package/dist/types/hooks/types.d.ts +45 -6
- package/dist/types/index.d.ts +2 -1
- package/dist/types/llm/invoke.d.ts +7 -0
- package/dist/types/llm/openai/index.d.ts +0 -11
- package/dist/types/llm/preempt.d.ts +40 -0
- package/dist/types/messages/alternation.d.ts +23 -0
- package/dist/types/messages/handoffCue.d.ts +40 -0
- package/dist/types/messages/index.d.ts +3 -0
- package/dist/types/messages/injected.d.ts +3 -0
- package/dist/types/run.d.ts +7 -0
- package/dist/types/stream.d.ts +14 -0
- package/dist/types/tools/BashExecutor.d.ts +18 -0
- package/dist/types/tools/CodeExecutor.d.ts +18 -0
- package/dist/types/tools/ReadFile.d.ts +18 -0
- package/dist/types/tools/SkillTool.d.ts +18 -0
- package/dist/types/tools/SubagentTool.d.ts +9 -0
- package/dist/types/tools/ToolNode.d.ts +37 -12
- package/dist/types/tools/ToolSearch.d.ts +18 -0
- package/dist/types/tools/intentArg.d.ts +119 -0
- package/dist/types/tools/ptcTimeout.d.ts +2 -0
- package/dist/types/tools/search/keenable-scraper.d.ts +15 -0
- package/dist/types/tools/search/schema.d.ts +18 -0
- package/dist/types/tools/search/tool.d.ts +18 -0
- package/dist/types/tools/search/types.d.ts +31 -2
- package/dist/types/tools/toolOutputReferences.d.ts +12 -2
- package/dist/types/types/graph.d.ts +8 -1
- package/dist/types/types/run.d.ts +65 -0
- package/dist/types/types/stream.d.ts +12 -25
- package/dist/types/types/tools.d.ts +27 -2
- package/package.json +1 -1
- package/src/{splitStream.test.ts → aggregator.test.ts} +59 -666
- package/src/common/constants.ts +21 -0
- package/src/events.ts +15 -1
- package/src/graphs/Graph.ts +568 -3
- package/src/graphs/__tests__/Graph.contextOverflow.test.ts +18 -7
- package/src/graphs/__tests__/Graph.preemptSignal.test.ts +126 -0
- package/src/hooks/HookRegistry.ts +40 -0
- package/src/hooks/__tests__/preemptBoundary.test.ts +152 -0
- package/src/hooks/index.ts +16 -2
- package/src/hooks/types.ts +47 -3
- package/src/index.ts +2 -1
- package/src/langfuse.ts +26 -1
- package/src/llm/bedrock/utils/message_inputs.test.ts +82 -0
- package/src/llm/bedrock/utils/message_inputs.ts +14 -11
- package/src/llm/bedrock/utils/toolResultCachePoint.test.ts +15 -0
- package/src/llm/invoke.alternation.test.ts +87 -0
- package/src/llm/invoke.handoffCue.test.ts +112 -0
- package/src/llm/invoke.ts +417 -8
- package/src/llm/openai/index.ts +74 -10
- package/src/llm/openai/llm.spec.ts +105 -0
- package/src/llm/preempt.test.ts +323 -0
- package/src/llm/preempt.ts +178 -0
- package/src/messages/alternation.test.ts +212 -0
- package/src/messages/alternation.ts +112 -0
- package/src/messages/format.ts +91 -0
- package/src/messages/formatAgentMessages.steer.test.ts +267 -0
- package/src/messages/handoffCue.test.ts +96 -0
- package/src/messages/handoffCue.ts +78 -0
- package/src/messages/index.ts +3 -0
- package/src/messages/injected.test.ts +90 -0
- package/src/messages/injected.ts +74 -0
- package/src/run.ts +91 -6
- package/src/scripts/preempt-probe.ts +330 -0
- package/src/scripts/preempt-scenarios.ts +388 -0
- package/src/session/handlers.ts +32 -12
- package/src/specs/handoffCue.test.ts +165 -0
- package/src/specs/langfuse-callbacks.test.ts +352 -2
- package/src/specs/preemptSeal.test.ts +309 -0
- package/src/stream.dispatch.test.ts +63 -0
- package/src/stream.ts +48 -9
- package/src/tools/BashExecutor.ts +6 -0
- package/src/tools/BashProgrammaticToolCalling.ts +2 -0
- package/src/tools/CodeExecutor.ts +6 -0
- package/src/tools/ProgrammaticToolCalling.ts +2 -0
- package/src/tools/ReadFile.ts +2 -0
- package/src/tools/SkillTool.ts +2 -0
- package/src/tools/SubagentTool.ts +3 -0
- package/src/tools/ToolNode.ts +193 -74
- package/src/tools/ToolSearch.ts +3 -0
- package/src/tools/__tests__/ToolNode.onResultCompletion.test.ts +174 -0
- package/src/tools/__tests__/intentArg.test.ts +281 -0
- package/src/tools/__tests__/intentCoverage.test.ts +139 -0
- package/src/tools/__tests__/toolOutputReferences.test.ts +83 -0
- package/src/tools/intentArg.ts +323 -0
- package/src/tools/local/CompileCheckTool.ts +4 -3
- package/src/tools/local/LocalCodingTools.ts +14 -13
- package/src/tools/ptcTimeout.ts +2 -0
- package/src/tools/search/keenable-scraper.test.ts +153 -0
- package/src/tools/search/keenable-scraper.ts +137 -0
- package/src/tools/search/outcome.test.ts +90 -0
- package/src/tools/search/schema.ts +3 -0
- package/src/tools/search/tool.ts +60 -3
- package/src/tools/search/types.ts +50 -3
- package/src/tools/subagent/SubagentExecutor.ts +2 -1
- package/src/tools/toolOutputReferences.ts +77 -9
- package/src/types/graph.ts +12 -1
- package/src/types/run.ts +67 -0
- package/src/types/stream.ts +12 -41
- package/src/types/tools.ts +24 -2
- package/dist/cjs/splitStream.cjs +0 -151
- package/dist/cjs/splitStream.cjs.map +0 -1
- package/dist/esm/splitStream.mjs +0 -150
- package/dist/esm/splitStream.mjs.map +0 -1
- package/dist/types/mockStream.d.ts +0 -32
- package/dist/types/splitStream.d.ts +0 -37
- package/src/mockStream.ts +0 -99
- package/src/splitStream.ts +0 -234
package/src/llm/invoke.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { concat } from '@langchain/core/utils/stream';
|
|
2
2
|
import { AIMessageChunk } from '@langchain/core/messages';
|
|
3
|
+
import {
|
|
4
|
+
CallbackManager,
|
|
5
|
+
CallbackManagerForLLMRun,
|
|
6
|
+
type Callbacks,
|
|
7
|
+
} from '@langchain/core/callbacks/manager';
|
|
8
|
+
import { getCallbackManagerForConfig } from '@langchain/core/runnables';
|
|
9
|
+
import type { Serialized } from '@langchain/core/load/serializable';
|
|
10
|
+
import type { ChatGeneration } from '@langchain/core/outputs';
|
|
3
11
|
import type { RunnableConfig } from '@langchain/core/runnables';
|
|
4
12
|
import type { ToolCall } from '@langchain/core/messages/tool';
|
|
5
13
|
import type { BaseMessage } from '@langchain/core/messages';
|
|
@@ -22,13 +30,22 @@ import {
|
|
|
22
30
|
} from '@/messages/cache';
|
|
23
31
|
import { annotateMessagesForLLM } from '@/tools/toolOutputReferences';
|
|
24
32
|
import { assertNotTruncatedToolCall } from '@/llm/truncation';
|
|
25
|
-
import { Constants, GraphEvents, Providers } from '@/common';
|
|
33
|
+
import { Constants, ContentTypes, GraphEvents, Providers } from '@/common';
|
|
26
34
|
import { manualToolStreamProviders } from '@/llm/providers';
|
|
35
|
+
import { appendCallbacks } from '@/utils/callbacks';
|
|
36
|
+
import { safeDispatchCustomEvent } from '@/utils/events';
|
|
27
37
|
import { getContextOverflowInfo } from '@/utils/errors';
|
|
28
|
-
import {
|
|
29
|
-
|
|
38
|
+
import {
|
|
39
|
+
modifyDeltaProperties,
|
|
40
|
+
coalesceAdjacentUserTurns,
|
|
41
|
+
strictAlternationProviders,
|
|
42
|
+
appendPredecessorHandoffCue,
|
|
43
|
+
removePredecessorHandoffCue,
|
|
44
|
+
} from '@/messages';
|
|
45
|
+
import { canSealPreempt } from '@/llm/preempt';
|
|
46
|
+
import { ChatModelStreamHandler, dispatchesChatModelStream } from '@/stream';
|
|
30
47
|
import { initializeModel } from '@/llm/init';
|
|
31
|
-
import { isOpenAILike } from '@/utils/llm';
|
|
48
|
+
import { isAnthropicLike, isOpenAILike } from '@/utils/llm';
|
|
32
49
|
|
|
33
50
|
/**
|
|
34
51
|
* Context passed to `attemptInvoke`. Matches the subset of Graph that
|
|
@@ -215,13 +232,23 @@ export function projectMessagesForProvider({
|
|
|
215
232
|
);
|
|
216
233
|
}
|
|
217
234
|
|
|
235
|
+
/**
|
|
236
|
+
* The registered handler that owns content-part dispatch, if any.
|
|
237
|
+
*
|
|
238
|
+
* Detected by brand rather than by `instanceof`: a host that registers
|
|
239
|
+
* `new ChatModelStreamHandler()` to opt out of sealing gets wrapped by
|
|
240
|
+
* `createRunHandlers` on every `AgentSession` run, and by
|
|
241
|
+
* `composeEventHandlers` on a key collision. Both wrappers forward to the same
|
|
242
|
+
* dispatcher while failing an identity check, so an identity test would
|
|
243
|
+
* silently revoke the opt-out documented on `StreamPreemption`.
|
|
244
|
+
*/
|
|
218
245
|
function getRegisteredDefaultChatStreamHandler(
|
|
219
246
|
context?: InvokeContext
|
|
220
|
-
):
|
|
247
|
+
): t.EventHandler | undefined {
|
|
221
248
|
const handler = context?.handlerRegistry?.getHandler(
|
|
222
249
|
GraphEvents.CHAT_MODEL_STREAM
|
|
223
250
|
);
|
|
224
|
-
return handler
|
|
251
|
+
return dispatchesChatModelStream(handler) ? handler : undefined;
|
|
225
252
|
}
|
|
226
253
|
|
|
227
254
|
function hasReasoningDetails(chunk: AIMessageChunk): boolean {
|
|
@@ -318,6 +345,280 @@ function getStreamHandlingChunk({
|
|
|
318
345
|
);
|
|
319
346
|
}
|
|
320
347
|
|
|
348
|
+
/**
|
|
349
|
+
* Best-effort output-token count for a sealed turn, used only when the
|
|
350
|
+
* provider never got to send its usage chunk.
|
|
351
|
+
*/
|
|
352
|
+
function countSealedTokens(
|
|
353
|
+
context: InvokeContext | undefined,
|
|
354
|
+
metadata: Record<string, unknown> | undefined,
|
|
355
|
+
messages: BaseMessage[]
|
|
356
|
+
): number | undefined {
|
|
357
|
+
try {
|
|
358
|
+
const counter = context?.getAgentContext(metadata).tokenCounter;
|
|
359
|
+
if (counter == null) {
|
|
360
|
+
return undefined;
|
|
361
|
+
}
|
|
362
|
+
let total = 0;
|
|
363
|
+
for (const message of messages) {
|
|
364
|
+
total += counter(message);
|
|
365
|
+
}
|
|
366
|
+
return total;
|
|
367
|
+
} catch {
|
|
368
|
+
return undefined;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Instruction overhead the provider processed but that never appears in the
|
|
374
|
+
* message array: `createCallModel` pipes the model through
|
|
375
|
+
* `agentContext.systemRunnable` and binds tool schemas AFTER `messages` is
|
|
376
|
+
* formed, so the system prompt, dynamic instructions, summary and tool
|
|
377
|
+
* schemas are all billed yet invisible here.
|
|
378
|
+
*
|
|
379
|
+
* Read per-node via `getAgentContext(metadata)` rather than the graph-level
|
|
380
|
+
* accessor, which is hardcoded to `defaultAgentId` and would report the wrong
|
|
381
|
+
* agent's overhead in a `MultiAgentGraph`.
|
|
382
|
+
*/
|
|
383
|
+
function sealedInstructionOverhead(
|
|
384
|
+
context: InvokeContext | undefined,
|
|
385
|
+
metadata: Record<string, unknown> | undefined
|
|
386
|
+
): number {
|
|
387
|
+
try {
|
|
388
|
+
const agentContext = context?.getAgentContext(metadata);
|
|
389
|
+
return (
|
|
390
|
+
agentContext?.resolvedInstructionOverhead ??
|
|
391
|
+
agentContext?.instructionTokens ??
|
|
392
|
+
0
|
|
393
|
+
);
|
|
394
|
+
} catch {
|
|
395
|
+
return 0;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Best-effort usage for a turn the provider never got to bill us for.
|
|
401
|
+
*
|
|
402
|
+
* The prompt matters as much as the completion: the provider processed the
|
|
403
|
+
* ENTIRE prompt — messages plus instruction overhead — before we sealed, and
|
|
404
|
+
* every resume re-sends it, so under-counting input hides the expensive half
|
|
405
|
+
* of a preempted run.
|
|
406
|
+
*
|
|
407
|
+
* ESTIMATE, NOT MEASUREMENT. Messages are counted with the host's tokenizer
|
|
408
|
+
* rather than the provider's, and `toolSchemaTokens` applies a heuristic
|
|
409
|
+
* multiplier. It is also an over-count on the fallback path, where
|
|
410
|
+
* `tryFallbackProviders` builds a bare model with no `systemRunnable` pipe so
|
|
411
|
+
* the system prompt genuinely is not sent. Accepted rather than threaded
|
|
412
|
+
* through a flag: only the fallback-plus-seal combination is affected, and an
|
|
413
|
+
* over-count is safer than the previous fabricated `input_tokens: 0`.
|
|
414
|
+
*
|
|
415
|
+
* Marked `estimated_usage` so calibration can refuse to learn from it — a
|
|
416
|
+
* ratio derived from the same counter that produced the estimate is
|
|
417
|
+
* self-consistent by construction and would drag a provider's real
|
|
418
|
+
* calibration toward 1.0.
|
|
419
|
+
*/
|
|
420
|
+
function synthesizeSealedUsage(
|
|
421
|
+
context: InvokeContext | undefined,
|
|
422
|
+
chunk: AIMessageChunk,
|
|
423
|
+
prompt: BaseMessage[],
|
|
424
|
+
metadata: Record<string, unknown> | undefined
|
|
425
|
+
): void {
|
|
426
|
+
if (chunk.usage_metadata != null) {
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
const outputTokens = countSealedTokens(context, metadata, [chunk]);
|
|
430
|
+
if (outputTokens == null) {
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
const inputTokens =
|
|
434
|
+
(countSealedTokens(context, metadata, prompt) ?? 0) +
|
|
435
|
+
sealedInstructionOverhead(context, metadata);
|
|
436
|
+
chunk.usage_metadata = {
|
|
437
|
+
input_tokens: inputTokens,
|
|
438
|
+
output_tokens: outputTokens,
|
|
439
|
+
total_tokens: inputTokens + outputTokens,
|
|
440
|
+
};
|
|
441
|
+
chunk.response_metadata = {
|
|
442
|
+
...chunk.response_metadata,
|
|
443
|
+
estimated_usage: true,
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
function getMessageText(chunk: AIMessageChunk): string {
|
|
448
|
+
if (typeof chunk.content === 'string') {
|
|
449
|
+
return chunk.content;
|
|
450
|
+
}
|
|
451
|
+
let text = '';
|
|
452
|
+
for (const block of chunk.content) {
|
|
453
|
+
if (block.type === ContentTypes.TEXT) {
|
|
454
|
+
const value = block[ContentTypes.TEXT];
|
|
455
|
+
if (typeof value === 'string') {
|
|
456
|
+
text += value;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
return text;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Ends the real model run for a turn that was sealed mid-stream.
|
|
465
|
+
*
|
|
466
|
+
* Mandatory, not cosmetic. `@langchain/core`'s `_streamIterator` calls
|
|
467
|
+
* `handleLLMEnd` after its try/catch with no `finally`, so breaking out of the
|
|
468
|
+
* consumer's `for await` produces a *return* completion that fires neither
|
|
469
|
+
* `handleLLMError` nor `handleLLMEnd`. The run would stay open in every
|
|
470
|
+
* callback handler: the host records no usage — and since each seal re-sends
|
|
471
|
+
* the whole prompt, N preemptions cost N unrecorded prompts — while LangSmith
|
|
472
|
+
* and Langfuse hold a span that never closes.
|
|
473
|
+
*
|
|
474
|
+
* `runId` cannot be dictated from here (the bound runnable consumes
|
|
475
|
+
* `config.runId` for its own run and hands the chat model a fresh one), but it
|
|
476
|
+
* can be OBSERVED: the capture handler installed at the `model.stream` call
|
|
477
|
+
* records it from `handleChatModelStart`, which fires before the first chunk.
|
|
478
|
+
* Rebuilding the manager against that id closes the real run, and the host's
|
|
479
|
+
* `on_chat_model_end` then arrives through the ordinary `streamEvents` path.
|
|
480
|
+
*
|
|
481
|
+
* Falls back to a custom-event dispatch if the id was never observed, so the
|
|
482
|
+
* host still records usage even when the native close is unavailable.
|
|
483
|
+
*/
|
|
484
|
+
/**
|
|
485
|
+
* Every callbacks source the real model run would compose beyond the per-call
|
|
486
|
+
* config. `model` here is whatever `createCallModel` produced — with tools
|
|
487
|
+
* that is `bindTools(...)`'s `RunnableBinding`, and a system runnable pipes a
|
|
488
|
+
* `RunnableSequence` on top — while `clientOptions.callbacks` lives on the
|
|
489
|
+
* chat model at the BOTTOM of that stack. Walks `bound` (bindings) and
|
|
490
|
+
* `last`/`steps` (sequences), collecting each wrapper's own `callbacks` and
|
|
491
|
+
* any binding-config callbacks along the way, since the binding merges its
|
|
492
|
+
* config into the call before the chat model composes.
|
|
493
|
+
*/
|
|
494
|
+
function collectModelCallbackSources(model: unknown): Callbacks[] {
|
|
495
|
+
const sources: Callbacks[] = [];
|
|
496
|
+
const seen = new Set<unknown>();
|
|
497
|
+
let current: unknown = model;
|
|
498
|
+
while (current != null && typeof current === 'object' && !seen.has(current)) {
|
|
499
|
+
seen.add(current);
|
|
500
|
+
const wrapper = current as {
|
|
501
|
+
callbacks?: Callbacks;
|
|
502
|
+
config?: { callbacks?: Callbacks };
|
|
503
|
+
bound?: unknown;
|
|
504
|
+
last?: unknown;
|
|
505
|
+
steps?: unknown[];
|
|
506
|
+
};
|
|
507
|
+
if (wrapper.callbacks != null) {
|
|
508
|
+
sources.push(wrapper.callbacks);
|
|
509
|
+
}
|
|
510
|
+
if (wrapper.config?.callbacks != null) {
|
|
511
|
+
sources.push(wrapper.config.callbacks);
|
|
512
|
+
}
|
|
513
|
+
current =
|
|
514
|
+
wrapper.bound ??
|
|
515
|
+
wrapper.last ??
|
|
516
|
+
(Array.isArray(wrapper.steps)
|
|
517
|
+
? wrapper.steps[wrapper.steps.length - 1]
|
|
518
|
+
: undefined);
|
|
519
|
+
}
|
|
520
|
+
return sources;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* The serving model's id, read through the same wrapper stack
|
|
525
|
+
* `collectModelCallbackSources` walks — `bindTools` returns a
|
|
526
|
+
* `RunnableBinding` and a system runnable pipes a `RunnableSequence`, and
|
|
527
|
+
* neither exposes the chat model's `model` at the top level.
|
|
528
|
+
*/
|
|
529
|
+
export function resolveServingModelId(model: unknown): string | undefined {
|
|
530
|
+
const seen = new Set<unknown>();
|
|
531
|
+
let current: unknown = model;
|
|
532
|
+
while (current != null && typeof current === 'object' && !seen.has(current)) {
|
|
533
|
+
seen.add(current);
|
|
534
|
+
const wrapper = current as {
|
|
535
|
+
model?: unknown;
|
|
536
|
+
bound?: unknown;
|
|
537
|
+
last?: unknown;
|
|
538
|
+
steps?: unknown[];
|
|
539
|
+
};
|
|
540
|
+
if (typeof wrapper.model === 'string' && wrapper.model !== '') {
|
|
541
|
+
return wrapper.model;
|
|
542
|
+
}
|
|
543
|
+
current =
|
|
544
|
+
wrapper.bound ??
|
|
545
|
+
wrapper.last ??
|
|
546
|
+
(Array.isArray(wrapper.steps)
|
|
547
|
+
? wrapper.steps[wrapper.steps.length - 1]
|
|
548
|
+
: undefined);
|
|
549
|
+
}
|
|
550
|
+
return undefined;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
async function endSealedModelRun(
|
|
554
|
+
context: InvokeContext | undefined,
|
|
555
|
+
chunk: AIMessageChunk,
|
|
556
|
+
prompt: BaseMessage[],
|
|
557
|
+
llmRunId: string | undefined,
|
|
558
|
+
config?: RunnableConfig,
|
|
559
|
+
model?: t.ChatModel
|
|
560
|
+
): Promise<void> {
|
|
561
|
+
const metadata = config?.metadata as Record<string, unknown> | undefined;
|
|
562
|
+
synthesizeSealedUsage(context, chunk, prompt, metadata);
|
|
563
|
+
if (llmRunId != null) {
|
|
564
|
+
try {
|
|
565
|
+
let callbackManager = await getCallbackManagerForConfig(config);
|
|
566
|
+
/**
|
|
567
|
+
* The real model run composes the per-call config's callbacks WITH the
|
|
568
|
+
* model's own (`CallbackManager.configure(config.callbacks,
|
|
569
|
+
* this.callbacks, …)` in `@langchain/core`'s base chat model), so a
|
|
570
|
+
* handler supplied via `clientOptions.callbacks` received
|
|
571
|
+
* `handleChatModelStart` for this run. Rebuilding from the config alone
|
|
572
|
+
* would close the run for every handler EXCEPT those — leaving their
|
|
573
|
+
* span open forever. Composed the same way the real run composes:
|
|
574
|
+
* model callbacks appended non-inheritable, parent run id preserved by
|
|
575
|
+
* `copy`, tracers deduped by `configure`.
|
|
576
|
+
*/
|
|
577
|
+
for (const source of collectModelCallbackSources(model)) {
|
|
578
|
+
callbackManager =
|
|
579
|
+
CallbackManager.configure(callbackManager ?? undefined, source) ??
|
|
580
|
+
callbackManager;
|
|
581
|
+
}
|
|
582
|
+
if (callbackManager != null) {
|
|
583
|
+
const runManager = new CallbackManagerForLLMRun(
|
|
584
|
+
llmRunId,
|
|
585
|
+
callbackManager.handlers,
|
|
586
|
+
callbackManager.inheritableHandlers,
|
|
587
|
+
callbackManager.tags,
|
|
588
|
+
callbackManager.inheritableTags,
|
|
589
|
+
callbackManager.metadata,
|
|
590
|
+
callbackManager.inheritableMetadata,
|
|
591
|
+
callbackManager.getParentRunId()
|
|
592
|
+
);
|
|
593
|
+
const generation: ChatGeneration = {
|
|
594
|
+
text: getMessageText(chunk),
|
|
595
|
+
message: chunk,
|
|
596
|
+
};
|
|
597
|
+
await runManager.handleLLMEnd({
|
|
598
|
+
generations: [[generation]],
|
|
599
|
+
llmOutput: {},
|
|
600
|
+
});
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
} catch (e) {
|
|
604
|
+
/**
|
|
605
|
+
* A sealed answer that reaches the user is worth more than a tidy
|
|
606
|
+
* trace. Fall through to the custom event rather than failing the run.
|
|
607
|
+
*/
|
|
608
|
+
// eslint-disable-next-line no-console
|
|
609
|
+
console.warn(
|
|
610
|
+
'[attemptInvoke] Native close of the sealed model run failed; falling back to a custom event:',
|
|
611
|
+
e instanceof Error ? e.message : e
|
|
612
|
+
);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
await safeDispatchCustomEvent(
|
|
616
|
+
GraphEvents.CHAT_MODEL_END,
|
|
617
|
+
{ output: chunk },
|
|
618
|
+
config
|
|
619
|
+
);
|
|
620
|
+
}
|
|
621
|
+
|
|
321
622
|
function appendStreamChunk({
|
|
322
623
|
current,
|
|
323
624
|
next,
|
|
@@ -376,11 +677,58 @@ export async function attemptInvoke(
|
|
|
376
677
|
});
|
|
377
678
|
const registry = context?.getOrCreateToolOutputRegistry();
|
|
378
679
|
const runId = config?.configurable?.run_id as string | undefined;
|
|
379
|
-
const
|
|
680
|
+
const annotated = annotateMessagesForLLM(
|
|
380
681
|
invocationMessages,
|
|
381
682
|
registry,
|
|
382
683
|
runId
|
|
383
684
|
);
|
|
685
|
+
/**
|
|
686
|
+
* Keyed on the provider ACTUALLY serving this call, not the agent's primary.
|
|
687
|
+
* `createCallModel` normalizes for the primary, but `tryFallbackProviders`
|
|
688
|
+
* re-sends the same array — so an OpenAI primary that fails after a boundary
|
|
689
|
+
* injected two human turns would hand a Bedrock or Mistral fallback the
|
|
690
|
+
* consecutive user turns those APIs reject, and the recovery request would
|
|
691
|
+
* fail for a reason unrelated to the original failure.
|
|
692
|
+
*
|
|
693
|
+
* `attemptInvoke` is the single funnel for primary, fallback and
|
|
694
|
+
* summarization calls, so applying it here covers all three. Idempotent, so
|
|
695
|
+
* the primary simply re-runs a no-op over already-coalesced messages.
|
|
696
|
+
*/
|
|
697
|
+
/**
|
|
698
|
+
* Serving-provider re-keying for the predecessor handoff cue (#345). The
|
|
699
|
+
* PRIMARY's cue is baked in createCallModel's measured transform stage —
|
|
700
|
+
* appending after measurement could push a just-fits prompt over budget —
|
|
701
|
+
* so this funnel only corrects for fallbacks crossing provider families:
|
|
702
|
+
* a tolerant primary falling back to a Claude surface gains the cue here,
|
|
703
|
+
* and an Anthropic primary falling back to OpenAI/Mistral/Nova has the
|
|
704
|
+
* Claude-only synthetic turn stripped. Both helpers are identity on their
|
|
705
|
+
* no-op paths, so the primary's own pass re-runs for free.
|
|
706
|
+
*
|
|
707
|
+
* The serving model id is read through the wrapper stack (`bindTools`'
|
|
708
|
+
* binding, a system runnable's sequence) — a wrapper's top-level `.model`
|
|
709
|
+
* is undefined, and `isAnthropicLike` would otherwise default a wrapped
|
|
710
|
+
* Bedrock-Nova model to Claude. The context cast is widened deliberately:
|
|
711
|
+
* the type says every context is a full Graph, but summarization passes
|
|
712
|
+
* none and long-standing tests pass partial stubs.
|
|
713
|
+
*/
|
|
714
|
+
const isRunProduced = (
|
|
715
|
+
context as
|
|
716
|
+
| { isRunProducedMessage?: (message: BaseMessage) => boolean }
|
|
717
|
+
| undefined
|
|
718
|
+
)?.isRunProducedMessage;
|
|
719
|
+
const cued = isAnthropicLike(provider, {
|
|
720
|
+
model: resolveServingModelId(model),
|
|
721
|
+
})
|
|
722
|
+
? appendPredecessorHandoffCue(
|
|
723
|
+
annotated,
|
|
724
|
+
isRunProduced == null
|
|
725
|
+
? undefined
|
|
726
|
+
: (message): boolean => isRunProduced.call(context, message)
|
|
727
|
+
)
|
|
728
|
+
: removePredecessorHandoffCue(annotated);
|
|
729
|
+
const messagesForProvider = strictAlternationProviders.has(provider)
|
|
730
|
+
? coalesceAdjacentUserTurns(cued)
|
|
731
|
+
: cued;
|
|
384
732
|
|
|
385
733
|
/**
|
|
386
734
|
* Stamp the provider that is ACTUALLY serving this invocation onto the
|
|
@@ -400,8 +748,34 @@ export async function attemptInvoke(
|
|
|
400
748
|
};
|
|
401
749
|
|
|
402
750
|
if (model.stream) {
|
|
403
|
-
|
|
751
|
+
/**
|
|
752
|
+
* Observed, not dictated. `handleChatModelStart` fires with the chat
|
|
753
|
+
* model's real run id before the first chunk, which is the only way to
|
|
754
|
+
* name the run a seal has to close — pinning `config.runId` does not
|
|
755
|
+
* survive the bound runnable. Installed only when preemption is
|
|
756
|
+
* configured, so a run that cannot seal carries no extra handler.
|
|
757
|
+
*/
|
|
758
|
+
let sealedRunId: string | undefined;
|
|
759
|
+
const streamConfig =
|
|
760
|
+
context?.preemption == null
|
|
761
|
+
? config
|
|
762
|
+
: {
|
|
763
|
+
...config,
|
|
764
|
+
callbacks: appendCallbacks(config.callbacks, [
|
|
765
|
+
{
|
|
766
|
+
handleChatModelStart: (
|
|
767
|
+
_llm: Serialized,
|
|
768
|
+
_messages: BaseMessage[][],
|
|
769
|
+
runId: string
|
|
770
|
+
): void => {
|
|
771
|
+
sealedRunId ??= runId;
|
|
772
|
+
},
|
|
773
|
+
},
|
|
774
|
+
]),
|
|
775
|
+
};
|
|
776
|
+
const stream = await model.stream(messagesForProvider, streamConfig);
|
|
404
777
|
let finalChunk: AIMessageChunk | undefined;
|
|
778
|
+
let preempted = false;
|
|
405
779
|
const registeredStreamHandler =
|
|
406
780
|
getRegisteredDefaultChatStreamHandler(context);
|
|
407
781
|
|
|
@@ -436,6 +810,26 @@ export async function attemptInvoke(
|
|
|
436
810
|
next: chunk,
|
|
437
811
|
provider,
|
|
438
812
|
});
|
|
813
|
+
/**
|
|
814
|
+
* Only this loop may seal. The registered-handler branch below
|
|
815
|
+
* dispatches through `run.ts`'s decoupled `streamEvents` consumer,
|
|
816
|
+
* which can lag the accumulated chunk — sealing there would let the
|
|
817
|
+
* host index a content part the user has not been shown yet.
|
|
818
|
+
*/
|
|
819
|
+
/**
|
|
820
|
+
* Cheap poll first, shape check second, budget claim last. The claim
|
|
821
|
+
* is what makes this safe under a parallel `MultiAgentGraph`: several
|
|
822
|
+
* agents share one graph and can each see the poll as true, but only
|
|
823
|
+
* one can take the slot, and a chunk that cannot seal never spends it.
|
|
824
|
+
*/
|
|
825
|
+
if (
|
|
826
|
+
context?.shouldPreemptStream() === true &&
|
|
827
|
+
canSealPreempt(finalChunk) &&
|
|
828
|
+
context.claimPreemptSeal()
|
|
829
|
+
) {
|
|
830
|
+
preempted = true;
|
|
831
|
+
break;
|
|
832
|
+
}
|
|
439
833
|
}
|
|
440
834
|
} else {
|
|
441
835
|
const metadata = config.metadata as Record<string, unknown> | undefined;
|
|
@@ -465,6 +859,21 @@ export async function attemptInvoke(
|
|
|
465
859
|
finalChunk = modifyDeltaProperties(provider, finalChunk);
|
|
466
860
|
}
|
|
467
861
|
|
|
862
|
+
if (preempted && finalChunk != null) {
|
|
863
|
+
finalChunk.response_metadata = {
|
|
864
|
+
...finalChunk.response_metadata,
|
|
865
|
+
preempted: true,
|
|
866
|
+
};
|
|
867
|
+
await endSealedModelRun(
|
|
868
|
+
context,
|
|
869
|
+
finalChunk,
|
|
870
|
+
messagesForProvider,
|
|
871
|
+
sealedRunId,
|
|
872
|
+
config,
|
|
873
|
+
model
|
|
874
|
+
);
|
|
875
|
+
}
|
|
876
|
+
|
|
468
877
|
if ((finalChunk?.tool_calls?.length ?? 0) > 0) {
|
|
469
878
|
finalChunk!.tool_calls = finalChunk!.tool_calls?.filter(
|
|
470
879
|
(tool_call: ToolCall) => !!tool_call.name
|
package/src/llm/openai/index.ts
CHANGED
|
@@ -51,6 +51,7 @@ import {
|
|
|
51
51
|
projectOpenAIResponsesToolMessageContent,
|
|
52
52
|
projectToolStreamContentForProvider,
|
|
53
53
|
} from '@/messages/core';
|
|
54
|
+
import { INTENT_ARG, isIntentLabelProperty } from '@/tools/intentArg';
|
|
54
55
|
import { isReasoningModel, _convertMessagesToOpenAIParams } from './utils';
|
|
55
56
|
import { dropRepeatedScalarMetadata } from './streamMetadata';
|
|
56
57
|
|
|
@@ -1003,6 +1004,65 @@ function createAbortHandler(controller: AbortController): () => void {
|
|
|
1003
1004
|
* @param {Object} [fields] Additional fields to add to the OpenAI tool.
|
|
1004
1005
|
* @returns {ToolDefinition} The inputted tool in OpenAI tool format.
|
|
1005
1006
|
*/
|
|
1007
|
+
/**
|
|
1008
|
+
* OpenAI strict function schemas require every property to appear in
|
|
1009
|
+
* `required`. The optional `intent` label (see `tools/intentArg.ts`) is
|
|
1010
|
+
* deliberately NOT required — the same schema is callable from programmatic
|
|
1011
|
+
* tool calling — so a tool auto-marked `strict: true` (the non-streaming
|
|
1012
|
+
* `json_schema` structured-output path) would be rejected as invalid before
|
|
1013
|
+
* execution. That path never streams a live label anyway, so the
|
|
1014
|
+
* marker-identified property is dropped there; every other path keeps it.
|
|
1015
|
+
*/
|
|
1016
|
+
function stripIntentFromStrictTools<T extends object>(params: T): T {
|
|
1017
|
+
const record = params as { tools?: unknown[] };
|
|
1018
|
+
const tools = record.tools;
|
|
1019
|
+
if (!Array.isArray(tools) || tools.length === 0) {
|
|
1020
|
+
return params;
|
|
1021
|
+
}
|
|
1022
|
+
const nextTools = tools.map((tool) => {
|
|
1023
|
+
const candidate = tool as {
|
|
1024
|
+
strict?: boolean;
|
|
1025
|
+
parameters?: { properties?: Record<string, unknown>; required?: unknown };
|
|
1026
|
+
function?: {
|
|
1027
|
+
strict?: boolean;
|
|
1028
|
+
parameters?: {
|
|
1029
|
+
properties?: Record<string, unknown>;
|
|
1030
|
+
required?: unknown;
|
|
1031
|
+
};
|
|
1032
|
+
};
|
|
1033
|
+
};
|
|
1034
|
+
/** Chat-completions tools nest under `function`; responses-API tools are flat. */
|
|
1035
|
+
const holder = candidate.function ?? candidate;
|
|
1036
|
+
if (holder.strict !== true) {
|
|
1037
|
+
return tool;
|
|
1038
|
+
}
|
|
1039
|
+
const parameters = holder.parameters;
|
|
1040
|
+
const properties = parameters?.properties;
|
|
1041
|
+
if (properties == null || !isIntentLabelProperty(properties[INTENT_ARG])) {
|
|
1042
|
+
return tool;
|
|
1043
|
+
}
|
|
1044
|
+
const required = Array.isArray(parameters?.required)
|
|
1045
|
+
? (parameters.required as unknown[])
|
|
1046
|
+
: [];
|
|
1047
|
+
if (required.includes(INTENT_ARG)) {
|
|
1048
|
+
return tool;
|
|
1049
|
+
}
|
|
1050
|
+
const { [INTENT_ARG]: _omit, ...restProps } = properties;
|
|
1051
|
+
const nextParams = { ...parameters, properties: restProps };
|
|
1052
|
+
if (candidate.function != null) {
|
|
1053
|
+
return {
|
|
1054
|
+
...candidate,
|
|
1055
|
+
function: { ...candidate.function, parameters: nextParams },
|
|
1056
|
+
};
|
|
1057
|
+
}
|
|
1058
|
+
return { ...candidate, parameters: nextParams };
|
|
1059
|
+
});
|
|
1060
|
+
if (nextTools.every((tool, index) => tool === tools[index])) {
|
|
1061
|
+
return params;
|
|
1062
|
+
}
|
|
1063
|
+
return { ...params, tools: nextTools } as T;
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1006
1066
|
export function _convertToOpenAITool(
|
|
1007
1067
|
tool: BindToolsInput,
|
|
1008
1068
|
fields?: {
|
|
@@ -1184,10 +1244,12 @@ class LibreChatOpenAICompletions extends OriginalChatOpenAICompletions {
|
|
|
1184
1244
|
options?: this['ParsedCallOptions'],
|
|
1185
1245
|
extra?: { streaming?: boolean }
|
|
1186
1246
|
): ReturnType<OriginalChatOpenAICompletions['invocationParams']> {
|
|
1187
|
-
return
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1247
|
+
return stripIntentFromStrictTools(
|
|
1248
|
+
applyManagedRequestParams(super.invocationParams(options, extra), {
|
|
1249
|
+
promptCacheExplicit: this.promptCacheExplicit,
|
|
1250
|
+
safetyIdentifier: this.safetyIdentifier,
|
|
1251
|
+
})
|
|
1252
|
+
);
|
|
1191
1253
|
}
|
|
1192
1254
|
|
|
1193
1255
|
protected _getReasoningParams(
|
|
@@ -1640,7 +1702,7 @@ class LibreChatOpenAIResponses extends OriginalChatOpenAIResponses {
|
|
|
1640
1702
|
]),
|
|
1641
1703
|
];
|
|
1642
1704
|
}
|
|
1643
|
-
return params;
|
|
1705
|
+
return stripIntentFromStrictTools(params);
|
|
1644
1706
|
}
|
|
1645
1707
|
|
|
1646
1708
|
async completionWithRetry(
|
|
@@ -1741,10 +1803,12 @@ class LibreChatAzureOpenAICompletions extends OriginalAzureChatOpenAICompletions
|
|
|
1741
1803
|
options?: this['ParsedCallOptions'],
|
|
1742
1804
|
extra?: { streaming?: boolean }
|
|
1743
1805
|
): ReturnType<OriginalAzureChatOpenAICompletions['invocationParams']> {
|
|
1744
|
-
return
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1806
|
+
return stripIntentFromStrictTools(
|
|
1807
|
+
applyManagedRequestParams(super.invocationParams(options, extra), {
|
|
1808
|
+
promptCacheExplicit: this.promptCacheExplicit,
|
|
1809
|
+
safetyIdentifier: this.safetyIdentifier,
|
|
1810
|
+
})
|
|
1811
|
+
);
|
|
1748
1812
|
}
|
|
1749
1813
|
|
|
1750
1814
|
protected _getReasoningParams(
|
|
@@ -1888,7 +1952,7 @@ class LibreChatAzureOpenAIResponses extends OriginalAzureChatOpenAIResponses {
|
|
|
1888
1952
|
]),
|
|
1889
1953
|
];
|
|
1890
1954
|
}
|
|
1891
|
-
return params;
|
|
1955
|
+
return stripIntentFromStrictTools(params);
|
|
1892
1956
|
}
|
|
1893
1957
|
|
|
1894
1958
|
async completionWithRetry(
|