@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
|
@@ -1,655 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import { applyPreCommandInstructionToState, clearPreCommandState } from './routing-pre-command-actions.js';
|
|
6
|
-
import { deserializeStopMessageState, serializeStopMessageState } from './routing-stop-message-state-codec.js';
|
|
7
|
-
import { deserializePreCommandState, serializePreCommandState } from './routing-pre-command-state-codec.js';
|
|
8
|
-
const ROUTING_INSTRUCTION_MARKER_PATTERN = /<\*\*[\s\S]*?\*\*>/;
|
|
9
|
-
const ROUTING_INSTRUCTION_MARKER_GLOBAL_PATTERN = /<\*\*[\s\S]*?\*\*>/g;
|
|
10
|
-
export function parseRoutingInstructions(messages) {
|
|
11
|
-
const instructions = [];
|
|
12
|
-
// 只解析“当前最新一条消息”中的 marker,避免历史 user marker 在后续轮次被重复回放。
|
|
13
|
-
const latestMessage = messages.length > 0 ? messages[messages.length - 1] : undefined;
|
|
14
|
-
if (!latestMessage || latestMessage.role !== 'user') {
|
|
15
|
-
return instructions;
|
|
16
|
-
}
|
|
17
|
-
const content = extractMessageText(latestMessage);
|
|
18
|
-
if (!content) {
|
|
19
|
-
return instructions;
|
|
20
|
-
}
|
|
21
|
-
const sanitized = stripCodeSegments(content);
|
|
22
|
-
if (!sanitized || !ROUTING_INSTRUCTION_MARKER_PATTERN.test(sanitized)) {
|
|
23
|
-
return instructions;
|
|
24
|
-
}
|
|
25
|
-
const regex = /<\*\*([\s\S]*?)\*\*>/g;
|
|
26
|
-
let match;
|
|
27
|
-
while ((match = regex.exec(sanitized)) !== null) {
|
|
28
|
-
const instruction = match[1].trim();
|
|
29
|
-
if (!instruction) {
|
|
30
|
-
continue;
|
|
31
|
-
}
|
|
32
|
-
const segments = expandInstructionSegments(instruction);
|
|
33
|
-
for (const segment of segments) {
|
|
34
|
-
const parsed = parseSingleInstruction(segment);
|
|
35
|
-
if (parsed) {
|
|
36
|
-
instructions.push(parsed);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
return normalizeStopMessageInstructionPrecedence(instructions);
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* 解析并预处理路由指令,优先处理 clear 指令,确保新指令能够覆盖旧状态。
|
|
44
|
-
* 返回清理后的指令列表,移除冗余的 stopMessageSet 指令。
|
|
45
|
-
*/
|
|
46
|
-
export function parseAndPreprocessRoutingInstructions(messages) {
|
|
47
|
-
const rawInstructions = parseRoutingInstructions(messages);
|
|
48
|
-
if (rawInstructions.length === 0) {
|
|
49
|
-
return [];
|
|
50
|
-
}
|
|
51
|
-
// 检查是否有 clear 指令
|
|
52
|
-
const hasClear = rawInstructions.some(inst => inst.type === 'clear');
|
|
53
|
-
if (!hasClear) {
|
|
54
|
-
return rawInstructions;
|
|
55
|
-
}
|
|
56
|
-
// 如果有 clear 指令,clear 之后的指令才有效,clear 之前的指令被清除
|
|
57
|
-
const clearIndex = rawInstructions.findIndex(inst => inst.type === 'clear');
|
|
58
|
-
const effectiveInstructions = rawInstructions.slice(clearIndex + 1);
|
|
59
|
-
// 移除 clear 后冗余的 stopMessageSet 指令(如果与原指令相同)
|
|
60
|
-
// 这里的逻辑会在 applyRoutingInstructions 中处理,
|
|
61
|
-
// 所以我们只需要返回 clear 之后的指令即可
|
|
62
|
-
return effectiveInstructions;
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* 提取 clear 指令(如果存在)。用于在路由选择前优先执行清理操作。
|
|
66
|
-
* @returns 是否存在 clear 指令
|
|
67
|
-
*/
|
|
68
|
-
export function extractClearInstruction(messages) {
|
|
69
|
-
const instructions = parseRoutingInstructions(messages);
|
|
70
|
-
return instructions.some((inst) => inst.type === 'clear');
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* 提取 stopMessageClear 指令(如果存在)。
|
|
74
|
-
* @returns 是否存在 stopMessageClear 指令
|
|
75
|
-
*/
|
|
76
|
-
export function extractStopMessageClearInstruction(messages) {
|
|
77
|
-
const instructions = parseRoutingInstructions(messages);
|
|
78
|
-
return instructions.some((inst) => inst.type === 'stopMessageClear');
|
|
79
|
-
}
|
|
80
|
-
function expandInstructionSegments(instruction) {
|
|
81
|
-
const trimmed = instruction.trim();
|
|
82
|
-
if (!trimmed) {
|
|
83
|
-
return [];
|
|
84
|
-
}
|
|
85
|
-
const normalizedLeading = normalizeInstructionLeading(trimmed);
|
|
86
|
-
// stopMessage 指令需要整体解析,不能按逗号拆分,否则类似
|
|
87
|
-
// "<**stopMessage:\"继续\",3**>" 会被错误拆成 ["stopMessage:\"继续\"", "3"]。
|
|
88
|
-
if (/^(?:"|')?stopMessage(?:"|')?\s*[:,]/i.test(normalizedLeading)) {
|
|
89
|
-
return [normalizeStopMessageCommandPrefix(normalizedLeading)];
|
|
90
|
-
}
|
|
91
|
-
if (/^precommand(?:\s*:|$)/i.test(normalizedLeading)) {
|
|
92
|
-
return [normalizedLeading];
|
|
93
|
-
}
|
|
94
|
-
const prefix = trimmed[0];
|
|
95
|
-
if (prefix === '!' || prefix === '#' || prefix === '@') {
|
|
96
|
-
const tokens = splitInstructionTargets(trimmed.substring(1));
|
|
97
|
-
return tokens
|
|
98
|
-
.map((token) => token.replace(/^[!#@]+/, '').trim())
|
|
99
|
-
.filter((token) => token.length > 0)
|
|
100
|
-
.map((token) => `${prefix}${token}`);
|
|
101
|
-
}
|
|
102
|
-
const splitTokens = splitInstructionTargets(trimmed);
|
|
103
|
-
const recoveredStopMessage = recoverSplitStopMessageInstruction(splitTokens);
|
|
104
|
-
if (recoveredStopMessage) {
|
|
105
|
-
return [recoveredStopMessage];
|
|
106
|
-
}
|
|
107
|
-
return splitTokens;
|
|
108
|
-
}
|
|
109
|
-
function splitInstructionTargets(content) {
|
|
110
|
-
return content
|
|
111
|
-
.split(',')
|
|
112
|
-
.map((segment) => segment.trim())
|
|
113
|
-
.filter((segment) => segment.length > 0);
|
|
114
|
-
}
|
|
115
|
-
function normalizeInstructionLeading(content) {
|
|
116
|
-
// Remove common zero-width prefixes that may be injected by client/editor copies.
|
|
117
|
-
return content.replace(/^[\u200B-\u200D\u2060\uFEFF]+/, '').trimStart();
|
|
118
|
-
}
|
|
119
|
-
function normalizeStopMessageCommandPrefix(content) {
|
|
120
|
-
const normalized = normalizeInstructionLeading(content);
|
|
121
|
-
return normalized.replace(/^(?:"|')?stopMessage(?:"|')?\s*([:,])/i, 'stopMessage$1');
|
|
122
|
-
}
|
|
123
|
-
function normalizeSplitStopMessageHeadToken(token) {
|
|
124
|
-
return normalizeInstructionLeading(token)
|
|
125
|
-
.replace(/^["']+|["']+$/g, '')
|
|
126
|
-
.trim();
|
|
127
|
-
}
|
|
128
|
-
function recoverSplitStopMessageInstruction(tokens) {
|
|
129
|
-
if (!Array.isArray(tokens) || tokens.length < 2) {
|
|
130
|
-
return null;
|
|
131
|
-
}
|
|
132
|
-
const head = normalizeSplitStopMessageHeadToken(tokens[0]);
|
|
133
|
-
if (!/^stopmessage$/i.test(head)) {
|
|
134
|
-
return null;
|
|
135
|
-
}
|
|
136
|
-
const tail = tokens.slice(1).join(',').trim();
|
|
137
|
-
if (!tail) {
|
|
138
|
-
return null;
|
|
139
|
-
}
|
|
140
|
-
return `stopMessage:${tail}`;
|
|
141
|
-
}
|
|
142
|
-
function splitTargetAndProcessMode(rawTarget) {
|
|
143
|
-
const trimmed = typeof rawTarget === 'string' ? rawTarget.trim() : '';
|
|
144
|
-
if (!trimmed) {
|
|
145
|
-
return { target: '' };
|
|
146
|
-
}
|
|
147
|
-
const separatorIndex = trimmed.lastIndexOf(':');
|
|
148
|
-
if (separatorIndex <= 0 || separatorIndex === trimmed.length - 1) {
|
|
149
|
-
return { target: trimmed };
|
|
150
|
-
}
|
|
151
|
-
const target = trimmed.slice(0, separatorIndex).trim();
|
|
152
|
-
const modeToken = trimmed.slice(separatorIndex + 1).trim().toLowerCase();
|
|
153
|
-
if (!target) {
|
|
154
|
-
return { target: trimmed };
|
|
155
|
-
}
|
|
156
|
-
if (modeToken === 'passthrough') {
|
|
157
|
-
return { target, processMode: 'passthrough' };
|
|
158
|
-
}
|
|
159
|
-
if (modeToken === 'chat') {
|
|
160
|
-
return { target, processMode: 'chat' };
|
|
161
|
-
}
|
|
162
|
-
return { target };
|
|
163
|
-
}
|
|
164
|
-
function parseNamedTargetInstruction(instruction, prefix) {
|
|
165
|
-
const re = new RegExp('^' + prefix + '\\s*:', 'i');
|
|
166
|
-
if (!re.test(instruction)) {
|
|
167
|
-
return null;
|
|
168
|
-
}
|
|
169
|
-
const body = instruction.slice(instruction.indexOf(':') + 1).trim();
|
|
170
|
-
if (!body) {
|
|
171
|
-
return null;
|
|
172
|
-
}
|
|
173
|
-
const { target, processMode } = splitTargetAndProcessMode(body);
|
|
174
|
-
if (!target) {
|
|
175
|
-
return null;
|
|
176
|
-
}
|
|
177
|
-
const parsed = parseTarget(target);
|
|
178
|
-
if (!parsed) {
|
|
179
|
-
return null;
|
|
180
|
-
}
|
|
181
|
-
const normalized = normalizeStickyOrForceTarget(parsed);
|
|
182
|
-
return { type: prefix, ...normalized, ...(processMode ? { processMode } : {}) };
|
|
183
|
-
}
|
|
184
|
-
function parseSingleInstruction(instruction) {
|
|
185
|
-
if (/^clear$/i.test(instruction)) {
|
|
186
|
-
return { type: 'clear' };
|
|
187
|
-
}
|
|
188
|
-
const preCommandInstruction = parsePreCommandInstruction(instruction);
|
|
189
|
-
if (preCommandInstruction) {
|
|
190
|
-
return preCommandInstruction;
|
|
191
|
-
}
|
|
192
|
-
const stopMessageInstruction = parseStopMessageInstruction(instruction);
|
|
193
|
-
if (stopMessageInstruction) {
|
|
194
|
-
return stopMessageInstruction;
|
|
195
|
-
}
|
|
196
|
-
const stickyInstruction = parseNamedTargetInstruction(instruction, 'sticky');
|
|
197
|
-
if (stickyInstruction) {
|
|
198
|
-
return stickyInstruction;
|
|
199
|
-
}
|
|
200
|
-
const forceInstruction = parseNamedTargetInstruction(instruction, 'force');
|
|
201
|
-
if (forceInstruction) {
|
|
202
|
-
return forceInstruction;
|
|
203
|
-
}
|
|
204
|
-
const preferInstruction = parseNamedTargetInstruction(instruction, 'prefer');
|
|
205
|
-
if (preferInstruction) {
|
|
206
|
-
return preferInstruction;
|
|
207
|
-
}
|
|
208
|
-
if (instruction.startsWith('!')) {
|
|
209
|
-
const rawTarget = instruction.substring(1).trim();
|
|
210
|
-
const { target, processMode } = splitTargetAndProcessMode(rawTarget);
|
|
211
|
-
if (!target) {
|
|
212
|
-
return null;
|
|
213
|
-
}
|
|
214
|
-
const parsed = parseTarget(target);
|
|
215
|
-
if (!parsed) {
|
|
216
|
-
return null;
|
|
217
|
-
}
|
|
218
|
-
// 约定:
|
|
219
|
-
// - "!providerA,providerB":允许列表(whitelist),用于快速限制可用 provider 集合;
|
|
220
|
-
// - "!provider.model" / "!provider[alias].model" / "!provider.2":prefer 语义;
|
|
221
|
-
// model 可用时只命中该 model(忽略路由),不可用则自动清除并回退到正常路由命中。
|
|
222
|
-
//
|
|
223
|
-
// 这样可以在不破坏既有 "!glm,openai" 语义的前提下,引入基于模型的优先命中行为。
|
|
224
|
-
if (!target.includes('.')) {
|
|
225
|
-
if (parsed.provider) {
|
|
226
|
-
return { type: 'allow', provider: parsed.provider, pathLength: parsed.pathLength };
|
|
227
|
-
}
|
|
228
|
-
return null;
|
|
229
|
-
}
|
|
230
|
-
const normalized = normalizeStickyOrForceTarget(parsed);
|
|
231
|
-
return { type: 'prefer', ...normalized, ...(processMode ? { processMode } : {}) };
|
|
232
|
-
}
|
|
233
|
-
else if (instruction.startsWith('#')) {
|
|
234
|
-
const target = instruction.substring(1).trim();
|
|
235
|
-
const parsed = parseTarget(target);
|
|
236
|
-
if (parsed) {
|
|
237
|
-
return { type: 'disable', ...parsed };
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
else if (instruction.startsWith('@')) {
|
|
241
|
-
const target = instruction.substring(1).trim();
|
|
242
|
-
const parsed = parseTarget(target);
|
|
243
|
-
if (parsed) {
|
|
244
|
-
return { type: 'enable', ...parsed };
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
else if (isValidProviderModel(instruction)) {
|
|
248
|
-
const parsed = parseTarget(instruction);
|
|
249
|
-
if (parsed) {
|
|
250
|
-
const normalized = normalizeStickyOrForceTarget(parsed);
|
|
251
|
-
return { type: 'force', ...normalized };
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
else if (isValidIdentifier(instruction)) {
|
|
255
|
-
// 仅 provider 标识(无 .)时,视为 provider 级白名单,等价于 "<**!provider**>"。
|
|
256
|
-
// 这样可以用 "<**antigravity**>" 快速激活当前 routing 中所有 antigravity 相关池子,
|
|
257
|
-
// 并保证路由仅命中该 provider 的所有模型/key。
|
|
258
|
-
return {
|
|
259
|
-
type: 'allow',
|
|
260
|
-
provider: instruction,
|
|
261
|
-
pathLength: 1
|
|
262
|
-
};
|
|
263
|
-
}
|
|
264
|
-
return null;
|
|
265
|
-
}
|
|
266
|
-
function normalizeStopMessageInstructionPrecedence(instructions) {
|
|
267
|
-
if (!Array.isArray(instructions) || instructions.length <= 1) {
|
|
268
|
-
return instructions;
|
|
269
|
-
}
|
|
270
|
-
const isStopDirective = (inst) => inst.type === 'stopMessageSet' || inst.type === 'stopMessageMode' || inst.type === 'stopMessageClear';
|
|
271
|
-
const hasGlobalClear = instructions.some((inst) => inst.type === 'clear');
|
|
272
|
-
const hasStopClear = instructions.some((inst) => inst.type === 'stopMessageClear');
|
|
273
|
-
if (hasGlobalClear) {
|
|
274
|
-
const lastGlobalClearIndex = instructions.map((inst) => inst.type).lastIndexOf('clear');
|
|
275
|
-
return lastGlobalClearIndex >= 0 ? [instructions[lastGlobalClearIndex]] : instructions;
|
|
276
|
-
}
|
|
277
|
-
if (hasStopClear) {
|
|
278
|
-
const lastStopClearIndex = instructions.map((inst) => inst.type).lastIndexOf('stopMessageClear');
|
|
279
|
-
return lastStopClearIndex >= 0 ? [instructions[lastStopClearIndex]] : instructions;
|
|
280
|
-
}
|
|
281
|
-
let lastStopIndex = -1;
|
|
282
|
-
for (let idx = instructions.length - 1; idx >= 0; idx -= 1) {
|
|
283
|
-
if (isStopDirective(instructions[idx])) {
|
|
284
|
-
lastStopIndex = idx;
|
|
285
|
-
break;
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
if (lastStopIndex < 0) {
|
|
289
|
-
return instructions;
|
|
290
|
-
}
|
|
291
|
-
return instructions.filter((inst, idx) => !isStopDirective(inst) || idx === lastStopIndex);
|
|
292
|
-
}
|
|
293
|
-
function parseTarget(target) {
|
|
294
|
-
if (!target) {
|
|
295
|
-
return null;
|
|
296
|
-
}
|
|
297
|
-
// Accept "provider[alias].model" (as printed in virtual-router-hit logs) to avoid users
|
|
298
|
-
// needing to translate bracket notation back to dot notation manually.
|
|
299
|
-
// With the alias disambiguated, allow dots in model ids (e.g. gpt-5.2) without ambiguity.
|
|
300
|
-
const bracketMatch = target.match(/^([a-zA-Z0-9_-]+)\[([a-zA-Z0-9_-]*)\](?:\.(.+))?$/);
|
|
301
|
-
if (bracketMatch) {
|
|
302
|
-
const provider = bracketMatch[1];
|
|
303
|
-
const keyAliasRaw = bracketMatch[2];
|
|
304
|
-
const keyAlias = typeof keyAliasRaw === 'string' ? keyAliasRaw.trim() : '';
|
|
305
|
-
const model = typeof bracketMatch[3] === 'string' ? bracketMatch[3].trim() : '';
|
|
306
|
-
if (!provider || !isValidIdentifier(provider)) {
|
|
307
|
-
return null;
|
|
308
|
-
}
|
|
309
|
-
// Allow omitting the alias: "provider[].model" means "provider.model across all aliases".
|
|
310
|
-
// This also enables disambiguating model ids that contain dots, without requiring the user
|
|
311
|
-
// to specify the alias.
|
|
312
|
-
if (!keyAlias) {
|
|
313
|
-
if (!model) {
|
|
314
|
-
return { provider, pathLength: 1 };
|
|
315
|
-
}
|
|
316
|
-
if (!/^[a-zA-Z0-9_.-]+$/.test(model)) {
|
|
317
|
-
return null;
|
|
318
|
-
}
|
|
319
|
-
return { provider, model, pathLength: 2 };
|
|
320
|
-
}
|
|
321
|
-
if (!isValidIdentifier(keyAlias)) {
|
|
322
|
-
return null;
|
|
323
|
-
}
|
|
324
|
-
if (!model) {
|
|
325
|
-
// Treat as explicit alias selection. Use pathLength=3 so engine resolves keyAlias directly.
|
|
326
|
-
return { provider, keyAlias, pathLength: 3 };
|
|
327
|
-
}
|
|
328
|
-
// Model ids may contain dots (e.g. gpt-5.2); allow them here because alias is already explicit.
|
|
329
|
-
if (!/^[a-zA-Z0-9_.-]+$/.test(model)) {
|
|
330
|
-
return null;
|
|
331
|
-
}
|
|
332
|
-
return { provider, keyAlias, model, pathLength: 3 };
|
|
333
|
-
}
|
|
334
|
-
// Dot syntax: align with config parsing used by routing entries.
|
|
335
|
-
// - "provider.modelId" -> modelId may contain dots; it always means model across all aliases.
|
|
336
|
-
// - Key/alias selection must use bracket syntax: "provider[alias]" or "provider[alias].modelId".
|
|
337
|
-
const firstDot = target.indexOf('.');
|
|
338
|
-
if (firstDot < 0) {
|
|
339
|
-
const provider = target.trim();
|
|
340
|
-
if (!provider || !isValidIdentifier(provider)) {
|
|
341
|
-
return null;
|
|
342
|
-
}
|
|
343
|
-
return { provider, pathLength: 1 };
|
|
344
|
-
}
|
|
345
|
-
const provider = target.slice(0, firstDot).trim();
|
|
346
|
-
const remainder = target.slice(firstDot + 1).trim();
|
|
347
|
-
if (!provider || !isValidIdentifier(provider) || !remainder) {
|
|
348
|
-
return null;
|
|
349
|
-
}
|
|
350
|
-
// Support "provider.2" key-index notation (only when remainder is a plain integer).
|
|
351
|
-
if (/^\d+$/.test(remainder)) {
|
|
352
|
-
const keyIndex = Number.parseInt(remainder, 10);
|
|
353
|
-
if (Number.isFinite(keyIndex) && keyIndex > 0) {
|
|
354
|
-
return { provider, keyIndex, pathLength: 2 };
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
// Treat everything after the first dot as the model id, allowing dots.
|
|
358
|
-
if (!/^[a-zA-Z0-9_.-]+$/.test(remainder)) {
|
|
359
|
-
return null;
|
|
360
|
-
}
|
|
361
|
-
return { provider, model: remainder, pathLength: 2 };
|
|
362
|
-
}
|
|
363
|
-
function normalizeStickyOrForceTarget(target) {
|
|
364
|
-
if (target &&
|
|
365
|
-
target.pathLength === 2 &&
|
|
366
|
-
typeof target.model === 'string' &&
|
|
367
|
-
typeof target.keyAlias === 'string' &&
|
|
368
|
-
target.model === target.keyAlias) {
|
|
369
|
-
const clone = { ...target };
|
|
370
|
-
delete clone.keyAlias;
|
|
371
|
-
return clone;
|
|
372
|
-
}
|
|
373
|
-
return target;
|
|
374
|
-
}
|
|
375
|
-
function isValidIdentifier(id) {
|
|
376
|
-
return /^[a-zA-Z0-9_-]+$/.test(id);
|
|
377
|
-
}
|
|
378
|
-
function isValidProviderModel(providerModel) {
|
|
379
|
-
const pattern = /^[a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)+$/;
|
|
380
|
-
return pattern.test(providerModel);
|
|
381
|
-
}
|
|
382
|
-
function stripCodeSegments(text) {
|
|
383
|
-
if (!text) {
|
|
384
|
-
return '';
|
|
385
|
-
}
|
|
386
|
-
// Remove fenced code blocks ```...``` or ~~~...~~~
|
|
387
|
-
let sanitized = text.replace(/```[\s\S]*?```/g, ' ');
|
|
388
|
-
sanitized = sanitized.replace(/~~~[\s\S]*?~~~/g, ' ');
|
|
389
|
-
// Remove inline code `...`
|
|
390
|
-
sanitized = sanitized.replace(/`[^`]*`/g, ' ');
|
|
391
|
-
return sanitized;
|
|
392
|
-
}
|
|
393
|
-
export function applyRoutingInstructions(instructions, currentState) {
|
|
394
|
-
const newState = {
|
|
395
|
-
forcedTarget: currentState.forcedTarget ? { ...currentState.forcedTarget } : undefined,
|
|
396
|
-
stickyTarget: currentState.stickyTarget ? { ...currentState.stickyTarget } : undefined,
|
|
397
|
-
preferTarget: currentState.preferTarget ? { ...currentState.preferTarget } : undefined,
|
|
398
|
-
allowedProviders: new Set(currentState.allowedProviders),
|
|
399
|
-
disabledProviders: new Set(currentState.disabledProviders),
|
|
400
|
-
disabledKeys: new Map(Array.from(currentState.disabledKeys.entries()).map(([k, v]) => [k, new Set(v)])),
|
|
401
|
-
disabledModels: new Map(Array.from(currentState.disabledModels.entries()).map(([k, v]) => [k, new Set(v)])),
|
|
402
|
-
stopMessageSource: currentState.stopMessageSource,
|
|
403
|
-
stopMessageText: currentState.stopMessageText,
|
|
404
|
-
stopMessageMaxRepeats: currentState.stopMessageMaxRepeats,
|
|
405
|
-
stopMessageUsed: currentState.stopMessageUsed,
|
|
406
|
-
stopMessageUpdatedAt: currentState.stopMessageUpdatedAt,
|
|
407
|
-
stopMessageLastUsedAt: currentState.stopMessageLastUsedAt,
|
|
408
|
-
stopMessageStageMode: currentState.stopMessageStageMode,
|
|
409
|
-
stopMessageAiMode: currentState.stopMessageAiMode,
|
|
410
|
-
stopMessageAiSeedPrompt: currentState.stopMessageAiSeedPrompt,
|
|
411
|
-
stopMessageAiHistory: Array.isArray(currentState.stopMessageAiHistory)
|
|
412
|
-
? currentState.stopMessageAiHistory.map((entry) => entry && typeof entry === 'object' && !Array.isArray(entry)
|
|
413
|
-
? { ...entry }
|
|
414
|
-
: {})
|
|
415
|
-
: undefined,
|
|
416
|
-
preCommandSource: currentState.preCommandSource,
|
|
417
|
-
preCommandScriptPath: currentState.preCommandScriptPath,
|
|
418
|
-
preCommandUpdatedAt: currentState.preCommandUpdatedAt
|
|
419
|
-
};
|
|
420
|
-
let allowReset = false;
|
|
421
|
-
let disableReset = false;
|
|
422
|
-
for (const instruction of instructions) {
|
|
423
|
-
switch (instruction.type) {
|
|
424
|
-
case 'force':
|
|
425
|
-
newState.forcedTarget = {
|
|
426
|
-
provider: instruction.provider,
|
|
427
|
-
keyAlias: instruction.keyAlias,
|
|
428
|
-
keyIndex: instruction.keyIndex,
|
|
429
|
-
model: instruction.model,
|
|
430
|
-
pathLength: instruction.pathLength,
|
|
431
|
-
processMode: instruction.processMode
|
|
432
|
-
};
|
|
433
|
-
// 保留 stickyTarget,允许单次 force 覆盖但不清除持久 sticky
|
|
434
|
-
// newState.stickyTarget = undefined;
|
|
435
|
-
break;
|
|
436
|
-
case 'sticky':
|
|
437
|
-
newState.stickyTarget = {
|
|
438
|
-
provider: instruction.provider,
|
|
439
|
-
keyAlias: instruction.keyAlias,
|
|
440
|
-
keyIndex: instruction.keyIndex,
|
|
441
|
-
model: instruction.model,
|
|
442
|
-
pathLength: instruction.pathLength,
|
|
443
|
-
processMode: instruction.processMode
|
|
444
|
-
};
|
|
445
|
-
newState.forcedTarget = undefined;
|
|
446
|
-
break;
|
|
447
|
-
case 'prefer':
|
|
448
|
-
newState.preferTarget = {
|
|
449
|
-
provider: instruction.provider,
|
|
450
|
-
keyAlias: instruction.keyAlias,
|
|
451
|
-
keyIndex: instruction.keyIndex,
|
|
452
|
-
model: instruction.model,
|
|
453
|
-
pathLength: instruction.pathLength,
|
|
454
|
-
processMode: instruction.processMode
|
|
455
|
-
};
|
|
456
|
-
newState.forcedTarget = undefined;
|
|
457
|
-
newState.stickyTarget = undefined;
|
|
458
|
-
break;
|
|
459
|
-
case 'allow':
|
|
460
|
-
if (!allowReset) {
|
|
461
|
-
newState.allowedProviders.clear();
|
|
462
|
-
allowReset = true;
|
|
463
|
-
}
|
|
464
|
-
if (instruction.provider) {
|
|
465
|
-
newState.allowedProviders.add(instruction.provider);
|
|
466
|
-
}
|
|
467
|
-
break;
|
|
468
|
-
case 'disable': {
|
|
469
|
-
if (!disableReset) {
|
|
470
|
-
newState.disabledProviders.clear();
|
|
471
|
-
newState.disabledKeys.clear();
|
|
472
|
-
newState.disabledModels.clear();
|
|
473
|
-
disableReset = true;
|
|
474
|
-
}
|
|
475
|
-
if (instruction.provider) {
|
|
476
|
-
const hasKeySpecifier = instruction.keyAlias || instruction.keyIndex !== undefined;
|
|
477
|
-
const hasModelSpecifier = typeof instruction.model === 'string' && instruction.model.length > 0;
|
|
478
|
-
if (hasKeySpecifier) {
|
|
479
|
-
if (!newState.disabledKeys.has(instruction.provider)) {
|
|
480
|
-
newState.disabledKeys.set(instruction.provider, new Set());
|
|
481
|
-
}
|
|
482
|
-
const keySet = newState.disabledKeys.get(instruction.provider);
|
|
483
|
-
if (instruction.keyAlias) {
|
|
484
|
-
keySet.add(instruction.keyAlias);
|
|
485
|
-
}
|
|
486
|
-
if (instruction.keyIndex !== undefined) {
|
|
487
|
-
keySet.add(instruction.keyIndex);
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
if (hasModelSpecifier) {
|
|
491
|
-
if (!newState.disabledModels.has(instruction.provider)) {
|
|
492
|
-
newState.disabledModels.set(instruction.provider, new Set());
|
|
493
|
-
}
|
|
494
|
-
newState.disabledModels.get(instruction.provider).add(instruction.model);
|
|
495
|
-
}
|
|
496
|
-
if (!hasKeySpecifier && !hasModelSpecifier) {
|
|
497
|
-
newState.disabledProviders.add(instruction.provider);
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
break;
|
|
501
|
-
}
|
|
502
|
-
case 'enable': {
|
|
503
|
-
if (instruction.provider) {
|
|
504
|
-
const hasKeySpecifier = instruction.keyAlias || instruction.keyIndex !== undefined;
|
|
505
|
-
const hasModelSpecifier = typeof instruction.model === 'string' && instruction.model.length > 0;
|
|
506
|
-
if (hasKeySpecifier) {
|
|
507
|
-
const keySet = newState.disabledKeys.get(instruction.provider);
|
|
508
|
-
if (keySet) {
|
|
509
|
-
if (instruction.keyAlias) {
|
|
510
|
-
keySet.delete(instruction.keyAlias);
|
|
511
|
-
}
|
|
512
|
-
if (instruction.keyIndex !== undefined) {
|
|
513
|
-
keySet.delete(instruction.keyIndex);
|
|
514
|
-
}
|
|
515
|
-
if (keySet.size === 0) {
|
|
516
|
-
newState.disabledKeys.delete(instruction.provider);
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
if (hasModelSpecifier) {
|
|
521
|
-
const modelSet = newState.disabledModels.get(instruction.provider);
|
|
522
|
-
if (modelSet) {
|
|
523
|
-
modelSet.delete(instruction.model);
|
|
524
|
-
if (modelSet.size === 0) {
|
|
525
|
-
newState.disabledModels.delete(instruction.provider);
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
if (!hasKeySpecifier && !hasModelSpecifier) {
|
|
530
|
-
newState.disabledProviders.delete(instruction.provider);
|
|
531
|
-
newState.disabledKeys.delete(instruction.provider);
|
|
532
|
-
newState.disabledModels.delete(instruction.provider);
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
break;
|
|
536
|
-
}
|
|
537
|
-
case 'clear':
|
|
538
|
-
newState.forcedTarget = undefined;
|
|
539
|
-
newState.stickyTarget = undefined;
|
|
540
|
-
newState.preferTarget = undefined;
|
|
541
|
-
newState.allowedProviders.clear();
|
|
542
|
-
newState.disabledProviders.clear();
|
|
543
|
-
newState.disabledKeys.clear();
|
|
544
|
-
newState.disabledModels.clear();
|
|
545
|
-
applyStopMessageInstructionToState({ type: 'stopMessageClear' }, newState);
|
|
546
|
-
clearPreCommandState(newState);
|
|
547
|
-
break;
|
|
548
|
-
case 'stopMessageSet':
|
|
549
|
-
case 'stopMessageMode':
|
|
550
|
-
case 'stopMessageClear':
|
|
551
|
-
applyStopMessageInstructionToState(instruction, newState);
|
|
552
|
-
break;
|
|
553
|
-
case 'preCommandSet':
|
|
554
|
-
case 'preCommandClear':
|
|
555
|
-
applyPreCommandInstructionToState(instruction, newState);
|
|
556
|
-
break;
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
return newState;
|
|
560
|
-
}
|
|
561
|
-
export function cleanMessagesFromRoutingInstructions(messages) {
|
|
562
|
-
return messages
|
|
563
|
-
.map((message) => {
|
|
564
|
-
if (message.role !== 'user' || typeof message.content !== 'string') {
|
|
565
|
-
return message;
|
|
566
|
-
}
|
|
567
|
-
const cleanedContent = message.content.replace(ROUTING_INSTRUCTION_MARKER_GLOBAL_PATTERN, '').trim();
|
|
568
|
-
return {
|
|
569
|
-
...message,
|
|
570
|
-
content: cleanedContent
|
|
571
|
-
};
|
|
572
|
-
})
|
|
573
|
-
.filter((message) => {
|
|
574
|
-
if (message.role !== 'user') {
|
|
575
|
-
return true;
|
|
576
|
-
}
|
|
577
|
-
if (typeof message.content !== 'string') {
|
|
578
|
-
return true;
|
|
579
|
-
}
|
|
580
|
-
return message.content.trim().length > 0;
|
|
581
|
-
});
|
|
582
|
-
}
|
|
583
|
-
export function serializeRoutingInstructionState(state) {
|
|
584
|
-
return {
|
|
585
|
-
forcedTarget: state.forcedTarget,
|
|
586
|
-
stickyTarget: state.stickyTarget,
|
|
587
|
-
preferTarget: state.preferTarget,
|
|
588
|
-
allowedProviders: Array.from(state.allowedProviders),
|
|
589
|
-
disabledProviders: Array.from(state.disabledProviders),
|
|
590
|
-
disabledKeys: Array.from(state.disabledKeys.entries()).map(([provider, keys]) => ({
|
|
591
|
-
provider,
|
|
592
|
-
keys: Array.from(keys)
|
|
593
|
-
})),
|
|
594
|
-
disabledModels: Array.from(state.disabledModels.entries()).map(([provider, models]) => ({
|
|
595
|
-
provider,
|
|
596
|
-
models: Array.from(models)
|
|
597
|
-
})),
|
|
598
|
-
...serializeStopMessageState(state),
|
|
599
|
-
...serializePreCommandState(state)
|
|
600
|
-
};
|
|
601
|
-
}
|
|
602
|
-
export function deserializeRoutingInstructionState(data) {
|
|
603
|
-
const state = {
|
|
604
|
-
forcedTarget: undefined,
|
|
605
|
-
stickyTarget: undefined,
|
|
606
|
-
preferTarget: undefined,
|
|
607
|
-
allowedProviders: new Set(),
|
|
608
|
-
disabledProviders: new Set(),
|
|
609
|
-
disabledKeys: new Map(),
|
|
610
|
-
disabledModels: new Map(),
|
|
611
|
-
stopMessageText: undefined,
|
|
612
|
-
stopMessageSource: undefined,
|
|
613
|
-
stopMessageMaxRepeats: undefined,
|
|
614
|
-
stopMessageUsed: undefined,
|
|
615
|
-
stopMessageStageMode: undefined,
|
|
616
|
-
stopMessageAiMode: undefined,
|
|
617
|
-
stopMessageAiSeedPrompt: undefined,
|
|
618
|
-
stopMessageAiHistory: undefined,
|
|
619
|
-
preCommandSource: undefined,
|
|
620
|
-
preCommandScriptPath: undefined,
|
|
621
|
-
preCommandUpdatedAt: undefined
|
|
622
|
-
};
|
|
623
|
-
if (data.forcedTarget && typeof data.forcedTarget === 'object') {
|
|
624
|
-
state.forcedTarget = data.forcedTarget;
|
|
625
|
-
}
|
|
626
|
-
if (data.stickyTarget && typeof data.stickyTarget === 'object') {
|
|
627
|
-
state.stickyTarget = data.stickyTarget;
|
|
628
|
-
}
|
|
629
|
-
if (data.preferTarget && typeof data.preferTarget === 'object') {
|
|
630
|
-
state.preferTarget = data.preferTarget;
|
|
631
|
-
}
|
|
632
|
-
if (Array.isArray(data.allowedProviders)) {
|
|
633
|
-
state.allowedProviders = new Set(data.allowedProviders);
|
|
634
|
-
}
|
|
635
|
-
if (Array.isArray(data.disabledProviders)) {
|
|
636
|
-
state.disabledProviders = new Set(data.disabledProviders);
|
|
637
|
-
}
|
|
638
|
-
if (Array.isArray(data.disabledKeys)) {
|
|
639
|
-
for (const entry of data.disabledKeys) {
|
|
640
|
-
if (entry.provider && Array.isArray(entry.keys)) {
|
|
641
|
-
state.disabledKeys.set(entry.provider, new Set(entry.keys));
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
if (Array.isArray(data.disabledModels)) {
|
|
646
|
-
for (const entry of data.disabledModels) {
|
|
647
|
-
if (entry.provider && Array.isArray(entry.models)) {
|
|
648
|
-
state.disabledModels.set(entry.provider, new Set(entry.models));
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
deserializeStopMessageState(data, state);
|
|
653
|
-
deserializePreCommandState(data, state);
|
|
654
|
-
return state;
|
|
655
|
-
}
|
|
1
|
+
export { ROUTING_INSTRUCTION_MARKER_PATTERN, ROUTING_INSTRUCTION_MARKER_GLOBAL_PATTERN } from './routing-instructions/types.js';
|
|
2
|
+
export { parseRoutingInstructions, parseAndPreprocessRoutingInstructions, extractClearInstruction, extractStopMessageClearInstruction } from './routing-instructions/parse.js';
|
|
3
|
+
export { applyRoutingInstructions, serializeRoutingInstructionState, deserializeRoutingInstructionState } from './routing-instructions/state.js';
|
|
4
|
+
export { cleanMessagesFromRoutingInstructions } from './routing-instructions/clean.js';
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import type { RoutingInstructionState } from './routing-instructions.js';
|
|
2
|
+
export declare class StickySessionKeyMissingError extends Error {
|
|
3
|
+
readonly key: string | undefined;
|
|
4
|
+
constructor(key: string | undefined, message: string);
|
|
5
|
+
}
|
|
2
6
|
export declare function loadRoutingInstructionStateSync(key: string | undefined): RoutingInstructionState | null;
|
|
3
7
|
export declare function saveRoutingInstructionStateAsync(key: string | undefined, state: RoutingInstructionState | null): void;
|
|
4
8
|
export declare function saveRoutingInstructionStateSync(key: string | undefined, state: RoutingInstructionState | null): void;
|