@xiaoso/dsh-tool-plus 0.1.5 → 0.1.7-beta.0
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/README.md +1 -1
- package/THIRD_PARTY_NOTICES.md +9 -3
- package/lib/{abort-Cwwm4Err.mjs → abort-Caqff3M6.mjs} +2 -2
- package/lib/alibaba-coding-plan-DTupMiAi.mjs +73 -0
- package/lib/alibaba-token-plan-CHGyWOfX.mjs +46 -0
- package/lib/alibaba-token-plan-Dj3OZhEE.mjs +82 -0
- package/lib/{amazon-bedrock-TVMpUTRG.mjs → amazon-bedrock-DbFSYXfJ.mjs} +117 -38
- package/lib/{anthropic-BL6LFDQS.mjs → anthropic-CTJ3IQVa.mjs} +675 -166
- package/lib/anthropic-CXfWlp-x.mjs +105 -0
- package/lib/{aws-credentials-B20dliS7.mjs → anthropic-wire-CKuhDwZ1.mjs} +74 -14
- package/lib/{api-key-login-CIDnXeYd.mjs → api-key-validation-CGCJFbFr.mjs} +27 -68
- package/lib/{azure-openai-responses-BkhsLmN3.mjs → azure-openai-responses-ChFbWaGj.mjs} +27 -16
- package/lib/{browser-render-CmgvSNte.mjs → browser-render-9o0Rknop.mjs} +4 -4
- package/lib/bun-shim.mjs +71 -2
- package/lib/{bundled-references-ChZSPDFw.mjs → bundled-references-DY3EJxZV.mjs} +6 -5
- package/lib/cline-pass-Bwg3esu9.mjs +44 -0
- package/lib/cloudflare-ai-gateway-BupNXyKK.mjs +35 -0
- package/lib/cloudflare-ai-gateway-EWo0VkP5.mjs +44 -0
- package/lib/collapse-DOR8sOGf.mjs +2304 -0
- package/lib/coreweave-C82HrLpb.mjs +31 -0
- package/lib/coreweave-Ct8cF-da.mjs +14 -0
- package/lib/{cursor-B6HcmplF.mjs → cursor-B95LzVWV.mjs} +11 -3
- package/lib/{cursor-CRpLpaZ3.mjs → cursor-DJV_dcgB.mjs} +887 -1784
- package/lib/{cursor-B8m6SqAH.mjs → cursor-LKGjucn2.mjs} +48 -38
- package/lib/cursor-proto-B8Wj8bv9.mjs +10513 -0
- package/lib/{deterministic-id-D-yIV_eI.mjs → deterministic-id-CUEIMSqR.mjs} +1 -1
- package/lib/devin-BMTdx_hx.mjs +316 -0
- package/lib/{devin-DUAfvBsW.mjs → devin-DSp0Rw_E.mjs} +172 -86
- package/lib/devin-ExGIghmx.mjs +69 -0
- package/lib/devin-proto-Br8fdyNl.mjs +2888 -0
- package/lib/{dom-CawWi8fa.mjs → dom-DG3sPESc.mjs} +8 -8
- package/lib/effort-BdtQMN-_.mjs +23 -0
- package/lib/{error-C-f_Wnw4.mjs → error-CORgGg5a.mjs} +275 -154
- package/lib/{event-stream-Dh2guZxS.mjs → event-stream-ulcDenZD.mjs} +20 -4
- package/lib/{gemini-headers-DKUShltF.mjs → gemini-headers-Co9cVvex.mjs} +2 -2
- package/lib/{github-copilot-suDymKrx.mjs → github-copilot-Dstq1D3s.mjs} +69 -29
- package/lib/github-copilot-headers-DOh1gt_w.mjs +312 -0
- package/lib/gitlab-duo-DSCMrU0m.mjs +11 -0
- package/lib/google-CtsKkOQK.mjs +38 -0
- package/lib/google-antigravity-z-5KsEci.mjs +252 -0
- package/lib/{google-auth-DYJLM792.mjs → google-auth-ieLBaneO.mjs} +4 -4
- package/lib/{google-gemini-cli-8BT513Ul.mjs → google-gemini-cli-C6NE5mWz.mjs} +28 -54
- package/lib/{google-gemini-cli-D6cSmfvB.mjs → google-gemini-cli-CAIPSl7e.mjs} +23 -29
- package/lib/google-oauth-shared-DhMllAkt.mjs +53 -0
- package/lib/{google-shared-CVbHK5vZ.mjs → google-shared-B0aNCYEH.mjs} +140 -44
- package/lib/{google-validation-Cgbn3tWJ.mjs → google-validation-BEkNs-Bx.mjs} +1 -1
- package/lib/{google-vertex-Bui-ypAe.mjs → google-vertex-Bbd1tYNc.mjs} +8 -8
- package/lib/hosts-00rjRzUD.mjs +203 -0
- package/lib/id-AL5obQzR.mjs +71 -0
- package/lib/{idle-iterator-CYAxUkSD.mjs → idle-iterator-DlUkEfzW.mjs} +3 -3
- package/lib/index.mjs +587 -5266
- package/lib/kilo-ChJL54wq.mjs +81 -0
- package/lib/kimi-C2c_Zq8A.mjs +67 -0
- package/lib/{launch-BmgEUycu.mjs → launch-DKDH71En.mjs} +1 -1
- package/lib/markit-CmRfm4E2.mjs +9885 -0
- package/lib/models-DnXMYGcJ.mjs +381604 -0
- package/lib/muse-code-Di1VZmB1.mjs +143 -0
- package/lib/{ollama-Df9ce-Cp.mjs → ollama-B8ic3sEp.mjs} +15 -30
- package/lib/{openai-codex-CAVI3Me-.mjs → openai-codex-DuJNC99x.mjs} +29 -99
- package/lib/{openai-codex-responses-BcnOotRB.mjs → openai-codex-responses-BL29nh9K.mjs} +204 -116
- package/lib/{openai-completions-Bq4WT47M.mjs → openai-completions-BK2f2dBv.mjs} +152 -82
- package/lib/openai-configuration-update-xMYUjaK_.mjs +150 -0
- package/lib/{openai-reasoning-fallback-DXsfiSXO.mjs → openai-reasoning-fallback-BdB3RCbj.mjs} +106 -12
- package/lib/{openai-responses-Mq_-PjvE.mjs → openai-responses-CGQPlIIy.mjs} +76 -82
- package/lib/{perplexity-XgLF73E7.mjs → perplexity-TBjz3VMB.mjs} +52 -9
- package/lib/{pkce-BlQikGPu.mjs → pkce-BYjmugmw.mjs} +1 -1
- package/lib/protobuf-aab1UGVn.mjs +717 -0
- package/lib/{provider-response-C6vcbQyO.mjs → provider-response-SqKSkkUc.mjs} +1 -1
- package/lib/{proxy-D9lm7ONA.mjs → proxy-5nWqRL1f.mjs} +45 -5
- package/lib/{readability-Cpm-ocau.mjs → readability-uGhqb4GC.mjs} +2 -2
- package/lib/reference-CtvM4zLU.mjs +114 -0
- package/lib/{request-debug-HJMoJncL.mjs → request-debug-NQN0BjHH.mjs} +1 -1
- package/lib/{sanitize-text-CfcXzw5X.mjs → sanitize-text-BCf5KmCf.mjs} +1 -1
- package/lib/{scrapers-CE_qK1yk.mjs → scrapers-D8oWspgW.mjs} +12 -12
- package/lib/{src-BcD0_rQR.mjs → src-BwW51vA5.mjs} +979 -388
- package/lib/{sse-debug-CYdjOC96.mjs → sse-debug-B-tkLCPW.mjs} +1 -1
- package/lib/{stream-Bjq8wjfr.mjs → stream-B_7qN-bA.mjs} +3802 -2623
- package/lib/stream-markup-healing-DKT1lnkW.mjs +267 -0
- package/lib/{strict-tool-validation-imVLUcbI.mjs → strict-tool-validation-CBTz1dAA.mjs} +2 -2
- package/lib/taxonomy-DSIM99rS.mjs +15392 -0
- package/lib/{stream-markup-healing-DZ6bVDxH.mjs → thinking-CiLa2LFB.mjs} +31 -186
- package/lib/{turndown-DN7ByzEI.mjs → turndown-DrX1M4WG.mjs} +4 -4
- package/lib/{type-guards-B9VVjRDK.mjs → type-guards-CttAANEx.mjs} +1 -1
- package/lib/{types-DX_bvuus.mjs → types-PVueGi9S.mjs} +2 -2
- package/lib/{utils-APrc-TBB.mjs → utils-CCfhUQen.mjs} +2364 -2676
- package/lib/{utils-Cp2Mxf_U.mjs → utils-CUPhpw9A.mjs} +413 -134
- package/lib/{utils-CQHPEQ3W.mjs → utils-DeWqNWV8.mjs} +2 -2
- package/lib/{vision-guard-mBmtAHx0.mjs → vision-guard-_XwsL1DF.mjs} +14 -29
- package/lib/xai-oauth-CXhnz0gO.mjs +210 -0
- package/lib/{xiaomi-7mE345KX.mjs → xiaomi-psoUItal.mjs} +8 -37
- package/lib/{zai-CeNpMV3W.mjs → zai-ApJ8HBgT.mjs} +8 -71
- package/lib/{zip-BK7UHCwX.mjs → zip-Kd602XNe.mjs} +1 -1
- package/package.json +43 -41
- package/presets/package.json +1 -1
- package/presets/tool-plus-ptc/agent.cordis.yml +13 -4
- package/presets/tool-plus-standard/agent.cordis.yml +11 -3
- package/lib/agent_pb-Rizyt9Zg.mjs +0 -805
- package/lib/anthropic-CDmj476p.mjs +0 -262
- package/lib/api_server_pb-CDZgLMta.mjs +0 -252
- package/lib/callback-server-CFJK-jvK.mjs +0 -398
- package/lib/codex-P1dGpX7G.mjs +0 -54
- package/lib/device-code-CuXTWYwY.mjs +0 -51
- package/lib/devin-BcQwht1W.mjs +0 -114
- package/lib/devin-BvMfGevz.mjs +0 -95
- package/lib/github-copilot-B3kQl0g0.mjs +0 -104
- package/lib/gitlab-duo-BriUTP8k.mjs +0 -155
- package/lib/gitlab-duo-workflow-wK5Ljzmc.mjs +0 -91
- package/lib/google-CE5tFDod.mjs +0 -30
- package/lib/google-antigravity-C1jgNljz.mjs +0 -198
- package/lib/google-oauth-shared-BLVTvokk.mjs +0 -147
- package/lib/grammar-D-NqNUxQ.mjs +0 -49
- package/lib/identity-HNO1Oe9B.mjs +0 -219
- package/lib/kimi-DgcUpPtK.mjs +0 -236
- package/lib/markit-DtGoRE6M.mjs +0 -1417
- package/lib/minimax-code-Y3h5li9N.mjs +0 -53
- package/lib/models-DRA2c_8U.mjs +0 -104660
- package/lib/opencode-BsVw9rCD.mjs +0 -38
- package/lib/to-binary-B1BEBIPC.mjs +0 -6002
- package/lib/wafer-BlhWLweO.mjs +0 -17
- package/lib/xai-oauth-5pORHUrg.mjs +0 -446
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
2
|
__installBunShim();
|
|
3
|
-
//#region node_modules/.pnpm/@oh-my-pi+pi-ai@
|
|
3
|
+
//#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/utils/deterministic-id.ts
|
|
4
4
|
/**
|
|
5
5
|
* Format the leading 128 bits of `seed`'s SHA-256 digest as a v4-shape UUID
|
|
6
6
|
* (8-4-4-4-12 hex groups).
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
|
+
__installBunShim();
|
|
3
|
+
import { C as warn } from "./src-BwW51vA5.mjs";
|
|
4
|
+
import { n as discoveryFetch } from "./utils-DeWqNWV8.mjs";
|
|
5
|
+
import { n as THINKING_EFFORTS } from "./effort-BdtQMN-_.mjs";
|
|
6
|
+
import { t as collapseVariants } from "./collapse-DOR8sOGf.mjs";
|
|
7
|
+
import { r as devinDiscoveryMetadata } from "./devin-ExGIghmx.mjs";
|
|
8
|
+
import { o as toBinary, t as create } from "./protobuf-aab1UGVn.mjs";
|
|
9
|
+
import { d as GetCliModelConfigsRequestSchema, f as GetCliModelConfigsResponseSchema, t as decodeDevinUnaryMessage, v as MetadataSchema } from "./devin-proto-Br8fdyNl.mjs";
|
|
10
|
+
//#region node_modules/.pnpm/@oh-my-pi+pi-catalog@18.1.17/node_modules/@oh-my-pi/pi-catalog/src/discovery/devin.ts
|
|
11
|
+
const DEVIN_GET_CLI_MODEL_CONFIGS_PATH = "/exa.api_server_pb.ApiServerService/GetCliModelConfigs";
|
|
12
|
+
const DEFAULT_CONTEXT_WINDOW = 2e5;
|
|
13
|
+
const DEFAULT_MAX_TOKENS = 64e3;
|
|
14
|
+
/**
|
|
15
|
+
* `DISPLAY_OPTION_INTERNAL_DEFAULT` — display slot for configs the server only
|
|
16
|
+
* reveals to clients that opt in, used for internal default/eval models.
|
|
17
|
+
*
|
|
18
|
+
* The vendored descriptor predates display options 6-8, so the generated
|
|
19
|
+
* `DisplayOption` enum stops at `QUICK_REVIEW` (4). Wire display options are
|
|
20
|
+
* plain int32, so the extra values decode and re-encode faithfully; casting
|
|
21
|
+
* here keeps the generated code untouched.
|
|
22
|
+
*/
|
|
23
|
+
const DEVIN_DISPLAY_OPTION_INTERNAL_DEFAULT = 6;
|
|
24
|
+
/**
|
|
25
|
+
* Display slots the native client advertises. `UNSPECIFIED` (0) is implicit —
|
|
26
|
+
* it is the default for configs with no display opinion. Asking for the
|
|
27
|
+
* internal slots is what makes the server return its full catalog; the
|
|
28
|
+
* internal ones are filtered client-side, exactly as native does.
|
|
29
|
+
*/
|
|
30
|
+
const DEVIN_SUPPORTED_MODEL_DISPLAYS = [
|
|
31
|
+
3,
|
|
32
|
+
4,
|
|
33
|
+
DEVIN_DISPLAY_OPTION_INTERNAL_DEFAULT,
|
|
34
|
+
7,
|
|
35
|
+
8
|
|
36
|
+
];
|
|
37
|
+
/** Display slots requested but never surfaced: quick-review and internal defaults. */
|
|
38
|
+
const DEVIN_INTERNAL_MODEL_DISPLAYS = /* @__PURE__ */ new Set([4, DEVIN_DISPLAY_OPTION_INTERNAL_DEFAULT]);
|
|
39
|
+
/** Best-effort match for labels whose wording implies a thinking / reasoning-effort variant. */
|
|
40
|
+
const REASONING_LABEL_PATTERN = /think|thinking|minimal|high|medium|low|xhigh|max|reasoning/i;
|
|
41
|
+
const NO_REASONING_LABEL_PATTERN = /\bno thinking\b/i;
|
|
42
|
+
/**
|
|
43
|
+
* Server model features are authoritative for reasoning support; the label
|
|
44
|
+
* heuristic only covers configs that ship no `modelFeatures` at all.
|
|
45
|
+
*/
|
|
46
|
+
function supportsDevinThinking(config) {
|
|
47
|
+
const features = config.modelInfo?.modelFeatures;
|
|
48
|
+
if (features !== void 0) return features.supportsThinking;
|
|
49
|
+
if (NO_REASONING_LABEL_PATTERN.test(config.label)) return false;
|
|
50
|
+
return REASONING_LABEL_PATTERN.test(config.label);
|
|
51
|
+
}
|
|
52
|
+
/** Cost `modelDimensions` labels, normalized, mapped onto catalog token rates. */
|
|
53
|
+
const DEVIN_COST_LABEL_INPUT = "input";
|
|
54
|
+
const DEVIN_COST_LABEL_CACHE_READ = "cached input";
|
|
55
|
+
const DEVIN_COST_LABEL_OUTPUT = "output";
|
|
56
|
+
/** Leading token count of a cost denominator ("1M tokens", "1K tokens"). */
|
|
57
|
+
const DEVIN_COST_DENOMINATOR_PATTERN = /(\d+(?:\.\d+)?)\s*([kmb])?/i;
|
|
58
|
+
const DEVIN_COST_DENOMINATOR_SCALE = {
|
|
59
|
+
k: 1e3,
|
|
60
|
+
m: 1e6,
|
|
61
|
+
b: 1e9
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Tokens covered by one cost dimension. Native prices per `1M tokens`; the
|
|
65
|
+
* scale is parsed instead of assumed so a future `1K` denominator still
|
|
66
|
+
* normalizes to catalog per-million rates.
|
|
67
|
+
*/
|
|
68
|
+
function devinCostDenominatorTokens(denominator) {
|
|
69
|
+
const match = DEVIN_COST_DENOMINATOR_PATTERN.exec(denominator);
|
|
70
|
+
if (match === null) return 1e6;
|
|
71
|
+
const suffix = match[2];
|
|
72
|
+
const scale = suffix === void 0 ? 1 : DEVIN_COST_DENOMINATOR_SCALE[suffix.toLowerCase()] ?? 1;
|
|
73
|
+
const tokens = Number(match[1]) * scale;
|
|
74
|
+
return tokens > 0 ? tokens : 1e6;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Per-million-token rates from the config's cost dimensions. `COST_FUZZY` marks
|
|
78
|
+
* an estimated rate, not a different unit, so both kinds are read. `cacheWrite`
|
|
79
|
+
* has no Cascade dimension — Devin bills cache writes at the input rate — and
|
|
80
|
+
* stays 0.
|
|
81
|
+
*/
|
|
82
|
+
function devinModelCost(config) {
|
|
83
|
+
const cost = {
|
|
84
|
+
input: 0,
|
|
85
|
+
output: 0,
|
|
86
|
+
cacheRead: 0,
|
|
87
|
+
cacheWrite: 0
|
|
88
|
+
};
|
|
89
|
+
for (const dimension of config.modelDimensions) {
|
|
90
|
+
if (dimension.kind !== 1 && dimension.kind !== 2) continue;
|
|
91
|
+
const perMillion = Math.round(dimension.value * 1e6 / devinCostDenominatorTokens(dimension.denominator) * 1e6) / 1e6;
|
|
92
|
+
switch (dimension.label.trim().toLowerCase()) {
|
|
93
|
+
case DEVIN_COST_LABEL_INPUT:
|
|
94
|
+
cost.input = perMillion;
|
|
95
|
+
break;
|
|
96
|
+
case DEVIN_COST_LABEL_CACHE_READ:
|
|
97
|
+
cost.cacheRead = perMillion;
|
|
98
|
+
break;
|
|
99
|
+
case DEVIN_COST_LABEL_OUTPUT: cost.output = perMillion;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return cost;
|
|
103
|
+
}
|
|
104
|
+
/** `modelFamilyMetadata` entry keys that carry the family's effort axis. */
|
|
105
|
+
const DEVIN_FAMILY_EFFORT_KEYS = {
|
|
106
|
+
effort: true,
|
|
107
|
+
"reasoning effort": true
|
|
108
|
+
};
|
|
109
|
+
/** `modelFamilyMetadata` entry key for the service-tier axis; order 1 is the fast lane. */
|
|
110
|
+
const DEVIN_FAMILY_FAST_KEY = "fast mode";
|
|
111
|
+
const DEVIN_FAMILY_FAST_ORDER = 1;
|
|
112
|
+
/** Boolean reasoning axis used by Claude families whose effort name alone is ambiguous. */
|
|
113
|
+
const DEVIN_FAMILY_THINKING_KEY = "thinking";
|
|
114
|
+
const DEVIN_FAMILY_THINKING_ORDER = 1;
|
|
115
|
+
/** Context-window axis; order 1 selects the separate 1M-context lane. */
|
|
116
|
+
const DEVIN_FAMILY_CONTEXT_1M_KEY = "1m context";
|
|
117
|
+
const DEVIN_FAMILY_CONTEXT_1M_ORDER = 1;
|
|
118
|
+
/** Effort-entry display names, normalized to a space-free token, mapped onto pi efforts. */
|
|
119
|
+
const DEVIN_FAMILY_EFFORT_BY_NAME = {
|
|
120
|
+
none: "off",
|
|
121
|
+
nothinking: "off",
|
|
122
|
+
minimal: "minimal",
|
|
123
|
+
low: "low",
|
|
124
|
+
medium: "medium",
|
|
125
|
+
high: "high",
|
|
126
|
+
xhigh: "xhigh",
|
|
127
|
+
max: "max"
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* File `config` under its server-declared family lane. Configs with no family
|
|
131
|
+
* metadata, or whose family carries no effort axis, are left alone and stay
|
|
132
|
+
* standalone specs.
|
|
133
|
+
*/
|
|
134
|
+
function collectDevinFamilyLane(lanes, config, uid) {
|
|
135
|
+
const metadata = config.modelFamilyMetadata;
|
|
136
|
+
if (metadata === void 0) return;
|
|
137
|
+
const label = metadata.modelFamilyLabel.trim();
|
|
138
|
+
if (!label) return;
|
|
139
|
+
let effort;
|
|
140
|
+
let thinking;
|
|
141
|
+
let fast = false;
|
|
142
|
+
let oneMillionContext = false;
|
|
143
|
+
for (const entry of metadata.entries) {
|
|
144
|
+
const value = entry.value;
|
|
145
|
+
if (value === void 0) continue;
|
|
146
|
+
const key = entry.key.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim();
|
|
147
|
+
if (key === DEVIN_FAMILY_FAST_KEY) {
|
|
148
|
+
fast = value.order === DEVIN_FAMILY_FAST_ORDER;
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
if (key === DEVIN_FAMILY_THINKING_KEY) {
|
|
152
|
+
thinking = value.order === DEVIN_FAMILY_THINKING_ORDER;
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
if (key === DEVIN_FAMILY_CONTEXT_1M_KEY) {
|
|
156
|
+
oneMillionContext = value.order === DEVIN_FAMILY_CONTEXT_1M_ORDER;
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (DEVIN_FAMILY_EFFORT_KEYS[key]) effort = DEVIN_FAMILY_EFFORT_BY_NAME[value.name.toLowerCase().replace(/[^a-z0-9]+/g, "")];
|
|
160
|
+
}
|
|
161
|
+
if (thinking === false) effort = "off";
|
|
162
|
+
const baseId = label.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
163
|
+
if (!baseId) return;
|
|
164
|
+
const laneId = `${baseId}${oneMillionContext ? "-1m" : ""}${fast ? "-fast" : ""}`;
|
|
165
|
+
let lane = lanes.get(laneId);
|
|
166
|
+
if (lane === void 0) {
|
|
167
|
+
lane = {
|
|
168
|
+
id: laneId,
|
|
169
|
+
name: `${label}${oneMillionContext ? " 1M" : ""}${fast ? " Fast" : ""}`,
|
|
170
|
+
members: [],
|
|
171
|
+
routing: {}
|
|
172
|
+
};
|
|
173
|
+
lanes.set(laneId, lane);
|
|
174
|
+
}
|
|
175
|
+
lane.members.push(uid);
|
|
176
|
+
if (lane.defaultMember === void 0 && (config.isDefaultModelInFamily || metadata.isDefaultModelInFamily)) lane.defaultMember = uid;
|
|
177
|
+
if (effort !== void 0 && lane.routing[effort] === void 0) lane.routing[effort] = uid;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Collapse families for the lanes that declare an effort ladder. The server
|
|
181
|
+
* default wire uid is hoisted to the front of `members` so collapsing adopts it
|
|
182
|
+
* as the logical model's default `requestModelId`.
|
|
183
|
+
*
|
|
184
|
+
* A lane with no non-`off` effort route has nothing to route: its members stay
|
|
185
|
+
* standalone rather than collapsing into a family with an empty effort list.
|
|
186
|
+
*/
|
|
187
|
+
function devinDynamicFamilies(lanes) {
|
|
188
|
+
const families = [];
|
|
189
|
+
for (const lane of lanes) {
|
|
190
|
+
const efforts = THINKING_EFFORTS.filter((effort) => lane.routing[effort] !== void 0);
|
|
191
|
+
if (efforts.length === 0) continue;
|
|
192
|
+
const defaultMember = lane.defaultMember;
|
|
193
|
+
const members = defaultMember === void 0 ? lane.members : [defaultMember, ...lane.members.filter((uid) => uid !== defaultMember)];
|
|
194
|
+
const defaultLevel = defaultMember === void 0 ? void 0 : efforts.find((effort) => lane.routing[effort] === defaultMember);
|
|
195
|
+
families.push({
|
|
196
|
+
id: lane.id,
|
|
197
|
+
name: lane.name,
|
|
198
|
+
members,
|
|
199
|
+
routing: lane.routing,
|
|
200
|
+
...defaultMember !== void 0 ? { defaultMember } : {},
|
|
201
|
+
thinking: {
|
|
202
|
+
mode: "effort",
|
|
203
|
+
efforts,
|
|
204
|
+
...defaultLevel !== void 0 ? { defaultLevel } : {},
|
|
205
|
+
...lane.routing.off === void 0 ? { requiresEffort: true } : {}
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
return families;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Fetches Devin models through the `GetCliModelConfigs` unary Connect RPC and
|
|
213
|
+
* normalizes them into canonical model entries.
|
|
214
|
+
*
|
|
215
|
+
* Returns `null` on request/decode failures.
|
|
216
|
+
* Returns `[]` only when the endpoint responds successfully with no usable models.
|
|
217
|
+
*/
|
|
218
|
+
async function fetchDevinModels(options) {
|
|
219
|
+
const timeoutMs = options.timeoutMs ?? 5e3;
|
|
220
|
+
const requestUrl = `${(options.baseUrl ?? "https://server.codeium.com").replace(/\/+$/, "")}${DEVIN_GET_CLI_MODEL_CONFIGS_PATH}`;
|
|
221
|
+
const controller = new AbortController();
|
|
222
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
223
|
+
const signal = options.signal ? AbortSignal.any([controller.signal, options.signal]) : controller.signal;
|
|
224
|
+
try {
|
|
225
|
+
const request = create(GetCliModelConfigsRequestSchema, { metadata: create(MetadataSchema, {
|
|
226
|
+
...devinDiscoveryMetadata(options.apiKey),
|
|
227
|
+
supportedModelDisplays: [...DEVIN_SUPPORTED_MODEL_DISPLAYS]
|
|
228
|
+
}) });
|
|
229
|
+
const body = toBinary(GetCliModelConfigsRequestSchema, request);
|
|
230
|
+
const response = await discoveryFetch(options.fetch)(requestUrl, {
|
|
231
|
+
method: "POST",
|
|
232
|
+
headers: {
|
|
233
|
+
"content-type": "application/proto",
|
|
234
|
+
"connect-protocol-version": "1",
|
|
235
|
+
accept: "*/*"
|
|
236
|
+
},
|
|
237
|
+
body,
|
|
238
|
+
signal
|
|
239
|
+
});
|
|
240
|
+
if (!response.ok) return null;
|
|
241
|
+
const decoded = decodeDevinUnaryMessage(GetCliModelConfigsResponseSchema, new Uint8Array(await response.arrayBuffer()));
|
|
242
|
+
if (!decoded) return null;
|
|
243
|
+
const models = normalizeDevinModels(decoded.clientModelConfigs, options.baseUrl);
|
|
244
|
+
if (models.length === 0) {
|
|
245
|
+
warn("Devin returned an empty native model catalog; the pinned CLI identity may be stale", { metadata: devinDiscoveryMetadata(void 0) });
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
return models;
|
|
249
|
+
} catch {
|
|
250
|
+
return null;
|
|
251
|
+
} finally {
|
|
252
|
+
clearTimeout(timer);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Wire uids whose configs advertise `supports_images` but whose backend
|
|
257
|
+
* silently drops the `ChatMessagePrompt.images` field. Verified live
|
|
258
|
+
* (2026-08-14, native CLI identity): SWE-1.6 and SWE-1.6 Fast answer as if no
|
|
259
|
+
* image was attached, while SWE-1.7, SWE-1.7 Lightning, and every proxied
|
|
260
|
+
* frontier model (Claude/Gemini/GPT/Kimi) read the same field correctly.
|
|
261
|
+
* Declaring text-only lets clients use their image fallback path instead of
|
|
262
|
+
* silently losing attachments ([#6072](https://github.com/can1357/oh-my-pi/issues/6072)).
|
|
263
|
+
* Remove entries if Devin ever wires SWE-1.6 vision up.
|
|
264
|
+
*/
|
|
265
|
+
const DEVIN_IMAGE_BLIND_UIDS = /* @__PURE__ */ new Set(["swe-1-6", "swe-1-6-fast"]);
|
|
266
|
+
/** One config as a raw (pre-collapse) spec keyed on its wire uid. */
|
|
267
|
+
function devinModelSpec(config, uid, baseUrl, isRouter) {
|
|
268
|
+
const features = config.modelInfo?.modelFeatures;
|
|
269
|
+
const input = (features !== void 0 ? features.supportsImages : config.supportsImages) && !DEVIN_IMAGE_BLIND_UIDS.has(uid) ? ["text", "image"] : ["text"];
|
|
270
|
+
const compat = {};
|
|
271
|
+
if (isRouter) compat.modelRouter = true;
|
|
272
|
+
if (features?.supportsParallelToolCalls === true) compat.supportsParallelToolCalls = true;
|
|
273
|
+
const maxOutputTokens = config.modelInfo?.maxOutputTokens ?? 0;
|
|
274
|
+
const spec = {
|
|
275
|
+
id: uid,
|
|
276
|
+
name: config.label.trim() || uid,
|
|
277
|
+
api: "devin-agent",
|
|
278
|
+
provider: "devin",
|
|
279
|
+
baseUrl,
|
|
280
|
+
reasoning: supportsDevinThinking(config),
|
|
281
|
+
input,
|
|
282
|
+
supportsTools: features !== void 0 ? features.supportsToolCalls : true,
|
|
283
|
+
cost: devinModelCost(config),
|
|
284
|
+
contextWindow: config.maxTokens > 0 ? config.maxTokens : DEFAULT_CONTEXT_WINDOW,
|
|
285
|
+
maxTokens: maxOutputTokens > 0 ? maxOutputTokens : DEFAULT_MAX_TOKENS,
|
|
286
|
+
...Object.keys(compat).length > 0 ? { compat } : {}
|
|
287
|
+
};
|
|
288
|
+
const description = config.description?.trim();
|
|
289
|
+
if (description) spec.description = description;
|
|
290
|
+
if (config.isNew) spec.isNew = true;
|
|
291
|
+
if (config.isBeta) spec.isBeta = true;
|
|
292
|
+
if (config.isRecommended) spec.isRecommended = true;
|
|
293
|
+
return spec;
|
|
294
|
+
}
|
|
295
|
+
function normalizeDevinModels(configs, baseUrlOverride) {
|
|
296
|
+
const baseUrl = baseUrlOverride ?? "https://server.codeium.com";
|
|
297
|
+
const specs = [];
|
|
298
|
+
const seen = /* @__PURE__ */ new Set();
|
|
299
|
+
const lanes = /* @__PURE__ */ new Map();
|
|
300
|
+
for (const config of configs) {
|
|
301
|
+
if (config.disabled) continue;
|
|
302
|
+
const displayOption = config.modelInfo?.displayOption ?? 0;
|
|
303
|
+
if (DEVIN_INTERNAL_MODEL_DISPLAYS.has(displayOption)) continue;
|
|
304
|
+
const uid = config.modelUid.trim();
|
|
305
|
+
if (!uid || seen.has(uid)) continue;
|
|
306
|
+
seen.add(uid);
|
|
307
|
+
const isRouter = displayOption === 3 || config.modelInfo?.isModelRouter === true;
|
|
308
|
+
specs.push(devinModelSpec(config, uid, baseUrl, isRouter));
|
|
309
|
+
if (!isRouter) collectDevinFamilyLane(lanes, config, uid);
|
|
310
|
+
}
|
|
311
|
+
const families = devinDynamicFamilies(lanes.values());
|
|
312
|
+
const dynamic = families.length > 0 ? collapseVariants(specs, { table: { families } }) : specs;
|
|
313
|
+
return collapseVariants(dynamic).sort((a, b) => a.id.localeCompare(b.id));
|
|
314
|
+
}
|
|
315
|
+
//#endregion
|
|
316
|
+
export { fetchDevinModels };
|