@jsonstudio/llms 0.6.3541 → 0.6.3685
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/conversion/compat/actions/antigravity-thought-signature-cache.js +23 -114
- package/dist/conversion/compat/actions/auto-thinking.js +3 -2
- package/dist/conversion/compat/actions/deepseek-web-response.js +9 -50
- package/dist/conversion/compat/actions/field-mapping.js +2 -153
- package/dist/conversion/compat/actions/gemini-cli-request.d.ts +2 -0
- package/dist/conversion/compat/actions/gemini-cli-request.js +1 -1
- package/dist/conversion/compat/actions/glm-history-image-trim.js +3 -37
- package/dist/conversion/compat/actions/glm-image-content.js +3 -32
- package/dist/conversion/compat/actions/glm-native-compat.d.ts +6 -0
- package/dist/conversion/compat/actions/glm-native-compat.js +34 -0
- package/dist/conversion/compat/actions/glm-vision-prompt.js +3 -76
- package/dist/conversion/compat/actions/glm-web-search.js +10 -43
- package/dist/conversion/compat/actions/iflow-kimi-cli-defaults.js +4 -53
- package/dist/conversion/compat/actions/iflow-kimi-history-media-placeholder.js +5 -141
- package/dist/conversion/compat/actions/iflow-kimi-thinking-reasoning-fill.js +7 -28
- package/dist/conversion/compat/actions/iflow-native-compat.d.ts +6 -0
- package/dist/conversion/compat/actions/iflow-native-compat.js +36 -0
- package/dist/conversion/compat/actions/iflow-response-body-unwrap.js +4 -119
- package/dist/conversion/compat/actions/iflow-web-search.js +14 -55
- package/dist/conversion/compat/actions/lmstudio-responses-input-stringify.js +3 -104
- package/dist/conversion/hub/node-support.js +1 -1
- package/dist/conversion/hub/operation-table/semantic-mappers/anthropic-mapper.js +9 -1
- package/dist/conversion/hub/operation-table/semantic-mappers/archive/chat-mapper.archive.js +5 -0
- package/dist/conversion/hub/operation-table/semantic-mappers/responses-mapper.js +34 -14
- package/dist/conversion/hub/pipeline/hub-pipeline.d.ts +14 -14
- package/dist/conversion/hub/pipeline/hub-pipeline.js +838 -524
- package/dist/conversion/hub/pipeline/hub-stage-timing.d.ts +6 -0
- package/dist/conversion/hub/pipeline/hub-stage-timing.js +178 -0
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage1_format_parse/index.js +6 -4
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage2_semantic_map/index.js +46 -0
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/context-capture-orchestration.d.ts +3 -0
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/context-capture-orchestration.js +2 -1
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/context-factories.js +2 -0
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/index.js +1 -0
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/responses-context-snapshot.d.ts +3 -2
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/responses-context-snapshot.js +18 -5
- package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/context-merge.d.ts +1 -2
- package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/context-merge.js +0 -16
- package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/index.d.ts +1 -1
- package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/index.js +30 -12
- package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage1_tool_governance/index.d.ts +1 -0
- package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage1_tool_governance/index.js +5 -2
- package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage2_route_select/index.d.ts +1 -1
- package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage2_route_select/index.js +9 -5
- package/dist/conversion/hub/process/chat-process-continue-execution.js +2 -4
- package/dist/conversion/hub/process/chat-process-governance-orchestration.js +3 -1
- package/dist/conversion/hub/process/chat-process-media.d.ts +1 -0
- package/dist/conversion/hub/process/chat-process-media.js +36 -0
- package/dist/conversion/hub/process/chat-process-session-usage.d.ts +25 -0
- package/dist/conversion/hub/process/chat-process-session-usage.js +246 -0
- package/dist/conversion/hub/response/provider-response.js +13 -0
- package/dist/conversion/hub/types/chat-envelope.d.ts +1 -0
- package/dist/conversion/pipeline/codecs/v2/openai-openai-pipeline.js +0 -4
- package/dist/conversion/responses/responses-openai-bridge/response-payload.js +0 -12
- package/dist/conversion/responses/responses-openai-bridge/types.d.ts +1 -9
- package/dist/conversion/responses/responses-openai-bridge.d.ts +1 -0
- package/dist/conversion/responses/responses-openai-bridge.js +51 -24
- package/dist/conversion/shared/anthropic-message-utils.js +14 -1
- package/dist/conversion/shared/reasoning-normalizer.js +61 -0
- package/dist/conversion/shared/tool-governor.js +2 -4
- package/dist/native/router_hotpath_napi.node +0 -0
- package/dist/quota/quota-state.js +1 -6
- package/dist/router/virtual-router/bootstrap/profile-builder.js +1 -0
- package/dist/router/virtual-router/bootstrap/provider-normalization.d.ts +1 -0
- package/dist/router/virtual-router/bootstrap/provider-normalization.js +6 -0
- package/dist/router/virtual-router/bootstrap.js +1 -6
- package/dist/router/virtual-router/engine/routing-state/store.js +21 -2
- package/dist/router/virtual-router/engine-legacy.js +43 -0
- package/dist/router/virtual-router/engine-logging.d.ts +3 -0
- package/dist/router/virtual-router/engine-logging.js +29 -3
- package/dist/router/virtual-router/engine-selection/native-chat-process-governed-filter-semantics.d.ts +1 -0
- package/dist/router/virtual-router/engine-selection/native-chat-process-governed-filter-semantics.js +1 -0
- package/dist/router/virtual-router/engine-selection/native-compat-action-semantics.d.ts +3 -0
- package/dist/router/virtual-router/engine-selection/native-compat-action-semantics.js +72 -0
- package/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics.d.ts +1 -1
- package/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics.js +1 -1
- package/dist/router/virtual-router/engine-selection/native-hub-pipeline-inbound-outbound-semantics.d.ts +0 -1
- package/dist/router/virtual-router/engine-selection/native-hub-pipeline-inbound-outbound-semantics.js +0 -29
- package/dist/router/virtual-router/engine-selection/native-hub-pipeline-req-process-semantics.d.ts +1 -0
- package/dist/router/virtual-router/engine-selection/native-router-hotpath-loader.js +6 -2
- package/dist/router/virtual-router/engine.js +28 -13
- package/dist/router/virtual-router/provider-registry.js +1 -0
- package/dist/router/virtual-router/routing-instructions/state.js +44 -2
- package/dist/router/virtual-router/routing-instructions/types.d.ts +6 -0
- package/dist/router/virtual-router/token-estimator.js +21 -0
- package/dist/router/virtual-router/types.d.ts +7 -0
- package/dist/servertool/engine.js +3 -34
- package/dist/servertool/handlers/followup-request-builder.js +0 -6
- package/dist/servertool/handlers/gemini-empty-reply-continue.js +3 -274
- package/dist/servertool/handlers/stop-message-auto/runtime-utils.d.ts +0 -3
- package/dist/servertool/handlers/stop-message-auto/runtime-utils.js +0 -29
- package/dist/servertool/handlers/stop-message-auto.js +11 -9
- package/dist/servertool/handlers/vision.js +4 -1
- package/dist/servertool/server-side-tools.d.ts +0 -1
- package/dist/servertool/server-side-tools.js +67 -5
- package/dist/tools/apply-patch/execution-capturer.d.ts +1 -1
- package/dist/tools/apply-patch/execution-capturer.js +1 -2
- package/dist/tools/apply-patch/regression-capturer.js +2 -1
- package/dist/tools/tool-registry.js +1 -2
- package/package.json +1 -1
|
@@ -6,6 +6,7 @@ import { ProviderRegistry } from './provider-registry.js';
|
|
|
6
6
|
import { resolveStopMessageScope } from './engine/routing-state/store.js';
|
|
7
7
|
import { loadRoutingInstructionStateSync } from './sticky-session-store.js';
|
|
8
8
|
import { mergeStopMessageFromPersisted } from './stop-message-state-sync.js';
|
|
9
|
+
import { resolveSessionColor } from './engine-logging.js';
|
|
9
10
|
export class VirtualRouterEngine {
|
|
10
11
|
nativeProxy;
|
|
11
12
|
registry;
|
|
@@ -72,6 +73,7 @@ export class VirtualRouterEngine {
|
|
|
72
73
|
parseLog?.scopedTypes.some((type) => type === 'stopMessageSet' || type === 'stopMessageMode' || type === 'stopMessageClear'));
|
|
73
74
|
emitVirtualRouterHitLog(parsed, {
|
|
74
75
|
requestId: metadata.requestId,
|
|
76
|
+
sessionId: resolveVirtualRouterLogSessionId(metadata),
|
|
75
77
|
stopScope,
|
|
76
78
|
stopState,
|
|
77
79
|
forceStopStatusLabel
|
|
@@ -176,6 +178,12 @@ function extractNativeErrorMessage(error) {
|
|
|
176
178
|
if (error instanceof Error) {
|
|
177
179
|
return error.message;
|
|
178
180
|
}
|
|
181
|
+
if (error && typeof error === 'object') {
|
|
182
|
+
const message = error.message;
|
|
183
|
+
if (typeof message === 'string') {
|
|
184
|
+
return message;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
179
187
|
return '';
|
|
180
188
|
}
|
|
181
189
|
function parseVirtualRouterErrorMessage(message) {
|
|
@@ -274,30 +282,37 @@ function emitVirtualRouterHitLog(result, options) {
|
|
|
274
282
|
const prefixColor = '\x1b[38;5;208m';
|
|
275
283
|
const timeColor = '\x1b[90m';
|
|
276
284
|
const stopColor = '\x1b[38;5;214m';
|
|
277
|
-
const routeColorMap = {
|
|
278
|
-
multimodal: '\x1b[38;5;45m',
|
|
279
|
-
tools: '\x1b[38;5;214m',
|
|
280
|
-
thinking: '\x1b[34m',
|
|
281
|
-
coding: '\x1b[35m',
|
|
282
|
-
longcontext: '\x1b[38;5;141m',
|
|
283
|
-
web_search: '\x1b[32m',
|
|
284
|
-
search: '\x1b[38;5;34m',
|
|
285
|
-
vision: '\x1b[38;5;207m',
|
|
286
|
-
background: '\x1b[90m'
|
|
287
|
-
};
|
|
288
285
|
const now = new Date();
|
|
289
286
|
const timestamp = `${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}`;
|
|
290
287
|
const routeLabel = result.decision.poolId
|
|
291
288
|
? `${result.decision.routeName}/${result.decision.poolId}`
|
|
292
289
|
: result.decision.routeName;
|
|
293
|
-
const routeColor =
|
|
290
|
+
const routeColor = resolveSessionColor(options?.sessionId);
|
|
294
291
|
const providerKey = result.decision.providerKey || result.target.providerKey;
|
|
295
292
|
const modelSuffix = result.target.modelId ? `.${result.target.modelId}` : '';
|
|
296
293
|
const reason = result.decision.reasoning ? ` reason=${result.decision.reasoning}` : '';
|
|
297
294
|
const stopStatusLabel = formatStopMessageStatusLabel(options?.stopState ?? null, options?.stopScope, Boolean(options?.forceStopStatusLabel));
|
|
298
295
|
const requestId = typeof options?.requestId === 'string' ? options.requestId : '';
|
|
299
296
|
const requestLabel = requestId && !requestId.includes('unknown') ? ` req=${requestId}` : '';
|
|
300
|
-
|
|
297
|
+
const sessionId = typeof options?.sessionId === 'string' ? options.sessionId.trim() : '';
|
|
298
|
+
const sessionLabel = sessionId ? ` sid=${sessionId}` : '';
|
|
299
|
+
console.log(`${prefixColor}[virtual-router-hit]${reset} ${timeColor}${timestamp}${reset}${requestLabel}${sessionLabel} ${routeColor}${routeLabel} -> ${providerKey}${modelSuffix}${reason}${reset}${stopStatusLabel ? ` ${stopColor}${stopStatusLabel}${reset}` : ''}`);
|
|
300
|
+
}
|
|
301
|
+
function resolveVirtualRouterLogSessionId(metadata) {
|
|
302
|
+
const candidates = [
|
|
303
|
+
metadata.sessionId,
|
|
304
|
+
metadata.clientTmuxSessionId,
|
|
305
|
+
metadata.client_tmux_session_id,
|
|
306
|
+
metadata.tmuxSessionId,
|
|
307
|
+
metadata.tmux_session_id,
|
|
308
|
+
metadata.conversationId
|
|
309
|
+
];
|
|
310
|
+
for (const value of candidates) {
|
|
311
|
+
if (typeof value === 'string' && value.trim()) {
|
|
312
|
+
return value.trim();
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
return undefined;
|
|
301
316
|
}
|
|
302
317
|
function formatStopMessageStatusLabel(snapshot, scope, forceShow) {
|
|
303
318
|
const scopeLabel = scope && scope.trim() ? scope.trim() : 'none';
|
|
@@ -97,6 +97,7 @@ export class ProviderRegistry {
|
|
|
97
97
|
providerType: profile.providerType,
|
|
98
98
|
endpoint: profile.endpoint,
|
|
99
99
|
auth: profile.auth,
|
|
100
|
+
...(profile.enabled !== undefined ? { enabled: profile.enabled } : {}),
|
|
100
101
|
outboundProfile: profile.outboundProfile,
|
|
101
102
|
compatibilityProfile: profile.compatibilityProfile,
|
|
102
103
|
runtimeKey: profile.runtimeKey,
|
|
@@ -27,7 +27,13 @@ export function applyRoutingInstructions(instructions, currentState) {
|
|
|
27
27
|
: undefined,
|
|
28
28
|
preCommandSource: currentState.preCommandSource,
|
|
29
29
|
preCommandScriptPath: currentState.preCommandScriptPath,
|
|
30
|
-
preCommandUpdatedAt: currentState.preCommandUpdatedAt
|
|
30
|
+
preCommandUpdatedAt: currentState.preCommandUpdatedAt,
|
|
31
|
+
chatProcessInputTokens: currentState.chatProcessInputTokens,
|
|
32
|
+
chatProcessMessageCount: currentState.chatProcessMessageCount,
|
|
33
|
+
chatProcessToolsSignature: currentState.chatProcessToolsSignature,
|
|
34
|
+
chatProcessParametersSignature: currentState.chatProcessParametersSignature,
|
|
35
|
+
chatProcessBoundarySignature: currentState.chatProcessBoundarySignature,
|
|
36
|
+
chatProcessUpdatedAt: currentState.chatProcessUpdatedAt
|
|
31
37
|
};
|
|
32
38
|
let allowReset = false;
|
|
33
39
|
let disableReset = false;
|
|
@@ -185,6 +191,18 @@ export function serializeRoutingInstructionState(state) {
|
|
|
185
191
|
provider,
|
|
186
192
|
models: Array.from(models)
|
|
187
193
|
})),
|
|
194
|
+
...(typeof state.chatProcessInputTokens === 'number' && Number.isFinite(state.chatProcessInputTokens)
|
|
195
|
+
? { chatProcessInputTokens: state.chatProcessInputTokens }
|
|
196
|
+
: {}),
|
|
197
|
+
...(typeof state.chatProcessMessageCount === 'number' && Number.isFinite(state.chatProcessMessageCount)
|
|
198
|
+
? { chatProcessMessageCount: state.chatProcessMessageCount }
|
|
199
|
+
: {}),
|
|
200
|
+
...(state.chatProcessToolsSignature ? { chatProcessToolsSignature: state.chatProcessToolsSignature } : {}),
|
|
201
|
+
...(state.chatProcessParametersSignature ? { chatProcessParametersSignature: state.chatProcessParametersSignature } : {}),
|
|
202
|
+
...(state.chatProcessBoundarySignature ? { chatProcessBoundarySignature: state.chatProcessBoundarySignature } : {}),
|
|
203
|
+
...(typeof state.chatProcessUpdatedAt === 'number' && Number.isFinite(state.chatProcessUpdatedAt)
|
|
204
|
+
? { chatProcessUpdatedAt: state.chatProcessUpdatedAt }
|
|
205
|
+
: {}),
|
|
188
206
|
...serializeStopMessageState(state),
|
|
189
207
|
...serializePreCommandState(state)
|
|
190
208
|
};
|
|
@@ -208,7 +226,13 @@ export function deserializeRoutingInstructionState(data) {
|
|
|
208
226
|
stopMessageAiHistory: undefined,
|
|
209
227
|
preCommandSource: undefined,
|
|
210
228
|
preCommandScriptPath: undefined,
|
|
211
|
-
preCommandUpdatedAt: undefined
|
|
229
|
+
preCommandUpdatedAt: undefined,
|
|
230
|
+
chatProcessInputTokens: undefined,
|
|
231
|
+
chatProcessMessageCount: undefined,
|
|
232
|
+
chatProcessToolsSignature: undefined,
|
|
233
|
+
chatProcessParametersSignature: undefined,
|
|
234
|
+
chatProcessBoundarySignature: undefined,
|
|
235
|
+
chatProcessUpdatedAt: undefined
|
|
212
236
|
};
|
|
213
237
|
if (data.forcedTarget && typeof data.forcedTarget === 'object') {
|
|
214
238
|
state.forcedTarget = data.forcedTarget;
|
|
@@ -241,5 +265,23 @@ export function deserializeRoutingInstructionState(data) {
|
|
|
241
265
|
}
|
|
242
266
|
deserializeStopMessageState(data, state);
|
|
243
267
|
deserializePreCommandState(data, state);
|
|
268
|
+
if (typeof data.chatProcessInputTokens === 'number' && Number.isFinite(data.chatProcessInputTokens)) {
|
|
269
|
+
state.chatProcessInputTokens = data.chatProcessInputTokens;
|
|
270
|
+
}
|
|
271
|
+
if (typeof data.chatProcessMessageCount === 'number' && Number.isFinite(data.chatProcessMessageCount)) {
|
|
272
|
+
state.chatProcessMessageCount = data.chatProcessMessageCount;
|
|
273
|
+
}
|
|
274
|
+
if (typeof data.chatProcessToolsSignature === 'string' && data.chatProcessToolsSignature.trim()) {
|
|
275
|
+
state.chatProcessToolsSignature = data.chatProcessToolsSignature.trim();
|
|
276
|
+
}
|
|
277
|
+
if (typeof data.chatProcessParametersSignature === 'string' && data.chatProcessParametersSignature.trim()) {
|
|
278
|
+
state.chatProcessParametersSignature = data.chatProcessParametersSignature.trim();
|
|
279
|
+
}
|
|
280
|
+
if (typeof data.chatProcessBoundarySignature === 'string' && data.chatProcessBoundarySignature.trim()) {
|
|
281
|
+
state.chatProcessBoundarySignature = data.chatProcessBoundarySignature.trim();
|
|
282
|
+
}
|
|
283
|
+
if (typeof data.chatProcessUpdatedAt === 'number' && Number.isFinite(data.chatProcessUpdatedAt)) {
|
|
284
|
+
state.chatProcessUpdatedAt = data.chatProcessUpdatedAt;
|
|
285
|
+
}
|
|
244
286
|
return state;
|
|
245
287
|
}
|
|
@@ -67,4 +67,10 @@ export interface RoutingInstructionState {
|
|
|
67
67
|
preCommandSource?: string;
|
|
68
68
|
preCommandScriptPath?: string;
|
|
69
69
|
preCommandUpdatedAt?: number;
|
|
70
|
+
chatProcessInputTokens?: number;
|
|
71
|
+
chatProcessMessageCount?: number;
|
|
72
|
+
chatProcessToolsSignature?: string;
|
|
73
|
+
chatProcessParametersSignature?: string;
|
|
74
|
+
chatProcessBoundarySignature?: string;
|
|
75
|
+
chatProcessUpdatedAt?: number;
|
|
70
76
|
}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { countRequestTokens } from './token-counter.js';
|
|
2
2
|
export function computeRequestTokens(request, fallbackText) {
|
|
3
|
+
const metadataEstimate = readEstimatedTokensFromMetadata(request);
|
|
4
|
+
if (metadataEstimate !== undefined) {
|
|
5
|
+
return metadataEstimate;
|
|
6
|
+
}
|
|
3
7
|
try {
|
|
4
8
|
return countRequestTokens(request);
|
|
5
9
|
}
|
|
@@ -7,6 +11,23 @@ export function computeRequestTokens(request, fallbackText) {
|
|
|
7
11
|
return fallbackEstimateTokens(fallbackText, request.messages?.length ?? 0);
|
|
8
12
|
}
|
|
9
13
|
}
|
|
14
|
+
function readEstimatedTokensFromMetadata(request) {
|
|
15
|
+
const metadata = request?.metadata;
|
|
16
|
+
if (!metadata || typeof metadata !== 'object') {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
const candidates = [
|
|
20
|
+
metadata.estimatedInputTokens,
|
|
21
|
+
metadata.estimatedTokens,
|
|
22
|
+
metadata.estimated_tokens
|
|
23
|
+
];
|
|
24
|
+
for (const candidate of candidates) {
|
|
25
|
+
if (typeof candidate === 'number' && Number.isFinite(candidate) && candidate > 0) {
|
|
26
|
+
return Math.max(1, Math.round(candidate));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
10
31
|
function fallbackEstimateTokens(text, messageCount) {
|
|
11
32
|
if (!text) {
|
|
12
33
|
return Math.max(32, Math.max(messageCount, 1) * 16);
|
|
@@ -17,6 +17,11 @@ export interface RoutePoolLoadBalancingPolicy {
|
|
|
17
17
|
* Optional pool-local weights. Keys may target runtime keys, provider.model groups, or provider ids.
|
|
18
18
|
*/
|
|
19
19
|
weights?: Record<string, number>;
|
|
20
|
+
responsesResume?: {
|
|
21
|
+
previousRequestId?: string;
|
|
22
|
+
restoredFromResponseId?: string;
|
|
23
|
+
[key: string]: unknown;
|
|
24
|
+
};
|
|
20
25
|
}
|
|
21
26
|
export interface RoutePoolTier {
|
|
22
27
|
id: string;
|
|
@@ -69,6 +74,7 @@ export interface ProviderProfile {
|
|
|
69
74
|
providerType: string;
|
|
70
75
|
endpoint: string;
|
|
71
76
|
auth: ProviderAuthConfig;
|
|
77
|
+
enabled?: boolean;
|
|
72
78
|
outboundProfile: string;
|
|
73
79
|
compatibilityProfile?: string;
|
|
74
80
|
runtimeKey?: string;
|
|
@@ -95,6 +101,7 @@ export interface ProviderRuntimeProfile {
|
|
|
95
101
|
endpoint: string;
|
|
96
102
|
headers?: Record<string, string>;
|
|
97
103
|
auth: ProviderAuthConfig;
|
|
104
|
+
enabled?: boolean;
|
|
98
105
|
outboundProfile: string;
|
|
99
106
|
compatibilityProfile?: string;
|
|
100
107
|
modelId?: string;
|
|
@@ -189,7 +189,7 @@ function isEmptyClientResponsePayload(payload) {
|
|
|
189
189
|
return false;
|
|
190
190
|
}
|
|
191
191
|
// OpenAI Responses: requires_action (function_call output) is a meaningful response and must not be
|
|
192
|
-
// treated as "empty". Some auto-followup servertools (
|
|
192
|
+
// treated as "empty". Some auto-followup servertools (for example stop_message_flow)
|
|
193
193
|
// previously misclassified this as empty because there is no output_text/content yet.
|
|
194
194
|
const requiredAction = payload.required_action;
|
|
195
195
|
if (requiredAction && typeof requiredAction === 'object') {
|
|
@@ -314,7 +314,6 @@ export async function runServerToolOrchestration(options) {
|
|
|
314
314
|
continue_execution_flow: 'continue_execution',
|
|
315
315
|
review_flow: 'review',
|
|
316
316
|
stop_message_flow: 'stop_message_auto',
|
|
317
|
-
empty_reply_continue: 'empty_reply_continue',
|
|
318
317
|
apply_patch_guard: 'apply_patch_guard',
|
|
319
318
|
exec_command_guard: 'exec_command_guard',
|
|
320
319
|
iflow_model_error_retry: 'iflow_model_error_retry',
|
|
@@ -636,11 +635,10 @@ export async function runServerToolOrchestration(options) {
|
|
|
636
635
|
const isClockHoldFlow = engineResult.execution.flowId === 'clock_hold_flow';
|
|
637
636
|
const isContinueExecutionFlow = engineResult.execution.flowId === 'continue_execution_flow';
|
|
638
637
|
const isReviewFlow = engineResult.execution.flowId === 'review_flow';
|
|
639
|
-
const isEmptyReplyContinue = engineResult.execution.flowId === 'empty_reply_continue';
|
|
640
638
|
const isApplyPatchGuard = engineResult.execution.flowId === 'apply_patch_guard';
|
|
641
639
|
const isExecCommandGuard = engineResult.execution.flowId === 'exec_command_guard';
|
|
642
640
|
const isErrorAutoFlow = engineResult.execution.flowId === 'iflow_model_error_retry';
|
|
643
|
-
const applyAutoLimit = isErrorAutoFlow ||
|
|
641
|
+
const applyAutoLimit = isErrorAutoFlow || isApplyPatchGuard || isExecCommandGuard;
|
|
644
642
|
// ServerTool followups must not inherit or inject any routeHint; always route fresh.
|
|
645
643
|
const preserveRouteHint = false;
|
|
646
644
|
const followupPlan = engineResult.execution.followup;
|
|
@@ -757,8 +755,6 @@ export async function runServerToolOrchestration(options) {
|
|
|
757
755
|
// - do not inherit sticky target
|
|
758
756
|
// - record original entry endpoint for downstream formatting/debug
|
|
759
757
|
rt.preserveRouteHint = preserveRouteHint;
|
|
760
|
-
// Use empty string (falsy) to avoid VirtualRouter calling `.trim()` on non-string values.
|
|
761
|
-
metadata.routeHint = '';
|
|
762
758
|
rt.disableStickyRoutes = true;
|
|
763
759
|
rt.serverToolOriginalEntryEndpoint =
|
|
764
760
|
(typeof options.entryEndpoint === 'string' && options.entryEndpoint.trim().length
|
|
@@ -774,7 +770,7 @@ export async function runServerToolOrchestration(options) {
|
|
|
774
770
|
metadata.__shadowCompareForcedProviderKey = providerKey;
|
|
775
771
|
}
|
|
776
772
|
}
|
|
777
|
-
const retryEmptyFollowupOnce = isStopMessageFlow
|
|
773
|
+
const retryEmptyFollowupOnce = isStopMessageFlow;
|
|
778
774
|
const maxAttempts = retryEmptyFollowupOnce ? 2 : 1;
|
|
779
775
|
const followupRequestId = buildFollowupRequestId(options.requestId, engineResult.execution.followup.requestIdSuffix);
|
|
780
776
|
const clientInjectOnlyRaw = metadata.clientInjectOnly;
|
|
@@ -1072,7 +1068,6 @@ export async function runServerToolOrchestration(options) {
|
|
|
1072
1068
|
replayRt.serverToolLoopState = replayLoopState;
|
|
1073
1069
|
}
|
|
1074
1070
|
replayMetadata.__hubEntry = 'chat_process';
|
|
1075
|
-
replayMetadata.routeHint = '';
|
|
1076
1071
|
replayRt.preserveRouteHint = false;
|
|
1077
1072
|
replayRt.disableStickyRoutes = true;
|
|
1078
1073
|
replayRt.serverToolOriginalEntryEndpoint =
|
|
@@ -1374,17 +1369,6 @@ function resolveCapturedChatRequest(adapterContext) {
|
|
|
1374
1369
|
if (direct && typeof direct === 'object' && !Array.isArray(direct)) {
|
|
1375
1370
|
return direct;
|
|
1376
1371
|
}
|
|
1377
|
-
const rt = readRuntimeMetadata(record);
|
|
1378
|
-
const runtimeCaptured = rt && typeof rt === 'object' && !Array.isArray(rt)
|
|
1379
|
-
? rt.capturedChatRequest
|
|
1380
|
-
: undefined;
|
|
1381
|
-
if (runtimeCaptured && typeof runtimeCaptured === 'object' && !Array.isArray(runtimeCaptured)) {
|
|
1382
|
-
return runtimeCaptured;
|
|
1383
|
-
}
|
|
1384
|
-
const originalRequest = record.originalRequest;
|
|
1385
|
-
if (originalRequest && typeof originalRequest === 'object' && !Array.isArray(originalRequest)) {
|
|
1386
|
-
return originalRequest;
|
|
1387
|
-
}
|
|
1388
1372
|
return null;
|
|
1389
1373
|
}
|
|
1390
1374
|
function buildStopMessageLoopPayload(adapterContext) {
|
|
@@ -1546,21 +1530,6 @@ function buildFollowupRequestId(baseRequestId, suffix) {
|
|
|
1546
1530
|
}
|
|
1547
1531
|
return normalized.endsWith(suffixText) ? normalized : `${normalized}${suffixText}`;
|
|
1548
1532
|
}
|
|
1549
|
-
function getStopMessageSource(adapterContext) {
|
|
1550
|
-
if (!adapterContext || typeof adapterContext !== 'object') {
|
|
1551
|
-
return undefined;
|
|
1552
|
-
}
|
|
1553
|
-
const rt = readRuntimeMetadata(adapterContext);
|
|
1554
|
-
const raw = rt?.stopMessageState;
|
|
1555
|
-
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
1556
|
-
return undefined;
|
|
1557
|
-
}
|
|
1558
|
-
const record = raw;
|
|
1559
|
-
const source = typeof record.stopMessageSource === 'string' && record.stopMessageSource.trim()
|
|
1560
|
-
? record.stopMessageSource.trim()
|
|
1561
|
-
: '';
|
|
1562
|
-
return source || undefined;
|
|
1563
|
-
}
|
|
1564
1533
|
function isAdapterClientDisconnected(adapterContext) {
|
|
1565
1534
|
if (!adapterContext || typeof adapterContext !== 'object') {
|
|
1566
1535
|
return false;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { buildChatRequestFromResponses, captureResponsesContext } from '../../conversion/responses/responses-openai-bridge.js';
|
|
2
|
-
import { stripHistoricalImageAttachments } from '../../conversion/hub/process/chat-process-media.js';
|
|
3
2
|
import { cloneJson } from '../server-side-tools.js';
|
|
4
3
|
import { trimOpenAiMessagesForFollowup } from './followup-message-trimmer.js';
|
|
5
4
|
function extractResponsesTopLevelParameters(record) {
|
|
@@ -423,11 +422,6 @@ export function buildServerToolFollowupChatPayloadFromInjection(args) {
|
|
|
423
422
|
return null;
|
|
424
423
|
}
|
|
425
424
|
let messages = Array.isArray(seed.messages) ? cloneJson(seed.messages) : [];
|
|
426
|
-
// ServerTool followups must enter marker/routing/chat-process analysis with the same
|
|
427
|
-
// historical-media invariants as normal chat-process requests:
|
|
428
|
-
// only the latest live user turn may keep inline image payloads; earlier user turns
|
|
429
|
-
// are scrubbed to placeholders before any followup ops append new assistant/user items.
|
|
430
|
-
messages = stripHistoricalImageAttachments(messages);
|
|
431
425
|
const ops = Array.isArray(args.injection?.ops) ? args.injection.ops : [];
|
|
432
426
|
// Followup is a normal request hop: inherit tool schema from the captured request and
|
|
433
427
|
// let compat/tool-governance apply standard sanitization rules.
|
|
@@ -1,274 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import { ensureRuntimeMetadata, readRuntimeMetadata } from '../../conversion/runtime-metadata.js';
|
|
5
|
-
const FLOW_ID = 'empty_reply_continue';
|
|
6
|
-
const MAX_TOOL_HINTS = 24;
|
|
7
|
-
const handler = async (ctx) => {
|
|
8
|
-
if (!ctx.capabilities.reenterPipeline) {
|
|
9
|
-
return null;
|
|
10
|
-
}
|
|
11
|
-
// 避免在 followup 请求里再次触发,防止循环。
|
|
12
|
-
const rt = readRuntimeMetadata(ctx.adapterContext);
|
|
13
|
-
const followupRaw = rt?.serverToolFollowup;
|
|
14
|
-
if (followupRaw === true || (typeof followupRaw === 'string' && followupRaw.trim().toLowerCase() === 'true')) {
|
|
15
|
-
return null;
|
|
16
|
-
}
|
|
17
|
-
if (hasCompactionFlag(rt)) {
|
|
18
|
-
return null;
|
|
19
|
-
}
|
|
20
|
-
// 通用空回复续跑:只要是 /v1/responses 链路且满足空回复判定,不区分 provider family / protocol。
|
|
21
|
-
const entryEndpoint = (ctx.entryEndpoint || '').toLowerCase();
|
|
22
|
-
if (!entryEndpoint.includes('/v1/responses')) {
|
|
23
|
-
return null;
|
|
24
|
-
}
|
|
25
|
-
// 支持两种客户端协议形状:
|
|
26
|
-
// - OpenAI Chat: choices[0].message.content
|
|
27
|
-
// - OpenAI Responses: output/output_text/status
|
|
28
|
-
const base = ctx.base;
|
|
29
|
-
const emptyDecision = decideEmptyReply(base);
|
|
30
|
-
if (!emptyDecision.shouldTrigger) {
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
33
|
-
// 统计连续空回复次数,超过上限后不再自动续写,而是返回一个可重试错误。
|
|
34
|
-
const previousCountRaw = rt?.emptyReplyContinueCount ?? rt?.geminiEmptyReplyCount;
|
|
35
|
-
const previousCount = typeof previousCountRaw === 'number' && Number.isFinite(previousCountRaw) && previousCountRaw >= 0
|
|
36
|
-
? previousCountRaw
|
|
37
|
-
: 0;
|
|
38
|
-
const nextCount = previousCount + 1;
|
|
39
|
-
const captured = getCapturedRequest(ctx.adapterContext);
|
|
40
|
-
if (!captured) {
|
|
41
|
-
return null;
|
|
42
|
-
}
|
|
43
|
-
if (isCompactionRequest(captured)) {
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
const seed = extractCapturedChatSeed(captured);
|
|
47
|
-
if (!seed) {
|
|
48
|
-
return null;
|
|
49
|
-
}
|
|
50
|
-
const continueText = buildContinueUserText(seed);
|
|
51
|
-
// 超过最多 3 次空回复:返回一个 HTTP_HANDLER_ERROR 形状的错误,交由上层错误中心处理。
|
|
52
|
-
if (nextCount > 3) {
|
|
53
|
-
const errorChat = {
|
|
54
|
-
id: base.id,
|
|
55
|
-
object: base.object,
|
|
56
|
-
model: base.model,
|
|
57
|
-
error: {
|
|
58
|
-
message: 'fetch failed: empty_reply_continue exceeded max empty replies',
|
|
59
|
-
code: 'HTTP_HANDLER_ERROR',
|
|
60
|
-
type: 'servertool_empty_reply'
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
return {
|
|
64
|
-
flowId: FLOW_ID,
|
|
65
|
-
finalize: async () => ({
|
|
66
|
-
chatResponse: errorChat,
|
|
67
|
-
execution: {
|
|
68
|
-
flowId: FLOW_ID
|
|
69
|
-
}
|
|
70
|
-
})
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
return {
|
|
74
|
-
flowId: FLOW_ID,
|
|
75
|
-
finalize: async () => ({
|
|
76
|
-
chatResponse: ctx.base,
|
|
77
|
-
execution: {
|
|
78
|
-
flowId: FLOW_ID,
|
|
79
|
-
followup: {
|
|
80
|
-
requestIdSuffix: ':continue',
|
|
81
|
-
entryEndpoint: ctx.entryEndpoint,
|
|
82
|
-
injection: {
|
|
83
|
-
ops: [
|
|
84
|
-
{ op: 'preserve_tools' },
|
|
85
|
-
{ op: 'append_assistant_message', required: false },
|
|
86
|
-
{ op: 'append_user_text', text: continueText }
|
|
87
|
-
]
|
|
88
|
-
},
|
|
89
|
-
metadata: (() => {
|
|
90
|
-
const meta = {};
|
|
91
|
-
const runtime = ensureRuntimeMetadata(meta);
|
|
92
|
-
runtime.emptyReplyContinueCount = nextCount;
|
|
93
|
-
// Backward compatibility for old snapshots/guards.
|
|
94
|
-
runtime.geminiEmptyReplyCount = nextCount;
|
|
95
|
-
return meta;
|
|
96
|
-
})()
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
})
|
|
100
|
-
};
|
|
101
|
-
};
|
|
102
|
-
registerServerToolHandler('empty_reply_continue', handler, { trigger: 'auto', hook: { phase: 'default', priority: 20 } });
|
|
103
|
-
function decideEmptyReply(base) {
|
|
104
|
-
// 1) OpenAI Chat shape
|
|
105
|
-
const choices = Array.isArray(base.choices) ? base.choices : [];
|
|
106
|
-
if (choices.length > 0) {
|
|
107
|
-
const firstRaw = choices[0];
|
|
108
|
-
if (!firstRaw || typeof firstRaw !== 'object') {
|
|
109
|
-
return { shouldTrigger: false };
|
|
110
|
-
}
|
|
111
|
-
const first = firstRaw;
|
|
112
|
-
const finishReasonRaw = typeof first.finish_reason === 'string' && first.finish_reason.trim()
|
|
113
|
-
? first.finish_reason.trim()
|
|
114
|
-
: '';
|
|
115
|
-
const finishReason = finishReasonRaw.toLowerCase();
|
|
116
|
-
const isStop = finishReason === 'stop';
|
|
117
|
-
const isMaxTokens = finishReason === 'length'; // 映射自 Gemini 的 MAX_TOKENS
|
|
118
|
-
if (!isStop && !isMaxTokens) {
|
|
119
|
-
return { shouldTrigger: false };
|
|
120
|
-
}
|
|
121
|
-
const message = first.message && typeof first.message === 'object' && !Array.isArray(first.message)
|
|
122
|
-
? first.message
|
|
123
|
-
: null;
|
|
124
|
-
if (!message) {
|
|
125
|
-
return { shouldTrigger: false };
|
|
126
|
-
}
|
|
127
|
-
const contentRaw = message.content;
|
|
128
|
-
const contentText = typeof contentRaw === 'string' ? contentRaw.trim() : '';
|
|
129
|
-
// 对于 finish_reason=stop,仅在真正“空回复”时触发;
|
|
130
|
-
// 对于 finish_reason=length(MAX_TOKENS 截断),允许已有内容,视为需要自动续写。
|
|
131
|
-
if (isStop && contentText.length > 0) {
|
|
132
|
-
return { shouldTrigger: false };
|
|
133
|
-
}
|
|
134
|
-
const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : [];
|
|
135
|
-
if (toolCalls.length > 0) {
|
|
136
|
-
return { shouldTrigger: false };
|
|
137
|
-
}
|
|
138
|
-
return { shouldTrigger: true };
|
|
139
|
-
}
|
|
140
|
-
// 2) OpenAI Responses shape
|
|
141
|
-
const statusRaw = typeof base.status === 'string' ? base.status.trim().toLowerCase() : '';
|
|
142
|
-
if (statusRaw && statusRaw !== 'completed') {
|
|
143
|
-
return { shouldTrigger: false };
|
|
144
|
-
}
|
|
145
|
-
if (base.required_action && typeof base.required_action === 'object') {
|
|
146
|
-
return { shouldTrigger: false };
|
|
147
|
-
}
|
|
148
|
-
const outputText = extractResponsesOutputText(base);
|
|
149
|
-
if (outputText.length > 0) {
|
|
150
|
-
return { shouldTrigger: false };
|
|
151
|
-
}
|
|
152
|
-
const outputRaw = Array.isArray(base.output) ? base.output : [];
|
|
153
|
-
if (outputRaw.some((item) => hasToolLikeOutput(item))) {
|
|
154
|
-
return { shouldTrigger: false };
|
|
155
|
-
}
|
|
156
|
-
// 允许 output 为空或仅包含空消息:视作空回复,触发自动续写。
|
|
157
|
-
return { shouldTrigger: true };
|
|
158
|
-
}
|
|
159
|
-
function extractResponsesOutputText(base) {
|
|
160
|
-
const raw = base.output_text;
|
|
161
|
-
if (typeof raw === 'string') {
|
|
162
|
-
return raw.trim();
|
|
163
|
-
}
|
|
164
|
-
if (Array.isArray(raw)) {
|
|
165
|
-
const texts = raw
|
|
166
|
-
.map((entry) => (typeof entry === 'string' ? entry : ''))
|
|
167
|
-
.filter((entry) => entry.trim().length > 0);
|
|
168
|
-
if (texts.length > 0) {
|
|
169
|
-
return texts.join('\n').trim();
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
const output = Array.isArray(base.output) ? (base.output) : [];
|
|
173
|
-
const chunks = [];
|
|
174
|
-
for (const item of output) {
|
|
175
|
-
if (!item || typeof item !== 'object' || Array.isArray(item))
|
|
176
|
-
continue;
|
|
177
|
-
if (typeof item.type !== 'string')
|
|
178
|
-
continue;
|
|
179
|
-
const type = String(item.type).trim().toLowerCase();
|
|
180
|
-
if (type !== 'message')
|
|
181
|
-
continue;
|
|
182
|
-
const content = Array.isArray(item.content) ? (item.content) : [];
|
|
183
|
-
for (const part of content) {
|
|
184
|
-
if (!part || typeof part !== 'object' || Array.isArray(part))
|
|
185
|
-
continue;
|
|
186
|
-
const pType = typeof part.type === 'string'
|
|
187
|
-
? String(part.type).trim().toLowerCase()
|
|
188
|
-
: '';
|
|
189
|
-
if (pType === 'output_text' || pType === 'text' || pType === 'input_text') {
|
|
190
|
-
const text = typeof part.text === 'string' ? String(part.text) : '';
|
|
191
|
-
if (text.trim().length)
|
|
192
|
-
chunks.push(text.trim());
|
|
193
|
-
continue;
|
|
194
|
-
}
|
|
195
|
-
const fallback = typeof part.content === 'string'
|
|
196
|
-
? String(part.content).trim()
|
|
197
|
-
: '';
|
|
198
|
-
if (fallback.length)
|
|
199
|
-
chunks.push(fallback);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
return chunks.join('\n').trim();
|
|
203
|
-
}
|
|
204
|
-
function hasToolLikeOutput(value) {
|
|
205
|
-
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
206
|
-
return false;
|
|
207
|
-
}
|
|
208
|
-
const typeRaw = value.type;
|
|
209
|
-
const type = typeof typeRaw === 'string' ? typeRaw.trim().toLowerCase() : '';
|
|
210
|
-
if (!type) {
|
|
211
|
-
return false;
|
|
212
|
-
}
|
|
213
|
-
return (type === 'tool_call' ||
|
|
214
|
-
type === 'tool_use' ||
|
|
215
|
-
type === 'function_call' ||
|
|
216
|
-
type.includes('tool'));
|
|
217
|
-
}
|
|
218
|
-
function getCapturedRequest(adapterContext) {
|
|
219
|
-
if (!adapterContext || typeof adapterContext !== 'object') {
|
|
220
|
-
return null;
|
|
221
|
-
}
|
|
222
|
-
const captured = adapterContext.capturedChatRequest;
|
|
223
|
-
if (!captured || typeof captured !== 'object' || Array.isArray(captured)) {
|
|
224
|
-
return null;
|
|
225
|
-
}
|
|
226
|
-
return captured;
|
|
227
|
-
}
|
|
228
|
-
function hasCompactionFlag(rt) {
|
|
229
|
-
const flag = rt && typeof rt === 'object' && !Array.isArray(rt) ? rt.compactionRequest : undefined;
|
|
230
|
-
if (flag === true) {
|
|
231
|
-
return true;
|
|
232
|
-
}
|
|
233
|
-
if (typeof flag === 'string' && flag.trim().toLowerCase() === 'true') {
|
|
234
|
-
return true;
|
|
235
|
-
}
|
|
236
|
-
return false;
|
|
237
|
-
}
|
|
238
|
-
function buildContinueUserText(seed) {
|
|
239
|
-
const toolNames = collectToolNames(seed);
|
|
240
|
-
if (!toolNames.length) {
|
|
241
|
-
return '继续执行';
|
|
242
|
-
}
|
|
243
|
-
const shown = toolNames.slice(0, MAX_TOOL_HINTS);
|
|
244
|
-
const omitted = toolNames.length - shown.length;
|
|
245
|
-
const listText = shown.join(', ');
|
|
246
|
-
const tail = omitted > 0 ? `(其余 ${omitted} 个省略)` : '';
|
|
247
|
-
return `继续执行。可用工具列表:${listText}${tail}。请优先调用这些工具,不要返回空回复。`;
|
|
248
|
-
}
|
|
249
|
-
function collectToolNames(seed) {
|
|
250
|
-
const tools = Array.isArray(seed.tools) ? seed.tools : [];
|
|
251
|
-
if (!tools.length) {
|
|
252
|
-
return [];
|
|
253
|
-
}
|
|
254
|
-
const names = [];
|
|
255
|
-
const seen = new Set();
|
|
256
|
-
for (const tool of tools) {
|
|
257
|
-
if (!tool || typeof tool !== 'object' || Array.isArray(tool))
|
|
258
|
-
continue;
|
|
259
|
-
const fnNode = tool.function;
|
|
260
|
-
const fnName = fnNode && typeof fnNode === 'object' && !Array.isArray(fnNode)
|
|
261
|
-
? normalizeToolName(fnNode.name)
|
|
262
|
-
: '';
|
|
263
|
-
const fallbackName = normalizeToolName(tool.name);
|
|
264
|
-
const resolvedName = fnName || fallbackName;
|
|
265
|
-
if (!resolvedName || seen.has(resolvedName))
|
|
266
|
-
continue;
|
|
267
|
-
seen.add(resolvedName);
|
|
268
|
-
names.push(resolvedName);
|
|
269
|
-
}
|
|
270
|
-
return names;
|
|
271
|
-
}
|
|
272
|
-
function normalizeToolName(value) {
|
|
273
|
-
return typeof value === 'string' && value.trim().length > 0 ? value.trim() : '';
|
|
274
|
-
}
|
|
1
|
+
// empty_reply_continue has been retired intentionally.
|
|
2
|
+
// This file remains as a tombstone so stale imports fail closed.
|
|
3
|
+
export {};
|
|
@@ -7,19 +7,16 @@ export declare function resolveStickyKey(record: {
|
|
|
7
7
|
sessionId?: unknown;
|
|
8
8
|
conversationId?: unknown;
|
|
9
9
|
metadata?: unknown;
|
|
10
|
-
originalRequest?: unknown;
|
|
11
10
|
[key: string]: unknown;
|
|
12
11
|
}, runtimeMetadata?: unknown): string | undefined;
|
|
13
12
|
export declare function persistStopMessageState(stickyKey: string | undefined, state: RoutingInstructionState): void;
|
|
14
13
|
export declare function resolveStopMessageSessionScope(record: {
|
|
15
14
|
sessionId?: unknown;
|
|
16
15
|
metadata?: unknown;
|
|
17
|
-
originalRequest?: unknown;
|
|
18
16
|
[key: string]: unknown;
|
|
19
17
|
}, runtimeMetadata?: unknown): string | undefined;
|
|
20
18
|
export declare function resolveBdWorkingDirectoryForRecord(record: {
|
|
21
19
|
metadata?: unknown;
|
|
22
|
-
originalRequest?: unknown;
|
|
23
20
|
[key: string]: unknown;
|
|
24
21
|
}, runtimeMetadata: unknown): string | undefined;
|
|
25
22
|
export declare function readServerToolFollowupFlowId(runtimeMetadata: unknown): string;
|