@jsonstudio/llms 0.6.3409 → 0.6.3539

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.
Files changed (82) hide show
  1. package/dist/conversion/codecs/anthropic-openai-codec.d.ts +12 -3
  2. package/dist/conversion/codecs/anthropic-openai-codec.js +32 -92
  3. package/dist/conversion/codecs/gemini-openai-codec.d.ts +6 -5
  4. package/dist/conversion/codecs/gemini-openai-codec.js +48 -685
  5. package/dist/conversion/codecs/openai-openai-codec.d.ts +1 -1
  6. package/dist/conversion/codecs/openai-openai-codec.js +34 -100
  7. package/dist/conversion/codecs/responses-openai-codec.d.ts +1 -1
  8. package/dist/conversion/codecs/responses-openai-codec.js +47 -159
  9. package/dist/conversion/compat/actions/anthropic-claude-code-system-prompt.d.ts +2 -6
  10. package/dist/conversion/compat/actions/anthropic-claude-code-system-prompt.js +29 -245
  11. package/dist/conversion/compat/actions/anthropic-claude-code-user-id.d.ts +3 -0
  12. package/dist/conversion/compat/actions/anthropic-claude-code-user-id.js +30 -0
  13. package/dist/conversion/compat/actions/antigravity-thought-signature-prepare.js +21 -232
  14. package/dist/conversion/compat/actions/deepseek-web-request.js +41 -276
  15. package/dist/conversion/compat/actions/deepseek-web-response.js +64 -859
  16. package/dist/conversion/compat/actions/gemini-cli-request.d.ts +1 -1
  17. package/dist/conversion/compat/actions/gemini-cli-request.js +20 -613
  18. package/dist/conversion/compat/actions/gemini-web-search.d.ts +1 -15
  19. package/dist/conversion/compat/actions/gemini-web-search.js +22 -69
  20. package/dist/conversion/compat/actions/glm-tool-extraction.d.ts +3 -2
  21. package/dist/conversion/compat/actions/glm-tool-extraction.js +28 -257
  22. package/dist/conversion/compat/actions/iflow-tool-text-fallback.d.ts +0 -8
  23. package/dist/conversion/compat/actions/iflow-tool-text-fallback.js +24 -206
  24. package/dist/conversion/compat/actions/qwen-transform.d.ts +3 -2
  25. package/dist/conversion/compat/actions/qwen-transform.js +30 -271
  26. package/dist/conversion/compat/actions/tool-text-request-guidance.js +3 -173
  27. package/dist/conversion/compat/actions/universal-shape-filter.d.ts +6 -23
  28. package/dist/conversion/compat/actions/universal-shape-filter.js +4 -383
  29. package/dist/conversion/hub/pipeline/compat/native-adapter-context.js +1 -0
  30. package/dist/conversion/pipeline/codecs/v2/anthropic-openai-pipeline.d.ts +1 -2
  31. package/dist/conversion/pipeline/codecs/v2/anthropic-openai-pipeline.js +50 -104
  32. package/dist/conversion/pipeline/codecs/v2/openai-openai-pipeline.js +12 -10
  33. package/dist/conversion/pipeline/codecs/v2/responses-openai-pipeline.d.ts +0 -2
  34. package/dist/conversion/pipeline/codecs/v2/responses-openai-pipeline.js +46 -67
  35. package/dist/conversion/pipeline/codecs/v2/shared/openai-chat-helpers.js +15 -40
  36. package/dist/conversion/responses/responses-openai-bridge/response-payload.js +47 -348
  37. package/dist/conversion/responses/responses-openai-bridge.js +129 -611
  38. package/dist/conversion/shared/chat-output-normalizer.js +6 -0
  39. package/dist/conversion/shared/chat-request-filters.js +1 -1
  40. package/dist/conversion/shared/output-content-normalizer.js +10 -0
  41. package/dist/conversion/shared/responses-conversation-store.js +22 -135
  42. package/dist/conversion/shared/responses-output-builder.d.ts +0 -2
  43. package/dist/conversion/shared/responses-output-builder.js +28 -318
  44. package/dist/conversion/shared/responses-response-utils.js +35 -86
  45. package/dist/conversion/shared/streaming-text-extractor.d.ts +1 -2
  46. package/dist/conversion/shared/streaming-text-extractor.js +13 -14
  47. package/dist/native/router_hotpath_napi.node +0 -0
  48. package/dist/router/virtual-router/bootstrap/routing-config.js +11 -3
  49. package/dist/router/virtual-router/engine-legacy.d.ts +3 -3
  50. package/dist/router/virtual-router/engine-legacy.js +15 -7
  51. package/dist/router/virtual-router/engine-selection/native-compat-action-semantics.d.ts +16 -0
  52. package/dist/router/virtual-router/engine-selection/native-compat-action-semantics.js +434 -46
  53. package/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics.d.ts +83 -0
  54. package/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics.js +295 -0
  55. package/dist/router/virtual-router/engine-selection/native-hub-pipeline-req-outbound-semantics.d.ts +1 -0
  56. package/dist/router/virtual-router/engine-selection/native-hub-pipeline-resp-semantics.d.ts +7 -0
  57. package/dist/router/virtual-router/engine-selection/native-hub-pipeline-resp-semantics.js +8 -1
  58. package/dist/router/virtual-router/engine-selection/native-router-hotpath-loader.js +383 -298
  59. package/dist/router/virtual-router/engine-selection/native-shared-conversion-semantics.d.ts +20 -0
  60. package/dist/router/virtual-router/engine-selection/native-shared-conversion-semantics.js +201 -0
  61. package/dist/router/virtual-router/engine-selection/native-virtual-router-routing-instructions-semantics.d.ts +1 -0
  62. package/dist/router/virtual-router/engine-selection/native-virtual-router-routing-instructions-semantics.js +37 -0
  63. package/dist/router/virtual-router/engine.js +0 -38
  64. package/dist/router/virtual-router/features.js +44 -3
  65. package/dist/router/virtual-router/routing-instructions/parse.d.ts +0 -12
  66. package/dist/router/virtual-router/routing-instructions/parse.js +9 -389
  67. package/dist/router/virtual-router/stop-message-state-sync.d.ts +3 -6
  68. package/dist/router/virtual-router/stop-message-state-sync.js +50 -21
  69. package/dist/sse/sse-to-json/anthropic-sse-to-json-converter.d.ts +1 -0
  70. package/dist/sse/sse-to-json/anthropic-sse-to-json-converter.js +26 -0
  71. package/dist/sse/sse-to-json/builders/anthropic-response-builder.js +12 -2
  72. package/package.json +1 -1
  73. package/dist/router/virtual-router/engine-legacy/route-finalize.d.ts +0 -9
  74. package/dist/router/virtual-router/engine-legacy/route-finalize.js +0 -84
  75. package/dist/router/virtual-router/engine-legacy/route-selection.d.ts +0 -17
  76. package/dist/router/virtual-router/engine-legacy/route-selection.js +0 -205
  77. package/dist/router/virtual-router/engine-legacy/route-state-allowlist.d.ts +0 -3
  78. package/dist/router/virtual-router/engine-legacy/route-state-allowlist.js +0 -36
  79. package/dist/router/virtual-router/engine-legacy/route-state.d.ts +0 -12
  80. package/dist/router/virtual-router/engine-legacy/route-state.js +0 -386
  81. package/dist/router/virtual-router/engine-legacy/routing.d.ts +0 -8
  82. package/dist/router/virtual-router/engine-legacy/routing.js +0 -8
@@ -1,386 +0,0 @@
1
- import { applyRoutingInstructions, cleanMessagesFromRoutingInstructions, parseRoutingInstructions } from '../routing-instructions.js';
2
- import { buildMetadataInstructions } from '../engine/routing-state/metadata.js';
3
- import { getRoutingInstructionState, persistRoutingInstructionState, resolveStopMessageScope } from '../engine/routing-state/store.js';
4
- import { ensureStopMessageModeMaxRepeats } from '../routing-stop-message-state-codec.js';
5
- import { extractMessageText } from '../message-utils.js';
6
- import { cleanResponsesContextFromRoutingInstructions, getLatestUserTextFromResponsesContext, hasLatestUserRoutingInstructionMarker, hasRoutingInstructionMarker, hasRoutingInstructionMarkerInResponsesContext, isServerToolFollowupRequest, isStopScopeTraceEnabled, normalizeStopMessageAiMode, normalizeStopMessageStageMode, stripClientInjectScopedFields, stripStopMessageFields } from './helpers.js';
7
- import { enforceAllowlistIntersection } from './route-state-allowlist.js';
8
- export function buildRoutingState(engine, request, metadata) {
9
- const stickyKey = engine.resolveStickyKey(metadata);
10
- const sessionScope = engine.resolveSessionScope(metadata);
11
- const stopMessageScope = resolveStopMessageScope(metadata);
12
- // Route sticky state remains session/request scoped for routing behavior,
13
- // but stopMessage state is tmux/clockd scoped and merged separately below.
14
- const stateKey = sessionScope || stickyKey || 'default';
15
- const baseState = getRoutingInstructionState(stateKey, engine.routingInstructionState, engine.routingStateStore);
16
- let routingState = stripStopMessageFields(baseState);
17
- const metadataInstructions = buildMetadataInstructions(metadata);
18
- if (metadataInstructions.length > 0) {
19
- routingState = applyRoutingInstructions(metadataInstructions, routingState);
20
- }
21
- const disableStickyRoutes = metadata &&
22
- typeof metadata === 'object' &&
23
- metadata.disableStickyRoutes === true;
24
- if (disableStickyRoutes && (routingState.stickyTarget || routingState.preferTarget)) {
25
- routingState = {
26
- ...routingState,
27
- stickyTarget: undefined,
28
- preferTarget: undefined
29
- };
30
- }
31
- if (stopMessageScope) {
32
- const sessionState = getRoutingInstructionState(stopMessageScope, engine.routingInstructionState, engine.routingStateStore);
33
- if (ensureStopMessageModeMaxRepeats(sessionState)) {
34
- engine.routingInstructionState.set(stopMessageScope, sessionState);
35
- persistRoutingInstructionState(stopMessageScope, sessionState, engine.routingStateStore);
36
- }
37
- if (typeof sessionState.stopMessageText === 'string' ||
38
- typeof sessionState.stopMessageMaxRepeats === 'number' ||
39
- typeof sessionState.stopMessageStageMode === 'string' ||
40
- typeof sessionState.stopMessageAiMode === 'string' ||
41
- typeof sessionState.stopMessageAiSeedPrompt === 'string' ||
42
- Array.isArray(sessionState.stopMessageAiHistory)) {
43
- routingState = {
44
- ...routingState,
45
- stopMessageText: sessionState.stopMessageText,
46
- stopMessageMaxRepeats: sessionState.stopMessageMaxRepeats,
47
- stopMessageUsed: sessionState.stopMessageUsed,
48
- stopMessageUpdatedAt: sessionState.stopMessageUpdatedAt,
49
- stopMessageLastUsedAt: sessionState.stopMessageLastUsedAt,
50
- stopMessageStageMode: sessionState.stopMessageStageMode,
51
- stopMessageAiMode: sessionState.stopMessageAiMode,
52
- stopMessageAiSeedPrompt: sessionState.stopMessageAiSeedPrompt,
53
- stopMessageAiHistory: sessionState.stopMessageAiHistory
54
- };
55
- }
56
- if (typeof sessionState.preCommandScriptPath === 'string' && sessionState.preCommandScriptPath.trim()) {
57
- routingState = {
58
- ...routingState,
59
- preCommandSource: sessionState.preCommandSource,
60
- preCommandScriptPath: sessionState.preCommandScriptPath,
61
- preCommandUpdatedAt: sessionState.preCommandUpdatedAt
62
- };
63
- }
64
- }
65
- let parsedInstructions = parseRoutingInstructions(request.messages);
66
- const responsesContext = request.semantics && typeof request.semantics === 'object'
67
- ? request.semantics.responses?.context
68
- : undefined;
69
- const responsesLatestUserText = getLatestUserTextFromResponsesContext(responsesContext);
70
- const responsesHasMarker = hasRoutingInstructionMarkerInResponsesContext(responsesContext);
71
- if (!parsedInstructions.length && responsesHasMarker) {
72
- parsedInstructions = parseRoutingInstructions([
73
- { role: 'user', content: responsesLatestUserText }
74
- ]);
75
- }
76
- const markerDetected = hasRoutingInstructionMarker(request.messages) || responsesHasMarker;
77
- const latestMessage = request.messages.length > 0 ? request.messages[request.messages.length - 1] : undefined;
78
- const latestUserText = latestMessage && latestMessage.role === 'user' ? extractMessageText(latestMessage).trim() : '';
79
- const stopMessageLogText = responsesHasMarker ? responsesLatestUserText : latestUserText;
80
- const containsStopMessage = Boolean(stopMessageLogText && /stopmessage/i.test(stopMessageLogText));
81
- const stopMessageTypes = parsedInstructions
82
- .filter((entry) => entry.type === 'stopMessageSet' ||
83
- entry.type === 'stopMessageMode' ||
84
- entry.type === 'stopMessageClear')
85
- .map((entry) => entry.type);
86
- if (containsStopMessage || stopMessageTypes.length > 0) {
87
- const preview = stopMessageLogText.replace(/\s+/g, ' ').slice(0, 120);
88
- engine.debug?.log?.(`[virtual-router][stop_message_parse] requestId=${metadata.requestId || 'n/a'} marker=${markerDetected ? 'detected' : 'missing'} parsed=${stopMessageTypes.join(',') || 'none'} preview=${preview}`);
89
- }
90
- if (markerDetected && isStopScopeTraceEnabled()) {
91
- const parsedTypes = parsedInstructions.map((entry) => entry.type);
92
- engine.debug?.log?.(`[virtual-router][instruction_parse] requestId=${metadata.requestId || 'n/a'} marker=detected parsed=${parsedTypes.join(',') || 'none'}`);
93
- }
94
- else if (isStopScopeTraceEnabled()) {
95
- if (stopMessageLogText && /stopmessage/i.test(stopMessageLogText)) {
96
- const preview = stopMessageLogText.replace(/\s+/g, ' ').slice(0, 120);
97
- engine.debug?.log?.(`[virtual-router][instruction_parse] requestId=${metadata.requestId || 'n/a'} marker=missing contains_stopmessage=yes preview=${preview}`);
98
- }
99
- }
100
- const serverToolFollowup = isServerToolFollowupRequest(metadata);
101
- const latestUserHasMarker = hasLatestUserRoutingInstructionMarker(request.messages) || responsesHasMarker;
102
- let instructions = parsedInstructions;
103
- if (serverToolFollowup && instructions.length > 0) {
104
- instructions = instructions.filter((entry) => entry.type !== 'stopMessageSet' &&
105
- entry.type !== 'stopMessageMode' &&
106
- entry.type !== 'stopMessageClear' &&
107
- entry.type !== 'preCommandSet' &&
108
- entry.type !== 'preCommandClear');
109
- }
110
- if (stopMessageScope && parsedInstructions.length > 0) {
111
- const sessionState = getRoutingInstructionState(stopMessageScope, engine.routingInstructionState, engine.routingStateStore);
112
- const hasStaleStopMessageInstruction = !latestUserHasMarker &&
113
- parsedInstructions.some((entry) => entry.type === 'stopMessageSet' || entry.type === 'stopMessageMode');
114
- if (hasStaleStopMessageInstruction) {
115
- const hasActiveStopState = typeof sessionState.stopMessageText === 'string' ||
116
- typeof sessionState.stopMessageMaxRepeats === 'number' ||
117
- typeof sessionState.stopMessageStageMode === 'string' ||
118
- typeof sessionState.stopMessageAiMode === 'string' ||
119
- typeof sessionState.stopMessageAiSeedPrompt === 'string' ||
120
- Array.isArray(sessionState.stopMessageAiHistory);
121
- const hasStopLifecycleStamp = (typeof sessionState.stopMessageUpdatedAt === 'number' &&
122
- Number.isFinite(sessionState.stopMessageUpdatedAt)) ||
123
- (typeof sessionState.stopMessageLastUsedAt === 'number' &&
124
- Number.isFinite(sessionState.stopMessageLastUsedAt));
125
- if (hasActiveStopState || hasStopLifecycleStamp) {
126
- instructions = instructions.filter((entry) => entry.type !== 'stopMessageSet' && entry.type !== 'stopMessageMode');
127
- }
128
- }
129
- }
130
- // stopMessage/precommand require explicit client inject scope (tmux).
131
- // When scope is missing, drop only these instructions and keep request passthrough.
132
- if (instructions.length > 0 && !stopMessageScope) {
133
- const blockedInstructionTypes = instructions
134
- .filter((entry) => entry.type === 'stopMessageSet' ||
135
- entry.type === 'stopMessageMode' ||
136
- entry.type === 'stopMessageClear' ||
137
- entry.type === 'preCommandSet' ||
138
- entry.type === 'preCommandClear')
139
- .map((entry) => entry.type);
140
- if (blockedInstructionTypes.length > 0 && isStopScopeTraceEnabled()) {
141
- engine.debug?.log?.(`[virtual-router][stop_scope] requestId=${metadata.requestId || 'n/a'} stage=drop reason=missing_tmux_scope instructions=${blockedInstructionTypes.join(',')}`);
142
- }
143
- instructions = instructions.filter((entry) => entry.type !== 'stopMessageSet' &&
144
- entry.type !== 'stopMessageMode' &&
145
- entry.type !== 'stopMessageClear' &&
146
- entry.type !== 'preCommandSet' &&
147
- entry.type !== 'preCommandClear');
148
- }
149
- if (hasRoutingInstructionMarker(request.messages) || responsesHasMarker) {
150
- request.messages = cleanMessagesFromRoutingInstructions(request.messages);
151
- cleanResponsesContextFromRoutingInstructions(responsesContext);
152
- }
153
- let appliedRoutingState = routingState;
154
- if (instructions.length > 0) {
155
- appliedRoutingState = applyRoutingInstructions(instructions, routingState);
156
- const persistedBaseState = stopMessageScope
157
- ? stripClientInjectScopedFields(appliedRoutingState)
158
- : appliedRoutingState;
159
- routingState = persistedBaseState;
160
- engine.routingInstructionState.set(stateKey, persistedBaseState);
161
- persistRoutingInstructionState(stateKey, persistedBaseState, engine.routingStateStore);
162
- // Persist stopMessage under tmux/clockd scope so client injection and trigger matching
163
- // use the same scope and never fall back to generic session keys.
164
- if (stopMessageScope) {
165
- const hasStopMessageSet = instructions.some((entry) => entry.type === 'stopMessageSet');
166
- const hasStopMessageMode = instructions.some((entry) => entry.type === 'stopMessageMode');
167
- const hasGlobalClear = instructions.some((entry) => entry.type === 'clear');
168
- const hasStopMessageClear = hasGlobalClear || instructions.some((entry) => entry.type === 'stopMessageClear');
169
- if (hasStopMessageSet || hasStopMessageMode || hasStopMessageClear) {
170
- const activeInstructionTypes = instructions
171
- .filter((entry) => entry.type === 'stopMessageSet' ||
172
- entry.type === 'stopMessageMode' ||
173
- entry.type === 'stopMessageClear')
174
- .map((entry) => entry.type);
175
- if (isStopScopeTraceEnabled()) {
176
- engine.debug?.log?.(`[virtual-router][stop_scope] requestId=${metadata.requestId || 'n/a'} stage=apply scope=${stopMessageScope} instructions=${activeInstructionTypes.join(',') || 'none'}`);
177
- }
178
- const sessionState = getRoutingInstructionState(stopMessageScope, engine.routingInstructionState, engine.routingStateStore);
179
- let nextSessionState = {
180
- ...sessionState
181
- };
182
- let shouldPersistSessionState = false;
183
- const hasStopMessageStateChanged = () => {
184
- return (nextSessionState.stopMessageText !== sessionState.stopMessageText ||
185
- nextSessionState.stopMessageMaxRepeats !== sessionState.stopMessageMaxRepeats ||
186
- nextSessionState.stopMessageUsed !== sessionState.stopMessageUsed ||
187
- nextSessionState.stopMessageUpdatedAt !== sessionState.stopMessageUpdatedAt ||
188
- nextSessionState.stopMessageLastUsedAt !== sessionState.stopMessageLastUsedAt ||
189
- nextSessionState.stopMessageSource !== sessionState.stopMessageSource ||
190
- nextSessionState.stopMessageStageMode !== sessionState.stopMessageStageMode ||
191
- nextSessionState.stopMessageAiMode !== sessionState.stopMessageAiMode ||
192
- nextSessionState.stopMessageAiSeedPrompt !== sessionState.stopMessageAiSeedPrompt ||
193
- JSON.stringify(nextSessionState.stopMessageAiHistory || []) !==
194
- JSON.stringify(sessionState.stopMessageAiHistory || []));
195
- };
196
- if (hasStopMessageClear) {
197
- if (hasGlobalClear) {
198
- // <**clear**> is a hard reset: clear all session-scoped routing state
199
- // and let persistRoutingInstructionState delete persistence markers.
200
- nextSessionState = {
201
- forcedTarget: undefined,
202
- stickyTarget: undefined,
203
- preferTarget: undefined,
204
- allowedProviders: new Set(),
205
- disabledProviders: new Set(),
206
- disabledKeys: new Map(),
207
- disabledModels: new Map(),
208
- stopMessageSource: undefined,
209
- stopMessageText: undefined,
210
- stopMessageMaxRepeats: undefined,
211
- stopMessageUsed: undefined,
212
- stopMessageUpdatedAt: undefined,
213
- stopMessageLastUsedAt: undefined,
214
- stopMessageStageMode: undefined,
215
- stopMessageAiMode: undefined,
216
- stopMessageAiSeedPrompt: undefined,
217
- stopMessageAiHistory: undefined,
218
- preCommandSource: undefined,
219
- preCommandScriptPath: undefined,
220
- preCommandUpdatedAt: undefined
221
- };
222
- shouldPersistSessionState = true;
223
- }
224
- else {
225
- nextSessionState.stopMessageText = undefined;
226
- nextSessionState.stopMessageMaxRepeats = undefined;
227
- nextSessionState.stopMessageUsed = undefined;
228
- nextSessionState.stopMessageUpdatedAt = undefined;
229
- nextSessionState.stopMessageLastUsedAt = undefined;
230
- nextSessionState.stopMessageSource = undefined;
231
- nextSessionState.stopMessageStageMode = undefined;
232
- nextSessionState.stopMessageAiMode = undefined;
233
- nextSessionState.stopMessageAiSeedPrompt = undefined;
234
- nextSessionState.stopMessageAiHistory = undefined;
235
- shouldPersistSessionState = true;
236
- }
237
- }
238
- else if (hasStopMessageSet || hasStopMessageMode) {
239
- nextSessionState.stopMessageText =
240
- typeof appliedRoutingState.stopMessageText === 'string' &&
241
- appliedRoutingState.stopMessageText.trim()
242
- ? appliedRoutingState.stopMessageText
243
- : undefined;
244
- nextSessionState.stopMessageMaxRepeats =
245
- typeof appliedRoutingState.stopMessageMaxRepeats === 'number' &&
246
- Number.isFinite(appliedRoutingState.stopMessageMaxRepeats)
247
- ? Math.floor(appliedRoutingState.stopMessageMaxRepeats)
248
- : undefined;
249
- nextSessionState.stopMessageUsed =
250
- typeof appliedRoutingState.stopMessageUsed === 'number' &&
251
- Number.isFinite(appliedRoutingState.stopMessageUsed)
252
- ? Math.max(0, Math.floor(appliedRoutingState.stopMessageUsed))
253
- : undefined;
254
- nextSessionState.stopMessageUpdatedAt =
255
- typeof appliedRoutingState.stopMessageUpdatedAt === 'number' &&
256
- Number.isFinite(appliedRoutingState.stopMessageUpdatedAt)
257
- ? appliedRoutingState.stopMessageUpdatedAt
258
- : undefined;
259
- nextSessionState.stopMessageLastUsedAt =
260
- typeof appliedRoutingState.stopMessageLastUsedAt === 'number' &&
261
- Number.isFinite(appliedRoutingState.stopMessageLastUsedAt)
262
- ? appliedRoutingState.stopMessageLastUsedAt
263
- : undefined;
264
- nextSessionState.stopMessageSource =
265
- typeof appliedRoutingState.stopMessageSource === 'string' &&
266
- appliedRoutingState.stopMessageSource.trim()
267
- ? appliedRoutingState.stopMessageSource.trim()
268
- : undefined;
269
- nextSessionState.stopMessageStageMode = normalizeStopMessageStageMode(appliedRoutingState.stopMessageStageMode);
270
- nextSessionState.stopMessageAiMode = normalizeStopMessageAiMode(appliedRoutingState.stopMessageAiMode);
271
- nextSessionState.stopMessageAiSeedPrompt =
272
- typeof appliedRoutingState.stopMessageAiSeedPrompt === 'string' &&
273
- appliedRoutingState.stopMessageAiSeedPrompt.trim()
274
- ? appliedRoutingState.stopMessageAiSeedPrompt.trim()
275
- : undefined;
276
- nextSessionState.stopMessageAiHistory = Array.isArray(appliedRoutingState.stopMessageAiHistory)
277
- ? appliedRoutingState.stopMessageAiHistory
278
- : undefined;
279
- shouldPersistSessionState = hasStopMessageStateChanged();
280
- }
281
- if (shouldPersistSessionState) {
282
- engine.routingInstructionState.set(stopMessageScope, nextSessionState);
283
- persistRoutingInstructionState(stopMessageScope, nextSessionState, engine.routingStateStore);
284
- }
285
- else {
286
- nextSessionState = sessionState;
287
- }
288
- // 日志展示使用 session scope 的 stopMessage 状态,避免每次解析重复刷新时间/次数。
289
- if (typeof nextSessionState.stopMessageText === 'string' ||
290
- typeof nextSessionState.stopMessageMaxRepeats === 'number' ||
291
- typeof nextSessionState.stopMessageStageMode === 'string' ||
292
- typeof nextSessionState.stopMessageAiMode === 'string' ||
293
- typeof nextSessionState.stopMessageAiSeedPrompt === 'string' ||
294
- Array.isArray(nextSessionState.stopMessageAiHistory)) {
295
- routingState.stopMessageText = nextSessionState.stopMessageText;
296
- routingState.stopMessageMaxRepeats = nextSessionState.stopMessageMaxRepeats;
297
- routingState.stopMessageUsed = nextSessionState.stopMessageUsed;
298
- routingState.stopMessageUpdatedAt = nextSessionState.stopMessageUpdatedAt;
299
- routingState.stopMessageLastUsedAt = nextSessionState.stopMessageLastUsedAt;
300
- routingState.stopMessageStageMode = nextSessionState.stopMessageStageMode;
301
- routingState.stopMessageAiMode = nextSessionState.stopMessageAiMode;
302
- routingState.stopMessageAiSeedPrompt = nextSessionState.stopMessageAiSeedPrompt;
303
- routingState.stopMessageAiHistory = nextSessionState.stopMessageAiHistory;
304
- }
305
- }
306
- }
307
- }
308
- if (instructions.length > 0 && stopMessageScope) {
309
- const hasPreCommandSet = instructions.some((entry) => entry.type === 'preCommandSet');
310
- const hasPreCommandClear = instructions.some((entry) => entry.type === 'preCommandClear');
311
- if (hasPreCommandSet || hasPreCommandClear) {
312
- const sessionState = getRoutingInstructionState(stopMessageScope, engine.routingInstructionState, engine.routingStateStore);
313
- const nextSessionState = {
314
- ...sessionState
315
- };
316
- let changed = false;
317
- if (hasPreCommandClear) {
318
- changed =
319
- typeof sessionState.preCommandScriptPath === 'string' ||
320
- typeof sessionState.preCommandSource === 'string' ||
321
- typeof sessionState.preCommandUpdatedAt === 'number';
322
- nextSessionState.preCommandScriptPath = undefined;
323
- nextSessionState.preCommandSource = undefined;
324
- nextSessionState.preCommandUpdatedAt = Date.now();
325
- }
326
- if (hasPreCommandSet) {
327
- const scriptPath = typeof appliedRoutingState.preCommandScriptPath === 'string'
328
- ? appliedRoutingState.preCommandScriptPath.trim()
329
- : '';
330
- if (scriptPath) {
331
- if (sessionState.preCommandScriptPath !== scriptPath) {
332
- changed = true;
333
- }
334
- nextSessionState.preCommandScriptPath = scriptPath;
335
- nextSessionState.preCommandSource = 'explicit';
336
- nextSessionState.preCommandUpdatedAt =
337
- typeof appliedRoutingState.preCommandUpdatedAt === 'number' &&
338
- Number.isFinite(appliedRoutingState.preCommandUpdatedAt)
339
- ? appliedRoutingState.preCommandUpdatedAt
340
- : Date.now();
341
- }
342
- }
343
- if (changed) {
344
- engine.routingInstructionState.set(stopMessageScope, nextSessionState);
345
- persistRoutingInstructionState(stopMessageScope, nextSessionState, engine.routingStateStore);
346
- routingState.preCommandScriptPath = nextSessionState.preCommandScriptPath;
347
- routingState.preCommandSource = nextSessionState.preCommandSource;
348
- routingState.preCommandUpdatedAt = nextSessionState.preCommandUpdatedAt;
349
- }
350
- }
351
- }
352
- if (instructions.length === 0 && stopMessageScope) {
353
- const sessionState = getRoutingInstructionState(stopMessageScope, engine.routingInstructionState, engine.routingStateStore);
354
- if (typeof sessionState.stopMessageText === 'string' ||
355
- typeof sessionState.stopMessageMaxRepeats === 'number' ||
356
- typeof sessionState.stopMessageStageMode === 'string' ||
357
- typeof sessionState.stopMessageAiMode === 'string' ||
358
- typeof sessionState.stopMessageAiSeedPrompt === 'string' ||
359
- Array.isArray(sessionState.stopMessageAiHistory)) {
360
- routingState.stopMessageText = sessionState.stopMessageText;
361
- routingState.stopMessageMaxRepeats = sessionState.stopMessageMaxRepeats;
362
- routingState.stopMessageUsed = sessionState.stopMessageUsed;
363
- routingState.stopMessageUpdatedAt = sessionState.stopMessageUpdatedAt;
364
- routingState.stopMessageLastUsedAt = sessionState.stopMessageLastUsedAt;
365
- routingState.stopMessageStageMode = sessionState.stopMessageStageMode;
366
- routingState.stopMessageAiMode = sessionState.stopMessageAiMode;
367
- routingState.stopMessageAiSeedPrompt = sessionState.stopMessageAiSeedPrompt;
368
- routingState.stopMessageAiHistory = sessionState.stopMessageAiHistory;
369
- }
370
- if (typeof sessionState.preCommandScriptPath === 'string' && sessionState.preCommandScriptPath.trim()) {
371
- routingState.preCommandScriptPath = sessionState.preCommandScriptPath;
372
- routingState.preCommandSource = sessionState.preCommandSource;
373
- routingState.preCommandUpdatedAt = sessionState.preCommandUpdatedAt;
374
- }
375
- }
376
- // Guardrail: if a session is restricted to providers that do not exist in any routing pools,
377
- // we must not hard-fail the request loop. Auto-clear the allowlist and fall back to normal routing.
378
- routingState = enforceAllowlistIntersection(engine, routingState, stateKey);
379
- return {
380
- routingState,
381
- stateKey,
382
- stopMessageScope,
383
- metadataInstructions,
384
- instructions
385
- };
386
- }
@@ -1,8 +0,0 @@
1
- import type { ProcessedRequest, StandardizedRequest } from '../../../conversion/hub/types/standardized.js';
2
- import type { RouterMetadataInput, RoutingDecision, RoutingDiagnostics, TargetMetadata } from '../types.js';
3
- import type { VirtualRouterEngine } from '../engine-legacy.js';
4
- export declare function routeRequest(engine: VirtualRouterEngine, request: StandardizedRequest | ProcessedRequest, metadata: RouterMetadataInput): {
5
- target: TargetMetadata;
6
- decision: RoutingDecision;
7
- diagnostics: RoutingDiagnostics;
8
- };
@@ -1,8 +0,0 @@
1
- import { buildRoutingState } from './route-state.js';
2
- import { selectRoutingTarget } from './route-selection.js';
3
- import { finalizeRoutingDecision } from './route-finalize.js';
4
- export function routeRequest(engine, request, metadata) {
5
- const routingStateResult = buildRoutingState(engine, request, metadata);
6
- const selectionResult = selectRoutingTarget(engine, request, metadata, routingStateResult.routingState, routingStateResult.stateKey);
7
- return finalizeRoutingDecision(engine, metadata, selectionResult.routingState, routingStateResult.metadataInstructions, routingStateResult.instructions, selectionResult);
8
- }