llm-simple-router 0.11.21 → 0.11.23
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/config/recommended-providers.json +3 -3
- package/dist/admin/providers.js +2 -2
- package/dist/config/recommended-providers.json +3 -3
- package/dist/db/migrations/050_normalize_patch_ids.sql +54 -0
- package/dist/proxy/patch/deepseek/patch-orphan-tool-results.d.ts +21 -12
- package/dist/proxy/patch/deepseek/patch-orphan-tool-results.js +166 -40
- package/dist/proxy/patch/index.js +3 -3
- package/frontend-dist/assets/{CardContent-1i8E_S3q.js → CardContent-tdwjLn4i.js} +1 -1
- package/frontend-dist/assets/{CardTitle-9IEYVrNF.js → CardTitle-QnVfhywP.js} +1 -1
- package/frontend-dist/assets/{CascadingModelSelect-CqzJeQWb.js → CascadingModelSelect-CUl0gGQL.js} +1 -1
- package/frontend-dist/assets/{Checkbox-9z_nic4H.js → Checkbox-uf5QqEJQ.js} +1 -1
- package/frontend-dist/assets/{CollapsibleContent-DRXTjuF_.js → CollapsibleContent-C0ytCrcq.js} +1 -1
- package/frontend-dist/assets/{CollapsibleTrigger-BusSosYR.js → CollapsibleTrigger-C_6qIDNW.js} +1 -1
- package/frontend-dist/assets/{Dashboard-DjO_Bc_0.js → Dashboard-Ems9PSCm.js} +1 -1
- package/frontend-dist/assets/{Input-BwqUPR8k.js → Input-CpDpvdgi.js} +1 -1
- package/frontend-dist/assets/{Label-CumWBzHY.js → Label-B83qJ4ZP.js} +1 -1
- package/frontend-dist/assets/{Login-9ZLrg5AA.js → Login-BMqtdfbp.js} +1 -1
- package/frontend-dist/assets/{Logs-DKktTerr.js → Logs-BLIKfkio.js} +1 -1
- package/frontend-dist/assets/{MappingEntryEditor-DX749LDW.js → MappingEntryEditor-D3KcV5CB.js} +1 -1
- package/frontend-dist/assets/{ModelMappings-snvf_INI.js → ModelMappings-DMTDact2.js} +1 -1
- package/frontend-dist/assets/{Monitor-RqCMWyto.js → Monitor-ss7HVjzI.js} +1 -1
- package/frontend-dist/assets/{Providers-DlVBSVgE.js → Providers-CedZBga7.js} +1 -1
- package/frontend-dist/assets/{ProxyEnhancement-CZBmTnsG.js → ProxyEnhancement-oUL_dwbp.js} +1 -1
- package/frontend-dist/assets/{QuickSetup-BIV6mDlG.js → QuickSetup-Co4FgTK_.js} +1 -1
- package/frontend-dist/assets/{RetryRules-DfeCwU9V.js → RetryRules-C69aeW9d.js} +1 -1
- package/frontend-dist/assets/{RouterKeys-tCdqFDml.js → RouterKeys-D3h7KUek.js} +1 -1
- package/frontend-dist/assets/{RovingFocusItem-D3EohvxE.js → RovingFocusItem-CBasI81o.js} +1 -1
- package/frontend-dist/assets/{Schedules-ImwpwJKm.js → Schedules-LaubVJAy.js} +1 -1
- package/frontend-dist/assets/{Settings-BUsDohX6.js → Settings-Dkj-jirH.js} +1 -1
- package/frontend-dist/assets/{Setup-2xmJP0f2.js → Setup-CNLhYD6z.js} +1 -1
- package/frontend-dist/assets/{Switch-Ce1RNEg2.js → Switch-JfjgADP5.js} +1 -1
- package/frontend-dist/assets/{TooltipTrigger-BvHKib2n.js → TooltipTrigger-C3Yxt228.js} +1 -1
- package/frontend-dist/assets/{TransformRulesForm-BT9zoPTc.js → TransformRulesForm-DA5XjrhO.js} +1 -1
- package/frontend-dist/assets/{UnifiedRequestDialog-D_88_dFB.js → UnifiedRequestDialog-B0GenWYJ.js} +1 -1
- package/frontend-dist/assets/{VisuallyHiddenInput-B-usxRjt.js → VisuallyHiddenInput-1EakFczP.js} +1 -1
- package/frontend-dist/assets/{button-Dm-cbgS5.js → button-EcESBjGm.js} +2 -2
- package/frontend-dist/assets/{copy-DMw-23Tb.js → copy-CmpVrrwT.js} +1 -1
- package/frontend-dist/assets/{dialog-Dzy4m58L.js → dialog-Is8Ujw3N.js} +1 -1
- package/frontend-dist/assets/{index-CTaQHTod.js → index-Dv_nrEfy.js} +2 -2
- package/frontend-dist/assets/{model-patches-Be68Qreu.js → model-patches-BKeZXFvS.js} +1 -1
- package/frontend-dist/assets/plus-CLv_FYiq.js +1 -0
- package/frontend-dist/assets/{sparkles-7mkrsmh7.js → sparkles-CGWfJ0kh.js} +1 -1
- package/frontend-dist/assets/{trash-2-BoBubJto.js → trash-2-Dz0n3WgV.js} +1 -1
- package/frontend-dist/assets/{useClipboard-DebN1Yvq.js → useClipboard-BJ0o_fEC.js} +1 -1
- package/frontend-dist/assets/{useLogRetention-BGDglTVo.js → useLogRetention-C05x-s32.js} +1 -1
- package/frontend-dist/index.html +2 -2
- package/package.json +1 -1
- package/frontend-dist/assets/plus-BkH7yWn-.js +0 -1
|
@@ -304,9 +304,7 @@
|
|
|
304
304
|
"mimo-v2-pro",
|
|
305
305
|
"mimo-v2-omni",
|
|
306
306
|
"mimo-v2.5-pro",
|
|
307
|
-
"mimo-v2.5"
|
|
308
|
-
"qwen3.6-plus",
|
|
309
|
-
"qwen3.5-plus"
|
|
307
|
+
"mimo-v2.5"
|
|
310
308
|
]
|
|
311
309
|
},
|
|
312
310
|
{
|
|
@@ -315,6 +313,8 @@
|
|
|
315
313
|
"apiType": "anthropic",
|
|
316
314
|
"baseUrl": "https://opencode.ai/zen/go/v1/messages",
|
|
317
315
|
"models": [
|
|
316
|
+
"qwen3.6-plus",
|
|
317
|
+
"qwen3.5-plus",
|
|
318
318
|
"minimax-m2.7",
|
|
319
319
|
"minimax-m2.5"
|
|
320
320
|
]
|
package/dist/admin/providers.js
CHANGED
|
@@ -4,7 +4,7 @@ import { encrypt, decrypt } from "../utils/crypto.js";
|
|
|
4
4
|
import { getSetting } from "../db/settings.js";
|
|
5
5
|
import { HTTP_CREATED, HTTP_NOT_FOUND, HTTP_CONFLICT, HTTP_BAD_REQUEST, HTTP_OK } from "./constants.js";
|
|
6
6
|
import { API_CODE, apiError } from "./api-response.js";
|
|
7
|
-
import { parseModels, buildModelInfoList } from "../config/model-context.js";
|
|
7
|
+
import { parseModels, buildModelInfoList, normalizePatchName } from "../config/model-context.js";
|
|
8
8
|
import { getModelInfoForProvider, setModelInfoForProvider, deleteAllModelInfoForProvider } from "../db/model-info.js";
|
|
9
9
|
import { buildUpstreamHeaders } from "../proxy/proxy-core.js";
|
|
10
10
|
import { callGet } from "../proxy/transport/http.js";
|
|
@@ -71,7 +71,7 @@ function extractModelOverrides(models) {
|
|
|
71
71
|
const name = m.name ?? m.id;
|
|
72
72
|
if (!name)
|
|
73
73
|
continue;
|
|
74
|
-
const entry = { name, patches: m.patches ?? [] };
|
|
74
|
+
const entry = { name, patches: (m.patches ?? []).map(normalizePatchName) };
|
|
75
75
|
if (m.stream_timeout_ms != null)
|
|
76
76
|
entry.stream_timeout_ms = m.stream_timeout_ms;
|
|
77
77
|
if (m.capabilities != null && Array.isArray(m.capabilities))
|
|
@@ -304,9 +304,7 @@
|
|
|
304
304
|
"mimo-v2-pro",
|
|
305
305
|
"mimo-v2-omni",
|
|
306
306
|
"mimo-v2.5-pro",
|
|
307
|
-
"mimo-v2.5"
|
|
308
|
-
"qwen3.6-plus",
|
|
309
|
-
"qwen3.5-plus"
|
|
307
|
+
"mimo-v2.5"
|
|
310
308
|
]
|
|
311
309
|
},
|
|
312
310
|
{
|
|
@@ -315,6 +313,8 @@
|
|
|
315
313
|
"apiType": "anthropic",
|
|
316
314
|
"baseUrl": "https://opencode.ai/zen/go/v1/messages",
|
|
317
315
|
"models": [
|
|
316
|
+
"qwen3.6-plus",
|
|
317
|
+
"qwen3.5-plus",
|
|
318
318
|
"minimax-m2.7",
|
|
319
319
|
"minimax-m2.5"
|
|
320
320
|
]
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
-- Normalize patch IDs in providers.models JSON from hyphen to underscore format.
|
|
2
|
+
-- All patch IDs stored in DB should use underscore (thinking_consistency, orphan_tool_results, etc).
|
|
3
|
+
-- Frontend sends hyphen format, normalizePatchName normalizes at write/read time.
|
|
4
|
+
-- This migration ensures existing DB data is also normalized and deduplicated.
|
|
5
|
+
|
|
6
|
+
-- Step 1: Migrate old patch IDs to current canonical names (underscore format)
|
|
7
|
+
-- These old IDs were already stored with underscores, just need name mapping
|
|
8
|
+
UPDATE providers
|
|
9
|
+
SET models = REPLACE(models, 'thinking_param', 'thinking_consistency')
|
|
10
|
+
WHERE models LIKE '%thinking_param%';
|
|
11
|
+
|
|
12
|
+
UPDATE providers
|
|
13
|
+
SET models = REPLACE(models, 'thinking_blocks', 'thinking_consistency')
|
|
14
|
+
WHERE models LIKE '%thinking_blocks%';
|
|
15
|
+
|
|
16
|
+
UPDATE providers
|
|
17
|
+
SET models = REPLACE(models, 'non_ds_tools', 'thinking_consistency')
|
|
18
|
+
WHERE models LIKE '%non_ds_tools%';
|
|
19
|
+
|
|
20
|
+
UPDATE providers
|
|
21
|
+
SET models = REPLACE(models, 'cache_control', 'thinking_consistency')
|
|
22
|
+
WHERE models LIKE '%cache_control%';
|
|
23
|
+
|
|
24
|
+
-- Step 2: Normalize hyphen to underscore (must handle multi-word IDs in correct order)
|
|
25
|
+
-- Longer IDs first to avoid partial replacement
|
|
26
|
+
|
|
27
|
+
-- orphan-tool-results-oa → orphan_tool_results_oa (before orphan-tool-results)
|
|
28
|
+
UPDATE providers
|
|
29
|
+
SET models = REPLACE(models, 'orphan-tool-results-oa', 'orphan_tool_results_oa')
|
|
30
|
+
WHERE models LIKE '%orphan-tool-results-oa%';
|
|
31
|
+
|
|
32
|
+
-- orphan-tool-results → orphan_tool_results
|
|
33
|
+
UPDATE providers
|
|
34
|
+
SET models = REPLACE(models, 'orphan-tool-results', 'orphan_tool_results')
|
|
35
|
+
WHERE models LIKE '%orphan-tool-results%';
|
|
36
|
+
|
|
37
|
+
-- thinking-consistency → thinking_consistency
|
|
38
|
+
UPDATE providers
|
|
39
|
+
SET models = REPLACE(models, 'thinking-consistency', 'thinking_consistency')
|
|
40
|
+
WHERE models LIKE '%thinking-consistency%';
|
|
41
|
+
|
|
42
|
+
-- developer-role → developer_role
|
|
43
|
+
UPDATE providers
|
|
44
|
+
SET models = REPLACE(models, 'developer-role', 'developer_role')
|
|
45
|
+
WHERE models LIKE '%developer-role%';
|
|
46
|
+
|
|
47
|
+
-- Step 3: Deduplicate patch arrays within each provider's models JSON.
|
|
48
|
+
-- After migration, the same patch ID may appear multiple times in an array.
|
|
49
|
+
-- This uses a recursive CTE to remove duplicate values from JSON arrays.
|
|
50
|
+
-- Only processes rows that have patches (contain "thinking_consistency" etc).
|
|
51
|
+
--
|
|
52
|
+
-- Note: SQLite JSON dedup is complex. The application layer (parseModels)
|
|
53
|
+
-- already deduplicates via Set at read time, so this step is best-effort
|
|
54
|
+
-- cleanup for DB consistency. A separate script is recommended for large datasets.
|
|
@@ -1,21 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* 可能丢失 tool_use 块但保留对应的 tool_result,导致 DeepSeek 严格校验失败。
|
|
2
|
+
* 修复 Anthropic 格式消息中的 tool_use / tool_result 配对断裂。
|
|
4
3
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Claude Code 的 context management 截断历史消息时可能产生两种方向的不匹配:
|
|
5
|
+
* - 正向:tool_result 存在但对应的 tool_use 被截断(孤儿 tool_result)
|
|
6
|
+
* - 反向:tool_use 存在但对应的 tool_result 被截断(孤儿 tool_use)
|
|
7
|
+
*
|
|
8
|
+
* 两种都会导致 DeepSeek Anthropic 端点校验失败。
|
|
9
|
+
*
|
|
10
|
+
* 算法(正向 + 反向):
|
|
11
|
+
* 1. 正向:收集所有 tool_use ID,移除无主的 tool_result 块
|
|
12
|
+
* 2. 反向:收集所有 tool_result ID,从非末尾 assistant 中移除无主的 tool_use 块
|
|
8
13
|
* 3. 移除清空后的空 user 消息
|
|
9
|
-
* 4.
|
|
10
|
-
* 5. 合并相邻的 assistant 消息(带 tool_use 去重)
|
|
11
|
-
* 6. 移除 content 为空数组的 assistant 消息
|
|
12
|
-
* 7. 最终合并连续同角色消息
|
|
14
|
+
* 4-7. 合并/清理消息链
|
|
13
15
|
*/
|
|
14
16
|
export declare function patchOrphanToolResults(body: Record<string, unknown>): void;
|
|
15
17
|
/**
|
|
16
|
-
* OpenAI
|
|
18
|
+
* OpenAI 格式版本的 tool_calls / tool 消息配对修复。
|
|
19
|
+
*
|
|
20
|
+
* 检测两种方向的不匹配:
|
|
21
|
+
* - 正向:role:"tool" 消息的 tool_call_id 无对应 assistant tool_calls[].id → 移除孤儿 tool 消息
|
|
22
|
+
* - 反向:非末尾 assistant 的 tool_calls[].id 无对应 tool 消息 → 移除该 tool_call 条目
|
|
23
|
+
*
|
|
24
|
+
* 反向跳过最后一条 assistant:它可能是正常的工具调用中间状态(模型刚返回 tool_calls,
|
|
25
|
+
* 客户端还没来得及执行并回传 tool 消息)。
|
|
17
26
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
27
|
+
* Step 4: 重排插在 assistant(tool_calls) 和 tool 之间的非 tool 消息(如用户中断),
|
|
28
|
+
* 将 tool 消息提前到紧接 assistant 之后,满足 DeepSeek"tool_calls 后必须紧跟 tool"的校验。
|
|
20
29
|
*/
|
|
21
30
|
export declare function patchOrphanToolResultsOA(body: Record<string, unknown>): void;
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { mergeConsecutive, mergeAssistantContent } from "./utils.js";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
* 可能丢失 tool_use 块但保留对应的 tool_result,导致 DeepSeek 严格校验失败。
|
|
3
|
+
* 修复 Anthropic 格式消息中的 tool_use / tool_result 配对断裂。
|
|
5
4
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* Claude Code 的 context management 截断历史消息时可能产生两种方向的不匹配:
|
|
6
|
+
* - 正向:tool_result 存在但对应的 tool_use 被截断(孤儿 tool_result)
|
|
7
|
+
* - 反向:tool_use 存在但对应的 tool_result 被截断(孤儿 tool_use)
|
|
8
|
+
*
|
|
9
|
+
* 两种都会导致 DeepSeek Anthropic 端点校验失败。
|
|
10
|
+
*
|
|
11
|
+
* 算法(正向 + 反向):
|
|
12
|
+
* 1. 正向:收集所有 tool_use ID,移除无主的 tool_result 块
|
|
13
|
+
* 2. 反向:收集所有 tool_result ID,从非末尾 assistant 中移除无主的 tool_use 块
|
|
9
14
|
* 3. 移除清空后的空 user 消息
|
|
10
|
-
* 4.
|
|
11
|
-
* 5. 合并相邻的 assistant 消息(带 tool_use 去重)
|
|
12
|
-
* 6. 移除 content 为空数组的 assistant 消息
|
|
13
|
-
* 7. 最终合并连续同角色消息
|
|
15
|
+
* 4-7. 合并/清理消息链
|
|
14
16
|
*/
|
|
15
17
|
export function patchOrphanToolResults(body) {
|
|
16
18
|
if (!body.messages)
|
|
@@ -18,7 +20,8 @@ export function patchOrphanToolResults(body) {
|
|
|
18
20
|
const messages = body.messages;
|
|
19
21
|
if (!Array.isArray(messages) || messages.length === 0)
|
|
20
22
|
return;
|
|
21
|
-
|
|
23
|
+
let changed = false;
|
|
24
|
+
// ---- 正向:移除孤儿 tool_result(tool_result 无对应 tool_use)----
|
|
22
25
|
const knownToolUseIds = new Set();
|
|
23
26
|
for (const msg of messages) {
|
|
24
27
|
if (msg.role !== "assistant" || !Array.isArray(msg.content))
|
|
@@ -29,8 +32,6 @@ export function patchOrphanToolResults(body) {
|
|
|
29
32
|
}
|
|
30
33
|
}
|
|
31
34
|
}
|
|
32
|
-
// Step 2: 移除孤儿 tool_result 块
|
|
33
|
-
let removedAny = false;
|
|
34
35
|
for (const msg of messages) {
|
|
35
36
|
if (msg.role !== "user" || !Array.isArray(msg.content))
|
|
36
37
|
continue;
|
|
@@ -44,12 +45,47 @@ export function patchOrphanToolResults(body) {
|
|
|
44
45
|
});
|
|
45
46
|
if (filtered.length < before) {
|
|
46
47
|
msg.content = filtered;
|
|
47
|
-
|
|
48
|
+
changed = true;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// ---- 反向:移除孤儿 tool_use(非末尾 assistant 的 tool_use 无对应 tool_result)----
|
|
52
|
+
const knownToolResultIds = new Set();
|
|
53
|
+
for (const msg of messages) {
|
|
54
|
+
if (msg.role !== "user" || !Array.isArray(msg.content))
|
|
55
|
+
continue;
|
|
56
|
+
for (const block of msg.content) {
|
|
57
|
+
if (block?.type === "tool_result" && typeof block.tool_use_id === "string") {
|
|
58
|
+
knownToolResultIds.add(block.tool_use_id);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const lastMsgIdx = messages.length - 1;
|
|
63
|
+
for (let i = 0; i <= lastMsgIdx; i++) {
|
|
64
|
+
const msg = messages[i];
|
|
65
|
+
if (msg.role !== "assistant" || !Array.isArray(msg.content))
|
|
66
|
+
continue;
|
|
67
|
+
// 跳过最后一条 assistant:它可能是正常的工具调用中间状态
|
|
68
|
+
if (i === lastMsgIdx)
|
|
69
|
+
break;
|
|
70
|
+
const blocks = msg.content;
|
|
71
|
+
const hasToolUse = blocks.some(b => b?.type === "tool_use");
|
|
72
|
+
if (!hasToolUse)
|
|
73
|
+
continue;
|
|
74
|
+
const before = blocks.length;
|
|
75
|
+
const filtered = blocks.filter(block => {
|
|
76
|
+
if (block?.type === "tool_use" && typeof block.id === "string") {
|
|
77
|
+
return knownToolResultIds.has(block.id);
|
|
78
|
+
}
|
|
79
|
+
return true;
|
|
80
|
+
});
|
|
81
|
+
if (filtered.length < before) {
|
|
82
|
+
msg.content = filtered;
|
|
83
|
+
changed = true;
|
|
48
84
|
}
|
|
49
85
|
}
|
|
50
|
-
if (!
|
|
86
|
+
if (!changed)
|
|
51
87
|
return;
|
|
52
|
-
//
|
|
88
|
+
// 移除清空后的空 user 消息(向后遍历避免索引错乱)
|
|
53
89
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
54
90
|
const msg = messages[i];
|
|
55
91
|
if (msg.role !== "user")
|
|
@@ -61,32 +97,39 @@ export function patchOrphanToolResults(body) {
|
|
|
61
97
|
messages.splice(i, 1);
|
|
62
98
|
}
|
|
63
99
|
}
|
|
64
|
-
//
|
|
100
|
+
// 合并相邻的 user 消息
|
|
65
101
|
mergeConsecutive(messages, "user");
|
|
66
|
-
//
|
|
102
|
+
// 合并相邻的 assistant 消息(带 tool_use 去重)+ 移除空 assistant
|
|
67
103
|
mergeConsecutive(messages, "assistant", mergeAssistantContent);
|
|
68
|
-
// Step 6: 移除 content 为空数组的 assistant 消息
|
|
69
104
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
70
105
|
const msg = messages[i];
|
|
71
106
|
if (msg.role === "assistant" && Array.isArray(msg.content) && msg.content.length === 0) {
|
|
72
107
|
messages.splice(i, 1);
|
|
73
108
|
}
|
|
74
109
|
}
|
|
75
|
-
//
|
|
110
|
+
// 删除空 assistant 后可能产生连续同角色消息,再合并一次
|
|
76
111
|
mergeConsecutive(messages, "user");
|
|
77
112
|
mergeConsecutive(messages, "assistant", mergeAssistantContent);
|
|
78
113
|
}
|
|
79
114
|
/**
|
|
80
|
-
* OpenAI
|
|
115
|
+
* OpenAI 格式版本的 tool_calls / tool 消息配对修复。
|
|
81
116
|
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
117
|
+
* 检测两种方向的不匹配:
|
|
118
|
+
* - 正向:role:"tool" 消息的 tool_call_id 无对应 assistant tool_calls[].id → 移除孤儿 tool 消息
|
|
119
|
+
* - 反向:非末尾 assistant 的 tool_calls[].id 无对应 tool 消息 → 移除该 tool_call 条目
|
|
120
|
+
*
|
|
121
|
+
* 反向跳过最后一条 assistant:它可能是正常的工具调用中间状态(模型刚返回 tool_calls,
|
|
122
|
+
* 客户端还没来得及执行并回传 tool 消息)。
|
|
123
|
+
*
|
|
124
|
+
* Step 4: 重排插在 assistant(tool_calls) 和 tool 之间的非 tool 消息(如用户中断),
|
|
125
|
+
* 将 tool 消息提前到紧接 assistant 之后,满足 DeepSeek"tool_calls 后必须紧跟 tool"的校验。
|
|
84
126
|
*/
|
|
85
127
|
export function patchOrphanToolResultsOA(body) {
|
|
86
128
|
const messages = body.messages;
|
|
87
129
|
if (!messages || !Array.isArray(messages) || messages.length === 0)
|
|
88
130
|
return;
|
|
89
|
-
//
|
|
131
|
+
// ---- 正向:移除孤儿 tool 消息 ----
|
|
132
|
+
// 收集所有 assistant tool_calls IDs
|
|
90
133
|
const knownToolCallIds = new Set();
|
|
91
134
|
for (const msg of messages) {
|
|
92
135
|
if (msg.role !== "assistant")
|
|
@@ -99,8 +142,8 @@ export function patchOrphanToolResultsOA(body) {
|
|
|
99
142
|
knownToolCallIds.add(tc.id);
|
|
100
143
|
}
|
|
101
144
|
}
|
|
102
|
-
//
|
|
103
|
-
let
|
|
145
|
+
// 移除无主 tool 消息(逆序遍历避免索引偏移)
|
|
146
|
+
let changed = false;
|
|
104
147
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
105
148
|
const msg = messages[i];
|
|
106
149
|
if (msg.role !== "tool")
|
|
@@ -108,24 +151,107 @@ export function patchOrphanToolResultsOA(body) {
|
|
|
108
151
|
const toolCallId = (msg.tool_call_id ?? "");
|
|
109
152
|
if (!knownToolCallIds.has(toolCallId)) {
|
|
110
153
|
messages.splice(i, 1);
|
|
111
|
-
|
|
154
|
+
changed = true;
|
|
112
155
|
}
|
|
113
156
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
157
|
+
// ---- 反向:移除孤儿 tool_calls 条目(非末尾 assistant)----
|
|
158
|
+
// 收集所有 tool 消息的 ID
|
|
159
|
+
const knownToolMsgIds = new Set();
|
|
160
|
+
for (const msg of messages) {
|
|
161
|
+
if (msg.role !== "tool")
|
|
162
|
+
continue;
|
|
163
|
+
const toolCallId = (msg.tool_call_id ?? "");
|
|
164
|
+
if (toolCallId)
|
|
165
|
+
knownToolMsgIds.add(toolCallId);
|
|
166
|
+
}
|
|
167
|
+
const lastMsgIdx = messages.length - 1;
|
|
168
|
+
for (let i = 0; i <= lastMsgIdx; i++) {
|
|
169
|
+
const msg = messages[i];
|
|
170
|
+
if (msg.role !== "assistant")
|
|
171
|
+
continue;
|
|
172
|
+
// 跳过最后一条 assistant:它可能是正常的工具调用中间状态
|
|
173
|
+
if (i === lastMsgIdx)
|
|
174
|
+
break;
|
|
175
|
+
const toolCalls = msg.tool_calls;
|
|
176
|
+
if (!toolCalls || toolCalls.length === 0)
|
|
177
|
+
continue;
|
|
178
|
+
const before = toolCalls.length;
|
|
179
|
+
const filtered = toolCalls.filter(tc => {
|
|
180
|
+
const id = tc.id;
|
|
181
|
+
return !id || knownToolMsgIds.has(id);
|
|
182
|
+
});
|
|
183
|
+
if (filtered.length < before) {
|
|
184
|
+
if (filtered.length === 0) {
|
|
185
|
+
delete msg.tool_calls;
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
msg.tool_calls = filtered;
|
|
189
|
+
}
|
|
190
|
+
changed = true;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (changed) {
|
|
194
|
+
// 移除空壳 assistant(content 无实质内容且无 tool_calls)
|
|
195
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
196
|
+
const m = messages[i];
|
|
197
|
+
if (m.role !== "assistant")
|
|
198
|
+
continue;
|
|
199
|
+
if (m.tool_calls)
|
|
200
|
+
continue;
|
|
201
|
+
const content = m.content;
|
|
202
|
+
if (content === null || content === undefined || content === ""
|
|
203
|
+
|| (Array.isArray(content) && content.length === 0)) {
|
|
204
|
+
messages.splice(i, 1);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
// 合并连续 user 消息
|
|
208
|
+
for (let i = 1; i < messages.length;) {
|
|
209
|
+
if (messages[i].role === "user" && messages[i - 1].role === "user") {
|
|
210
|
+
const prev = messages[i - 1];
|
|
211
|
+
const curr = messages[i];
|
|
212
|
+
const prevContent = typeof prev.content === "string" ? prev.content : JSON.stringify(prev.content ?? "");
|
|
213
|
+
const currContent = typeof curr.content === "string" ? curr.content : JSON.stringify(curr.content ?? "");
|
|
214
|
+
prev.content = prevContent + "\n" + currContent;
|
|
215
|
+
messages.splice(i, 1);
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
i++;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
// Step 4: 修复 tool_calls 消息顺序——将插在 assistant(tool_calls) 与 tool 之间的
|
|
223
|
+
// 非 tool 消息(如用户中断、系统提醒)挪到 tool 消息之后
|
|
224
|
+
// scanLimit 上限:每个 tool_call 最多对应 1 个 tool 消息 + 1 个可能穿插的非 tool 消息,
|
|
225
|
+
// 额外 +3 留出边界余量(额外的 user/system 消息)
|
|
226
|
+
const SCAN_LIMIT_EXTRA = 3;
|
|
227
|
+
for (let idx = 0; idx < messages.length; idx++) {
|
|
228
|
+
const msg = messages[idx];
|
|
229
|
+
if (msg.role !== "assistant" || !msg.tool_calls || !msg.tool_calls.length)
|
|
230
|
+
continue;
|
|
231
|
+
const toolCalls = msg.tool_calls;
|
|
232
|
+
const expectedIds = new Set(toolCalls.map(tc => tc.id));
|
|
233
|
+
const intervening = [];
|
|
234
|
+
const toolMsgs = [];
|
|
235
|
+
const SCAN_SLOTS_PER_CALL = 2; // 每个 tool_call: 1 个 tool 消息 + 1 个可能穿插的消息
|
|
236
|
+
const scanLimit = idx + 1 + expectedIds.size * SCAN_SLOTS_PER_CALL + SCAN_LIMIT_EXTRA;
|
|
237
|
+
let j = idx + 1;
|
|
238
|
+
for (; j < messages.length && j <= scanLimit; j++) {
|
|
239
|
+
const next = messages[j];
|
|
240
|
+
if (next.role === "tool" && expectedIds.has(next.tool_call_id)) {
|
|
241
|
+
toolMsgs.push(next);
|
|
242
|
+
expectedIds.delete(next.tool_call_id);
|
|
243
|
+
if (expectedIds.size === 0)
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
intervening.push(next);
|
|
248
|
+
}
|
|
126
249
|
}
|
|
127
|
-
|
|
128
|
-
|
|
250
|
+
if (intervening.length > 0 && toolMsgs.length > 0 && expectedIds.size === 0) {
|
|
251
|
+
const count = intervening.length + toolMsgs.length;
|
|
252
|
+
messages.splice(idx + 1, count, ...toolMsgs, ...intervening);
|
|
253
|
+
// splice 后跳过已重排的区域(toolMsgs + intervening),避免重复处理
|
|
254
|
+
idx += count;
|
|
129
255
|
}
|
|
130
256
|
}
|
|
131
257
|
}
|
|
@@ -24,15 +24,15 @@ export function applyProviderPatches(body, provider) {
|
|
|
24
24
|
const modelPatches = modelEntry?.patches ?? [];
|
|
25
25
|
if (modelPatches.length > 0) {
|
|
26
26
|
// developer_role 补丁(仅 openai 格式需要)
|
|
27
|
-
if (hasPatch(modelPatches, "
|
|
27
|
+
if (hasPatch(modelPatches, "developer_role") && provider.api_type === "openai" && hasDeveloperRole(body)) {
|
|
28
28
|
patchDeveloperRole(ensureCloned());
|
|
29
29
|
patches.push("developer_role");
|
|
30
30
|
}
|
|
31
31
|
// DeepSeek 补丁:新旧 patch ID 都能触发,内部按 apiType 自动分发
|
|
32
32
|
const dsPatches = [
|
|
33
|
-
"
|
|
33
|
+
"thinking_consistency", "thinking-param", "thinking-blocks",
|
|
34
34
|
"non-ds-tools", "cache-control",
|
|
35
|
-
"
|
|
35
|
+
"orphan_tool_results", "orphan_tool_results_oa",
|
|
36
36
|
];
|
|
37
37
|
if (dsPatches.some(p => hasPatch(modelPatches, p))) {
|
|
38
38
|
applyDeepSeekPatches(ensureCloned(), provider.api_type);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Gt as e,et as t,gt as n,it as r,qt as i,r as a,yt as o}from"./button-
|
|
1
|
+
import{Gt as e,et as t,gt as n,it as r,qt as i,r as a,yt as o}from"./button-EcESBjGm.js";var s=[`data-size`],c=r({__name:`Card`,props:{class:{type:[Boolean,null,String,Object,Array]},size:{default:`default`}},setup(r){let c=r;return(l,u)=>(n(),t(`div`,{"data-slot":`card`,"data-size":r.size,class:i(e(a)(`ring-foreground/10 bg-card text-card-foreground gap-4 overflow-hidden rounded-lg py-4 text-sm ring-1 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-lg *:[img:last-child]:rounded-b-lg group/card flex flex-col`,c.class))},[o(l.$slots,`default`)],10,s))}}),l=r({__name:`CardContent`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(r){let s=r;return(r,c)=>(n(),t(`div`,{"data-slot":`card-content`,class:i(e(a)(`px-4 group-data-[size=sm]/card:px-3`,s.class))},[o(r.$slots,`default`)],2))}});export{c as n,l as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Gt as e,et as t,gt as n,it as r,qt as i,r as a,yt as o}from"./button-
|
|
1
|
+
import{Gt as e,et as t,gt as n,it as r,qt as i,r as a,yt as o}from"./button-EcESBjGm.js";var s=r({__name:`CardHeader`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(r){let s=r;return(r,c)=>(n(),t(`div`,{"data-slot":`card-header`,class:i(e(a)(`gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3 group/card-header @container/card-header grid auto-rows-min items-start has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto]`,s.class))},[o(r.$slots,`default`)],2))}}),c=r({__name:`CardTitle`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(r){let s=r;return(r,c)=>(n(),t(`div`,{"data-slot":`card-title`,class:i(e(a)(`text-base leading-snug font-medium group-data-[size=sm]/card:text-sm cn-font-heading`,s.class))},[o(r.$slots,`default`)],2))}});export{s as n,c as t};
|
package/frontend-dist/assets/{CascadingModelSelect-CqzJeQWb.js → CascadingModelSelect-CUl0gGQL.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{$ as e,Gt as t,H as n,J as r,L as i,Lt as a,Q as o,X as s,Xt as c,Z as l,et as u,gt as d,it as f,kt as p,qt as m,rt as h,vt as g}from"./button-
|
|
1
|
+
import{$ as e,Gt as t,H as n,J as r,L as i,Lt as a,Q as o,X as s,Xt as c,Z as l,et as u,gt as d,it as f,kt as p,qt as m,rt as h,vt as g}from"./button-EcESBjGm.js";import{b as _,ft as v,ht as y,v as b,y as x}from"./index-Dv_nrEfy.js";var S=i(`chevron-right`,[[`path`,{d:`m9 18 6-6-6-6`,key:`mthhwq`}]]),C=[`onMouseenter`],w={class:`truncate max-w-40`},T={key:0,class:`ml-1 text-[10px] px-1 py-px rounded bg-emerald-500/15 text-emerald-400 shrink-0`},E=[`onMouseenter`],D=[`onClick`],O={class:`truncate`},k={key:0,class:`shrink-0 text-xs text-muted-foreground`},A={key:0,class:`px-2 py-1.5 text-sm text-muted-foreground`},j=f({__name:`CascadingSelect`,props:{groups:{},modelValue:{},placeholder:{default:``},compact:{type:Boolean,default:!1}},emits:[`update:modelValue`],setup(i,{emit:f}){let{t:y}=n(),j=i,M=s(()=>j.placeholder||y(`common.selectPlaceholder`)),N=f,P=a(!1),F=a(null),I=s(()=>{if(!j.modelValue)return``;let e=j.groups.find(e=>e.key===j.modelValue.groupKey);if(!e)return``;let t=e.options.find(e=>e.value===j.modelValue.value);return t?`${e.label} / ${t.label}`:``});function L(e,t){N(`update:modelValue`,{groupKey:e,value:t}),P.value=!1}function R(e){P.value=e,e||(F.value=null)}return(n,a)=>(d(),o(t(_),{open:P.value,"onUpdate:open":R},{default:p(()=>[h(t(b),{"as-child":``},{default:p(()=>[l(`div`,{class:m([`flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background cursor-pointer hover:bg-accent hover:text-accent-foreground`,[i.compact?`h-8 text-xs px-2.5 py-1`:`h-10 text-sm px-3 py-2`,{"ring-2 ring-ring ring-offset-2":P.value}]])},[l(`span`,{class:m([`truncate`,i.modelValue?`text-foreground`:`text-muted-foreground`])},c(I.value||M.value),3),h(t(v),{class:`h-4 w-4 shrink-0 opacity-50`})],2)]),_:1}),h(t(x),{align:`start`,"side-offset":4,class:`z-[200] w-auto min-w-56 overflow-visible p-1`},{default:p(()=>[(d(!0),u(r,null,g(i.groups,n=>(d(),u(`div`,{key:n.key,class:m([`relative flex cursor-pointer items-center justify-between rounded-sm px-2 py-1.5 text-sm hover:bg-accent hover:text-accent-foreground`,{"bg-accent text-accent-foreground z-10":F.value===n.key}]),onMouseenter:e=>F.value=n.key},[l(`span`,w,c(n.label),1),n.badge?(d(),u(`span`,T,c(n.badge),1)):e(``,!0),h(t(S),{class:`ml-1 h-4 w-4 shrink-0 opacity-50`}),F.value===n.key&&n.options.length>0?(d(),u(`div`,{key:1,class:`absolute left-full top-0 ml-0.5 min-w-48 rounded-md border bg-popover p-1 text-popover-foreground shadow-md`,onMouseenter:e=>F.value=n.key},[(d(!0),u(r,null,g(n.options,t=>(d(),u(`div`,{key:t.value,class:m([`flex cursor-pointer items-center justify-between gap-2 rounded-sm px-2 py-1.5 text-sm hover:bg-accent hover:text-accent-foreground`,{"bg-accent text-accent-foreground":i.modelValue?.groupKey===n.key&&i.modelValue?.value===t.value}]),onClick:e=>L(n.key,t.value)},[l(`span`,O,c(t.label),1),t.tag?(d(),u(`span`,k,c(t.tag),1)):e(``,!0)],10,D))),128))],40,E)):e(``,!0)],42,C))),128)),i.groups.length===0?(d(),u(`div`,A,c(t(y)(`common.noOptions`)),1)):e(``,!0)]),_:1})]),_:1},8,[`open`]))}}),M=f({__name:`CascadingModelSelect`,props:{providers:{},modelValue:{},placeholder:{default:``},compact:{type:Boolean}},emits:[`update:modelValue`],setup(e,{emit:t}){let{t:r}=n(),i=e,a=s(()=>i.placeholder||r(`mappings.selectProviderModel`)),c=t,l=s(()=>i.providers.map(e=>({key:e.provider.id,label:e.provider.name,badge:e.isNew?r(`common.new`):void 0,options:e.models.map(e=>({value:e.name,label:e.name,tag:y(e.contextWindow)}))}))),u=s(()=>i.modelValue?{groupKey:i.modelValue.provider_id,value:i.modelValue.model}:void 0);function f(e){c(`update:modelValue`,{provider_id:e.groupKey,model:e.value})}return(t,n)=>(d(),o(j,{groups:l.value,"model-value":u.value,placeholder:a.value,compact:e.compact,"onUpdate:modelValue":f},null,8,[`groups`,`model-value`,`placeholder`,`compact`]))}});export{M as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{$ as e,Gt as t,Jt as n,K as r,Q as i,X as a,dt as o,gt as s,i as c,it as l,kt as u,m as d,o as f,ot as p,q as m,r as h,rt as g,x as _,xt as v,yt as y}from"./button-
|
|
1
|
+
import{$ as e,Gt as t,Jt as n,K as r,Q as i,X as a,dt as o,gt as s,i as c,it as l,kt as u,m as d,o as f,ot as p,q as m,r as h,rt as g,x as _,xt as v,yt as y}from"./button-EcESBjGm.js";import{t as b}from"./VisuallyHiddenInput-1EakFczP.js";import{t as x}from"./RovingFocusItem-CBasI81o.js";import{J as S,K as C,R as w,U as T,V as E,X as D,pt as O}from"./index-Dv_nrEfy.js";function k(e,t){return C(e)?!1:Array.isArray(e)?e.some(e=>D(e,t)):D(e,t)}var[A,j]=S(`CheckboxGroupRoot`);function M(e){return e===`indeterminate`}function N(e){return M(e)?`indeterminate`:e?`checked`:`unchecked`}var[P,F]=S(`CheckboxRoot`),I=l({inheritAttrs:!1,__name:`CheckboxRoot`,props:{defaultValue:{type:null,required:!1},modelValue:{type:null,required:!1,default:void 0},disabled:{type:Boolean,required:!1},value:{type:null,required:!1,default:`on`},id:{type:String,required:!1},trueValue:{type:null,required:!1,default:()=>!0},falseValue:{type:null,required:!1,default:()=>!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`button`},name:{type:String,required:!1},required:{type:Boolean,required:!1}},emits:[`update:modelValue`],setup(n,{emit:l}){let p=n,h=l,{forwardRef:g,currentElement:_}=f(),S=A(null),w=d(p,`modelValue`,h,{defaultValue:p.defaultValue??p.falseValue,passive:p.modelValue===void 0}),E=a(()=>S?.disabled.value||p.disabled),O=a(()=>D(w.value,p.trueValue)),j=a(()=>C(S?.modelValue.value)?w.value===`indeterminate`?`indeterminate`:O.value:k(S.modelValue.value,p.value));function P(){if(C(S?.modelValue.value))w.value===`indeterminate`?w.value=p.trueValue:w.value=O.value?p.falseValue:p.trueValue;else{let e=[...S.modelValue.value||[]];if(k(e,p.value)){let t=e.findIndex(e=>D(e,p.value));e.splice(t,1)}else e.push(p.value);S.modelValue.value=e}}let I=T(_),L=a(()=>p.id&&_.value?document.querySelector(`[for="${p.id}"]`)?.innerText:void 0);return F({disabled:E,state:j}),(n,a)=>(s(),i(v(t(S)?.rovingFocus.value?t(x):t(c)),o(n.$attrs,{id:n.id,ref:t(g),role:`checkbox`,"as-child":n.asChild,as:n.as,type:n.as===`button`?`button`:void 0,"aria-checked":t(M)(j.value)?`mixed`:j.value,"aria-required":n.required,"aria-label":n.$attrs[`aria-label`]||L.value,"data-state":t(N)(j.value),"data-disabled":E.value?``:void 0,disabled:E.value,focusable:t(S)?.rovingFocus.value?!E.value:void 0,onKeydown:r(m(()=>{},[`prevent`]),[`enter`]),onClick:P}),{default:u(()=>[y(n.$slots,`default`,{modelValue:t(w),state:j.value}),t(I)&&n.name&&!t(S)?(s(),i(t(b),{key:0,type:`checkbox`,checked:!!j.value,name:n.name,value:n.value,disabled:E.value,required:n.required},null,8,[`checked`,`name`,`value`,`disabled`,`required`])):e(`v-if`,!0)]),_:3},16,[`id`,`as-child`,`as`,`type`,`aria-checked`,`aria-required`,`aria-label`,`data-state`,`data-disabled`,`disabled`,`focusable`,`onKeydown`]))}}),L=l({__name:`CheckboxIndicator`,props:{forceMount:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`span`}},setup(e){let{forwardRef:n}=f(),r=P();return(e,a)=>(s(),i(t(w),{present:e.forceMount||t(M)(t(r).state.value)||t(r).state.value===!0},{default:u(()=>[g(t(c),o({ref:t(n),"data-state":t(N)(t(r).state.value),"data-disabled":t(r).disabled.value?``:void 0,style:{pointerEvents:`none`},"as-child":e.asChild,as:e.as},e.$attrs),{default:u(()=>[y(e.$slots,`default`)]),_:3},16,[`data-state`,`data-disabled`,`as-child`,`as`])]),_:3},8,[`present`]))}}),R=l({__name:`Checkbox`,props:{defaultValue:{},modelValue:{},disabled:{type:Boolean},value:{},id:{},trueValue:{},falseValue:{},asChild:{type:Boolean},as:{},name:{},required:{type:Boolean},class:{type:[Boolean,null,String,Object,Array]}},emits:[`update:modelValue`],setup(e,{emit:r}){let a=e,c=r,l=E(_(a,`class`),c);return(e,r)=>(s(),i(t(I),o({"data-slot":`checkbox`},t(l),{class:t(h)(`border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary aria-invalid:aria-checked:border-primary aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 flex size-4 items-center justify-center rounded-md border transition-colors group-has-disabled/field:opacity-50 focus-visible:ring-3 aria-invalid:ring-3 peer relative shrink-0 outline-none after:absolute after:-inset-x-3 after:-inset-y-2 disabled:cursor-not-allowed disabled:opacity-50`,a.class)}),{default:u(r=>[g(t(L),{"data-slot":`checkbox-indicator`,class:`[&>svg]:size-3.5 grid place-content-center text-current transition-none`},{default:u(()=>[y(e.$slots,`default`,n(p(r)),()=>[g(t(O))])]),_:2},1024)]),_:3},16,[`class`]))}});export{R as t};
|
package/frontend-dist/assets/{CollapsibleContent-DRXTjuF_.js → CollapsibleContent-C0ytCrcq.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{$ as e,Et as t,Gt as n,Ht as r,Jt as i,Lt as a,Q as o,X as s,d as c,dt as l,ft as u,gt as d,i as f,it as p,kt as m,m as h,mt as g,o as _,ot as v,rt as y,yt as b}from"./button-
|
|
1
|
+
import{$ as e,Et as t,Gt as n,Ht as r,Jt as i,Lt as a,Q as o,X as s,d as c,dt as l,ft as u,gt as d,i as f,it as p,kt as m,m as h,mt as g,o as _,ot as v,rt as y,yt as b}from"./button-EcESBjGm.js";import{B as x,J as S,R as C,V as w}from"./index-Dv_nrEfy.js";var[T,E]=S(`CollapsibleRoot`),D=p({__name:`CollapsibleRoot`,props:{defaultOpen:{type:Boolean,required:!1,default:!1},open:{type:Boolean,required:!1,default:void 0},disabled:{type:Boolean,required:!1},unmountOnHide:{type:Boolean,required:!1,default:!0},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},emits:[`update:open`],setup(e,{expose:t,emit:i}){let a=e,s=h(a,`open`,i,{defaultValue:a.defaultOpen,passive:a.open===void 0}),{disabled:c,unmountOnHide:l}=r(a);return E({contentId:``,disabled:c,open:s,unmountOnHide:l,onOpenToggle:()=>{c.value||(s.value=!s.value)}}),t({open:s}),_(),(e,t)=>(d(),o(n(f),{as:e.as,"as-child":a.asChild,"data-state":n(s)?`open`:`closed`,"data-disabled":n(c)?``:void 0},{default:m(()=>[b(e.$slots,`default`,{open:n(s)})]),_:3},8,[`as`,`as-child`,`data-state`,`data-disabled`]))}}),O=p({inheritAttrs:!1,__name:`CollapsibleContent`,props:{forceMount:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},emits:[`contentFound`],setup(r,{emit:i}){let p=r,h=i,v=T();v.contentId||=x(void 0,`reka-collapsible-content`);let S=a(),{forwardRef:w,currentElement:E}=_(),D=a(0),O=a(0),k=s(()=>v.open.value),A=a(k.value),j=a();t(()=>[k.value,S.value?.present],async()=>{await u();let e=E.value;if(!e)return;j.value=j.value||{transitionDuration:e.style.transitionDuration,animationName:e.style.animationName},e.style.transitionDuration=`0s`,e.style.animationName=`none`;let t=e.getBoundingClientRect();O.value=t.height,D.value=t.width,A.value||(e.style.transitionDuration=j.value.transitionDuration,e.style.animationName=j.value.animationName)},{immediate:!0});let M=s(()=>A.value&&v.open.value);return g(()=>{requestAnimationFrame(()=>{A.value=!1})}),c(E,`beforematch`,e=>{requestAnimationFrame(()=>{v.onOpenToggle(),h(`contentFound`)})}),(t,r)=>(d(),o(n(C),{ref_key:`presentRef`,ref:S,present:t.forceMount||n(v).open.value,"force-mount":!0},{default:m(({present:r})=>[y(n(f),l(t.$attrs,{id:n(v).contentId,ref:n(w),"as-child":p.asChild,as:t.as,hidden:r?void 0:n(v).unmountOnHide.value?``:`until-found`,"data-state":M.value?void 0:n(v).open.value?`open`:`closed`,"data-disabled":n(v).disabled?.value?``:void 0,style:{"--reka-collapsible-content-height":`${O.value}px`,"--reka-collapsible-content-width":`${D.value}px`}}),{default:m(()=>[!n(v).unmountOnHide.value||r?b(t.$slots,`default`,{key:0}):e(`v-if`,!0)]),_:2},1040,[`id`,`as-child`,`as`,`hidden`,`data-state`,`data-disabled`,`style`])]),_:3},8,[`present`]))}}),k=p({__name:`Collapsible`,props:{defaultOpen:{type:Boolean},open:{type:Boolean},disabled:{type:Boolean},unmountOnHide:{type:Boolean},asChild:{type:Boolean},as:{}},emits:[`update:open`],setup(e,{emit:t}){let r=w(e,t);return(e,t)=>(d(),o(n(D),l({"data-slot":`collapsible`},n(r)),{default:m(t=>[b(e.$slots,`default`,i(v(t)))]),_:3},16))}}),A=p({__name:`CollapsibleContent`,props:{forceMount:{type:Boolean},asChild:{type:Boolean},as:{}},setup(e){let t=e;return(e,r)=>(d(),o(n(O),l({"data-slot":`collapsible-content`},t),{default:m(()=>[b(e.$slots,`default`)]),_:3},16))}});export{k as n,T as r,A as t};
|
package/frontend-dist/assets/{CollapsibleTrigger-BusSosYR.js → CollapsibleTrigger-C_6qIDNW.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Gt as e,Ht as t,Jt as n,K as r,Lt as i,Q as a,X as o,dt as s,gt as c,i as l,it as u,kt as d,m as f,o as p,ot as m,q as h,r as g,rt as _,x as v,yt as y,zt as b}from"./button-
|
|
1
|
+
import{Gt as e,Ht as t,Jt as n,K as r,Lt as i,Q as a,X as o,dt as s,gt as c,i as l,it as u,kt as d,m as f,o as p,ot as m,q as h,r as g,rt as _,x as v,yt as y,zt as b}from"./button-EcESBjGm.js";import{r as x}from"./CollapsibleContent-C0ytCrcq.js";import{n as S,t as C}from"./RovingFocusItem-CBasI81o.js";import{B as w,H as T,J as E,V as D,W as O}from"./index-Dv_nrEfy.js";var k=u({__name:`CollapsibleTrigger`,props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`button`}},setup(t){let n=t;p();let r=x();return(t,i)=>(c(),a(e(l),{type:t.as===`button`?`button`:void 0,as:t.as,"as-child":n.asChild,"aria-controls":e(r).contentId,"aria-expanded":e(r).open.value,"data-state":e(r).open.value?`open`:`closed`,"data-disabled":e(r).disabled?.value?``:void 0,disabled:e(r).disabled?.value,onClick:e(r).onOpenToggle},{default:d(()=>[y(t.$slots,`default`)]),_:3},8,[`type`,`as`,`as-child`,`aria-controls`,`aria-expanded`,`data-state`,`data-disabled`,`disabled`,`onClick`]))}}),[A,j]=E(`TabsRoot`),M=u({__name:`TabsRoot`,props:{defaultValue:{type:null,required:!1},orientation:{type:String,required:!1,default:`horizontal`},dir:{type:String,required:!1},activationMode:{type:String,required:!1,default:`automatic`},modelValue:{type:null,required:!1},unmountOnHide:{type:Boolean,required:!1,default:!0},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},emits:[`update:modelValue`],setup(n,{emit:r}){let o=n,s=r,{orientation:u,unmountOnHide:m,dir:h}=t(o),g=O(h);p();let _=f(o,`modelValue`,s,{defaultValue:o.defaultValue,passive:o.modelValue===void 0}),v=i(),x=b(new Set);return j({modelValue:_,changeModelValue:e=>{_.value=e},orientation:u,dir:g,unmountOnHide:m,activationMode:o.activationMode,baseId:w(void 0,`reka-tabs`),tabsList:v,contentIds:x,registerContent:e=>{x.value=new Set([...x.value,e])},unregisterContent:e=>{let t=new Set(x.value);t.delete(e),x.value=t}}),(t,n)=>(c(),a(e(l),{dir:e(g),"data-orientation":e(u),"as-child":t.asChild,as:t.as},{default:d(()=>[y(t.$slots,`default`,{modelValue:e(_)})]),_:3},8,[`dir`,`data-orientation`,`as-child`,`as`]))}});function N(e,t){return`${e}-trigger-${t}`}function P(e,t){return`${e}-content-${t}`}var F=u({__name:`TabsList`,props:{loop:{type:Boolean,required:!1,default:!0},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},setup(n){let{loop:r}=t(n),{forwardRef:i,currentElement:o}=p(),s=A();return s.tabsList=o,(t,n)=>(c(),a(e(S),{"as-child":``,orientation:e(s).orientation.value,dir:e(s).dir.value,loop:e(r)},{default:d(()=>[_(e(l),{ref:e(i),role:`tablist`,"as-child":t.asChild,as:t.as,"aria-orientation":e(s).orientation.value},{default:d(()=>[y(t.$slots,`default`)]),_:3},8,[`as-child`,`as`,`aria-orientation`])]),_:3},8,[`orientation`,`dir`,`loop`]))}}),I=u({__name:`TabsTrigger`,props:{value:{type:[String,Number],required:!0},disabled:{type:Boolean,required:!1,default:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`button`}},setup(t){let n=t,{forwardRef:i}=p(),s=A(),u=o(()=>N(s.baseId,n.value)),f=o(()=>s.contentIds.value.has(n.value)?P(s.baseId,n.value):void 0),m=o(()=>n.value===s.modelValue.value);return(t,n)=>(c(),a(e(C),{"as-child":``,focusable:!t.disabled,active:m.value},{default:d(()=>[_(e(l),{id:u.value,ref:e(i),role:`tab`,type:t.as===`button`?`button`:void 0,as:t.as,"as-child":t.asChild,"aria-selected":m.value?`true`:`false`,"aria-controls":f.value,"data-state":m.value?`active`:`inactive`,disabled:t.disabled,"data-disabled":t.disabled?``:void 0,"data-orientation":e(s).orientation.value,onMousedown:n[0]||=h(n=>{!t.disabled&&n.ctrlKey===!1?e(s).changeModelValue(t.value):n.preventDefault()},[`left`]),onKeydown:n[1]||=r(n=>e(s).changeModelValue(t.value),[`enter`,`space`]),onFocus:n[2]||=()=>{let n=e(s).activationMode!==`manual`;!m.value&&!t.disabled&&n&&e(s).changeModelValue(t.value)}},{default:d(()=>[y(t.$slots,`default`)]),_:3},8,[`id`,`type`,`as`,`as-child`,`aria-selected`,`aria-controls`,`data-state`,`disabled`,`data-disabled`,`data-orientation`])]),_:3},8,[`focusable`,`active`]))}}),L=u({__name:`Tabs`,props:{defaultValue:{},orientation:{},dir:{},activationMode:{},modelValue:{},unmountOnHide:{type:Boolean},asChild:{type:Boolean},as:{},class:{type:[Boolean,null,String,Object,Array]}},emits:[`update:modelValue`],setup(t,{emit:r}){let i=t,o=r,l=D(v(i,`class`),o);return(t,r)=>(c(),a(e(M),s({"data-slot":`tabs`,"data-orientation":e(l).orientation||`horizontal`},e(l),{class:e(g)(`gap-2 group/tabs flex data-[orientation=horizontal]:flex-col`,i.class)}),{default:d(e=>[y(t.$slots,`default`,n(m(e)))]),_:3},16,[`data-orientation`,`class`]))}}),R=u({__name:`TabsList`,props:{loop:{type:Boolean},asChild:{type:Boolean},as:{},class:{type:[Boolean,null,String,Object,Array]},variant:{default:`default`}},setup(t){let n=t,r=v(n,`class`,`variant`);return(i,o)=>(c(),a(e(F),s({"data-slot":`tabs-list`,"data-variant":t.variant},e(r),{class:e(g)(`rounded-lg p-[3px] group-data-[orientation=horizontal]/tabs:h-8 data-[variant=line]:rounded-none group/tabs-list inline-flex w-fit items-center justify-center text-muted-foreground group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col`,t.variant===`default`&&`bg-muted`,t.variant===`line`&&`gap-1 bg-transparent`,n.class)}),{default:d(()=>[y(i.$slots,`default`)]),_:3},16,[`data-variant`,`class`]))}}),z=u({__name:`TabsTrigger`,props:{value:{},disabled:{type:Boolean},asChild:{type:Boolean},as:{},class:{type:[Boolean,null,String,Object,Array]}},setup(t){let n=t,r=T(v(n,`class`));return(t,i)=>(c(),a(e(I),s({"data-slot":`tabs-trigger`,class:e(g)(`gap-1.5 rounded-md border border-transparent px-1.5 py-0.5 text-sm font-medium group-data-[variant=default]/tabs-list:data-[state=active]:shadow-sm group-data-[variant=line]/tabs-list:data-[state=active]:shadow-none [&_svg:not([class*=size-])]:size-4 has-data-[icon=inline-end]:pr-1 has-data-[icon=inline-start]:pl-1 relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center whitespace-nowrap text-foreground/60 transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1 focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50 dark:text-muted-foreground dark:hover:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0`,`group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:border-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent`,`data-[state=active]:bg-background data-[state=active]:text-foreground dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 dark:data-[state=active]:text-foreground`,`after:absolute after:bg-foreground after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-[state=active]:after:opacity-100`,n.class)},e(r)),{default:d(()=>[y(t.$slots,`default`)]),_:3},16,[`class`]))}}),B=u({__name:`CollapsibleTrigger`,props:{asChild:{type:Boolean},as:{}},setup(t){let n=t;return(t,r)=>(c(),a(e(k),s({"data-slot":`collapsible-trigger`},n),{default:d(()=>[y(t.$slots,`default`)]),_:3},16))}});export{P as a,L as i,z as n,N as o,R as r,A as s,B as t};
|