dsh-connect-trae 4.4.4 → 4.4.5
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/CHANGELOG.md +112 -4
- package/lib/client.js +544 -71
- package/lib/index.d.ts +341 -2
- package/lib/index.js +500 -65
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -3513,6 +3513,182 @@ function identityHeaders(identity) {
|
|
|
3513
3513
|
};
|
|
3514
3514
|
}
|
|
3515
3515
|
//#endregion
|
|
3516
|
+
//#region src/model-order.ts
|
|
3517
|
+
/**
|
|
3518
|
+
* Wire name of the default SOLO chat function.
|
|
3519
|
+
*
|
|
3520
|
+
* Lives here rather than in `solo.ts` so this module stays importable from the
|
|
3521
|
+
* client; `solo.ts` re-exports it, so there is still exactly one definition.
|
|
3522
|
+
*/
|
|
3523
|
+
const TRAE_SOLO_FUNCTION = "solo_work_lite";
|
|
3524
|
+
/**
|
|
3525
|
+
* The chat functions of one region, in PRIORITY order.
|
|
3526
|
+
*
|
|
3527
|
+
* Two consumers read it, and both mean "priority", which is why they can share
|
|
3528
|
+
* one array: the wire asks these functions in order and the first to list a
|
|
3529
|
+
* config owns it (`solo.ts`), and the card draws the groups in the same order so
|
|
3530
|
+
* the row a user sees first is the one the resolver prefers.
|
|
3531
|
+
*/
|
|
3532
|
+
const TRAE_CHANNEL_PRIORITY = {
|
|
3533
|
+
cn: [
|
|
3534
|
+
"solo_work_remote",
|
|
3535
|
+
TRAE_SOLO_FUNCTION,
|
|
3536
|
+
"solo_agent_remote",
|
|
3537
|
+
"chat_v3",
|
|
3538
|
+
"solo_coder"
|
|
3539
|
+
],
|
|
3540
|
+
ai: [
|
|
3541
|
+
"solo_work_remote",
|
|
3542
|
+
TRAE_SOLO_FUNCTION,
|
|
3543
|
+
"solo_agent_remote",
|
|
3544
|
+
"chat_v3"
|
|
3545
|
+
]
|
|
3546
|
+
};
|
|
3547
|
+
/**
|
|
3548
|
+
* Rank of one channel inside the region's priority list.
|
|
3549
|
+
*
|
|
3550
|
+
* Three cases, and the order between them is deliberate:
|
|
3551
|
+
*
|
|
3552
|
+
* - a known chat channel: its index in the priority list;
|
|
3553
|
+
* - an UNKNOWN channel name (a function the region does not call through —
|
|
3554
|
+
* `withChatCallableFunctions` clears those, so this is a defensive branch):
|
|
3555
|
+
* after every known channel, then alphabetically among themselves;
|
|
3556
|
+
* - NO channel at all (a row demoted to the default chat function): last. Such
|
|
3557
|
+
* a row is the one the resolver knows least about, so it must not push a
|
|
3558
|
+
* properly attributed row down the list.
|
|
3559
|
+
*/
|
|
3560
|
+
function channelRank(channel, priority) {
|
|
3561
|
+
if (channel === void 0 || channel === "") return priority.length + 1;
|
|
3562
|
+
const known = priority.indexOf(channel);
|
|
3563
|
+
return known === -1 ? priority.length : known;
|
|
3564
|
+
}
|
|
3565
|
+
/**
|
|
3566
|
+
* Compare two display names the way a person reading a model list expects:
|
|
3567
|
+
* case-insensitively, with embedded numbers compared as NUMBERS, so `GLM-5.10`
|
|
3568
|
+
* sorts after `GLM-5.9`. Plain text comparison puts `5.10` first, which reads as
|
|
3569
|
+
* a bug to anyone who sees the version numbers.
|
|
3570
|
+
*/
|
|
3571
|
+
function compareNames(left, right) {
|
|
3572
|
+
const byName = left.trim().localeCompare(right.trim(), void 0, {
|
|
3573
|
+
numeric: true,
|
|
3574
|
+
sensitivity: "base"
|
|
3575
|
+
});
|
|
3576
|
+
return byName !== 0 ? byName : left.localeCompare(right);
|
|
3577
|
+
}
|
|
3578
|
+
/**
|
|
3579
|
+
* The catalog in display order: channel priority first, then name.
|
|
3580
|
+
*
|
|
3581
|
+
* Total and stable — ties fall through to `id`, so two rows with the same name
|
|
3582
|
+
* in the same channel still get one fixed order rather than the order they
|
|
3583
|
+
* arrived in.
|
|
3584
|
+
*/
|
|
3585
|
+
function orderTraeModels(rows, region = "cn") {
|
|
3586
|
+
const priority = TRAE_CHANNEL_PRIORITY[region] ?? TRAE_CHANNEL_PRIORITY.cn;
|
|
3587
|
+
return [...rows].sort((left, right) => {
|
|
3588
|
+
const byRank = channelRank(left.wireFunction, priority) - channelRank(right.wireFunction, priority);
|
|
3589
|
+
if (byRank !== 0) return byRank;
|
|
3590
|
+
if (left.wireFunction !== right.wireFunction) return (left.wireFunction ?? "").localeCompare(right.wireFunction ?? "");
|
|
3591
|
+
const byName = compareNames(left.name, right.name);
|
|
3592
|
+
return byName !== 0 ? byName : left.id.localeCompare(right.id);
|
|
3593
|
+
});
|
|
3594
|
+
}
|
|
3595
|
+
/**
|
|
3596
|
+
* Split rows into channel groups, in display order.
|
|
3597
|
+
*
|
|
3598
|
+
* Ordering is re-applied here rather than trusted from the caller: a group list
|
|
3599
|
+
* built from an unsorted input would put the groups in arrival order, which is
|
|
3600
|
+
* the exact instability this module exists to remove.
|
|
3601
|
+
*/
|
|
3602
|
+
function groupTraeModels(rows, region = "cn") {
|
|
3603
|
+
const groups = [];
|
|
3604
|
+
const byChannel = /* @__PURE__ */ new Map();
|
|
3605
|
+
for (const row of orderTraeModels(rows, region)) {
|
|
3606
|
+
const channel = row.wireFunction === "" ? void 0 : row.wireFunction;
|
|
3607
|
+
const key = channel ?? "\0default";
|
|
3608
|
+
const existing = byChannel.get(key);
|
|
3609
|
+
if (existing !== void 0) {
|
|
3610
|
+
existing.rows.push(row);
|
|
3611
|
+
continue;
|
|
3612
|
+
}
|
|
3613
|
+
const group = {
|
|
3614
|
+
channel,
|
|
3615
|
+
rows: [row]
|
|
3616
|
+
};
|
|
3617
|
+
byChannel.set(key, group);
|
|
3618
|
+
groups.push(group);
|
|
3619
|
+
}
|
|
3620
|
+
return groups;
|
|
3621
|
+
}
|
|
3622
|
+
/**
|
|
3623
|
+
* Does one row match a search query?
|
|
3624
|
+
*
|
|
3625
|
+
* Matches the display name, the display id and the WIRE config name — the last
|
|
3626
|
+
* one because a user debugging a `4001 config_name rejected` arrives with the
|
|
3627
|
+
* upstream name in hand, and the two differ exactly on the rows that carry a
|
|
3628
|
+
* suffix (`DeepSeek-V4-Flash` vs `DeepSeek-V4-Flash-Official`).
|
|
3629
|
+
*/
|
|
3630
|
+
function traeModelMatchesQuery(model, query) {
|
|
3631
|
+
const needle = query.trim().toLowerCase();
|
|
3632
|
+
if (needle === "") return true;
|
|
3633
|
+
if (model.name.toLowerCase().includes(needle)) return true;
|
|
3634
|
+
if (model.id.toLowerCase().includes(needle)) return true;
|
|
3635
|
+
return (model.wireConfigName ?? "").toLowerCase().includes(needle);
|
|
3636
|
+
}
|
|
3637
|
+
/** Filter by {@link traeModelMatchesQuery}, preserving order. */
|
|
3638
|
+
function filterTraeModels(rows, query) {
|
|
3639
|
+
if (query.trim() === "") return [...rows];
|
|
3640
|
+
return rows.filter((row) => traeModelMatchesQuery(row, query));
|
|
3641
|
+
}
|
|
3642
|
+
/**
|
|
3643
|
+
* The channels a NORMAL Trae chat session actually runs on: the `solo_work_*`
|
|
3644
|
+
* family, i.e. the panel's own chat modes.
|
|
3645
|
+
*
|
|
3646
|
+
* Deliberately not "every channel we can call". After issue #52 P1 the catalog
|
|
3647
|
+
* is 34 rows and 10 of them are reachable only through a SPECIALIST channel:
|
|
3648
|
+
* `solo_coder` (7: `Doubao-Seed-2.0-Code`, `glm-5.1`, `glm-5v-turbo`,
|
|
3649
|
+
* `kimi-k2.5`, `minimax-m2.7`, `qwen-3.5`, `qwen-3.6-plus`), `chat_v3` (2:
|
|
3650
|
+
* `kimi-k2.8-preview`, `qwen3.8-flash`) and `solo_agent_remote` (1:
|
|
3651
|
+
* `Doubao-Seed-Code`). Measured 2026-10-23 on a live CN account. Those rows work
|
|
3652
|
+
* — that is why P1 kept them — but they are not what Trae's main chat offers,
|
|
3653
|
+
* and mixing them into the default view is exactly the "a code model answering a
|
|
3654
|
+
* solo request" shape issue #52 asked about.
|
|
3655
|
+
*/
|
|
3656
|
+
const TRAE_COMMON_FUNCTIONS = {
|
|
3657
|
+
cn: ["solo_work_remote", TRAE_SOLO_FUNCTION],
|
|
3658
|
+
ai: ["solo_work_remote", TRAE_SOLO_FUNCTION]
|
|
3659
|
+
};
|
|
3660
|
+
/**
|
|
3661
|
+
* The function a request for this row will NAME.
|
|
3662
|
+
*
|
|
3663
|
+
* A row with no `wireFunction` is not "unknown to the wire": the bridge sends
|
|
3664
|
+
* the region default (`TRAE_SOLO_FUNCTION`), so for every question about where
|
|
3665
|
+
* the turn goes, the default is the answer. The distinction still matters for
|
|
3666
|
+
* DISPLAY (`groupTraeModels` keeps these in their own group, because their
|
|
3667
|
+
* provenance — which directory group advertised them — really is unknown), but
|
|
3668
|
+
* not for scope: a `solo_work_lite` turn is a normal chat turn either way.
|
|
3669
|
+
*/
|
|
3670
|
+
function traeModelCallChannel(model) {
|
|
3671
|
+
const channel = model.wireFunction;
|
|
3672
|
+
return channel === void 0 || channel === "" ? TRAE_SOLO_FUNCTION : channel;
|
|
3673
|
+
}
|
|
3674
|
+
/**
|
|
3675
|
+
* Does this row belong to the view?
|
|
3676
|
+
*
|
|
3677
|
+
* Judged on {@link traeModelCallChannel}, never on `wireFunction` directly:
|
|
3678
|
+
* otherwise the one row without a function (`doubao_1_8`, measured 2026-10-23)
|
|
3679
|
+
* would fall OUT of the common view while being called through exactly the
|
|
3680
|
+
* common channel it belongs to.
|
|
3681
|
+
*/
|
|
3682
|
+
function traeModelInView(model, view, region = "cn") {
|
|
3683
|
+
if (view === "all") return true;
|
|
3684
|
+
return (TRAE_COMMON_FUNCTIONS[region] ?? TRAE_COMMON_FUNCTIONS.cn).includes(traeModelCallChannel(model));
|
|
3685
|
+
}
|
|
3686
|
+
/** Keep the rows a view asks for, preserving order. */
|
|
3687
|
+
function scopeTraeModels(rows, view, region = "cn") {
|
|
3688
|
+
if (view === "all") return [...rows];
|
|
3689
|
+
return rows.filter((row) => traeModelInView(row, view, region));
|
|
3690
|
+
}
|
|
3691
|
+
//#endregion
|
|
3516
3692
|
//#region src/shim.ts
|
|
3517
3693
|
const BODY_LIMIT = 67108864;
|
|
3518
3694
|
const LOOPBACK_HOSTS = /* @__PURE__ */ new Set([
|
|
@@ -3772,6 +3948,48 @@ function createTraeShim(options) {
|
|
|
3772
3948
|
};
|
|
3773
3949
|
}
|
|
3774
3950
|
//#endregion
|
|
3951
|
+
//#region src/model-detail.ts
|
|
3952
|
+
const TRAE_MODEL_DETAIL_PATH = "/api/ide/v1/batch_get_detail_param";
|
|
3953
|
+
const TRAE_MODEL_DETAIL_FUNCTIONS = [
|
|
3954
|
+
"ui_builder_v2",
|
|
3955
|
+
"solo_coder",
|
|
3956
|
+
"chat_v3",
|
|
3957
|
+
"solo_builder",
|
|
3958
|
+
"builder_v3",
|
|
3959
|
+
"builder",
|
|
3960
|
+
"chat",
|
|
3961
|
+
"inline_chat",
|
|
3962
|
+
"git_ai",
|
|
3963
|
+
"custom_agent_generation",
|
|
3964
|
+
"utils",
|
|
3965
|
+
"code_reviewer",
|
|
3966
|
+
"code_review_summary",
|
|
3967
|
+
"solo_agent",
|
|
3968
|
+
"solo_agent_remote",
|
|
3969
|
+
"solo_work_remote",
|
|
3970
|
+
"solo_agent_lite",
|
|
3971
|
+
"solo_work_lite",
|
|
3972
|
+
"solo_design_lite",
|
|
3973
|
+
"solo_design_remote",
|
|
3974
|
+
"multimodal",
|
|
3975
|
+
"system_diagnosis"
|
|
3976
|
+
];
|
|
3977
|
+
/** Build the exact request shape observed in successful current Trae CN logs. */
|
|
3978
|
+
function buildTraeModelDetailRequest(configName = "", custom = false) {
|
|
3979
|
+
return {
|
|
3980
|
+
functions: [...TRAE_MODEL_DETAIL_FUNCTIONS],
|
|
3981
|
+
agent_type: configName === "" ? "" : "solo_agent",
|
|
3982
|
+
current_config_info: {
|
|
3983
|
+
config_name: configName,
|
|
3984
|
+
is_custom_model: custom
|
|
3985
|
+
},
|
|
3986
|
+
mode_type: 0,
|
|
3987
|
+
access_type: 0,
|
|
3988
|
+
ab_force_vids: "",
|
|
3989
|
+
ab_autotest_advanced_mode: 0
|
|
3990
|
+
};
|
|
3991
|
+
}
|
|
3992
|
+
//#endregion
|
|
3775
3993
|
//#region src/protocol.ts
|
|
3776
3994
|
const TRAE_CN_AGENT_TASK_PATH = "/api/agent/v3/create_agent_task";
|
|
3777
3995
|
const TRAE_CN_TITLE_PATH = "/api/agent/v3/llm_utils_chat";
|
|
@@ -3875,6 +4093,231 @@ function traeEndpoint(baseUrl, path) {
|
|
|
3875
4093
|
return `${baseUrl.replace(/\/$/, "")}/${path.replace(/^\//, "")}`;
|
|
3876
4094
|
}
|
|
3877
4095
|
//#endregion
|
|
4096
|
+
//#region src/official-roster.ts
|
|
4097
|
+
const CHAT_USAGE = "chat_completion";
|
|
4098
|
+
/**
|
|
4099
|
+
* Parse a `batch_get_detail_param` answer into a per-(config, function) index.
|
|
4100
|
+
*
|
|
4101
|
+
* Tolerant on purpose: this document is 1.8 MB of upstream-owned shape
|
|
4102
|
+
* (`function_configs[] → config_info_list[] → model_detail_list[]`), and the
|
|
4103
|
+
* plugin must not lose the whole refresh because one nested field changed
|
|
4104
|
+
* spelling. Rows that cannot be read are skipped; a document with no
|
|
4105
|
+
* `function_configs` at all yields an empty roster, which the filter reads as
|
|
4106
|
+
* "nothing to say" rather than "hide everything".
|
|
4107
|
+
*
|
|
4108
|
+
* Duplicate pairs are collapsed first-wins, matching the rest of the catalog's
|
|
4109
|
+
* convention (`mergeTraeModelSources`). Two functions can both list a config,
|
|
4110
|
+
* and those are DIFFERENT pairs, so both are kept.
|
|
4111
|
+
*/
|
|
4112
|
+
function parseTraeOfficialRoster(payload) {
|
|
4113
|
+
const channels = /* @__PURE__ */ new Map();
|
|
4114
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4115
|
+
let pairs = 0;
|
|
4116
|
+
const document = typeof payload === "object" && payload !== null ? payload : {};
|
|
4117
|
+
const groups = Array.isArray(document["function_configs"]) ? document["function_configs"] : [];
|
|
4118
|
+
for (const group of groups) {
|
|
4119
|
+
if (typeof group !== "object" || group === null) continue;
|
|
4120
|
+
const record = group;
|
|
4121
|
+
const functionName = typeof record["function"] === "string" ? record["function"] : "";
|
|
4122
|
+
if (functionName === "") continue;
|
|
4123
|
+
const list = Array.isArray(record["config_info_list"]) ? record["config_info_list"] : [];
|
|
4124
|
+
for (const item of list) {
|
|
4125
|
+
if (typeof item !== "object" || item === null) continue;
|
|
4126
|
+
const config = item;
|
|
4127
|
+
const configName = typeof config["config_name"] === "string" ? config["config_name"].trim() : "";
|
|
4128
|
+
if (configName === "") continue;
|
|
4129
|
+
const key = `${functionName}\u0000${configName.toLowerCase()}`;
|
|
4130
|
+
if (seen.has(key)) continue;
|
|
4131
|
+
seen.add(key);
|
|
4132
|
+
const channel = {
|
|
4133
|
+
function: functionName,
|
|
4134
|
+
usage: typeof config["usage"] === "string" ? config["usage"] : "",
|
|
4135
|
+
enabled: config["config_switch"] !== false,
|
|
4136
|
+
invisible: config["is_invisible_to_user"] === true
|
|
4137
|
+
};
|
|
4138
|
+
pairs += 1;
|
|
4139
|
+
const bucket = channels.get(configName.toLowerCase());
|
|
4140
|
+
if (bucket === void 0) channels.set(configName.toLowerCase(), [channel]);
|
|
4141
|
+
else bucket.push(channel);
|
|
4142
|
+
}
|
|
4143
|
+
}
|
|
4144
|
+
return {
|
|
4145
|
+
channels,
|
|
4146
|
+
size: {
|
|
4147
|
+
configs: channels.size,
|
|
4148
|
+
pairs
|
|
4149
|
+
}
|
|
4150
|
+
};
|
|
4151
|
+
}
|
|
4152
|
+
/** The `config_name` a catalog row would actually send (see `wireConfigName`). */
|
|
4153
|
+
function officialKeyOf(model) {
|
|
4154
|
+
return (model.wireConfigName ?? model.id).trim().toLowerCase();
|
|
4155
|
+
}
|
|
4156
|
+
/**
|
|
4157
|
+
* Decide one row from the roster.
|
|
4158
|
+
*
|
|
4159
|
+
* `chatFunctions` is the region's own `TRAE_DIRECTORY_FUNCTIONS` list, in
|
|
4160
|
+
* priority order: only those functions can carry a VERDICT, because only those
|
|
4161
|
+
* are functions `llm_utils_chat` accepts. A config the vendor shows under
|
|
4162
|
+
* `code_review_summary` alone is not offered as a chat model at all — that is
|
|
4163
|
+
* exactly the `glm-4.7` case, and it is a "hide", not a "re-pin".
|
|
4164
|
+
*
|
|
4165
|
+
* The verdict is `keep` when the roster cannot speak: no entry for the config
|
|
4166
|
+
* (measured 2026-10-23: `kimi-k2.8-preview` and `qwen3.8-flash` exist only in
|
|
4167
|
+
* the Remote directory's `chat_v3` group), only tool rows (`usage: 'summary'`,
|
|
4168
|
+
* `fast_apply`, …), or no chat function at all. Silence is never a verdict.
|
|
4169
|
+
*/
|
|
4170
|
+
function officialVerdictOf(model, roster, chatFunctions) {
|
|
4171
|
+
const entries = roster.channels.get(officialKeyOf(model));
|
|
4172
|
+
if (entries === void 0 || entries.length === 0) return { kind: "keep" };
|
|
4173
|
+
const callable = entries.filter((entry) => entry.usage === "" || entry.usage === CHAT_USAGE).filter((entry) => chatFunctions.includes(entry.function));
|
|
4174
|
+
if (callable.length === 0) return { kind: "keep" };
|
|
4175
|
+
const listedBy = callable.map((entry) => entry.function);
|
|
4176
|
+
const shown = callable.filter((entry) => !entry.invisible);
|
|
4177
|
+
if (shown.length === 0) return {
|
|
4178
|
+
kind: "hide",
|
|
4179
|
+
function: model.wireFunction,
|
|
4180
|
+
listedBy
|
|
4181
|
+
};
|
|
4182
|
+
const own = model.wireFunction === void 0 ? void 0 : callable.find((entry) => entry.function === model.wireFunction);
|
|
4183
|
+
if (own !== void 0 && !own.invisible) return { kind: "keep" };
|
|
4184
|
+
const to = chatFunctions.find((fn) => shown.some((entry) => entry.function === fn));
|
|
4185
|
+
if (to === void 0) return { kind: "keep" };
|
|
4186
|
+
return {
|
|
4187
|
+
kind: "repin",
|
|
4188
|
+
from: model.wireFunction,
|
|
4189
|
+
to,
|
|
4190
|
+
listedBy
|
|
4191
|
+
};
|
|
4192
|
+
}
|
|
4193
|
+
/**
|
|
4194
|
+
* Apply the roster: retire what no chat function offers any more, and re-pin
|
|
4195
|
+
* what the vendor offers under a different channel.
|
|
4196
|
+
*
|
|
4197
|
+
* FAIL-OPEN BY CONSTRUCTION, which is the whole safety argument for applying
|
|
4198
|
+
* this by default:
|
|
4199
|
+
*
|
|
4200
|
+
* - `undefined` roster (transport failure, restricted network, a credential
|
|
4201
|
+
* that cannot read the IDE document) keeps EVERY row. A refresh must never
|
|
4202
|
+
* lose models because a second, optional endpoint was unreachable.
|
|
4203
|
+
* - `keep` covers every ambiguity — no entry, tool-only entries, a channel the
|
|
4204
|
+
* roster does not name. Only an explicit "the vendor shows this nowhere we
|
|
4205
|
+
* can call it" removes a row.
|
|
4206
|
+
* - `config_switch === false` alone does NOT remove a row: the flag is
|
|
4207
|
+
* recorded on {@link TraeOfficialChannel} but not used as a verdict, because
|
|
4208
|
+
* its semantics are unmeasured and "disabled" there may describe a function
|
|
4209
|
+
* override rather than the model itself.
|
|
4210
|
+
*
|
|
4211
|
+
* This is deliberately NOT "match the Trae client": the client renders one
|
|
4212
|
+
* function, the plugin serves the union, and issue #46's reporter wants the
|
|
4213
|
+
* dated snapshots the union carries. What changes here is only the class where
|
|
4214
|
+
* the union is provably wrong — twelve retired configs that made up the reported
|
|
4215
|
+
* "tail of old models", plus rows pinned to a channel their own vendor hides
|
|
4216
|
+
* them on (the "code model on a solo channel" risk of issue #52).
|
|
4217
|
+
*/
|
|
4218
|
+
function applyOfficialRoster(rows, roster, chatFunctions) {
|
|
4219
|
+
if (roster === void 0) return {
|
|
4220
|
+
rows: [...rows],
|
|
4221
|
+
hidden: [],
|
|
4222
|
+
repinned: []
|
|
4223
|
+
};
|
|
4224
|
+
const kept = [];
|
|
4225
|
+
const hidden = [];
|
|
4226
|
+
const repinned = [];
|
|
4227
|
+
for (const row of rows) {
|
|
4228
|
+
const verdict = officialVerdictOf(row, roster, chatFunctions);
|
|
4229
|
+
if (verdict.kind === "hide") {
|
|
4230
|
+
hidden.push({
|
|
4231
|
+
id: row.id,
|
|
4232
|
+
function: verdict.function
|
|
4233
|
+
});
|
|
4234
|
+
continue;
|
|
4235
|
+
}
|
|
4236
|
+
if (verdict.kind === "repin") {
|
|
4237
|
+
repinned.push({
|
|
4238
|
+
id: row.id,
|
|
4239
|
+
from: verdict.from,
|
|
4240
|
+
to: verdict.to
|
|
4241
|
+
});
|
|
4242
|
+
kept.push({
|
|
4243
|
+
...row,
|
|
4244
|
+
wireFunction: verdict.to
|
|
4245
|
+
});
|
|
4246
|
+
continue;
|
|
4247
|
+
}
|
|
4248
|
+
kept.push(row);
|
|
4249
|
+
}
|
|
4250
|
+
return {
|
|
4251
|
+
rows: kept,
|
|
4252
|
+
hidden,
|
|
4253
|
+
repinned
|
|
4254
|
+
};
|
|
4255
|
+
}
|
|
4256
|
+
/** How long one successful roster read stays usable, in milliseconds. */
|
|
4257
|
+
const ROSTER_CACHE_MS = 6e5;
|
|
4258
|
+
/** Timeout for the roster read. It is an OPTIONAL signal; it must not stall a refresh. */
|
|
4259
|
+
const ROSTER_TIMEOUT_MS = 2e4;
|
|
4260
|
+
/**
|
|
4261
|
+
* Reads the IDE's roster once per cache window and never throws.
|
|
4262
|
+
*
|
|
4263
|
+
* `undefined` is a first-class answer: it is what a caller sees when the
|
|
4264
|
+
* document could not be read, and {@link applyOfficialRoster} treats it as "no
|
|
4265
|
+
* opinion". Silence on failure is intentional — this is a refinement of a
|
|
4266
|
+
* refresh that already succeeded, so a strict error would turn a usable catalog
|
|
4267
|
+
* into a failed refresh.
|
|
4268
|
+
*/
|
|
4269
|
+
var TraeOfficialRosterClient = class {
|
|
4270
|
+
options;
|
|
4271
|
+
fetchImpl;
|
|
4272
|
+
now;
|
|
4273
|
+
cached;
|
|
4274
|
+
/** The last failure, so a repeatedly-broken endpoint is not re-probed on every refresh. */
|
|
4275
|
+
failedAt;
|
|
4276
|
+
constructor(options) {
|
|
4277
|
+
this.options = options;
|
|
4278
|
+
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
4279
|
+
this.now = options.now ?? Date.now;
|
|
4280
|
+
}
|
|
4281
|
+
/** Cached roster, without any network I/O. */
|
|
4282
|
+
cachedRoster() {
|
|
4283
|
+
return this.cached === void 0 ? void 0 : this.cached.roster;
|
|
4284
|
+
}
|
|
4285
|
+
async fetch(signal) {
|
|
4286
|
+
const now = this.now();
|
|
4287
|
+
if (this.cached !== void 0 && now - this.cached.at < ROSTER_CACHE_MS) return this.cached.roster;
|
|
4288
|
+
if (this.failedAt !== void 0 && now - this.failedAt < ROSTER_CACHE_MS) return void 0;
|
|
4289
|
+
try {
|
|
4290
|
+
const [credential, identity] = await Promise.all([this.options.credential(), this.options.identity()]);
|
|
4291
|
+
const region = regionOfCredential(credential);
|
|
4292
|
+
const base = this.options.baseUrl ?? (this.options.route === "enterprise" ? "https://console.enterprise.trae.cn" : REGION_GATEWAYS[region].chat);
|
|
4293
|
+
const response = await this.fetchImpl(traeEndpoint(base, TRAE_MODEL_DETAIL_PATH), {
|
|
4294
|
+
method: "POST",
|
|
4295
|
+
headers: buildTraeCnHeaders(credential, identity, { profile: "model-detail" }),
|
|
4296
|
+
body: JSON.stringify({
|
|
4297
|
+
...buildTraeModelDetailRequest(""),
|
|
4298
|
+
show_custom_model: true
|
|
4299
|
+
}),
|
|
4300
|
+
signal: signal ?? AbortSignal.timeout(ROSTER_TIMEOUT_MS)
|
|
4301
|
+
});
|
|
4302
|
+
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
4303
|
+
const roster = parseTraeOfficialRoster(await response.json());
|
|
4304
|
+
if (roster.size.configs === 0) throw new Error("roster document carried no config_name");
|
|
4305
|
+
this.cached = {
|
|
4306
|
+
at: now,
|
|
4307
|
+
roster
|
|
4308
|
+
};
|
|
4309
|
+
this.failedAt = void 0;
|
|
4310
|
+
return roster;
|
|
4311
|
+
} catch (error) {
|
|
4312
|
+
this.failedAt = now;
|
|
4313
|
+
this.options.log?.("dsh-connect-trae: IDE model roster unavailable, keeping every discovered row", { reason: error instanceof Error ? error.message : String(error) });
|
|
4314
|
+
return;
|
|
4315
|
+
}
|
|
4316
|
+
}
|
|
4317
|
+
};
|
|
4318
|
+
/** Where the client asks for the roster; re-exported so diagnostics do not hard-code it. */
|
|
4319
|
+
const TRAE_OFFICIAL_ROSTER_PATH = TRAE_MODEL_DETAIL_PATH;
|
|
4320
|
+
//#endregion
|
|
3878
4321
|
//#region src/raw-chat.ts
|
|
3879
4322
|
const TRAE_RAW_CHAT_V2_PATH = "/api/ide/v2/llm_raw_chat";
|
|
3880
4323
|
const TRAE_RAW_CHAT_V1_PATH = "/api/ide/v1/llm_raw_chat";
|
|
@@ -4138,7 +4581,6 @@ function applyReasoningEffort(body, effort, capability) {
|
|
|
4138
4581
|
}
|
|
4139
4582
|
//#endregion
|
|
4140
4583
|
//#region src/solo.ts
|
|
4141
|
-
const TRAE_SOLO_FUNCTION = "solo_work_lite";
|
|
4142
4584
|
/**
|
|
4143
4585
|
* `llm_utils_chat` functions to union per region, in priority order.
|
|
4144
4586
|
*
|
|
@@ -4202,22 +4644,12 @@ const TRAE_SOLO_FUNCTION = "solo_work_lite";
|
|
|
4202
4644
|
* A model in NO chat function's roster is still left to the merge: it ships
|
|
4203
4645
|
* with no wire target and its call fails with a readable upstream message
|
|
4204
4646
|
* rather than being hidden (see mergeTraeModelSources).
|
|
4647
|
+
*
|
|
4648
|
+
* The list itself lives in {@link TRAE_CHANNEL_PRIORITY} (`model-order.ts`) and
|
|
4649
|
+
* is aliased here, not copied: the card groups its rows by these same names in
|
|
4650
|
+
* this same order.
|
|
4205
4651
|
*/
|
|
4206
|
-
const TRAE_DIRECTORY_FUNCTIONS =
|
|
4207
|
-
cn: [
|
|
4208
|
-
"solo_work_remote",
|
|
4209
|
-
TRAE_SOLO_FUNCTION,
|
|
4210
|
-
"solo_agent_remote",
|
|
4211
|
-
"chat_v3",
|
|
4212
|
-
"solo_coder"
|
|
4213
|
-
],
|
|
4214
|
-
ai: [
|
|
4215
|
-
"solo_work_remote",
|
|
4216
|
-
TRAE_SOLO_FUNCTION,
|
|
4217
|
-
"solo_agent_remote",
|
|
4218
|
-
"chat_v3"
|
|
4219
|
-
]
|
|
4220
|
-
};
|
|
4652
|
+
const TRAE_DIRECTORY_FUNCTIONS = TRAE_CHANNEL_PRIORITY;
|
|
4221
4653
|
const TRAE_SOLO_CHAT_PATH = "/api/agent/v3/llm_utils_chat";
|
|
4222
4654
|
const TRAE_SOLO_MODELS_PATH = "/api/ide/v1/get_detail_param";
|
|
4223
4655
|
function classify(status) {
|
|
@@ -8898,48 +9330,6 @@ function parseTraeModelExtraConfigLogLine(line) {
|
|
|
8898
9330
|
}
|
|
8899
9331
|
}
|
|
8900
9332
|
//#endregion
|
|
8901
|
-
//#region src/model-detail.ts
|
|
8902
|
-
const TRAE_MODEL_DETAIL_PATH = "/api/ide/v1/batch_get_detail_param";
|
|
8903
|
-
const TRAE_MODEL_DETAIL_FUNCTIONS = [
|
|
8904
|
-
"ui_builder_v2",
|
|
8905
|
-
"solo_coder",
|
|
8906
|
-
"chat_v3",
|
|
8907
|
-
"solo_builder",
|
|
8908
|
-
"builder_v3",
|
|
8909
|
-
"builder",
|
|
8910
|
-
"chat",
|
|
8911
|
-
"inline_chat",
|
|
8912
|
-
"git_ai",
|
|
8913
|
-
"custom_agent_generation",
|
|
8914
|
-
"utils",
|
|
8915
|
-
"code_reviewer",
|
|
8916
|
-
"code_review_summary",
|
|
8917
|
-
"solo_agent",
|
|
8918
|
-
"solo_agent_remote",
|
|
8919
|
-
"solo_work_remote",
|
|
8920
|
-
"solo_agent_lite",
|
|
8921
|
-
"solo_work_lite",
|
|
8922
|
-
"solo_design_lite",
|
|
8923
|
-
"solo_design_remote",
|
|
8924
|
-
"multimodal",
|
|
8925
|
-
"system_diagnosis"
|
|
8926
|
-
];
|
|
8927
|
-
/** Build the exact request shape observed in successful current Trae CN logs. */
|
|
8928
|
-
function buildTraeModelDetailRequest(configName = "", custom = false) {
|
|
8929
|
-
return {
|
|
8930
|
-
functions: [...TRAE_MODEL_DETAIL_FUNCTIONS],
|
|
8931
|
-
agent_type: configName === "" ? "" : "solo_agent",
|
|
8932
|
-
current_config_info: {
|
|
8933
|
-
config_name: configName,
|
|
8934
|
-
is_custom_model: custom
|
|
8935
|
-
},
|
|
8936
|
-
mode_type: 0,
|
|
8937
|
-
access_type: 0,
|
|
8938
|
-
ab_force_vids: "",
|
|
8939
|
-
ab_autotest_advanced_mode: 0
|
|
8940
|
-
};
|
|
8941
|
-
}
|
|
8942
|
-
//#endregion
|
|
8943
9333
|
//#region src/redact.ts
|
|
8944
9334
|
/**
|
|
8945
9335
|
* Redaction helpers for diagnostics that a user may paste into a public issue.
|
|
@@ -9421,6 +9811,24 @@ function apply(ctx, config) {
|
|
|
9421
9811
|
credential: () => store.resolve(),
|
|
9422
9812
|
log: (message, detail) => ctx.logger.warn(message, detail)
|
|
9423
9813
|
});
|
|
9814
|
+
/**
|
|
9815
|
+
* The IDE's own roster: which models the vendor's picker shows, per
|
|
9816
|
+
* function (issue #52).
|
|
9817
|
+
*
|
|
9818
|
+
* It is a REFINEMENT of a successful discovery, never a dependency: every
|
|
9819
|
+
* failure path in {@link TraeOfficialRosterClient.fetch} collapses to
|
|
9820
|
+
* `undefined`, and `applyOfficialRoster` then keeps every row. That is why
|
|
9821
|
+
* this can be wired in without a setting — it only acts where every chat
|
|
9822
|
+
* function hides a config (retire it) or where the vendor shows it on a
|
|
9823
|
+
* DIFFERENT chat function than the one we guessed (re-pin). Both are the
|
|
9824
|
+
* upstream's own answers, and both leave anything ambiguous alone.
|
|
9825
|
+
*/
|
|
9826
|
+
const officialRoster = new TraeOfficialRosterClient({
|
|
9827
|
+
credential: () => store.resolve(),
|
|
9828
|
+
identity,
|
|
9829
|
+
...panel === "enterprise" ? { route: "enterprise" } : {},
|
|
9830
|
+
log: (message, detail) => ctx.logger.warn(message, detail)
|
|
9831
|
+
});
|
|
9424
9832
|
const wireResolver = (displayId) => wire.byId.get(displayId) ?? wire.byName.get(displayId.trim().toLowerCase());
|
|
9425
9833
|
/**
|
|
9426
9834
|
* One client + bridge per provider id.
|
|
@@ -9572,25 +9980,52 @@ function apply(ctx, config) {
|
|
|
9572
9980
|
};
|
|
9573
9981
|
},
|
|
9574
9982
|
discoverModels: async (signal) => {
|
|
9575
|
-
const
|
|
9983
|
+
const remote = await withDirectoryRetry(() => remoteCatalog.fetchModels(signal));
|
|
9984
|
+
const [wireModels, roster] = await Promise.all([solo.fetchModels(signal), officialRoster.fetch(signal)]);
|
|
9985
|
+
const merged = mergeTraeModelSources(remote, wireModels);
|
|
9576
9986
|
const callable = withChatCallableFunctions(merged, TRAE_DIRECTORY_FUNCTIONS[region]);
|
|
9577
9987
|
const chatFunctions = TRAE_DIRECTORY_FUNCTIONS[region];
|
|
9578
9988
|
for (const model of merged) {
|
|
9579
9989
|
if (model.wireFunction === void 0 || chatFunctions.includes(model.wireFunction)) continue;
|
|
9580
9990
|
ctx.logger.warn(`model directory row is pinned to a non-chat function and will be called through the default chat function instead: ${model.id} (pinned to function ${model.wireFunction})`);
|
|
9581
9991
|
}
|
|
9992
|
+
/**
|
|
9993
|
+
* Retire what no chat function offers any more, and re-pin what the
|
|
9994
|
+
* vendor offers under a DIFFERENT channel (issue #52).
|
|
9995
|
+
*
|
|
9996
|
+
* Runs AFTER `withChatCallableFunctions` on purpose: that step decides
|
|
9997
|
+
* the `wireFunction` this filter judges the row on. Rows the IDE roster
|
|
9998
|
+
* does not mention, and every row when the roster could not be read at
|
|
9999
|
+
* all, survive untouched — see `applyOfficialRoster`.
|
|
10000
|
+
*/
|
|
10001
|
+
const official = applyOfficialRoster(callable, roster, chatFunctions);
|
|
10002
|
+
/**
|
|
10003
|
+
* Fix the ORDER once, here, so it is a property of the catalog rather
|
|
10004
|
+
* than of the screen that happens to draw it (issue #52, P0).
|
|
10005
|
+
*
|
|
10006
|
+
* The merge walks twelve directory groups and `solo-remote.ts` records
|
|
10007
|
+
* that the group order varies between calls, so the same account could
|
|
10008
|
+
* get two different lists from two refreshes. Sorting by (channel
|
|
10009
|
+
* priority, name) makes the saved `lastCatalog` — and therefore the DSH
|
|
10010
|
+
* model picker, which renders in catalog order — identical across
|
|
10011
|
+
* refreshes. The card re-applies the same function for catalogs saved
|
|
10012
|
+
* before this existed.
|
|
10013
|
+
*/
|
|
10014
|
+
const visible = orderTraeModels(official.rows, region);
|
|
10015
|
+
if (official.hidden.length > 0) ctx.logger.warn(`hiding ${official.hidden.length} model(s) no chat function offers any more (issue #52)`, official.hidden);
|
|
10016
|
+
if (official.repinned.length > 0) ctx.logger.warn(`re-pinning ${official.repinned.length} model(s) to the function their vendor shows them on (issue #52)`, official.repinned);
|
|
9582
10017
|
wire.callableKeys.clear();
|
|
9583
|
-
for (const model of
|
|
10018
|
+
for (const model of visible) {
|
|
9584
10019
|
wire.callableKeys.add(model.id.trim().toLowerCase());
|
|
9585
10020
|
wire.callableKeys.add(model.name.trim().toLowerCase());
|
|
9586
10021
|
}
|
|
9587
|
-
wire.resolved =
|
|
9588
|
-
const wireTargets = wireTargetsOf(
|
|
10022
|
+
wire.resolved = visible.length > 0;
|
|
10023
|
+
const wireTargets = wireTargetsOf(visible);
|
|
9589
10024
|
wire.byId = wireTargets.byId;
|
|
9590
10025
|
wire.byName = wireTargets.byName;
|
|
9591
10026
|
latestDiscovery.length = 0;
|
|
9592
|
-
latestDiscovery.push(...
|
|
9593
|
-
return
|
|
10027
|
+
latestDiscovery.push(...visible);
|
|
10028
|
+
return visible;
|
|
9594
10029
|
},
|
|
9595
10030
|
/**
|
|
9596
10031
|
* One-click availability test. The ids come from the card, so each one is
|
|
@@ -10294,4 +10729,4 @@ function apply(ctx, config) {
|
|
|
10294
10729
|
});
|
|
10295
10730
|
}
|
|
10296
10731
|
//#endregion
|
|
10297
|
-
export { Config, FALLBACK_TRAE_MODELS, FALLBACK_TRAE_MODELS_AI, MAX_PROBE_INPUT_TOKENS, REGION_GATEWAYS, SseDecoder, TRAE_ACCOUNT_STATUS_PATH, TRAE_AI_PROVIDER, TRAE_CHECKIN_PATH, TRAE_CN_AGENT_TASK_PATH, TRAE_CN_TITLE_PATH, TRAE_ENTERPRISE_PROVIDER, TRAE_MODELS_TEST_PATH, TRAE_MODEL_DETAIL_FUNCTIONS, TRAE_MODEL_DETAIL_PATH, TRAE_PANELS, TRAE_PAY_BASE, TRAE_PROBE_TIMEOUT_MS, TRAE_PROVIDER, TRAE_PROVIDERS, TRAE_PROVIDER_DISPLAY_NAMES, TRAE_PROVIDER_IDS, TRAE_PROVIDER_ID_DISPLAY_NAMES, TRAE_PROVIDER_ROUTES, TRAE_RAW_CHAT_V1_PATH, TRAE_RAW_CHAT_V2_PATH, TRAE_REASONING_EFFORTS, TRAE_REGIONS, TRAE_REGION_PARAM, TRAE_SETTINGS_NS, TRAE_SOLO_CHAT_PATH, TRAE_SOLO_FUNCTION, TRAE_SOLO_MODELS_PATH, TRAE_SOLO_REMOTE_BASE, TRAE_STATE_DB_FILENAME, TRAE_STREAM_IDLE_TIMEOUT_MS, TRAE_USAGE_PATH, TRAE_VERSION_CODE_FALLBACK, TraeCatalog, TraeCredentialStore, TraeDelegatingUpstreamClient, TraeFallbackUpstreamClient, TraeGatedUpstreamClient, TraeRawCapabilityController, TraeRawCapabilityState, TraeRawChatUpstreamClient, TraeSoloBridge, TraeSoloRemoteCatalogClient, TraeSoloUpstreamClient, TraeUsageClient, UnconfiguredTraeUpstreamClient, adaptLegacyPiAiContext, adaptModernPiAiContext, apply, applyContextBudgets, applyImageSelection, applyReasoningEffort, asVolatile, bridgeTraeSoloStream, buildTraeAgentTaskBody, buildTraeCnHeaders, buildTraeFusionRawChatEnvelope, buildTraeModelDetailRequest, buildTraeRawChatDraft, buildTraeRawChatRuntimeConfig, classifyProbeError, classifyProbeResult, classifyTraeRawChatFailure, configuredAccountsOf, createTraeAdapter, createTraeRawGateway, createTraeShim, creditPosition, decidePiAiGeneration, decodeRawChatChunk, decodeTraeEvent, decryptTraeStorageValue, deriveCatalog, describeIdShape, describeNameShape, describeTraeFailure, discoveredCatalog, displayNameOfTraeProvider, fallbackModelsFor, generationOf, hashTraeRawChatArg, identityHeaders, inject, isEnterpriseAccount, isPromotableWireModel, legacyTraeOwnAuthPath, maskUserPath, mergeTraeModelSources, name, nextRegionCreditPosition, nextRegionEnabled, nextRegionSlots, normalizeTraeCredential, normalizeTraeToolSchema, normalizeTraeToolSchemas, normalizeTraeVersionCode, panelOfKey, panelOfProvider, parseObservedModelConfig, parseReasoningCapability, parseTraeAuthValue, parseTraeCachedModel, parseTraeModelExtraConfigLogLine, parseTraeRawChatBehaviorConfig, parseTraeRemoteModel, parseTraeStorageDocument, piAiRuntimeInfo, pickTraeStorageIdentity, prepareSoloBody, probeBody, probeModelsSequentially, probeOneModel, probeTraeRawChatCapability, providerOfPanel, rawCapabilityDiagnostic, rawCapabilityFingerprint, readTraeCachedModel, readTraeCliIdentity, readTraeIdentity, refreshTraeCredential, regionCreditPositionOf, regionEnabled, regionEnabledOf, regionOfCredential, regionOfEdition, regionOfHost, regionOfPanel, regionOfTraeProvider, regionOfTraeStatusUrl, regionOfUserRegion, regionStateOf, registerTraeUsageRoute, resolveTraeIdentity, resolveTraeRawRuntime, routeOfTraeProvider, sanitizeCatalog, settingsNamespaceOf, traeEndpoint, traeInputModalities, traeModelDisplayName, traeOwnAuthPath, traeRawChatExtraInfo, traeStateDatabaseCandidates, traeStorageCandidates, traeWebUsage, traeWindowsAppNames, unwrapVolatile, unwrapVolatileDeep, wireTargetsOf, withContextAdaptation, withTraeRegion };
|
|
10732
|
+
export { Config, FALLBACK_TRAE_MODELS, FALLBACK_TRAE_MODELS_AI, MAX_PROBE_INPUT_TOKENS, REGION_GATEWAYS, SseDecoder, TRAE_ACCOUNT_STATUS_PATH, TRAE_AI_PROVIDER, TRAE_CHANNEL_PRIORITY, TRAE_CHECKIN_PATH, TRAE_CN_AGENT_TASK_PATH, TRAE_CN_TITLE_PATH, TRAE_COMMON_FUNCTIONS, TRAE_ENTERPRISE_PROVIDER, TRAE_MODELS_TEST_PATH, TRAE_MODEL_DETAIL_FUNCTIONS, TRAE_MODEL_DETAIL_PATH, TRAE_OFFICIAL_ROSTER_PATH, TRAE_PANELS, TRAE_PAY_BASE, TRAE_PROBE_TIMEOUT_MS, TRAE_PROVIDER, TRAE_PROVIDERS, TRAE_PROVIDER_DISPLAY_NAMES, TRAE_PROVIDER_IDS, TRAE_PROVIDER_ID_DISPLAY_NAMES, TRAE_PROVIDER_ROUTES, TRAE_RAW_CHAT_V1_PATH, TRAE_RAW_CHAT_V2_PATH, TRAE_REASONING_EFFORTS, TRAE_REGIONS, TRAE_REGION_PARAM, TRAE_SETTINGS_NS, TRAE_SOLO_CHAT_PATH, TRAE_SOLO_FUNCTION, TRAE_SOLO_MODELS_PATH, TRAE_SOLO_REMOTE_BASE, TRAE_STATE_DB_FILENAME, TRAE_STREAM_IDLE_TIMEOUT_MS, TRAE_USAGE_PATH, TRAE_VERSION_CODE_FALLBACK, TraeCatalog, TraeCredentialStore, TraeDelegatingUpstreamClient, TraeFallbackUpstreamClient, TraeGatedUpstreamClient, TraeOfficialRosterClient, TraeRawCapabilityController, TraeRawCapabilityState, TraeRawChatUpstreamClient, TraeSoloBridge, TraeSoloRemoteCatalogClient, TraeSoloUpstreamClient, TraeUsageClient, UnconfiguredTraeUpstreamClient, adaptLegacyPiAiContext, adaptModernPiAiContext, apply, applyContextBudgets, applyImageSelection, applyOfficialRoster, applyReasoningEffort, asVolatile, bridgeTraeSoloStream, buildTraeAgentTaskBody, buildTraeCnHeaders, buildTraeFusionRawChatEnvelope, buildTraeModelDetailRequest, buildTraeRawChatDraft, buildTraeRawChatRuntimeConfig, classifyProbeError, classifyProbeResult, classifyTraeRawChatFailure, configuredAccountsOf, createTraeAdapter, createTraeRawGateway, createTraeShim, creditPosition, decidePiAiGeneration, decodeRawChatChunk, decodeTraeEvent, decryptTraeStorageValue, deriveCatalog, describeIdShape, describeNameShape, describeTraeFailure, discoveredCatalog, displayNameOfTraeProvider, fallbackModelsFor, filterTraeModels, generationOf, groupTraeModels, hashTraeRawChatArg, identityHeaders, inject, isEnterpriseAccount, isPromotableWireModel, legacyTraeOwnAuthPath, maskUserPath, mergeTraeModelSources, name, nextRegionCreditPosition, nextRegionEnabled, nextRegionSlots, normalizeTraeCredential, normalizeTraeToolSchema, normalizeTraeToolSchemas, normalizeTraeVersionCode, officialVerdictOf, orderTraeModels, panelOfKey, panelOfProvider, parseObservedModelConfig, parseReasoningCapability, parseTraeAuthValue, parseTraeCachedModel, parseTraeModelExtraConfigLogLine, parseTraeOfficialRoster, parseTraeRawChatBehaviorConfig, parseTraeRemoteModel, parseTraeStorageDocument, piAiRuntimeInfo, pickTraeStorageIdentity, prepareSoloBody, probeBody, probeModelsSequentially, probeOneModel, probeTraeRawChatCapability, providerOfPanel, rawCapabilityDiagnostic, rawCapabilityFingerprint, readTraeCachedModel, readTraeCliIdentity, readTraeIdentity, refreshTraeCredential, regionCreditPositionOf, regionEnabled, regionEnabledOf, regionOfCredential, regionOfEdition, regionOfHost, regionOfPanel, regionOfTraeProvider, regionOfTraeStatusUrl, regionOfUserRegion, regionStateOf, registerTraeUsageRoute, resolveTraeIdentity, resolveTraeRawRuntime, routeOfTraeProvider, sanitizeCatalog, scopeTraeModels, settingsNamespaceOf, traeEndpoint, traeInputModalities, traeModelCallChannel, traeModelDisplayName, traeModelInView, traeModelMatchesQuery, traeOwnAuthPath, traeRawChatExtraInfo, traeStateDatabaseCandidates, traeStorageCandidates, traeWebUsage, traeWindowsAppNames, unwrapVolatile, unwrapVolatileDeep, wireTargetsOf, withChatCallableFunctions, withContextAdaptation, withTraeRegion };
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "dsh-connect-trae",
|
|
3
3
|
"displayName": "DSH Connect Trae",
|
|
4
4
|
"description": "把本机登录的 Trae 模型接入 DeepSeek Harness:国内版与国际版双供应商并行,提供用量/积分概览与每日签到领取。",
|
|
5
|
-
"version": "4.4.
|
|
5
|
+
"version": "4.4.5",
|
|
6
6
|
"author": "dingminhua",
|
|
7
7
|
"copyright": "Copyright (c) 2026 LaoDing",
|
|
8
8
|
"license": "MIT",
|