swarm_memory 2.1.5 → 2.1.6
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/lib/swarm_memory/version.rb +1 -1
- metadata +5 -184
- data/lib/claude_swarm/base_executor.rb +0 -133
- data/lib/claude_swarm/claude_code_executor.rb +0 -349
- data/lib/claude_swarm/claude_mcp_server.rb +0 -78
- data/lib/claude_swarm/cli.rb +0 -697
- data/lib/claude_swarm/commands/ps.rb +0 -215
- data/lib/claude_swarm/commands/show.rb +0 -139
- data/lib/claude_swarm/configuration.rb +0 -373
- data/lib/claude_swarm/hooks/session_start_hook.rb +0 -42
- data/lib/claude_swarm/json_handler.rb +0 -91
- data/lib/claude_swarm/mcp_generator.rb +0 -230
- data/lib/claude_swarm/openai/chat_completion.rb +0 -256
- data/lib/claude_swarm/openai/executor.rb +0 -256
- data/lib/claude_swarm/openai/responses.rb +0 -319
- data/lib/claude_swarm/orchestrator.rb +0 -878
- data/lib/claude_swarm/process_tracker.rb +0 -78
- data/lib/claude_swarm/session_cost_calculator.rb +0 -209
- data/lib/claude_swarm/session_path.rb +0 -42
- data/lib/claude_swarm/settings_generator.rb +0 -77
- data/lib/claude_swarm/system_utils.rb +0 -46
- data/lib/claude_swarm/templates/generation_prompt.md.erb +0 -230
- data/lib/claude_swarm/tools/reset_session_tool.rb +0 -24
- data/lib/claude_swarm/tools/session_info_tool.rb +0 -24
- data/lib/claude_swarm/tools/task_tool.rb +0 -63
- data/lib/claude_swarm/version.rb +0 -5
- data/lib/claude_swarm/worktree_manager.rb +0 -475
- data/lib/claude_swarm/yaml_loader.rb +0 -22
- data/lib/claude_swarm.rb +0 -67
- data/lib/swarm_cli/cli.rb +0 -201
- data/lib/swarm_cli/command_registry.rb +0 -61
- data/lib/swarm_cli/commands/mcp_serve.rb +0 -130
- data/lib/swarm_cli/commands/mcp_tools.rb +0 -148
- data/lib/swarm_cli/commands/migrate.rb +0 -55
- data/lib/swarm_cli/commands/run.rb +0 -173
- data/lib/swarm_cli/config_loader.rb +0 -98
- data/lib/swarm_cli/formatters/human_formatter.rb +0 -781
- data/lib/swarm_cli/formatters/json_formatter.rb +0 -51
- data/lib/swarm_cli/interactive_repl.rb +0 -924
- data/lib/swarm_cli/mcp_serve_options.rb +0 -44
- data/lib/swarm_cli/mcp_tools_options.rb +0 -59
- data/lib/swarm_cli/migrate_options.rb +0 -54
- data/lib/swarm_cli/migrator.rb +0 -132
- data/lib/swarm_cli/options.rb +0 -151
- data/lib/swarm_cli/ui/components/agent_badge.rb +0 -33
- data/lib/swarm_cli/ui/components/content_block.rb +0 -120
- data/lib/swarm_cli/ui/components/divider.rb +0 -57
- data/lib/swarm_cli/ui/components/panel.rb +0 -62
- data/lib/swarm_cli/ui/components/usage_stats.rb +0 -70
- data/lib/swarm_cli/ui/formatters/cost.rb +0 -49
- data/lib/swarm_cli/ui/formatters/number.rb +0 -58
- data/lib/swarm_cli/ui/formatters/text.rb +0 -77
- data/lib/swarm_cli/ui/formatters/time.rb +0 -73
- data/lib/swarm_cli/ui/icons.rb +0 -36
- data/lib/swarm_cli/ui/renderers/event_renderer.rb +0 -188
- data/lib/swarm_cli/ui/state/agent_color_cache.rb +0 -45
- data/lib/swarm_cli/ui/state/depth_tracker.rb +0 -40
- data/lib/swarm_cli/ui/state/spinner_manager.rb +0 -170
- data/lib/swarm_cli/ui/state/usage_tracker.rb +0 -62
- data/lib/swarm_cli/version.rb +0 -5
- data/lib/swarm_cli.rb +0 -46
- data/lib/swarm_sdk/agent/RETRY_LOGIC.md +0 -127
- data/lib/swarm_sdk/agent/builder.rb +0 -552
- data/lib/swarm_sdk/agent/chat.rb +0 -774
- data/lib/swarm_sdk/agent/chat_helpers/context_tracker.rb +0 -268
- data/lib/swarm_sdk/agent/chat_helpers/event_emitter.rb +0 -204
- data/lib/swarm_sdk/agent/chat_helpers/hook_integration.rb +0 -480
- data/lib/swarm_sdk/agent/chat_helpers/instrumentation.rb +0 -78
- data/lib/swarm_sdk/agent/chat_helpers/llm_configuration.rb +0 -233
- data/lib/swarm_sdk/agent/chat_helpers/logging_helpers.rb +0 -116
- data/lib/swarm_sdk/agent/chat_helpers/serialization.rb +0 -83
- data/lib/swarm_sdk/agent/chat_helpers/system_reminder_injector.rb +0 -136
- data/lib/swarm_sdk/agent/chat_helpers/system_reminders.rb +0 -79
- data/lib/swarm_sdk/agent/chat_helpers/token_tracking.rb +0 -98
- data/lib/swarm_sdk/agent/context.rb +0 -116
- data/lib/swarm_sdk/agent/context_manager.rb +0 -315
- data/lib/swarm_sdk/agent/definition.rb +0 -477
- data/lib/swarm_sdk/agent/llm_instrumentation_middleware.rb +0 -182
- data/lib/swarm_sdk/agent/system_prompt_builder.rb +0 -161
- data/lib/swarm_sdk/builders/base_builder.rb +0 -409
- data/lib/swarm_sdk/claude_code_agent_adapter.rb +0 -205
- data/lib/swarm_sdk/concerns/cleanupable.rb +0 -39
- data/lib/swarm_sdk/concerns/snapshotable.rb +0 -67
- data/lib/swarm_sdk/concerns/validatable.rb +0 -55
- data/lib/swarm_sdk/configuration/parser.rb +0 -353
- data/lib/swarm_sdk/configuration/translator.rb +0 -255
- data/lib/swarm_sdk/configuration.rb +0 -135
- data/lib/swarm_sdk/context_compactor/metrics.rb +0 -147
- data/lib/swarm_sdk/context_compactor/token_counter.rb +0 -106
- data/lib/swarm_sdk/context_compactor.rb +0 -335
- data/lib/swarm_sdk/context_management/builder.rb +0 -128
- data/lib/swarm_sdk/context_management/context.rb +0 -328
- data/lib/swarm_sdk/defaults.rb +0 -196
- data/lib/swarm_sdk/events_to_messages.rb +0 -199
- data/lib/swarm_sdk/hooks/adapter.rb +0 -359
- data/lib/swarm_sdk/hooks/context.rb +0 -197
- data/lib/swarm_sdk/hooks/definition.rb +0 -80
- data/lib/swarm_sdk/hooks/error.rb +0 -29
- data/lib/swarm_sdk/hooks/executor.rb +0 -146
- data/lib/swarm_sdk/hooks/registry.rb +0 -147
- data/lib/swarm_sdk/hooks/result.rb +0 -150
- data/lib/swarm_sdk/hooks/shell_executor.rb +0 -255
- data/lib/swarm_sdk/hooks/tool_call.rb +0 -35
- data/lib/swarm_sdk/hooks/tool_result.rb +0 -62
- data/lib/swarm_sdk/log_collector.rb +0 -227
- data/lib/swarm_sdk/log_stream.rb +0 -127
- data/lib/swarm_sdk/markdown_parser.rb +0 -75
- data/lib/swarm_sdk/model_aliases.json +0 -8
- data/lib/swarm_sdk/models.json +0 -1
- data/lib/swarm_sdk/models.rb +0 -120
- data/lib/swarm_sdk/node_context.rb +0 -245
- data/lib/swarm_sdk/observer/builder.rb +0 -81
- data/lib/swarm_sdk/observer/config.rb +0 -45
- data/lib/swarm_sdk/observer/manager.rb +0 -236
- data/lib/swarm_sdk/patterns/agent_observer.rb +0 -160
- data/lib/swarm_sdk/permissions/config.rb +0 -239
- data/lib/swarm_sdk/permissions/error_formatter.rb +0 -121
- data/lib/swarm_sdk/permissions/path_matcher.rb +0 -35
- data/lib/swarm_sdk/permissions/validator.rb +0 -173
- data/lib/swarm_sdk/permissions_builder.rb +0 -122
- data/lib/swarm_sdk/plugin.rb +0 -309
- data/lib/swarm_sdk/plugin_registry.rb +0 -101
- data/lib/swarm_sdk/proc_helpers.rb +0 -53
- data/lib/swarm_sdk/prompts/base_system_prompt.md.erb +0 -117
- data/lib/swarm_sdk/restore_result.rb +0 -65
- data/lib/swarm_sdk/result.rb +0 -123
- data/lib/swarm_sdk/snapshot.rb +0 -156
- data/lib/swarm_sdk/snapshot_from_events.rb +0 -397
- data/lib/swarm_sdk/state_restorer.rb +0 -476
- data/lib/swarm_sdk/state_snapshot.rb +0 -334
- data/lib/swarm_sdk/swarm/agent_initializer.rb +0 -683
- data/lib/swarm_sdk/swarm/all_agents_builder.rb +0 -167
- data/lib/swarm_sdk/swarm/builder.rb +0 -249
- data/lib/swarm_sdk/swarm/executor.rb +0 -213
- data/lib/swarm_sdk/swarm/hook_triggers.rb +0 -150
- data/lib/swarm_sdk/swarm/logging_callbacks.rb +0 -340
- data/lib/swarm_sdk/swarm/mcp_configurator.rb +0 -154
- data/lib/swarm_sdk/swarm/swarm_registry_builder.rb +0 -67
- data/lib/swarm_sdk/swarm/tool_configurator.rb +0 -358
- data/lib/swarm_sdk/swarm.rb +0 -717
- data/lib/swarm_sdk/swarm_loader.rb +0 -145
- data/lib/swarm_sdk/swarm_registry.rb +0 -136
- data/lib/swarm_sdk/tools/bash.rb +0 -282
- data/lib/swarm_sdk/tools/clock.rb +0 -44
- data/lib/swarm_sdk/tools/delegate.rb +0 -267
- data/lib/swarm_sdk/tools/document_converters/base_converter.rb +0 -83
- data/lib/swarm_sdk/tools/document_converters/docx_converter.rb +0 -99
- data/lib/swarm_sdk/tools/document_converters/html_converter.rb +0 -101
- data/lib/swarm_sdk/tools/document_converters/pdf_converter.rb +0 -78
- data/lib/swarm_sdk/tools/document_converters/xlsx_converter.rb +0 -194
- data/lib/swarm_sdk/tools/edit.rb +0 -145
- data/lib/swarm_sdk/tools/glob.rb +0 -166
- data/lib/swarm_sdk/tools/grep.rb +0 -235
- data/lib/swarm_sdk/tools/image_extractors/docx_image_extractor.rb +0 -43
- data/lib/swarm_sdk/tools/image_extractors/pdf_image_extractor.rb +0 -163
- data/lib/swarm_sdk/tools/image_formats/tiff_builder.rb +0 -65
- data/lib/swarm_sdk/tools/multi_edit.rb +0 -236
- data/lib/swarm_sdk/tools/path_resolver.rb +0 -92
- data/lib/swarm_sdk/tools/read.rb +0 -261
- data/lib/swarm_sdk/tools/registry.rb +0 -205
- data/lib/swarm_sdk/tools/scratchpad/scratchpad_list.rb +0 -117
- data/lib/swarm_sdk/tools/scratchpad/scratchpad_read.rb +0 -97
- data/lib/swarm_sdk/tools/scratchpad/scratchpad_write.rb +0 -108
- data/lib/swarm_sdk/tools/stores/read_tracker.rb +0 -96
- data/lib/swarm_sdk/tools/stores/scratchpad_storage.rb +0 -272
- data/lib/swarm_sdk/tools/stores/storage.rb +0 -142
- data/lib/swarm_sdk/tools/stores/todo_manager.rb +0 -65
- data/lib/swarm_sdk/tools/think.rb +0 -98
- data/lib/swarm_sdk/tools/todo_write.rb +0 -235
- data/lib/swarm_sdk/tools/web_fetch.rb +0 -262
- data/lib/swarm_sdk/tools/write.rb +0 -112
- data/lib/swarm_sdk/utils.rb +0 -68
- data/lib/swarm_sdk/validation_result.rb +0 -33
- data/lib/swarm_sdk/version.rb +0 -5
- data/lib/swarm_sdk/workflow/agent_config.rb +0 -79
- data/lib/swarm_sdk/workflow/builder.rb +0 -143
- data/lib/swarm_sdk/workflow/executor.rb +0 -497
- data/lib/swarm_sdk/workflow/node_builder.rb +0 -555
- data/lib/swarm_sdk/workflow/transformer_executor.rb +0 -249
- data/lib/swarm_sdk/workflow.rb +0 -554
- data/lib/swarm_sdk.rb +0 -524
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module SwarmSDK
|
|
4
|
-
# LogCollector manages subscriber callbacks for log events with filtering support.
|
|
5
|
-
#
|
|
6
|
-
# This module acts as an emitter implementation that forwards events
|
|
7
|
-
# to user-registered callbacks. It's designed to be set as the LogStream
|
|
8
|
-
# emitter during swarm execution.
|
|
9
|
-
#
|
|
10
|
-
# ## Features
|
|
11
|
-
#
|
|
12
|
-
# - **Filtered Subscriptions**: Subscribe to specific agents, event types, or swarm IDs
|
|
13
|
-
# - **Unsubscribe Support**: Remove subscriptions by ID to prevent memory leaks
|
|
14
|
-
# - **Error Isolation**: One subscriber's error doesn't break others
|
|
15
|
-
# - **Thread Safety**: Fiber-local storage for multi-threaded environments
|
|
16
|
-
#
|
|
17
|
-
# ## Thread Safety for Multi-Threaded Environments (Puma, Sidekiq)
|
|
18
|
-
#
|
|
19
|
-
# Subscriptions are stored in Fiber-local storage (Fiber[:log_subscriptions]) instead
|
|
20
|
-
# of class instance variables. This ensures callbacks registered in the parent
|
|
21
|
-
# thread/fiber are accessible to child fibers created by Async reactor.
|
|
22
|
-
#
|
|
23
|
-
# Why: In Puma/Sidekiq, class instance variables (@subscriptions) are thread-isolated
|
|
24
|
-
# and don't properly propagate to child fibers. Using Fiber-local storage ensures
|
|
25
|
-
# events emitted from within Async blocks can reach registered subscriptions.
|
|
26
|
-
#
|
|
27
|
-
# Child fibers inherit parent fiber-local storage automatically, so events
|
|
28
|
-
# emitted from agent callbacks (on_tool_call, on_end_message, etc.) executing
|
|
29
|
-
# in child fibers can still reach the parent's registered subscriptions.
|
|
30
|
-
#
|
|
31
|
-
# ## Usage
|
|
32
|
-
#
|
|
33
|
-
# # Subscribe to all events
|
|
34
|
-
# sub_id = LogCollector.subscribe { |event| puts event }
|
|
35
|
-
#
|
|
36
|
-
# # Subscribe to specific agent
|
|
37
|
-
# sub_id = LogCollector.subscribe(filter: { agent: :backend }) { |event|
|
|
38
|
-
# puts "Backend: #{event}"
|
|
39
|
-
# }
|
|
40
|
-
#
|
|
41
|
-
# # Subscribe to specific event types
|
|
42
|
-
# sub_id = LogCollector.subscribe(filter: { type: ["tool_call", "tool_result"] }) { |event|
|
|
43
|
-
# log_tool_activity(event)
|
|
44
|
-
# }
|
|
45
|
-
#
|
|
46
|
-
# # Subscribe with regex matching
|
|
47
|
-
# sub_id = LogCollector.subscribe(filter: { type: /^tool_/ }) { |event|
|
|
48
|
-
# track_tool_usage(event)
|
|
49
|
-
# }
|
|
50
|
-
#
|
|
51
|
-
# # Unsubscribe when done
|
|
52
|
-
# LogCollector.unsubscribe(sub_id)
|
|
53
|
-
#
|
|
54
|
-
# # After execution, reset for next use
|
|
55
|
-
# LogCollector.reset!
|
|
56
|
-
#
|
|
57
|
-
module LogCollector
|
|
58
|
-
# Subscription object with filtering capabilities
|
|
59
|
-
#
|
|
60
|
-
# Encapsulates a callback with optional filters. Filters can match
|
|
61
|
-
# against agent name, event type, swarm_id, or any event field.
|
|
62
|
-
class Subscription
|
|
63
|
-
attr_reader :id, :filter, :callback
|
|
64
|
-
|
|
65
|
-
# Initialize a subscription
|
|
66
|
-
#
|
|
67
|
-
# @param filter [Hash] Filter criteria
|
|
68
|
-
# @param callback [Proc] Block to call when event matches
|
|
69
|
-
def initialize(filter: {}, &callback)
|
|
70
|
-
@id = SecureRandom.uuid
|
|
71
|
-
@filter = normalize_filter(filter)
|
|
72
|
-
@callback = callback
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
# Check if event matches filter criteria
|
|
76
|
-
#
|
|
77
|
-
# Empty filter matches all events. Multiple filter keys are AND'd together.
|
|
78
|
-
#
|
|
79
|
-
# @param event [Hash] Event entry with :type, :agent, etc.
|
|
80
|
-
# @return [Boolean] True if event matches filter
|
|
81
|
-
def matches?(event)
|
|
82
|
-
return true if @filter.empty?
|
|
83
|
-
|
|
84
|
-
@filter.all? do |key, matcher|
|
|
85
|
-
value = event[key]
|
|
86
|
-
case matcher
|
|
87
|
-
when Array
|
|
88
|
-
# Match if value is in array (handles symbols/strings)
|
|
89
|
-
matcher.include?(value) || matcher.map(&:to_s).include?(value.to_s)
|
|
90
|
-
when Regexp
|
|
91
|
-
# Regex matching
|
|
92
|
-
value.to_s.match?(matcher)
|
|
93
|
-
when Proc
|
|
94
|
-
# Custom matcher
|
|
95
|
-
matcher.call(value)
|
|
96
|
-
else
|
|
97
|
-
# Exact match (handles symbols/strings)
|
|
98
|
-
matcher == value || matcher.to_s == value.to_s
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
private
|
|
104
|
-
|
|
105
|
-
# Normalize filter keys to symbols for consistent matching
|
|
106
|
-
#
|
|
107
|
-
# @param filter [Hash] Raw filter
|
|
108
|
-
# @return [Hash] Normalized filter with symbol keys
|
|
109
|
-
def normalize_filter(filter)
|
|
110
|
-
filter.transform_keys(&:to_sym)
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
class << self
|
|
115
|
-
# Subscribe to log events with optional filtering
|
|
116
|
-
#
|
|
117
|
-
# Registers a callback that will receive events matching the filter criteria.
|
|
118
|
-
# Returns a subscription ID that can be used to unsubscribe later.
|
|
119
|
-
#
|
|
120
|
-
# @param filter [Hash] Filter criteria (empty = all events)
|
|
121
|
-
# - :agent [Symbol, String, Array, Regexp] Agent name(s) to observe
|
|
122
|
-
# - :type [String, Array, Regexp] Event type(s) to receive
|
|
123
|
-
# - :swarm_id [String] Specific swarm instance
|
|
124
|
-
# - Any other key matches against event fields
|
|
125
|
-
# @yield [Hash] Log event entry
|
|
126
|
-
# @return [String] Subscription ID for unsubscribe
|
|
127
|
-
#
|
|
128
|
-
# @example Subscribe to all events
|
|
129
|
-
# LogCollector.subscribe { |event| puts event }
|
|
130
|
-
#
|
|
131
|
-
# @example Subscribe to specific agent's tool calls
|
|
132
|
-
# sub_id = LogCollector.subscribe(
|
|
133
|
-
# filter: { agent: :backend, type: /^tool_/ }
|
|
134
|
-
# ) do |event|
|
|
135
|
-
# puts "Backend used tool: #{event[:tool]}"
|
|
136
|
-
# end
|
|
137
|
-
#
|
|
138
|
-
# @example Subscribe to multiple agents
|
|
139
|
-
# LogCollector.subscribe(
|
|
140
|
-
# filter: { agent: [:backend, :frontend], type: "agent_stop" }
|
|
141
|
-
# ) { |e| record_completion(e) }
|
|
142
|
-
def subscribe(filter: {}, &block)
|
|
143
|
-
subscription = Subscription.new(filter: filter, &block)
|
|
144
|
-
subscriptions << subscription
|
|
145
|
-
subscription.id
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
# Unsubscribe by ID
|
|
149
|
-
#
|
|
150
|
-
# Removes a subscription to prevent memory leaks and stop receiving events.
|
|
151
|
-
#
|
|
152
|
-
# @param subscription_id [String] ID returned from subscribe
|
|
153
|
-
# @return [Subscription, nil] Removed subscription or nil if not found
|
|
154
|
-
def unsubscribe(subscription_id)
|
|
155
|
-
index = subscriptions.find_index { |s| s.id == subscription_id }
|
|
156
|
-
return unless index
|
|
157
|
-
|
|
158
|
-
subscriptions.delete_at(index)
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
# Clear all subscriptions
|
|
162
|
-
#
|
|
163
|
-
# Removes all subscriptions. Useful for testing or execution cleanup.
|
|
164
|
-
#
|
|
165
|
-
# @return [void]
|
|
166
|
-
def clear_subscriptions
|
|
167
|
-
subscriptions.clear
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
# Get current subscription count
|
|
171
|
-
#
|
|
172
|
-
# @return [Integer] Number of active subscriptions
|
|
173
|
-
def subscription_count
|
|
174
|
-
subscriptions.size
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
# Emit an event to all matching subscribers
|
|
178
|
-
#
|
|
179
|
-
# Automatically adds a timestamp if one doesn't exist.
|
|
180
|
-
# Errors in individual subscribers are isolated - one bad subscriber
|
|
181
|
-
# won't prevent others from receiving events.
|
|
182
|
-
#
|
|
183
|
-
# @param entry [Hash] Log event entry
|
|
184
|
-
# @return [void]
|
|
185
|
-
def emit(entry)
|
|
186
|
-
entry_with_timestamp = ensure_timestamp(entry)
|
|
187
|
-
|
|
188
|
-
subscriptions.each do |subscription|
|
|
189
|
-
next unless subscription.matches?(entry_with_timestamp)
|
|
190
|
-
|
|
191
|
-
begin
|
|
192
|
-
subscription.callback.call(entry_with_timestamp)
|
|
193
|
-
rescue StandardError => e
|
|
194
|
-
# Error isolation - don't let one subscriber break others
|
|
195
|
-
RubyLLM.logger.error("SwarmSDK: Subscription #{subscription.id} error: #{e.message}")
|
|
196
|
-
end
|
|
197
|
-
end
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
# Reset the collector (clears subscriptions for next execution)
|
|
201
|
-
#
|
|
202
|
-
# @return [void]
|
|
203
|
-
def reset!
|
|
204
|
-
Fiber[:log_subscriptions] = []
|
|
205
|
-
end
|
|
206
|
-
|
|
207
|
-
private
|
|
208
|
-
|
|
209
|
-
# Get subscriptions from Fiber-local storage
|
|
210
|
-
#
|
|
211
|
-
# @return [Array<Subscription>] Current subscriptions
|
|
212
|
-
def subscriptions
|
|
213
|
-
Fiber[:log_subscriptions] ||= []
|
|
214
|
-
end
|
|
215
|
-
|
|
216
|
-
# Ensure event has a timestamp
|
|
217
|
-
#
|
|
218
|
-
# @param entry [Hash] Event entry
|
|
219
|
-
# @return [Hash] Entry with timestamp
|
|
220
|
-
def ensure_timestamp(entry)
|
|
221
|
-
return entry if entry.key?(:timestamp)
|
|
222
|
-
|
|
223
|
-
entry.merge(timestamp: Time.now.utc.iso8601(6))
|
|
224
|
-
end
|
|
225
|
-
end
|
|
226
|
-
end
|
|
227
|
-
end
|
data/lib/swarm_sdk/log_stream.rb
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module SwarmSDK
|
|
4
|
-
# LogStream provides a module-level singleton for emitting log events.
|
|
5
|
-
#
|
|
6
|
-
# This allows any component (tools, providers, agents) to emit structured
|
|
7
|
-
# log events without needing references to logger instances.
|
|
8
|
-
#
|
|
9
|
-
# ## Usage
|
|
10
|
-
#
|
|
11
|
-
# # Emit an event from anywhere in the SDK
|
|
12
|
-
# LogStream.emit(
|
|
13
|
-
# type: "user_prompt",
|
|
14
|
-
# agent: :backend,
|
|
15
|
-
# model: "claude-sonnet-4",
|
|
16
|
-
# message_count: 5
|
|
17
|
-
# )
|
|
18
|
-
#
|
|
19
|
-
# ## Thread Safety
|
|
20
|
-
#
|
|
21
|
-
# LogStream is thread-safe and fiber-safe:
|
|
22
|
-
# - Uses Fiber storage for per-request isolation in multi-threaded servers (Puma, Sidekiq)
|
|
23
|
-
# - Each thread/request has its own emitter instance
|
|
24
|
-
# - Child fibers inherit the emitter from their parent fiber
|
|
25
|
-
# - No cross-thread contamination of log events
|
|
26
|
-
#
|
|
27
|
-
# Usage pattern:
|
|
28
|
-
# 1. Set emitter BEFORE starting Async execution
|
|
29
|
-
# 2. During Async execution, only emit() (reads emitter)
|
|
30
|
-
# 3. Each event includes agent context for identification
|
|
31
|
-
#
|
|
32
|
-
# ## Testing
|
|
33
|
-
#
|
|
34
|
-
# # Inject a test emitter
|
|
35
|
-
# LogStream.emitter = TestEmitter.new
|
|
36
|
-
# # ... run tests ...
|
|
37
|
-
# LogStream.reset!
|
|
38
|
-
#
|
|
39
|
-
module LogStream
|
|
40
|
-
class << self
|
|
41
|
-
# Emit a log event
|
|
42
|
-
#
|
|
43
|
-
# Adds timestamp and forwards to the registered emitter.
|
|
44
|
-
# Auto-injects execution_id, swarm_id, and parent_swarm_id from Fiber storage.
|
|
45
|
-
# Explicit values in data override auto-injected ones.
|
|
46
|
-
#
|
|
47
|
-
# @param data [Hash] Event data (type, agent, and event-specific fields)
|
|
48
|
-
# @return [void]
|
|
49
|
-
def emit(**data)
|
|
50
|
-
emitter = Fiber[:log_stream_emitter]
|
|
51
|
-
return unless emitter
|
|
52
|
-
|
|
53
|
-
# Auto-inject execution context from Fiber storage
|
|
54
|
-
# Explicit values in data override auto-injected ones
|
|
55
|
-
auto_injected = {
|
|
56
|
-
execution_id: Fiber[:execution_id],
|
|
57
|
-
swarm_id: Fiber[:swarm_id],
|
|
58
|
-
parent_swarm_id: Fiber[:parent_swarm_id],
|
|
59
|
-
}.compact
|
|
60
|
-
|
|
61
|
-
entry = auto_injected.merge(data).merge(timestamp: Time.now.utc.iso8601(6)).compact
|
|
62
|
-
|
|
63
|
-
emitter.emit(entry)
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
# Set the emitter (for dependency injection in tests)
|
|
67
|
-
#
|
|
68
|
-
# Stores emitter in Fiber storage for thread-safe, per-request isolation.
|
|
69
|
-
#
|
|
70
|
-
# @param emitter [#emit] Object responding to emit(Hash)
|
|
71
|
-
# @return [void]
|
|
72
|
-
def emitter=(emitter)
|
|
73
|
-
Fiber[:log_stream_emitter] = emitter
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
# Get the current emitter
|
|
77
|
-
#
|
|
78
|
-
# @return [#emit, nil] Current emitter or nil if not set
|
|
79
|
-
def emitter
|
|
80
|
-
Fiber[:log_stream_emitter]
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
# Reset the emitter (for test cleanup)
|
|
84
|
-
#
|
|
85
|
-
# @return [void]
|
|
86
|
-
def reset!
|
|
87
|
-
Fiber[:log_stream_emitter] = nil
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
# Check if logging is enabled
|
|
91
|
-
#
|
|
92
|
-
# @return [Boolean] true if an emitter is configured
|
|
93
|
-
def enabled?
|
|
94
|
-
!Fiber[:log_stream_emitter].nil?
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
# Emit an internal error event
|
|
98
|
-
#
|
|
99
|
-
# Provides consistent error event emission for all internal errors.
|
|
100
|
-
# These are errors that occur during execution but are handled gracefully
|
|
101
|
-
# (with fallback behavior) rather than causing failures.
|
|
102
|
-
#
|
|
103
|
-
# @param error [Exception] The caught exception
|
|
104
|
-
# @param source [String] Source module/class (e.g., "hook_triggers", "context_compactor")
|
|
105
|
-
# @param context [String] Specific operation context (e.g., "swarm_stop", "summarization")
|
|
106
|
-
# @param agent [Symbol, String, nil] Agent name if applicable
|
|
107
|
-
# @param metadata [Hash] Additional context data
|
|
108
|
-
# @return [void]
|
|
109
|
-
def emit_error(error, source:, context:, agent: nil, **metadata)
|
|
110
|
-
emit(
|
|
111
|
-
type: "internal_error",
|
|
112
|
-
source: source,
|
|
113
|
-
context: context,
|
|
114
|
-
agent: agent,
|
|
115
|
-
error_class: error.class.name,
|
|
116
|
-
error_message: error.message,
|
|
117
|
-
backtrace: error.backtrace&.first(5),
|
|
118
|
-
**metadata,
|
|
119
|
-
)
|
|
120
|
-
rescue StandardError
|
|
121
|
-
# Absolute fallback - if emit_error itself fails, don't break execution
|
|
122
|
-
# This should never happen, but we must be defensive
|
|
123
|
-
nil
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
end
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module SwarmSDK
|
|
4
|
-
# Parser for agent markdown files with YAML frontmatter
|
|
5
|
-
#
|
|
6
|
-
# Supports two formats:
|
|
7
|
-
# 1. SwarmSDK format - YAML frontmatter with array-based tools
|
|
8
|
-
# 2. Claude Code format - Detected and converted via ClaudeCodeAgentAdapter
|
|
9
|
-
#
|
|
10
|
-
# Format detection is automatic based on frontmatter structure.
|
|
11
|
-
class MarkdownParser
|
|
12
|
-
FRONTMATTER_PATTERN = /\A---\s*\n(.*?)\n---\s*\n(.*)\z/m
|
|
13
|
-
|
|
14
|
-
class << self
|
|
15
|
-
# Parse markdown content into an Agent::Definition
|
|
16
|
-
#
|
|
17
|
-
# Automatically detects format (SwarmSDK or Claude Code) and routes
|
|
18
|
-
# to appropriate parser.
|
|
19
|
-
#
|
|
20
|
-
# @param content [String] Markdown content with YAML frontmatter
|
|
21
|
-
# @param agent_name [Symbol, String, nil] Name of the agent
|
|
22
|
-
# @return [Agent::Definition] Parsed agent definition
|
|
23
|
-
# @raise [ConfigurationError] if format is invalid
|
|
24
|
-
def parse(content, agent_name = nil)
|
|
25
|
-
# Detect Claude Code format and route to adapter
|
|
26
|
-
if ClaudeCodeAgentAdapter.claude_code_format?(content)
|
|
27
|
-
config = ClaudeCodeAgentAdapter.parse(content, agent_name)
|
|
28
|
-
# For Claude Code format, agent_name parameter is required since
|
|
29
|
-
# the 'name' field in frontmatter is Claude Code specific and not used
|
|
30
|
-
unless agent_name
|
|
31
|
-
raise ConfigurationError, "Agent name must be provided when parsing Claude Code format"
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
Agent::Definition.new(agent_name.to_sym, config)
|
|
35
|
-
else
|
|
36
|
-
# Use standard SwarmSDK format parsing
|
|
37
|
-
new(content, agent_name).parse
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def initialize(content, agent_name = nil)
|
|
43
|
-
@content = content
|
|
44
|
-
@agent_name = agent_name
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def parse
|
|
48
|
-
if @content =~ FRONTMATTER_PATTERN
|
|
49
|
-
frontmatter_yaml = Regexp.last_match(1)
|
|
50
|
-
prompt_content = Regexp.last_match(2).strip
|
|
51
|
-
|
|
52
|
-
frontmatter = YAML.safe_load(frontmatter_yaml, permitted_classes: [Symbol], aliases: true)
|
|
53
|
-
|
|
54
|
-
unless frontmatter.is_a?(Hash)
|
|
55
|
-
raise ConfigurationError, "Invalid frontmatter format in agent definition"
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
# Symbolize keys for AgentDefinition
|
|
59
|
-
config = Utils.symbolize_keys(frontmatter).merge(system_prompt: prompt_content)
|
|
60
|
-
|
|
61
|
-
name = @agent_name || frontmatter["name"]
|
|
62
|
-
unless name
|
|
63
|
-
raise ConfigurationError, "Agent definition must include 'name' in frontmatter or be specified externally"
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
# Convert name to symbol
|
|
67
|
-
name = name.to_sym
|
|
68
|
-
|
|
69
|
-
Agent::Definition.new(name, config)
|
|
70
|
-
else
|
|
71
|
-
raise ConfigurationError, "Invalid Markdown agent definition format. Expected YAML frontmatter followed by prompt content."
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
end
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"sonnet": "claude-sonnet-4-5-20250929",
|
|
3
|
-
"opus": "claude-opus-4-1-20250805",
|
|
4
|
-
"haiku": "claude-haiku-4-5-20251001",
|
|
5
|
-
"claude-sonnet-4-5": "claude-sonnet-4-5-20250929",
|
|
6
|
-
"claude-opus-4-1": "claude-opus-4-1-20250805",
|
|
7
|
-
"claude-haiku-4-5": "claude-haiku-4-5-20251001"
|
|
8
|
-
}
|
data/lib/swarm_sdk/models.json
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
[{"name":"Claude Sonnet 4.5","id":"claude-sonnet-4-5-20250929","provider":"anthropic","family":"claude-sonnet-4-5","context_window":200000,"max_output_tokens":64000,"modalities":{"input":["image","text"],"output":["text"]},"capabilities":["function_calling"],"pricing":{"text_tokens":{"standard":{"input_per_million":3.0,"cached_input_per_million":3.75,"output_per_million":15.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"Claude Haiku 4.5","id":"claude-haiku-4-5-20251001","provider":"anthropic","family":"claude-haiku-4-5","context_window":200000,"max_output_tokens":64000,"modalities":{"input":["image","text"],"output":["text"]},"capabilities":["function_calling"],"pricing":{"text_tokens":{"standard":{"input_per_million":1.0,"cached_input_per_million":1.25,"output_per_million":5.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"Claude Opus 4.1","id":"claude-opus-4-1-20250805","provider":"anthropic","family":"claude-opus-4-1","context_window":200000,"max_output_tokens":32000,"modalities":{"input":["image","text"],"output":["text"]},"capabilities":["function_calling"],"pricing":{"text_tokens":{"standard":{"input_per_million":15.0,"cached_input_per_million":18.75,"output_per_million":75.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"Gemini 2.5 Pro","id":"gemini-2.5-pro","provider":"gemini","family":"gemini-2.5-pro","context_window":1048576,"max_output_tokens":65536,"modalities":{"input":["audio","text"],"output":["text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":1.25,"cached_input_per_million":0.125,"output_per_million":10.0},"batch":{"input_per_million":0.625,"output_per_million":5.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"Gemini 2.5 Flash","id":"gemini-2.5-flash","provider":"gemini","family":"gemini-2.5-flash","context_window":1048576,"max_output_tokens":65536,"modalities":{"input":["audio","image","text"],"output":["text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.3,"cached_input_per_million":0.03,"output_per_million":2.5},"batch":{"input_per_million":0.15,"output_per_million":1.25}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"Gemini 2.5 Flash-Lite","id":"gemini-2.5-flash-lite","provider":"gemini","family":"gemini-2.5-flash-lite","context_window":1048576,"max_output_tokens":65536,"modalities":{"input":["audio","image","text"],"output":["text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.3,"cached_input_per_million":0.03,"output_per_million":2.5},"batch":{"input_per_million":0.15,"output_per_million":1.25}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"Gemini 2.0 Flash","id":"gemini-2.0-flash","provider":"gemini","family":"gemini-2.0-flash","context_window":1048576,"max_output_tokens":8192,"modalities":{"input":["audio","image","text"],"output":["text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.1,"cached_input_per_million":0.025,"output_per_million":0.4},"batch":{"input_per_million":0.05,"output_per_million":0.2}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"Gemini 2.0 Flash","id":"gemini-2.0-flash-001","provider":"gemini","family":"gemini-2.0-flash","context_window":1048576,"max_output_tokens":8192,"modalities":{"input":["audio","image","text"],"output":["text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.1,"cached_input_per_million":0.025,"output_per_million":0.4},"batch":{"input_per_million":0.05,"output_per_million":0.2}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"Gemini 2.0 Flash","id":"gemini-2.0-flash-exp","provider":"gemini","family":"gemini-2.0-flash","context_window":1048576,"max_output_tokens":8192,"modalities":{"input":["audio","image","text"],"output":["text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.1,"cached_input_per_million":0.025,"output_per_million":0.4},"batch":{"input_per_million":0.05,"output_per_million":0.2}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"Gemini 2.0 Flash-Lite","id":"gemini-2.0-flash-lite","provider":"gemini","family":"gemini-2.0-flash-lite","context_window":1048576,"max_output_tokens":8192,"modalities":{"input":["audio","image","text"],"output":["text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.1,"cached_input_per_million":0.025,"output_per_million":0.4},"batch":{"input_per_million":0.05,"output_per_million":0.2}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"Gemini 2.0 Flash-Lite","id":"gemini-2.0-flash-lite-001","provider":"gemini","family":"gemini-2.0-flash-lite","context_window":1048576,"max_output_tokens":8192,"modalities":{"input":["audio","image","text"],"output":["text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.1,"cached_input_per_million":0.025,"output_per_million":0.4},"batch":{"input_per_million":0.05,"output_per_million":0.2}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"deepseek-chat","id":"deepseek-chat","provider":"deepseek","family":"deepseek-chat","context_window":128000,"max_output_tokens":8000,"modalities":{"input":["text"],"output":["text"]},"capabilities":["function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.28,"cached_input_per_million":0.028,"output_per_million":0.42},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"deepseek-reasoner","id":"deepseek-reasoner","provider":"deepseek","family":"deepseek-reasoner","context_window":null,"max_output_tokens":64000,"modalities":{"input":["text"],"output":["text"]},"capabilities":["function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":null,"cached_input_per_million":null,"output_per_million":null},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-5","family":"gpt-5","provider":"openai","id":"gpt-5-2025-08-07","context_window":400000,"max_output_tokens":128000,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":1.25,"cached_input_per_million":0.125,"output_per_million":10.0},"batch":{"input_per_million":0.625,"output_per_million":5.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-5","family":"gpt-5","provider":"openai","id":"gpt-5","context_window":400000,"max_output_tokens":128000,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":1.25,"cached_input_per_million":0.125,"output_per_million":10.0},"batch":{"input_per_million":0.625,"output_per_million":5.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-5 mini","family":"gpt-5-mini","provider":"openai","id":"gpt-5-mini-2025-08-07","context_window":400000,"max_output_tokens":128000,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.25,"cached_input_per_million":0.025,"output_per_million":2.0},"batch":{"input_per_million":0.125,"output_per_million":1.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-5 mini","family":"gpt-5-mini","provider":"openai","id":"gpt-5-mini","context_window":400000,"max_output_tokens":128000,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.25,"cached_input_per_million":0.025,"output_per_million":2.0},"batch":{"input_per_million":0.125,"output_per_million":1.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-5 nano","family":"gpt-5-nano","provider":"openai","id":"gpt-5-nano-2025-08-07","context_window":400000,"max_output_tokens":128000,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.05,"cached_input_per_million":0.005,"output_per_million":0.4},"batch":{"input_per_million":0.025,"output_per_million":0.2}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-5 nano","family":"gpt-5-nano","provider":"openai","id":"gpt-5-nano","context_window":400000,"max_output_tokens":128000,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.05,"cached_input_per_million":0.005,"output_per_million":0.4},"batch":{"input_per_million":0.025,"output_per_million":0.2}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-5 pro","family":"gpt-5-pro","provider":"openai","id":"gpt-5-pro-2025-10-06","context_window":400000,"max_output_tokens":272000,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":15.0,"cached_input_per_million":null,"output_per_million":120.0},"batch":{"input_per_million":7.5,"output_per_million":60.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-5 pro","family":"gpt-5-pro","provider":"openai","id":"gpt-5-pro","context_window":400000,"max_output_tokens":272000,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":15.0,"cached_input_per_million":null,"output_per_million":120.0},"batch":{"input_per_million":7.5,"output_per_million":60.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4.1","family":"gpt-4.1","provider":"openai","id":"gpt-4.1-2025-04-14","context_window":1047576,"max_output_tokens":32768,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":2.0,"cached_input_per_million":0.5,"output_per_million":8.0},"batch":{"input_per_million":1.0,"output_per_million":4.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4.1","family":"gpt-4.1","provider":"openai","id":"gpt-4.1","context_window":1047576,"max_output_tokens":32768,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":2.0,"cached_input_per_million":0.5,"output_per_million":8.0},"batch":{"input_per_million":1.0,"output_per_million":4.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"gpt-oss-120b","family":"gpt-oss-120b","provider":"openai","id":"gpt-oss-120b","context_window":131072,"max_output_tokens":131072,"modalities":{"input":["text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":null,"cached_input_per_million":null,"output_per_million":null},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"gpt-oss-20b","family":"gpt-oss-20b","provider":"openai","id":"gpt-oss-20b","context_window":131072,"max_output_tokens":131072,"modalities":{"input":["text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":null,"cached_input_per_million":null,"output_per_million":null},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"Sora 2","family":"sora-2","provider":"openai","id":"sora-2","context_window":null,"max_output_tokens":null,"modalities":{"input":["image","text"],"output":["audio","embeddings"]},"capabilities":[],"pricing":{"text_tokens":{"standard":{"input_per_million":null,"cached_input_per_million":null,"output_per_million":null},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"Sora 2 Pro","family":"sora-2-pro","provider":"openai","id":"sora-2-pro","context_window":null,"max_output_tokens":null,"modalities":{"input":["image","text"],"output":["audio","embeddings"]},"capabilities":[],"pricing":{"text_tokens":{"standard":{"input_per_million":null,"cached_input_per_million":null,"output_per_million":null},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"o3-deep-research","family":"o3-deep-research","provider":"openai","id":"o3-deep-research-2025-06-26","context_window":200000,"max_output_tokens":100000,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch"],"pricing":{"text_tokens":{"standard":{"input_per_million":10.0,"cached_input_per_million":2.5,"output_per_million":40.0},"batch":{"input_per_million":5.0,"output_per_million":20.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"o3-deep-research","family":"o3-deep-research","provider":"openai","id":"o3-deep-research","context_window":200000,"max_output_tokens":100000,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch"],"pricing":{"text_tokens":{"standard":{"input_per_million":10.0,"cached_input_per_million":2.5,"output_per_million":40.0},"batch":{"input_per_million":5.0,"output_per_million":20.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"o4-mini-deep-research","family":"o4-mini-deep-research","provider":"openai","id":"o4-mini-deep-research-2025-06-26","context_window":200000,"max_output_tokens":100000,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch"],"pricing":{"text_tokens":{"standard":{"input_per_million":2.0,"cached_input_per_million":0.5,"output_per_million":8.0},"batch":{"input_per_million":1.0,"output_per_million":4.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"o4-mini-deep-research","family":"o4-mini-deep-research","provider":"openai","id":"o4-mini-deep-research","context_window":200000,"max_output_tokens":100000,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch"],"pricing":{"text_tokens":{"standard":{"input_per_million":2.0,"cached_input_per_million":0.5,"output_per_million":8.0},"batch":{"input_per_million":1.0,"output_per_million":4.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT Image 1","family":"gpt-image-1","provider":"openai","id":"gpt-image-1","context_window":null,"max_output_tokens":null,"modalities":{"input":["image","text"],"output":["embeddings","image"]},"capabilities":[],"pricing":{"text_tokens":{"standard":{"input_per_million":5.0,"cached_input_per_million":1.25,"output_per_million":40.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"gpt-image-1-mini","family":"gpt-image-1-mini","provider":"openai","id":"gpt-image-1-mini","context_window":null,"max_output_tokens":null,"modalities":{"input":["image","text"],"output":["embeddings","image"]},"capabilities":[],"pricing":{"text_tokens":{"standard":{"input_per_million":2.0,"cached_input_per_million":0.2,"output_per_million":8.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"DALL·E 3","family":"dall-e-3","provider":"openai","id":"dall-e-3","context_window":null,"max_output_tokens":null,"modalities":{"input":["text"],"output":["embeddings","image"]},"capabilities":[],"pricing":{"text_tokens":{"standard":{"input_per_million":null,"cached_input_per_million":null,"output_per_million":null},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4o mini TTS","family":"gpt-4o-mini-tts","provider":"openai","id":"gpt-4o-mini-tts","context_window":2000,"max_output_tokens":null,"modalities":{"input":["text"],"output":["audio","embeddings"]},"capabilities":[],"pricing":{"text_tokens":{"standard":{"input_per_million":0.6,"cached_input_per_million":null,"output_per_million":12.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4o Transcribe","family":"gpt-4o-transcribe","provider":"openai","id":"gpt-4o-transcribe","context_window":16000,"max_output_tokens":2000,"modalities":{"input":["audio","text"],"output":["embeddings","text"]},"capabilities":[],"pricing":{"text_tokens":{"standard":{"input_per_million":2.5,"cached_input_per_million":null,"output_per_million":10.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4o mini Transcribe","family":"gpt-4o-mini-transcribe","provider":"openai","id":"gpt-4o-mini-transcribe","context_window":16000,"max_output_tokens":2000,"modalities":{"input":["audio","text"],"output":["embeddings","text"]},"capabilities":[],"pricing":{"text_tokens":{"standard":{"input_per_million":1.25,"cached_input_per_million":null,"output_per_million":5.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"gpt-realtime","family":"gpt-realtime","provider":"openai","id":"gpt-realtime-2025-08-28","context_window":32000,"max_output_tokens":4096,"modalities":{"input":["audio","image","text"],"output":["audio","embeddings","text"]},"capabilities":["function_calling"],"pricing":{"text_tokens":{"standard":{"input_per_million":4.0,"cached_input_per_million":0.5,"output_per_million":16.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"gpt-realtime","family":"gpt-realtime","provider":"openai","id":"gpt-realtime","context_window":32000,"max_output_tokens":4096,"modalities":{"input":["audio","image","text"],"output":["audio","embeddings","text"]},"capabilities":["function_calling"],"pricing":{"text_tokens":{"standard":{"input_per_million":4.0,"cached_input_per_million":0.5,"output_per_million":16.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"gpt-audio","family":"gpt-audio","provider":"openai","id":"gpt-audio-2025-08-28","context_window":128000,"max_output_tokens":16384,"modalities":{"input":["audio","text"],"output":["audio","embeddings","text"]},"capabilities":["function_calling"],"pricing":{"text_tokens":{"standard":{"input_per_million":2.5,"cached_input_per_million":null,"output_per_million":10.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"gpt-audio","family":"gpt-audio","provider":"openai","id":"gpt-audio","context_window":128000,"max_output_tokens":16384,"modalities":{"input":["audio","text"],"output":["audio","embeddings","text"]},"capabilities":["function_calling"],"pricing":{"text_tokens":{"standard":{"input_per_million":2.5,"cached_input_per_million":null,"output_per_million":10.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"gpt-realtime-mini","family":"gpt-realtime-mini","provider":"openai","id":"gpt-realtime-mini-2025-10-06","context_window":32000,"max_output_tokens":4096,"modalities":{"input":["audio","image","text"],"output":["audio","embeddings","text"]},"capabilities":["function_calling"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.6,"cached_input_per_million":0.06,"output_per_million":2.4},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"gpt-realtime-mini","family":"gpt-realtime-mini","provider":"openai","id":"gpt-realtime-mini","context_window":32000,"max_output_tokens":4096,"modalities":{"input":["audio","image","text"],"output":["audio","embeddings","text"]},"capabilities":["function_calling"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.6,"cached_input_per_million":0.06,"output_per_million":2.4},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"gpt-audio-mini","family":"gpt-audio-mini","provider":"openai","id":"gpt-audio-mini-2025-10-06","context_window":128000,"max_output_tokens":16384,"modalities":{"input":["audio","text"],"output":["audio","embeddings","text"]},"capabilities":["function_calling"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.6,"cached_input_per_million":null,"output_per_million":2.4},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"gpt-audio-mini","family":"gpt-audio-mini","provider":"openai","id":"gpt-audio-mini","context_window":128000,"max_output_tokens":16384,"modalities":{"input":["audio","text"],"output":["audio","embeddings","text"]},"capabilities":["function_calling"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.6,"cached_input_per_million":null,"output_per_million":2.4},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-5 Chat","family":"gpt-5-chat-latest","provider":"openai","id":"gpt-5-chat-latest","context_window":128000,"max_output_tokens":16384,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":1.25,"cached_input_per_million":0.125,"output_per_million":10.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"ChatGPT-4o","family":"chatgpt-4o-latest","provider":"openai","id":"chatgpt-4o-latest","context_window":128000,"max_output_tokens":16384,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":[],"pricing":{"text_tokens":{"standard":{"input_per_million":5.0,"cached_input_per_million":null,"output_per_million":15.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-5-Codex","family":"gpt-5-codex","provider":"openai","id":"gpt-5-codex","context_window":400000,"max_output_tokens":128000,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":1.25,"cached_input_per_million":0.125,"output_per_million":10.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"o3-pro","family":"o3-pro","provider":"openai","id":"o3-pro-2025-06-10","context_window":200000,"max_output_tokens":100000,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":20.0,"cached_input_per_million":null,"output_per_million":80.0},"batch":{"input_per_million":10.0,"output_per_million":40.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"o3-pro","family":"o3-pro","provider":"openai","id":"o3-pro","context_window":200000,"max_output_tokens":100000,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":20.0,"cached_input_per_million":null,"output_per_million":80.0},"batch":{"input_per_million":10.0,"output_per_million":40.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"o3","family":"o3","provider":"openai","id":"o3-2025-04-16","context_window":200000,"max_output_tokens":100000,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":2.0,"cached_input_per_million":0.5,"output_per_million":8.0},"batch":{"input_per_million":1.0,"output_per_million":4.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"o3","family":"o3","provider":"openai","id":"o3","context_window":200000,"max_output_tokens":100000,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":2.0,"cached_input_per_million":0.5,"output_per_million":8.0},"batch":{"input_per_million":1.0,"output_per_million":4.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"o4-mini","family":"o4-mini","provider":"openai","id":"o4-mini-2025-04-16","context_window":200000,"max_output_tokens":100000,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":1.1,"cached_input_per_million":0.275,"output_per_million":4.4},"batch":{"input_per_million":0.55,"output_per_million":2.2}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"o4-mini","family":"o4-mini","provider":"openai","id":"o4-mini","context_window":200000,"max_output_tokens":100000,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":1.1,"cached_input_per_million":0.275,"output_per_million":4.4},"batch":{"input_per_million":0.55,"output_per_million":2.2}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4.1 mini","family":"gpt-4.1-mini","provider":"openai","id":"gpt-4.1-mini-2025-04-14","context_window":1047576,"max_output_tokens":32768,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.4,"cached_input_per_million":0.1,"output_per_million":1.6},"batch":{"input_per_million":0.2,"output_per_million":0.8}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4.1 mini","family":"gpt-4.1-mini","provider":"openai","id":"gpt-4.1-mini","context_window":1047576,"max_output_tokens":32768,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.4,"cached_input_per_million":0.1,"output_per_million":1.6},"batch":{"input_per_million":0.2,"output_per_million":0.8}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4.1 nano","family":"gpt-4.1-nano","provider":"openai","id":"gpt-4.1-nano-2025-04-14","context_window":1047576,"max_output_tokens":32768,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.1,"cached_input_per_million":0.025,"output_per_million":0.4},"batch":{"input_per_million":0.05,"output_per_million":0.2}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4.1 nano","family":"gpt-4.1-nano","provider":"openai","id":"gpt-4.1-nano","context_window":1047576,"max_output_tokens":32768,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.1,"cached_input_per_million":0.025,"output_per_million":0.4},"batch":{"input_per_million":0.05,"output_per_million":0.2}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"o1-pro","family":"o1-pro","provider":"openai","id":"o1-pro-2025-03-19","context_window":200000,"max_output_tokens":100000,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":150.0,"cached_input_per_million":null,"output_per_million":600.0},"batch":{"input_per_million":75.0,"output_per_million":300.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"o1-pro","family":"o1-pro","provider":"openai","id":"o1-pro","context_window":200000,"max_output_tokens":100000,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":150.0,"cached_input_per_million":null,"output_per_million":600.0},"batch":{"input_per_million":75.0,"output_per_million":300.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"computer-use-preview","family":"computer-use-preview","provider":"openai","id":"computer-use-preview-2025-03-11","context_window":8192,"max_output_tokens":1024,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling"],"pricing":{"text_tokens":{"standard":{"input_per_million":3.0,"cached_input_per_million":null,"output_per_million":12.0},"batch":{"input_per_million":1.5,"output_per_million":6.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"computer-use-preview","family":"computer-use-preview","provider":"openai","id":"computer-use-preview","context_window":8192,"max_output_tokens":1024,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling"],"pricing":{"text_tokens":{"standard":{"input_per_million":3.0,"cached_input_per_million":null,"output_per_million":12.0},"batch":{"input_per_million":1.5,"output_per_million":6.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4o mini Search Preview","family":"gpt-4o-mini-search-preview","provider":"openai","id":"gpt-4o-mini-search-preview-2025-03-11","context_window":128000,"max_output_tokens":16384,"modalities":{"input":["text"],"output":["embeddings","text"]},"capabilities":["structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.15,"cached_input_per_million":null,"output_per_million":0.6},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4o mini Search Preview","family":"gpt-4o-mini-search-preview","provider":"openai","id":"gpt-4o-mini-search-preview","context_window":128000,"max_output_tokens":16384,"modalities":{"input":["text"],"output":["embeddings","text"]},"capabilities":["structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.15,"cached_input_per_million":null,"output_per_million":0.6},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4o Search Preview","family":"gpt-4o-search-preview","provider":"openai","id":"gpt-4o-search-preview-2025-03-11","context_window":128000,"max_output_tokens":16384,"modalities":{"input":["text"],"output":["embeddings","text"]},"capabilities":["structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":2.5,"cached_input_per_million":null,"output_per_million":10.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4o Search Preview","family":"gpt-4o-search-preview","provider":"openai","id":"gpt-4o-search-preview","context_window":128000,"max_output_tokens":16384,"modalities":{"input":["text"],"output":["embeddings","text"]},"capabilities":["structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":2.5,"cached_input_per_million":null,"output_per_million":10.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4.5 Preview (Deprecated)","family":"gpt-4.5-preview","provider":"openai","id":"gpt-4.5-preview-2025-02-27","context_window":128000,"max_output_tokens":16384,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":75.0,"cached_input_per_million":37.5,"output_per_million":150.0},"batch":{"input_per_million":37.5,"output_per_million":75.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4.5 Preview (Deprecated)","family":"gpt-4.5-preview","provider":"openai","id":"gpt-4.5-preview","context_window":128000,"max_output_tokens":16384,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":75.0,"cached_input_per_million":37.5,"output_per_million":150.0},"batch":{"input_per_million":37.5,"output_per_million":75.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"o3-mini","family":"o3-mini","provider":"openai","id":"o3-mini-2025-01-31","context_window":200000,"max_output_tokens":100000,"modalities":{"input":["text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":1.1,"cached_input_per_million":0.55,"output_per_million":4.4},"batch":{"input_per_million":0.55,"output_per_million":2.2}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"o3-mini","family":"o3-mini","provider":"openai","id":"o3-mini","context_window":200000,"max_output_tokens":100000,"modalities":{"input":["text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":1.1,"cached_input_per_million":0.55,"output_per_million":4.4},"batch":{"input_per_million":0.55,"output_per_million":2.2}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4o mini Audio","family":"gpt-4o-mini-audio-preview","provider":"openai","id":"gpt-4o-mini-audio-preview-2024-12-17","context_window":128000,"max_output_tokens":16384,"modalities":{"input":["audio","text"],"output":["audio","embeddings","text"]},"capabilities":["function_calling"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.15,"cached_input_per_million":null,"output_per_million":0.6},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4o mini Audio","family":"gpt-4o-mini-audio-preview","provider":"openai","id":"gpt-4o-mini-audio-preview","context_window":128000,"max_output_tokens":16384,"modalities":{"input":["audio","text"],"output":["audio","embeddings","text"]},"capabilities":["function_calling"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.15,"cached_input_per_million":null,"output_per_million":0.6},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4o mini Realtime","family":"gpt-4o-mini-realtime-preview","provider":"openai","id":"gpt-4o-mini-realtime-preview-2024-12-17","context_window":16000,"max_output_tokens":4096,"modalities":{"input":["audio","text"],"output":["audio","embeddings","text"]},"capabilities":["function_calling"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.6,"cached_input_per_million":0.3,"output_per_million":2.4},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4o mini Realtime","family":"gpt-4o-mini-realtime-preview","provider":"openai","id":"gpt-4o-mini-realtime-preview","context_window":16000,"max_output_tokens":4096,"modalities":{"input":["audio","text"],"output":["audio","embeddings","text"]},"capabilities":["function_calling"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.6,"cached_input_per_million":0.3,"output_per_million":2.4},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"o1","family":"o1","provider":"openai","id":"o1-2024-12-17","context_window":200000,"max_output_tokens":100000,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":15.0,"cached_input_per_million":7.5,"output_per_million":60.0},"batch":{"input_per_million":7.5,"output_per_million":30.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"o1","family":"o1","provider":"openai","id":"o1","context_window":200000,"max_output_tokens":100000,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":15.0,"cached_input_per_million":7.5,"output_per_million":60.0},"batch":{"input_per_million":7.5,"output_per_million":30.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"omni-moderation","family":"omni-moderation-latest","provider":"openai","id":"omni-moderation-latest","context_window":null,"max_output_tokens":null,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":[],"pricing":{"text_tokens":{"standard":{"input_per_million":0.0,"cached_input_per_million":null,"output_per_million":null},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"o1-mini","family":"o1-mini","provider":"openai","id":"o1-mini-2024-09-12","context_window":128000,"max_output_tokens":65536,"modalities":{"input":["text"],"output":["embeddings","text"]},"capabilities":[],"pricing":{"text_tokens":{"standard":{"input_per_million":1.1,"cached_input_per_million":0.55,"output_per_million":4.4},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"o1-mini","family":"o1-mini","provider":"openai","id":"o1-mini","context_window":128000,"max_output_tokens":65536,"modalities":{"input":["text"],"output":["embeddings","text"]},"capabilities":[],"pricing":{"text_tokens":{"standard":{"input_per_million":1.1,"cached_input_per_million":0.55,"output_per_million":4.4},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"o1 Preview","family":"o1-preview","provider":"openai","id":"o1-preview-2024-09-12","context_window":128000,"max_output_tokens":32768,"modalities":{"input":["text"],"output":["embeddings","text"]},"capabilities":["function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":15.0,"cached_input_per_million":7.5,"output_per_million":60.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"o1 Preview","family":"o1-preview","provider":"openai","id":"o1-preview","context_window":128000,"max_output_tokens":32768,"modalities":{"input":["text"],"output":["embeddings","text"]},"capabilities":["function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":15.0,"cached_input_per_million":7.5,"output_per_million":60.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4o","family":"gpt-4o","provider":"openai","id":"gpt-4o-2024-08-06","context_window":128000,"max_output_tokens":16384,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":2.5,"cached_input_per_million":1.25,"output_per_million":10.0},"batch":{"input_per_million":1.25,"output_per_million":5.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4o","family":"gpt-4o","provider":"openai","id":"gpt-4o","context_window":128000,"max_output_tokens":16384,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":2.5,"cached_input_per_million":1.25,"output_per_million":10.0},"batch":{"input_per_million":1.25,"output_per_million":5.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4o Audio","family":"gpt-4o-audio-preview","provider":"openai","id":"gpt-4o-audio-preview","context_window":128000,"max_output_tokens":16384,"modalities":{"input":["audio","text"],"output":["audio","embeddings","text"]},"capabilities":["function_calling"],"pricing":{"text_tokens":{"standard":{"input_per_million":2.5,"cached_input_per_million":null,"output_per_million":10.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4o mini","family":"gpt-4o-mini","provider":"openai","id":"gpt-4o-mini-2024-07-18","context_window":128000,"max_output_tokens":16384,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.15,"cached_input_per_million":0.075,"output_per_million":0.6},"batch":{"input_per_million":0.075,"output_per_million":0.3}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4o mini","family":"gpt-4o-mini","provider":"openai","id":"gpt-4o-mini","context_window":128000,"max_output_tokens":16384,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.15,"cached_input_per_million":0.075,"output_per_million":0.6},"batch":{"input_per_million":0.075,"output_per_million":0.3}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4o Realtime","family":"gpt-4o-realtime-preview","provider":"openai","id":"gpt-4o-realtime-preview","context_window":32000,"max_output_tokens":4096,"modalities":{"input":["audio","text"],"output":["audio","embeddings","text"]},"capabilities":["function_calling"],"pricing":{"text_tokens":{"standard":{"input_per_million":5.0,"cached_input_per_million":2.5,"output_per_million":20.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4 Turbo","family":"gpt-4-turbo","provider":"openai","id":"gpt-4-turbo-2024-04-09","context_window":128000,"max_output_tokens":4096,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling"],"pricing":{"text_tokens":{"standard":{"input_per_million":10.0,"cached_input_per_million":null,"output_per_million":30.0},"batch":{"input_per_million":5.0,"output_per_million":15.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4 Turbo","family":"gpt-4-turbo","provider":"openai","id":"gpt-4-turbo","context_window":128000,"max_output_tokens":4096,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["batch","function_calling"],"pricing":{"text_tokens":{"standard":{"input_per_million":10.0,"cached_input_per_million":null,"output_per_million":30.0},"batch":{"input_per_million":5.0,"output_per_million":15.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"babbage-002","family":"babbage-002","provider":"openai","id":"babbage-002","context_window":null,"max_output_tokens":16384,"modalities":{"input":["text"],"output":["embeddings","text"]},"capabilities":[],"pricing":{"text_tokens":{"standard":{"input_per_million":0.4,"cached_input_per_million":null,"output_per_million":0.4},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"codex-mini-latest","family":"codex-mini-latest","provider":"openai","id":"codex-mini-latest","context_window":200000,"max_output_tokens":100000,"modalities":{"input":["image","text"],"output":["embeddings","text"]},"capabilities":["function_calling","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":1.5,"cached_input_per_million":0.375,"output_per_million":6.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"DALL·E 2","family":"dall-e-2","provider":"openai","id":"dall-e-2","context_window":null,"max_output_tokens":null,"modalities":{"input":["text"],"output":["embeddings","image"]},"capabilities":[],"pricing":{"text_tokens":{"standard":{"input_per_million":null,"cached_input_per_million":null,"output_per_million":null},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"davinci-002","family":"davinci-002","provider":"openai","id":"davinci-002","context_window":null,"max_output_tokens":16384,"modalities":{"input":["text"],"output":["embeddings","text"]},"capabilities":[],"pricing":{"text_tokens":{"standard":{"input_per_million":2.0,"cached_input_per_million":null,"output_per_million":2.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-3.5 Turbo","family":"gpt-3.5-turbo","provider":"openai","id":"gpt-3.5-turbo","context_window":16385,"max_output_tokens":4096,"modalities":{"input":["text"],"output":["embeddings","text"]},"capabilities":["batch"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.5,"cached_input_per_million":null,"output_per_million":1.5},"batch":{"input_per_million":0.25,"output_per_million":0.75}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4","family":"gpt-4","provider":"openai","id":"gpt-4-0613","context_window":8192,"max_output_tokens":8192,"modalities":{"input":["text"],"output":["embeddings","text"]},"capabilities":["batch"],"pricing":{"text_tokens":{"standard":{"input_per_million":30.0,"cached_input_per_million":null,"output_per_million":60.0},"batch":{"input_per_million":15.0,"output_per_million":30.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4","family":"gpt-4","provider":"openai","id":"gpt-4","context_window":8192,"max_output_tokens":8192,"modalities":{"input":["text"],"output":["embeddings","text"]},"capabilities":["batch"],"pricing":{"text_tokens":{"standard":{"input_per_million":30.0,"cached_input_per_million":null,"output_per_million":60.0},"batch":{"input_per_million":15.0,"output_per_million":30.0}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"GPT-4 Turbo Preview","family":"gpt-4-turbo-preview","provider":"openai","id":"gpt-4-turbo-preview","context_window":128000,"max_output_tokens":4096,"modalities":{"input":["text"],"output":["embeddings","text"]},"capabilities":[],"pricing":{"text_tokens":{"standard":{"input_per_million":10.0,"cached_input_per_million":null,"output_per_million":30.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"gpt-4o-transcribe-diarize","family":"gpt-4o-transcribe-diarize","provider":"openai","id":"gpt-4o-transcribe-diarize","context_window":16000,"max_output_tokens":2000,"modalities":{"input":["audio","text"],"output":["embeddings","text"]},"capabilities":[],"pricing":{"text_tokens":{"standard":{"input_per_million":2.5,"cached_input_per_million":null,"output_per_million":10.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"text-embedding-3-large","family":"text-embedding-3-large","provider":"openai","id":"text-embedding-3-large","context_window":null,"max_output_tokens":null,"modalities":{"input":["text"],"output":["embeddings","text"]},"capabilities":["batch"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.13,"cached_input_per_million":null,"output_per_million":null},"batch":{"input_per_million":0.065,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":0.13},"batch":{"input_per_million":0.065}}}},{"name":"text-embedding-3-small","family":"text-embedding-3-small","provider":"openai","id":"text-embedding-3-small","context_window":null,"max_output_tokens":null,"modalities":{"input":["text"],"output":["embeddings","text"]},"capabilities":["batch","structured_output"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.02,"cached_input_per_million":null,"output_per_million":null},"batch":{"input_per_million":0.01,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":0.02},"batch":{"input_per_million":0.01}}}},{"name":"text-embedding-ada-002","family":"text-embedding-ada-002","provider":"openai","id":"text-embedding-ada-002","context_window":null,"max_output_tokens":null,"modalities":{"input":["text"],"output":["embeddings","text"]},"capabilities":["batch"],"pricing":{"text_tokens":{"standard":{"input_per_million":0.1,"cached_input_per_million":null,"output_per_million":null},"batch":{"input_per_million":0.05,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":0.1},"batch":{"input_per_million":0.05}}}},{"name":"text-moderation","family":"text-moderation-latest","provider":"openai","id":"text-moderation-latest","context_window":null,"max_output_tokens":32768,"modalities":{"input":["text"],"output":["embeddings","text"]},"capabilities":[],"pricing":{"text_tokens":{"standard":{"input_per_million":0.0,"cached_input_per_million":null,"output_per_million":0.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"text-moderation-stable","family":"text-moderation-stable","provider":"openai","id":"text-moderation-stable","context_window":null,"max_output_tokens":32768,"modalities":{"input":["text"],"output":["embeddings","text"]},"capabilities":[],"pricing":{"text_tokens":{"standard":{"input_per_million":0.0,"cached_input_per_million":null,"output_per_million":0.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"TTS-1","family":"tts-1","provider":"openai","id":"tts-1","context_window":null,"max_output_tokens":null,"modalities":{"input":["text"],"output":["audio","embeddings"]},"capabilities":[],"pricing":{"text_tokens":{"standard":{"input_per_million":15.0,"cached_input_per_million":null,"output_per_million":null},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"TTS-1 HD","family":"tts-1-hd","provider":"openai","id":"tts-1-hd","context_window":null,"max_output_tokens":null,"modalities":{"input":["text"],"output":["audio","embeddings"]},"capabilities":[],"pricing":{"text_tokens":{"standard":{"input_per_million":null,"cached_input_per_million":null,"output_per_million":30.0},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}},{"name":"Whisper","family":"whisper-1","provider":"openai","id":"whisper-1","context_window":null,"max_output_tokens":null,"modalities":{"input":["audio"],"output":["audio","embeddings","text"]},"capabilities":[],"pricing":{"text_tokens":{"standard":{"input_per_million":0.006,"cached_input_per_million":null,"output_per_million":null},"batch":{"input_per_million":null,"output_per_million":null}},"embeddings":{"standard":{"input_per_million":null},"batch":{"input_per_million":null}}}}]
|