@nyte-ai/plugin 0.0.23 → 0.0.24

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.
Files changed (79) hide show
  1. package/THIRD-PARTY-NOTICES.md +2 -38
  2. package/dist/chunks/{billing-2v3g7rd9.js → bash-description-2v3g7rd9.js} +1 -1
  3. package/dist/chunks/{billing-3j77ss7y.js → bash-description-3j77ss7y.js} +1 -1
  4. package/dist/chunks/{billing-bv5zr32b.js → bash-description-dnvgk30y.js} +2 -2
  5. package/dist/chunks/{billing-hg64tqf1.js → bash-description-hg64tqf1.js} +1 -1
  6. package/dist/chunks/{billing-r2ftaajy.js → bash-description-necnb2k7.js} +2 -7
  7. package/dist/chunks/{billing-mvc33pv6.js → bash-description-qnwggxq3.js} +1 -1
  8. package/dist/chunks/{billing-svrhh5a5.js → bash-description-svrhh5a5.js} +1 -1
  9. package/dist/chunks/{billing-wbe8w0te.js → bash-description-wbe8w0te.js} +1 -1
  10. package/dist/chunks/{billing-wmcbg6fw.js → bash-description-wmcbg6fw.js} +1 -1
  11. package/dist/chunks/{billing-sxc70w72.js → bash-description-yyd9jznf.js} +1 -1
  12. package/dist/chunks/{billing-gs2h17jb.js → bash-description-zz15raxk.js} +1 -1
  13. package/dist/src/acp/connection.js +3 -3
  14. package/dist/src/acp/index.js +6 -6
  15. package/dist/src/acp/registry.js +2 -2
  16. package/dist/src/acp/thread.js +2 -2
  17. package/dist/src/acp/transcript.js +2 -2
  18. package/dist/src/acp/translate.js +1 -1
  19. package/dist/src/approvals/approvals.js +1 -1
  20. package/dist/src/approvals/schema.js +1 -1
  21. package/dist/src/canvas/canvas-compile.js +3 -3
  22. package/dist/src/canvas/canvas-libraries.js +1 -1
  23. package/dist/src/canvas/canvas-preview.js +3 -3
  24. package/dist/src/canvas/canvas-protocol.d.ts +1 -1
  25. package/dist/src/canvas/canvas-protocol.js +2 -2
  26. package/dist/src/canvas/canvas.js +5 -5
  27. package/dist/src/canvas/schema.js +3 -3
  28. package/dist/src/claude-code-sdk/index.js +6 -6
  29. package/dist/src/claude-code-sdk/session.js +2 -2
  30. package/dist/src/claude-code-sdk/transcript.js +2 -2
  31. package/dist/src/claude-code-sdk/translate.js +1 -1
  32. package/dist/src/find-on-path.js +1 -1
  33. package/dist/src/question/client/questions-tui.js +1 -1
  34. package/dist/src/question/client/questions.js +1 -1
  35. package/dist/src/question/question.js +2 -2
  36. package/dist/src/question/schema.js +1 -1
  37. package/package.json +4 -8
  38. package/dist/chunks/billing-0y7dfkp2.js +0 -146
  39. package/dist/chunks/billing-3scqmkzb.js +0 -559
  40. package/dist/chunks/billing-8rjk35gr.js +0 -444
  41. package/dist/chunks/billing-9qc0eqh4.js +0 -174
  42. package/dist/chunks/billing-a9vqn66p.js +0 -351
  43. package/dist/chunks/billing-cy1rg619.js +0 -302
  44. package/dist/chunks/billing-ejx2hv52.js +0 -323
  45. package/dist/chunks/billing-j643d12p.js +0 -197
  46. package/dist/chunks/billing-s4rrspsk.js +0 -7
  47. package/dist/chunks/billing-t1qrxe16.js +0 -41
  48. package/dist/chunks/billing-tzr3cebf.js +0 -20
  49. package/dist/examples/claude-code/LICENSE +0 -21
  50. package/dist/examples/claude-code/billing.d.ts +0 -7
  51. package/dist/examples/claude-code/billing.js +0 -11
  52. package/dist/examples/claude-code/claude-cli.d.ts +0 -35
  53. package/dist/examples/claude-code/claude-cli.js +0 -15
  54. package/dist/examples/claude-code/env.d.ts +0 -1
  55. package/dist/examples/claude-code/env.js +0 -6
  56. package/dist/examples/claude-code/index.d.ts +0 -24
  57. package/dist/examples/claude-code/index.js +0 -149
  58. package/dist/examples/claude-code/inert-mcp.d.ts +0 -1
  59. package/dist/examples/claude-code/inert-mcp.js +0 -6
  60. package/dist/examples/claude-code/model-catalog.d.ts +0 -27
  61. package/dist/examples/claude-code/model-catalog.js +0 -12
  62. package/dist/examples/claude-code/process.d.ts +0 -22
  63. package/dist/examples/claude-code/process.js +0 -25
  64. package/dist/examples/claude-code/replay.d.ts +0 -4
  65. package/dist/examples/claude-code/replay.js +0 -11
  66. package/dist/examples/claude-code/stream.d.ts +0 -3
  67. package/dist/examples/claude-code/stream.js +0 -16
  68. package/dist/examples/claude-code/transcript.d.ts +0 -83
  69. package/dist/examples/claude-code/transcript.js +0 -23
  70. package/dist/examples/claude-code/turn-relay.d.ts +0 -48
  71. package/dist/examples/claude-code/turn-relay.js +0 -9
  72. package/dist/examples/claude-code/wire.d.ts +0 -372
  73. package/dist/examples/claude-code/wire.js +0 -18
  74. /package/dist/chunks/{billing-4vz9pxyx.js → bash-description-4vz9pxyx.js} +0 -0
  75. /package/dist/chunks/{billing-6z2kgtyt.js → bash-description-6z2kgtyt.js} +0 -0
  76. /package/dist/chunks/{billing-9nn3yp18.js → bash-description-9nn3yp18.js} +0 -0
  77. /package/dist/chunks/{billing-h13r0byk.js → bash-description-h13r0byk.js} +0 -0
  78. /package/dist/chunks/{billing-ye3wk5r3.js → bash-description-ye3wk5r3.js} +0 -0
  79. /package/dist/chunks/{billing-zfpm2rt0.js → bash-description-zfpm2rt0.js} +0 -0
@@ -1,351 +0,0 @@
1
- import {
2
- matchesRecord2,
3
- parseRecord2,
4
- parseStreamEvent2
5
- } from "./billing-0y7dfkp2.js";
6
-
7
- // examples/claude-code/turn-relay.ts
8
- import { createServer, request as httpRequest } from "node:http";
9
- import https from "node:https";
10
- import { randomBytes } from "node:crypto";
11
- class AnthropicCapture2 {
12
- message;
13
- complete = false;
14
- error;
15
- pending = "";
16
- decoder = new TextDecoder;
17
- argumentsByIndex = new Map;
18
- onEvent;
19
- constructor(onEvent) {
20
- this.onEvent = onEvent;
21
- }
22
- feed(chunk) {
23
- this.pending += this.decoder.decode(chunk, { stream: true });
24
- this.consumeFrames();
25
- }
26
- finish() {
27
- this.pending += this.decoder.decode();
28
- this.consumeFrames();
29
- }
30
- consumeFrames() {
31
- for (;; ) {
32
- const match = /\r?\n\r?\n/u.exec(this.pending);
33
- if (!match)
34
- return;
35
- const frame = this.pending.slice(0, match.index);
36
- this.pending = this.pending.slice(match.index + match[0].length);
37
- const data = frame.split(/\r?\n/u).filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trimStart()).join(`
38
- `);
39
- if (!data || data === "[DONE]")
40
- continue;
41
- const event = parseStreamEvent2(data);
42
- if (event === undefined)
43
- continue;
44
- this.apply(event);
45
- this.onEvent?.(event);
46
- }
47
- }
48
- apply(event) {
49
- switch (event.type) {
50
- case "message_start":
51
- this.message = structuredClone(event.message);
52
- break;
53
- case "content_block_start":
54
- if (this.message)
55
- this.message.content[event.index] = structuredClone(event.content_block);
56
- break;
57
- case "content_block_delta": {
58
- const block = this.message?.content[event.index];
59
- if (!block)
60
- break;
61
- const delta = event.delta;
62
- if (delta.type === "text_delta" && block.type === "text")
63
- block.text += delta.text;
64
- else if (delta.type === "thinking_delta" && block.type === "thinking")
65
- block.thinking += delta.thinking;
66
- else if (delta.type === "signature_delta" && block.type === "thinking") {
67
- block.signature = (block.signature ?? "") + delta.signature;
68
- } else if (delta.type === "input_json_delta" && block.type === "tool_use") {
69
- this.argumentsByIndex.set(event.index, (this.argumentsByIndex.get(event.index) ?? "") + delta.partial_json);
70
- }
71
- break;
72
- }
73
- case "content_block_stop": {
74
- const block = this.message?.content[event.index];
75
- if (block?.type === "tool_use" && this.argumentsByIndex.has(event.index)) {
76
- const raw = this.argumentsByIndex.get(event.index) ?? "";
77
- block.input = raw.trim() ? parseRecord2(raw) : {};
78
- this.argumentsByIndex.delete(event.index);
79
- }
80
- break;
81
- }
82
- case "message_delta":
83
- if (this.message) {
84
- Object.assign(this.message, event.delta);
85
- if (event.usage)
86
- this.message.usage = {
87
- input_tokens: this.message.usage?.input_tokens ?? 0,
88
- output_tokens: this.message.usage?.output_tokens ?? 0,
89
- ...this.message.usage,
90
- ...event.usage
91
- };
92
- }
93
- break;
94
- case "message_stop":
95
- this.complete = !!this.message?.stop_reason && this.argumentsByIndex.size === 0;
96
- break;
97
- case "error": {
98
- const { type, message } = event.error ?? {};
99
- this.error = [type, message].filter(Boolean).join(": ") || "unknown stream error";
100
- break;
101
- }
102
- }
103
- }
104
- }
105
- var STRIPPED_REQUEST_HEADERS = new Set([
106
- "host",
107
- "connection",
108
- "content-length",
109
- "transfer-encoding",
110
- "proxy-authorization",
111
- "proxy-connection",
112
- "accept-encoding"
113
- ]);
114
- var STRIPPED_RESPONSE_HEADERS = new Set(["connection", "transfer-encoding", "server", "date"]);
115
-
116
- class TurnRelay2 {
117
- capture;
118
- used = false;
119
- denied = 0;
120
- status;
121
- requestId;
122
- failure;
123
- errorBody = Buffer.alloc(0);
124
- originalRequestBody;
125
- requestBody;
126
- upstream;
127
- prefix = `/turn/${randomBytes(32).toString("base64url")}`;
128
- server;
129
- sockets = new Set;
130
- active = new Set;
131
- cancelled = false;
132
- closed = false;
133
- baseUrl;
134
- transformRequest;
135
- requestBetas = [];
136
- timeoutMs;
137
- constructor(upstream = "https://api.anthropic.com", timeoutMs = 180000, onEvent, transformRequest, requestBetas = []) {
138
- this.timeoutMs = timeoutMs;
139
- this.upstream = new URL(upstream);
140
- const loopback = ["127.0.0.1", "::1", "localhost"].includes(this.upstream.hostname);
141
- if (this.upstream.protocol !== "https:" && !(this.upstream.protocol === "http:" && loopback) || this.upstream.username || this.upstream.password || this.upstream.search || this.upstream.hash) {
142
- throw new Error("Claude Code upstream must be HTTPS or a loopback HTTP fixture");
143
- }
144
- this.capture = new AnthropicCapture2(onEvent);
145
- this.transformRequest = transformRequest;
146
- this.requestBetas = requestBetas;
147
- this.server = createServer((request, response) => {
148
- const operation = this.handle(request, response).finally(() => this.active.delete(operation));
149
- this.active.add(operation);
150
- });
151
- }
152
- beginTurn(onEvent, transformRequest, requestBetas = []) {
153
- if (this.closed)
154
- throw new Error("Claude Code turn relay is closed");
155
- if (this.active.size > 0)
156
- throw new Error("Claude Code turn relay still has an active request");
157
- this.capture = new AnthropicCapture2(onEvent);
158
- this.used = false;
159
- this.denied = 0;
160
- this.status = undefined;
161
- this.requestId = undefined;
162
- this.failure = undefined;
163
- this.errorBody = Buffer.alloc(0);
164
- this.originalRequestBody = undefined;
165
- this.requestBody = undefined;
166
- this.transformRequest = transformRequest;
167
- this.requestBetas = requestBetas;
168
- this.cancelled = false;
169
- }
170
- finishTurn() {
171
- if (this.cancelled)
172
- return;
173
- this.cancelled = true;
174
- for (const socket of this.sockets)
175
- socket.destroy(new Error("Claude Code request aborted"));
176
- this.sockets.clear();
177
- this.server.closeAllConnections?.();
178
- }
179
- async start() {
180
- await new Promise((resolve, reject) => {
181
- const onError = (error) => reject(error);
182
- this.server.once("error", onError);
183
- this.server.listen(0, "127.0.0.1", () => {
184
- this.server.off("error", onError);
185
- resolve();
186
- });
187
- });
188
- const address = this.server.address();
189
- if (address === null || typeof address === "string")
190
- throw new Error("Claude Code relay did not bind a TCP port");
191
- this.baseUrl = `http://127.0.0.1:${address.port}${this.prefix}`;
192
- return this.baseUrl;
193
- }
194
- errorText() {
195
- if (this.capture.error)
196
- return this.capture.error;
197
- const text = this.errorBody.toString("utf8");
198
- try {
199
- const payload = parseRecord2(text);
200
- return matchesRecord2(payload.error) && typeof payload.error.message === "string" ? payload.error.message : text;
201
- } catch {
202
- return text;
203
- }
204
- }
205
- abort() {
206
- this.finishTurn();
207
- }
208
- async settled() {
209
- await Promise.allSettled(this.active);
210
- }
211
- async close() {
212
- this.closed = true;
213
- this.abort();
214
- await new Promise((resolve) => {
215
- if (!this.server.listening)
216
- return resolve();
217
- this.server.close(() => resolve());
218
- });
219
- await this.settled();
220
- }
221
- async handle(request, response) {
222
- const requestUrl = new URL(request.url ?? "/", "http://127.0.0.1");
223
- if (request.method !== "POST" || requestUrl.pathname !== `${this.prefix}/v1/messages` || request.headers.origin) {
224
- response.writeHead(404).end();
225
- return;
226
- }
227
- if (this.cancelled || this.used) {
228
- this.denied += 1;
229
- const body = Buffer.from(JSON.stringify({
230
- type: "error",
231
- error: { type: "invalid_request_error", message: "NYTE_CLAUDE_CODE_TURN_RELAY_CONSUMED" }
232
- }));
233
- response.writeHead(400, { "content-type": "application/json", "content-length": body.length }).end(body);
234
- return;
235
- }
236
- this.used = true;
237
- this.sockets.add(request);
238
- this.sockets.add(response);
239
- let upstreamRequest;
240
- try {
241
- let body = await this.readBody(request);
242
- this.originalRequestBody = Buffer.from(body);
243
- if (this.transformRequest)
244
- body = this.transformRequest(body);
245
- this.requestBody = Buffer.from(body);
246
- if (this.cancelled)
247
- return;
248
- const headers = {};
249
- for (const [name, value] of Object.entries(request.headers)) {
250
- if (!STRIPPED_REQUEST_HEADERS.has(name.toLowerCase()) && value !== undefined)
251
- headers[name] = value;
252
- }
253
- headers["accept-encoding"] = "identity";
254
- headers["content-length"] = body.length;
255
- if (this.requestBetas.length > 0) {
256
- const existing = Array.isArray(headers["anthropic-beta"]) ? headers["anthropic-beta"].join(",") : String(headers["anthropic-beta"] ?? "");
257
- headers["anthropic-beta"] = [
258
- ...new Set([
259
- ...existing.split(",").map((value) => value.trim()).filter(Boolean),
260
- ...this.requestBetas
261
- ])
262
- ].join(",");
263
- }
264
- const pathPrefix = this.upstream.pathname.replace(/\/$/u, "");
265
- const send = this.upstream.protocol === "https:" ? https.request : httpRequest;
266
- const outgoing = send({
267
- protocol: this.upstream.protocol,
268
- hostname: this.upstream.hostname,
269
- port: this.upstream.port || undefined,
270
- method: "POST",
271
- path: `${pathPrefix}/v1/messages${requestUrl.search}`,
272
- headers,
273
- timeout: this.timeoutMs
274
- });
275
- upstreamRequest = outgoing;
276
- this.sockets.add(outgoing);
277
- const upstreamResponse = await new Promise((resolve, reject) => {
278
- outgoing.once("response", resolve);
279
- outgoing.once("error", reject);
280
- outgoing.end(body);
281
- });
282
- this.sockets.add(upstreamResponse);
283
- this.status = upstreamResponse.statusCode;
284
- this.requestId = String(upstreamResponse.headers["request-id"] ?? upstreamResponse.headers["x-request-id"] ?? "") || undefined;
285
- const responseHeaders = {};
286
- for (const [name, value] of Object.entries(upstreamResponse.headers)) {
287
- if (!STRIPPED_RESPONSE_HEADERS.has(name.toLowerCase()) && value !== undefined)
288
- responseHeaders[name] = value;
289
- }
290
- responseHeaders.connection = "close";
291
- response.writeHead(upstreamResponse.statusCode ?? 502, responseHeaders);
292
- for await (const rawChunk of upstreamResponse) {
293
- const chunk = Buffer.isBuffer(rawChunk) ? rawChunk : Buffer.from(rawChunk);
294
- if (this.status === 200)
295
- this.capture.feed(chunk);
296
- else if (this.errorBody.length < 65536) {
297
- this.errorBody = Buffer.concat([this.errorBody, chunk]).subarray(0, 65536);
298
- }
299
- if (!response.write(chunk))
300
- await this.waitForDrain(response);
301
- }
302
- if (this.status === 200)
303
- this.capture.finish();
304
- response.end();
305
- } catch (error) {
306
- this.failure = error instanceof Error ? error.name : "UnknownError";
307
- if (!response.headersSent)
308
- response.writeHead(this.cancelled ? 499 : 502).end();
309
- else
310
- response.destroy();
311
- } finally {
312
- if (upstreamRequest)
313
- this.sockets.delete(upstreamRequest);
314
- this.sockets.delete(request);
315
- this.sockets.delete(response);
316
- upstreamRequest?.destroy();
317
- }
318
- }
319
- async waitForDrain(response) {
320
- await new Promise((resolve, reject) => {
321
- const cleanup = () => {
322
- response.off("drain", onDrain);
323
- response.off("close", onClose);
324
- response.off("error", onError);
325
- };
326
- const onDrain = () => {
327
- cleanup();
328
- resolve();
329
- };
330
- const onClose = () => {
331
- cleanup();
332
- reject(new Error("Claude Code disconnected from the turn relay"));
333
- };
334
- const onError = (error) => {
335
- cleanup();
336
- reject(error);
337
- };
338
- response.once("drain", onDrain);
339
- response.once("close", onClose);
340
- response.once("error", onError);
341
- });
342
- }
343
- async readBody(request) {
344
- const chunks = [];
345
- for await (const rawChunk of request)
346
- chunks.push(Buffer.isBuffer(rawChunk) ? rawChunk : Buffer.from(rawChunk));
347
- return Buffer.concat(chunks);
348
- }
349
- }
350
-
351
- export { AnthropicCapture2, TurnRelay2 };
@@ -1,302 +0,0 @@
1
- import {
2
- envFlagEnabled2
3
- } from "./billing-s4rrspsk.js";
4
- import {
5
- discoveredModelSchema2
6
- } from "./billing-9qc0eqh4.js";
7
- import {
8
- matchesRecord2,
9
- parseRecord2
10
- } from "./billing-0y7dfkp2.js";
11
-
12
- // examples/claude-code/process.ts
13
- import { spawn } from "node:child_process";
14
- import { constants } from "node:fs";
15
- import { access } from "node:fs/promises";
16
- import { delimiter, extname, isAbsolute, join, resolve as resolvePath } from "node:path";
17
- import { createInterface } from "node:readline";
18
- import { Value } from "typebox/value";
19
- var INSTALL_HINT = "Claude Code is not installed. Install it with `npm install -g @anthropic-ai/claude-code` " + "or set NYTE_CLAUDE_CODE_COMMAND to the executable.";
20
- var LOGIN_HINT2 = "Claude Code is installed but not logged in. Run `claude auth login` and try again.";
21
- function configuredCommand2(env) {
22
- return env.NYTE_CLAUDE_CODE_COMMAND || "claude";
23
- }
24
- async function executable(path) {
25
- try {
26
- await access(path, process.platform === "win32" ? constants.F_OK : constants.X_OK);
27
- return true;
28
- } catch {
29
- return false;
30
- }
31
- }
32
- async function resolveClaudeExecutable(env = process.env) {
33
- const command = configuredCommand2(env);
34
- if (isAbsolute(command) || command.includes("/") || command.includes("\\")) {
35
- const candidate = resolvePath(command);
36
- return await executable(candidate) ? candidate : undefined;
37
- }
38
- const extensions = process.platform === "win32" ? (env.PATHEXT || ".COM;.EXE;.BAT;.CMD").split(";").flatMap((suffix) => [suffix, suffix.toLowerCase()]) : [""];
39
- for (const directory of (env.PATH || "").split(delimiter)) {
40
- if (!directory)
41
- continue;
42
- for (const suffix of extensions) {
43
- const candidate = join(directory, process.platform === "win32" && extname(command) ? command : command + suffix);
44
- if (await executable(candidate))
45
- return candidate;
46
- }
47
- }
48
- return;
49
- }
50
- function withConfigDirectory(env) {
51
- const output = {};
52
- for (const [key, value] of Object.entries(env))
53
- if (value !== undefined)
54
- output[key] = value;
55
- if (output.NYTE_CLAUDE_CODE_CONFIG_DIR)
56
- output.CLAUDE_CONFIG_DIR = output.NYTE_CLAUDE_CODE_CONFIG_DIR;
57
- return output;
58
- }
59
- async function captureProcess(command, args, env, signal, timeoutMs = 20000) {
60
- signal?.throwIfAborted();
61
- const child = spawnCommand2(command, args, { env, stdio: ["ignore", "pipe", "pipe"] });
62
- let stdout = "";
63
- let stderr = "";
64
- child.stdout?.setEncoding("utf8");
65
- child.stderr?.setEncoding("utf8");
66
- child.stdout?.on("data", (chunk) => stdout = (stdout + chunk).slice(-1e6));
67
- child.stderr?.on("data", (chunk) => stderr = (stderr + chunk).slice(-65536));
68
- const abort = () => killProcessTree2(child);
69
- signal?.addEventListener("abort", abort, { once: true });
70
- const timer = setTimeout(abort, timeoutMs);
71
- try {
72
- const code = await childExit2(child);
73
- signal?.throwIfAborted();
74
- return { code, stdout, stderr };
75
- } finally {
76
- clearTimeout(timer);
77
- signal?.removeEventListener("abort", abort);
78
- }
79
- }
80
- async function getClaudeStatus2(envInput = process.env, signal) {
81
- const env = withConfigDirectory(envInput);
82
- const command = await resolveClaudeExecutable(env);
83
- if (!command)
84
- return { available: false, loggedIn: false, subscription: false, detail: INSTALL_HINT };
85
- try {
86
- const result = await captureProcess(command, ["auth", "status"], env, signal);
87
- const payload = result.stdout.trim().startsWith("{") ? parseRecord2(result.stdout) : {};
88
- const loggedIn = payload.loggedIn === true;
89
- const plan = typeof payload.subscriptionType === "string" ? payload.subscriptionType : undefined;
90
- return {
91
- available: true,
92
- loggedIn,
93
- subscription: loggedIn && !!plan,
94
- command,
95
- authMethod: typeof payload.authMethod === "string" ? payload.authMethod : undefined,
96
- plan,
97
- detail: loggedIn ? undefined : LOGIN_HINT2
98
- };
99
- } catch (error) {
100
- if (signal?.aborted)
101
- throw error;
102
- return { available: true, loggedIn: false, subscription: false, command, detail: LOGIN_HINT2 };
103
- }
104
- }
105
- var READY_STATUS_TTL_MS = 60000;
106
- var readyStatusCache = new Map;
107
- async function readyClaudeCommand2(envInput, signal) {
108
- const env = withConfigDirectory(envInput);
109
- const key = JSON.stringify([configuredCommand2(env), env.PATH, env.HOME, env.CLAUDE_CONFIG_DIR]);
110
- const cached = readyStatusCache.get(key);
111
- if (cached && cached.expires > Date.now())
112
- return cached.command;
113
- const status = await getClaudeStatus2(env, signal);
114
- if (!status.available || !status.command)
115
- throw new Error(INSTALL_HINT);
116
- if (!status.loggedIn) {
117
- readyStatusCache.delete(key);
118
- throw new Error(LOGIN_HINT2);
119
- }
120
- readyStatusCache.set(key, { command: status.command, expires: Date.now() + READY_STATUS_TTL_MS });
121
- return status.command;
122
- }
123
- async function discoverClaudeModels2(envInput = process.env, signal, timeoutMs = 20000) {
124
- signal?.throwIfAborted();
125
- const env = processEnvironment2(envInput, {});
126
- const command = await resolveClaudeExecutable(env);
127
- if (!command)
128
- throw new Error(INSTALL_HINT);
129
- const args = [
130
- "-p",
131
- "--input-format",
132
- "stream-json",
133
- "--output-format",
134
- "stream-json",
135
- "--verbose",
136
- "--model",
137
- "default",
138
- "--tools",
139
- "",
140
- "--setting-sources",
141
- "",
142
- "--strict-mcp-config",
143
- "--disable-slash-commands",
144
- "--permission-mode",
145
- "dontAsk",
146
- "--permission-prompts",
147
- "none",
148
- "--no-session-persistence",
149
- "--mcp-config",
150
- JSON.stringify({ mcpServers: {} })
151
- ];
152
- const child = spawnCommand2(command, args, {
153
- cwd: process.cwd(),
154
- env,
155
- detached: process.platform !== "win32",
156
- windowsHide: true,
157
- stdio: ["pipe", "pipe", "pipe"]
158
- });
159
- let stderr = "";
160
- child.stderr?.setEncoding("utf8");
161
- child.stderr?.on("data", (chunk) => stderr = (stderr + chunk).slice(-65536));
162
- const abort = () => killProcessTree2(child);
163
- signal?.addEventListener("abort", abort, { once: true });
164
- let timedOut = false;
165
- const timer = setTimeout(() => {
166
- timedOut = true;
167
- killProcessTree2(child);
168
- }, timeoutMs);
169
- const requestId = `nyte-models-${Date.now()}`;
170
- child.stdin?.write(`${JSON.stringify({ type: "control_request", request_id: requestId, request: { subtype: "initialize" } })}
171
- `);
172
- child.stdin?.end(`${JSON.stringify({
173
- type: "user",
174
- message: { role: "user", content: [{ type: "text", text: "model-catalog-probe" }] },
175
- shouldQuery: false
176
- })}
177
- `);
178
- let models;
179
- try {
180
- if (child.stdout === null)
181
- throw new Error("Claude Code stdout is unavailable");
182
- const reader = createInterface({ input: child.stdout, crlfDelay: Infinity });
183
- for await (const line of reader) {
184
- if (!line.trim())
185
- continue;
186
- let event;
187
- try {
188
- event = parseRecord2(line);
189
- } catch {
190
- continue;
191
- }
192
- if (event.type !== "control_response")
193
- continue;
194
- const envelope = event.response;
195
- if (!matchesRecord2(envelope))
196
- continue;
197
- if (envelope.request_id !== requestId || envelope.subtype !== "success")
198
- continue;
199
- const response = envelope.response;
200
- if (matchesRecord2(response) && Array.isArray(response.models))
201
- models = response.models.filter((model) => Value.Check(discoveredModelSchema2, model));
202
- }
203
- const exitCode = await childExit2(child);
204
- signal?.throwIfAborted();
205
- if (timedOut)
206
- throw new Error("Claude Code model discovery timed out");
207
- if (exitCode !== 0)
208
- throw new Error(`Claude Code model discovery failed${stderr ? `: ${stderr.trim().slice(-500)}` : ""}`);
209
- if (!models?.length)
210
- throw new Error("Claude Code returned no selectable models");
211
- return models;
212
- } catch (error) {
213
- if (timedOut)
214
- throw new Error("Claude Code model discovery timed out", { cause: error });
215
- throw error;
216
- } finally {
217
- clearTimeout(timer);
218
- signal?.removeEventListener("abort", abort);
219
- if (child.exitCode === null)
220
- killProcessTree2(child);
221
- }
222
- }
223
- function quote(value) {
224
- return `"${value.replace(/"/gu, '""')}"`;
225
- }
226
- function spawnCommand2(command, args, options) {
227
- if (process.platform === "win32" && /\.(?:cmd|bat)$/iu.test(command)) {
228
- const comspec = options?.env?.COMSPEC || process.env.COMSPEC || "cmd.exe";
229
- return spawn(comspec, ["/d", "/s", "/c", [quote(command), ...args.map(quote)].join(" ")], options);
230
- }
231
- return spawn(command, args, options);
232
- }
233
- function childExit2(child) {
234
- return new Promise((resolve, reject) => {
235
- child.once("error", reject);
236
- child.once("exit", (code, signal) => {
237
- if (code !== null)
238
- resolve(code);
239
- else
240
- reject(new Error(`Claude Code exited from signal ${signal ?? "unknown"}`));
241
- });
242
- });
243
- }
244
- function killProcessTree2(child) {
245
- if (child.exitCode !== null || child.pid === undefined)
246
- return;
247
- if (process.platform === "win32") {
248
- const killer = spawn("taskkill", ["/F", "/T", "/PID", String(child.pid)], {
249
- stdio: "ignore",
250
- windowsHide: true
251
- });
252
- killer.unref();
253
- return;
254
- }
255
- try {
256
- process.kill(-child.pid, "SIGKILL");
257
- } catch {
258
- try {
259
- child.kill("SIGKILL");
260
- } catch {}
261
- }
262
- }
263
- function conflictingEnvironment(env) {
264
- const conflicts = [
265
- "ANTHROPIC_API_KEY",
266
- "ANTHROPIC_AUTH_TOKEN",
267
- "ANTHROPIC_BASE_URL",
268
- "ANTHROPIC_FOUNDRY_API_KEY"
269
- ].filter((key) => !!env[key]);
270
- for (const key of [
271
- "CLAUDE_CODE_USE_BEDROCK",
272
- "CLAUDE_CODE_USE_VERTEX",
273
- "CLAUDE_CODE_USE_FOUNDRY"
274
- ]) {
275
- if (envFlagEnabled2(env[key]))
276
- conflicts.push(key);
277
- }
278
- return conflicts;
279
- }
280
- function processEnvironment2(input, extraBody) {
281
- const env = withConfigDirectory({ ...process.env, ...input });
282
- const conflicts = conflictingEnvironment(env);
283
- if (conflicts.length) {
284
- throw new Error(`Claude Code subscription provider refuses conflicting auth/backend overrides: ${conflicts.join(", ")}`);
285
- }
286
- delete env.CLAUDE_CODE_EXTRA_BODY;
287
- Object.assign(env, {
288
- ENABLE_TOOL_SEARCH: "false",
289
- CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: "1",
290
- CLAUDE_CODE_MAX_RETRIES: "0",
291
- DISABLE_AUTO_COMPACT: "1",
292
- DISABLE_COMPACT: "1",
293
- CLAUDE_CODE_TOTAL_TOKENS_REMINDER: "off",
294
- DISABLE_TELEMETRY: "1",
295
- DISABLE_ERROR_REPORTING: "1"
296
- });
297
- if (typeof extraBody.max_tokens === "number")
298
- env.CLAUDE_CODE_MAX_OUTPUT_TOKENS = String(extraBody.max_tokens);
299
- return env;
300
- }
301
-
302
- export { LOGIN_HINT2, configuredCommand2, getClaudeStatus2, readyClaudeCommand2, discoverClaudeModels2, spawnCommand2, childExit2, killProcessTree2, processEnvironment2 };