@anthropic-ai/claude-agent-sdk 0.1.63 → 0.1.66

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/sdk.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  // (c) Anthropic PBC. All rights reserved. Use is subject to the Legal Agreements outlined here: https://code.claude.com/docs/en/legal-and-compliance.
3
3
 
4
- // Version: 0.1.63
4
+ // Version: 0.1.66
5
5
 
6
6
  // Want to see the unminified source? We're hiring!
7
7
  // https://job-boards.greenhouse.io/anthropic/jobs/4816199008
@@ -7037,6 +7037,9 @@ var NodeFsOperations = {
7037
7037
  statSync(fsPath) {
7038
7038
  return withSlowLogging("statSync", () => fs.statSync(fsPath));
7039
7039
  },
7040
+ lstatSync(fsPath) {
7041
+ return withSlowLogging("lstatSync", () => fs.lstatSync(fsPath));
7042
+ },
7040
7043
  readFileSync(fsPath, options) {
7041
7044
  return withSlowLogging("readFileSync", () => fs.readFileSync(fsPath, { encoding: options.encoding }));
7042
7045
  },
@@ -7238,9 +7241,9 @@ function mergeSandboxIntoExtraArgs(extraArgs, sandbox) {
7238
7241
  // ../src/transport/ProcessTransport.ts
7239
7242
  class ProcessTransport {
7240
7243
  options;
7241
- child;
7242
- childStdin;
7243
- childStdout;
7244
+ process;
7245
+ processStdin;
7246
+ processStdout;
7244
7247
  ready = false;
7245
7248
  abortController;
7246
7249
  exitError;
@@ -7252,13 +7255,50 @@ class ProcessTransport {
7252
7255
  this.abortController = options.abortController || createAbortController();
7253
7256
  this.initialize();
7254
7257
  }
7258
+ getDefaultExecutable() {
7259
+ return isRunningWithBun() ? "bun" : "node";
7260
+ }
7261
+ spawnLocalProcess(spawnOptions) {
7262
+ const { command, args, cwd: cwd2, env, signal } = spawnOptions;
7263
+ const stderrMode = env.DEBUG_CLAUDE_AGENT_SDK || this.options.stderr ? "pipe" : "ignore";
7264
+ const childProcess = spawn(command, args, {
7265
+ cwd: cwd2,
7266
+ stdio: ["pipe", "pipe", stderrMode],
7267
+ signal,
7268
+ env
7269
+ });
7270
+ if (env.DEBUG_CLAUDE_AGENT_SDK || this.options.stderr) {
7271
+ childProcess.stderr.on("data", (data) => {
7272
+ const message = data.toString();
7273
+ logForSdkDebugging(message);
7274
+ if (this.options.stderr) {
7275
+ this.options.stderr(message);
7276
+ }
7277
+ });
7278
+ }
7279
+ const mappedProcess = {
7280
+ stdin: childProcess.stdin,
7281
+ stdout: childProcess.stdout,
7282
+ get killed() {
7283
+ return childProcess.killed;
7284
+ },
7285
+ get exitCode() {
7286
+ return childProcess.exitCode;
7287
+ },
7288
+ kill: childProcess.kill.bind(childProcess),
7289
+ on: childProcess.on.bind(childProcess),
7290
+ once: childProcess.once.bind(childProcess),
7291
+ off: childProcess.off.bind(childProcess)
7292
+ };
7293
+ return mappedProcess;
7294
+ }
7255
7295
  initialize() {
7256
7296
  try {
7257
7297
  const {
7258
7298
  additionalDirectories = [],
7259
7299
  betas,
7260
7300
  cwd: cwd2,
7261
- executable = isRunningWithBun() ? "bun" : "node",
7301
+ executable = this.getDefaultExecutable(),
7262
7302
  executableArgs = [],
7263
7303
  extraArgs = {},
7264
7304
  pathToClaudeCodeExecutable,
@@ -7278,6 +7318,7 @@ class ProcessTransport {
7278
7318
  settingSources,
7279
7319
  allowedTools = [],
7280
7320
  disallowedTools = [],
7321
+ tools,
7281
7322
  mcpServers,
7282
7323
  strictMcpConfig,
7283
7324
  canUseTool,
@@ -7329,7 +7370,6 @@ class ProcessTransport {
7329
7370
  if (disallowedTools.length > 0) {
7330
7371
  args.push("--disallowedTools", disallowedTools.join(","));
7331
7372
  }
7332
- const { tools } = this.options;
7333
7373
  if (tools !== undefined) {
7334
7374
  if (Array.isArray(tools)) {
7335
7375
  if (tools.length === 0) {
@@ -7403,47 +7443,44 @@ class ProcessTransport {
7403
7443
  } else {
7404
7444
  delete env.DEBUG;
7405
7445
  }
7406
- const fs2 = getFsImplementation();
7407
- if (!fs2.existsSync(pathToClaudeCodeExecutable)) {
7408
- const errorMessage = isNativeBinary(pathToClaudeCodeExecutable) ? `Claude Code native binary not found at ${pathToClaudeCodeExecutable}. Please ensure Claude Code is installed via native installer or specify a valid path with options.pathToClaudeCodeExecutable.` : `Claude Code executable not found at ${pathToClaudeCodeExecutable}. Is options.pathToClaudeCodeExecutable set?`;
7409
- throw new ReferenceError(errorMessage);
7410
- }
7411
7446
  const isNative = isNativeBinary(pathToClaudeCodeExecutable);
7412
7447
  const spawnCommand = isNative ? pathToClaudeCodeExecutable : executable;
7413
7448
  const spawnArgs = isNative ? [...executableArgs, ...args] : [...executableArgs, pathToClaudeCodeExecutable, ...args];
7414
- const spawnMessage = isNative ? `Spawning Claude Code native binary: ${spawnCommand} ${spawnArgs.join(" ")}` : `Spawning Claude Code process: ${spawnCommand} ${spawnArgs.join(" ")}`;
7415
- logForSdkDebugging(spawnMessage);
7416
- if (stderr) {
7417
- stderr(spawnMessage);
7418
- }
7419
- const stderrMode = env.DEBUG_CLAUDE_AGENT_SDK || stderr ? "pipe" : "ignore";
7420
- this.child = spawn(spawnCommand, spawnArgs, {
7449
+ const spawnOptions = {
7450
+ command: spawnCommand,
7451
+ args: spawnArgs,
7421
7452
  cwd: cwd2,
7422
- stdio: ["pipe", "pipe", stderrMode],
7423
- signal: this.abortController.signal,
7424
- env
7425
- });
7426
- this.childStdin = this.child.stdin;
7427
- this.childStdout = this.child.stdout;
7428
- if (env.DEBUG_CLAUDE_AGENT_SDK || stderr) {
7429
- this.child.stderr.on("data", (data) => {
7430
- const message = data.toString();
7431
- logForSdkDebugging(message);
7432
- if (stderr) {
7433
- stderr(message);
7434
- }
7435
- });
7453
+ env,
7454
+ signal: this.abortController.signal
7455
+ };
7456
+ if (this.options.spawnClaudeCodeProcess) {
7457
+ logForSdkDebugging(`Spawning Claude Code (custom): ${spawnCommand} ${spawnArgs.join(" ")}`);
7458
+ this.process = this.options.spawnClaudeCodeProcess(spawnOptions);
7459
+ } else {
7460
+ const fs2 = getFsImplementation();
7461
+ if (!fs2.existsSync(pathToClaudeCodeExecutable)) {
7462
+ const errorMessage = isNative ? `Claude Code native binary not found at ${pathToClaudeCodeExecutable}. Please ensure Claude Code is installed via native installer or specify a valid path with options.pathToClaudeCodeExecutable.` : `Claude Code executable not found at ${pathToClaudeCodeExecutable}. Is options.pathToClaudeCodeExecutable set?`;
7463
+ throw new ReferenceError(errorMessage);
7464
+ }
7465
+ const spawnMessage = `Spawning Claude Code: ${spawnCommand} ${spawnArgs.join(" ")}`;
7466
+ logForSdkDebugging(spawnMessage);
7467
+ if (stderr) {
7468
+ stderr(spawnMessage);
7469
+ }
7470
+ this.process = this.spawnLocalProcess(spawnOptions);
7436
7471
  }
7472
+ this.processStdin = this.process.stdin;
7473
+ this.processStdout = this.process.stdout;
7437
7474
  const cleanup = () => {
7438
- if (this.child && !this.child.killed) {
7439
- this.child.kill("SIGTERM");
7475
+ if (this.process && !this.process.killed) {
7476
+ this.process.kill("SIGTERM");
7440
7477
  }
7441
7478
  };
7442
7479
  this.processExitHandler = cleanup;
7443
7480
  this.abortHandler = cleanup;
7444
7481
  process.on("exit", this.processExitHandler);
7445
7482
  this.abortController.signal.addEventListener("abort", this.abortHandler);
7446
- this.child.on("error", (error) => {
7483
+ this.process.on("error", (error) => {
7447
7484
  this.ready = false;
7448
7485
  if (this.abortController.signal.aborted) {
7449
7486
  this.exitError = new AbortError("Claude Code process aborted by user");
@@ -7452,7 +7489,7 @@ class ProcessTransport {
7452
7489
  logForSdkDebugging(this.exitError.message);
7453
7490
  }
7454
7491
  });
7455
- this.child.on("close", (code, signal) => {
7492
+ this.process.on("exit", (code, signal) => {
7456
7493
  this.ready = false;
7457
7494
  if (this.abortController.signal.aborted) {
7458
7495
  this.exitError = new AbortError("Claude Code process aborted by user");
@@ -7482,10 +7519,10 @@ class ProcessTransport {
7482
7519
  if (this.abortController.signal.aborted) {
7483
7520
  throw new AbortError("Operation aborted");
7484
7521
  }
7485
- if (!this.ready || !this.childStdin) {
7522
+ if (!this.ready || !this.processStdin) {
7486
7523
  throw new Error("ProcessTransport is not ready for writing");
7487
7524
  }
7488
- if (this.child?.killed || this.child?.exitCode !== null) {
7525
+ if (this.process?.killed || this.process?.exitCode !== null) {
7489
7526
  throw new Error("Cannot write to terminated process");
7490
7527
  }
7491
7528
  if (this.exitError) {
@@ -7493,7 +7530,7 @@ class ProcessTransport {
7493
7530
  }
7494
7531
  logForSdkDebugging(`[ProcessTransport] Writing to stdin: ${data.substring(0, 100)}`);
7495
7532
  try {
7496
- const written = this.childStdin.write(data);
7533
+ const written = this.processStdin.write(data);
7497
7534
  if (!written) {
7498
7535
  logForSdkDebugging("[ProcessTransport] Write buffer full, data queued");
7499
7536
  }
@@ -7503,40 +7540,40 @@ class ProcessTransport {
7503
7540
  }
7504
7541
  }
7505
7542
  close() {
7506
- if (this.childStdin) {
7507
- this.childStdin.end();
7508
- this.childStdin = undefined;
7509
- }
7510
- if (this.processExitHandler) {
7511
- process.off("exit", this.processExitHandler);
7512
- this.processExitHandler = undefined;
7543
+ if (this.processStdin) {
7544
+ this.processStdin.end();
7545
+ this.processStdin = undefined;
7513
7546
  }
7514
7547
  if (this.abortHandler) {
7515
7548
  this.abortController.signal.removeEventListener("abort", this.abortHandler);
7516
7549
  this.abortHandler = undefined;
7517
7550
  }
7518
7551
  for (const { handler } of this.exitListeners) {
7519
- this.child?.off("exit", handler);
7552
+ this.process?.off("exit", handler);
7520
7553
  }
7521
7554
  this.exitListeners = [];
7522
- if (this.child && !this.child.killed) {
7523
- this.child.kill("SIGTERM");
7555
+ if (this.process && !this.process.killed) {
7556
+ this.process.kill("SIGTERM");
7524
7557
  setTimeout(() => {
7525
- if (this.child && !this.child.killed) {
7526
- this.child.kill("SIGKILL");
7558
+ if (this.process && !this.process.killed) {
7559
+ this.process.kill("SIGKILL");
7527
7560
  }
7528
7561
  }, 5000);
7529
7562
  }
7530
7563
  this.ready = false;
7564
+ if (this.processExitHandler) {
7565
+ process.off("exit", this.processExitHandler);
7566
+ this.processExitHandler = undefined;
7567
+ }
7531
7568
  }
7532
7569
  isReady() {
7533
7570
  return this.ready;
7534
7571
  }
7535
7572
  async* readMessages() {
7536
- if (!this.childStdout) {
7573
+ if (!this.processStdout) {
7537
7574
  throw new Error("ProcessTransport output stream not available");
7538
7575
  }
7539
- const rl = createInterface({ input: this.childStdout });
7576
+ const rl = createInterface({ input: this.processStdout });
7540
7577
  try {
7541
7578
  for await (const line of rl) {
7542
7579
  if (line.trim()) {
@@ -7552,25 +7589,25 @@ class ProcessTransport {
7552
7589
  }
7553
7590
  }
7554
7591
  endInput() {
7555
- if (this.childStdin) {
7556
- this.childStdin.end();
7592
+ if (this.processStdin) {
7593
+ this.processStdin.end();
7557
7594
  }
7558
7595
  }
7559
7596
  getInputStream() {
7560
- return this.childStdin;
7597
+ return this.processStdin;
7561
7598
  }
7562
7599
  onExit(callback) {
7563
- if (!this.child)
7600
+ if (!this.process)
7564
7601
  return () => {};
7565
7602
  const handler = (code, signal) => {
7566
7603
  const error = this.getProcessExitError(code, signal);
7567
7604
  callback(error);
7568
7605
  };
7569
- this.child.on("exit", handler);
7606
+ this.process.on("exit", handler);
7570
7607
  this.exitListeners.push({ callback, handler });
7571
7608
  return () => {
7572
- if (this.child) {
7573
- this.child.off("exit", handler);
7609
+ if (this.process) {
7610
+ this.process.off("exit", handler);
7574
7611
  }
7575
7612
  const index = this.exitListeners.findIndex((l) => l.handler === handler);
7576
7613
  if (index !== -1) {
@@ -7579,13 +7616,13 @@ class ProcessTransport {
7579
7616
  };
7580
7617
  }
7581
7618
  async waitForExit() {
7582
- if (!this.child) {
7619
+ if (!this.process) {
7583
7620
  if (this.exitError) {
7584
7621
  throw this.exitError;
7585
7622
  }
7586
7623
  return;
7587
7624
  }
7588
- if (this.child.exitCode !== null || this.child.killed) {
7625
+ if (this.process.exitCode !== null || this.process.killed) {
7589
7626
  if (this.exitError) {
7590
7627
  throw this.exitError;
7591
7628
  }
@@ -7604,14 +7641,14 @@ class ProcessTransport {
7604
7641
  resolve();
7605
7642
  }
7606
7643
  };
7607
- this.child.once("exit", exitHandler);
7644
+ this.process.once("exit", exitHandler);
7608
7645
  const errorHandler = (error) => {
7609
- this.child.off("exit", exitHandler);
7646
+ this.process.off("exit", exitHandler);
7610
7647
  reject(error);
7611
7648
  };
7612
- this.child.once("error", errorHandler);
7613
- this.child.once("exit", () => {
7614
- this.child.off("error", errorHandler);
7649
+ this.process.once("error", errorHandler);
7650
+ this.process.once("exit", () => {
7651
+ this.process.off("error", errorHandler);
7615
7652
  });
7616
7653
  });
7617
7654
  }
@@ -8167,7 +8204,17 @@ class SessionImpl {
8167
8204
  query;
8168
8205
  queryIterator = null;
8169
8206
  abortController;
8207
+ _sessionId = null;
8208
+ get sessionId() {
8209
+ if (this._sessionId === null) {
8210
+ throw new Error("Session ID not available until after receiving messages");
8211
+ }
8212
+ return this._sessionId;
8213
+ }
8170
8214
  constructor(options) {
8215
+ if (options.resume) {
8216
+ this._sessionId = options.resume;
8217
+ }
8171
8218
  this.inputStream = new Stream;
8172
8219
  let pathToClaudeCodeExecutable = options.pathToClaudeCodeExecutable;
8173
8220
  if (!pathToClaudeCodeExecutable) {
@@ -8175,7 +8222,7 @@ class SessionImpl {
8175
8222
  const dirname2 = join4(filename, "..");
8176
8223
  pathToClaudeCodeExecutable = join4(dirname2, "cli.js");
8177
8224
  }
8178
- const processEnv = { ...process.env };
8225
+ const processEnv = { ...options.env ?? process.env };
8179
8226
  if (!processEnv.CLAUDE_CODE_ENTRYPOINT) {
8180
8227
  processEnv.CLAUDE_CODE_ENTRYPOINT = "sdk-ts";
8181
8228
  }
@@ -8234,6 +8281,9 @@ class SessionImpl {
8234
8281
  if (done) {
8235
8282
  return;
8236
8283
  }
8284
+ if (value.type === "system" && value.subtype === "init") {
8285
+ this._sessionId = value.session_id;
8286
+ }
8237
8287
  yield value;
8238
8288
  if (value.type === "result") {
8239
8289
  return;
@@ -15159,7 +15209,7 @@ function query({
15159
15209
  const dirname2 = join5(filename, "..");
15160
15210
  pathToClaudeCodeExecutable = join5(dirname2, "cli.js");
15161
15211
  }
15162
- process.env.CLAUDE_AGENT_SDK_VERSION = "0.1.63";
15212
+ process.env.CLAUDE_AGENT_SDK_VERSION = "0.1.66";
15163
15213
  const {
15164
15214
  abortController = createAbortController(),
15165
15215
  additionalDirectories = [],
@@ -15261,7 +15311,8 @@ function query({
15261
15311
  includePartialMessages,
15262
15312
  persistSession,
15263
15313
  plugins,
15264
- sandbox
15314
+ sandbox,
15315
+ spawnClaudeCodeProcess: rest.spawnClaudeCodeProcess
15265
15316
  });
15266
15317
  const initConfig = {
15267
15318
  systemPrompt: customSystemPrompt,
@@ -0,0 +1,60 @@
1
+ import type { Readable, Writable } from 'stream';
2
+ /**
3
+ * Represents a spawned process with stdin/stdout streams and lifecycle management.
4
+ * Implementers provide this interface to abstract the process spawning mechanism.
5
+ * ChildProcess already satisfies this interface.
6
+ */
7
+ export interface SpawnedProcess {
8
+ /** Writable stream for sending data to the process stdin */
9
+ stdin: Writable;
10
+ /** Readable stream for receiving data from the process stdout */
11
+ stdout: Readable;
12
+ /** Whether the process has been killed */
13
+ readonly killed: boolean;
14
+ /** Exit code if the process has exited, null otherwise */
15
+ readonly exitCode: number | null;
16
+ /**
17
+ * Kill the process with the given signal
18
+ * @param signal - The signal to send (e.g., 'SIGTERM', 'SIGKILL')
19
+ */
20
+ kill(signal: NodeJS.Signals): boolean;
21
+ /**
22
+ * Register a callback for when the process exits
23
+ * @param event - Must be 'exit'
24
+ * @param listener - Callback receiving exit code and signal
25
+ */
26
+ on(event: 'exit', listener: (code: number | null, signal: NodeJS.Signals | null) => void): void;
27
+ /**
28
+ * Register a callback for process errors
29
+ * @param event - Must be 'error'
30
+ * @param listener - Callback receiving the error
31
+ */
32
+ on(event: 'error', listener: (error: Error) => void): void;
33
+ /**
34
+ * Register a one-time callback for when the process exits
35
+ */
36
+ once(event: 'exit', listener: (code: number | null, signal: NodeJS.Signals | null) => void): void;
37
+ once(event: 'error', listener: (error: Error) => void): void;
38
+ /**
39
+ * Remove an event listener
40
+ */
41
+ off(event: 'exit', listener: (code: number | null, signal: NodeJS.Signals | null) => void): void;
42
+ off(event: 'error', listener: (error: Error) => void): void;
43
+ }
44
+ /**
45
+ * Options passed to the spawn function.
46
+ */
47
+ export interface SpawnOptions {
48
+ /** Command to execute */
49
+ command: string;
50
+ /** Arguments to pass to the command */
51
+ args: string[];
52
+ /** Working directory */
53
+ cwd?: string;
54
+ /** Environment variables */
55
+ env: {
56
+ [envVar: string]: string | undefined;
57
+ };
58
+ /** Abort signal for cancellation */
59
+ signal: AbortSignal;
60
+ }
@@ -0,0 +1,30 @@
1
+ import type { StdoutMessage } from '../entrypoints/sdkControlTypes.js';
2
+ /**
3
+ * Transport interface for Claude Code SDK communication
4
+ * Abstracts the communication layer to support both process and WebSocket transports
5
+ */
6
+ export interface Transport {
7
+ /**
8
+ * Write data to the transport
9
+ * May be async for network-based transports
10
+ */
11
+ write(data: string): void | Promise<void>;
12
+ /**
13
+ * Close the transport connection and clean up resources
14
+ * This also closes stdin if still open (eliminating need for endInput)
15
+ */
16
+ close(): void;
17
+ /**
18
+ * Check if transport is ready for communication
19
+ */
20
+ isReady(): boolean;
21
+ /**
22
+ * Read and parse messages from the transport
23
+ * Each transport handles its own protocol and error checking
24
+ */
25
+ readMessages(): AsyncGenerator<StdoutMessage, void, unknown>;
26
+ /**
27
+ * End the input stream
28
+ */
29
+ endInput(): void;
30
+ }