claude-agent-sdk 0.36.0 → 1.0.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +34 -0
- data/README.md +7 -3
- data/UPGRADING-1.0.md +151 -0
- data/docs/client.md +26 -1
- data/docs/errors.md +6 -0
- data/docs/hooks-and-permissions.md +5 -3
- data/docs/mcp-servers.md +1 -2
- data/docs/sessions.md +101 -3
- data/docs/types.md +109 -4
- data/lib/claude_agent_sdk/cli_installer.rb +30 -3
- data/lib/claude_agent_sdk/command_builder.rb +109 -98
- data/lib/claude_agent_sdk/deprecation.rb +1 -1
- data/lib/claude_agent_sdk/errors.rb +10 -0
- data/lib/claude_agent_sdk/fiber_boundary.rb +2 -0
- data/lib/claude_agent_sdk/instrumentation/otel.rb +15 -7
- data/lib/claude_agent_sdk/message_parser.rb +23 -9
- data/lib/claude_agent_sdk/observer.rb +2 -1
- data/lib/claude_agent_sdk/option_warnings.rb +2 -0
- data/lib/claude_agent_sdk/query.rb +50 -43
- data/lib/claude_agent_sdk/sdk_mcp_server.rb +22 -13
- data/lib/claude_agent_sdk/session_mutations.rb +20 -8
- data/lib/claude_agent_sdk/session_resume.rb +31 -16
- data/lib/claude_agent_sdk/session_store.rb +7 -3
- data/lib/claude_agent_sdk/session_summary.rb +4 -2
- data/lib/claude_agent_sdk/sessions.rb +8 -6
- data/lib/claude_agent_sdk/streaming.rb +1 -1
- data/lib/claude_agent_sdk/subprocess_cli_transport.rb +72 -40
- data/lib/claude_agent_sdk/testing/session_store_conformance.rb +14 -10
- data/lib/claude_agent_sdk/transcript_mirror_batcher.rb +2 -0
- data/lib/claude_agent_sdk/types/attributes.rb +236 -0
- data/lib/claude_agent_sdk/types/base.rb +322 -0
- data/lib/claude_agent_sdk/types/content_blocks.rb +57 -0
- data/lib/claude_agent_sdk/types/hooks.rb +640 -0
- data/lib/claude_agent_sdk/types/mcp.rb +232 -0
- data/lib/claude_agent_sdk/types/messages.rb +614 -0
- data/lib/claude_agent_sdk/types/option_values.rb +302 -0
- data/lib/claude_agent_sdk/types/options.rb +352 -0
- data/lib/claude_agent_sdk/types/permissions.rb +107 -0
- data/lib/claude_agent_sdk/types/sessions.rb +10 -0
- data/lib/claude_agent_sdk/types.rb +13 -2534
- data/lib/claude_agent_sdk/version.rb +1 -1
- data/lib/claude_agent_sdk.rb +62 -28
- data/sig/claude_agent_sdk/cancellation_signal.rbs +14 -0
- data/sig/claude_agent_sdk/configuration.rbs +14 -0
- data/sig/claude_agent_sdk/errors.rbs +86 -0
- data/sig/claude_agent_sdk/observer.rbs +42 -0
- data/sig/claude_agent_sdk/railtie.rbs +10 -0
- data/sig/claude_agent_sdk/sdk_mcp_server.rbs +76 -0
- data/sig/claude_agent_sdk/session_store.rbs +105 -0
- data/sig/claude_agent_sdk/streaming.rbs +15 -0
- data/sig/claude_agent_sdk/transport.rbs +98 -0
- data/sig/claude_agent_sdk/types/base.rbs +39 -0
- data/sig/claude_agent_sdk/types/content_blocks.rbs +79 -0
- data/sig/claude_agent_sdk/types/hooks.rbs +528 -0
- data/sig/claude_agent_sdk/types/mcp.rbs +216 -0
- data/sig/claude_agent_sdk/types/messages.rbs +586 -0
- data/sig/claude_agent_sdk/types/option_values.rbs +245 -0
- data/sig/claude_agent_sdk/types/options.rbs +288 -0
- data/sig/claude_agent_sdk/types/permissions.rbs +108 -0
- data/sig/claude_agent_sdk/types/sessions.rbs +66 -0
- data/sig/claude_agent_sdk.rbs +231 -0
- data/sig/manifest.yaml +5 -0
- metadata +32 -1
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
module ClaudeAgentSDK
|
|
2
|
+
# Values of ClaudeAgentOptions#session_store_flush.
|
|
3
|
+
SESSION_STORE_FLUSH_MODES: Array[String]
|
|
4
|
+
|
|
5
|
+
# A SessionStore key. String keys: 'project_key' and 'session_id' always;
|
|
6
|
+
# 'subpath' (e.g. "subagents/agent-<id>") only for a subagent transcript.
|
|
7
|
+
type session_key = Hash[String, String?]
|
|
8
|
+
|
|
9
|
+
# A session summary as built by ClaudeAgentSDK.fold_session_summary:
|
|
10
|
+
# { 'session_id' => String, 'mtime' => Integer, 'data' => Hash[String, untyped] }.
|
|
11
|
+
type session_summary = Hash[String, untyped]
|
|
12
|
+
|
|
13
|
+
# The duck type ClaudeAgentOptions#session_store and the session functions'
|
|
14
|
+
# session_store: accept. Only #append and #load are required; an adapter
|
|
15
|
+
# need not subclass SessionStore. Keys and entries cross this boundary as
|
|
16
|
+
# String-keyed Hashes (docs/types.md#hash-keys).
|
|
17
|
+
#
|
|
18
|
+
# The SDK also probes (SessionStore.implements?) for these OPTIONAL methods
|
|
19
|
+
# and uses them when present — they cannot be expressed as optional
|
|
20
|
+
# interface members, so they are listed here:
|
|
21
|
+
#
|
|
22
|
+
# def list_sessions: (String project_key) -> Array[{ 'session_id' => String, 'mtime' => Integer }]
|
|
23
|
+
# def list_session_summaries: (String project_key) -> Array[session_summary]
|
|
24
|
+
# def delete: (session_key key) -> void # a main key cascades to its subkeys
|
|
25
|
+
# def list_subkeys: (session_key key) -> Array[String]
|
|
26
|
+
# def callback_scheduling: () -> (:thread | :inline) # :inline = fiber-native adapter
|
|
27
|
+
#
|
|
28
|
+
# ClaudeAgentSDK::Testing.run_session_store_conformance checks an adapter
|
|
29
|
+
# against the behavioral contracts.
|
|
30
|
+
interface _SessionStore
|
|
31
|
+
# Mirrors a batch of transcript entries. Must be thread-safe per key and
|
|
32
|
+
# should dedupe by entry['uuid'].
|
|
33
|
+
def append: (session_key key, Array[transcript_hash] entries) -> void
|
|
34
|
+
|
|
35
|
+
# The full transcript for key, or nil when it was never written.
|
|
36
|
+
def load: (session_key key) -> Array[transcript_hash]?
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Optional base class for adapters. Its methods raise NotImplementedError,
|
|
40
|
+
# which marks an optional method as absent (see .implements?).
|
|
41
|
+
class SessionStore
|
|
42
|
+
# True when store overrides method rather than inheriting the
|
|
43
|
+
# NotImplementedError default (works for duck-typed adapters too).
|
|
44
|
+
def self.implements?: (untyped store, Symbol | String method) -> bool
|
|
45
|
+
|
|
46
|
+
def append: (session_key key, Array[transcript_hash] entries) -> void
|
|
47
|
+
|
|
48
|
+
def load: (session_key key) -> Array[transcript_hash]?
|
|
49
|
+
|
|
50
|
+
def list_sessions: (String project_key) -> Array[Hash[String, String | Integer]]
|
|
51
|
+
|
|
52
|
+
def list_session_summaries: (String project_key) -> Array[session_summary]
|
|
53
|
+
|
|
54
|
+
def delete: (session_key key) -> void
|
|
55
|
+
|
|
56
|
+
def list_subkeys: (session_key key) -> Array[String]
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# In-memory SessionStore for tests and development; data is lost on exit.
|
|
60
|
+
# Implements every optional method.
|
|
61
|
+
class InMemorySessionStore < SessionStore
|
|
62
|
+
def initialize: () -> void
|
|
63
|
+
|
|
64
|
+
def append: (session_key key, Array[transcript_hash]? entries) -> void
|
|
65
|
+
|
|
66
|
+
def load: (session_key key) -> Array[transcript_hash]?
|
|
67
|
+
|
|
68
|
+
def list_sessions: (String project_key) -> Array[Hash[String, String | Integer]]
|
|
69
|
+
|
|
70
|
+
def list_session_summaries: (String project_key) -> Array[session_summary]
|
|
71
|
+
|
|
72
|
+
def delete: (session_key key) -> void
|
|
73
|
+
|
|
74
|
+
def list_subkeys: (session_key key) -> Array[String]
|
|
75
|
+
|
|
76
|
+
# Test helper: all entries for key ([] when absent).
|
|
77
|
+
def get_entries: (session_key key) -> Array[transcript_hash]
|
|
78
|
+
|
|
79
|
+
# Test helper: number of stored main transcripts.
|
|
80
|
+
def size: () -> Integer
|
|
81
|
+
|
|
82
|
+
# Test helper: removes everything.
|
|
83
|
+
def clear: () -> void
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Test helpers shipped for third-party SessionStore adapter authors.
|
|
87
|
+
module Testing
|
|
88
|
+
# Raised by run_session_store_conformance on the first violated contract.
|
|
89
|
+
class ConformanceError < StandardError
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# The optional SessionStore methods skip_optional: accepts.
|
|
93
|
+
OPTIONAL_METHODS: Array[String]
|
|
94
|
+
|
|
95
|
+
# Asserts the SessionStore behavioral contracts against a fresh store
|
|
96
|
+
# from make_store (called once per contract). Raises ConformanceError on
|
|
97
|
+
# a violation; returns nil otherwise.
|
|
98
|
+
def self.run_session_store_conformance: (_StoreFactory make_store, ?skip_optional: Array[String | Symbol], ?check_uuid_dedupe: bool) -> nil
|
|
99
|
+
|
|
100
|
+
# Returns a fresh store per call.
|
|
101
|
+
interface _StoreFactory
|
|
102
|
+
def call: () -> _SessionStore
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module ClaudeAgentSDK
|
|
2
|
+
# Builders for streaming input: a prompt that is an Enumerator of JSONL
|
|
3
|
+
# user messages.
|
|
4
|
+
module Streaming
|
|
5
|
+
# One JSON-encoded user message, newline-terminated. content is a String
|
|
6
|
+
# or an Array of content-block Hashes.
|
|
7
|
+
def self.user_message: (String | Array[Hash[Symbol | String, untyped]] content, ?session_id: String, ?parent_tool_use_id: String?) -> String
|
|
8
|
+
|
|
9
|
+
def self.from_array: (_Each[String | Array[Hash[Symbol | String, untyped]]] messages, ?session_id: String) -> Enumerator[String, void]
|
|
10
|
+
|
|
11
|
+
# The block receives an Enumerator::Yielder; each value it yields becomes
|
|
12
|
+
# one user message.
|
|
13
|
+
def self.from_block: (?session_id: String) { (Enumerator::Yielder yielder) -> void } -> Enumerator[String, void]
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
module ClaudeAgentSDK
|
|
2
|
+
# What `query(transport:)` and Client need from a transport. A custom
|
|
3
|
+
# transport may subclass Transport or be any object with these methods.
|
|
4
|
+
# read_messages must yield each stdout line parsed with
|
|
5
|
+
# `JSON.parse(line, symbolize_names: true)` (see docs/types.md#hash-keys).
|
|
6
|
+
# #close must be idempotent. (Transport#ready? is part of the abstract
|
|
7
|
+
# class but the SDK never calls it, so it is not required here.)
|
|
8
|
+
interface _Transport
|
|
9
|
+
def connect: () -> void
|
|
10
|
+
|
|
11
|
+
def write: (String data) -> void
|
|
12
|
+
|
|
13
|
+
def read_messages: () { (wire_hash message) -> void } -> void
|
|
14
|
+
|
|
15
|
+
def close: () -> void
|
|
16
|
+
|
|
17
|
+
def end_input: () -> void
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Client's transport_class: Client calls
|
|
21
|
+
# `transport_class.new(options, **transport_args)`.
|
|
22
|
+
interface _TransportClass
|
|
23
|
+
def new: (ClaudeAgentOptions options, **untyped transport_args) -> _Transport
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Abstract base for custom transports: every method raises
|
|
27
|
+
# NotImplementedError until overridden.
|
|
28
|
+
class Transport
|
|
29
|
+
def connect: () -> void
|
|
30
|
+
|
|
31
|
+
def write: (String data) -> void
|
|
32
|
+
|
|
33
|
+
def read_messages: () { (wire_hash message) -> void } -> void
|
|
34
|
+
| () -> Enumerator[wire_hash, void]
|
|
35
|
+
|
|
36
|
+
def close: () -> void
|
|
37
|
+
|
|
38
|
+
def ready?: () -> bool
|
|
39
|
+
|
|
40
|
+
def end_input: () -> void
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# The default transport: spawns the `claude` CLI and speaks stream-JSON
|
|
44
|
+
# over its stdin/stdout.
|
|
45
|
+
class SubprocessCLITransport < Transport
|
|
46
|
+
# The legacy two-argument form `new(prompt, options)` ignores prompt.
|
|
47
|
+
def initialize: (ClaudeAgentOptions options) -> void
|
|
48
|
+
| (untyped prompt, ClaudeAgentOptions options) -> void
|
|
49
|
+
|
|
50
|
+
def connect: () -> void
|
|
51
|
+
|
|
52
|
+
def write: (String data) -> void
|
|
53
|
+
|
|
54
|
+
def read_messages: () { (wire_hash message) -> void } -> void
|
|
55
|
+
| () -> Enumerator[wire_hash, void]
|
|
56
|
+
|
|
57
|
+
def close: () -> void
|
|
58
|
+
|
|
59
|
+
def ready?: () -> bool
|
|
60
|
+
|
|
61
|
+
def end_input: () -> void
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Builds the CLI argv SubprocessCLITransport would spawn (for custom
|
|
65
|
+
# transports that run the CLI elsewhere; see docs/client.md).
|
|
66
|
+
class CommandBuilder
|
|
67
|
+
def initialize: (String cli_path, ClaudeAgentOptions options) -> void
|
|
68
|
+
|
|
69
|
+
def build: () -> Array[String]
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Downloads a pinned Claude Code CLI into vendor/claude (Docker/CI deploys).
|
|
73
|
+
# Every failure raises CLIInstallError.
|
|
74
|
+
module CLIInstaller
|
|
75
|
+
# The CLI version this gem release is tested against.
|
|
76
|
+
PINNED_CLI_VERSION: String
|
|
77
|
+
|
|
78
|
+
# The directory vendor/claude resolves against (nil: the cwd at call
|
|
79
|
+
# time). An absolute, frozen path once set.
|
|
80
|
+
def self.root: () -> String?
|
|
81
|
+
|
|
82
|
+
def self.root=: ((String | Pathname)? path) -> (String | Pathname)?
|
|
83
|
+
|
|
84
|
+
# Absolute path of the default install directory.
|
|
85
|
+
def self.default_dir: () -> String
|
|
86
|
+
|
|
87
|
+
# Installs the CLI ('stable', 'latest' or a concrete version) and returns
|
|
88
|
+
# the absolute path of the binary. Idempotent and safe to run
|
|
89
|
+
# concurrently.
|
|
90
|
+
def self.install: (?version: String, ?dir: (String | Pathname)?) -> String
|
|
91
|
+
|
|
92
|
+
# Installs PINNED_CLI_VERSION.
|
|
93
|
+
def self.install_pinned: (?dir: (String | Pathname)?) -> String
|
|
94
|
+
|
|
95
|
+
# Path of an already-installed binary, or nil.
|
|
96
|
+
def self.installed_path: (?dir: (String | Pathname)?) -> String?
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module ClaudeAgentSDK
|
|
2
|
+
# Base class of the SDK's value types (messages, content blocks, hook
|
|
3
|
+
# inputs/outputs, option values).
|
|
4
|
+
#
|
|
5
|
+
# Attribute names are accepted in several spellings — Symbol or String,
|
|
6
|
+
# snake_case or camelCase — by .new, #[] and #[]=, which reach attributes
|
|
7
|
+
# only. The camelCase readers (`msg.sessionId`) are public API too but are
|
|
8
|
+
# resolved dynamically (method_missing), so they have no static signature
|
|
9
|
+
# here: prefer the snake_case readers, or #[], in typed code.
|
|
10
|
+
class Type
|
|
11
|
+
# Returns object unchanged when it already is an instance, nil for nil,
|
|
12
|
+
# and otherwise builds one (leniently: unknown keys never raise).
|
|
13
|
+
def self.wrap: (untyped object) -> instance?
|
|
14
|
+
|
|
15
|
+
# Builds an instance from a Hash (leniently); nil for anything else.
|
|
16
|
+
def self.from_hash: (untyped hash) -> instance?
|
|
17
|
+
|
|
18
|
+
# attributes: a Hash of attribute name => value (the keyword form
|
|
19
|
+
# `Klass.new(name: value)` passes the same Hash). On a user-constructed
|
|
20
|
+
# (strict) type an unknown key raises ArgumentError; types parsed from
|
|
21
|
+
# CLI output ignore it.
|
|
22
|
+
def initialize: (?Hash[Symbol | String, untyped]? attributes) -> void
|
|
23
|
+
|
|
24
|
+
# Reads an attribute; nil for a name that is not an attribute.
|
|
25
|
+
def []: (Symbol | String name) -> untyped
|
|
26
|
+
|
|
27
|
+
# Writes an attribute through its setter; returns value. A name that is
|
|
28
|
+
# not an attribute is ignored, or raises ArgumentError on a strict type.
|
|
29
|
+
def []=: (Symbol | String name, untyped value) -> untyped
|
|
30
|
+
|
|
31
|
+
# The wire (CLI) form; types that are sent to the CLI override this.
|
|
32
|
+
def to_h: () -> Hash[Symbol, untyped]
|
|
33
|
+
|
|
34
|
+
# Bounded, credential-filtered, human-oriented rendering.
|
|
35
|
+
def inspect: () -> String
|
|
36
|
+
|
|
37
|
+
def to_s: () -> String
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
module ClaudeAgentSDK
|
|
2
|
+
# A raw Hash inside a content block: Symbol keys on live messages, String
|
|
3
|
+
# keys on blocks parsed from a transcript (SessionMessage#content_blocks).
|
|
4
|
+
type block_hash = wire_hash | transcript_hash
|
|
5
|
+
|
|
6
|
+
# A content block of a UserMessage / AssistantMessage / SessionMessage.
|
|
7
|
+
type content_block = TextBlock
|
|
8
|
+
| ThinkingBlock
|
|
9
|
+
| ToolUseBlock
|
|
10
|
+
| ToolResultBlock
|
|
11
|
+
| ServerToolUseBlock
|
|
12
|
+
| ServerToolResultBlock
|
|
13
|
+
| UnknownBlock
|
|
14
|
+
|
|
15
|
+
class TextBlock < Type
|
|
16
|
+
attr_accessor text: String?
|
|
17
|
+
|
|
18
|
+
def to_s: () -> String
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class ThinkingBlock < Type
|
|
22
|
+
attr_accessor thinking: String?
|
|
23
|
+
|
|
24
|
+
attr_accessor signature: String?
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class ToolUseBlock < Type
|
|
28
|
+
attr_accessor id: String?
|
|
29
|
+
|
|
30
|
+
attr_accessor name: String?
|
|
31
|
+
|
|
32
|
+
attr_accessor input: block_hash?
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
class ToolResultBlock < Type
|
|
36
|
+
attr_accessor tool_use_id: String?
|
|
37
|
+
|
|
38
|
+
# A String, or an Array of content-block Hashes.
|
|
39
|
+
attr_accessor content: (String | Array[block_hash])?
|
|
40
|
+
|
|
41
|
+
attr_accessor is_error: bool?
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# A server-side tool call (advisor, web_search, code_execution, ...).
|
|
45
|
+
class ServerToolUseBlock < Type
|
|
46
|
+
attr_accessor id: String?
|
|
47
|
+
|
|
48
|
+
attr_accessor name: String?
|
|
49
|
+
|
|
50
|
+
attr_accessor input: block_hash?
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# The result of a server-side tool call. content is passed through from
|
|
54
|
+
# the API as-is and its shape depends on the tool.
|
|
55
|
+
class ServerToolResultBlock < Type
|
|
56
|
+
attr_accessor tool_use_id: String?
|
|
57
|
+
|
|
58
|
+
attr_accessor content: untyped
|
|
59
|
+
|
|
60
|
+
attr_accessor is_error: bool?
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# A block type this SDK version does not model ("document", "image", ...):
|
|
64
|
+
# type is the original block type, data the raw block.
|
|
65
|
+
class UnknownBlock < Type
|
|
66
|
+
attr_accessor type: String?
|
|
67
|
+
|
|
68
|
+
attr_accessor data: block_hash?
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# A tool call a PreToolUse hook deferred (ResultMessage#deferred_tool_use).
|
|
72
|
+
class DeferredToolUse < Type
|
|
73
|
+
attr_accessor id: String?
|
|
74
|
+
|
|
75
|
+
attr_accessor name: String?
|
|
76
|
+
|
|
77
|
+
attr_accessor input: block_hash?
|
|
78
|
+
end
|
|
79
|
+
end
|