zidane 6.5.2 → 6.5.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/dist/{acp-565X8nVP.js → acp-CIpD8UIw.js} +2 -2
- package/dist/{acp-565X8nVP.js.map → acp-CIpD8UIw.js.map} +1 -1
- package/dist/acp-cli.js +5 -5
- package/dist/acp.d.ts +1 -1
- package/dist/acp.js +1 -1
- package/dist/{agent-CvO7UOxv.js → agent-8kfGIDb_.js} +2 -2
- package/dist/{agent-CvO7UOxv.js.map → agent-8kfGIDb_.js.map} +1 -1
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +1 -1
- package/dist/{anthropic-Dov2mC5e.js → anthropic-qaw8XAc9.js} +2 -2
- package/dist/{anthropic-Dov2mC5e.js.map → anthropic-qaw8XAc9.js.map} +1 -1
- package/dist/{auth-B8ZuBcKC.js → auth-BLy7X1SY.js} +8 -5
- package/dist/{auth-B8ZuBcKC.js.map → auth-BLy7X1SY.js.map} +1 -1
- package/dist/chat/pure.d.ts +3 -3
- package/dist/chat.d.ts +20 -15
- package/dist/chat.d.ts.map +1 -1
- package/dist/chat.js +3 -3
- package/dist/{context-transport-ClvadrlH.js → context-transport-Bco9Wo0b.js} +3 -3
- package/dist/{context-transport-ClvadrlH.js.map → context-transport-Bco9Wo0b.js.map} +1 -1
- package/dist/contexts/daytona.d.ts +1 -1
- package/dist/contexts/daytona.d.ts.map +1 -1
- package/dist/contexts/daytona.js +5 -2
- package/dist/contexts/daytona.js.map +1 -1
- package/dist/contexts/e2b.d.ts +1 -1
- package/dist/cursor-iojRXHF9.js +139 -0
- package/dist/cursor-iojRXHF9.js.map +1 -0
- package/dist/eval.d.ts +1 -1
- package/dist/extensions.d.ts +1 -1
- package/dist/extensions.js +1 -1
- package/dist/headless.d.ts +1 -1
- package/dist/headless.js +1 -1
- package/dist/{index-DfERTrql.d.ts → index-BSNr0OQn.d.ts} +20 -3
- package/dist/index-BSNr0OQn.d.ts.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +8 -8
- package/dist/{login-Cl6ML2XN.js → login-D3CKhgbI.js} +2 -2
- package/dist/{login-Cl6ML2XN.js.map → login-D3CKhgbI.js.map} +1 -1
- package/dist/{mcp-DdntU47g.js → mcp-D9fqOQo5.js} +3 -3
- package/dist/{mcp-DdntU47g.js.map → mcp-D9fqOQo5.js.map} +1 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +1 -1
- package/dist/{oauth-bkEOybqm.js → oauth-ZebH9NHb.js} +70 -11
- package/dist/oauth-ZebH9NHb.js.map +1 -0
- package/dist/output/stream-json.d.ts +1 -1
- package/dist/output/terminal.d.ts +1 -1
- package/dist/pkce-t8BcPyEi.js +30 -0
- package/dist/pkce-t8BcPyEi.js.map +1 -0
- package/dist/plugins.d.ts +1 -1
- package/dist/presets.d.ts +1 -1
- package/dist/presets.js +1 -1
- package/dist/providers/anthropic.d.ts +1 -1
- package/dist/providers/anthropic.js +1 -1
- package/dist/providers/arcee.d.ts +1 -1
- package/dist/providers/baseten.d.ts +1 -1
- package/dist/providers/cerebras.d.ts +1 -1
- package/dist/providers/local.d.ts +1 -1
- package/dist/providers/openai-compat.d.ts +1 -1
- package/dist/providers/openai.d.ts +1 -1
- package/dist/providers/openai.js +1 -1
- package/dist/providers/openrouter.d.ts +1 -1
- package/dist/providers/xai.d.ts +1 -1
- package/dist/providers/xai.js +68 -1
- package/dist/providers/xai.js.map +1 -0
- package/dist/providers-Bxs-XHir.js +137 -0
- package/dist/providers-Bxs-XHir.js.map +1 -0
- package/dist/providers.d.ts +2 -2
- package/dist/providers.js +5 -5
- package/dist/restate.d.ts +1 -1
- package/dist/restate.js +1 -1
- package/dist/rolldown-runtime-BhDjJH2R.js +15 -0
- package/dist/session/sqlite.d.ts +1 -1
- package/dist/session.d.ts +1 -1
- package/dist/skills.d.ts +1 -1
- package/dist/{stdio-BQeCMmuK.js → stdio-DPpBDPx5.js} +13 -4
- package/dist/{stdio-BQeCMmuK.js.map → stdio-DPpBDPx5.js.map} +1 -1
- package/dist/{stdio-loader-BN1l1ZAG.js → stdio-loader-CI4sPFve.js} +11 -6
- package/dist/stdio-loader-CI4sPFve.js.map +1 -0
- package/dist/{tool-formatters-B2gBbKaS.d.ts → tool-formatters-BfKqWm5N.d.ts} +3 -3
- package/dist/{tool-formatters-B2gBbKaS.d.ts.map → tool-formatters-BfKqWm5N.d.ts.map} +1 -1
- package/dist/tools/fetch-url.d.ts +1 -1
- package/dist/tools/web-search.d.ts +1 -1
- package/dist/tools.d.ts +1 -1
- package/dist/tools.js +1 -1
- package/dist/{transcript-anchors-CmFKUw8M.js → transcript-anchors-Bv8HQ3S2.js} +36 -31
- package/dist/transcript-anchors-Bv8HQ3S2.js.map +1 -0
- package/dist/{transcript-anchors-CeIxhKP7.d.ts → transcript-anchors-CNqDbrc9.d.ts} +2 -2
- package/dist/{transcript-anchors-CeIxhKP7.d.ts.map → transcript-anchors-CNqDbrc9.d.ts.map} +1 -1
- package/dist/tui.d.ts +3 -3
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +19 -13
- package/dist/tui.js.map +1 -1
- package/dist/{turn-operations-Dyv3Z-Ff.d.ts → turn-operations-CnIpcenJ.d.ts} +3 -3
- package/dist/{turn-operations-Dyv3Z-Ff.d.ts.map → turn-operations-CnIpcenJ.d.ts.map} +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/{xai-Du6Wfnlb.js → xai-DILdFGzN.js} +11 -94
- package/dist/xai-DILdFGzN.js.map +1 -0
- package/docs/RESTATE.md +7 -0
- package/package.json +18 -17
- package/dist/index-DfERTrql.d.ts.map +0 -1
- package/dist/oauth-bkEOybqm.js.map +0 -1
- package/dist/providers-B6mFe7OD.js +0 -264
- package/dist/providers-B6mFe7OD.js.map +0 -1
- package/dist/stdio-loader-BN1l1ZAG.js.map +0 -1
- package/dist/transcript-anchors-CmFKUw8M.js.map +0 -1
- package/dist/xai-Du6Wfnlb.js.map +0 -1
|
@@ -1,264 +0,0 @@
|
|
|
1
|
-
import { m as openaiCompat } from "./openai-compat-CnHeo4Lz.js";
|
|
2
|
-
import { s as resolveOAuthApiKey } from "./oauth-bkEOybqm.js";
|
|
3
|
-
import { r as generatePkce } from "./xai-Du6Wfnlb.js";
|
|
4
|
-
//#region src/chat/oauth-page/cursor.ts
|
|
5
|
-
/** pi-ai / zidane OAuth provider id. Also the credentials-file key. */
|
|
6
|
-
const CURSOR_OAUTH_PROVIDER_ID = "cursor";
|
|
7
|
-
const CURSOR_LOGIN_URL = "https://cursor.com/loginDeepControl";
|
|
8
|
-
const CURSOR_POLL_URL = "https://api2.cursor.sh/auth/poll";
|
|
9
|
-
const CURSOR_REFRESH_URL = "https://api2.cursor.sh/auth/exchange_user_api_key";
|
|
10
|
-
const POLL_MAX_ATTEMPTS = 150;
|
|
11
|
-
const POLL_BASE_DELAY_MS = 1e3;
|
|
12
|
-
const POLL_MAX_DELAY_MS = 1e4;
|
|
13
|
-
const POLL_BACKOFF_MULTIPLIER = 1.2;
|
|
14
|
-
const POLL_MAX_CONSECUTIVE_ERRORS = 3;
|
|
15
|
-
/** Fallback lifetime when the JWT carries no `exp`. */
|
|
16
|
-
const DEFAULT_TOKEN_TTL_MS = 3600 * 1e3;
|
|
17
|
-
/** Refresh slightly early so requests don't race expiry. */
|
|
18
|
-
const TOKEN_EXPIRY_SKEW_MS = 300 * 1e3;
|
|
19
|
-
/**
|
|
20
|
-
* Derive expiry (epoch ms) from a JWT's `exp` claim, minus a safety skew.
|
|
21
|
-
* Returns `now + 1h` for malformed tokens so a missing claim never wedges
|
|
22
|
-
* refresh into an immediate-expire loop.
|
|
23
|
-
*/
|
|
24
|
-
function cursorTokenExpiry(token) {
|
|
25
|
-
try {
|
|
26
|
-
const parts = token.split(".");
|
|
27
|
-
const payload = parts[1];
|
|
28
|
-
if (parts.length !== 3 || !payload) return Date.now() + DEFAULT_TOKEN_TTL_MS;
|
|
29
|
-
const json = JSON.parse(atob(payload.replace(/-/g, "+").replace(/_/g, "/")));
|
|
30
|
-
if (typeof json.exp === "number") return json.exp * 1e3 - TOKEN_EXPIRY_SKEW_MS;
|
|
31
|
-
} catch {}
|
|
32
|
-
return Date.now() + DEFAULT_TOKEN_TTL_MS;
|
|
33
|
-
}
|
|
34
|
-
function delay(ms) {
|
|
35
|
-
return new Promise((r) => setTimeout(r, ms));
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Poll Cursor's auth endpoint until login completes. `404` means the user
|
|
39
|
-
* hasn't finished the browser flow yet; anything else non-2xx is a hard error.
|
|
40
|
-
*/
|
|
41
|
-
async function pollForTokens(uuid, verifier, callbacks) {
|
|
42
|
-
let wait = POLL_BASE_DELAY_MS;
|
|
43
|
-
let consecutiveErrors = 0;
|
|
44
|
-
for (let attempt = 0; attempt < POLL_MAX_ATTEMPTS; attempt++) {
|
|
45
|
-
if (callbacks.signal?.aborted) throw new Error("Cursor login aborted");
|
|
46
|
-
await delay(wait);
|
|
47
|
-
try {
|
|
48
|
-
const url = `${CURSOR_POLL_URL}?uuid=${encodeURIComponent(uuid)}&verifier=${encodeURIComponent(verifier)}`;
|
|
49
|
-
const response = await fetch(url, { signal: callbacks.signal });
|
|
50
|
-
if (response.status === 404) {
|
|
51
|
-
consecutiveErrors = 0;
|
|
52
|
-
wait = Math.min(wait * POLL_BACKOFF_MULTIPLIER, POLL_MAX_DELAY_MS);
|
|
53
|
-
continue;
|
|
54
|
-
}
|
|
55
|
-
if (response.ok) {
|
|
56
|
-
const data = await response.json();
|
|
57
|
-
if (!data.accessToken || !data.refreshToken) throw new Error(`Cursor poll response missing tokens: ${JSON.stringify(data)}`);
|
|
58
|
-
return {
|
|
59
|
-
accessToken: data.accessToken,
|
|
60
|
-
refreshToken: data.refreshToken
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
throw new Error(`Cursor poll failed (${response.status})`);
|
|
64
|
-
} catch (err) {
|
|
65
|
-
if (callbacks.signal?.aborted) throw new Error("Cursor login aborted");
|
|
66
|
-
consecutiveErrors++;
|
|
67
|
-
if (consecutiveErrors >= POLL_MAX_CONSECUTIVE_ERRORS) throw err instanceof Error ? err : new Error(String(err));
|
|
68
|
-
callbacks.onProgress?.("Waiting for Cursor login to complete…");
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
throw new Error("Cursor authentication timed out");
|
|
72
|
-
}
|
|
73
|
-
async function loginCursor(callbacks) {
|
|
74
|
-
const { verifier, challenge } = await generatePkce();
|
|
75
|
-
const uuid = crypto.randomUUID();
|
|
76
|
-
const authUrl = new URL(CURSOR_LOGIN_URL);
|
|
77
|
-
authUrl.searchParams.set("challenge", challenge);
|
|
78
|
-
authUrl.searchParams.set("uuid", uuid);
|
|
79
|
-
authUrl.searchParams.set("mode", "login");
|
|
80
|
-
authUrl.searchParams.set("redirectTarget", "cli");
|
|
81
|
-
callbacks.onAuth({
|
|
82
|
-
url: authUrl.toString(),
|
|
83
|
-
instructions: "A browser window should open. Complete login in Cursor to finish."
|
|
84
|
-
});
|
|
85
|
-
const tokens = await pollForTokens(uuid, verifier, callbacks);
|
|
86
|
-
return {
|
|
87
|
-
access: tokens.accessToken,
|
|
88
|
-
refresh: tokens.refreshToken,
|
|
89
|
-
expires: cursorTokenExpiry(tokens.accessToken)
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
async function refreshCursorToken(credentials) {
|
|
93
|
-
const response = await fetch(CURSOR_REFRESH_URL, {
|
|
94
|
-
method: "POST",
|
|
95
|
-
headers: {
|
|
96
|
-
"Authorization": `Bearer ${credentials.refresh}`,
|
|
97
|
-
"Content-Type": "application/json"
|
|
98
|
-
},
|
|
99
|
-
body: "{}"
|
|
100
|
-
});
|
|
101
|
-
if (!response.ok) {
|
|
102
|
-
const text = await response.text().catch(() => "");
|
|
103
|
-
throw new Error(`Cursor token refresh failed (${response.status}): ${text || response.statusText}`);
|
|
104
|
-
}
|
|
105
|
-
const data = await response.json();
|
|
106
|
-
if (!data.accessToken) throw new Error(`Cursor token refresh response missing access token: ${JSON.stringify(data)}`);
|
|
107
|
-
return {
|
|
108
|
-
access: data.accessToken,
|
|
109
|
-
refresh: data.refreshToken || credentials.refresh,
|
|
110
|
-
expires: cursorTokenExpiry(data.accessToken)
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Build a Cursor `OAuthProviderInterface`. Shape matches Anthropic / Codex so
|
|
115
|
-
* it drops into `BUILTIN_PROVIDERS` and `src/auth.ts` unchanged.
|
|
116
|
-
*
|
|
117
|
-
* No `renderPage` parameter: Cursor's poll flow has no local callback server,
|
|
118
|
-
* so there is no post-redirect page to theme.
|
|
119
|
-
*/
|
|
120
|
-
function createCursorOAuthProvider() {
|
|
121
|
-
return {
|
|
122
|
-
id: CURSOR_OAUTH_PROVIDER_ID,
|
|
123
|
-
name: "Cursor",
|
|
124
|
-
usesCallbackServer: false,
|
|
125
|
-
login: loginCursor,
|
|
126
|
-
refreshToken: refreshCursorToken,
|
|
127
|
-
getApiKey: (credentials) => credentials.access
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
//#endregion
|
|
131
|
-
//#region src/providers/cursor.ts
|
|
132
|
-
const DEFAULT_MODEL = "claude-4.6-sonnet";
|
|
133
|
-
const NOT_IMPLEMENTED_MESSAGE = "Cursor OAuth login works, but inference over Cursor is not implemented yet. Cursor uses a protobuf/HTTP-2 agent protocol (not an OpenAI-compatible API), so the streaming transport still needs to be ported. Use another provider for now.";
|
|
134
|
-
function cursor(params) {
|
|
135
|
-
const defaultModel = params?.defaultModel || DEFAULT_MODEL;
|
|
136
|
-
const base = openaiCompat({
|
|
137
|
-
name: "cursor",
|
|
138
|
-
apiKey: params?.apiKey ?? "oauth",
|
|
139
|
-
baseURL: "https://api2.cursor.sh",
|
|
140
|
-
defaultModel,
|
|
141
|
-
capabilities: {
|
|
142
|
-
vision: true,
|
|
143
|
-
imageInToolResult: false
|
|
144
|
-
},
|
|
145
|
-
extraHeaders: params?.extraHeaders
|
|
146
|
-
});
|
|
147
|
-
return {
|
|
148
|
-
...base,
|
|
149
|
-
meta: {
|
|
150
|
-
...base.meta,
|
|
151
|
-
defaultModel
|
|
152
|
-
},
|
|
153
|
-
async stream(options, callbacks) {
|
|
154
|
-
await resolveOAuthApiKey({
|
|
155
|
-
provider: "cursor",
|
|
156
|
-
providerId: CURSOR_OAUTH_PROVIDER_ID,
|
|
157
|
-
params,
|
|
158
|
-
missingError: "No Cursor credentials found. Run `bun run auth --cursor` first.",
|
|
159
|
-
refreshError: (reason) => `Cursor OAuth token refresh failed. Run \`bun run auth --cursor\` again. ${reason}`
|
|
160
|
-
}, callbacks);
|
|
161
|
-
throw new Error(NOT_IMPLEMENTED_MESSAGE);
|
|
162
|
-
}
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
//#endregion
|
|
166
|
-
//#region src/providers/mistral.ts
|
|
167
|
-
const BASE_URL$1 = "https://api.mistral.ai/v1";
|
|
168
|
-
function getApiKey$1(params) {
|
|
169
|
-
if (typeof params?.apiKey === "string" && params.apiKey.length > 0) return params.apiKey;
|
|
170
|
-
if (process.env.MISTRAL_API_KEY) return process.env.MISTRAL_API_KEY;
|
|
171
|
-
throw new Error("No Mistral API key found. Pass `apiKey` or set MISTRAL_API_KEY in your environment.");
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Model ids that accept `reasoning_effort`. Mistral rejects unknown request
|
|
175
|
-
* fields on some routes, so the knob is sent only for the families that
|
|
176
|
-
* document it (`mistral-small-*`, `mistral-medium-3.5` / `-2604`, and the
|
|
177
|
-
* deprecated-but-live `magistral-*`); `codestral` / `devstral` / `ministral`
|
|
178
|
-
* requests stay byte-identical to what they were without this planner.
|
|
179
|
-
*/
|
|
180
|
-
const REASONING_MODELS = /^(?:magistral-|mistral-small-|mistral-medium-(?:3\.5|2604))/;
|
|
181
|
-
/**
|
|
182
|
-
* Map zidane's thinking level to Mistral's `reasoning_effort`. Only the two
|
|
183
|
-
* documented values are emitted — `'none'` (thinking chunk omitted, `content`
|
|
184
|
-
* stays a plain string) and `'high'` (full thinking chunk). `adaptive` sends
|
|
185
|
-
* nothing so the model's own default applies.
|
|
186
|
-
*
|
|
187
|
-
* Exported for tests.
|
|
188
|
-
*/
|
|
189
|
-
function planMistralReasoning(ctx) {
|
|
190
|
-
if (!REASONING_MODELS.test(ctx.model)) return void 0;
|
|
191
|
-
if (ctx.thinking === void 0 || ctx.thinking === "adaptive") return void 0;
|
|
192
|
-
return { reasoning_effort: ctx.thinking === "off" ? "none" : "high" };
|
|
193
|
-
}
|
|
194
|
-
/**
|
|
195
|
-
* Mistral provider (La Plateforme).
|
|
196
|
-
*
|
|
197
|
-
* Thin wrapper around {@link openaiCompat} with Mistral-specific defaults
|
|
198
|
-
* (base URL, default model, `reasoning_effort` planner). `supportsReasoning`
|
|
199
|
-
* stays off: Mistral carries thinking inside `content` chunks rather than a
|
|
200
|
-
* `reasoning_content` field, so there is nothing to echo back upstream —
|
|
201
|
-
* thinking streams to the UI and is dropped from subsequent requests.
|
|
202
|
-
*/
|
|
203
|
-
function mistral(params) {
|
|
204
|
-
return openaiCompat({
|
|
205
|
-
name: "mistral",
|
|
206
|
-
apiKey: getApiKey$1(params),
|
|
207
|
-
baseURL: params?.baseURL || BASE_URL$1,
|
|
208
|
-
defaultModel: params?.defaultModel || "mistral-medium-latest",
|
|
209
|
-
capabilities: params?.capabilities ?? {
|
|
210
|
-
vision: true,
|
|
211
|
-
imageInToolResult: false
|
|
212
|
-
},
|
|
213
|
-
planReasoningRequest: planMistralReasoning,
|
|
214
|
-
extraHeaders: params?.extraHeaders
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
//#endregion
|
|
218
|
-
//#region src/providers/zai.ts
|
|
219
|
-
const BASE_URL = "https://api.z.ai/api/paas/v4";
|
|
220
|
-
function getApiKey(params) {
|
|
221
|
-
if (typeof params?.apiKey === "string" && params.apiKey.length > 0) return params.apiKey;
|
|
222
|
-
if (process.env.ZAI_API_KEY) return process.env.ZAI_API_KEY;
|
|
223
|
-
throw new Error("No Z.ai API key found. Pass `apiKey` or set ZAI_API_KEY in your environment.");
|
|
224
|
-
}
|
|
225
|
-
/**
|
|
226
|
-
* Map zidane's thinking level to Z.ai's `extra_body.thinking` request shape.
|
|
227
|
-
* GLM has no depth knob — thinking is a binary switch — so any non-`off`
|
|
228
|
-
* level enables it and `off` explicitly disables it (GLM-5.x/4.7 think by
|
|
229
|
-
* default, so a silent omission would not turn thinking off).
|
|
230
|
-
*
|
|
231
|
-
* Exported for tests.
|
|
232
|
-
*/
|
|
233
|
-
function planZaiReasoning(ctx) {
|
|
234
|
-
return { thinking: { type: !!ctx.thinking && ctx.thinking !== "off" ? "enabled" : "disabled" } };
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Z.ai (Zhipu) GLM provider.
|
|
238
|
-
*
|
|
239
|
-
* Thin wrapper around {@link openaiCompat} pinned to the `reasoning_content`
|
|
240
|
-
* round-trip mode: thinking arrives in the `reasoning_content` delta field and
|
|
241
|
-
* is echoed back on assistant messages under the same name, keeping GLM's
|
|
242
|
-
* interleaved/preserved thinking coherent across tool calls.
|
|
243
|
-
*/
|
|
244
|
-
function zai(params) {
|
|
245
|
-
return openaiCompat({
|
|
246
|
-
name: "zai",
|
|
247
|
-
apiKey: getApiKey(params),
|
|
248
|
-
baseURL: params?.baseURL || BASE_URL,
|
|
249
|
-
defaultModel: params?.defaultModel || "glm-4.7-flash",
|
|
250
|
-
capabilities: params?.capabilities ?? {
|
|
251
|
-
vision: false,
|
|
252
|
-
imageInToolResult: false
|
|
253
|
-
},
|
|
254
|
-
supportsReasoning: true,
|
|
255
|
-
reasoningMode: "reasoning_content",
|
|
256
|
-
reasoningContentField: "reasoning_content",
|
|
257
|
-
planReasoningRequest: planZaiReasoning,
|
|
258
|
-
extraHeaders: params?.extraHeaders
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
|
-
//#endregion
|
|
262
|
-
export { cursor as a, planMistralReasoning as i, zai as n, createCursorOAuthProvider as o, mistral as r, planZaiReasoning as t };
|
|
263
|
-
|
|
264
|
-
//# sourceMappingURL=providers-B6mFe7OD.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"providers-B6mFe7OD.js","names":["BASE_URL","getApiKey"],"sources":["../src/chat/oauth-page/cursor.ts","../src/providers/cursor.ts","../src/providers/mistral.ts","../src/providers/zai.ts"],"sourcesContent":["/**\n * Cursor OAuth flow.\n *\n * Unlike Anthropic / OpenAI Codex (loopback-redirect PKCE), Cursor uses a\n * **poll-based** PKCE flow with no local callback server:\n *\n * 1. Generate a PKCE verifier + challenge and a random UUID.\n * 2. Open the browser to `cursor.com/loginDeepControl?challenge&uuid&mode&redirectTarget`.\n * 3. Poll `api2.cursor.sh/auth/poll?uuid&verifier` until tokens come back\n * (HTTP 404 = \"not ready yet\", keep polling with backoff).\n * 4. Refresh via `POST api2.cursor.sh/auth/exchange_user_api_key` with\n * `Authorization: Bearer <refresh>`.\n *\n * Token expiry is derived from the access token's JWT `exp` claim (minus a\n * 5-minute safety margin), falling back to +1h when the claim is missing.\n *\n * Flow adapted from https://github.com/ndraiman/pi-cursor-provider, itself\n * derived from https://github.com/ephraimduncan/opencode-cursor.\n *\n * Cursor's auth + inference protocol is unofficial and undocumented — re-verify\n * the endpoints/params below if login starts failing.\n */\n\nimport type {\n OAuthCredentials,\n OAuthLoginCallbacks,\n} from '@earendil-works/pi-ai/oauth'\nimport type { OAuthProviderInterface } from '../../providers/oauth-registry'\nimport { generatePkce } from './pkce'\n\n/** pi-ai / zidane OAuth provider id. Also the credentials-file key. */\nexport const CURSOR_OAUTH_PROVIDER_ID = 'cursor'\n\nconst CURSOR_LOGIN_URL = 'https://cursor.com/loginDeepControl'\nconst CURSOR_POLL_URL = 'https://api2.cursor.sh/auth/poll'\nconst CURSOR_REFRESH_URL = 'https://api2.cursor.sh/auth/exchange_user_api_key'\n\nconst POLL_MAX_ATTEMPTS = 150\nconst POLL_BASE_DELAY_MS = 1000\nconst POLL_MAX_DELAY_MS = 10_000\nconst POLL_BACKOFF_MULTIPLIER = 1.2\nconst POLL_MAX_CONSECUTIVE_ERRORS = 3\n\n/** Fallback lifetime when the JWT carries no `exp`. */\nconst DEFAULT_TOKEN_TTL_MS = 3600 * 1000\n/** Refresh slightly early so requests don't race expiry. */\nconst TOKEN_EXPIRY_SKEW_MS = 5 * 60 * 1000\n\ninterface CursorTokenResponse {\n accessToken: string\n refreshToken: string\n}\n\n/**\n * Derive expiry (epoch ms) from a JWT's `exp` claim, minus a safety skew.\n * Returns `now + 1h` for malformed tokens so a missing claim never wedges\n * refresh into an immediate-expire loop.\n */\nexport function cursorTokenExpiry(token: string): number {\n try {\n const parts = token.split('.')\n const payload = parts[1]\n if (parts.length !== 3 || !payload)\n return Date.now() + DEFAULT_TOKEN_TTL_MS\n\n const json = JSON.parse(atob(payload.replace(/-/g, '+').replace(/_/g, '/'))) as { exp?: unknown }\n if (typeof json.exp === 'number')\n return json.exp * 1000 - TOKEN_EXPIRY_SKEW_MS\n }\n catch {\n // fall through to default\n }\n return Date.now() + DEFAULT_TOKEN_TTL_MS\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise(r => setTimeout(r, ms))\n}\n\n/**\n * Poll Cursor's auth endpoint until login completes. `404` means the user\n * hasn't finished the browser flow yet; anything else non-2xx is a hard error.\n */\nasync function pollForTokens(\n uuid: string,\n verifier: string,\n callbacks: OAuthLoginCallbacks,\n): Promise<CursorTokenResponse> {\n let wait = POLL_BASE_DELAY_MS\n let consecutiveErrors = 0\n\n for (let attempt = 0; attempt < POLL_MAX_ATTEMPTS; attempt++) {\n if (callbacks.signal?.aborted)\n throw new Error('Cursor login aborted')\n\n await delay(wait)\n\n try {\n const url = `${CURSOR_POLL_URL}?uuid=${encodeURIComponent(uuid)}&verifier=${encodeURIComponent(verifier)}`\n const response = await fetch(url, { signal: callbacks.signal })\n\n if (response.status === 404) {\n consecutiveErrors = 0\n wait = Math.min(wait * POLL_BACKOFF_MULTIPLIER, POLL_MAX_DELAY_MS)\n continue\n }\n\n if (response.ok) {\n const data = await response.json() as Partial<CursorTokenResponse>\n if (!data.accessToken || !data.refreshToken)\n throw new Error(`Cursor poll response missing tokens: ${JSON.stringify(data)}`)\n return { accessToken: data.accessToken, refreshToken: data.refreshToken }\n }\n\n throw new Error(`Cursor poll failed (${response.status})`)\n }\n catch (err) {\n if (callbacks.signal?.aborted)\n throw new Error('Cursor login aborted')\n consecutiveErrors++\n if (consecutiveErrors >= POLL_MAX_CONSECUTIVE_ERRORS)\n throw err instanceof Error ? err : new Error(String(err))\n callbacks.onProgress?.('Waiting for Cursor login to complete…')\n }\n }\n\n throw new Error('Cursor authentication timed out')\n}\n\nexport async function loginCursor(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials> {\n const { verifier, challenge } = await generatePkce()\n const uuid = crypto.randomUUID()\n\n const authUrl = new URL(CURSOR_LOGIN_URL)\n authUrl.searchParams.set('challenge', challenge)\n authUrl.searchParams.set('uuid', uuid)\n authUrl.searchParams.set('mode', 'login')\n authUrl.searchParams.set('redirectTarget', 'cli')\n\n callbacks.onAuth({\n url: authUrl.toString(),\n instructions: 'A browser window should open. Complete login in Cursor to finish.',\n })\n\n const tokens = await pollForTokens(uuid, verifier, callbacks)\n\n return {\n access: tokens.accessToken,\n refresh: tokens.refreshToken,\n expires: cursorTokenExpiry(tokens.accessToken),\n }\n}\n\nexport async function refreshCursorToken(credentials: OAuthCredentials): Promise<OAuthCredentials> {\n const response = await fetch(CURSOR_REFRESH_URL, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${credentials.refresh}`,\n 'Content-Type': 'application/json',\n },\n body: '{}',\n })\n\n if (!response.ok) {\n const text = await response.text().catch(() => '')\n throw new Error(`Cursor token refresh failed (${response.status}): ${text || response.statusText}`)\n }\n\n const data = await response.json() as Partial<CursorTokenResponse>\n if (!data.accessToken)\n throw new Error(`Cursor token refresh response missing access token: ${JSON.stringify(data)}`)\n\n return {\n access: data.accessToken,\n // Cursor may omit a rotated refresh token — keep the existing one.\n refresh: data.refreshToken || credentials.refresh,\n expires: cursorTokenExpiry(data.accessToken),\n }\n}\n\n/**\n * Build a Cursor `OAuthProviderInterface`. Shape matches Anthropic / Codex so\n * it drops into `BUILTIN_PROVIDERS` and `src/auth.ts` unchanged.\n *\n * No `renderPage` parameter: Cursor's poll flow has no local callback server,\n * so there is no post-redirect page to theme.\n */\nexport function createCursorOAuthProvider(): OAuthProviderInterface {\n return {\n id: CURSOR_OAUTH_PROVIDER_ID,\n name: 'Cursor',\n usesCallbackServer: false,\n login: loginCursor,\n refreshToken: refreshCursorToken,\n getApiKey: credentials => credentials.access,\n }\n}\n","import type { Provider, StreamCallbacks } from '.'\nimport { CURSOR_OAUTH_PROVIDER_ID } from '../chat/oauth-page/cursor'\nimport { resolveOAuthApiKey } from './oauth'\nimport { openaiCompat } from './openai-compat'\n\n/**\n * Cursor provider (OAuth).\n *\n * Auth is fully wired: `bun run auth --cursor` (or the TUI wizard) logs in via\n * Cursor's poll-based PKCE flow and persists credentials; this provider resolves\n * + refreshes the OAuth token on every turn via {@link resolveOAuthApiKey}.\n *\n * Inference is **not** wired yet. Cursor does not expose an OpenAI-compatible\n * HTTP endpoint — it speaks a protobuf/Connect agent protocol over HTTP/2 to\n * `api2.cursor.sh`. Implementing `stream()` requires porting that transport\n * (generated protobuf schemas + an HTTP/2 streaming client) in-process, which\n * is intentionally left as a follow-up. Until then `stream()` resolves the\n * token (proving auth works) and then throws a clear, actionable error.\n *\n * The `openaiCompat` base supplies the message-format helpers (`formatTools`,\n * `userMessage`, `toolResultsMessage`, …) so the provider satisfies the full\n * `Provider` contract and slots into the registry; only `stream` is overridden.\n */\nexport interface CursorParams {\n /** Bypass OAuth resolution with an explicit token (mainly for tests). */\n apiKey?: string\n defaultModel?: string\n /**\n * Extra HTTP headers for the eventual Cursor transport. Accepted for API\n * parity with the other providers and forwarded to the openai-compat base,\n * but inert until Cursor inference is implemented (the `stream` override\n * currently throws before any request is made).\n */\n extraHeaders?: Record<string, string>\n}\n\nconst DEFAULT_MODEL = 'claude-4.6-sonnet'\n\nconst NOT_IMPLEMENTED_MESSAGE\n = 'Cursor OAuth login works, but inference over Cursor is not implemented yet. '\n + 'Cursor uses a protobuf/HTTP-2 agent protocol (not an OpenAI-compatible API), '\n + 'so the streaming transport still needs to be ported. Use another provider for now.'\n\nexport function cursor(params?: CursorParams): Provider {\n const defaultModel = params?.defaultModel || DEFAULT_MODEL\n\n // Base only provides the format/serialization methods; `baseURL` is never\n // hit because we override `stream` below.\n const base = openaiCompat({\n name: 'cursor',\n apiKey: params?.apiKey ?? 'oauth',\n baseURL: 'https://api2.cursor.sh',\n defaultModel,\n capabilities: { vision: true, imageInToolResult: false },\n extraHeaders: params?.extraHeaders,\n })\n\n return {\n ...base,\n meta: { ...base.meta, defaultModel },\n async stream(options, callbacks: StreamCallbacks) {\n // Resolve (and lazily refresh) the OAuth token so auth failures surface\n // here with the right remediation, distinct from the not-implemented path.\n await resolveOAuthApiKey(\n {\n provider: 'cursor',\n providerId: CURSOR_OAUTH_PROVIDER_ID,\n params,\n missingError: 'No Cursor credentials found. Run `bun run auth --cursor` first.',\n refreshError: reason => `Cursor OAuth token refresh failed. Run \\`bun run auth --cursor\\` again. ${reason}`,\n },\n callbacks,\n )\n void options\n throw new Error(NOT_IMPLEMENTED_MESSAGE)\n },\n }\n}\n","import type { Provider, ProviderCapabilities } from '.'\nimport type { ThinkingLevel } from '../types'\nimport { openaiCompat } from './openai-compat'\n\n// Mistral La Plateforme — OpenAI-compatible `/v1/chat/completions`. Model ids\n// are plain slugs (`mistral-medium-latest`, `devstral-2512`, …). Reasoning is\n// NOT a separate wire field here: with `reasoning_effort: 'high'` the response\n// `content` becomes a list of `thinking` / `text` chunks (handled by\n// `openaiCompat`'s content-chunk path), and with `'none'` it stays a plain\n// string. See https://docs.mistral.ai/studio-api/conversations/reasoning.\nconst BASE_URL = 'https://api.mistral.ai/v1'\n\nexport interface MistralParams {\n apiKey?: string\n defaultModel?: string\n /**\n * Override the base URL — e.g. point at a regional endpoint or a gateway in\n * front of La Plateforme.\n */\n baseURL?: string\n /**\n * Provider capability flags. The `mistral-medium` / `mistral-large` /\n * `pixtral` families accept `image_url` parts — default:\n * `{ vision: true, imageInToolResult: false }`. Set `vision: false` when\n * pinning a text-only model (`codestral`, `devstral`, `ministral`).\n */\n capabilities?: ProviderCapabilities\n /**\n * Extra HTTP headers sent on every request. Forwarded to the underlying\n * {@link openaiCompat} client.\n */\n extraHeaders?: Record<string, string>\n}\n\nfunction getApiKey(params?: MistralParams): string {\n // Resolution order aligned with the other providers: explicit > env > fail.\n if (typeof params?.apiKey === 'string' && params.apiKey.length > 0)\n return params.apiKey\n\n if (process.env.MISTRAL_API_KEY)\n return process.env.MISTRAL_API_KEY\n\n throw new Error('No Mistral API key found. Pass `apiKey` or set MISTRAL_API_KEY in your environment.')\n}\n\n/**\n * Model ids that accept `reasoning_effort`. Mistral rejects unknown request\n * fields on some routes, so the knob is sent only for the families that\n * document it (`mistral-small-*`, `mistral-medium-3.5` / `-2604`, and the\n * deprecated-but-live `magistral-*`); `codestral` / `devstral` / `ministral`\n * requests stay byte-identical to what they were without this planner.\n */\nconst REASONING_MODELS = /^(?:magistral-|mistral-small-|mistral-medium-(?:3\\.5|2604))/\n\n/**\n * Map zidane's thinking level to Mistral's `reasoning_effort`. Only the two\n * documented values are emitted — `'none'` (thinking chunk omitted, `content`\n * stays a plain string) and `'high'` (full thinking chunk). `adaptive` sends\n * nothing so the model's own default applies.\n *\n * Exported for tests.\n */\nexport function planMistralReasoning(\n ctx: { model: string, thinking?: ThinkingLevel },\n): Record<string, unknown> | undefined {\n if (!REASONING_MODELS.test(ctx.model))\n return undefined\n if (ctx.thinking === undefined || ctx.thinking === 'adaptive')\n return undefined\n return { reasoning_effort: ctx.thinking === 'off' ? 'none' : 'high' }\n}\n\n/**\n * Mistral provider (La Plateforme).\n *\n * Thin wrapper around {@link openaiCompat} with Mistral-specific defaults\n * (base URL, default model, `reasoning_effort` planner). `supportsReasoning`\n * stays off: Mistral carries thinking inside `content` chunks rather than a\n * `reasoning_content` field, so there is nothing to echo back upstream —\n * thinking streams to the UI and is dropped from subsequent requests.\n */\nexport function mistral(params?: MistralParams): Provider {\n return openaiCompat({\n name: 'mistral',\n apiKey: getApiKey(params),\n baseURL: params?.baseURL || BASE_URL,\n defaultModel: params?.defaultModel || 'mistral-medium-latest',\n capabilities: params?.capabilities ?? { vision: true, imageInToolResult: false },\n planReasoningRequest: planMistralReasoning,\n extraHeaders: params?.extraHeaders,\n })\n}\n","import type { Provider, ProviderCapabilities } from '.'\nimport type { ThinkingLevel } from '../types'\nimport { openaiCompat } from './openai-compat'\n\n// Z.ai (Zhipu) GLM Open Platform — OpenAI-compatible endpoint. Model ids are\n// plain lowercase slugs (`glm-4.7`, `glm-4.7-flash`, …), reasoning streams in\n// the `reasoning_content` delta field, and thinking is toggled via an\n// `extra_body.thinking` object rather than a `reasoning_effort` string.\n// See https://docs.z.ai/guides/develop/http/introduction and\n// https://docs.z.ai/guides/capabilities/thinking-mode.\nconst BASE_URL = 'https://api.z.ai/api/paas/v4'\n\nexport interface ZaiParams {\n apiKey?: string\n defaultModel?: string\n /**\n * Override the base URL — e.g. point at the dedicated Coding Plan endpoint\n * instead of the standard API endpoint.\n */\n baseURL?: string\n /**\n * Provider capability flags. GLM text models are text-only — default:\n * `{ vision: false, imageInToolResult: false }`.\n */\n capabilities?: ProviderCapabilities\n /**\n * Extra HTTP headers sent on every request. Forwarded to the underlying\n * {@link openaiCompat} client.\n */\n extraHeaders?: Record<string, string>\n}\n\nfunction getApiKey(params?: ZaiParams): string {\n // Resolution order aligned with the other providers: explicit > env > fail.\n if (typeof params?.apiKey === 'string' && params.apiKey.length > 0)\n return params.apiKey\n\n if (process.env.ZAI_API_KEY)\n return process.env.ZAI_API_KEY\n\n throw new Error('No Z.ai API key found. Pass `apiKey` or set ZAI_API_KEY in your environment.')\n}\n\n/**\n * Map zidane's thinking level to Z.ai's `extra_body.thinking` request shape.\n * GLM has no depth knob — thinking is a binary switch — so any non-`off`\n * level enables it and `off` explicitly disables it (GLM-5.x/4.7 think by\n * default, so a silent omission would not turn thinking off).\n *\n * Exported for tests.\n */\nexport function planZaiReasoning(\n ctx: { thinking?: ThinkingLevel },\n): Record<string, unknown> {\n const enabled = !!ctx.thinking && ctx.thinking !== 'off'\n return { thinking: { type: enabled ? 'enabled' : 'disabled' } }\n}\n\n/**\n * Z.ai (Zhipu) GLM provider.\n *\n * Thin wrapper around {@link openaiCompat} pinned to the `reasoning_content`\n * round-trip mode: thinking arrives in the `reasoning_content` delta field and\n * is echoed back on assistant messages under the same name, keeping GLM's\n * interleaved/preserved thinking coherent across tool calls.\n */\nexport function zai(params?: ZaiParams): Provider {\n return openaiCompat({\n name: 'zai',\n apiKey: getApiKey(params),\n baseURL: params?.baseURL || BASE_URL,\n defaultModel: params?.defaultModel || 'glm-4.7-flash',\n capabilities: params?.capabilities ?? { vision: false, imageInToolResult: false },\n supportsReasoning: true,\n reasoningMode: 'reasoning_content',\n reasoningContentField: 'reasoning_content',\n planReasoningRequest: planZaiReasoning,\n extraHeaders: params?.extraHeaders,\n })\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"stdio-loader-BN1l1ZAG.js","names":["spawn","nodeSpawn","spawnSync","nodeSpawnSync","spawn"],"sources":["../scripts/cross-spawn-shim.mjs","../node_modules/.bun/@modelcontextprotocol+sdk@1.29.0/node_modules/@modelcontextprotocol/sdk/dist/esm/client/stdio.js"],"sourcesContent":["/**\n * Build-time replacement for the userland process-spawn helper that the\n * MCP SDK's stdio transport depends on. Injected by tsdown via the\n * rolldown alias plugin in `tsdown.config.ts`.\n *\n * Why this exists\n *\n * The upstream spawn helper is CJS and its first line dynamically resolves\n * Node's process-spawn built-in via a bare specifier. When a downstream\n * consumer re-bundles zidane as ESM (esbuild / Vite / tsup with\n * `format: 'esm'` and Node built-ins not externalized), that bare\n * resolution gets wrapped in esbuild's `__require` shim and throws at\n * runtime — every stdio MCP server fails to launch.\n *\n * Aliasing the helper to this file at zidane's own build step replaces\n * the offending bare resolution with explicit `node:`-prefixed imports.\n * Downstream bundlers recognize the `node:` prefix as a Node built-in\n * and externalize it automatically. The upstream MCP SDK is unmodified.\n *\n * Tradeoff\n *\n * The replaced helper does two extra things vs. raw spawn:\n * 1. Windows `.cmd` / `.bat` / `.ps1` resolution via PATHEXT + cmd.exe\n * shelling. Compensated below with `shell: true` on Win32, which\n * routes through cmd.exe and handles the common `npx` / `pnpm` /\n * `yarn` shims.\n * 2. Synthesizes a clean ENOENT error event for missing commands.\n * `node:child_process.spawn` already emits a perfectly usable\n * `error` event with `code === 'ENOENT'`, which the MCP SDK's stdio\n * transport forwards to `onerror`. Functionally equivalent.\n *\n * Net: zero behavioural change on POSIX, near-identical on Windows for\n * MCP-style stdio invocations.\n */\n\nimport { spawn as nodeSpawn, spawnSync as nodeSpawnSync } from 'node:child_process'\nimport process from 'node:process'\n\nconst IS_WIN32 = process.platform === 'win32'\n\nfunction withWin32Shell(options) {\n // Only opt into shell mode on Windows, and only when the caller hasn't\n // explicitly disabled it. POSIX never needs the shell wrapper — args\n // would have to be re-quoted (changes argv semantics) and trap/`set -e`\n // behaviour shifts in subtle ways.\n if (!IS_WIN32)\n return options\n if (options && options.shell !== undefined)\n return options\n return { ...(options ?? {}), shell: true }\n}\n\nexport function spawn(command, args, options) {\n return nodeSpawn(command, args, withWin32Shell(options))\n}\n\nexport function spawnSync(command, args, options) {\n return nodeSpawnSync(command, args, withWin32Shell(options))\n}\n\n// Match cross-spawn's CommonJS interop shape so existing imports keep\n// working byte-for-byte:\n// - default import: `import spawn from 'cross-spawn'` (SDK uses this)\n// - named import: `import { spawn, sync } from 'cross-spawn'`\n// - require pattern: `const cs = require('cross-spawn'); cs.sync(...)`\nspawn.spawn = spawn\nspawn.sync = spawnSync\n\nexport const sync = spawnSync\nexport default spawn\n","import spawn from 'cross-spawn';\nimport process from 'node:process';\nimport { PassThrough } from 'node:stream';\nimport { ReadBuffer, serializeMessage } from '../shared/stdio.js';\n/**\n * Environment variables to inherit by default, if an environment is not explicitly given.\n */\nexport const DEFAULT_INHERITED_ENV_VARS = process.platform === 'win32'\n ? [\n 'APPDATA',\n 'HOMEDRIVE',\n 'HOMEPATH',\n 'LOCALAPPDATA',\n 'PATH',\n 'PROCESSOR_ARCHITECTURE',\n 'SYSTEMDRIVE',\n 'SYSTEMROOT',\n 'TEMP',\n 'USERNAME',\n 'USERPROFILE',\n 'PROGRAMFILES'\n ]\n : /* list inspired by the default env inheritance of sudo */\n ['HOME', 'LOGNAME', 'PATH', 'SHELL', 'TERM', 'USER'];\n/**\n * Returns a default environment object including only environment variables deemed safe to inherit.\n */\nexport function getDefaultEnvironment() {\n const env = {};\n for (const key of DEFAULT_INHERITED_ENV_VARS) {\n const value = process.env[key];\n if (value === undefined) {\n continue;\n }\n if (value.startsWith('()')) {\n // Skip functions, which are a security risk.\n continue;\n }\n env[key] = value;\n }\n return env;\n}\n/**\n * Client transport for stdio: this will connect to a server by spawning a process and communicating with it over stdin/stdout.\n *\n * This transport is only available in Node.js environments.\n */\nexport class StdioClientTransport {\n constructor(server) {\n this._readBuffer = new ReadBuffer();\n this._stderrStream = null;\n this._serverParams = server;\n if (server.stderr === 'pipe' || server.stderr === 'overlapped') {\n this._stderrStream = new PassThrough();\n }\n }\n /**\n * Starts the server process and prepares to communicate with it.\n */\n async start() {\n if (this._process) {\n throw new Error('StdioClientTransport already started! If using Client class, note that connect() calls start() automatically.');\n }\n return new Promise((resolve, reject) => {\n this._process = spawn(this._serverParams.command, this._serverParams.args ?? [], {\n // merge default env with server env because mcp server needs some env vars\n env: {\n ...getDefaultEnvironment(),\n ...this._serverParams.env\n },\n stdio: ['pipe', 'pipe', this._serverParams.stderr ?? 'inherit'],\n shell: false,\n windowsHide: process.platform === 'win32',\n cwd: this._serverParams.cwd\n });\n this._process.on('error', error => {\n reject(error);\n this.onerror?.(error);\n });\n this._process.on('spawn', () => {\n resolve();\n });\n this._process.on('close', _code => {\n this._process = undefined;\n this.onclose?.();\n });\n this._process.stdin?.on('error', error => {\n this.onerror?.(error);\n });\n this._process.stdout?.on('data', chunk => {\n this._readBuffer.append(chunk);\n this.processReadBuffer();\n });\n this._process.stdout?.on('error', error => {\n this.onerror?.(error);\n });\n if (this._stderrStream && this._process.stderr) {\n this._process.stderr.pipe(this._stderrStream);\n }\n });\n }\n /**\n * The stderr stream of the child process, if `StdioServerParameters.stderr` was set to \"pipe\" or \"overlapped\".\n *\n * If stderr piping was requested, a PassThrough stream is returned _immediately_, allowing callers to\n * attach listeners before the start method is invoked. This prevents loss of any early\n * error output emitted by the child process.\n */\n get stderr() {\n if (this._stderrStream) {\n return this._stderrStream;\n }\n return this._process?.stderr ?? null;\n }\n /**\n * The child process pid spawned by this transport.\n *\n * This is only available after the transport has been started.\n */\n get pid() {\n return this._process?.pid ?? null;\n }\n processReadBuffer() {\n while (true) {\n try {\n const message = this._readBuffer.readMessage();\n if (message === null) {\n break;\n }\n this.onmessage?.(message);\n }\n catch (error) {\n this.onerror?.(error);\n }\n }\n }\n async close() {\n if (this._process) {\n const processToClose = this._process;\n this._process = undefined;\n const closePromise = new Promise(resolve => {\n processToClose.once('close', () => {\n resolve();\n });\n });\n try {\n processToClose.stdin?.end();\n }\n catch {\n // ignore\n }\n await Promise.race([closePromise, new Promise(resolve => setTimeout(resolve, 2000).unref())]);\n if (processToClose.exitCode === null) {\n try {\n processToClose.kill('SIGTERM');\n }\n catch {\n // ignore\n }\n await Promise.race([closePromise, new Promise(resolve => setTimeout(resolve, 2000).unref())]);\n }\n if (processToClose.exitCode === null) {\n try {\n processToClose.kill('SIGKILL');\n }\n catch {\n // ignore\n }\n }\n }\n this._readBuffer.clear();\n }\n send(message) {\n return new Promise(resolve => {\n if (!this._process?.stdin) {\n throw new Error('Not connected');\n }\n const json = serializeMessage(message);\n if (this._process.stdin.write(json)) {\n resolve();\n }\n else {\n this._process.stdin.once('drain', resolve);\n }\n });\n }\n}\n//# sourceMappingURL=stdio.js.map"],"x_google_ignoreList":[1],"mappings":"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"}
|