@jsonstudio/llms 0.6.2979 → 0.6.3238
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/args-mapping.js +8 -0
- package/dist/conversion/{shared/bridge-actions.js → bridge-actions.js} +2 -1
- package/dist/conversion/{shared/bridge-id-utils.js → bridge-id-utils.js} +1 -1
- package/dist/conversion/{shared/bridge-instructions.js → bridge-instructions.js} +1 -1
- package/dist/conversion/{shared/bridge-message-utils.d.ts → bridge-message-utils.d.ts} +1 -1
- package/dist/conversion/{shared/bridge-message-utils.js → bridge-message-utils.js} +5 -149
- package/dist/conversion/{shared/bridge-metadata.js → bridge-metadata.js} +1 -1
- package/dist/conversion/{shared/bridge-policies.js → bridge-policies.js} +1 -1
- package/dist/conversion/codecs/gemini-openai-codec.js +27 -8
- package/dist/conversion/codecs/responses-openai-codec.js +1 -1
- package/dist/conversion/{shared/compaction-detect.d.ts → compaction-detect.d.ts} +1 -1
- package/dist/conversion/compaction-detect.js +4 -0
- package/dist/conversion/compat/actions/apply-patch-fixer.js +2 -2
- package/dist/conversion/compat/actions/deepseek-web-response.d.ts +0 -1
- package/dist/conversion/compat/actions/deepseek-web-response.js +15 -405
- package/dist/conversion/compat/actions/harvest-tool-calls-from-text.js +1 -1
- package/dist/conversion/compat/actions/lmstudio-responses-fc-ids.js +1 -1
- package/dist/conversion/compat/actions/qwen-transform.js +74 -2
- package/dist/conversion/compat/actions/snapshot.js +1 -1
- package/dist/conversion/compat/antigravity-session-signature.js +36 -0
- package/dist/conversion/compat/profiles/chat-deepseek-web.json +0 -22
- package/dist/conversion/compat/profiles/chat-glm.json +251 -72
- package/dist/conversion/compat/profiles/chat-iflow.json +174 -39
- package/dist/conversion/compat/profiles/chat-lmstudio.json +43 -14
- package/dist/conversion/hub/operation-table/operation-table-runner.js +2 -2
- package/dist/conversion/hub/operation-table/semantic-mappers/anthropic-mapper.js +1 -1
- package/dist/conversion/hub/operation-table/semantic-mappers/archive/chat-mapper.archive.d.ts +8 -0
- package/dist/conversion/hub/operation-table/semantic-mappers/archive/chat-mapper.archive.js +404 -0
- package/dist/conversion/hub/operation-table/semantic-mappers/chat-mapper.js +5 -381
- package/dist/conversion/hub/operation-table/semantic-mappers/gemini-mapper.js +2 -2
- package/dist/conversion/hub/operation-table/semantic-mappers/responses-mapper.js +2 -8
- package/dist/conversion/hub/pipeline/hub-pipeline.d.ts +1 -0
- package/dist/conversion/hub/pipeline/hub-pipeline.js +50 -3
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage2_semantic_map/index.d.ts +1 -1
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage2_semantic_map/index.js +62 -0
- package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage2_route_select/index.js +3 -1
- package/dist/conversion/hub/pipeline/stages/resp_inbound/resp_inbound_stage1_sse_decode/index.js +1 -1
- package/dist/conversion/hub/pipeline/stages/resp_outbound/resp_outbound_stage1_client_remap/chat-process-semantics-bridge.d.ts +1 -1
- package/dist/conversion/hub/pipeline/stages/resp_process/resp_process_stage1_tool_governance/index.js +42 -29
- package/dist/conversion/hub/pipeline/stages/resp_process/resp_process_stage2_finalize/index.js +12 -0
- package/dist/conversion/hub/policy/protocol-spec.js +1 -1
- package/dist/conversion/hub/process/chat-process-clock-reminders.js +1 -1
- package/dist/conversion/hub/process/chat-process-clock-tools.js +1 -1
- package/dist/conversion/hub/process/chat-process-continue-execution.js +1 -1
- package/dist/conversion/hub/process/chat-process-servertool-orchestration.js +1 -1
- package/dist/conversion/hub/process/chat-process-web-search.js +1 -1
- package/dist/conversion/hub/response/provider-response.js +14 -5
- package/dist/conversion/hub/response/response-mappers.js +23 -1
- package/dist/conversion/hub/response/response-runtime.js +28 -5
- package/dist/conversion/hub/snapshot-recorder.js +3 -92
- package/dist/conversion/hub/tool-governance/engine.d.ts +8 -0
- package/dist/conversion/hub/tool-governance/engine.js +40 -193
- package/dist/conversion/hub/tool-governance/rules.js +73 -69
- package/dist/conversion/hub/tool-surface/tool-surface-engine.js +1 -1
- package/dist/conversion/index.d.ts +1 -2
- package/dist/conversion/index.js +1 -2
- package/dist/conversion/{shared/jsonish.js → jsonish.js} +1 -1
- package/dist/conversion/{shared/mcp-injection.js → mcp-injection.js} +1 -1
- package/dist/conversion/media.js +4 -0
- package/dist/conversion/{shared/metadata-passthrough.d.ts → metadata-passthrough.d.ts} +1 -1
- package/dist/conversion/{shared/metadata-passthrough.js → metadata-passthrough.js} +2 -2
- package/dist/conversion/payload-budget.js +47 -0
- package/dist/conversion/protocol-field-allowlists.d.ts +7 -0
- package/dist/conversion/protocol-field-allowlists.js +9 -0
- package/dist/conversion/{shared/protocol-state.d.ts → protocol-state.d.ts} +2 -2
- package/dist/conversion/{shared/protocol-state.js → protocol-state.js} +2 -2
- package/dist/conversion/{shared/errors.d.ts → provider-protocol-error.d.ts} +0 -3
- package/dist/conversion/provider-protocol-error.js +25 -0
- package/dist/conversion/responses/responses-openai-bridge/response-payload.js +8 -5
- package/dist/conversion/responses/responses-openai-bridge/types.d.ts +1 -1
- package/dist/conversion/responses/responses-openai-bridge.d.ts +1 -1
- package/dist/conversion/responses/responses-openai-bridge.js +43 -10
- package/dist/conversion/{shared/runtime-metadata.d.ts → runtime-metadata.d.ts} +1 -1
- package/dist/conversion/{shared/runtime-metadata.js → runtime-metadata.js} +2 -2
- package/dist/conversion/shared/anthropic-message-utils.js +19 -8
- package/dist/conversion/shared/chat-request-filters.d.ts +3 -4
- package/dist/conversion/shared/chat-request-filters.js +22 -78
- package/dist/conversion/shared/gemini-tool-utils.d.ts +1 -1
- package/dist/conversion/shared/openai-finalizer.js +1 -0
- package/dist/conversion/shared/openai-message-normalize.js +2 -2
- package/dist/conversion/shared/reasoning-normalizer.js +6 -0
- package/dist/conversion/shared/reasoning-utils.js +5 -2
- package/dist/conversion/shared/responses-conversation-store.js +1 -1
- package/dist/conversion/shared/responses-output-builder.js +55 -11
- package/dist/conversion/shared/responses-reasoning-registry.d.ts +14 -2
- package/dist/conversion/shared/responses-reasoning-registry.js +34 -6
- package/dist/conversion/shared/responses-response-utils.js +99 -9
- package/dist/conversion/shared/responses-tool-utils.js +1 -1
- package/dist/conversion/shared/text-markup-normalizer/normalize.d.ts +1 -1
- package/dist/conversion/shared/text-markup-normalizer.d.ts +2 -2
- package/dist/conversion/shared/text-markup-normalizer.js +1 -1
- package/dist/conversion/shared/tool-filter-pipeline.js +1 -1
- package/dist/conversion/shared/tool-governor.js +3 -3
- package/dist/conversion/shared/tool-mapping.d.ts +1 -1
- package/dist/conversion/{shared/snapshot-utils.d.ts → snapshot-utils.d.ts} +11 -0
- package/dist/conversion/{shared/snapshot-utils.js → snapshot-utils.js} +14 -23
- package/dist/conversion/types/text-markup-normalizer.d.ts +13 -0
- package/dist/conversion/types/text-markup-normalizer.js +1 -0
- package/dist/filters/special/request-tools-normalize.js +1 -1
- package/dist/filters/special/response-tool-text-canonicalize.js +2 -2
- package/dist/native/router_hotpath_napi.node +0 -0
- package/dist/quota/quota-manager.js +31 -59
- package/dist/quota/quota-state.js +14 -7
- package/dist/router/virtual-router/bootstrap/profile-builder.d.ts +1 -0
- package/dist/router/virtual-router/bootstrap/profile-builder.js +13 -0
- package/dist/router/virtual-router/bootstrap/provider-normalization.d.ts +2 -0
- package/dist/router/virtual-router/bootstrap/provider-normalization.js +4 -1
- package/dist/router/virtual-router/bootstrap/streaming-helpers.d.ts +7 -0
- package/dist/router/virtual-router/bootstrap/streaming-helpers.js +44 -0
- package/dist/router/virtual-router/bootstrap.js +2 -0
- package/dist/router/virtual-router/engine/routing-state/store.d.ts +1 -2
- package/dist/router/virtual-router/engine/routing-state/store.js +2 -2
- package/dist/router/virtual-router/engine-legacy/config.d.ts +11 -0
- package/dist/router/virtual-router/engine-legacy/config.js +108 -0
- package/dist/router/virtual-router/engine-legacy/direct-model.d.ts +10 -0
- package/dist/router/virtual-router/engine-legacy/direct-model.js +38 -0
- package/dist/router/virtual-router/engine-legacy/health.d.ts +13 -0
- package/dist/router/virtual-router/engine-legacy/health.js +104 -0
- package/dist/router/virtual-router/engine-legacy/helpers.d.ts +16 -0
- package/dist/router/virtual-router/engine-legacy/helpers.js +226 -0
- package/dist/router/virtual-router/engine-legacy/route-finalize.d.ts +9 -0
- package/dist/router/virtual-router/engine-legacy/route-finalize.js +84 -0
- package/dist/router/virtual-router/engine-legacy/route-selection.d.ts +17 -0
- package/dist/router/virtual-router/engine-legacy/route-selection.js +205 -0
- package/dist/router/virtual-router/engine-legacy/route-state-allowlist.d.ts +3 -0
- package/dist/router/virtual-router/engine-legacy/route-state-allowlist.js +36 -0
- package/dist/router/virtual-router/engine-legacy/route-state.d.ts +12 -0
- package/dist/router/virtual-router/engine-legacy/route-state.js +386 -0
- package/dist/router/virtual-router/engine-legacy/route-utils.d.ts +19 -0
- package/dist/router/virtual-router/engine-legacy/route-utils.js +212 -0
- package/dist/router/virtual-router/engine-legacy/routing.d.ts +8 -0
- package/dist/router/virtual-router/engine-legacy/routing.js +8 -0
- package/dist/router/virtual-router/engine-legacy/selection-core.d.ts +28 -0
- package/dist/router/virtual-router/engine-legacy/selection-core.js +112 -0
- package/dist/router/virtual-router/engine-legacy/selection-state.d.ts +16 -0
- package/dist/router/virtual-router/engine-legacy/selection-state.js +187 -0
- package/dist/router/virtual-router/engine-legacy/state-accessors.d.ts +21 -0
- package/dist/router/virtual-router/engine-legacy/state-accessors.js +118 -0
- package/dist/router/virtual-router/engine-legacy.d.ts +123 -0
- package/dist/router/virtual-router/engine-legacy.js +194 -0
- package/dist/router/virtual-router/engine-logging.d.ts +2 -0
- package/dist/router/virtual-router/engine-logging.js +7 -2
- package/dist/router/virtual-router/engine-selection/key-parsing.js +0 -3
- package/dist/router/virtual-router/engine-selection/native-chat-request-filter-semantics.d.ts +1 -0
- package/dist/router/virtual-router/engine-selection/native-chat-request-filter-semantics.js +54 -0
- package/dist/router/virtual-router/engine-selection/native-hub-bridge-policy-semantics.d.ts +10 -0
- package/dist/router/virtual-router/engine-selection/native-hub-bridge-policy-semantics.js +67 -0
- package/dist/router/virtual-router/engine-selection/native-hub-pipeline-governance-semantics.d.ts +30 -0
- package/dist/router/virtual-router/engine-selection/native-hub-pipeline-governance-semantics.js +202 -0
- package/dist/router/virtual-router/engine-selection/native-hub-pipeline-semantic-mappers.d.ts +2 -0
- package/dist/router/virtual-router/engine-selection/native-hub-pipeline-semantic-mappers.js +83 -0
- package/dist/router/virtual-router/engine-selection/native-router-hotpath-loader.js +43 -2
- package/dist/router/virtual-router/engine-selection/native-shared-conversion-semantics.d.ts +75 -0
- package/dist/router/virtual-router/engine-selection/native-shared-conversion-semantics.js +205 -0
- package/dist/router/virtual-router/engine-selection/native-snapshot-hooks.d.ts +3 -0
- package/dist/router/virtual-router/engine-selection/native-snapshot-hooks.js +109 -0
- package/dist/router/virtual-router/engine-selection/native-virtual-router-engine-proxy.d.ts +16 -0
- package/dist/router/virtual-router/engine-selection/native-virtual-router-engine-proxy.js +14 -0
- package/dist/router/virtual-router/engine-selection/native-virtual-router-routing-instructions-semantics.d.ts +2 -0
- package/dist/router/virtual-router/engine-selection/native-virtual-router-routing-instructions-semantics.js +86 -0
- package/dist/router/virtual-router/engine-selection/tier-selection-quota-integration.js +100 -0
- package/dist/router/virtual-router/engine-selection/tier-selection-select.js +99 -0
- package/dist/router/virtual-router/engine.d.ts +22 -105
- package/dist/router/virtual-router/engine.js +274 -1641
- package/dist/router/virtual-router/load-balancer.d.ts +8 -0
- package/dist/router/virtual-router/load-balancer.js +65 -2
- package/dist/router/virtual-router/provider-registry.js +2 -0
- package/dist/router/virtual-router/routing-instructions/clean.d.ts +3 -0
- package/dist/router/virtual-router/routing-instructions/clean.js +34 -0
- package/dist/router/virtual-router/routing-instructions/parse.d.ts +18 -0
- package/dist/router/virtual-router/routing-instructions/parse.js +377 -0
- package/dist/router/virtual-router/routing-instructions/state.d.ts +4 -0
- package/dist/router/virtual-router/routing-instructions/state.js +245 -0
- package/dist/router/virtual-router/routing-instructions/types.d.ts +70 -0
- package/dist/router/virtual-router/routing-instructions/types.js +2 -0
- package/dist/router/virtual-router/routing-instructions.d.ts +5 -89
- package/dist/router/virtual-router/routing-instructions.js +4 -655
- package/dist/router/virtual-router/sticky-session-store.d.ts +4 -0
- package/dist/router/virtual-router/sticky-session-store.js +19 -81
- package/dist/router/virtual-router/tool-signals.js +21 -3
- package/dist/router/virtual-router/types.d.ts +4 -0
- package/dist/servertool/clock/session-scope.js +32 -1
- package/dist/servertool/engine.js +79 -8
- package/dist/servertool/handlers/antigravity-thought-signature-bootstrap.js +1 -1
- package/dist/servertool/handlers/clock-auto.js +1 -1
- package/dist/servertool/handlers/clock.js +1 -1
- package/dist/servertool/handlers/compaction-detect.d.ts +1 -1
- package/dist/servertool/handlers/compaction-detect.js +1 -1
- package/dist/servertool/handlers/gemini-empty-reply-continue.js +1 -1
- package/dist/servertool/handlers/iflow-model-error-retry.js +1 -1
- package/dist/servertool/handlers/recursive-detection-guard.js +1 -1
- package/dist/servertool/handlers/review.js +1 -1
- package/dist/servertool/handlers/stop-message-auto/iflow-followup.js +1 -1
- package/dist/servertool/handlers/stop-message-auto/runtime-utils.js +1 -1
- package/dist/servertool/handlers/stop-message-auto.js +1 -1
- package/dist/servertool/handlers/vision.js +1 -1
- package/dist/servertool/handlers/web-search.js +1 -1
- package/dist/servertool/reenter-backend.js +1 -1
- package/dist/servertool/server-side-tools.js +2 -2
- package/dist/servertool/stop-gateway-context.js +1 -1
- package/dist/servertool/stop-message-compare-context.js +1 -1
- package/dist/sse/json-to-sse/event-generators/responses.d.ts +4 -0
- package/dist/sse/json-to-sse/event-generators/responses.js +95 -1
- package/dist/sse/json-to-sse/sequencers/responses-sequencer.js +6 -4
- package/dist/sse/sse-to-json/builders/response-builder.d.ts +8 -0
- package/dist/sse/sse-to-json/builders/response-builder.js +162 -4
- package/dist/sse/sse-to-json/responses-sse-to-json-converter.js +2 -0
- package/dist/sse/types/responses-types.d.ts +6 -2
- package/dist/tools/apply-patch/structured/coercion.js +5 -0
- package/dist/tools/args-json.js +29 -0
- package/package.json +8 -5
- package/dist/conversion/shared/args-mapping.js +0 -77
- package/dist/conversion/shared/compaction-detect.js +0 -4
- package/dist/conversion/shared/errors.js +0 -31
- package/dist/conversion/shared/media.js +0 -4
- package/dist/conversion/shared/payload-budget.js +0 -165
- package/dist/conversion/shared/protocol-field-allowlists.d.ts +0 -7
- package/dist/conversion/shared/protocol-field-allowlists.js +0 -149
- package/dist/conversion/shared/snapshot-hooks.d.ts +0 -11
- package/dist/conversion/shared/snapshot-hooks.js +0 -503
- package/dist/conversion/shared/text-markup-normalizer/extractors-apply-patch.d.ts +0 -2
- package/dist/conversion/shared/text-markup-normalizer/extractors-apply-patch.js +0 -129
- package/dist/conversion/shared/text-markup-normalizer/extractors-json.d.ts +0 -4
- package/dist/conversion/shared/text-markup-normalizer/extractors-json.js +0 -637
- package/dist/conversion/shared/text-markup-normalizer/extractors-shared.d.ts +0 -21
- package/dist/conversion/shared/text-markup-normalizer/extractors-shared.js +0 -177
- package/dist/conversion/shared/text-markup-normalizer/extractors-transcript.d.ts +0 -5
- package/dist/conversion/shared/text-markup-normalizer/extractors-transcript.js +0 -385
- package/dist/conversion/shared/text-markup-normalizer/extractors-xml.d.ts +0 -10
- package/dist/conversion/shared/text-markup-normalizer/extractors-xml.js +0 -602
- package/dist/conversion/shared/text-markup-normalizer/extractors.d.ts +0 -5
- package/dist/conversion/shared/text-markup-normalizer/extractors.js +0 -4
- package/dist/conversion/shared/tool-canonicalizer.d.ts +0 -2
- package/dist/conversion/shared/tool-canonicalizer.js +0 -38
- /package/dist/conversion/{shared/args-mapping.d.ts → args-mapping.d.ts} +0 -0
- /package/dist/conversion/{shared/bridge-actions.d.ts → bridge-actions.d.ts} +0 -0
- /package/dist/conversion/{shared/bridge-id-utils.d.ts → bridge-id-utils.d.ts} +0 -0
- /package/dist/conversion/{shared/bridge-instructions.d.ts → bridge-instructions.d.ts} +0 -0
- /package/dist/conversion/{shared/bridge-metadata.d.ts → bridge-metadata.d.ts} +0 -0
- /package/dist/conversion/{shared/bridge-policies.d.ts → bridge-policies.d.ts} +0 -0
- /package/dist/conversion/{shared/jsonish.d.ts → jsonish.d.ts} +0 -0
- /package/dist/conversion/{shared/mcp-injection.d.ts → mcp-injection.d.ts} +0 -0
- /package/dist/conversion/{shared/media.d.ts → media.d.ts} +0 -0
- /package/dist/conversion/{shared/payload-budget.d.ts → payload-budget.d.ts} +0 -0
- /package/dist/conversion/{shared → types}/bridge-message-types.d.ts +0 -0
- /package/dist/conversion/{shared → types}/bridge-message-types.js +0 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { failNativeRequired } from './native-router-hotpath-policy.js';
|
|
2
|
+
import { loadNativeRouterHotpathBindingForInternalUse } from './native-router-hotpath.js';
|
|
3
|
+
function readNativeFunction(name) {
|
|
4
|
+
const binding = loadNativeRouterHotpathBindingForInternalUse();
|
|
5
|
+
const fn = binding?.[name];
|
|
6
|
+
return typeof fn === 'function' ? fn : null;
|
|
7
|
+
}
|
|
8
|
+
function safeStringify(value) {
|
|
9
|
+
try {
|
|
10
|
+
return JSON.stringify(value);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function parseArrayPayload(raw) {
|
|
17
|
+
try {
|
|
18
|
+
const parsed = JSON.parse(raw);
|
|
19
|
+
if (!Array.isArray(parsed))
|
|
20
|
+
return null;
|
|
21
|
+
return parsed.filter((entry) => typeof entry === 'string');
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function parseRecordPayload(raw) {
|
|
28
|
+
try {
|
|
29
|
+
const parsed = JSON.parse(raw);
|
|
30
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
return parsed;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export function parseRoutingInstructionKindsWithNative(request) {
|
|
40
|
+
const capability = 'parseRoutingInstructionKindsJson';
|
|
41
|
+
const fail = (reason) => failNativeRequired(capability, reason);
|
|
42
|
+
const fn = readNativeFunction(capability);
|
|
43
|
+
if (!fn) {
|
|
44
|
+
return fail();
|
|
45
|
+
}
|
|
46
|
+
const requestJson = safeStringify(request);
|
|
47
|
+
if (!requestJson) {
|
|
48
|
+
return fail('json stringify failed');
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
const result = fn(requestJson);
|
|
52
|
+
if (typeof result !== 'string' || !result) {
|
|
53
|
+
return fail('empty result');
|
|
54
|
+
}
|
|
55
|
+
const parsed = parseArrayPayload(result);
|
|
56
|
+
return parsed ?? fail('invalid payload');
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
|
|
60
|
+
return fail(reason);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export function cleanRoutingInstructionMarkersWithNative(request) {
|
|
64
|
+
const capability = 'cleanRoutingInstructionMarkersJson';
|
|
65
|
+
const fail = (reason) => failNativeRequired(capability, reason);
|
|
66
|
+
const fn = readNativeFunction(capability);
|
|
67
|
+
if (!fn) {
|
|
68
|
+
return fail();
|
|
69
|
+
}
|
|
70
|
+
const requestJson = safeStringify(request);
|
|
71
|
+
if (!requestJson) {
|
|
72
|
+
return fail('json stringify failed');
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
const result = fn(requestJson);
|
|
76
|
+
if (typeof result !== 'string' || !result) {
|
|
77
|
+
return fail('empty result');
|
|
78
|
+
}
|
|
79
|
+
const parsed = parseRecordPayload(result);
|
|
80
|
+
return parsed ?? fail('invalid payload');
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
|
|
84
|
+
return fail(reason);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -3,6 +3,72 @@ import { computeHealthWeight } from '../health-weighted.js';
|
|
|
3
3
|
import { buildQuotaBuckets } from './native-router-hotpath.js';
|
|
4
4
|
import { computeContextWeightMultipliers } from './context-weight-multipliers.js';
|
|
5
5
|
import { pickPriorityGroup } from './tier-priority.js';
|
|
6
|
+
import { extractProviderId, getProviderModelId } from './key-parsing.js';
|
|
7
|
+
function buildPrimaryTargetGroups(candidates, deps) {
|
|
8
|
+
const groups = new Map();
|
|
9
|
+
for (const key of candidates) {
|
|
10
|
+
const providerId = extractProviderId(key) ?? '';
|
|
11
|
+
if (!providerId) {
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
let modelId;
|
|
15
|
+
try {
|
|
16
|
+
modelId = getProviderModelId(key, deps.providerRegistry) ?? undefined;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
modelId = undefined;
|
|
20
|
+
}
|
|
21
|
+
const groupId = modelId ? `${providerId}.${modelId}` : providerId;
|
|
22
|
+
const entry = groups.get(groupId) ?? [];
|
|
23
|
+
entry.push(key);
|
|
24
|
+
groups.set(groupId, entry);
|
|
25
|
+
}
|
|
26
|
+
return groups;
|
|
27
|
+
}
|
|
28
|
+
function resolveGroupWeight(groupId, weights) {
|
|
29
|
+
if (!weights) {
|
|
30
|
+
return 1;
|
|
31
|
+
}
|
|
32
|
+
const direct = weights[groupId];
|
|
33
|
+
if (typeof direct === 'number' && Number.isFinite(direct) && direct > 0) {
|
|
34
|
+
return direct;
|
|
35
|
+
}
|
|
36
|
+
const providerId = groupId.split('.')[0] ?? groupId;
|
|
37
|
+
const providerOnly = weights[providerId];
|
|
38
|
+
if (typeof providerOnly === 'number' && Number.isFinite(providerOnly) && providerOnly > 0) {
|
|
39
|
+
return providerOnly;
|
|
40
|
+
}
|
|
41
|
+
return 1;
|
|
42
|
+
}
|
|
43
|
+
function buildGroupWeights(groups, weights) {
|
|
44
|
+
if (!groups.size) {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
const out = {};
|
|
48
|
+
for (const [groupId] of groups.entries()) {
|
|
49
|
+
out[groupId] = resolveGroupWeight(groupId, weights);
|
|
50
|
+
}
|
|
51
|
+
return out;
|
|
52
|
+
}
|
|
53
|
+
function hasNonUniformWeights(candidates, weights) {
|
|
54
|
+
if (!weights || candidates.length < 2) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
let ref;
|
|
58
|
+
for (const key of candidates) {
|
|
59
|
+
const raw = weights[key];
|
|
60
|
+
if (typeof raw !== 'number' || !Number.isFinite(raw)) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (ref === undefined) {
|
|
64
|
+
ref = raw;
|
|
65
|
+
}
|
|
66
|
+
else if (Math.abs(raw - ref) > 1e-6) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
6
72
|
export function selectProviderKeyWithQuotaBuckets(opts) {
|
|
7
73
|
const { routeName, tier, stickyKey, candidates, isSafePool, deps, options, contextResult, warnRatio, isRecoveryAttempt, now, nowForWeights, healthWeightedCfg, contextWeightedCfg, quotaView, isAvailable, selectFirstAvailable, applyAliasStickyQueuePinning, preferAntigravityAliasesOnRetry } = opts;
|
|
8
74
|
const bucketInputs = candidates.map((key, order) => {
|
|
@@ -78,6 +144,23 @@ export function selectProviderKeyWithQuotaBuckets(opts) {
|
|
|
78
144
|
for (const key of group.groupCandidates) {
|
|
79
145
|
groupWeights[key] = bucketWeights[key] ?? 1;
|
|
80
146
|
}
|
|
147
|
+
const allowGrouped = !hasNonUniformWeights(group.groupCandidates, bucketWeights);
|
|
148
|
+
if (allowGrouped && deps.loadBalancer.getPolicy().strategy !== 'sticky') {
|
|
149
|
+
const groups = buildPrimaryTargetGroups(group.groupCandidates, deps);
|
|
150
|
+
if (groups.size > 0) {
|
|
151
|
+
const groupWeightMap = buildGroupWeights(groups, deps.loadBalancer.getPolicy().weights);
|
|
152
|
+
const selected = deps.loadBalancer.selectGrouped({
|
|
153
|
+
routeName: `${routeName}:${tier.id}:priority:${priority}:group:${group.groupId}`,
|
|
154
|
+
groups,
|
|
155
|
+
stickyKey: options.allowAliasRotation ? undefined : stickyKey,
|
|
156
|
+
weights: groupWeightMap,
|
|
157
|
+
availabilityCheck: isAvailable
|
|
158
|
+
}, 'round-robin');
|
|
159
|
+
if (selected) {
|
|
160
|
+
return selected;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
81
164
|
const selected = deps.loadBalancer.select({
|
|
82
165
|
routeName: `${routeName}:${tier.id}:priority:${priority}:group:${group.groupId}`,
|
|
83
166
|
candidates: group.groupCandidates,
|
|
@@ -101,6 +184,23 @@ export function selectProviderKeyWithQuotaBuckets(opts) {
|
|
|
101
184
|
return recovered;
|
|
102
185
|
continue;
|
|
103
186
|
}
|
|
187
|
+
const allowGrouped = !hasNonUniformWeights(bucketCandidates, bucketWeights);
|
|
188
|
+
if (allowGrouped && deps.loadBalancer.getPolicy().strategy !== 'sticky') {
|
|
189
|
+
const groups = buildPrimaryTargetGroups(bucketCandidates, deps);
|
|
190
|
+
if (groups.size > 0) {
|
|
191
|
+
const groupWeightMap = buildGroupWeights(groups, deps.loadBalancer.getPolicy().weights);
|
|
192
|
+
const selected = deps.loadBalancer.selectGrouped({
|
|
193
|
+
routeName: `${routeName}:${tier.id}:${priority}`,
|
|
194
|
+
groups,
|
|
195
|
+
stickyKey: options.allowAliasRotation ? undefined : stickyKey,
|
|
196
|
+
weights: groupWeightMap,
|
|
197
|
+
availabilityCheck: isAvailable
|
|
198
|
+
}, tier.mode === 'round-robin' ? 'round-robin' : undefined);
|
|
199
|
+
if (selected) {
|
|
200
|
+
return selected;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
104
204
|
const selected = deps.loadBalancer.select({
|
|
105
205
|
routeName: `${routeName}:${tier.id}`,
|
|
106
206
|
candidates: bucketCandidates,
|
|
@@ -4,6 +4,71 @@ import { computeContextWeightMultipliers } from './context-weight-multipliers.js
|
|
|
4
4
|
import { extractKeyAlias, extractProviderId, getProviderModelId } from './key-parsing.js';
|
|
5
5
|
import { pickPriorityGroup } from './tier-priority.js';
|
|
6
6
|
import { selectProviderKeyWithQuotaBuckets } from './tier-selection-quota-integration.js';
|
|
7
|
+
function buildPrimaryTargetGroups(candidates, deps) {
|
|
8
|
+
const groups = new Map();
|
|
9
|
+
for (const key of candidates) {
|
|
10
|
+
const providerId = extractProviderId(key) ?? '';
|
|
11
|
+
if (!providerId) {
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
let modelId;
|
|
15
|
+
try {
|
|
16
|
+
modelId = getProviderModelId(key, deps.providerRegistry) ?? undefined;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
modelId = undefined;
|
|
20
|
+
}
|
|
21
|
+
const groupId = modelId ? `${providerId}.${modelId}` : providerId;
|
|
22
|
+
const entry = groups.get(groupId) ?? [];
|
|
23
|
+
entry.push(key);
|
|
24
|
+
groups.set(groupId, entry);
|
|
25
|
+
}
|
|
26
|
+
return groups;
|
|
27
|
+
}
|
|
28
|
+
function resolveGroupWeight(groupId, weights) {
|
|
29
|
+
if (!weights) {
|
|
30
|
+
return 1;
|
|
31
|
+
}
|
|
32
|
+
const direct = weights[groupId];
|
|
33
|
+
if (typeof direct === 'number' && Number.isFinite(direct) && direct > 0) {
|
|
34
|
+
return direct;
|
|
35
|
+
}
|
|
36
|
+
const providerId = groupId.split('.')[0] ?? groupId;
|
|
37
|
+
const providerOnly = weights[providerId];
|
|
38
|
+
if (typeof providerOnly === 'number' && Number.isFinite(providerOnly) && providerOnly > 0) {
|
|
39
|
+
return providerOnly;
|
|
40
|
+
}
|
|
41
|
+
return 1;
|
|
42
|
+
}
|
|
43
|
+
function buildGroupWeights(groups, weights) {
|
|
44
|
+
if (!groups.size) {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
const out = {};
|
|
48
|
+
for (const [groupId] of groups.entries()) {
|
|
49
|
+
out[groupId] = resolveGroupWeight(groupId, weights);
|
|
50
|
+
}
|
|
51
|
+
return out;
|
|
52
|
+
}
|
|
53
|
+
function hasNonUniformWeights(candidates, weights) {
|
|
54
|
+
if (!weights || candidates.length < 2) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
let ref;
|
|
58
|
+
for (const key of candidates) {
|
|
59
|
+
const raw = weights[key];
|
|
60
|
+
if (typeof raw !== 'number' || !Number.isFinite(raw)) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (ref === undefined) {
|
|
64
|
+
ref = raw;
|
|
65
|
+
}
|
|
66
|
+
else if (Math.abs(raw - ref) > 1e-6) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
7
72
|
function applyAliasStickyQueuePinning(opts) {
|
|
8
73
|
const { candidates, orderedTargets, deps, excludedKeys } = opts;
|
|
9
74
|
if (!Array.isArray(candidates) || candidates.length < 2) {
|
|
@@ -217,6 +282,23 @@ export function selectProviderKeyFromCandidatePool(opts) {
|
|
|
217
282
|
}
|
|
218
283
|
return out;
|
|
219
284
|
})();
|
|
285
|
+
const allowGrouped = !hasNonUniformWeights(group.groupCandidates, weights);
|
|
286
|
+
if (allowGrouped && deps.loadBalancer.getPolicy().strategy !== 'sticky') {
|
|
287
|
+
const groups = buildPrimaryTargetGroups(group.groupCandidates, deps);
|
|
288
|
+
if (groups.size > 0) {
|
|
289
|
+
const groupWeights = buildGroupWeights(groups, deps.loadBalancer.getPolicy().weights);
|
|
290
|
+
const selected = deps.loadBalancer.selectGrouped({
|
|
291
|
+
routeName: `${routeName}:${tier.id}:priority:group:${group.groupId}`,
|
|
292
|
+
groups,
|
|
293
|
+
stickyKey: options.allowAliasRotation ? undefined : stickyKey,
|
|
294
|
+
weights: groupWeights,
|
|
295
|
+
availabilityCheck: isAvailable
|
|
296
|
+
}, 'round-robin');
|
|
297
|
+
if (selected) {
|
|
298
|
+
return selected;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
220
302
|
return deps.loadBalancer.select({
|
|
221
303
|
routeName: `${routeName}:${tier.id}:priority:group:${group.groupId}`,
|
|
222
304
|
candidates: group.groupCandidates,
|
|
@@ -242,6 +324,23 @@ export function selectProviderKeyFromCandidatePool(opts) {
|
|
|
242
324
|
}
|
|
243
325
|
return out;
|
|
244
326
|
})();
|
|
327
|
+
const allowGrouped = !hasNonUniformWeights(pinnedCandidates, weights);
|
|
328
|
+
if (allowGrouped && deps.loadBalancer.getPolicy().strategy !== 'sticky') {
|
|
329
|
+
const groups = buildPrimaryTargetGroups(pinnedCandidates, deps);
|
|
330
|
+
if (groups.size > 0) {
|
|
331
|
+
const groupWeights = buildGroupWeights(groups, deps.loadBalancer.getPolicy().weights);
|
|
332
|
+
const selected = deps.loadBalancer.selectGrouped({
|
|
333
|
+
routeName: `${routeName}:${tier.id}`,
|
|
334
|
+
groups,
|
|
335
|
+
stickyKey: options.allowAliasRotation ? undefined : stickyKey,
|
|
336
|
+
weights: groupWeights,
|
|
337
|
+
availabilityCheck: isAvailable
|
|
338
|
+
}, tier.mode === 'round-robin' ? 'round-robin' : undefined);
|
|
339
|
+
if (selected) {
|
|
340
|
+
return selected;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
245
344
|
return deps.loadBalancer.select({
|
|
246
345
|
routeName: `${routeName}:${tier.id}`,
|
|
247
346
|
candidates: pinnedCandidates,
|
|
@@ -1,51 +1,34 @@
|
|
|
1
|
-
import { type RoutingDecision, type RoutingDiagnostics, type StopMessageStateSnapshot, type PreCommandStateSnapshot, type RouterMetadataInput, type VirtualRouterConfig, type TargetMetadata, type ProviderFailureEvent, type ProviderErrorEvent, type ProviderSuccessEvent, type VirtualRouterHealthStore } from './types.js';
|
|
2
1
|
import type { ProcessedRequest, StandardizedRequest } from '../../conversion/hub/types/standardized.js';
|
|
3
|
-
import {
|
|
4
|
-
import type { ProviderQuotaView } from './types.js';
|
|
5
|
-
interface RoutingInstructionStateStore {
|
|
6
|
-
loadSync(key: string): RoutingInstructionState | null;
|
|
7
|
-
saveAsync(key: string, state: RoutingInstructionState | null): void;
|
|
8
|
-
saveSync?: (key: string, state: RoutingInstructionState | null) => void;
|
|
9
|
-
}
|
|
2
|
+
import type { ProviderErrorEvent, ProviderFailureEvent, ProviderQuotaView, ProviderSuccessEvent, RouterMetadataInput, RoutingDecision, RoutingDiagnostics, RoutingStatusSnapshot, StopMessageStateSnapshot, PreCommandStateSnapshot, TargetMetadata, VirtualRouterConfig, VirtualRouterHealthStore } from './types.js';
|
|
10
3
|
export declare class VirtualRouterEngine {
|
|
11
|
-
private
|
|
12
|
-
private readonly
|
|
13
|
-
private readonly
|
|
14
|
-
private get providerCooldowns();
|
|
15
|
-
private loadBalancer;
|
|
16
|
-
private classifier;
|
|
17
|
-
private readonly contextAdvisor;
|
|
18
|
-
private contextRouting;
|
|
19
|
-
private readonly routeAnalytics;
|
|
20
|
-
private stickySessionManager;
|
|
21
|
-
private cooldownManager;
|
|
22
|
-
private antigravityLeasePersistence;
|
|
23
|
-
private readonly debug;
|
|
24
|
-
private healthConfig;
|
|
25
|
-
private readonly statsCenter;
|
|
26
|
-
private webSearchForce;
|
|
27
|
-
private healthStore?;
|
|
28
|
-
private routingStateStore;
|
|
29
|
-
private routingInstructionState;
|
|
30
|
-
private quotaView?;
|
|
31
|
-
/**
|
|
32
|
-
* Backward-compatible test/debug surface used by existing regression scripts.
|
|
33
|
-
* Keep this as a read-only view over StickySessionManager storage.
|
|
34
|
-
*/
|
|
35
|
-
get antigravitySessionAliasStore(): Map<string, string>;
|
|
4
|
+
private readonly nativeProxy;
|
|
5
|
+
private readonly registry;
|
|
6
|
+
private readonly routingInstructionStateStore;
|
|
36
7
|
constructor(deps?: {
|
|
37
8
|
healthStore?: VirtualRouterHealthStore;
|
|
38
|
-
routingStateStore?:
|
|
9
|
+
routingStateStore?: {
|
|
10
|
+
loadSync: (key: string) => unknown;
|
|
11
|
+
saveAsync: (key: string, state: unknown) => void;
|
|
12
|
+
saveSync?: (key: string, state: unknown) => void;
|
|
13
|
+
};
|
|
39
14
|
quotaView?: ProviderQuotaView;
|
|
40
15
|
});
|
|
16
|
+
get antigravitySessionAliasStore(): Map<string, string>;
|
|
17
|
+
get routingInstructionState(): Map<string, unknown>;
|
|
18
|
+
get providerRegistry(): unknown;
|
|
19
|
+
initialize(config: VirtualRouterConfig): void;
|
|
41
20
|
updateDeps(deps: {
|
|
42
21
|
healthStore?: VirtualRouterHealthStore | null;
|
|
43
|
-
routingStateStore?:
|
|
22
|
+
routingStateStore?: {
|
|
23
|
+
loadSync: (key: string) => unknown;
|
|
24
|
+
saveAsync: (key: string, state: unknown) => void;
|
|
25
|
+
saveSync?: (key: string, state: unknown) => void;
|
|
26
|
+
} | null;
|
|
44
27
|
quotaView?: ProviderQuotaView | null;
|
|
45
28
|
}): void;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
29
|
+
updateVirtualRouterConfig(config: VirtualRouterConfig): void;
|
|
30
|
+
markProviderCooldown(providerKey: string, cooldownMs: number | undefined): void;
|
|
31
|
+
clearProviderCooldown(providerKey: string): void;
|
|
49
32
|
route(request: StandardizedRequest | ProcessedRequest, metadata: RouterMetadataInput): {
|
|
50
33
|
target: TargetMetadata;
|
|
51
34
|
decision: RoutingDecision;
|
|
@@ -56,71 +39,5 @@ export declare class VirtualRouterEngine {
|
|
|
56
39
|
handleProviderFailure(event: ProviderFailureEvent): void;
|
|
57
40
|
handleProviderError(event: ProviderErrorEvent): void;
|
|
58
41
|
handleProviderSuccess(event: ProviderSuccessEvent): void;
|
|
59
|
-
getStatus():
|
|
60
|
-
routes: Record<string, {
|
|
61
|
-
providers: string[];
|
|
62
|
-
hits: number;
|
|
63
|
-
lastUsedProvider?: string;
|
|
64
|
-
lastHit?: {
|
|
65
|
-
timestampMs: number;
|
|
66
|
-
reason?: string;
|
|
67
|
-
requestTokens?: number;
|
|
68
|
-
selectionPenalty?: number;
|
|
69
|
-
stopMessageActive: boolean;
|
|
70
|
-
stopMessageMode?: "on" | "off" | "auto";
|
|
71
|
-
stopMessageRemaining?: number;
|
|
72
|
-
};
|
|
73
|
-
}>;
|
|
74
|
-
health: import("./types.js").ProviderHealthState[];
|
|
75
|
-
};
|
|
76
|
-
/**
|
|
77
|
-
* 将分类器产生的逻辑路由名直接归一化为配置中的路由键。
|
|
78
|
-
* 不再维护 "websearch" 之类的别名,调用方应显式使用 "web_search" 或 "search" 等实际路由名。
|
|
79
|
-
*/
|
|
80
|
-
private normalizeRouteAlias;
|
|
81
|
-
private validateConfig;
|
|
82
|
-
private selectProvider;
|
|
83
|
-
private resolveSelectionPenalty;
|
|
84
|
-
private providerHealthConfig;
|
|
85
|
-
private resolveStickyKey;
|
|
86
|
-
private resolveSessionScope;
|
|
87
|
-
private resolveInstructionProcessModeForSelection;
|
|
88
|
-
private resolveInstructionTarget;
|
|
89
|
-
private filterCandidatesByRoutingState;
|
|
90
|
-
private selectFromCandidates;
|
|
91
|
-
/**
|
|
92
|
-
* 在已有候选路由集合上,筛选出真正挂载了 sticky 池内 providerKey 的路由,
|
|
93
|
-
* 并按 ROUTE_PRIORITY 进行排序;同时显式排除 tools 路由,保证一旦进入
|
|
94
|
-
* sticky 模式,就不会再命中独立的 tools 池(例如 glm/qwen 工具模型)。
|
|
95
|
-
* 若候选集合中完全没有挂载 sticky key 的路由,则尝试在 default 路由上兜底。
|
|
96
|
-
*/
|
|
97
|
-
private buildStickyRouteCandidatesFromFiltered;
|
|
98
|
-
/**
|
|
99
|
-
* 在 sticky 模式下,仅在 sticky 池内选择 Provider:
|
|
100
|
-
* - stickyKeySet 表示已经解析并通过健康检查的 providerKey 集合;
|
|
101
|
-
* - 不再依赖 routing[*].targets 中是否挂载这些 key,避免「未初始化路由池」导致 sticky 池为空;
|
|
102
|
-
* - 仍然尊重 allowed/disabledProviders、disabledKeys、disabledModels 以及上下文长度。
|
|
103
|
-
*/
|
|
104
|
-
private selectFromStickyPool;
|
|
105
|
-
private extractExcludedProviderKeySet;
|
|
106
|
-
private buildRouteCandidates;
|
|
107
|
-
private reorderForInlineVision;
|
|
108
|
-
private reorderForPreferredModel;
|
|
109
|
-
private routeSupportsModel;
|
|
110
|
-
private routeSupportsInlineVision;
|
|
111
|
-
private sortByPriority;
|
|
112
|
-
private routeWeight;
|
|
113
|
-
private routeHasForceFlag;
|
|
114
|
-
private routeHasTargets;
|
|
115
|
-
private hasPrimaryPool;
|
|
116
|
-
private sortRoutePools;
|
|
117
|
-
private flattenPoolTargets;
|
|
118
|
-
private markProviderCooldown;
|
|
119
|
-
private clearProviderCooldown;
|
|
120
|
-
private isProviderCoolingDown;
|
|
121
|
-
private getProviderCooldownRemainingMs;
|
|
122
|
-
private restoreHealthFromStore;
|
|
123
|
-
private buildHealthSnapshot;
|
|
124
|
-
private persistHealthSnapshot;
|
|
42
|
+
getStatus(): RoutingStatusSnapshot;
|
|
125
43
|
}
|
|
126
|
-
export {};
|