claude_agent 0.7.12 → 0.7.14
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/.claude/rules/testing.md +51 -10
- data/.claude/settings.json +1 -0
- data/ARCHITECTURE.md +237 -0
- data/CHANGELOG.md +53 -0
- data/CLAUDE.md +2 -0
- data/README.md +46 -1
- data/Rakefile +17 -0
- data/SPEC.md +214 -125
- data/lib/claude_agent/client/commands.rb +225 -0
- data/lib/claude_agent/client.rb +4 -206
- data/lib/claude_agent/content_blocks/generic_block.rb +39 -0
- data/lib/claude_agent/content_blocks/image_content_block.rb +54 -0
- data/lib/claude_agent/content_blocks/server_tool_result_block.rb +22 -0
- data/lib/claude_agent/content_blocks/server_tool_use_block.rb +48 -0
- data/lib/claude_agent/content_blocks/text_block.rb +19 -0
- data/lib/claude_agent/content_blocks/thinking_block.rb +19 -0
- data/lib/claude_agent/content_blocks/tool_result_block.rb +25 -0
- data/lib/claude_agent/content_blocks/tool_use_block.rb +134 -0
- data/lib/claude_agent/content_blocks.rb +8 -335
- data/lib/claude_agent/control_protocol/commands.rb +304 -0
- data/lib/claude_agent/control_protocol/lifecycle.rb +116 -0
- data/lib/claude_agent/control_protocol/messaging.rb +163 -0
- data/lib/claude_agent/control_protocol/primitives.rb +168 -0
- data/lib/claude_agent/control_protocol/request_handling.rb +231 -0
- data/lib/claude_agent/control_protocol.rb +50 -882
- data/lib/claude_agent/conversation.rb +8 -1
- data/lib/claude_agent/event_handler.rb +1 -0
- data/lib/claude_agent/get_session_info.rb +86 -0
- data/lib/claude_agent/hooks.rb +23 -2
- data/lib/claude_agent/list_sessions.rb +22 -13
- data/lib/claude_agent/message_parser.rb +26 -4
- data/lib/claude_agent/messages/conversation.rb +138 -0
- data/lib/claude_agent/messages/generic.rb +39 -0
- data/lib/claude_agent/messages/hook_lifecycle.rb +158 -0
- data/lib/claude_agent/messages/result.rb +80 -0
- data/lib/claude_agent/messages/streaming.rb +84 -0
- data/lib/claude_agent/messages/system.rb +67 -0
- data/lib/claude_agent/messages/task_lifecycle.rb +240 -0
- data/lib/claude_agent/messages/tool_lifecycle.rb +95 -0
- data/lib/claude_agent/messages.rb +11 -829
- data/lib/claude_agent/options/serializer.rb +194 -0
- data/lib/claude_agent/options.rb +11 -176
- data/lib/claude_agent/query.rb +0 -2
- data/lib/claude_agent/sandbox_settings.rb +3 -0
- data/lib/claude_agent/session.rb +0 -204
- data/lib/claude_agent/session_mutations.rb +148 -0
- data/lib/claude_agent/transport/subprocess.rb +2 -2
- data/lib/claude_agent/types/mcp.rb +30 -0
- data/lib/claude_agent/types/models.rb +146 -0
- data/lib/claude_agent/types/operations.rb +38 -0
- data/lib/claude_agent/types/sessions.rb +50 -0
- data/lib/claude_agent/types/tools.rb +32 -0
- data/lib/claude_agent/types.rb +6 -264
- data/lib/claude_agent/v2_session.rb +207 -0
- data/lib/claude_agent/version.rb +1 -1
- data/lib/claude_agent.rb +37 -3
- data/sig/claude_agent.rbs +144 -13
- metadata +33 -1
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
|
|
5
|
+
module ClaudeAgent
|
|
6
|
+
# Session mutation operations: rename and tag sessions.
|
|
7
|
+
#
|
|
8
|
+
# Appends JSONL entries to session files to modify session metadata.
|
|
9
|
+
# Follows the TypeScript SDK pattern of file-level mutations.
|
|
10
|
+
#
|
|
11
|
+
# @example Rename a session
|
|
12
|
+
# ClaudeAgent.rename_session("abc-123-...", "My new title")
|
|
13
|
+
#
|
|
14
|
+
# @example Tag a session
|
|
15
|
+
# ClaudeAgent.tag_session("abc-123-...", "important")
|
|
16
|
+
#
|
|
17
|
+
# @example Clear a tag
|
|
18
|
+
# ClaudeAgent.tag_session("abc-123-...", nil)
|
|
19
|
+
#
|
|
20
|
+
module SessionMutations
|
|
21
|
+
# Unicode characters to strip from tag values (zero-width chars, directional marks)
|
|
22
|
+
UNICODE_SANITIZE_PATTERN = /[\u200B\u200C\u200D\uFEFF\u200E\u200F\u202A-\u202E\u2066-\u2069]/
|
|
23
|
+
|
|
24
|
+
module_function
|
|
25
|
+
|
|
26
|
+
# Rename a session by appending a custom-title entry to its session file.
|
|
27
|
+
#
|
|
28
|
+
# @param session_id [String] UUID of the session to rename
|
|
29
|
+
# @param title [String] New title for the session (must be non-empty)
|
|
30
|
+
# @param dir [String, nil] Project directory to find the session in.
|
|
31
|
+
# When nil, searches all projects.
|
|
32
|
+
# @return [void]
|
|
33
|
+
# @raise [ArgumentError] If session_id is not a valid UUID or title is empty
|
|
34
|
+
# @raise [Error] If the session file is not found
|
|
35
|
+
def rename_session(session_id, title, dir: nil)
|
|
36
|
+
validate_session_id!(session_id)
|
|
37
|
+
raise ArgumentError, "title must be a non-empty string" if title.nil? || title.to_s.strip.empty?
|
|
38
|
+
|
|
39
|
+
path = find_session_file(session_id, dir: dir)
|
|
40
|
+
raise Error, "Session not found: #{session_id}" unless path
|
|
41
|
+
|
|
42
|
+
entry = {
|
|
43
|
+
type: "custom-title",
|
|
44
|
+
customTitle: title.to_s,
|
|
45
|
+
sessionId: session_id
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
append_jsonl(path, entry)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Tag a session by appending a tag entry to its session file.
|
|
52
|
+
#
|
|
53
|
+
# @param session_id [String] UUID of the session to tag
|
|
54
|
+
# @param tag [String, nil] Tag value. Pass nil to clear the tag.
|
|
55
|
+
# @param dir [String, nil] Project directory to find the session in.
|
|
56
|
+
# When nil, searches all projects.
|
|
57
|
+
# @return [void]
|
|
58
|
+
# @raise [ArgumentError] If session_id is not a valid UUID
|
|
59
|
+
# @raise [Error] If the session file is not found
|
|
60
|
+
def tag_session(session_id, tag, dir: nil)
|
|
61
|
+
validate_session_id!(session_id)
|
|
62
|
+
|
|
63
|
+
path = find_session_file(session_id, dir: dir)
|
|
64
|
+
raise Error, "Session not found: #{session_id}" unless path
|
|
65
|
+
|
|
66
|
+
sanitized_tag = tag.nil? ? "" : sanitize_unicode(tag.to_s)
|
|
67
|
+
|
|
68
|
+
entry = {
|
|
69
|
+
type: "tag",
|
|
70
|
+
tag: sanitized_tag,
|
|
71
|
+
sessionId: session_id
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
append_jsonl(path, entry)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# --- Private Helpers ---
|
|
78
|
+
|
|
79
|
+
# Validate that a string is a valid UUID.
|
|
80
|
+
# @param session_id [String]
|
|
81
|
+
# @raise [ArgumentError] If not a valid UUID
|
|
82
|
+
def validate_session_id!(session_id)
|
|
83
|
+
unless SessionPaths::UUID_PATTERN.match?(session_id.to_s)
|
|
84
|
+
raise ArgumentError, "Invalid session_id: #{session_id}. Must be a valid UUID."
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Find a session file by UUID, searching project directories.
|
|
89
|
+
# @param session_id [String] UUID
|
|
90
|
+
# @param dir [String, nil] Optional directory to scope the search
|
|
91
|
+
# @return [String, nil] Path to the .jsonl file or nil
|
|
92
|
+
def find_session_file(session_id, dir: nil)
|
|
93
|
+
filename = "#{session_id}.jsonl"
|
|
94
|
+
|
|
95
|
+
if dir
|
|
96
|
+
resolved = SessionPaths.realpath(dir)
|
|
97
|
+
project_dir = SessionPaths.find_project_dir(resolved)
|
|
98
|
+
return nil unless project_dir
|
|
99
|
+
|
|
100
|
+
path = File.join(project_dir, filename)
|
|
101
|
+
return path if File.exist?(path)
|
|
102
|
+
|
|
103
|
+
# Check worktrees
|
|
104
|
+
worktrees = SessionPaths.git_worktrees(resolved)
|
|
105
|
+
worktrees.each do |wt|
|
|
106
|
+
wt_project_dir = SessionPaths.find_project_dir(wt)
|
|
107
|
+
next unless wt_project_dir
|
|
108
|
+
|
|
109
|
+
wt_path = File.join(wt_project_dir, filename)
|
|
110
|
+
return wt_path if File.exist?(wt_path)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
nil
|
|
114
|
+
else
|
|
115
|
+
# Search all project directories
|
|
116
|
+
base = SessionPaths.projects_dir
|
|
117
|
+
return nil unless File.directory?(base)
|
|
118
|
+
|
|
119
|
+
Dir.entries(base).each do |entry|
|
|
120
|
+
next if entry.start_with?(".")
|
|
121
|
+
dir_path = File.join(base, entry)
|
|
122
|
+
next unless File.directory?(dir_path)
|
|
123
|
+
|
|
124
|
+
path = File.join(dir_path, filename)
|
|
125
|
+
return path if File.exist?(path)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
nil
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Sanitize a string by removing zero-width and directional Unicode characters.
|
|
133
|
+
# @param str [String]
|
|
134
|
+
# @return [String]
|
|
135
|
+
def sanitize_unicode(str)
|
|
136
|
+
str.gsub(UNICODE_SANITIZE_PATTERN, "")
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Atomically append a JSONL entry to a file.
|
|
140
|
+
# @param path [String] File path
|
|
141
|
+
# @param entry [Hash] JSON-serializable entry
|
|
142
|
+
def append_jsonl(path, entry)
|
|
143
|
+
File.open(path, "a") do |f|
|
|
144
|
+
f.write("#{JSON.generate(entry)}\n")
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
@@ -387,8 +387,8 @@ module ClaudeAgent
|
|
|
387
387
|
@stderr.each_line do |line|
|
|
388
388
|
# Call callback if provided, otherwise just drain
|
|
389
389
|
@options.stderr_callback&.call(line.chomp)
|
|
390
|
-
rescue
|
|
391
|
-
|
|
390
|
+
rescue => e
|
|
391
|
+
logger.debug("transport") { "stderr callback error: #{e.message}" }
|
|
392
392
|
end
|
|
393
393
|
rescue IOError
|
|
394
394
|
# Stream closed, exit thread
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ClaudeAgent
|
|
4
|
+
# Return type for mcp_server_status() (TypeScript SDK parity)
|
|
5
|
+
# Status values: "connected", "failed", "needs-auth", "pending"
|
|
6
|
+
#
|
|
7
|
+
# @example
|
|
8
|
+
# status = McpServerStatus.new(name: "filesystem", status: "connected", server_info: {name: "fs", version: "1.0"})
|
|
9
|
+
#
|
|
10
|
+
McpServerStatus = Data.define(:name, :status, :server_info, :error, :config, :scope, :tools) do
|
|
11
|
+
def initialize(name:, status:, server_info: nil, error: nil, config: nil, scope: nil, tools: nil)
|
|
12
|
+
super
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Result of set_mcp_servers() control method (TypeScript SDK parity)
|
|
17
|
+
#
|
|
18
|
+
# @example
|
|
19
|
+
# result = McpSetServersResult.new(
|
|
20
|
+
# added: ["server1"],
|
|
21
|
+
# removed: ["old-server"],
|
|
22
|
+
# errors: {"server2" => "Connection failed"}
|
|
23
|
+
# )
|
|
24
|
+
#
|
|
25
|
+
McpSetServersResult = Data.define(:added, :removed, :errors) do
|
|
26
|
+
def initialize(added: [], removed: [], errors: {})
|
|
27
|
+
super
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ClaudeAgent
|
|
4
|
+
# Return type for supported_models() (TypeScript SDK parity)
|
|
5
|
+
#
|
|
6
|
+
# @example
|
|
7
|
+
# model = ModelInfo.new(value: "claude-3-opus", display_name: "Claude 3 Opus", description: "Most capable")
|
|
8
|
+
# model.value # => "claude-3-opus"
|
|
9
|
+
# model.display_name # => "Claude 3 Opus"
|
|
10
|
+
#
|
|
11
|
+
ModelInfo = Data.define(:value, :display_name, :description, :supports_effort, :supported_effort_levels, :supports_adaptive_thinking, :supports_fast_mode, :supports_auto_mode) do
|
|
12
|
+
def initialize(value:, display_name: nil, description: nil, supports_effort: nil, supported_effort_levels: nil, supports_adaptive_thinking: nil, supports_fast_mode: nil, supports_auto_mode: nil)
|
|
13
|
+
super
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Per-model usage statistics returned in result messages (TypeScript SDK parity)
|
|
18
|
+
#
|
|
19
|
+
# @example
|
|
20
|
+
# usage = ModelUsage.new(input_tokens: 100, output_tokens: 50, cost_usd: 0.01, max_output_tokens: 4096)
|
|
21
|
+
#
|
|
22
|
+
ModelUsage = Data.define(
|
|
23
|
+
:input_tokens,
|
|
24
|
+
:output_tokens,
|
|
25
|
+
:cache_read_input_tokens,
|
|
26
|
+
:cache_creation_input_tokens,
|
|
27
|
+
:web_search_requests,
|
|
28
|
+
:cost_usd,
|
|
29
|
+
:context_window,
|
|
30
|
+
:max_output_tokens
|
|
31
|
+
) do
|
|
32
|
+
def initialize(
|
|
33
|
+
input_tokens: 0,
|
|
34
|
+
output_tokens: 0,
|
|
35
|
+
cache_read_input_tokens: 0,
|
|
36
|
+
cache_creation_input_tokens: 0,
|
|
37
|
+
web_search_requests: 0,
|
|
38
|
+
cost_usd: 0.0,
|
|
39
|
+
context_window: nil,
|
|
40
|
+
max_output_tokens: nil
|
|
41
|
+
)
|
|
42
|
+
super
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Return type for account_info() (TypeScript SDK parity)
|
|
47
|
+
#
|
|
48
|
+
# @example
|
|
49
|
+
# info = AccountInfo.new(email: "user@example.com", organization: "Acme Corp")
|
|
50
|
+
#
|
|
51
|
+
AccountInfo = Data.define(:email, :organization, :subscription_type, :token_source, :api_key_source) do
|
|
52
|
+
def initialize(email: nil, organization: nil, subscription_type: nil, token_source: nil, api_key_source: nil)
|
|
53
|
+
super
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Return type for supported_agents() (TypeScript SDK v0.2.63 parity)
|
|
58
|
+
#
|
|
59
|
+
# @example
|
|
60
|
+
# agent = AgentInfo.new(name: "Explore", description: "Search agent", model: "haiku")
|
|
61
|
+
# agent.name # => "Explore"
|
|
62
|
+
# agent.description # => "Search agent"
|
|
63
|
+
#
|
|
64
|
+
AgentInfo = Data.define(:name, :description, :model) do
|
|
65
|
+
def initialize(name:, description: nil, model: nil)
|
|
66
|
+
super
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Agent definition for custom subagents (TypeScript SDK parity)
|
|
71
|
+
#
|
|
72
|
+
# @example Basic agent
|
|
73
|
+
# agent = AgentDefinition.new(
|
|
74
|
+
# description: "Runs tests and reports results",
|
|
75
|
+
# prompt: "You are a test runner...",
|
|
76
|
+
# tools: ["Read", "Grep", "Glob", "Bash"],
|
|
77
|
+
# model: "haiku"
|
|
78
|
+
# )
|
|
79
|
+
#
|
|
80
|
+
# @example Agent with skills and max_turns
|
|
81
|
+
# agent = AgentDefinition.new(
|
|
82
|
+
# description: "Research agent with specialized skills",
|
|
83
|
+
# prompt: "You are a research expert...",
|
|
84
|
+
# skills: ["web-search", "summarization"],
|
|
85
|
+
# max_turns: 10
|
|
86
|
+
# )
|
|
87
|
+
#
|
|
88
|
+
AgentDefinition = Data.define(
|
|
89
|
+
:description,
|
|
90
|
+
:prompt,
|
|
91
|
+
:tools,
|
|
92
|
+
:disallowed_tools,
|
|
93
|
+
:model,
|
|
94
|
+
:mcp_servers,
|
|
95
|
+
:critical_system_reminder,
|
|
96
|
+
:skills,
|
|
97
|
+
:max_turns
|
|
98
|
+
) do
|
|
99
|
+
def initialize(
|
|
100
|
+
description:,
|
|
101
|
+
prompt:,
|
|
102
|
+
tools: nil,
|
|
103
|
+
disallowed_tools: nil,
|
|
104
|
+
model: nil,
|
|
105
|
+
mcp_servers: nil,
|
|
106
|
+
critical_system_reminder: nil,
|
|
107
|
+
skills: nil,
|
|
108
|
+
max_turns: nil
|
|
109
|
+
)
|
|
110
|
+
super
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def to_h
|
|
114
|
+
result = {
|
|
115
|
+
description: description,
|
|
116
|
+
prompt: prompt
|
|
117
|
+
}
|
|
118
|
+
result[:tools] = tools if tools
|
|
119
|
+
result[:disallowedTools] = disallowed_tools if disallowed_tools
|
|
120
|
+
result[:model] = model if model
|
|
121
|
+
result[:mcpServers] = mcp_servers if mcp_servers
|
|
122
|
+
result[:criticalSystemReminder_EXPERIMENTAL] = critical_system_reminder if critical_system_reminder
|
|
123
|
+
result[:skills] = skills if skills
|
|
124
|
+
result[:maxTurns] = max_turns if max_turns
|
|
125
|
+
result
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Composite initialization result from supported_commands request (TypeScript SDK parity)
|
|
130
|
+
#
|
|
131
|
+
# @example
|
|
132
|
+
# result = InitializationResult.new(
|
|
133
|
+
# commands: [SlashCommand.new(name: "commit")],
|
|
134
|
+
# output_style: "default",
|
|
135
|
+
# available_output_styles: ["default", "concise"],
|
|
136
|
+
# models: [ModelInfo.new(value: "claude-sonnet")],
|
|
137
|
+
# account: AccountInfo.new(email: "user@example.com"),
|
|
138
|
+
# agents: [AgentInfo.new(name: "Explore")]
|
|
139
|
+
# )
|
|
140
|
+
#
|
|
141
|
+
InitializationResult = Data.define(:commands, :output_style, :available_output_styles, :models, :account, :agents, :fast_mode_state) do
|
|
142
|
+
def initialize(commands: [], output_style: nil, available_output_styles: [], models: [], account: nil, agents: [], fast_mode_state: nil)
|
|
143
|
+
super
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ClaudeAgent
|
|
4
|
+
# Task usage statistics for TaskNotificationMessage (TypeScript SDK parity)
|
|
5
|
+
#
|
|
6
|
+
# @example
|
|
7
|
+
# usage = TaskUsage.new(total_tokens: 5000, tool_uses: 3, duration_ms: 2500)
|
|
8
|
+
#
|
|
9
|
+
TaskUsage = Data.define(:total_tokens, :tool_uses, :duration_ms) do
|
|
10
|
+
def initialize(total_tokens: 0, tool_uses: 0, duration_ms: 0)
|
|
11
|
+
super
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Permission denial information in result messages (TypeScript SDK parity)
|
|
16
|
+
#
|
|
17
|
+
SDKPermissionDenial = Data.define(:tool_name, :tool_use_id, :tool_input) do
|
|
18
|
+
def initialize(tool_name:, tool_use_id:, tool_input:)
|
|
19
|
+
super
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Result of rewind_files() control method (TypeScript SDK parity)
|
|
24
|
+
#
|
|
25
|
+
# @example
|
|
26
|
+
# result = RewindFilesResult.new(
|
|
27
|
+
# can_rewind: true,
|
|
28
|
+
# files_changed: ["src/foo.rb", "src/bar.rb"],
|
|
29
|
+
# insertions: 10,
|
|
30
|
+
# deletions: 5
|
|
31
|
+
# )
|
|
32
|
+
#
|
|
33
|
+
RewindFilesResult = Data.define(:can_rewind, :error, :files_changed, :insertions, :deletions) do
|
|
34
|
+
def initialize(can_rewind:, error: nil, files_changed: nil, insertions: nil, deletions: nil)
|
|
35
|
+
super
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ClaudeAgent
|
|
4
|
+
# Session metadata returned by list_sessions (TypeScript SDK parity: SDKSessionInfo)
|
|
5
|
+
#
|
|
6
|
+
# @example
|
|
7
|
+
# session = SessionInfo.new(
|
|
8
|
+
# session_id: "abc-123",
|
|
9
|
+
# summary: "Fix login bug",
|
|
10
|
+
# last_modified: 1706000000000,
|
|
11
|
+
# file_size: 4096,
|
|
12
|
+
# custom_title: "Login fix",
|
|
13
|
+
# first_prompt: "Help me fix the login page",
|
|
14
|
+
# git_branch: "fix/login",
|
|
15
|
+
# cwd: "/Users/dev/myapp"
|
|
16
|
+
# )
|
|
17
|
+
#
|
|
18
|
+
SessionInfo = Data.define(
|
|
19
|
+
:session_id,
|
|
20
|
+
:summary,
|
|
21
|
+
:last_modified,
|
|
22
|
+
:file_size,
|
|
23
|
+
:custom_title,
|
|
24
|
+
:first_prompt,
|
|
25
|
+
:git_branch,
|
|
26
|
+
:cwd,
|
|
27
|
+
:tag,
|
|
28
|
+
:created_at
|
|
29
|
+
) do
|
|
30
|
+
def initialize(session_id:, summary:, last_modified:, file_size:, custom_title: nil, first_prompt: nil, git_branch: nil, cwd: nil, tag: nil, created_at: nil)
|
|
31
|
+
super
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Message from a session transcript returned by get_session_messages (TypeScript SDK v0.2.59 parity)
|
|
36
|
+
#
|
|
37
|
+
# @example
|
|
38
|
+
# msg = SessionMessage.new(
|
|
39
|
+
# type: "user",
|
|
40
|
+
# uuid: "abc-123",
|
|
41
|
+
# session_id: "def-456",
|
|
42
|
+
# message: { "role" => "user", "content" => [{ "type" => "text", "text" => "Hello" }] }
|
|
43
|
+
# )
|
|
44
|
+
#
|
|
45
|
+
SessionMessage = Data.define(:type, :uuid, :session_id, :message, :parent_tool_use_id) do
|
|
46
|
+
def initialize(type:, uuid:, session_id:, message:, parent_tool_use_id: nil)
|
|
47
|
+
super
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ClaudeAgent
|
|
4
|
+
# Tools preset configuration (TypeScript SDK parity)
|
|
5
|
+
#
|
|
6
|
+
# @example
|
|
7
|
+
# preset = ToolsPreset.new(preset: "claude_code")
|
|
8
|
+
# options = ClaudeAgent::Options.new(tools: preset)
|
|
9
|
+
#
|
|
10
|
+
ToolsPreset = Data.define(:type, :preset) do
|
|
11
|
+
def initialize(type: "preset", preset: "claude_code")
|
|
12
|
+
super
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def to_h
|
|
16
|
+
{ type: type, preset: preset }
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Return type for supported_commands() (TypeScript SDK parity)
|
|
21
|
+
#
|
|
22
|
+
# @example
|
|
23
|
+
# cmd = SlashCommand.new(name: "commit", description: "Create a commit", argument_hint: "[message]")
|
|
24
|
+
# cmd.name # => "commit"
|
|
25
|
+
# cmd.description # => "Create a commit"
|
|
26
|
+
#
|
|
27
|
+
SlashCommand = Data.define(:name, :description, :argument_hint) do
|
|
28
|
+
def initialize(name:, description: nil, argument_hint: nil)
|
|
29
|
+
super
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|