robot_lab 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +1 -1
- data/lib/robot_lab/mcp/transports/streamable_http.rb +1 -1
- data/lib/robot_lab/version.rb +1 -1
- metadata +3 -253
- data/.architecture/AGENTS.md +0 -32
- data/.architecture/config.yml +0 -8
- data/.architecture/members.yml +0 -60
- data/.architecture/reviews/feature-free-will.md +0 -490
- data/.architecture/reviews/overall-codebase.md +0 -427
- data/.claude/settings.local.json +0 -57
- data/.codex/config.toml +0 -2
- data/.envrc +0 -6
- data/.github/workflows/deploy-github-pages.yml +0 -52
- data/.irbrc +0 -6
- data/.loki +0 -65
- data/.quality/reek_baseline.txt +0 -43
- data/.rubocop.yml +0 -10
- data/Archspec.rb +0 -44
- data/CLAUDE.md +0 -141
- data/COMMITS.md +0 -196
- data/Rakefile +0 -193
- data/_typos.toml +0 -21
- data/agent2agent_review.md +0 -192
- data/agentf_improvements.md +0 -253
- data/agents.md +0 -14
- data/docs/api/core/index.md +0 -147
- data/docs/api/core/memory.md +0 -578
- data/docs/api/core/network.md +0 -553
- data/docs/api/core/result.md +0 -211
- data/docs/api/core/robot.md +0 -1667
- data/docs/api/core/state.md +0 -145
- data/docs/api/core/tool.md +0 -520
- data/docs/api/errors.md +0 -323
- data/docs/api/hooks.md +0 -469
- data/docs/api/index.md +0 -137
- data/docs/api/mcp/client.md +0 -387
- data/docs/api/mcp/index.md +0 -267
- data/docs/api/mcp/server.md +0 -252
- data/docs/api/mcp/transports.md +0 -339
- data/docs/api/messages/index.md +0 -126
- data/docs/api/messages/text-message.md +0 -170
- data/docs/api/messages/tool-call-message.md +0 -206
- data/docs/api/messages/tool-result-message.md +0 -242
- data/docs/api/messages/user-message.md +0 -232
- data/docs/api/skills.md +0 -423
- data/docs/api/streaming/context.md +0 -280
- data/docs/api/streaming/events.md +0 -185
- data/docs/api/streaming/index.md +0 -156
- data/docs/api/support.md +0 -846
- data/docs/architecture/core-concepts.md +0 -575
- data/docs/architecture/index.md +0 -252
- data/docs/architecture/message-flow.md +0 -366
- data/docs/architecture/network-orchestration.md +0 -478
- data/docs/architecture/robot-execution.md +0 -396
- data/docs/architecture/state-management.md +0 -410
- data/docs/assets/css/custom.css +0 -56
- data/docs/assets/images/robot_lab.jpg +0 -0
- data/docs/concepts.md +0 -641
- data/docs/examples/basic-chat.md +0 -258
- data/docs/examples/index.md +0 -425
- data/docs/examples/mcp-server.md +0 -403
- data/docs/examples/multi-robot-network.md +0 -476
- data/docs/examples/tool-usage.md +0 -468
- data/docs/getting-started/configuration.md +0 -645
- data/docs/getting-started/index.md +0 -56
- data/docs/getting-started/installation.md +0 -197
- data/docs/getting-started/quick-start.md +0 -293
- data/docs/guides/building-robots.md +0 -1187
- data/docs/guides/creating-networks.md +0 -736
- data/docs/guides/hooks.md +0 -1206
- data/docs/guides/index.md +0 -78
- data/docs/guides/knowledge.md +0 -219
- data/docs/guides/mcp-integration.md +0 -740
- data/docs/guides/memory.md +0 -458
- data/docs/guides/observability.md +0 -733
- data/docs/guides/streaming.md +0 -323
- data/docs/guides/using-tools.md +0 -780
- data/docs/index.md +0 -280
- data/docs/superpowers/plans/2026-05-06-agentskills.md +0 -1303
- data/docs/superpowers/specs/2026-05-06-agentskills-design.md +0 -247
- data/examples/.envrc +0 -3
- data/examples/01_simple_robot.rb +0 -31
- data/examples/02_tools.rb +0 -109
- data/examples/03_network.rb +0 -118
- data/examples/04_mcp.rb +0 -217
- data/examples/05_streaming.rb +0 -137
- data/examples/06_prompt_templates.rb +0 -325
- data/examples/07_network_memory.rb +0 -313
- data/examples/08_llm_config.rb +0 -162
- data/examples/09_chaining.rb +0 -251
- data/examples/10_memory.rb +0 -315
- data/examples/11_network_introspection.rb +0 -239
- data/examples/12_message_bus.rb +0 -67
- data/examples/13_spawn.rb +0 -85
- data/examples/14_rusty_circuit/.envrc +0 -1
- data/examples/14_rusty_circuit/.gitignore +0 -1
- data/examples/14_rusty_circuit/README.md +0 -1
- data/examples/14_rusty_circuit/comic.rb +0 -149
- data/examples/14_rusty_circuit/display.rb +0 -217
- data/examples/14_rusty_circuit/heckler.rb +0 -65
- data/examples/14_rusty_circuit/open_mic.rb +0 -132
- data/examples/14_rusty_circuit/prompts/open_mic_comic.md +0 -20
- data/examples/14_rusty_circuit/prompts/open_mic_heckler.md +0 -23
- data/examples/14_rusty_circuit/prompts/open_mic_scout.md +0 -20
- data/examples/14_rusty_circuit/scout.rb +0 -165
- data/examples/14_rusty_circuit/show.log +0 -234
- data/examples/15_memory_network_and_bus/.envrc +0 -1
- data/examples/15_memory_network_and_bus/README.md +0 -66
- data/examples/15_memory_network_and_bus/editor_in_chief.rb +0 -24
- data/examples/15_memory_network_and_bus/editorial_pipeline.rb +0 -213
- data/examples/15_memory_network_and_bus/linux_writer.rb +0 -80
- data/examples/15_memory_network_and_bus/os_editor.rb +0 -48
- data/examples/15_memory_network_and_bus/os_writer.rb +0 -49
- data/examples/15_memory_network_and_bus/output/combined_article.md +0 -11
- data/examples/15_memory_network_and_bus/output/final_article.md +0 -8
- data/examples/15_memory_network_and_bus/output/linux_draft.md +0 -7
- data/examples/15_memory_network_and_bus/output/mac_draft.md +0 -7
- data/examples/15_memory_network_and_bus/output/memory.json +0 -13
- data/examples/15_memory_network_and_bus/output/revision_1.md +0 -29
- data/examples/15_memory_network_and_bus/output/revision_2.md +0 -50
- data/examples/15_memory_network_and_bus/output/revision_3.md +0 -8
- data/examples/15_memory_network_and_bus/output/windows_draft.md +0 -7
- data/examples/15_memory_network_and_bus/prompts/os_advocate.md +0 -13
- data/examples/15_memory_network_and_bus/prompts/os_chief.md +0 -13
- data/examples/15_memory_network_and_bus/prompts/os_editor.md +0 -13
- data/examples/16_writers_room/.envrc +0 -1
- data/examples/16_writers_room/display.rb +0 -158
- data/examples/16_writers_room/output/.gitignore +0 -4
- data/examples/16_writers_room/output/README.md +0 -69
- data/examples/16_writers_room/output/opus_001.md +0 -263
- data/examples/16_writers_room/output/opus_001_notes.log +0 -470
- data/examples/16_writers_room/output/opus_002.md +0 -245
- data/examples/16_writers_room/output/opus_002_notes.log +0 -546
- data/examples/16_writers_room/output/opus_002_screenplay.md +0 -7989
- data/examples/16_writers_room/output/opus_002_screenplay_notes.md +0 -993
- data/examples/16_writers_room/prompts/screenplay_writer.md +0 -66
- data/examples/16_writers_room/prompts/writer.md +0 -37
- data/examples/16_writers_room/room.rb +0 -186
- data/examples/16_writers_room/tools.rb +0 -173
- data/examples/16_writers_room/writer.rb +0 -121
- data/examples/16_writers_room/writers_room.rb +0 -256
- data/examples/17_skills.rb +0 -234
- data/examples/18_rails/.envrc +0 -3
- data/examples/18_rails/.gitignore +0 -5
- data/examples/18_rails/Gemfile +0 -11
- data/examples/18_rails/README.md +0 -67
- data/examples/18_rails/Rakefile +0 -4
- data/examples/18_rails/app/controllers/application_controller.rb +0 -4
- data/examples/18_rails/app/controllers/chat_controller.rb +0 -50
- data/examples/18_rails/app/jobs/application_job.rb +0 -4
- data/examples/18_rails/app/jobs/robot_run_job.rb +0 -25
- data/examples/18_rails/app/models/application_record.rb +0 -5
- data/examples/18_rails/app/models/robot_lab_result.rb +0 -36
- data/examples/18_rails/app/models/robot_lab_thread.rb +0 -23
- data/examples/18_rails/app/robots/chat_robot.rb +0 -25
- data/examples/18_rails/app/tools/time_tool.rb +0 -9
- data/examples/18_rails/app/views/chat/_user_message.html.erb +0 -1
- data/examples/18_rails/app/views/chat/index.html.erb +0 -67
- data/examples/18_rails/app/views/layouts/application.html.erb +0 -49
- data/examples/18_rails/bin/dev +0 -7
- data/examples/18_rails/bin/rails +0 -6
- data/examples/18_rails/bin/setup +0 -15
- data/examples/18_rails/config/application.rb +0 -33
- data/examples/18_rails/config/cable.yml +0 -2
- data/examples/18_rails/config/database.yml +0 -5
- data/examples/18_rails/config/environment.rb +0 -4
- data/examples/18_rails/config/initializers/robot_lab.rb +0 -11
- data/examples/18_rails/config/routes.rb +0 -6
- data/examples/18_rails/config.ru +0 -4
- data/examples/18_rails/db/migrate/001_create_robot_lab_tables.rb +0 -32
- data/examples/19_token_tracking.rb +0 -138
- data/examples/20_circuit_breaker.rb +0 -147
- data/examples/21_learning_loop.rb +0 -181
- data/examples/22_context_compression.rb +0 -172
- data/examples/23_convergence.rb +0 -133
- data/examples/24_structured_delegation.rb +0 -151
- data/examples/25_history_search/conversation.jsonl +0 -30
- data/examples/25_history_search.rb +0 -133
- data/examples/26_document_store/api_versioning_adr.md +0 -52
- data/examples/26_document_store/incident_postmortem.md +0 -46
- data/examples/26_document_store/postgres_runbook.md +0 -49
- data/examples/26_document_store/redis_caching_guide.md +0 -48
- data/examples/26_document_store/sidekiq_guide.md +0 -51
- data/examples/26_document_store.rb +0 -140
- data/examples/27_incident_response/README.md +0 -65
- data/examples/27_incident_response/incident_response.rb +0 -261
- data/examples/28_mcp_discovery.rb +0 -113
- data/examples/29_ractor_tools.rb +0 -240
- data/examples/30_ractor_network.rb +0 -252
- data/examples/31_launch_assessment.rb +0 -246
- data/examples/32_newsletter_reader.rb +0 -193
- data/examples/33_stock_generator.rb +0 -80
- data/examples/33_stock_predictor.rb +0 -327
- data/examples/34_agentskills.rb +0 -76
- data/examples/35_hooks.rb +0 -266
- data/examples/README.md +0 -550
- data/examples/common.rb +0 -180
- data/examples/prompts/assistant.md +0 -5
- data/examples/prompts/audit_trail.md +0 -8
- data/examples/prompts/billing.md +0 -10
- data/examples/prompts/classifier.md +0 -7
- data/examples/prompts/comedian.md +0 -6
- data/examples/prompts/comedy_critic.md +0 -10
- data/examples/prompts/configurable.md +0 -9
- data/examples/prompts/dispatcher.md +0 -12
- data/examples/prompts/entity_extractor.md +0 -14
- data/examples/prompts/escalation.md +0 -42
- data/examples/prompts/frontmatter_mcp_test.md +0 -9
- data/examples/prompts/frontmatter_named_test.md +0 -5
- data/examples/prompts/frontmatter_tools_test.md +0 -6
- data/examples/prompts/general.md +0 -7
- data/examples/prompts/github_assistant.md +0 -14
- data/examples/prompts/helper.md +0 -4
- data/examples/prompts/incident_responder.md +0 -18
- data/examples/prompts/keyword_extractor.md +0 -11
- data/examples/prompts/llm_config_demo.md +0 -20
- data/examples/prompts/order_support.md +0 -35
- data/examples/prompts/os_advocate.md +0 -13
- data/examples/prompts/os_chief.md +0 -13
- data/examples/prompts/os_editor.md +0 -13
- data/examples/prompts/parameterized_main_test.md +0 -6
- data/examples/prompts/pii_redactor.md +0 -7
- data/examples/prompts/product_support.md +0 -37
- data/examples/prompts/runbook_protocol.md +0 -12
- data/examples/prompts/sentiment_analyzer.md +0 -12
- data/examples/prompts/skill_a_test.md +0 -4
- data/examples/prompts/skill_b_test.md +0 -4
- data/examples/prompts/skill_config_test.md +0 -5
- data/examples/prompts/skill_cycle_a_test.md +0 -6
- data/examples/prompts/skill_cycle_b_test.md +0 -6
- data/examples/prompts/skill_description_test.md +0 -4
- data/examples/prompts/skill_leaf_test.md +0 -4
- data/examples/prompts/skill_nested_test.md +0 -6
- data/examples/prompts/skill_refs_main_test.md +0 -6
- data/examples/prompts/skill_self_ref_test.md +0 -6
- data/examples/prompts/skill_with_mcp_test.md +0 -9
- data/examples/prompts/skill_with_params_test.md +0 -6
- data/examples/prompts/skill_with_robot_name_test.md +0 -5
- data/examples/prompts/skill_with_tools_test.md +0 -6
- data/examples/prompts/sre_compliance.md +0 -10
- data/examples/prompts/structured_output.md +0 -7
- data/examples/prompts/synthesizer.md +0 -17
- data/examples/prompts/technical.md +0 -10
- data/examples/prompts/template_with_skills_test.md +0 -6
- data/examples/prompts/triage.md +0 -22
- data/examples/ruboruby.md +0 -423
- data/examples/run_all.rb +0 -60
- data/examples/xyzzy.rb +0 -97
- data/logfile +0 -8
- data/mkdocs.yml +0 -209
- data/robot_concurrency.md +0 -38
- data/simple_acp_review.md +0 -298
- data/temp.md +0 -6
- data/tool_manifest_plan.md +0 -155
data/docs/api/messages/index.md
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
# Messages
|
|
2
|
-
|
|
3
|
-
Message types for LLM conversation representation.
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
RobotLab uses a structured message system to represent conversations between users, assistants, and tools.
|
|
8
|
-
|
|
9
|
-
```ruby
|
|
10
|
-
# User input
|
|
11
|
-
user_msg = UserMessage.new("Hello", session_id: "123")
|
|
12
|
-
|
|
13
|
-
# Assistant response
|
|
14
|
-
text_msg = TextMessage.new(role: "assistant", content: "Hi there!")
|
|
15
|
-
|
|
16
|
-
# Tool interaction
|
|
17
|
-
tool = ToolMessage.new(id: "call_1", name: "get_weather", input: { city: "NYC" })
|
|
18
|
-
tool_call = ToolCallMessage.new(role: "assistant", tools: [tool])
|
|
19
|
-
tool_result = ToolResultMessage.new(tool: tool, content: { data: { temp: 72 } })
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
## Message Hierarchy
|
|
23
|
-
|
|
24
|
-
```
|
|
25
|
-
Message (base)
|
|
26
|
-
├── TextMessage - role + text content
|
|
27
|
-
├── ToolCallMessage - role + Array<ToolMessage>
|
|
28
|
-
└── ToolResultMessage - tool + result content
|
|
29
|
-
|
|
30
|
-
UserMessage - Standalone PORO (superclass Object)
|
|
31
|
-
ToolMessage - Standalone PORO (superclass Object)
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
`UserMessage` and `ToolMessage` are plain objects — their superclass is `Object`,
|
|
35
|
-
not `Message`. They do not respond to `type`, `role`, or any of the predicates
|
|
36
|
-
below.
|
|
37
|
-
|
|
38
|
-
## Common Interface
|
|
39
|
-
|
|
40
|
-
All Message subclasses implement:
|
|
41
|
-
|
|
42
|
-
```ruby
|
|
43
|
-
message.role # => String ("system", "user", "assistant", "tool_result")
|
|
44
|
-
message.content # => String or structured data
|
|
45
|
-
message.type # => String ("text", "tool_call", "tool_result")
|
|
46
|
-
message.to_h # => Hash representation
|
|
47
|
-
message.to_json # => JSON string
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
Valid values are fixed by constants on `Message`, and the constructor raises
|
|
51
|
-
`ArgumentError` for anything else:
|
|
52
|
-
|
|
53
|
-
```ruby
|
|
54
|
-
RobotLab::Message::VALID_TYPES # => ["text", "tool_call", "tool_result"]
|
|
55
|
-
RobotLab::Message::VALID_ROLES # => ["system", "user", "assistant", "tool_result"]
|
|
56
|
-
RobotLab::Message::VALID_STOP_REASONS # => ["tool", "stop"]
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
### Nil keys and `to_h`
|
|
60
|
-
|
|
61
|
-
`Message#to_h` — used as-is by `TextMessage` — ends in `.compact`, so any key
|
|
62
|
-
whose value is `nil` is **absent** from the hash, not present with a `nil` value.
|
|
63
|
-
A `TextMessage` built without a `stop_reason` produces a three-key hash. The same
|
|
64
|
-
applies to `UserMessage#to_h`.
|
|
65
|
-
|
|
66
|
-
`ToolCallMessage`, `ToolResultMessage`, and `ToolMessage` override `to_h` without
|
|
67
|
-
compacting, so their keys are always present.
|
|
68
|
-
|
|
69
|
-
Type and role predicates:
|
|
70
|
-
|
|
71
|
-
```ruby
|
|
72
|
-
message.text? # => true if type is "text"
|
|
73
|
-
message.tool_call? # => true if type is "tool_call"
|
|
74
|
-
message.tool_result? # => true if type is "tool_result"
|
|
75
|
-
message.system? # => true if role is "system"
|
|
76
|
-
message.user? # => true if role is "user"
|
|
77
|
-
message.assistant? # => true if role is "assistant"
|
|
78
|
-
message.stopped? # => true if stop_reason is "stop"
|
|
79
|
-
message.tool_stop? # => true if stop_reason is "tool"
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
## Classes
|
|
83
|
-
|
|
84
|
-
| Class | Description |
|
|
85
|
-
|-------|-------------|
|
|
86
|
-
| [UserMessage](user-message.md) | User input with session and metadata |
|
|
87
|
-
| [TextMessage](text-message.md) | Text message with role (system, user, or assistant) |
|
|
88
|
-
| [ToolCallMessage](tool-call-message.md) | Tool invocation request containing ToolMessage objects |
|
|
89
|
-
| [ToolResultMessage](tool-result-message.md) | Tool execution result |
|
|
90
|
-
|
|
91
|
-
## Usage in Memory
|
|
92
|
-
|
|
93
|
-
Messages are typically accessed through memory:
|
|
94
|
-
|
|
95
|
-
```ruby
|
|
96
|
-
memory.messages # => Array<Message>
|
|
97
|
-
|
|
98
|
-
# Format for LLM
|
|
99
|
-
memory.format_history # => Array<Message>
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
## Deserializing from Hash
|
|
103
|
-
|
|
104
|
-
`Message.from_hash` reconstructs the correct subclass from a stored hash:
|
|
105
|
-
|
|
106
|
-
```ruby
|
|
107
|
-
RobotLab::Message.from_hash({ type: "text", role: "user", content: "Hello" })
|
|
108
|
-
# => #<RobotLab::TextMessage ...>
|
|
109
|
-
|
|
110
|
-
RobotLab::Message.from_hash({ type: "tool_call", role: "assistant", tools: [...] })
|
|
111
|
-
# => #<RobotLab::ToolCallMessage ...>
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
When the `type` key is absent or `nil` (e.g. records persisted before the field was introduced), `from_hash` defaults to `TextMessage`:
|
|
115
|
-
|
|
116
|
-
```ruby
|
|
117
|
-
RobotLab::Message.from_hash({ role: "user", content: "legacy row" })
|
|
118
|
-
# => #<RobotLab::TextMessage ...>
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
String keys are normalised automatically via `transform_keys(&:to_sym)`.
|
|
122
|
-
|
|
123
|
-
## See Also
|
|
124
|
-
|
|
125
|
-
- [Memory](../core/memory.md)
|
|
126
|
-
- [Message Flow Architecture](../../architecture/message-flow.md)
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
# TextMessage
|
|
2
|
-
|
|
3
|
-
Text message from system, user, or assistant.
|
|
4
|
-
|
|
5
|
-
## Class: `RobotLab::TextMessage`
|
|
6
|
-
|
|
7
|
-
```ruby
|
|
8
|
-
message = TextMessage.new(role: "assistant", content: "Hello! How can I help you today?")
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Constructor
|
|
12
|
-
|
|
13
|
-
```ruby
|
|
14
|
-
TextMessage.new(role:, content:, stop_reason: nil)
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
**Parameters:**
|
|
18
|
-
|
|
19
|
-
| Name | Type | Description |
|
|
20
|
-
|------|------|-------------|
|
|
21
|
-
| `role` | `String` | Message role ("system", "user", or "assistant") |
|
|
22
|
-
| `content` | `String` | The text content |
|
|
23
|
-
| `stop_reason` | `String`, `nil` | Stop reason ("stop" or "tool") |
|
|
24
|
-
|
|
25
|
-
## Attributes
|
|
26
|
-
|
|
27
|
-
### content
|
|
28
|
-
|
|
29
|
-
```ruby
|
|
30
|
-
message.content # => String
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
The text content.
|
|
34
|
-
|
|
35
|
-
### role
|
|
36
|
-
|
|
37
|
-
```ruby
|
|
38
|
-
message.role # => "assistant"
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
Returns a String: `"system"`, `"user"`, or `"assistant"`.
|
|
42
|
-
|
|
43
|
-
### type
|
|
44
|
-
|
|
45
|
-
```ruby
|
|
46
|
-
message.type # => "text"
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
Always returns `"text"`.
|
|
50
|
-
|
|
51
|
-
### stop_reason
|
|
52
|
-
|
|
53
|
-
```ruby
|
|
54
|
-
message.stop_reason # => "stop" or nil
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
The stop reason, if any.
|
|
58
|
-
|
|
59
|
-
## Methods
|
|
60
|
-
|
|
61
|
-
### to_h
|
|
62
|
-
|
|
63
|
-
```ruby
|
|
64
|
-
message.to_h # => Hash
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
Hash representation. Inherited from `Message#to_h`, which ends in `.compact` — a
|
|
68
|
-
`nil` `stop_reason` is **omitted** rather than serialized as `nil`.
|
|
69
|
-
|
|
70
|
-
**Returns:**
|
|
71
|
-
|
|
72
|
-
```ruby
|
|
73
|
-
TextMessage.new(role: "assistant", content: "Hello! How can I help you today?").to_h
|
|
74
|
-
# => { type: "text", role: "assistant", content: "Hello! How can I help you today?" }
|
|
75
|
-
|
|
76
|
-
TextMessage.new(role: "assistant", content: "Done.", stop_reason: "stop").to_h
|
|
77
|
-
# => { type: "text", role: "assistant", content: "Done.", stop_reason: "stop" }
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
### to_json
|
|
81
|
-
|
|
82
|
-
```ruby
|
|
83
|
-
message.to_json # => String
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
JSON representation.
|
|
87
|
-
|
|
88
|
-
### Predicates
|
|
89
|
-
|
|
90
|
-
```ruby
|
|
91
|
-
message.text? # => true
|
|
92
|
-
message.tool_call? # => false
|
|
93
|
-
message.assistant? # => true (if role is "assistant")
|
|
94
|
-
message.user? # => false
|
|
95
|
-
message.stopped? # => true (if stop_reason is "stop")
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
## Examples
|
|
99
|
-
|
|
100
|
-
### System Message
|
|
101
|
-
|
|
102
|
-
```ruby
|
|
103
|
-
message = TextMessage.new(role: "system", content: "You are a helpful assistant")
|
|
104
|
-
message.system? # => true
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
### User Message
|
|
108
|
-
|
|
109
|
-
```ruby
|
|
110
|
-
message = TextMessage.new(role: "user", content: "What's the weather?")
|
|
111
|
-
message.user? # => true
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
### Assistant Response
|
|
115
|
-
|
|
116
|
-
```ruby
|
|
117
|
-
message = TextMessage.new(
|
|
118
|
-
role: "assistant",
|
|
119
|
-
content: "Your order has shipped!",
|
|
120
|
-
stop_reason: "stop"
|
|
121
|
-
)
|
|
122
|
-
message.assistant? # => true
|
|
123
|
-
message.stopped? # => true
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
### In Robot Results
|
|
127
|
-
|
|
128
|
-
`Robot#run` returns a `RobotResult`, **not** a `TextMessage`. `RobotResult` has no
|
|
129
|
-
`text?` and no `content` — calling either raises `NoMethodError`. Read the reply
|
|
130
|
-
with `last_text_content` (aliased as `reply`):
|
|
131
|
-
|
|
132
|
-
```ruby
|
|
133
|
-
result = robot.run("Tell me a joke")
|
|
134
|
-
|
|
135
|
-
puts result.last_text_content # => the assistant's text
|
|
136
|
-
puts result.reply # => same thing
|
|
137
|
-
result.stopped? # => true whenever there are no tool calls
|
|
138
|
-
result.has_tool_calls? # => whether the final message carried tool calls
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
!!! note "`RobotResult#stopped?` is not driven by `stop_reason`"
|
|
142
|
-
A `RobotResult` produced by `Robot#run` always has `stop_reason == nil`
|
|
143
|
-
(`RubyLLM::Message` does not define the method, so `build_result` falls back
|
|
144
|
-
to `nil`), and the `TextMessage` it wraps is built without a `stop_reason`
|
|
145
|
-
too. `stopped?` therefore reduces to `!has_tool_calls?` — it never becomes
|
|
146
|
-
true because a `stop_reason` of `"stop"` was reported. The
|
|
147
|
-
`stop_reason: "stop"` form shown above only applies to `TextMessage`
|
|
148
|
-
instances you construct yourself.
|
|
149
|
-
|
|
150
|
-
`result.output` is an `Array` holding a single `TextMessage` rebuilt from the
|
|
151
|
-
final response text — it is not the full turn:
|
|
152
|
-
|
|
153
|
-
```ruby
|
|
154
|
-
msg = result.output.first
|
|
155
|
-
msg.text? # => true
|
|
156
|
-
msg.content # => the assistant's text
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
### Filtering Text Content
|
|
160
|
-
|
|
161
|
-
```ruby
|
|
162
|
-
# Get only text messages from memory
|
|
163
|
-
text_messages = memory.messages.select(&:text?).map(&:content)
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
## See Also
|
|
167
|
-
|
|
168
|
-
- [UserMessage](user-message.md)
|
|
169
|
-
- [ToolCallMessage](tool-call-message.md)
|
|
170
|
-
- [Robot](../core/robot.md)
|
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
# ToolCallMessage
|
|
2
|
-
|
|
3
|
-
Tool invocation request from the LLM.
|
|
4
|
-
|
|
5
|
-
## Class: `RobotLab::ToolCallMessage`
|
|
6
|
-
|
|
7
|
-
```ruby
|
|
8
|
-
message = ToolCallMessage.new(
|
|
9
|
-
role: "assistant",
|
|
10
|
-
tools: [
|
|
11
|
-
ToolMessage.new(id: "call_abc123", name: "get_weather", input: { city: "New York" })
|
|
12
|
-
]
|
|
13
|
-
)
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
## Constructor
|
|
17
|
-
|
|
18
|
-
```ruby
|
|
19
|
-
ToolCallMessage.new(role:, tools:, stop_reason: nil)
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
**Parameters:**
|
|
23
|
-
|
|
24
|
-
| Name | Type | Description |
|
|
25
|
-
|------|------|-------------|
|
|
26
|
-
| `role` | `String` | Message role (typically "assistant") |
|
|
27
|
-
| `tools` | `Array<ToolMessage, Hash>` | Tool calls; plain Hashes are normalized via `ToolMessage.from_hash` |
|
|
28
|
-
| `stop_reason` | `String`, `nil` | Stop reason (defaults to "tool") |
|
|
29
|
-
|
|
30
|
-
Each entry in `tools` may be a `ToolMessage` **or** a Hash. Anything else raises
|
|
31
|
-
`ArgumentError: Invalid tool: must be ToolMessage or Hash`. The `tools` reader
|
|
32
|
-
always returns `ToolMessage` objects.
|
|
33
|
-
|
|
34
|
-
```ruby
|
|
35
|
-
ToolCallMessage.new(
|
|
36
|
-
role: "assistant",
|
|
37
|
-
tools: [{ id: "call_1", name: "get_weather", arguments: { city: "NYC" } }]
|
|
38
|
-
).tools.first.input
|
|
39
|
-
# => { city: "NYC" }
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
`ToolMessage.from_hash` symbolizes keys and accepts either `input:` or
|
|
43
|
-
`arguments:` for the parameter hash (`input` wins), defaulting to `{}` when
|
|
44
|
-
neither is present. This makes raw provider tool-call payloads usable directly.
|
|
45
|
-
|
|
46
|
-
## ToolMessage
|
|
47
|
-
|
|
48
|
-
Each tool call is represented by a standalone `ToolMessage` object. It is a plain
|
|
49
|
-
Ruby object — its superclass is `Object`, **not** `Message` — so it has no
|
|
50
|
-
`type`, `role`, or predicate methods:
|
|
51
|
-
|
|
52
|
-
```ruby
|
|
53
|
-
ToolMessage.new(id:, name:, input:)
|
|
54
|
-
ToolMessage.from_hash(hash)
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
| Name | Type | Description |
|
|
58
|
-
|------|------|-------------|
|
|
59
|
-
| `id` | `String` | Unique call identifier |
|
|
60
|
-
| `name` | `String` | Tool name |
|
|
61
|
-
| `input` | `Hash`, `nil` | Tool parameters; `nil` becomes `{}` |
|
|
62
|
-
|
|
63
|
-
`ToolMessage#to_h` returns `{ type: "tool", id:, name:, input: }`. It is not
|
|
64
|
-
compacted, so every key is always present.
|
|
65
|
-
|
|
66
|
-
## Attributes
|
|
67
|
-
|
|
68
|
-
### tools
|
|
69
|
-
|
|
70
|
-
```ruby
|
|
71
|
-
message.tools # => Array<ToolMessage>
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
Array of `ToolMessage` objects representing the tool calls.
|
|
75
|
-
|
|
76
|
-
### role
|
|
77
|
-
|
|
78
|
-
```ruby
|
|
79
|
-
message.role # => "assistant"
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
Returns a String. The LLM initiates tool calls, so this is typically `"assistant"`.
|
|
83
|
-
|
|
84
|
-
### type
|
|
85
|
-
|
|
86
|
-
```ruby
|
|
87
|
-
message.type # => "tool_call"
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
Always returns `"tool_call"`.
|
|
91
|
-
|
|
92
|
-
### content
|
|
93
|
-
|
|
94
|
-
```ruby
|
|
95
|
-
message.content # => nil
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
Always `nil` for tool call messages (the tool data is in `tools`).
|
|
99
|
-
|
|
100
|
-
### stop_reason
|
|
101
|
-
|
|
102
|
-
```ruby
|
|
103
|
-
message.stop_reason # => "tool"
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
Defaults to `"tool"` indicating the conversation stopped for tool execution.
|
|
107
|
-
|
|
108
|
-
## Methods
|
|
109
|
-
|
|
110
|
-
### to_h
|
|
111
|
-
|
|
112
|
-
```ruby
|
|
113
|
-
message.to_h # => Hash
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
Hash representation. `ToolCallMessage` overrides `Message#to_h` and does **not**
|
|
117
|
-
compact, so all four keys are always present (`content` is not included at all).
|
|
118
|
-
|
|
119
|
-
**Returns:**
|
|
120
|
-
|
|
121
|
-
```ruby
|
|
122
|
-
{
|
|
123
|
-
type: "tool_call",
|
|
124
|
-
role: "assistant",
|
|
125
|
-
tools: [
|
|
126
|
-
{ type: "tool", id: "call_abc123", name: "get_weather", input: { city: "New York" } }
|
|
127
|
-
],
|
|
128
|
-
stop_reason: "tool"
|
|
129
|
-
}
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
### to_json
|
|
133
|
-
|
|
134
|
-
```ruby
|
|
135
|
-
message.to_json # => String
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
JSON representation.
|
|
139
|
-
|
|
140
|
-
### Predicates
|
|
141
|
-
|
|
142
|
-
```ruby
|
|
143
|
-
message.tool_call? # => true
|
|
144
|
-
message.text? # => false
|
|
145
|
-
message.assistant? # => true
|
|
146
|
-
message.tool_stop? # => true
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
## Examples
|
|
150
|
-
|
|
151
|
-
### Single Tool Call
|
|
152
|
-
|
|
153
|
-
```ruby
|
|
154
|
-
tool = ToolMessage.new(
|
|
155
|
-
id: "call_1",
|
|
156
|
-
name: "search_orders",
|
|
157
|
-
input: { user_id: "123", status: "pending" }
|
|
158
|
-
)
|
|
159
|
-
|
|
160
|
-
call = ToolCallMessage.new(role: "assistant", tools: [tool])
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
### Multiple Tool Calls
|
|
164
|
-
|
|
165
|
-
```ruby
|
|
166
|
-
tools = [
|
|
167
|
-
ToolMessage.new(id: "call_1", name: "get_weather", input: { city: "NYC" }),
|
|
168
|
-
ToolMessage.new(id: "call_2", name: "get_time", input: { timezone: "EST" })
|
|
169
|
-
]
|
|
170
|
-
|
|
171
|
-
call = ToolCallMessage.new(role: "assistant", tools: tools)
|
|
172
|
-
call.tools.length # => 2
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
### Processing Tool Calls
|
|
176
|
-
|
|
177
|
-
```ruby
|
|
178
|
-
if message.tool_call?
|
|
179
|
-
message.tools.each do |tool|
|
|
180
|
-
puts "Tool called: #{tool.name}"
|
|
181
|
-
puts "Parameters: #{tool.input.inspect}"
|
|
182
|
-
end
|
|
183
|
-
end
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
### In Tool Execution Flow
|
|
187
|
-
|
|
188
|
-
```ruby
|
|
189
|
-
# LLM returns a tool call
|
|
190
|
-
tool = ToolMessage.new(id: "call_weather_1", name: "get_weather", input: { city: "Seattle" })
|
|
191
|
-
tool_call = ToolCallMessage.new(role: "assistant", tools: [tool])
|
|
192
|
-
|
|
193
|
-
# Execute the tool and record the result
|
|
194
|
-
result_data = execute_tool(tool.name, tool.input)
|
|
195
|
-
|
|
196
|
-
tool_result = ToolResultMessage.new(
|
|
197
|
-
tool: tool,
|
|
198
|
-
content: { data: result_data }
|
|
199
|
-
)
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
## See Also
|
|
203
|
-
|
|
204
|
-
- [ToolResultMessage](tool-result-message.md)
|
|
205
|
-
- [Tool](../core/tool.md)
|
|
206
|
-
- [Using Tools Guide](../../guides/using-tools.md)
|