claude-agent-sdk 0.37.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 +17 -0
- data/README.md +6 -2
- data/UPGRADING-1.0.md +151 -0
- data/docs/errors.md +6 -0
- data/docs/sessions.md +20 -1
- data/docs/types.md +17 -14
- data/lib/claude_agent_sdk/deprecation.rb +1 -40
- data/lib/claude_agent_sdk/errors.rb +10 -0
- data/lib/claude_agent_sdk/session_resume.rb +11 -5
- data/lib/claude_agent_sdk/types/attributes.rb +14 -49
- data/lib/claude_agent_sdk/types/base.rb +2 -0
- data/lib/claude_agent_sdk/version.rb +1 -1
- data/lib/claude_agent_sdk.rb +11 -11
- 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 +22 -1
data/lib/claude_agent_sdk.rb
CHANGED
|
@@ -541,27 +541,27 @@ module ClaudeAgentSDK # rubocop:disable Metrics/ModuleLength -- the public entry
|
|
|
541
541
|
SessionSummary.fold_session_summary(prev, key, entries)
|
|
542
542
|
end
|
|
543
543
|
|
|
544
|
-
# ---- Deprecated store twins (removed in
|
|
544
|
+
# ---- Deprecated store twins (removed in 2.0) ----
|
|
545
545
|
#
|
|
546
546
|
# Each forwards to the same implementation as before — not to the merged
|
|
547
547
|
# function, so a nil session_store keeps failing as it always did instead
|
|
548
548
|
# of silently reading local disk — after one warning per method per process.
|
|
549
549
|
|
|
550
|
-
# @deprecated Use {.list_sessions} with +session_store:+. Removed in
|
|
550
|
+
# @deprecated Use {.list_sessions} with +session_store:+. Removed in 2.0.
|
|
551
551
|
# @return [Array<SDKSessionInfo>] sorted by last_modified descending
|
|
552
552
|
def self.list_sessions_from_store(session_store:, directory: nil, limit: nil, offset: 0)
|
|
553
553
|
Deprecation.warn_once(:list_sessions_from_store, 'list_sessions(session_store: store)')
|
|
554
554
|
Sessions.list_sessions_from_store(session_store: session_store, directory: directory, limit: limit, offset: offset)
|
|
555
555
|
end
|
|
556
556
|
|
|
557
|
-
# @deprecated Use {.get_session_info} with +session_store:+. Removed in
|
|
557
|
+
# @deprecated Use {.get_session_info} with +session_store:+. Removed in 2.0.
|
|
558
558
|
# @return [SDKSessionInfo, nil]
|
|
559
559
|
def self.get_session_info_from_store(session_store:, session_id:, directory: nil)
|
|
560
560
|
Deprecation.warn_once(:get_session_info_from_store, 'get_session_info(session_store: store, ...)')
|
|
561
561
|
Sessions.get_session_info_from_store(session_store: session_store, session_id: session_id, directory: directory)
|
|
562
562
|
end
|
|
563
563
|
|
|
564
|
-
# @deprecated Use {.get_session_messages} with +session_store:+. Removed in
|
|
564
|
+
# @deprecated Use {.get_session_messages} with +session_store:+. Removed in 2.0.
|
|
565
565
|
# @return [Array<SessionMessage>]
|
|
566
566
|
def self.get_session_messages_from_store(session_store:, session_id:, directory: nil, limit: nil, offset: 0)
|
|
567
567
|
Deprecation.warn_once(:get_session_messages_from_store, 'get_session_messages(session_store: store, ...)')
|
|
@@ -569,14 +569,14 @@ module ClaudeAgentSDK # rubocop:disable Metrics/ModuleLength -- the public entry
|
|
|
569
569
|
directory: directory, limit: limit, offset: offset)
|
|
570
570
|
end
|
|
571
571
|
|
|
572
|
-
# @deprecated Use {.list_subagents} with +session_store:+. Removed in
|
|
572
|
+
# @deprecated Use {.list_subagents} with +session_store:+. Removed in 2.0.
|
|
573
573
|
# @return [Array<String>]
|
|
574
574
|
def self.list_subagents_from_store(session_store:, session_id:, directory: nil)
|
|
575
575
|
Deprecation.warn_once(:list_subagents_from_store, 'list_subagents(session_store: store, ...)')
|
|
576
576
|
Sessions.list_subagents_from_store(session_store: session_store, session_id: session_id, directory: directory)
|
|
577
577
|
end
|
|
578
578
|
|
|
579
|
-
# @deprecated Use {.get_subagent_metadata} with +session_store:+. Removed in
|
|
579
|
+
# @deprecated Use {.get_subagent_metadata} with +session_store:+. Removed in 2.0.
|
|
580
580
|
# @return [Hash{String => Object}, nil]
|
|
581
581
|
def self.get_subagent_metadata_from_store(session_store:, session_id:, agent_id:, directory: nil)
|
|
582
582
|
Deprecation.warn_once(:get_subagent_metadata_from_store, 'get_subagent_metadata(session_store: store, ...)')
|
|
@@ -584,7 +584,7 @@ module ClaudeAgentSDK # rubocop:disable Metrics/ModuleLength -- the public entry
|
|
|
584
584
|
agent_id: agent_id, directory: directory)
|
|
585
585
|
end
|
|
586
586
|
|
|
587
|
-
# @deprecated Use {.get_subagent_messages} with +session_store:+. Removed in
|
|
587
|
+
# @deprecated Use {.get_subagent_messages} with +session_store:+. Removed in 2.0.
|
|
588
588
|
# @return [Array<SessionMessage>]
|
|
589
589
|
def self.get_subagent_messages_from_store(session_store:, session_id:, agent_id:, directory: nil, limit: nil,
|
|
590
590
|
offset: 0)
|
|
@@ -593,28 +593,28 @@ module ClaudeAgentSDK # rubocop:disable Metrics/ModuleLength -- the public entry
|
|
|
593
593
|
agent_id: agent_id, directory: directory, limit: limit, offset: offset)
|
|
594
594
|
end
|
|
595
595
|
|
|
596
|
-
# @deprecated Use {.rename_session} with +session_store:+. Removed in
|
|
596
|
+
# @deprecated Use {.rename_session} with +session_store:+. Removed in 2.0.
|
|
597
597
|
def self.rename_session_via_store(session_store:, session_id:, title:, directory: nil)
|
|
598
598
|
Deprecation.warn_once(:rename_session_via_store, 'rename_session(session_store: store, ...)')
|
|
599
599
|
SessionMutations.rename_session_via_store(session_store: session_store, session_id: session_id,
|
|
600
600
|
title: title, directory: directory)
|
|
601
601
|
end
|
|
602
602
|
|
|
603
|
-
# @deprecated Use {.tag_session} with +session_store:+. Removed in
|
|
603
|
+
# @deprecated Use {.tag_session} with +session_store:+. Removed in 2.0.
|
|
604
604
|
def self.tag_session_via_store(session_store:, session_id:, tag:, directory: nil)
|
|
605
605
|
Deprecation.warn_once(:tag_session_via_store, 'tag_session(session_store: store, ...)')
|
|
606
606
|
SessionMutations.tag_session_via_store(session_store: session_store, session_id: session_id,
|
|
607
607
|
tag: tag, directory: directory)
|
|
608
608
|
end
|
|
609
609
|
|
|
610
|
-
# @deprecated Use {.delete_session} with +session_store:+. Removed in
|
|
610
|
+
# @deprecated Use {.delete_session} with +session_store:+. Removed in 2.0.
|
|
611
611
|
def self.delete_session_via_store(session_store:, session_id:, directory: nil)
|
|
612
612
|
Deprecation.warn_once(:delete_session_via_store, 'delete_session(session_store: store, ...)')
|
|
613
613
|
SessionMutations.delete_session_via_store(session_store: session_store, session_id: session_id,
|
|
614
614
|
directory: directory)
|
|
615
615
|
end
|
|
616
616
|
|
|
617
|
-
# @deprecated Use {.fork_session} with +session_store:+. Removed in
|
|
617
|
+
# @deprecated Use {.fork_session} with +session_store:+. Removed in 2.0.
|
|
618
618
|
# @return [ForkSessionResult]
|
|
619
619
|
def self.fork_session_via_store(session_store:, session_id:, directory: nil, up_to_message_id: nil, title: nil)
|
|
620
620
|
Deprecation.warn_once(:fork_session_via_store, 'fork_session(session_store: store, ...)')
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module ClaudeAgentSDK
|
|
2
|
+
# Delivered as ToolPermissionContext#signal and HookContext#signal. It is
|
|
3
|
+
# cancelled when the CLI cancels the request (or the session closes), so a
|
|
4
|
+
# long-running callback can stop early.
|
|
5
|
+
class CancellationSignal
|
|
6
|
+
def initialize: () -> void
|
|
7
|
+
|
|
8
|
+
def cancelled?: () -> bool
|
|
9
|
+
|
|
10
|
+
# Blocks until cancelled or until timeout seconds pass; returns
|
|
11
|
+
# #cancelled?.
|
|
12
|
+
def wait: (?timeout: (Integer | Float)?) -> bool
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module ClaudeAgentSDK
|
|
2
|
+
# Global defaults set via ClaudeAgentSDK.configure, merged under every
|
|
3
|
+
# ClaudeAgentOptions (per-call options win).
|
|
4
|
+
class Configuration
|
|
5
|
+
# A frozen snapshot of the configured defaults ({} when unset). Keys are
|
|
6
|
+
# ClaudeAgentOptions option names.
|
|
7
|
+
attr_reader default_options: Hash[Symbol | String, untyped]
|
|
8
|
+
|
|
9
|
+
def initialize: () -> void
|
|
10
|
+
|
|
11
|
+
# Stores a deep-frozen copy; nil resets to {}.
|
|
12
|
+
def default_options=: (Hash[Symbol | String, untyped]? value) -> Hash[Symbol | String, untyped]?
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
module ClaudeAgentSDK
|
|
2
|
+
# Base exception for all Claude SDK errors.
|
|
3
|
+
class ClaudeSDKError < StandardError
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
# Raised when unable to connect to Claude Code (also: "Not connected").
|
|
7
|
+
class CLIConnectionError < ClaudeSDKError
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Raised when the control protocol does not respond in time.
|
|
11
|
+
class ControlRequestTimeoutError < CLIConnectionError
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Raised when Claude Code is not found or not installed.
|
|
15
|
+
class CLINotFoundError < CLIConnectionError
|
|
16
|
+
def initialize: (?String message, ?cli_path: (String | Pathname)?) -> void
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Raised when CLIInstaller cannot install the CLI binary.
|
|
20
|
+
class CLIInstallError < ClaudeSDKError
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Raised by the local-disk session APIs when the Claude config directory
|
|
24
|
+
# cannot be located.
|
|
25
|
+
class ConfigDirError < ClaudeSDKError
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Raised by Client#connect, ClaudeAgentSDK.query and .ask when resuming
|
|
29
|
+
# from ClaudeAgentOptions#session_store fails (a store call raised or
|
|
30
|
+
# exceeded load_timeout_ms). #cause holds the adapter's own exception.
|
|
31
|
+
class SessionStoreError < ClaudeSDKError
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Raised when the CLI process fails.
|
|
35
|
+
class ProcessError < ClaudeSDKError
|
|
36
|
+
attr_reader exit_code: Integer?
|
|
37
|
+
|
|
38
|
+
attr_reader stderr: String?
|
|
39
|
+
|
|
40
|
+
def initialize: (String message, ?exit_code: Integer?, ?stderr: String?) -> void
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Raised when the CLI exits non-zero after an error result. Every
|
|
44
|
+
# structured field is type-narrowed (nil unless the payload held the
|
|
45
|
+
# documented type); #data holds the payload as the CLI sent it.
|
|
46
|
+
class ResultError < ProcessError
|
|
47
|
+
attr_reader subtype: String?
|
|
48
|
+
|
|
49
|
+
attr_reader errors: Array[String]
|
|
50
|
+
|
|
51
|
+
attr_reader result: String?
|
|
52
|
+
|
|
53
|
+
attr_reader api_error_status: Integer?
|
|
54
|
+
|
|
55
|
+
attr_reader terminal_reason: String?
|
|
56
|
+
|
|
57
|
+
attr_reader session_id: String?
|
|
58
|
+
|
|
59
|
+
attr_reader data: Hash[Symbol | String, untyped]
|
|
60
|
+
|
|
61
|
+
attr_reader original_error: ProcessError?
|
|
62
|
+
|
|
63
|
+
# The exception text a `result` payload produces (any payload is
|
|
64
|
+
# accepted; a non-Hash reads as empty).
|
|
65
|
+
def self.error_text: (untyped data) -> String
|
|
66
|
+
|
|
67
|
+
def initialize: (String message, ?data: untyped, ?exit_code: Integer?, ?stderr: String?, ?original_error: ProcessError?) -> void
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Raised when a stdout line from the CLI is not valid JSON.
|
|
71
|
+
class CLIJSONDecodeError < ClaudeSDKError
|
|
72
|
+
attr_reader line: String
|
|
73
|
+
|
|
74
|
+
attr_reader original_error: Exception
|
|
75
|
+
|
|
76
|
+
def initialize: (String line, Exception original_error) -> void
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Raised when a CLI message cannot be parsed into a typed message.
|
|
80
|
+
class MessageParseError < ClaudeSDKError
|
|
81
|
+
# The offending payload, as received.
|
|
82
|
+
attr_reader data: untyped
|
|
83
|
+
|
|
84
|
+
def initialize: (String message, ?data: untyped) -> void
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
module ClaudeAgentSDK
|
|
2
|
+
# Base module for message observers (ClaudeAgentOptions#observers): include
|
|
3
|
+
# it and override the callbacks you need; each defaults to a no-op.
|
|
4
|
+
# Observer errors are rescued and never reach the pipeline.
|
|
5
|
+
module Observer
|
|
6
|
+
def on_user_prompt: (String prompt) -> void
|
|
7
|
+
|
|
8
|
+
def on_message: (message message) -> void
|
|
9
|
+
|
|
10
|
+
def on_error: (StandardError error) -> void
|
|
11
|
+
|
|
12
|
+
def on_close: () -> void
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Loaded by `require 'claude_agent_sdk/instrumentation'` (needs the
|
|
16
|
+
# opentelemetry-api gem).
|
|
17
|
+
module Instrumentation
|
|
18
|
+
# Emits OpenTelemetry spans (gen_ai.* + OpenInference conventions) for a
|
|
19
|
+
# session.
|
|
20
|
+
class OTelObserver
|
|
21
|
+
include Observer
|
|
22
|
+
|
|
23
|
+
TRACER_NAME: String
|
|
24
|
+
|
|
25
|
+
MAX_ATTRIBUTE_LENGTH: Integer
|
|
26
|
+
|
|
27
|
+
# default_attributes are added to every span. Attribute names usually
|
|
28
|
+
# contain dots, so they are commonly given as String keys
|
|
29
|
+
# (`new('user.id' => 'u1')`).
|
|
30
|
+
def initialize: (?tracer_name: String, **untyped default_attributes) -> void
|
|
31
|
+
| (Hash[String | Symbol, untyped] default_attributes) -> void
|
|
32
|
+
|
|
33
|
+
def on_user_prompt: (String prompt) -> void
|
|
34
|
+
|
|
35
|
+
def on_message: (message message) -> void
|
|
36
|
+
|
|
37
|
+
def on_error: (StandardError error) -> void
|
|
38
|
+
|
|
39
|
+
def on_close: () -> void
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
module ClaudeAgentSDK
|
|
2
|
+
# Rails integration (lib/claude_agent_sdk/railtie.rb), loaded only when
|
|
3
|
+
# Rails::Railtie is defined. Declared without its Rails::Railtie superclass
|
|
4
|
+
# so these signatures validate without Rails' own.
|
|
5
|
+
class Railtie
|
|
6
|
+
# A callback_wrapper that runs SDK callbacks in the Rails executor,
|
|
7
|
+
# deadlock-free under development code reloading.
|
|
8
|
+
def self.callback_wrapper: () -> _CallbackWrapper
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
module ClaudeAgentSDK
|
|
2
|
+
# What an SDK MCP tool handler returns: a String (sent as one text block),
|
|
3
|
+
# or a Hash with a :content Array of MCP content blocks plus optional
|
|
4
|
+
# :is_error / :structured_content.
|
|
5
|
+
type tool_result = String | Hash[Symbol | String, untyped]
|
|
6
|
+
|
|
7
|
+
# An SDK MCP tool handler (the block given to ClaudeAgentSDK.create_tool).
|
|
8
|
+
# args is the tools/call arguments Hash (wire_hash).
|
|
9
|
+
interface _ToolHandler
|
|
10
|
+
def call: (wire_hash args) -> tool_result
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# An SDK MCP resource reader: returns a Hash with a :contents Array.
|
|
14
|
+
interface _ResourceReader
|
|
15
|
+
def call: () -> Hash[Symbol | String, untyped]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# An SDK MCP prompt generator: returns a Hash with a :messages Array.
|
|
19
|
+
interface _PromptGenerator
|
|
20
|
+
def call: (Hash[Symbol | String, untyped] args) -> Hash[Symbol | String, untyped]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# An in-process MCP server (built by ClaudeAgentSDK.create_sdk_mcp_server).
|
|
24
|
+
# The list_*/call_*/read_*/get_* methods invoke it directly, outside a
|
|
25
|
+
# session.
|
|
26
|
+
class SdkMcpServer
|
|
27
|
+
attr_reader name: String
|
|
28
|
+
|
|
29
|
+
attr_reader version: String
|
|
30
|
+
|
|
31
|
+
attr_reader tools: Array[SdkMcpTool]
|
|
32
|
+
|
|
33
|
+
attr_reader resources: Array[SdkMcpResource]
|
|
34
|
+
|
|
35
|
+
attr_reader prompts: Array[SdkMcpPrompt]
|
|
36
|
+
|
|
37
|
+
# The underlying server object from the `mcp` gem (MCP::Server); not
|
|
38
|
+
# typed here so the signatures don't depend on that gem's.
|
|
39
|
+
attr_reader mcp_server: untyped
|
|
40
|
+
|
|
41
|
+
# Where handlers run on DIRECT invocations (a session dispatch uses the
|
|
42
|
+
# session's own mode). Defaults to :thread.
|
|
43
|
+
attr_reader callback_scheduling: :thread | :inline
|
|
44
|
+
|
|
45
|
+
# Wrapper for DIRECT invocations (a session dispatch uses the session's).
|
|
46
|
+
attr_reader callback_wrapper: _CallbackWrapper?
|
|
47
|
+
|
|
48
|
+
# A String is coerced to a Symbol; anything but :thread / :inline raises
|
|
49
|
+
# ArgumentError.
|
|
50
|
+
def callback_scheduling=: (:thread | :inline | "thread" | "inline" value) -> (:thread | :inline | "thread" | "inline")
|
|
51
|
+
|
|
52
|
+
# Raises ArgumentError unless value is callable or nil.
|
|
53
|
+
def callback_wrapper=: (_CallbackWrapper? value) -> _CallbackWrapper?
|
|
54
|
+
|
|
55
|
+
def initialize: (name: String, ?version: String, ?tools: Array[SdkMcpTool], ?resources: Array[SdkMcpResource], ?prompts: Array[SdkMcpPrompt]) -> void
|
|
56
|
+
|
|
57
|
+
# Tool definitions: { name:, description:, inputSchema:, annotations:?, _meta:? }.
|
|
58
|
+
def list_tools: () -> Array[Hash[Symbol, untyped]]
|
|
59
|
+
|
|
60
|
+
# Runs the tool's handler. Failures come back in-band with isError: true
|
|
61
|
+
# (a String handler result is wrapped into a text block).
|
|
62
|
+
def call_tool: (String name, Hash[Symbol | String, untyped] arguments) -> Hash[Symbol | String, untyped]
|
|
63
|
+
|
|
64
|
+
def list_resources: () -> Array[Hash[Symbol, untyped]]
|
|
65
|
+
|
|
66
|
+
# Raises when the resource does not exist or its reader returns no
|
|
67
|
+
# :contents.
|
|
68
|
+
def read_resource: (String uri) -> Hash[Symbol | String, untyped]
|
|
69
|
+
|
|
70
|
+
def list_prompts: () -> Array[Hash[Symbol, untyped]]
|
|
71
|
+
|
|
72
|
+
# Raises when the prompt does not exist or its generator returns no
|
|
73
|
+
# :messages.
|
|
74
|
+
def get_prompt: (String name, ?Hash[Symbol | String, untyped] arguments) -> Hash[Symbol | String, untyped]
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -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
|