@jsonstudio/llms 0.6.473 → 0.6.567
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/claude-thinking-tools.d.ts +15 -0
- package/dist/conversion/compat/actions/claude-thinking-tools.js +72 -0
- package/dist/conversion/compat/profiles/chat-gemini.json +15 -14
- package/dist/conversion/compat/profiles/chat-glm.json +194 -194
- package/dist/conversion/compat/profiles/chat-iflow.json +199 -199
- package/dist/conversion/compat/profiles/chat-lmstudio.json +43 -43
- package/dist/conversion/compat/profiles/chat-qwen.json +20 -20
- package/dist/conversion/compat/profiles/responses-c4m.json +42 -42
- package/dist/conversion/compat/profiles/responses-output2choices-test.json +12 -0
- package/dist/conversion/hub/pipeline/compat/compat-pipeline-executor.js +6 -0
- package/dist/conversion/hub/pipeline/compat/compat-types.d.ts +2 -0
- package/dist/conversion/hub/pipeline/hub-pipeline.js +15 -0
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/index.js +15 -0
- package/dist/conversion/hub/process/chat-process.js +44 -17
- package/dist/conversion/hub/semantic-mappers/anthropic-mapper.js +8 -0
- package/dist/conversion/hub/semantic-mappers/gemini-mapper.js +13 -8
- package/dist/conversion/hub/tool-session-compat.d.ts +26 -0
- package/dist/conversion/hub/tool-session-compat.js +299 -0
- package/dist/conversion/responses/responses-openai-bridge.d.ts +0 -1
- package/dist/conversion/responses/responses-openai-bridge.js +0 -71
- package/dist/conversion/shared/gemini-tool-utils.js +8 -0
- package/dist/conversion/shared/responses-output-builder.js +6 -68
- package/dist/conversion/shared/tool-governor.js +75 -4
- package/dist/conversion/shared/tool-mapping.js +14 -8
- package/dist/filters/special/request-toolcalls-stringify.js +5 -55
- package/dist/filters/special/request-tools-normalize.js +0 -19
- package/dist/guidance/index.js +25 -9
- package/dist/router/virtual-router/engine-health.d.ts +11 -0
- package/dist/router/virtual-router/engine-health.js +210 -0
- package/dist/router/virtual-router/engine-logging.d.ts +19 -0
- package/dist/router/virtual-router/engine-logging.js +165 -0
- package/dist/router/virtual-router/engine-selection.d.ts +32 -0
- package/dist/router/virtual-router/engine-selection.js +649 -0
- package/dist/router/virtual-router/engine.d.ts +4 -13
- package/dist/router/virtual-router/engine.js +64 -535
- package/dist/router/virtual-router/message-utils.js +22 -0
- package/dist/router/virtual-router/routing-instructions.d.ts +6 -1
- package/dist/router/virtual-router/routing-instructions.js +119 -3
- package/dist/servertool/handlers/gemini-empty-reply-continue.d.ts +1 -0
- package/dist/servertool/handlers/gemini-empty-reply-continue.js +120 -0
- package/dist/servertool/handlers/stop-message-auto.d.ts +1 -0
- package/dist/servertool/handlers/stop-message-auto.js +147 -0
- package/dist/servertool/handlers/vision.js +105 -7
- package/dist/servertool/server-side-tools.d.ts +2 -0
- package/dist/servertool/server-side-tools.js +2 -0
- package/dist/tools/tool-registry.js +195 -4
- package/package.json +1 -1
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { DEFAULT_MODEL_CONTEXT_TOKENS, DEFAULT_ROUTE } from './types.js';
|
|
2
|
+
export function formatStickyScope(scope) {
|
|
3
|
+
if (!scope || scope.trim().length === 0) {
|
|
4
|
+
return undefined;
|
|
5
|
+
}
|
|
6
|
+
const normalized = scope.trim();
|
|
7
|
+
const maxLength = 20;
|
|
8
|
+
if (normalized.length <= maxLength) {
|
|
9
|
+
return normalized;
|
|
10
|
+
}
|
|
11
|
+
const delimiterIndex = normalized.indexOf(':');
|
|
12
|
+
const prefix = delimiterIndex > 0 ? normalized.slice(0, delimiterIndex + 1) : '';
|
|
13
|
+
const body = delimiterIndex > 0 ? normalized.slice(delimiterIndex + 1) : normalized;
|
|
14
|
+
if (body.length <= 8) {
|
|
15
|
+
return `${prefix}${body}`;
|
|
16
|
+
}
|
|
17
|
+
return `${prefix}${body.slice(0, 4)}…${body.slice(-4)}`;
|
|
18
|
+
}
|
|
19
|
+
export function parseProviderKey(providerKey) {
|
|
20
|
+
const trimmed = typeof providerKey === 'string' ? providerKey.trim() : '';
|
|
21
|
+
if (!trimmed) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const parts = trimmed.split('.');
|
|
25
|
+
if (parts.length < 2) {
|
|
26
|
+
return { providerId: trimmed };
|
|
27
|
+
}
|
|
28
|
+
if (parts.length === 2) {
|
|
29
|
+
return { providerId: parts[0], modelId: parts[1] };
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
providerId: parts[0],
|
|
33
|
+
keyAlias: parts[1],
|
|
34
|
+
modelId: parts.slice(2).join('.')
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export function describeTargetProvider(providerKey, fallbackModelId) {
|
|
38
|
+
const parsed = parseProviderKey(providerKey);
|
|
39
|
+
if (!parsed) {
|
|
40
|
+
return { providerLabel: providerKey, resolvedModel: fallbackModelId };
|
|
41
|
+
}
|
|
42
|
+
const aliasLabel = parsed.keyAlias ? `${parsed.providerId}[${parsed.keyAlias}]` : parsed.providerId;
|
|
43
|
+
const resolvedModel = parsed.modelId || fallbackModelId;
|
|
44
|
+
return { providerLabel: aliasLabel, resolvedModel };
|
|
45
|
+
}
|
|
46
|
+
function resolveRouteColor(routeName) {
|
|
47
|
+
const map = {
|
|
48
|
+
tools: '\x1b[38;5;214m',
|
|
49
|
+
thinking: '\x1b[34m',
|
|
50
|
+
coding: '\x1b[35m',
|
|
51
|
+
longcontext: '\x1b[38;5;141m',
|
|
52
|
+
web_search: '\x1b[32m',
|
|
53
|
+
search: '\x1b[38;5;34m',
|
|
54
|
+
vision: '\x1b[38;5;207m',
|
|
55
|
+
background: '\x1b[90m'
|
|
56
|
+
};
|
|
57
|
+
return map[routeName] ?? '\x1b[36m';
|
|
58
|
+
}
|
|
59
|
+
function describeContextUsage(providerKey, estimatedTokens, deps) {
|
|
60
|
+
if (typeof estimatedTokens !== 'number' || !Number.isFinite(estimatedTokens) || estimatedTokens <= 0) {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
let limit = DEFAULT_MODEL_CONTEXT_TOKENS;
|
|
64
|
+
try {
|
|
65
|
+
const profile = deps.providerRegistry.get(providerKey);
|
|
66
|
+
if (profile?.maxContextTokens && Number.isFinite(profile.maxContextTokens)) {
|
|
67
|
+
limit = profile.maxContextTokens;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
limit = DEFAULT_MODEL_CONTEXT_TOKENS;
|
|
72
|
+
}
|
|
73
|
+
if (!limit || limit <= 0) {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
const ratio = estimatedTokens / limit;
|
|
77
|
+
const threshold = deps.contextRouting?.warnRatio ?? 0.9;
|
|
78
|
+
if (ratio < threshold) {
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
return `${ratio.toFixed(2)}/${Math.round(limit)}`;
|
|
82
|
+
}
|
|
83
|
+
function decorateWithDetail(baseLabel, primaryReason, detail) {
|
|
84
|
+
const normalizedDetail = detail && detail.trim();
|
|
85
|
+
if (!normalizedDetail) {
|
|
86
|
+
return primaryReason || baseLabel;
|
|
87
|
+
}
|
|
88
|
+
if (primaryReason) {
|
|
89
|
+
return `${primaryReason}(${normalizedDetail})`;
|
|
90
|
+
}
|
|
91
|
+
return `${baseLabel}(${normalizedDetail})`;
|
|
92
|
+
}
|
|
93
|
+
export function buildHitReason(routeUsed, providerKey, classification, features, mode, deps) {
|
|
94
|
+
const reasoning = classification.reasoning || '';
|
|
95
|
+
let primary = reasoning.split('|')[0] || '';
|
|
96
|
+
const commandDetail = features.lastAssistantToolLabel;
|
|
97
|
+
const isStickyMode = mode === 'sticky';
|
|
98
|
+
if (isStickyMode &&
|
|
99
|
+
(routeUsed === 'tools' || routeUsed === 'thinking' || routeUsed === 'coding')) {
|
|
100
|
+
primary = '';
|
|
101
|
+
}
|
|
102
|
+
const base = (() => {
|
|
103
|
+
if (routeUsed === 'tools') {
|
|
104
|
+
const label = isStickyMode ? 'sticky' : 'tools';
|
|
105
|
+
return decorateWithDetail(primary || label, primary, commandDetail);
|
|
106
|
+
}
|
|
107
|
+
if (routeUsed === 'thinking') {
|
|
108
|
+
const label = isStickyMode ? 'sticky' : 'thinking';
|
|
109
|
+
return decorateWithDetail(primary || label, primary, commandDetail);
|
|
110
|
+
}
|
|
111
|
+
if (routeUsed === 'coding') {
|
|
112
|
+
const label = isStickyMode ? 'sticky' : 'coding';
|
|
113
|
+
return decorateWithDetail(primary || label, primary, commandDetail);
|
|
114
|
+
}
|
|
115
|
+
if (routeUsed === 'web_search' || routeUsed === 'search') {
|
|
116
|
+
return decorateWithDetail(primary || routeUsed, primary, commandDetail);
|
|
117
|
+
}
|
|
118
|
+
if (routeUsed === DEFAULT_ROUTE && classification.fallback) {
|
|
119
|
+
if (isStickyMode) {
|
|
120
|
+
return primary || 'sticky:default';
|
|
121
|
+
}
|
|
122
|
+
return primary || 'fallback:default';
|
|
123
|
+
}
|
|
124
|
+
if (primary) {
|
|
125
|
+
return primary;
|
|
126
|
+
}
|
|
127
|
+
return routeUsed ? `route:${routeUsed}` : 'route:unknown';
|
|
128
|
+
})();
|
|
129
|
+
const contextDetail = describeContextUsage(providerKey, features.estimatedTokens, deps);
|
|
130
|
+
if (contextDetail) {
|
|
131
|
+
return `${base}|context:${contextDetail}`;
|
|
132
|
+
}
|
|
133
|
+
return base;
|
|
134
|
+
}
|
|
135
|
+
export function formatVirtualRouterHit(routeName, poolId, providerKey, modelId, hitReason, stickyScope) {
|
|
136
|
+
try {
|
|
137
|
+
const now = new Date();
|
|
138
|
+
const hours = String(now.getHours()).padStart(2, '0');
|
|
139
|
+
const minutes = String(now.getMinutes()).padStart(2, '0');
|
|
140
|
+
const seconds = String(now.getSeconds()).padStart(2, '0');
|
|
141
|
+
const timestamp = `${hours}:${minutes}:${seconds}`;
|
|
142
|
+
const prefixColor = '\x1b[38;5;208m';
|
|
143
|
+
const reset = '\x1b[0m';
|
|
144
|
+
const timeColor = '\x1b[90m';
|
|
145
|
+
const stickyColor = '\x1b[33m';
|
|
146
|
+
const routeColor = resolveRouteColor(routeName);
|
|
147
|
+
const prefix = `${prefixColor}[virtual-router-hit]${reset}`;
|
|
148
|
+
const timeLabel = `${timeColor}${timestamp}${reset}`;
|
|
149
|
+
const { providerLabel, resolvedModel } = describeTargetProvider(providerKey, modelId);
|
|
150
|
+
const routeLabel = poolId ? `${routeName}/${poolId}` : routeName;
|
|
151
|
+
const targetLabel = `${routeLabel} -> ${providerLabel}${resolvedModel ? '.' + resolvedModel : ''}`;
|
|
152
|
+
const stickyText = formatStickyScope(stickyScope);
|
|
153
|
+
const stickyLabel = stickyText ? ` ${stickyColor}[sticky:${stickyText}]${reset}` : '';
|
|
154
|
+
const reasonLabel = hitReason ? ` reason=${hitReason}` : '';
|
|
155
|
+
return `${prefix} ${timeLabel} ${routeColor}${targetLabel}${stickyLabel}${reasonLabel}${reset}`;
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
const now = new Date();
|
|
159
|
+
const timestamp = now.toLocaleTimeString('zh-CN', { hour12: false });
|
|
160
|
+
const routeLabel = poolId ? `${routeName}/${poolId}` : routeName;
|
|
161
|
+
const stickyText = formatStickyScope(stickyScope);
|
|
162
|
+
const stickyLabel = stickyText ? ` [sticky:${stickyText}]` : '';
|
|
163
|
+
return `[virtual-router-hit] ${timestamp} ${routeLabel} -> ${providerKey}${modelId ? '.' + modelId : ''}${stickyLabel}${hitReason ? ` reason=${hitReason}` : ''}`;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ClassificationResult, RoutePoolTier, RouterMetadataInput, RoutingFeatures } from './types.js';
|
|
2
|
+
import type { RoutingInstructionState } from './routing-instructions.js';
|
|
3
|
+
import type { ContextAdvisor } from './context-advisor.js';
|
|
4
|
+
import type { RouteLoadBalancer } from './load-balancer.js';
|
|
5
|
+
import type { ProviderHealthManager } from './health-manager.js';
|
|
6
|
+
import type { ProviderRegistry } from './provider-registry.js';
|
|
7
|
+
type SelectionDeps = {
|
|
8
|
+
routing: Record<string, RoutePoolTier[]>;
|
|
9
|
+
providerRegistry: ProviderRegistry;
|
|
10
|
+
healthManager: ProviderHealthManager;
|
|
11
|
+
contextAdvisor: ContextAdvisor;
|
|
12
|
+
loadBalancer: RouteLoadBalancer;
|
|
13
|
+
isProviderCoolingDown: (providerKey: string) => boolean;
|
|
14
|
+
resolveStickyKey: (metadata: RouterMetadataInput) => string | undefined;
|
|
15
|
+
};
|
|
16
|
+
export declare function selectProviderImpl(requestedRoute: string, metadata: RouterMetadataInput, classification: ClassificationResult, features: RoutingFeatures, activeState: RoutingInstructionState, deps: SelectionDeps, options?: {
|
|
17
|
+
routingState?: RoutingInstructionState;
|
|
18
|
+
}): {
|
|
19
|
+
providerKey: string;
|
|
20
|
+
routeUsed: string;
|
|
21
|
+
pool: string[];
|
|
22
|
+
poolId?: string;
|
|
23
|
+
};
|
|
24
|
+
export declare function selectFromStickyPool(stickyKeySet: Set<string>, metadata: RouterMetadataInput, features: RoutingFeatures, state: RoutingInstructionState, deps: SelectionDeps, options: {
|
|
25
|
+
allowAliasRotation?: boolean;
|
|
26
|
+
}): {
|
|
27
|
+
providerKey: string;
|
|
28
|
+
routeUsed: string;
|
|
29
|
+
pool: string[];
|
|
30
|
+
poolId?: string;
|
|
31
|
+
} | null;
|
|
32
|
+
export {};
|