@anthropic-ai/claude-code 1.0.44 → 1.0.46

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anthropic-ai/claude-code",
3
- "version": "1.0.44",
3
+ "version": "1.0.46",
4
4
  "main": "sdk.mjs",
5
5
  "types": "sdk.d.ts",
6
6
  "bin": {
package/sdk-tools.d.ts ADDED
@@ -0,0 +1,332 @@
1
+ /* eslint-disable */
2
+ /**
3
+ * This file was automatically generated by json-schema-to-typescript.
4
+ * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
5
+ * and run json-schema-to-typescript to regenerate this file.
6
+ */
7
+
8
+ /**
9
+ * JSON Schema definitions for Claude CLI tool inputs
10
+ */
11
+ export type ToolInputSchemas =
12
+ | AgentInput
13
+ | BashInput
14
+ | BashOutputInput
15
+ | ExitPlanModeInput
16
+ | FileEditInput
17
+ | FileMultiEditInput
18
+ | FileReadInput
19
+ | FileWriteInput
20
+ | GlobInput
21
+ | GrepInput
22
+ | KillShellInput
23
+ | ListMcpResourcesInput
24
+ | LsInput
25
+ | McpInput
26
+ | NotebookEditInput
27
+ | NotebookReadInput
28
+ | ReadMcpResourceInput
29
+ | TodoWriteInput
30
+ | WebFetchInput
31
+ | WebSearchInput;
32
+
33
+ export interface AgentInput {
34
+ /**
35
+ * A short (3-5 word) description of the task
36
+ */
37
+ description: string;
38
+ /**
39
+ * The task for the agent to perform
40
+ */
41
+ prompt: string;
42
+ }
43
+ export interface BashInput {
44
+ /**
45
+ * The command to execute
46
+ */
47
+ command: string;
48
+ /**
49
+ * Optional timeout in milliseconds (max 600000)
50
+ */
51
+ timeout?: number;
52
+ /**
53
+ * Clear, concise description of what this command does in 5-10 words. Examples:
54
+ * Input: ls
55
+ * Output: Lists files in current directory
56
+ *
57
+ * Input: git status
58
+ * Output: Shows working tree status
59
+ *
60
+ * Input: npm install
61
+ * Output: Installs package dependencies
62
+ *
63
+ * Input: mkdir foo
64
+ * Output: Creates directory 'foo'
65
+ */
66
+ description?: string;
67
+ /**
68
+ * whether to run this command in sandboxed mode: command run in this mode may not write to the filesystem or use the network, but they can read files, analyze data, and report back to you. When possible, run commands (e.g. grep) in this mode to present a smoother experience for the human, who isn't prompted to approve commands run in sandbox mode. If you run a command in sandbox mode and it looks like it fails because it needs write access after all, try again in non-sandbox mode
69
+ */
70
+ sandbox?: boolean;
71
+ /**
72
+ * Optional shell path to use instead of the default shell. The snapshot path will be set to undefined as well. Used primarily for testing.
73
+ */
74
+ shellExecutable?: string;
75
+ }
76
+ export interface BashOutputInput {
77
+ /**
78
+ * The ID of the background shell to retrieve output from
79
+ */
80
+ shell_id: string;
81
+ }
82
+ export interface ExitPlanModeInput {
83
+ /**
84
+ * The plan you came up with, that you want to run by the user for approval. Supports markdown. The plan should be pretty concise.
85
+ */
86
+ plan: string;
87
+ }
88
+ export interface FileEditInput {
89
+ /**
90
+ * The absolute path to the file to modify
91
+ */
92
+ file_path: string;
93
+ /**
94
+ * The text to replace
95
+ */
96
+ old_string: string;
97
+ /**
98
+ * The text to replace it with (must be different from old_string)
99
+ */
100
+ new_string: string;
101
+ /**
102
+ * Replace all occurences of old_string (default false)
103
+ */
104
+ replace_all?: boolean;
105
+ }
106
+ export interface FileMultiEditInput {
107
+ /**
108
+ * The absolute path to the file to modify
109
+ */
110
+ file_path: string;
111
+ /**
112
+ * Array of edit operations to perform sequentially on the file
113
+ *
114
+ * @minItems 1
115
+ */
116
+ edits: [
117
+ {
118
+ /**
119
+ * The text to replace
120
+ */
121
+ old_string: string;
122
+ /**
123
+ * The text to replace it with
124
+ */
125
+ new_string: string;
126
+ /**
127
+ * Replace all occurences of old_string (default false).
128
+ */
129
+ replace_all?: boolean;
130
+ },
131
+ ...{
132
+ /**
133
+ * The text to replace
134
+ */
135
+ old_string: string;
136
+ /**
137
+ * The text to replace it with
138
+ */
139
+ new_string: string;
140
+ /**
141
+ * Replace all occurences of old_string (default false).
142
+ */
143
+ replace_all?: boolean;
144
+ }[]
145
+ ];
146
+ }
147
+ export interface FileReadInput {
148
+ /**
149
+ * The absolute path to the file to read
150
+ */
151
+ file_path: string;
152
+ /**
153
+ * The line number to start reading from. Only provide if the file is too large to read at once
154
+ */
155
+ offset?: number;
156
+ /**
157
+ * The number of lines to read. Only provide if the file is too large to read at once.
158
+ */
159
+ limit?: number;
160
+ }
161
+ export interface FileWriteInput {
162
+ /**
163
+ * The absolute path to the file to write (must be absolute, not relative)
164
+ */
165
+ file_path: string;
166
+ /**
167
+ * The content to write to the file
168
+ */
169
+ content: string;
170
+ }
171
+ export interface GlobInput {
172
+ /**
173
+ * The glob pattern to match files against
174
+ */
175
+ pattern: string;
176
+ /**
177
+ * The directory to search in. If not specified, the current working directory will be used. IMPORTANT: Omit this field to use the default directory. DO NOT enter "undefined" or "null" - simply omit it for the default behavior. Must be a valid directory path if provided.
178
+ */
179
+ path?: string;
180
+ }
181
+ export interface GrepInput {
182
+ /**
183
+ * The regular expression pattern to search for in file contents
184
+ */
185
+ pattern: string;
186
+ /**
187
+ * File or directory to search in (rg PATH). Defaults to current working directory.
188
+ */
189
+ path?: string;
190
+ /**
191
+ * Glob pattern to filter files (e.g. "*.js", "*.{ts,tsx}") - maps to rg --glob
192
+ */
193
+ glob?: string;
194
+ /**
195
+ * Output mode: "content" shows matching lines (supports -A/-B/-C context, -n line numbers, head_limit), "files_with_matches" shows file paths (supports head_limit), "count" shows match counts (supports head_limit). Defaults to "files_with_matches".
196
+ */
197
+ output_mode?: "content" | "files_with_matches" | "count";
198
+ /**
199
+ * Number of lines to show before each match (rg -B). Requires output_mode: "content", ignored otherwise.
200
+ */
201
+ "-B"?: number;
202
+ /**
203
+ * Number of lines to show after each match (rg -A). Requires output_mode: "content", ignored otherwise.
204
+ */
205
+ "-A"?: number;
206
+ /**
207
+ * Number of lines to show before and after each match (rg -C). Requires output_mode: "content", ignored otherwise.
208
+ */
209
+ "-C"?: number;
210
+ /**
211
+ * Show line numbers in output (rg -n). Requires output_mode: "content", ignored otherwise.
212
+ */
213
+ "-n"?: boolean;
214
+ /**
215
+ * Case insensitive search (rg -i)
216
+ */
217
+ "-i"?: boolean;
218
+ /**
219
+ * File type to search (rg --type). Common types: js, py, rust, go, java, etc. More efficient than include for standard file types.
220
+ */
221
+ type?: string;
222
+ /**
223
+ * Limit output to first N lines/entries, equivalent to "| head -N". Works across all output modes: content (limits output lines), files_with_matches (limits file paths), count (limits count entries). When unspecified, shows all results from ripgrep.
224
+ */
225
+ head_limit?: number;
226
+ /**
227
+ * Enable multiline mode where . matches newlines and patterns can span lines (rg -U --multiline-dotall). Default: false.
228
+ */
229
+ multiline?: boolean;
230
+ }
231
+ export interface KillShellInput {
232
+ /**
233
+ * The ID of the background shell to kill
234
+ */
235
+ shell_id: string;
236
+ }
237
+ export interface ListMcpResourcesInput {
238
+ /**
239
+ * Optional server name to filter resources by
240
+ */
241
+ server?: string;
242
+ }
243
+ export interface LsInput {
244
+ /**
245
+ * The absolute path to the directory to list (must be absolute, not relative)
246
+ */
247
+ path: string;
248
+ /**
249
+ * List of glob patterns to ignore
250
+ */
251
+ ignore?: string[];
252
+ }
253
+ export interface McpInput {
254
+ [k: string]: unknown;
255
+ }
256
+ export interface NotebookEditInput {
257
+ /**
258
+ * The absolute path to the Jupyter notebook file to edit (must be absolute, not relative)
259
+ */
260
+ notebook_path: string;
261
+ /**
262
+ * The ID of the cell to edit. When inserting a new cell, the new cell will be inserted after the cell with this ID, or at the beginning if not specified.
263
+ */
264
+ cell_id?: string;
265
+ /**
266
+ * The new source for the cell
267
+ */
268
+ new_source: string;
269
+ /**
270
+ * The type of the cell (code or markdown). If not specified, it defaults to the current cell type. If using edit_mode=insert, this is required.
271
+ */
272
+ cell_type?: "code" | "markdown";
273
+ /**
274
+ * The type of edit to make (replace, insert, delete). Defaults to replace.
275
+ */
276
+ edit_mode?: "replace" | "insert" | "delete";
277
+ }
278
+ export interface NotebookReadInput {
279
+ /**
280
+ * The absolute path to the Jupyter notebook file to read (must be absolute, not relative)
281
+ */
282
+ notebook_path: string;
283
+ /**
284
+ * The ID of a specific cell to read. If not provided, all cells will be read.
285
+ */
286
+ cell_id?: string;
287
+ }
288
+ export interface ReadMcpResourceInput {
289
+ /**
290
+ * The MCP server name
291
+ */
292
+ server: string;
293
+ /**
294
+ * The resource URI to read
295
+ */
296
+ uri: string;
297
+ }
298
+ export interface TodoWriteInput {
299
+ /**
300
+ * The updated todo list
301
+ */
302
+ todos: {
303
+ content: string;
304
+ status: "pending" | "in_progress" | "completed";
305
+ priority: "high" | "medium" | "low";
306
+ id: string;
307
+ }[];
308
+ }
309
+ export interface WebFetchInput {
310
+ /**
311
+ * The URL to fetch content from
312
+ */
313
+ url: string;
314
+ /**
315
+ * The prompt to run on the fetched content
316
+ */
317
+ prompt: string;
318
+ }
319
+ export interface WebSearchInput {
320
+ /**
321
+ * The search query to use
322
+ */
323
+ query: string;
324
+ /**
325
+ * Only include search results from these domains
326
+ */
327
+ allowed_domains?: string[];
328
+ /**
329
+ * Never include search results from these domains
330
+ */
331
+ blocked_domains?: string[];
332
+ }
package/sdk.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  // (c) Anthropic PBC. All rights reserved. Use is subject to Anthropic's Commercial Terms of Service (https://www.anthropic.com/legal/commercial-terms).
2
2
 
3
- // Version: 1.0.44
3
+ // Version: 1.0.46
4
4
 
5
5
  // src/entrypoints/sdk.ts
6
6
  import { spawn } from "child_process";
@@ -8,9 +8,85 @@ import { join } from "path";
8
8
  import { fileURLToPath } from "url";
9
9
  import { createInterface } from "readline";
10
10
  import { existsSync } from "fs";
11
+
12
+ // src/utils/stream.ts
13
+ class Stream {
14
+ returned;
15
+ queue = [];
16
+ readResolve;
17
+ readReject;
18
+ isDone = false;
19
+ hasError;
20
+ started = false;
21
+ constructor(returned) {
22
+ this.returned = returned;
23
+ }
24
+ [Symbol.asyncIterator]() {
25
+ if (this.started) {
26
+ throw new Error("Stream can only be iterated once");
27
+ }
28
+ this.started = true;
29
+ return this;
30
+ }
31
+ next() {
32
+ if (this.queue.length > 0) {
33
+ return Promise.resolve({
34
+ done: false,
35
+ value: this.queue.shift()
36
+ });
37
+ }
38
+ if (this.isDone) {
39
+ return Promise.resolve({ done: true, value: undefined });
40
+ }
41
+ if (this.hasError) {
42
+ return Promise.reject(this.hasError);
43
+ }
44
+ return new Promise((resolve, reject) => {
45
+ this.readResolve = resolve;
46
+ this.readReject = reject;
47
+ });
48
+ }
49
+ enqueue(value) {
50
+ if (this.readResolve) {
51
+ const resolve = this.readResolve;
52
+ this.readResolve = undefined;
53
+ this.readReject = undefined;
54
+ resolve({ done: false, value });
55
+ } else {
56
+ this.queue.push(value);
57
+ }
58
+ }
59
+ done() {
60
+ this.isDone = true;
61
+ if (this.readResolve) {
62
+ const resolve = this.readResolve;
63
+ this.readResolve = undefined;
64
+ this.readReject = undefined;
65
+ resolve({ done: true, value: undefined });
66
+ }
67
+ }
68
+ error(error) {
69
+ this.hasError = error;
70
+ if (this.readReject) {
71
+ const reject = this.readReject;
72
+ this.readResolve = undefined;
73
+ this.readReject = undefined;
74
+ reject(error);
75
+ }
76
+ }
77
+ return() {
78
+ this.isDone = true;
79
+ if (this.returned) {
80
+ this.returned();
81
+ }
82
+ return Promise.resolve({ done: true, value: undefined });
83
+ }
84
+ }
85
+
86
+ // src/entrypoints/sdk.ts
11
87
  var __filename2 = fileURLToPath(import.meta.url);
12
88
  var __dirname2 = join(__filename2, "..");
13
- async function* query({
89
+ function query({
14
90
  prompt,
15
91
  options: {
16
92
  abortController = new AbortController,
@@ -89,10 +165,12 @@ async function* query({
89
165
  ...process.env
90
166
  }
91
167
  });
168
+ let childStdin;
92
169
  if (typeof prompt === "string") {
93
170
  child.stdin.end();
94
171
  } else {
95
172
  streamToStdin(prompt, child.stdin, abortController);
173
+ childStdin = child.stdin;
96
174
  }
97
175
  if (process.env.DEBUG) {
98
176
  child.stderr.on("data", (data) => {
@@ -106,44 +184,125 @@ async function* query({
106
184
  };
107
185
  abortController.signal.addEventListener("abort", cleanup);
108
186
  process.on("exit", cleanup);
109
- try {
110
- let processError = null;
111
- child.on("error", (error) => {
112
- processError = new Error(`Failed to spawn Claude Code process: ${error.message}`);
113
- });
114
- const processExitPromise = new Promise((resolve, reject) => {
115
- child.on("close", (code) => {
116
- if (abortController.signal.aborted) {
117
- reject(new AbortError("Claude Code process aborted by user"));
118
- }
119
- if (code !== 0) {
120
- reject(new Error(`Claude Code process exited with code ${code}`));
121
- } else {
122
- resolve();
123
- }
124
- });
187
+ const processExitPromise = new Promise((resolve) => {
188
+ child.on("close", (code) => {
189
+ if (abortController.signal.aborted) {
190
+ query2.setError(new AbortError("Claude Code process aborted by user"));
191
+ return;
192
+ }
193
+ if (code !== 0) {
194
+ query2.setError(new Error(`Claude Code process exited with code ${code}`));
195
+ } else {
196
+ resolve();
197
+ }
125
198
  });
126
- const rl = createInterface({ input: child.stdout });
199
+ });
200
+ const query2 = new Query(childStdin, child.stdout, processExitPromise);
201
+ child.on("error", (error) => {
202
+ if (abortController.signal.aborted) {
203
+ query2.setError(new AbortError("Claude Code process aborted by user"));
204
+ } else {
205
+ query2.setError(new Error(`Failed to spawn Claude Code process: ${error.message}`));
206
+ }
207
+ });
208
+ processExitPromise.finally(() => {
209
+ cleanup();
210
+ abortController.signal.removeEventListener("abort", cleanup);
211
+ if (process.env.CLAUDE_SDK_MCP_SERVERS) {
212
+ delete process.env.CLAUDE_SDK_MCP_SERVERS;
213
+ }
214
+ });
215
+ return query2;
216
+ }
217
+
218
+ class Query {
219
+ childStdin;
220
+ childStdout;
221
+ processExitPromise;
222
+ pendingControlResponses = new Map;
223
+ sdkMessages;
224
+ inputStream = new Stream;
225
+ constructor(childStdin, childStdout, processExitPromise) {
226
+ this.childStdin = childStdin;
227
+ this.childStdout = childStdout;
228
+ this.processExitPromise = processExitPromise;
229
+ this.readMessages();
230
+ this.sdkMessages = this.readSdkMessages();
231
+ }
232
+ setError(error) {
233
+ this.inputStream.error(error);
234
+ }
235
+ next(...[value]) {
236
+ return this.sdkMessages.next(...[value]);
237
+ }
238
+ return(value) {
239
+ return this.sdkMessages.return(value);
240
+ }
241
+ throw(e) {
242
+ return this.sdkMessages.throw(e);
243
+ }
244
+ [Symbol.asyncIterator]() {
245
+ return this.sdkMessages;
246
+ }
247
+ [Symbol.asyncDispose]() {
248
+ return this.sdkMessages[Symbol.asyncDispose]();
249
+ }
250
+ async readMessages() {
251
+ const rl = createInterface({ input: this.childStdout });
127
252
  try {
128
253
  for await (const line of rl) {
129
- if (processError) {
130
- throw processError;
131
- }
132
254
  if (line.trim()) {
133
- yield JSON.parse(line);
255
+ const message = JSON.parse(line);
256
+ if (message.type === "control_response") {
257
+ const handler = this.pendingControlResponses.get(message.response.request_id);
258
+ if (handler) {
259
+ handler(message.response);
260
+ }
261
+ continue;
262
+ }
263
+ this.inputStream.enqueue(message);
134
264
  }
135
265
  }
266
+ await this.processExitPromise;
267
+ } catch (error) {
268
+ this.inputStream.error(error);
136
269
  } finally {
270
+ this.inputStream.done();
137
271
  rl.close();
138
272
  }
139
- await processExitPromise;
140
- } finally {
141
- cleanup();
142
- abortController.signal.removeEventListener("abort", cleanup);
143
- if (process.env.CLAUDE_SDK_MCP_SERVERS) {
144
- delete process.env.CLAUDE_SDK_MCP_SERVERS;
273
+ }
274
+ async* readSdkMessages() {
275
+ for await (const message of this.inputStream) {
276
+ yield message;
145
277
  }
146
278
  }
279
+ async interrupt() {
280
+ if (!this.childStdin) {
281
+ throw new Error("Interrupt requires --input-format stream-json");
282
+ }
283
+ await this.request({
284
+ subtype: "interrupt"
285
+ }, this.childStdin);
286
+ }
287
+ request(request, childStdin) {
288
+ const requestId = Math.random().toString(36).substring(2, 15);
289
+ const sdkRequest = {
290
+ request_id: requestId,
291
+ type: "control_request",
292
+ request
293
+ };
294
+ return new Promise((resolve, reject) => {
295
+ this.pendingControlResponses.set(requestId, (response) => {
296
+ if (response.subtype === "success") {
297
+ resolve(response);
298
+ } else {
299
+ reject(new Error(response.error));
300
+ }
301
+ });
302
+ childStdin.write(JSON.stringify(sdkRequest) + `
303
+ `);
304
+ });
305
+ }
147
306
  }
148
307
  async function streamToStdin(stream, stdin, abortController) {
149
308
  for await (const message of stream) {
Binary file