@xiaoso/dsh-tool-plus 0.1.0-beta.2 → 0.1.0-beta.4
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.en.md +122 -0
- package/README.md +3 -2
- package/THIRD_PARTY_NOTICES.md +4 -35
- package/lib/abort-B7izMMna.mjs +51 -0
- package/lib/abort-D1_Z5Ut5.mjs +51 -0
- package/lib/abort-dIkZBV7Q.mjs +51 -0
- package/lib/amazon-bedrock-B0nxT06F.mjs +917 -0
- package/lib/amazon-bedrock-D-shAr1X.mjs +917 -0
- package/lib/amazon-bedrock-WQhvjHYu.mjs +917 -0
- package/lib/anthropic-BWsZFzU8.mjs +262 -0
- package/lib/anthropic-CJCauvYz.mjs +3115 -0
- package/lib/anthropic-CMT1Qj1t.mjs +3115 -0
- package/lib/anthropic-CZghe_9U.mjs +3115 -0
- package/lib/anthropic-sCMH7JID.mjs +262 -0
- package/lib/anthropic-tTntD8BD.mjs +262 -0
- package/lib/api-key-login-BzqNdM2y.mjs +157 -0
- package/lib/api-key-login-CWVwvHT1.mjs +157 -0
- package/lib/api-key-login-CpzSezsi.mjs +157 -0
- package/lib/aws-credentials-8Mgn5MAy.mjs +867 -0
- package/lib/aws-credentials-CXryMobh.mjs +867 -0
- package/lib/aws-credentials-ChG79ey-.mjs +867 -0
- package/lib/azure-openai-responses-CNkHiLUh.mjs +274 -0
- package/lib/azure-openai-responses-Cgmc-rbL.mjs +274 -0
- package/lib/azure-openai-responses-DuukbD0F.mjs +274 -0
- package/lib/bun-shim.mjs +252 -12
- package/lib/bundled-references-CSuBco5p.mjs +55 -0
- package/lib/bundled-references-Cavaffah.mjs +55 -0
- package/lib/bundled-references-sLN0YdXU.mjs +55 -0
- package/lib/callback-server-BEFNf-jf.mjs +398 -0
- package/lib/callback-server-CQ5Jo8F-.mjs +398 -0
- package/lib/callback-server-DDSrZ6l_.mjs +398 -0
- package/lib/client.js +111 -41
- package/lib/cursor-B3zg7EHj.mjs +273 -0
- package/lib/cursor-B6TUEmgP.mjs +135 -0
- package/lib/cursor-BIQfBC6V.mjs +135 -0
- package/lib/cursor-D8gvtTL3.mjs +135 -0
- package/lib/cursor-DNk6eXDd.mjs +5470 -0
- package/lib/cursor-DkSX2h3H.mjs +5441 -0
- package/lib/cursor-MjSm74IJ.mjs +273 -0
- package/lib/cursor-aJrXeYCb.mjs +273 -0
- package/lib/cursor-mJQwUKXK.mjs +5441 -0
- package/lib/device-code-DBo3B5nh.mjs +51 -0
- package/lib/device-code-DIb0FU-H.mjs +51 -0
- package/lib/device-code-OI_tQcmc.mjs +51 -0
- package/lib/devin-BHZZyMhO.mjs +95 -0
- package/lib/devin-BK7DHeca.mjs +114 -0
- package/lib/devin-CfMp3cXS.mjs +95 -0
- package/lib/devin-CldyPD8K.mjs +95 -0
- package/lib/devin-CzRpTUOA.mjs +114 -0
- package/lib/devin-D9zR5B_R.mjs +542 -0
- package/lib/devin-DXOeNyU7.mjs +542 -0
- package/lib/devin-Q1yem3lp.mjs +114 -0
- package/lib/devin-vNZTNUON.mjs +542 -0
- package/lib/error-B3bevhrs.mjs +1449 -0
- package/lib/error-Dd8DIqs-.mjs +1449 -0
- package/lib/error-yCSG0mGC.mjs +1449 -0
- package/lib/event-stream-BDPi64mK.mjs +151 -0
- package/lib/event-stream-BbFZJy-z.mjs +151 -0
- package/lib/event-stream-loUa0s1T.mjs +151 -0
- package/lib/fs-promises-shim-Bx0fpxuk.mjs +57 -0
- package/lib/github-copilot-4GaMtQmg.mjs +208 -0
- package/lib/github-copilot-B1yiyVRh.mjs +104 -0
- package/lib/github-copilot-B2HGSIJK.mjs +104 -0
- package/lib/github-copilot-BWT3eAOF.mjs +208 -0
- package/lib/github-copilot-CYkjeTi3.mjs +208 -0
- package/lib/github-copilot-jscUZ8Hf.mjs +104 -0
- package/lib/gitlab-duo-CM7Ref1H.mjs +155 -0
- package/lib/gitlab-duo-akICyfeD.mjs +155 -0
- package/lib/gitlab-duo-gubO4FNw.mjs +155 -0
- package/lib/gitlab-duo-workflow-BGAF6JDw.mjs +91 -0
- package/lib/gitlab-duo-workflow-CSEgYk3N.mjs +91 -0
- package/lib/gitlab-duo-workflow-D78tdn8E.mjs +91 -0
- package/lib/google-BS4T25Pn.mjs +30 -0
- package/lib/google-TFe-7-of.mjs +30 -0
- package/lib/google-antigravity-DGmwC2KV.mjs +198 -0
- package/lib/google-antigravity-DNYhgTpA.mjs +198 -0
- package/lib/google-antigravity-Dlkdhahq.mjs +198 -0
- package/lib/google-auth-B6gjsZvg.mjs +232 -0
- package/lib/google-auth-De7_s3eo.mjs +232 -0
- package/lib/google-auth-DhqpOYrX.mjs +232 -0
- package/lib/google-gemini-cli-BG_LRdIV.mjs +850 -0
- package/lib/google-gemini-cli-CWu8HvXW.mjs +211 -0
- package/lib/google-gemini-cli-Cb97bzQc.mjs +850 -0
- package/lib/google-gemini-cli-Cqds_Q5T.mjs +850 -0
- package/lib/google-gemini-cli-Dsztq0N5.mjs +211 -0
- package/lib/google-gemini-cli-zJhiOcND.mjs +211 -0
- package/lib/google-oauth-shared-CuEHaDDj.mjs +147 -0
- package/lib/google-oauth-shared-CwNWYdmR.mjs +147 -0
- package/lib/google-oauth-shared-yqlyqPPC.mjs +147 -0
- package/lib/google-shared-CgKmmdO3.mjs +760 -0
- package/lib/google-shared-Dr-VG-ap.mjs +760 -0
- package/lib/google-shared-DzhCb9b0.mjs +760 -0
- package/lib/google-vertex-BDN2tLaD.mjs +99 -0
- package/lib/google-vertex-DopVOQOG.mjs +99 -0
- package/lib/google-vertex-kscbkyRb.mjs +99 -0
- package/lib/google-zyDOG9x7.mjs +30 -0
- package/lib/identity-Da1GPU9a.mjs +219 -0
- package/lib/identity-DnB63pS7.mjs +219 -0
- package/lib/identity-xRP7_eSR.mjs +219 -0
- package/lib/idle-iterator-Baoyn3Hp.mjs +366 -0
- package/lib/idle-iterator-C6XbWcuB.mjs +366 -0
- package/lib/idle-iterator-DUjKQEGT.mjs +366 -0
- package/lib/index.mjs +4608 -3935
- package/lib/kimi--wUOWER5.mjs +236 -0
- package/lib/kimi-DMVI-zrZ.mjs +236 -0
- package/lib/kimi-Dh0pv3WZ.mjs +236 -0
- package/lib/markit-BL3cH47U.mjs +1417 -0
- package/lib/markit-BNiNY6SE.mjs +1417 -0
- package/lib/markit-M0jhziqU.mjs +1417 -0
- package/lib/minimax-code-BK-3eBbz.mjs +53 -0
- package/lib/minimax-code-DCbuA6Yk.mjs +53 -0
- package/lib/minimax-code-Uq8Qu9LW.mjs +53 -0
- package/lib/models-CfT4coYT.mjs +104660 -0
- package/lib/models-D_XnT6ay.mjs +104660 -0
- package/lib/models-SGASygJ3.mjs +104660 -0
- package/lib/ollama-BQMGPxtV.mjs +589 -0
- package/lib/ollama-DPzBmq89.mjs +589 -0
- package/lib/ollama-DoBz5SFm.mjs +589 -0
- package/lib/openai-codex-Bi-4S4PX.mjs +255 -0
- package/lib/openai-codex-CQL_kvYL.mjs +255 -0
- package/lib/openai-codex-Ch8CkT3p.mjs +255 -0
- package/lib/openai-codex-responses-CvxL_FMF.mjs +3144 -0
- package/lib/openai-codex-responses-Cz-2qpC7.mjs +3144 -0
- package/lib/openai-codex-responses-pejZgdZo.mjs +3144 -0
- package/lib/openai-completions-CF8IyNtP.mjs +1360 -0
- package/lib/openai-completions-DIf361kF.mjs +1360 -0
- package/lib/openai-completions-i8doczAk.mjs +1360 -0
- package/lib/openai-reasoning-fallback-DGVVLgd1.mjs +286 -0
- package/lib/openai-reasoning-fallback-Nj6yB2rY.mjs +286 -0
- package/lib/openai-reasoning-fallback-OdJREP1o.mjs +286 -0
- package/lib/openai-responses-BqXJInHX.mjs +867 -0
- package/lib/openai-responses-DTkBiiy-.mjs +867 -0
- package/lib/openai-responses-Db_a-U4-.mjs +867 -0
- package/lib/opencode-DaJjcUbf.mjs +38 -0
- package/lib/opencode-DhMolSoB.mjs +38 -0
- package/lib/opencode-Rq_Q2vAO.mjs +38 -0
- package/lib/perplexity-9b-RQ0mV.mjs +194 -0
- package/lib/perplexity-C4iLVMUj.mjs +194 -0
- package/lib/perplexity-Uu7Jzg5b.mjs +194 -0
- package/lib/proxy-DDqrmjjC.mjs +190 -0
- package/lib/proxy-ZtUcl6r5.mjs +190 -0
- package/lib/proxy-pM_NIv-H.mjs +190 -0
- package/lib/request-debug-HJMoJncL.mjs +183 -0
- package/lib/sanitize-text-CfcXzw5X.mjs +33 -0
- package/lib/scrapers-BkFfcPHj.mjs +9198 -0
- package/lib/scrapers-CL-WgdU1.mjs +9198 -0
- package/lib/scrapers-CVptboMs.mjs +9198 -0
- package/lib/scrapers-CipyKyCH.mjs +9198 -0
- package/lib/scrapers-DGfrYhtw.mjs +9198 -0
- package/lib/scrapers-DSUPYoUF.mjs +9198 -0
- package/lib/scrapers-DZ2GXmp7.mjs +9198 -0
- package/lib/scrapers-nhQAvc8d.mjs +9198 -0
- package/lib/shell-snapshot-fn-env.sh +67 -43
- package/lib/src-BgpusnsB.mjs +5076 -0
- package/lib/src-DTid0g4K.mjs +5001 -0
- package/lib/src-lDmkSRbm.mjs +5006 -0
- package/lib/stream-BlldLkVq.mjs +10236 -0
- package/lib/stream-CRtexYLe.mjs +10236 -0
- package/lib/stream-C_RAoxJC.mjs +10236 -0
- package/lib/stream-markup-healing-2toHXWXM.mjs +491 -0
- package/lib/stream-markup-healing-DMsxBx1L.mjs +491 -0
- package/lib/stream-markup-healing-KMkiAA00.mjs +491 -0
- package/lib/turndown-DN7ByzEI.mjs +667 -0
- package/lib/types/client/locales.d.ts +1 -1
- package/lib/types/config/fields.d.ts +1 -1
- package/lib/types/config/settings.d.ts +25 -3
- package/lib/types/config/truncate.d.ts +9 -5
- package/lib/types/tools/bash/background.d.ts +1 -1
- package/lib/types/tools/bash/bash-executor.d.ts +4 -0
- package/lib/types/tools/bash/bash-interceptor.d.ts +10 -8
- package/lib/types/tools/bash/cd-workdir.d.ts +35 -0
- package/lib/types/tools/bash/non-interactive-env.d.ts +2 -0
- package/lib/types/tools/bash/render.d.ts +4 -3
- package/lib/types/tools/bash/sanitize-text.d.ts +5 -0
- package/lib/types/tools/bash/shell-snapshot.d.ts +4 -1
- package/lib/types/tools/bash/shell-tokenize.d.ts +60 -0
- package/lib/types/tools/bash/streaming-output.d.ts +12 -212
- package/lib/types/tools/bash/which.d.ts +20 -0
- package/lib/types/tools/bash/windows-shell.d.ts +31 -0
- package/lib/types/tools/edit/adapter/index.d.ts +25 -3
- package/lib/types/tools/edit/adapter/tools/auto-generated-guard.d.ts +7 -17
- package/lib/types/tools/glob/adapter/index.d.ts +27 -1
- package/lib/types/tools/grep/adapter/index.d.ts +29 -1
- package/lib/types/tools/omp/edit/dispatch.d.ts +43 -0
- package/lib/types/tools/omp/edit/hashline/noop-loop-guard.d.ts +3 -1
- package/lib/types/tools/omp/sdk.d.ts +6 -0
- package/lib/types/tools/omp/tools/auto-generated-guard.d.ts +20 -0
- package/lib/types/tools/omp/tools/fetch.d.ts +2 -0
- package/lib/types/tools/omp/tools/read.d.ts +2 -8
- package/lib/types/tools/omp/tools/write.d.ts +4 -4
- package/lib/types/tools/omp/utils/image-loading.d.ts +10 -36
- package/lib/types/tools/read/adapter/index.d.ts +4 -1
- package/lib/types/tools/read-image/index.d.ts +4 -0
- package/lib/types/tools/shared/auto-generated-guard.dsh.d.ts +16 -4
- package/lib/types/tools/shared/bun-shim.d.ts +39 -3
- package/lib/types/tools/shared/fs-promises-shim.d.ts +3 -1
- package/lib/types/tools/shared/image-bridge.d.ts +98 -0
- package/lib/types/tools/shared/omp-prompt.d.ts +17 -9
- package/lib/types/tools/shared/session-state.d.ts +9 -3
- package/lib/utils-2Wq2eATG.mjs +8119 -0
- package/lib/utils-BnX8O3vi.mjs +12303 -0
- package/lib/utils-Bw139LTz.mjs +8119 -0
- package/lib/utils-CE8N8P4Q.mjs +12315 -0
- package/lib/utils-CZw4tVZQ.mjs +12315 -0
- package/lib/utils-C_MrQ_0z.mjs +12301 -0
- package/lib/utils-CiGN7OHR.mjs +12315 -0
- package/lib/utils-Cp76gCyk.mjs +8119 -0
- package/lib/utils-D0GRDgAr.mjs +12315 -0
- package/lib/utils-D0Z1fyoO.mjs +12299 -0
- package/lib/utils-D2YknRk4.mjs +51 -0
- package/lib/utils-DppGHXQB.mjs +51 -0
- package/lib/utils-DzXZDfYc.mjs +51 -0
- package/lib/utils-W8WdSBpX.mjs +12315 -0
- package/lib/vision-guard-01qSwFpf.mjs +92 -0
- package/lib/vision-guard-BDD4OrKo.mjs +92 -0
- package/lib/vision-guard-DzZGaOga.mjs +92 -0
- package/lib/wafer-CgtPHerf.mjs +17 -0
- package/lib/wafer-DRU0EjZX.mjs +17 -0
- package/lib/wafer-cBtrn6q9.mjs +17 -0
- package/lib/xai-oauth-Buk8XVvM.mjs +446 -0
- package/lib/xai-oauth-CMal8l1O.mjs +446 -0
- package/lib/xai-oauth-DPHDXKD7.mjs +446 -0
- package/lib/xiaomi-CZgwvX2G.mjs +157 -0
- package/lib/xiaomi-D2qT5cAC.mjs +157 -0
- package/lib/xiaomi-Dd87KSg5.mjs +157 -0
- package/lib/zai-7DWMkEqM.mjs +203 -0
- package/lib/zai-C59YnomG.mjs +203 -0
- package/lib/zai-CFeOt-53.mjs +203 -0
- package/lib/zip-Cg9ANN_U.mjs +1316 -0
- package/lib/zip-D36ZKsP8.mjs +1316 -0
- package/lib/zip-D6QXpvaJ.mjs +1316 -0
- package/package.json +14 -10
- package/presets/package.json +1 -1
- package/presets/tool-plus-ptc/preset.yml +1 -1
- package/presets/tool-plus-standard/preset.yml +1 -1
|
@@ -0,0 +1,542 @@
|
|
|
1
|
+
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
|
+
__installBunShim();
|
|
3
|
+
import { C as error, S as debug, T as warn, _ as parseStreamingJsonThrottled, g as parseStreamingJson } from "./src-DTid0g4K.mjs";
|
|
4
|
+
import { l as finalize, o as DevinApiError, r as ValidationError, s as ProviderResponseError, w as create, x as attach, y as Flag } from "./error-B3bevhrs.mjs";
|
|
5
|
+
import { a as normalizeSystemPrompts, g as isDemotedThinking, k as toolWireSchema, m as transformMessages } from "./utils-2Wq2eATG.mjs";
|
|
6
|
+
import { t as calculateCost } from "./models-CfT4coYT.mjs";
|
|
7
|
+
import { t as AssistantMessageEventStream } from "./event-stream-BDPi64mK.mjs";
|
|
8
|
+
import { E as create$1, c as messageDesc, i as fromBinary, r as fileDesc, t as toBinary } from "./to-binary-B1BEBIPC.mjs";
|
|
9
|
+
import { a as ChatMessagePromptSchema, c as PromptCacheOptionsSchema, d as ImageDataSchema, f as MetadataSchema, l as ChatToolCallSchema, m as file_buf_validate_validate, n as GetChatMessageResponseSchema, o as ChatToolChoiceSchema, p as file_exa_codeium_common_pb_codeium_common, s as ChatToolDefinitionSchema, t as GetChatMessageRequestSchema, u as CompletionConfigurationSchema } from "./api_server_pb-CDZgLMta.mjs";
|
|
10
|
+
import { t as deterministicUuid } from "./deterministic-id-D-yIV_eI.mjs";
|
|
11
|
+
import { gunzipSync, gzipSync } from "node:zlib";
|
|
12
|
+
//#region node_modules/.pnpm/@oh-my-pi+pi-catalog@17.3.5/node_modules/@oh-my-pi/pi-catalog/src/discovery/devin-gen/exa/auth_pb/auth_pb.ts
|
|
13
|
+
/**
|
|
14
|
+
* Describes the file exa/auth_pb/auth.proto.
|
|
15
|
+
*/
|
|
16
|
+
const file_exa_auth_pb_auth = /*@__PURE__*/ fileDesc("ChZleGEvYXV0aF9wYi9hdXRoLnByb3RvEgtleGEuYXV0aF9wYiJGChFHZXRVc2VySnd0UmVxdWVzdBIxCghtZXRhZGF0YRgBIAEoCzIfLmV4YS5jb2RlaXVtX2NvbW1vbl9wYi5NZXRhZGF0YSJFChJHZXRVc2VySnd0UmVzcG9uc2USEAoIdXNlcl9qd3QYASABKAkSHQoVY3VzdG9tX2FwaV9zZXJ2ZXJfdXJsGAIgASgJMlwKC0F1dGhTZXJ2aWNlEk0KCkdldFVzZXJKd3QSHi5leGEuYXV0aF9wYi5HZXRVc2VySnd0UmVxdWVzdBofLmV4YS5hdXRoX3BiLkdldFVzZXJKd3RSZXNwb25zZWIGcHJvdG8z", [file_buf_validate_validate, file_exa_codeium_common_pb_codeium_common]);
|
|
17
|
+
/**
|
|
18
|
+
* Describes the message exa.auth_pb.GetUserJwtRequest.
|
|
19
|
+
* Use `create(GetUserJwtRequestSchema)` to create a new message.
|
|
20
|
+
*/
|
|
21
|
+
const GetUserJwtRequestSchema = /*@__PURE__*/ messageDesc(file_exa_auth_pb_auth, 0);
|
|
22
|
+
/**
|
|
23
|
+
* Describes the message exa.auth_pb.GetUserJwtResponse.
|
|
24
|
+
* Use `create(GetUserJwtResponseSchema)` to create a new message.
|
|
25
|
+
*/
|
|
26
|
+
const GetUserJwtResponseSchema = /*@__PURE__*/ messageDesc(file_exa_auth_pb_auth, 1);
|
|
27
|
+
const CHAT_MESSAGE_PATH = "/exa.api_server_pb.ApiServerService/GetChatMessage";
|
|
28
|
+
const DEVIN_IDE_VERSION = "3.2.23";
|
|
29
|
+
const DEVIN_EXTENSION_VERSION = "1.48.2";
|
|
30
|
+
const DEVIN_SESSION_TOKEN_PREFIX = "devin-session-token$";
|
|
31
|
+
const DEVIN_AUTH_PATH = "/exa.auth_pb.AuthService/GetUserJwt";
|
|
32
|
+
const DEVIN_DEFAULT_STOP_PATTERNS = [
|
|
33
|
+
"<|user|>",
|
|
34
|
+
"<|bot|>",
|
|
35
|
+
"<|context_request|>",
|
|
36
|
+
"<|endoftext|>",
|
|
37
|
+
"<|end_of_turn|>"
|
|
38
|
+
];
|
|
39
|
+
/** Connect streaming framing: flag byte bit 0x01 = gzip payload, 0x02 = end-of-stream JSON trailers. */
|
|
40
|
+
const CONNECT_COMPRESSED_FLAG = 1;
|
|
41
|
+
const CONNECT_END_STREAM_FLAG = 2;
|
|
42
|
+
/**
|
|
43
|
+
* Hard upper bound on a single Connect frame payload. The 4-byte length prefix
|
|
44
|
+
* is otherwise attacker-controlled (up to `2**32 - 1`), so a malicious or buggy
|
|
45
|
+
* peer could force {@link streamDevin}'s reader to buffer gigabytes via
|
|
46
|
+
* `Buffer.concat` before the idle-timeout wrapper aborts. Well above any
|
|
47
|
+
* legitimate Cascade response but tight enough that a corrupt length prefix
|
|
48
|
+
* fails fast instead of consuming memory.
|
|
49
|
+
*/
|
|
50
|
+
const MAX_CONNECT_FRAME_PAYLOAD = 16777216;
|
|
51
|
+
/**
|
|
52
|
+
* Recovery heuristic for opaque Devin `invalid_argument` trailers. This is not
|
|
53
|
+
* asserted to be the backend's hard limit: small requests can hit the same
|
|
54
|
+
* intermittent error, while compactable message history this large is likely
|
|
55
|
+
* to benefit from the existing context-overflow maintenance path.
|
|
56
|
+
*/
|
|
57
|
+
const LARGE_HISTORY_RECOVERY_BYTES = 524288;
|
|
58
|
+
const streamDevin = (model, context, options) => {
|
|
59
|
+
const stream = new AssistantMessageEventStream();
|
|
60
|
+
(async () => {
|
|
61
|
+
const startTime = performance.now();
|
|
62
|
+
let firstTokenTime;
|
|
63
|
+
const output = {
|
|
64
|
+
role: "assistant",
|
|
65
|
+
content: [],
|
|
66
|
+
api: "devin-agent",
|
|
67
|
+
provider: model.provider,
|
|
68
|
+
model: model.id,
|
|
69
|
+
usage: {
|
|
70
|
+
input: 0,
|
|
71
|
+
output: 0,
|
|
72
|
+
cacheRead: 0,
|
|
73
|
+
cacheWrite: 0,
|
|
74
|
+
totalTokens: 0,
|
|
75
|
+
cost: {
|
|
76
|
+
input: 0,
|
|
77
|
+
output: 0,
|
|
78
|
+
cacheRead: 0,
|
|
79
|
+
cacheWrite: 0,
|
|
80
|
+
total: 0
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
stopReason: "stop",
|
|
84
|
+
timestamp: Date.now()
|
|
85
|
+
};
|
|
86
|
+
let currentTextBlock = null;
|
|
87
|
+
let currentThinkingBlock = null;
|
|
88
|
+
const toolBlocks = /* @__PURE__ */ new Map();
|
|
89
|
+
const toolPartialJson = /* @__PURE__ */ new Map();
|
|
90
|
+
const toolLastParseLen = /* @__PURE__ */ new Map();
|
|
91
|
+
let activeToolCallId;
|
|
92
|
+
let latestStopReason = 0;
|
|
93
|
+
const markFirstToken = () => {
|
|
94
|
+
if (firstTokenTime === void 0) firstTokenTime = performance.now();
|
|
95
|
+
};
|
|
96
|
+
const endTextBlock = () => {
|
|
97
|
+
const block = currentTextBlock;
|
|
98
|
+
if (!block) return;
|
|
99
|
+
currentTextBlock = null;
|
|
100
|
+
stream.push({
|
|
101
|
+
type: "text_end",
|
|
102
|
+
contentIndex: output.content.indexOf(block),
|
|
103
|
+
content: block.text,
|
|
104
|
+
partial: output
|
|
105
|
+
});
|
|
106
|
+
};
|
|
107
|
+
const endThinkingBlock = () => {
|
|
108
|
+
const block = currentThinkingBlock;
|
|
109
|
+
if (!block) return;
|
|
110
|
+
currentThinkingBlock = null;
|
|
111
|
+
stream.push({
|
|
112
|
+
type: "thinking_end",
|
|
113
|
+
contentIndex: output.content.indexOf(block),
|
|
114
|
+
content: block.thinking,
|
|
115
|
+
partial: output
|
|
116
|
+
});
|
|
117
|
+
};
|
|
118
|
+
try {
|
|
119
|
+
const fetchImpl = options?.fetch ?? fetch;
|
|
120
|
+
const baseUrl = (model.baseUrl || "https://server.codeium.com").replace(/\/+$/, "");
|
|
121
|
+
const apiKey = normalizeDevinSessionToken(options?.apiKey);
|
|
122
|
+
const auth = await fetchDevinAuthMetadata(apiKey, baseUrl, fetchImpl, options?.signal);
|
|
123
|
+
const chatBaseUrl = auth.baseUrl ?? baseUrl;
|
|
124
|
+
const request = buildDevinChatRequest(model, context, options, apiKey, auth.userJwt);
|
|
125
|
+
const reqBytes = toBinary(GetChatMessageRequestSchema, request);
|
|
126
|
+
const gz = gzipSync(reqBytes);
|
|
127
|
+
debug("devin: sending chat request", {
|
|
128
|
+
model: model.id,
|
|
129
|
+
tools: context.tools?.length ?? 0,
|
|
130
|
+
requestBytes: reqBytes.byteLength,
|
|
131
|
+
compressedBytes: gz.byteLength
|
|
132
|
+
});
|
|
133
|
+
const frame = Buffer.alloc(5 + gz.length);
|
|
134
|
+
frame[0] = CONNECT_COMPRESSED_FLAG;
|
|
135
|
+
frame.writeUInt32BE(gz.length, 1);
|
|
136
|
+
frame.set(gz, 5);
|
|
137
|
+
const response = await fetchImpl(chatBaseUrl + CHAT_MESSAGE_PATH, {
|
|
138
|
+
method: "POST",
|
|
139
|
+
headers: {
|
|
140
|
+
"content-type": "application/connect+proto",
|
|
141
|
+
"connect-protocol-version": "1",
|
|
142
|
+
"connect-content-encoding": "gzip",
|
|
143
|
+
"accept-encoding": "identity",
|
|
144
|
+
"user-agent": "connect-go/1.18.1 (go1.26.3)",
|
|
145
|
+
"connect-accept-encoding": "gzip",
|
|
146
|
+
...options?.headers ?? {}
|
|
147
|
+
},
|
|
148
|
+
body: frame,
|
|
149
|
+
signal: options?.signal
|
|
150
|
+
});
|
|
151
|
+
if (!response.ok) {
|
|
152
|
+
const text = await response.text();
|
|
153
|
+
throw new DevinApiError(`Devin API error ${response.status} ${response.statusText}: ${text}`, response.status);
|
|
154
|
+
}
|
|
155
|
+
if (!response.body) throw new ProviderResponseError("Devin API error: response body is empty", {
|
|
156
|
+
provider: model.provider,
|
|
157
|
+
kind: "empty-body"
|
|
158
|
+
});
|
|
159
|
+
const body = response.body;
|
|
160
|
+
stream.push({
|
|
161
|
+
type: "start",
|
|
162
|
+
partial: output
|
|
163
|
+
});
|
|
164
|
+
const reader = body.getReader();
|
|
165
|
+
let pending = Buffer.alloc(0);
|
|
166
|
+
for (;;) {
|
|
167
|
+
const { done, value } = await reader.read();
|
|
168
|
+
if (value && value.length > 0) pending = pending.length === 0 ? Buffer.from(value.buffer, value.byteOffset, value.byteLength) : Buffer.concat([pending, value]);
|
|
169
|
+
while (pending.length >= 5) {
|
|
170
|
+
const flag = pending[0];
|
|
171
|
+
const len = pending.readUInt32BE(1);
|
|
172
|
+
if (len > MAX_CONNECT_FRAME_PAYLOAD) throw new ProviderResponseError(`Devin Connect frame length ${len} exceeds ${MAX_CONNECT_FRAME_PAYLOAD}-byte cap`, {
|
|
173
|
+
provider: model.provider,
|
|
174
|
+
kind: "envelope"
|
|
175
|
+
});
|
|
176
|
+
if (pending.length < 5 + len) break;
|
|
177
|
+
const payload = pending.subarray(5, 5 + len);
|
|
178
|
+
pending = pending.subarray(5 + len);
|
|
179
|
+
if (flag & CONNECT_END_STREAM_FLAG) {
|
|
180
|
+
const trailerError = readConnectTrailerError((flag & CONNECT_COMPRESSED_FLAG ? gunzipSync(payload) : payload).toString("utf8").trim());
|
|
181
|
+
if (trailerError) {
|
|
182
|
+
const error = new ValidationError(trailerError.formatted);
|
|
183
|
+
if (firstTokenTime === void 0 && trailerError.code.toLowerCase() === "invalid_argument" && /\binternal error\b/i.test(trailerError.message)) {
|
|
184
|
+
let activeTailCount = 0;
|
|
185
|
+
const lastRole = context.messages.at(-1)?.role;
|
|
186
|
+
if (lastRole === "user" || lastRole === "developer") {
|
|
187
|
+
activeTailCount = 1;
|
|
188
|
+
if (lastRole === "developer") for (let i = context.messages.length - 2; i >= 0; i--) {
|
|
189
|
+
const role = context.messages[i].role;
|
|
190
|
+
if (role !== "user" && role !== "developer") break;
|
|
191
|
+
activeTailCount++;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
const shrinkablePrompts = activeTailCount > 0 ? request.chatMessagePrompts.slice(0, -activeTailCount) : request.chatMessagePrompts;
|
|
195
|
+
const historyBytes = toBinary(GetChatMessageRequestSchema, create$1(GetChatMessageRequestSchema, { chatMessagePrompts: shrinkablePrompts })).byteLength;
|
|
196
|
+
if (historyBytes >= LARGE_HISTORY_RECOVERY_BYTES) {
|
|
197
|
+
attach(error, create(Flag.ContextOverflow));
|
|
198
|
+
warn("devin: treating large-history invalid_argument as context overflow", {
|
|
199
|
+
model: model.id,
|
|
200
|
+
historyBytes,
|
|
201
|
+
requestBytes: reqBytes.byteLength,
|
|
202
|
+
compressedBytes: gz.byteLength
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
throw error;
|
|
207
|
+
}
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
const raw = flag & CONNECT_COMPRESSED_FLAG ? gunzipSync(payload) : payload;
|
|
211
|
+
const msg = fromBinary(GetChatMessageResponseSchema, raw);
|
|
212
|
+
if (msg.messageId && !output.responseId) output.responseId = msg.messageId;
|
|
213
|
+
if (msg.deltaThinking) {
|
|
214
|
+
markFirstToken();
|
|
215
|
+
const block = currentThinkingBlock ?? {
|
|
216
|
+
type: "thinking",
|
|
217
|
+
thinking: ""
|
|
218
|
+
};
|
|
219
|
+
if (currentThinkingBlock !== block) {
|
|
220
|
+
output.content.push(block);
|
|
221
|
+
currentThinkingBlock = block;
|
|
222
|
+
stream.push({
|
|
223
|
+
type: "thinking_start",
|
|
224
|
+
contentIndex: output.content.length - 1,
|
|
225
|
+
partial: output
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
block.thinking += msg.deltaThinking;
|
|
229
|
+
if (msg.deltaSignature) block.thinkingSignature = msg.deltaSignature;
|
|
230
|
+
stream.push({
|
|
231
|
+
type: "thinking_delta",
|
|
232
|
+
contentIndex: output.content.indexOf(block),
|
|
233
|
+
delta: msg.deltaThinking,
|
|
234
|
+
partial: output
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
if (msg.deltaText) {
|
|
238
|
+
markFirstToken();
|
|
239
|
+
endThinkingBlock();
|
|
240
|
+
const block = currentTextBlock ?? {
|
|
241
|
+
type: "text",
|
|
242
|
+
text: ""
|
|
243
|
+
};
|
|
244
|
+
if (currentTextBlock !== block) {
|
|
245
|
+
output.content.push(block);
|
|
246
|
+
currentTextBlock = block;
|
|
247
|
+
stream.push({
|
|
248
|
+
type: "text_start",
|
|
249
|
+
contentIndex: output.content.length - 1,
|
|
250
|
+
partial: output
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
block.text += msg.deltaText;
|
|
254
|
+
stream.push({
|
|
255
|
+
type: "text_delta",
|
|
256
|
+
contentIndex: output.content.indexOf(block),
|
|
257
|
+
delta: msg.deltaText,
|
|
258
|
+
partial: output
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
if (msg.deltaToolCalls.length > 0) {
|
|
262
|
+
markFirstToken();
|
|
263
|
+
endTextBlock();
|
|
264
|
+
endThinkingBlock();
|
|
265
|
+
for (const tc of msg.deltaToolCalls) {
|
|
266
|
+
const toolCallId = tc.id || activeToolCallId;
|
|
267
|
+
if (!toolCallId) continue;
|
|
268
|
+
let block = toolBlocks.get(toolCallId);
|
|
269
|
+
if (!block) {
|
|
270
|
+
block = {
|
|
271
|
+
type: "toolCall",
|
|
272
|
+
id: toolCallId,
|
|
273
|
+
name: tc.name,
|
|
274
|
+
arguments: {}
|
|
275
|
+
};
|
|
276
|
+
output.content.push(block);
|
|
277
|
+
toolBlocks.set(toolCallId, block);
|
|
278
|
+
toolPartialJson.set(toolCallId, "");
|
|
279
|
+
stream.push({
|
|
280
|
+
type: "toolcall_start",
|
|
281
|
+
contentIndex: output.content.length - 1,
|
|
282
|
+
partial: output
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
if (tc.name) block.name = tc.name;
|
|
286
|
+
activeToolCallId = toolCallId;
|
|
287
|
+
if (!tc.argumentsJson) continue;
|
|
288
|
+
const previousJson = toolPartialJson.get(toolCallId) ?? "";
|
|
289
|
+
const accumulated = tc.argumentsJson.startsWith(previousJson) ? tc.argumentsJson : previousJson + tc.argumentsJson;
|
|
290
|
+
const delta = accumulated.slice(previousJson.length);
|
|
291
|
+
toolPartialJson.set(toolCallId, accumulated);
|
|
292
|
+
const throttled = parseStreamingJsonThrottled(accumulated, toolLastParseLen.get(toolCallId) ?? 0);
|
|
293
|
+
if (throttled) {
|
|
294
|
+
block.arguments = throttled.value;
|
|
295
|
+
toolLastParseLen.set(toolCallId, throttled.parsedLen);
|
|
296
|
+
}
|
|
297
|
+
stream.push({
|
|
298
|
+
type: "toolcall_delta",
|
|
299
|
+
contentIndex: output.content.indexOf(block),
|
|
300
|
+
delta,
|
|
301
|
+
partial: output
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
if (msg.stopReason !== 0) latestStopReason = msg.stopReason;
|
|
306
|
+
if (msg.usage) {
|
|
307
|
+
output.usage.input = Number(msg.usage.inputTokens);
|
|
308
|
+
output.usage.output = Number(msg.usage.outputTokens);
|
|
309
|
+
output.usage.cacheRead = Number(msg.usage.cacheReadTokens);
|
|
310
|
+
output.usage.cacheWrite = Number(msg.usage.cacheWriteTokens);
|
|
311
|
+
output.usage.totalTokens = output.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
if (done) break;
|
|
315
|
+
}
|
|
316
|
+
endTextBlock();
|
|
317
|
+
endThinkingBlock();
|
|
318
|
+
for (const [id, block] of toolBlocks) {
|
|
319
|
+
block.arguments = parseStreamingJson(toolPartialJson.get(id));
|
|
320
|
+
stream.push({
|
|
321
|
+
type: "toolcall_end",
|
|
322
|
+
contentIndex: output.content.indexOf(block),
|
|
323
|
+
toolCall: block,
|
|
324
|
+
partial: output
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
const doneReason = toolBlocks.size > 0 ? "toolUse" : latestStopReason === 3 ? "length" : "stop";
|
|
328
|
+
output.stopReason = doneReason;
|
|
329
|
+
calculateCost(model, output.usage);
|
|
330
|
+
output.duration = performance.now() - startTime;
|
|
331
|
+
if (firstTokenTime) output.ttft = firstTokenTime - startTime;
|
|
332
|
+
stream.push({
|
|
333
|
+
type: "done",
|
|
334
|
+
reason: doneReason,
|
|
335
|
+
message: output
|
|
336
|
+
});
|
|
337
|
+
stream.end();
|
|
338
|
+
} catch (error$1) {
|
|
339
|
+
error("devin: stream failed", { error: String(error$1) });
|
|
340
|
+
const result = await finalize(error$1, {
|
|
341
|
+
api: model.api,
|
|
342
|
+
signal: options?.signal
|
|
343
|
+
});
|
|
344
|
+
output.stopReason = result.stopReason;
|
|
345
|
+
output.errorStatus = result.status;
|
|
346
|
+
output.errorId = result.id;
|
|
347
|
+
output.errorMessage = result.message;
|
|
348
|
+
output.duration = performance.now() - startTime;
|
|
349
|
+
if (firstTokenTime) output.ttft = firstTokenTime - startTime;
|
|
350
|
+
stream.push({
|
|
351
|
+
type: "error",
|
|
352
|
+
reason: result.stopReason,
|
|
353
|
+
error: output
|
|
354
|
+
});
|
|
355
|
+
stream.end();
|
|
356
|
+
}
|
|
357
|
+
})();
|
|
358
|
+
return stream;
|
|
359
|
+
};
|
|
360
|
+
function normalizeDevinSessionToken(apiKey) {
|
|
361
|
+
if (!apiKey) return "";
|
|
362
|
+
return apiKey.startsWith(DEVIN_SESSION_TOKEN_PREFIX) ? apiKey : `${DEVIN_SESSION_TOKEN_PREFIX}${apiKey}`;
|
|
363
|
+
}
|
|
364
|
+
async function fetchDevinAuthMetadata(apiKey, baseUrl, fetchImpl, signal) {
|
|
365
|
+
const request = create$1(GetUserJwtRequestSchema, { metadata: create$1(MetadataSchema, {
|
|
366
|
+
apiKey,
|
|
367
|
+
ideName: "windsurf",
|
|
368
|
+
ideVersion: DEVIN_IDE_VERSION,
|
|
369
|
+
extensionName: "windsurf",
|
|
370
|
+
extensionVersion: DEVIN_EXTENSION_VERSION,
|
|
371
|
+
locale: "en"
|
|
372
|
+
}) });
|
|
373
|
+
const response = await fetchImpl(`${baseUrl}${DEVIN_AUTH_PATH}`, {
|
|
374
|
+
method: "POST",
|
|
375
|
+
headers: {
|
|
376
|
+
"content-type": "application/proto",
|
|
377
|
+
"connect-protocol-version": "1",
|
|
378
|
+
accept: "*/*"
|
|
379
|
+
},
|
|
380
|
+
body: toBinary(GetUserJwtRequestSchema, request),
|
|
381
|
+
signal
|
|
382
|
+
});
|
|
383
|
+
const payload = new Uint8Array(await response.arrayBuffer());
|
|
384
|
+
if (!response.ok) throw new DevinApiError(`Devin auth error ${response.status} ${response.statusText}: ${new TextDecoder().decode(payload)}`, response.status);
|
|
385
|
+
const decoded = decodeDevinUserJwtResponse(payload);
|
|
386
|
+
if (!decoded.userJwt) throw new ProviderResponseError("Devin auth error: GetUserJwt returned an empty user JWT", {
|
|
387
|
+
provider: "devin",
|
|
388
|
+
kind: "runtime"
|
|
389
|
+
});
|
|
390
|
+
const customBaseUrl = decoded.customApiServerUrl.trim();
|
|
391
|
+
return {
|
|
392
|
+
userJwt: decoded.userJwt,
|
|
393
|
+
...customBaseUrl ? { baseUrl: customBaseUrl.replace(/\/+$/, "") } : void 0
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
function decodeDevinUserJwtResponse(payload) {
|
|
397
|
+
try {
|
|
398
|
+
return fromBinary(GetUserJwtResponseSchema, payload);
|
|
399
|
+
} catch {
|
|
400
|
+
return fromBinary(GetUserJwtResponseSchema, gunzipSync(payload));
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Build a {@link GetChatMessageRequest} for one Cascade turn. Auth rides inside
|
|
405
|
+
* `Metadata.apiKey`; the system prompt is the flattened `prompt` string and the
|
|
406
|
+
* conversation history maps to `chatMessagePrompts`.
|
|
407
|
+
*/
|
|
408
|
+
function buildDevinChatRequest(model, context, options, apiKey, userJwt) {
|
|
409
|
+
const cascadeId = options?.conversationId ?? options?.sessionId ?? crypto.randomUUID();
|
|
410
|
+
const stopPatterns = options?.stopSequences && options.stopSequences.length > 0 ? [...DEVIN_DEFAULT_STOP_PATTERNS, ...options.stopSequences] : DEVIN_DEFAULT_STOP_PATTERNS;
|
|
411
|
+
const messages = transformMessages(context.messages, model);
|
|
412
|
+
return create$1(GetChatMessageRequestSchema, {
|
|
413
|
+
metadata: create$1(MetadataSchema, {
|
|
414
|
+
apiKey,
|
|
415
|
+
userJwt,
|
|
416
|
+
ideName: "windsurf",
|
|
417
|
+
ideVersion: DEVIN_IDE_VERSION,
|
|
418
|
+
extensionName: "windsurf",
|
|
419
|
+
extensionVersion: DEVIN_EXTENSION_VERSION,
|
|
420
|
+
locale: "en"
|
|
421
|
+
}),
|
|
422
|
+
prompt: normalizeSystemPrompts(context.systemPrompt).join("\n\n"),
|
|
423
|
+
chatMessagePrompts: buildChatMessagePrompts(messages, cascadeId, model),
|
|
424
|
+
chatModelUid: options?.chatModelUid ?? model.requestModelId ?? model.id,
|
|
425
|
+
requestType: 5,
|
|
426
|
+
plannerMode: 1,
|
|
427
|
+
toolChoice: create$1(ChatToolChoiceSchema, { choice: {
|
|
428
|
+
case: "optionName",
|
|
429
|
+
value: "auto"
|
|
430
|
+
} }),
|
|
431
|
+
systemPromptCacheOptions: create$1(PromptCacheOptionsSchema, { type: 1 }),
|
|
432
|
+
disableParallelToolCalls: true,
|
|
433
|
+
cascadeId,
|
|
434
|
+
executionId: crypto.randomUUID(),
|
|
435
|
+
configuration: create$1(CompletionConfigurationSchema, {
|
|
436
|
+
numCompletions: 1n,
|
|
437
|
+
maxTokens: BigInt(options?.maxTokens ?? model.maxTokens ?? 64e3),
|
|
438
|
+
maxNewlines: 200n,
|
|
439
|
+
temperature: options?.temperature ?? .4,
|
|
440
|
+
firstTemperature: options?.temperature ?? .4,
|
|
441
|
+
topK: 50n,
|
|
442
|
+
topP: options?.topP ?? 1,
|
|
443
|
+
stopPatterns,
|
|
444
|
+
fimEotProbThreshold: 1
|
|
445
|
+
}),
|
|
446
|
+
tools: (context.tools ?? []).map((tool) => create$1(ChatToolDefinitionSchema, {
|
|
447
|
+
name: tool.name,
|
|
448
|
+
description: tool.description,
|
|
449
|
+
jsonSchemaString: JSON.stringify(toolWireSchema(tool)),
|
|
450
|
+
strict: tool.strict ?? false
|
|
451
|
+
}))
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
/** Map omp `Message` history onto Cascade `ChatMessagePrompt`s (USER / SYSTEM / TOOL channels). */
|
|
455
|
+
function buildChatMessagePrompts(messages, cascadeId, model) {
|
|
456
|
+
const prompts = [];
|
|
457
|
+
for (const [index, msg] of messages.entries()) if (msg.role === "user" || msg.role === "developer") {
|
|
458
|
+
let promptText = "";
|
|
459
|
+
const images = [];
|
|
460
|
+
if (typeof msg.content === "string") promptText = msg.content;
|
|
461
|
+
else for (const part of msg.content) if (part.type === "text") promptText += part.text;
|
|
462
|
+
else if (part.type === "image") images.push(create$1(ImageDataSchema, {
|
|
463
|
+
base64Data: part.data,
|
|
464
|
+
mimeType: part.mimeType
|
|
465
|
+
}));
|
|
466
|
+
prompts.push(create$1(ChatMessagePromptSchema, {
|
|
467
|
+
messageId: deterministicUuid(`${cascadeId}\0${index}\0${msg.role}`),
|
|
468
|
+
source: 1,
|
|
469
|
+
prompt: promptText,
|
|
470
|
+
images
|
|
471
|
+
}));
|
|
472
|
+
} else if (msg.role === "assistant") {
|
|
473
|
+
const isNativeDevinMessage = msg.api === model.api && msg.provider === model.provider && msg.model === model.id;
|
|
474
|
+
let promptText = "";
|
|
475
|
+
let thinkingText = "";
|
|
476
|
+
let signature = "";
|
|
477
|
+
const toolCalls = [];
|
|
478
|
+
for (const part of msg.content) if (part.type === "text") promptText += `${part.text}${isDemotedThinking(part) ? "\n" : ""}`;
|
|
479
|
+
else if (part.type === "thinking") {
|
|
480
|
+
thinkingText += part.thinking;
|
|
481
|
+
if (isNativeDevinMessage && !signature && part.thinkingSignature) signature = part.thinkingSignature;
|
|
482
|
+
} else if (part.type === "toolCall") toolCalls.push(create$1(ChatToolCallSchema, {
|
|
483
|
+
id: part.id,
|
|
484
|
+
name: part.name,
|
|
485
|
+
argumentsJson: JSON.stringify(part.arguments)
|
|
486
|
+
}));
|
|
487
|
+
if (!promptText && !thinkingText && !signature && toolCalls.length === 0) continue;
|
|
488
|
+
prompts.push(create$1(ChatMessagePromptSchema, {
|
|
489
|
+
messageId: isNativeDevinMessage && msg.responseId ? msg.responseId : `bot-${deterministicUuid(`${cascadeId}\0${index}\0assistant`)}`,
|
|
490
|
+
source: 2,
|
|
491
|
+
prompt: promptText,
|
|
492
|
+
thinking: thinkingText,
|
|
493
|
+
signature,
|
|
494
|
+
signatureType: "",
|
|
495
|
+
toolCalls
|
|
496
|
+
}));
|
|
497
|
+
} else {
|
|
498
|
+
let resultText = "";
|
|
499
|
+
const images = [];
|
|
500
|
+
for (const part of msg.content) if (part.type === "text") resultText += part.text;
|
|
501
|
+
else if (part.type === "image") images.push(create$1(ImageDataSchema, {
|
|
502
|
+
base64Data: part.data,
|
|
503
|
+
mimeType: part.mimeType
|
|
504
|
+
}));
|
|
505
|
+
prompts.push(create$1(ChatMessagePromptSchema, {
|
|
506
|
+
messageId: deterministicUuid(`${cascadeId}\0${index}\0tool\0${msg.toolCallId}`),
|
|
507
|
+
source: 4,
|
|
508
|
+
toolCallId: msg.toolCallId,
|
|
509
|
+
toolResultIsError: msg.isError,
|
|
510
|
+
prompt: resultText,
|
|
511
|
+
images
|
|
512
|
+
}));
|
|
513
|
+
}
|
|
514
|
+
return prompts;
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Parse a Connect end-of-stream JSON trailer and return its structured error
|
|
518
|
+
* when it carries `{ error: { code, message } }`, else `null`. The trailer is
|
|
519
|
+
* untrusted server output, so the shape is checked with guards rather than asserted.
|
|
520
|
+
*/
|
|
521
|
+
function readConnectTrailerError(text) {
|
|
522
|
+
if (text.length === 0) return null;
|
|
523
|
+
let parsed;
|
|
524
|
+
try {
|
|
525
|
+
parsed = JSON.parse(text);
|
|
526
|
+
} catch {
|
|
527
|
+
return null;
|
|
528
|
+
}
|
|
529
|
+
if (!parsed || typeof parsed !== "object" || !("error" in parsed)) return null;
|
|
530
|
+
const err = parsed.error;
|
|
531
|
+
if (!err || typeof err !== "object") return null;
|
|
532
|
+
const code = "code" in err && typeof err.code === "string" ? err.code : "";
|
|
533
|
+
const message = "message" in err && typeof err.message === "string" ? err.message : "";
|
|
534
|
+
if (!code && !message) return null;
|
|
535
|
+
return {
|
|
536
|
+
code,
|
|
537
|
+
message,
|
|
538
|
+
formatted: `Devin stream error${code ? ` ${code}` : ""}: ${message}`
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
//#endregion
|
|
542
|
+
export { streamDevin };
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
|
+
__installBunShim();
|
|
3
|
+
import { n as discoveryFetch } from "./utils-DzXZDfYc.mjs";
|
|
4
|
+
import { E as create, i as fromBinary, t as toBinary } from "./to-binary-B1BEBIPC.mjs";
|
|
5
|
+
import { f as MetadataSchema, i as GetCliModelConfigsResponseSchema, r as GetCliModelConfigsRequestSchema } from "./api_server_pb-CDZgLMta.mjs";
|
|
6
|
+
import { gunzipSync } from "node:zlib";
|
|
7
|
+
//#region node_modules/.pnpm/@oh-my-pi+pi-catalog@17.3.5/node_modules/@oh-my-pi/pi-catalog/src/discovery/devin.ts
|
|
8
|
+
const DEVIN_DEFAULT_BASE_URL = "https://server.codeium.com";
|
|
9
|
+
const DEVIN_GET_CLI_MODEL_CONFIGS_PATH = "/exa.api_server_pb.ApiServerService/GetCliModelConfigs";
|
|
10
|
+
const DEVIN_IDE_VERSION = "3.2.23";
|
|
11
|
+
const DEVIN_EXTENSION_VERSION = "1.48.2";
|
|
12
|
+
const DEVIN_SESSION_TOKEN_PREFIX = "devin-session-token$";
|
|
13
|
+
const DEFAULT_CONTEXT_WINDOW = 2e5;
|
|
14
|
+
const DEFAULT_MAX_TOKENS = 64e3;
|
|
15
|
+
/** Best-effort match for labels whose wording implies a thinking / reasoning-effort variant. */
|
|
16
|
+
const REASONING_LABEL_PATTERN = /think|thinking|minimal|high|medium|low|xhigh|max|reasoning/i;
|
|
17
|
+
const NO_REASONING_LABEL_PATTERN = /\bno thinking\b/i;
|
|
18
|
+
function supportsDevinThinking(config) {
|
|
19
|
+
if (NO_REASONING_LABEL_PATTERN.test(config.label)) return false;
|
|
20
|
+
return config.modelInfo?.modelFeatures?.supportsThinking === true || REASONING_LABEL_PATTERN.test(config.label);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Fetches Devin models through the `GetCliModelConfigs` unary Connect RPC and
|
|
24
|
+
* normalizes them into canonical model entries.
|
|
25
|
+
*
|
|
26
|
+
* Returns `null` on request/decode failures.
|
|
27
|
+
* Returns `[]` only when the endpoint responds successfully with no usable models.
|
|
28
|
+
*/
|
|
29
|
+
async function fetchDevinModels(options) {
|
|
30
|
+
const timeoutMs = options.timeoutMs ?? 5e3;
|
|
31
|
+
const requestUrl = `${(options.baseUrl ?? DEVIN_DEFAULT_BASE_URL).replace(/\/+$/, "")}${DEVIN_GET_CLI_MODEL_CONFIGS_PATH}`;
|
|
32
|
+
const controller = new AbortController();
|
|
33
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
34
|
+
const signal = options.signal ? AbortSignal.any([controller.signal, options.signal]) : controller.signal;
|
|
35
|
+
try {
|
|
36
|
+
const request = create(GetCliModelConfigsRequestSchema, { metadata: create(MetadataSchema, {
|
|
37
|
+
apiKey: normalizeDevinSessionToken(options.apiKey),
|
|
38
|
+
ideName: "windsurf",
|
|
39
|
+
ideVersion: DEVIN_IDE_VERSION,
|
|
40
|
+
extensionName: "windsurf",
|
|
41
|
+
extensionVersion: DEVIN_EXTENSION_VERSION
|
|
42
|
+
}) });
|
|
43
|
+
const body = toBinary(GetCliModelConfigsRequestSchema, request);
|
|
44
|
+
const response = await discoveryFetch(options.fetch)(requestUrl, {
|
|
45
|
+
method: "POST",
|
|
46
|
+
headers: {
|
|
47
|
+
"content-type": "application/proto",
|
|
48
|
+
"connect-protocol-version": "1",
|
|
49
|
+
accept: "*/*"
|
|
50
|
+
},
|
|
51
|
+
body,
|
|
52
|
+
signal
|
|
53
|
+
});
|
|
54
|
+
if (!response.ok) return null;
|
|
55
|
+
const decoded = decodeCliModelConfigsResponse(new Uint8Array(await response.arrayBuffer()));
|
|
56
|
+
if (!decoded) return null;
|
|
57
|
+
return normalizeDevinModels(decoded.clientModelConfigs, options.baseUrl);
|
|
58
|
+
} catch {
|
|
59
|
+
return null;
|
|
60
|
+
} finally {
|
|
61
|
+
clearTimeout(timer);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function normalizeDevinSessionToken(apiKey) {
|
|
65
|
+
if (!apiKey) return "";
|
|
66
|
+
return apiKey.startsWith(DEVIN_SESSION_TOKEN_PREFIX) ? apiKey : `${DEVIN_SESSION_TOKEN_PREFIX}${apiKey}`;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Decodes a raw (unframed) `GetCliModelConfigsResponse`. Bun's `fetch` usually
|
|
70
|
+
* auto-decompresses gzip, so the direct decode is attempted first; a
|
|
71
|
+
* `gunzipSync` fallback covers runtimes that hand back the still-compressed body.
|
|
72
|
+
*/
|
|
73
|
+
function decodeCliModelConfigsResponse(payload) {
|
|
74
|
+
try {
|
|
75
|
+
return fromBinary(GetCliModelConfigsResponseSchema, payload);
|
|
76
|
+
} catch {
|
|
77
|
+
try {
|
|
78
|
+
return fromBinary(GetCliModelConfigsResponseSchema, gunzipSync(payload));
|
|
79
|
+
} catch {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function normalizeDevinModels(configs, baseUrlOverride) {
|
|
85
|
+
const byId = /* @__PURE__ */ new Map();
|
|
86
|
+
for (const config of configs) {
|
|
87
|
+
if (config.disabled) continue;
|
|
88
|
+
const id = config.modelUid.trim();
|
|
89
|
+
if (!id) continue;
|
|
90
|
+
const input = config.supportsImages ? ["text", "image"] : ["text"];
|
|
91
|
+
const contextWindow = config.maxTokens > 0 ? config.maxTokens : DEFAULT_CONTEXT_WINDOW;
|
|
92
|
+
byId.set(id, {
|
|
93
|
+
id,
|
|
94
|
+
name: config.label.trim() || id,
|
|
95
|
+
api: "devin-agent",
|
|
96
|
+
provider: "devin",
|
|
97
|
+
baseUrl: baseUrlOverride ?? DEVIN_DEFAULT_BASE_URL,
|
|
98
|
+
reasoning: supportsDevinThinking(config),
|
|
99
|
+
input,
|
|
100
|
+
supportsTools: true,
|
|
101
|
+
cost: {
|
|
102
|
+
input: 0,
|
|
103
|
+
output: 0,
|
|
104
|
+
cacheRead: 0,
|
|
105
|
+
cacheWrite: 0
|
|
106
|
+
},
|
|
107
|
+
contextWindow,
|
|
108
|
+
maxTokens: Math.min(config.maxTokens > 0 ? config.maxTokens : DEFAULT_MAX_TOKENS, DEFAULT_MAX_TOKENS)
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
return [...byId.values()].sort((a, b) => a.id.localeCompare(b.id));
|
|
112
|
+
}
|
|
113
|
+
//#endregion
|
|
114
|
+
export { fetchDevinModels };
|