smart_message 0.0.10 → 0.0.13
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/.github/workflows/deploy-github-pages.yml +38 -0
- data/.gitignore +5 -0
- data/CHANGELOG.md +64 -0
- data/Gemfile.lock +35 -4
- data/README.md +169 -71
- data/Rakefile +29 -4
- data/docs/assets/images/ddq_architecture.svg +130 -0
- data/docs/assets/images/dlq_architecture.svg +115 -0
- data/docs/assets/images/enhanced-dual-publishing.svg +136 -0
- data/docs/assets/images/enhanced-fluent-api.svg +149 -0
- data/docs/assets/images/enhanced-microservices-routing.svg +115 -0
- data/docs/assets/images/enhanced-pattern-matching.svg +107 -0
- data/docs/assets/images/fluent-api-demo.svg +59 -0
- data/docs/assets/images/performance-comparison.svg +161 -0
- data/docs/assets/images/redis-basic-architecture.svg +53 -0
- data/docs/assets/images/redis-enhanced-architecture.svg +88 -0
- data/docs/assets/images/redis-queue-architecture.svg +101 -0
- data/docs/assets/images/smart_message.jpg +0 -0
- data/docs/assets/images/smart_message_walking.jpg +0 -0
- data/docs/assets/images/smartmessage_architecture_overview.svg +173 -0
- data/docs/assets/images/transport-comparison-matrix.svg +171 -0
- data/docs/assets/javascripts/mathjax.js +17 -0
- data/docs/assets/stylesheets/extra.css +51 -0
- data/docs/{addressing.md → core-concepts/addressing.md} +5 -7
- data/docs/{architecture.md → core-concepts/architecture.md} +80 -145
- data/docs/{dispatcher.md → core-concepts/dispatcher.md} +21 -21
- data/docs/{message_filtering.md → core-concepts/message-filtering.md} +2 -3
- data/docs/{message_processing.md → core-concepts/message-processing.md} +17 -17
- data/docs/{troubleshooting.md → development/troubleshooting.md} +7 -7
- data/docs/{examples.md → getting-started/examples.md} +103 -89
- data/docs/{getting-started.md → getting-started/quick-start.md} +47 -23
- data/docs/index.md +64 -0
- data/docs/{dead_letter_queue.md → reference/dead-letter-queue.md} +2 -3
- data/docs/{logging.md → reference/logging.md} +1 -1
- data/docs/{message_deduplication.md → reference/message-deduplication.md} +1 -0
- data/docs/{proc_handlers_summary.md → reference/proc-handlers.md} +7 -6
- data/docs/reference/serializers.md +245 -0
- data/docs/{transports.md → reference/transports.md} +9 -11
- data/docs/transports/memory-transport.md +374 -0
- data/docs/transports/redis-transport-comparison.md +361 -0
- data/docs/transports/redis-transport.md +490 -0
- data/examples/README.md +104 -14
- data/examples/city_scenario/911_emergency_call_flow.svg +99 -0
- data/examples/city_scenario/README.md +515 -0
- data/examples/city_scenario/ai_visitor_intelligence_flow.svg +108 -0
- data/examples/city_scenario/citizen.rb +195 -0
- data/examples/city_scenario/city_diagram.svg +125 -0
- data/examples/city_scenario/common/health_monitor.rb +80 -0
- data/examples/city_scenario/common/logger.rb +30 -0
- data/examples/city_scenario/emergency_dispatch_center.rb +270 -0
- data/examples/city_scenario/fire_department.rb +446 -0
- data/examples/city_scenario/fire_emergency_flow.svg +95 -0
- data/examples/city_scenario/health_department.rb +100 -0
- data/examples/city_scenario/health_monitoring_system.svg +130 -0
- data/examples/city_scenario/house.rb +244 -0
- data/examples/city_scenario/local_bank.rb +217 -0
- data/examples/city_scenario/messages/emergency_911_message.rb +80 -0
- data/examples/city_scenario/messages/emergency_resolved_message.rb +42 -0
- data/examples/city_scenario/messages/fire_dispatch_message.rb +42 -0
- data/examples/city_scenario/messages/fire_emergency_message.rb +44 -0
- data/examples/city_scenario/messages/health_check_message.rb +21 -0
- data/examples/city_scenario/messages/health_status_message.rb +34 -0
- data/examples/city_scenario/messages/police_dispatch_message.rb +45 -0
- data/examples/city_scenario/messages/silent_alarm_message.rb +37 -0
- data/examples/city_scenario/police_department.rb +316 -0
- data/examples/city_scenario/redis_monitor.rb +129 -0
- data/examples/city_scenario/redis_stats.rb +743 -0
- data/examples/city_scenario/room_for_improvement.md +240 -0
- data/examples/city_scenario/security_emergency_flow.svg +95 -0
- data/examples/city_scenario/service_internal_architecture.svg +154 -0
- data/examples/city_scenario/smart_message_ai_agent.rb +364 -0
- data/examples/city_scenario/start_demo.sh +236 -0
- data/examples/city_scenario/stop_demo.sh +106 -0
- data/examples/city_scenario/visitor.rb +631 -0
- data/examples/{10_message_deduplication.rb → memory/01_message_deduplication_demo.rb} +1 -3
- data/examples/{09_dead_letter_queue_demo.rb → memory/02_dead_letter_queue_demo.rb} +10 -40
- data/examples/{01_point_to_point_orders.rb → memory/03_point_to_point_orders.rb} +1 -3
- data/examples/{02_publish_subscribe_events.rb → memory/04_publish_subscribe_events.rb} +1 -2
- data/examples/{03_many_to_many_chat.rb → memory/05_many_to_many_chat.rb} +1 -4
- data/examples/{show_me.rb → memory/06_pretty_print_demo.rb} +1 -1
- data/examples/{05_proc_handlers.rb → memory/07_proc_handlers_demo.rb} +1 -2
- data/examples/{06_custom_logger_example.rb → memory/08_custom_logger_demo.rb} +13 -14
- data/examples/{07_error_handling_scenarios.rb → memory/09_error_handling_demo.rb} +1 -4
- data/examples/{08_entity_addressing_basic.rb → memory/10_entity_addressing_basic.rb} +2 -8
- data/examples/{08_entity_addressing_with_filtering.rb → memory/11_entity_addressing_with_filtering.rb} +2 -6
- data/examples/{09_regex_filtering_microservices.rb → memory/12_regex_filtering_microservices.rb} +1 -2
- data/examples/{10_header_block_configuration.rb → memory/13_header_block_configuration.rb} +1 -6
- data/examples/{11_global_configuration_example.rb → memory/14_global_configuration_demo.rb} +17 -8
- data/examples/{show_logger.rb → memory/15_logger_demo.rb} +1 -2
- data/examples/memory/README.md +163 -0
- data/examples/memory/memory_transport_architecture.svg +90 -0
- data/examples/memory/point_to_point_pattern.svg +94 -0
- data/examples/memory/publish_subscribe_pattern.svg +125 -0
- data/examples/{04_redis_smart_home_iot.rb → redis/01_smart_home_iot_demo.rb} +1 -5
- data/examples/redis/README.md +228 -0
- data/examples/redis/alert_system_flow.svg +127 -0
- data/examples/redis/dashboard_status_flow.svg +107 -0
- data/examples/redis/device_command_flow.svg +113 -0
- data/examples/redis/redis_transport_architecture.svg +115 -0
- data/examples/{smart_home_iot_dataflow.md → redis/smart_home_iot_dataflow.md} +4 -116
- data/examples/redis/smart_home_system_architecture.svg +133 -0
- data/ideas/README.md +41 -0
- data/ideas/agents.md +1001 -0
- data/ideas/database_transport.md +980 -0
- data/ideas/improvement.md +359 -0
- data/ideas/meshage.md +1788 -0
- data/ideas/message_discovery.md +178 -0
- data/ideas/message_schema.md +1381 -0
- data/lib/smart_message/.idea/.gitignore +8 -0
- data/lib/smart_message/.idea/markdown.xml +6 -0
- data/lib/smart_message/.idea/misc.xml +4 -0
- data/lib/smart_message/.idea/modules.xml +8 -0
- data/lib/smart_message/.idea/smart_message.iml +16 -0
- data/lib/smart_message/.idea/vcs.xml +6 -0
- data/lib/smart_message/addressing.rb +15 -0
- data/lib/smart_message/base.rb +19 -12
- data/lib/smart_message/configuration.rb +2 -23
- data/lib/smart_message/dead_letter_queue.rb +1 -1
- data/lib/smart_message/logger.rb +15 -4
- data/lib/smart_message/messaging.rb +3 -62
- data/lib/smart_message/plugins.rb +6 -44
- data/lib/smart_message/serializer.rb +14 -0
- data/lib/smart_message/transport/base.rb +42 -8
- data/lib/smart_message/transport/memory_transport.rb +23 -4
- data/lib/smart_message/transport/redis_transport.rb +11 -0
- data/lib/smart_message/transport/stdout_transport.rb +28 -10
- data/lib/smart_message/transport.rb +33 -1
- data/lib/smart_message/version.rb +1 -1
- data/lib/smart_message.rb +5 -52
- data/mkdocs.yml +184 -0
- data/p2p_plan.md +326 -0
- data/p2p_roadmap.md +287 -0
- data/smart_message.gemspec +2 -0
- data/smart_message.svg +51 -0
- metadata +145 -45
- data/docs/README.md +0 -57
- data/docs/serializers.md +0 -575
- data/examples/dead_letters.jsonl +0 -12
- data/examples/temp.txt +0 -94
- data/examples/tmux_chat/README.md +0 -283
- data/examples/tmux_chat/bot_agent.rb +0 -278
- data/examples/tmux_chat/human_agent.rb +0 -199
- data/examples/tmux_chat/room_monitor.rb +0 -160
- data/examples/tmux_chat/shared_chat_system.rb +0 -328
- data/examples/tmux_chat/start_chat_demo.sh +0 -190
- data/examples/tmux_chat/stop_chat_demo.sh +0 -22
- /data/docs/{properties.md → core-concepts/properties.md} +0 -0
- /data/docs/{ideas_to_think_about.md → development/ideas.md} +0 -0
@@ -1,283 +0,0 @@
|
|
1
|
-
# SmartMessage Tmux Chat Visualization
|
2
|
-
|
3
|
-
This is an enhanced version of the many-to-many chat example that uses tmux to provide a clear, visual representation of the messaging interactions between different agents across multiple chat rooms.
|
4
|
-
|
5
|
-
## Overview
|
6
|
-
|
7
|
-
Instead of having all output mixed together in a single terminal, this tmux version separates:
|
8
|
-
|
9
|
-
- **Room Monitors**: Visual displays showing activity in each chat room
|
10
|
-
- **Human Agents**: Interactive chat clients for simulated users
|
11
|
-
- **Bot Agents**: Automated responders with various capabilities
|
12
|
-
|
13
|
-
## Layout
|
14
|
-
|
15
|
-
The tmux session creates three windows:
|
16
|
-
|
17
|
-
### Window 0: Chat Control Center (2x2 grid)
|
18
|
-
```
|
19
|
-
┌─────────────────┬─────────────────┐
|
20
|
-
│ General Room │ Tech Room │
|
21
|
-
│ Monitor │ Monitor │
|
22
|
-
├─────────────────┼─────────────────┤
|
23
|
-
│ Random Room │ System Info & │
|
24
|
-
│ Monitor │ Instructions │
|
25
|
-
└─────────────────┴─────────────────┘
|
26
|
-
```
|
27
|
-
|
28
|
-
### Window 1: Human Agents (3 panes)
|
29
|
-
```
|
30
|
-
┌─────────────────┬─────────────────┐
|
31
|
-
│ │ Bob │
|
32
|
-
│ Alice ├─────────────────┤
|
33
|
-
│ │ Carol │
|
34
|
-
└─────────────────┴─────────────────┘
|
35
|
-
```
|
36
|
-
|
37
|
-
### Window 2: Bot Agents (2 panes)
|
38
|
-
```
|
39
|
-
┌─────────────────┬─────────────────┐
|
40
|
-
│ HelpBot │ FunBot │
|
41
|
-
│ │ │
|
42
|
-
└─────────────────┴─────────────────┘
|
43
|
-
```
|
44
|
-
|
45
|
-
## Features
|
46
|
-
|
47
|
-
### Room Monitors
|
48
|
-
Each room monitor shows:
|
49
|
-
- Real-time message activity for that specific room
|
50
|
-
- User join/leave notifications
|
51
|
-
- Command detections
|
52
|
-
- Activity status (active/quiet/inactive)
|
53
|
-
- Message count and participant statistics
|
54
|
-
|
55
|
-
### Human Agents
|
56
|
-
Interactive chat clients with:
|
57
|
-
- Command support (`/join`, `/leave`, `/list`, `/help`, `/quit`)
|
58
|
-
- Multi-room messaging
|
59
|
-
- Auto-response to mentions
|
60
|
-
- Real-time message display
|
61
|
-
|
62
|
-
### Bot Agents
|
63
|
-
Automated agents with capabilities like:
|
64
|
-
- **HelpBot**: `/help`, `/stats`, `/time`
|
65
|
-
- **FunBot**: `/joke`, `/weather`, `/echo`
|
66
|
-
- Keyword responses (hello, help, thank you)
|
67
|
-
- Command processing with visual feedback
|
68
|
-
|
69
|
-
## Quick Start
|
70
|
-
|
71
|
-
### Prerequisites
|
72
|
-
- tmux installed (`brew install tmux` on macOS)
|
73
|
-
- Ruby with SmartMessage gem
|
74
|
-
- Terminal with decent size (recommended: 120x40 or larger)
|
75
|
-
|
76
|
-
### Running the Demo
|
77
|
-
|
78
|
-
```bash
|
79
|
-
# Start the entire chat system
|
80
|
-
cd examples/tmux_chat
|
81
|
-
./start_chat_demo.sh
|
82
|
-
```
|
83
|
-
|
84
|
-
### Navigation
|
85
|
-
|
86
|
-
Once in tmux:
|
87
|
-
|
88
|
-
**Switch Between Windows:**
|
89
|
-
- **Ctrl+b then 0**: Switch to Control Center (room monitors)
|
90
|
-
- **Ctrl+b then 1**: Switch to Human Agents (Alice, Bob, Carol)
|
91
|
-
- **Ctrl+b then 2**: Switch to Bot Agents (HelpBot, FunBot)
|
92
|
-
|
93
|
-
**Move Between Panes (within a window):**
|
94
|
-
- **Ctrl+b then o**: Cycle through all panes in current window
|
95
|
-
- **Ctrl+b then arrow keys**: Move directly to pane in that direction (↑↓←→)
|
96
|
-
- **Ctrl+b then ;**: Toggle between current and last pane
|
97
|
-
|
98
|
-
**Other Useful Commands:**
|
99
|
-
- **Ctrl+b then z**: Zoom current pane (toggle fullscreen)
|
100
|
-
- **Ctrl+b then d**: Detach from session (keeps it running)
|
101
|
-
- **Ctrl+b then ?**: Show all tmux commands
|
102
|
-
|
103
|
-
### Getting Started Workflow
|
104
|
-
|
105
|
-
1. **After starting the demo**, you'll be in the Human Agents window (window 1)
|
106
|
-
2. **Look for the active pane** (has colored border) - usually Alice's pane
|
107
|
-
3. **Start typing immediately** - you're in the chat interface, not bash
|
108
|
-
4. **Try these first commands:**
|
109
|
-
```
|
110
|
-
/join general
|
111
|
-
Hello everyone!
|
112
|
-
/help
|
113
|
-
```
|
114
|
-
5. **Switch to other agents** using `Ctrl+b then o` to see different perspectives
|
115
|
-
6. **Watch room activity** by switching to Control Center: `Ctrl+b then 0`
|
116
|
-
|
117
|
-
### Interacting with Agents
|
118
|
-
|
119
|
-
In any human agent pane (Alice, Bob, Carol):
|
120
|
-
```bash
|
121
|
-
# Join rooms
|
122
|
-
/join general
|
123
|
-
/join tech
|
124
|
-
/join random
|
125
|
-
|
126
|
-
# Send messages (goes to all your active rooms)
|
127
|
-
Hello everyone!
|
128
|
-
|
129
|
-
# Use bot commands
|
130
|
-
/help
|
131
|
-
/joke
|
132
|
-
/weather Tokyo
|
133
|
-
/stats
|
134
|
-
|
135
|
-
# Mention other users
|
136
|
-
@alice how are you?
|
137
|
-
|
138
|
-
# Leave rooms
|
139
|
-
/leave tech
|
140
|
-
|
141
|
-
# Exit
|
142
|
-
/quit
|
143
|
-
```
|
144
|
-
|
145
|
-
### Stopping the Demo
|
146
|
-
|
147
|
-
```bash
|
148
|
-
# From outside tmux
|
149
|
-
./stop_chat_demo.sh
|
150
|
-
|
151
|
-
# Or from inside tmux
|
152
|
-
Ctrl+b then d # Detach
|
153
|
-
./stop_chat_demo.sh
|
154
|
-
```
|
155
|
-
|
156
|
-
## Architecture
|
157
|
-
|
158
|
-
### File-Based Transport
|
159
|
-
|
160
|
-
This example uses a custom `FileTransport` that:
|
161
|
-
- Writes messages to room-specific queue files in `/tmp/smart_message_chat/`
|
162
|
-
- Polls files for new messages
|
163
|
-
- Enables inter-process communication between tmux panes
|
164
|
-
- Cleans up automatically on shutdown
|
165
|
-
|
166
|
-
### Message Types
|
167
|
-
|
168
|
-
Three types of messages flow through the system:
|
169
|
-
|
170
|
-
1. **ChatMessage**: Regular chat messages
|
171
|
-
2. **BotCommandMessage**: Commands directed to bots
|
172
|
-
3. **SystemNotificationMessage**: Join/leave/system events
|
173
|
-
|
174
|
-
### Agent Types
|
175
|
-
|
176
|
-
- **BaseAgent**: Common functionality for all agents
|
177
|
-
- **HumanChatAgent**: Interactive user simulation
|
178
|
-
- **BotChatAgent**: Automated response agents
|
179
|
-
- **RoomMonitor**: Display-only room activity monitors
|
180
|
-
|
181
|
-
## Advantages Over Single-Terminal Version
|
182
|
-
|
183
|
-
### Visual Clarity
|
184
|
-
- **Room Separation**: See each room's activity independently
|
185
|
-
- **Agent Separation**: Each agent has its own display space
|
186
|
-
- **Real-time Updates**: Monitors show live activity as it happens
|
187
|
-
|
188
|
-
### Better Understanding
|
189
|
-
- **Message Flow**: Clearly see how messages route between rooms
|
190
|
-
- **Agent Behavior**: Watch how different agents respond to events
|
191
|
-
- **System Dynamics**: Observe the many-to-many messaging patterns
|
192
|
-
|
193
|
-
### Interactive Experience
|
194
|
-
- **Multiple Perspectives**: Switch between different agent viewpoints
|
195
|
-
- **Live Interaction**: Type and send messages in real-time
|
196
|
-
- **System Monitoring**: Watch room activity while participating
|
197
|
-
|
198
|
-
## Example Workflow
|
199
|
-
|
200
|
-
1. **Start the demo**: `./start_chat_demo.sh`
|
201
|
-
2. **Watch the Control Center**: See rooms come online and initial messages
|
202
|
-
3. **Switch to Human Agents**: Navigate to Alice, Bob, or Carol
|
203
|
-
4. **Join rooms**: Use `/join general` to participate
|
204
|
-
5. **Send messages**: Type anything to chat in your active rooms
|
205
|
-
6. **Try bot commands**: Use `/joke`, `/weather`, `/help`
|
206
|
-
7. **Watch interactions**: Switch back to Control Center to see message flow
|
207
|
-
8. **Monitor bots**: Check Bot Agents window to see bot responses
|
208
|
-
|
209
|
-
## Customization
|
210
|
-
|
211
|
-
### Adding New Rooms
|
212
|
-
Edit `start_chat_demo.sh` to add more room monitors:
|
213
|
-
```bash
|
214
|
-
tmux new-window -t $SESSION_NAME -n "New-Room"
|
215
|
-
tmux send-keys "ruby room_monitor.rb newroom" C-m
|
216
|
-
```
|
217
|
-
|
218
|
-
### Adding New Agents
|
219
|
-
Create additional panes:
|
220
|
-
```bash
|
221
|
-
tmux split-window -t $SESSION_NAME:1 -v
|
222
|
-
tmux send-keys "ruby human_agent.rb david David" C-m
|
223
|
-
```
|
224
|
-
|
225
|
-
### Custom Bot Capabilities
|
226
|
-
Modify `bot_agent.rb` or create new bots:
|
227
|
-
```bash
|
228
|
-
ruby bot_agent.rb mybot MyBot "custom,commands,here"
|
229
|
-
```
|
230
|
-
|
231
|
-
## Troubleshooting
|
232
|
-
|
233
|
-
### Common Issues
|
234
|
-
|
235
|
-
**Tmux not found**:
|
236
|
-
```bash
|
237
|
-
# macOS
|
238
|
-
brew install tmux
|
239
|
-
|
240
|
-
# Ubuntu/Debian
|
241
|
-
sudo apt-get install tmux
|
242
|
-
```
|
243
|
-
|
244
|
-
**Messages not appearing**:
|
245
|
-
- Check that `/tmp/smart_message_chat/` directory exists
|
246
|
-
- Verify agents have joined the same rooms
|
247
|
-
- Try stopping and restarting the demo
|
248
|
-
|
249
|
-
**Pane too small**:
|
250
|
-
- Resize terminal window to at least 120x40
|
251
|
-
- Use `Ctrl+b then z` to zoom a pane temporarily
|
252
|
-
|
253
|
-
**Agents not responding**:
|
254
|
-
- Check that agents are in the same rooms (`/list` command)
|
255
|
-
- Verify bot capabilities match the commands being used
|
256
|
-
|
257
|
-
**Agents crash with console errors**:
|
258
|
-
- Fixed in latest version - agents now handle missing IO.console gracefully
|
259
|
-
- If issues persist, check Ruby version and terminal compatibility
|
260
|
-
|
261
|
-
### Manual Cleanup
|
262
|
-
|
263
|
-
If the automatic cleanup doesn't work:
|
264
|
-
```bash
|
265
|
-
# Kill tmux session
|
266
|
-
tmux kill-session -t smart_message_chat
|
267
|
-
|
268
|
-
# Remove message queues
|
269
|
-
rm -rf /tmp/smart_message_chat
|
270
|
-
```
|
271
|
-
|
272
|
-
## Educational Value
|
273
|
-
|
274
|
-
This visualization helps understand:
|
275
|
-
|
276
|
-
- **Many-to-many messaging patterns**
|
277
|
-
- **Room-based routing and filtering**
|
278
|
-
- **Agent coordination and communication**
|
279
|
-
- **Event-driven architecture**
|
280
|
-
- **Real-time system monitoring**
|
281
|
-
- **Service discovery and capabilities**
|
282
|
-
|
283
|
-
Perfect for demonstrating SmartMessage's power in complex, distributed scenarios!
|
@@ -1,278 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# examples/tmux_chat/bot_agent.rb
|
3
|
-
#
|
4
|
-
# Bot agent for tmux chat visualization
|
5
|
-
|
6
|
-
require_relative 'shared_chat_system'
|
7
|
-
|
8
|
-
class BotChatAgent < BaseAgent
|
9
|
-
def initialize(bot_id:, name:, capabilities: [])
|
10
|
-
@capabilities = capabilities
|
11
|
-
@command_count = 0
|
12
|
-
super(agent_id: bot_id, name: name, agent_type: 'bot')
|
13
|
-
|
14
|
-
log_display("🤖 Bot #{@name} online!")
|
15
|
-
log_display("🔧 Capabilities: #{@capabilities.join(', ')}")
|
16
|
-
log_display("⚡ Listening for commands and messages...")
|
17
|
-
log_display("")
|
18
|
-
end
|
19
|
-
|
20
|
-
def setup_subscriptions
|
21
|
-
# Subscribe to bot commands and chat messages
|
22
|
-
BotCommandMessage.subscribe("BotChatAgent.handle_bot_command_#{@agent_id}")
|
23
|
-
ChatMessage.subscribe("BotChatAgent.handle_chat_message_#{@agent_id}")
|
24
|
-
|
25
|
-
# Register this instance
|
26
|
-
@@bots ||= {}
|
27
|
-
@@bots[@agent_id] = self
|
28
|
-
end
|
29
|
-
|
30
|
-
def run
|
31
|
-
# Start processing messages and wait
|
32
|
-
begin
|
33
|
-
while true
|
34
|
-
sleep(1)
|
35
|
-
end
|
36
|
-
rescue Interrupt
|
37
|
-
shutdown
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
# Class method routing for SmartMessage
|
42
|
-
def self.method_missing(method_name, *args)
|
43
|
-
if method_name.to_s.start_with?('handle_bot_command_')
|
44
|
-
bot_id = method_name.to_s.split('_').last
|
45
|
-
bot = (@@bots ||= {})[bot_id]
|
46
|
-
bot&.handle_bot_command(*args)
|
47
|
-
elsif method_name.to_s.start_with?('handle_chat_message_')
|
48
|
-
bot_id = method_name.to_s.split('_').last
|
49
|
-
bot = (@@bots ||= {})[bot_id]
|
50
|
-
bot&.handle_chat_message(*args)
|
51
|
-
else
|
52
|
-
super
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def handle_bot_command(wrapper)
|
57
|
-
message_header, message_payload = wrapper.split
|
58
|
-
command_data = JSON.parse(message_payload)
|
59
|
-
|
60
|
-
# Only handle commands in rooms we're in and commands we can handle
|
61
|
-
return unless @active_rooms.include?(command_data['room_id'])
|
62
|
-
return unless can_handle_command?(command_data['command'])
|
63
|
-
|
64
|
-
@command_count += 1
|
65
|
-
log_display("⚡ Processing command: /#{command_data['command']} (#{@command_count})")
|
66
|
-
|
67
|
-
process_command(command_data)
|
68
|
-
end
|
69
|
-
|
70
|
-
def handle_chat_message(wrapper)
|
71
|
-
message_header, message_payload = wrapper.split
|
72
|
-
chat_data = JSON.parse(message_payload)
|
73
|
-
|
74
|
-
# Only process messages from rooms we're in and not our own messages
|
75
|
-
return unless @active_rooms.include?(chat_data['room_id'])
|
76
|
-
return if chat_data['sender_id'] == @agent_id
|
77
|
-
|
78
|
-
# Don't respond to other bots to avoid infinite loops
|
79
|
-
return if chat_data['message_type'] == 'bot'
|
80
|
-
|
81
|
-
# Log the message
|
82
|
-
log_display("👁️ [#{chat_data['room_id']}] #{chat_data['sender_name']}: #{chat_data['content']}")
|
83
|
-
|
84
|
-
# Check if it's a bot command
|
85
|
-
if chat_data['content'].start_with?('/')
|
86
|
-
handle_inline_command(chat_data)
|
87
|
-
else
|
88
|
-
# Respond to certain keywords from human users only
|
89
|
-
respond_to_keywords(chat_data)
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
def can_handle_command?(command)
|
94
|
-
@capabilities.include?(command)
|
95
|
-
end
|
96
|
-
|
97
|
-
private
|
98
|
-
|
99
|
-
def handle_inline_command(chat_data)
|
100
|
-
content = chat_data['content']
|
101
|
-
command_parts = content[1..-1].split(' ')
|
102
|
-
command = command_parts.first
|
103
|
-
parameters = command_parts[1..-1]
|
104
|
-
|
105
|
-
return unless can_handle_command?(command)
|
106
|
-
|
107
|
-
# Create bot command message
|
108
|
-
bot_command = BotCommandMessage.new(
|
109
|
-
command_id: "CMD-#{@agent_id}-#{Time.now.to_i}-#{rand(1000)}",
|
110
|
-
room_id: chat_data['room_id'],
|
111
|
-
user_id: chat_data['sender_id'],
|
112
|
-
user_name: chat_data['sender_name'],
|
113
|
-
command: command,
|
114
|
-
parameters: parameters,
|
115
|
-
timestamp: Time.now.iso8601,
|
116
|
-
from: chat_data['sender_id']
|
117
|
-
)
|
118
|
-
|
119
|
-
bot_command.publish
|
120
|
-
end
|
121
|
-
|
122
|
-
def process_command(command_data)
|
123
|
-
case command_data['command']
|
124
|
-
when 'weather'
|
125
|
-
handle_weather_command(command_data)
|
126
|
-
when 'joke'
|
127
|
-
handle_joke_command(command_data)
|
128
|
-
when 'help'
|
129
|
-
handle_help_command(command_data)
|
130
|
-
when 'stats'
|
131
|
-
handle_stats_command(command_data)
|
132
|
-
when 'time'
|
133
|
-
handle_time_command(command_data)
|
134
|
-
when 'echo'
|
135
|
-
handle_echo_command(command_data)
|
136
|
-
else
|
137
|
-
send_bot_response(
|
138
|
-
room_id: command_data['room_id'],
|
139
|
-
content: "🤷♂️ Sorry, I don't know how to handle /#{command_data['command']}"
|
140
|
-
)
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
def respond_to_keywords(chat_data)
|
145
|
-
content = chat_data['content'].downcase
|
146
|
-
|
147
|
-
if content.include?('hello') || content.include?('hi')
|
148
|
-
send_bot_response(
|
149
|
-
room_id: chat_data['room_id'],
|
150
|
-
content: "Hello #{chat_data['sender_name']}! 👋"
|
151
|
-
)
|
152
|
-
elsif content.include?('help') && !content.start_with?('/')
|
153
|
-
send_bot_response(
|
154
|
-
room_id: chat_data['room_id'],
|
155
|
-
content: "Type /help to see my commands! 🤖"
|
156
|
-
)
|
157
|
-
elsif content.include?('thank')
|
158
|
-
send_bot_response(
|
159
|
-
room_id: chat_data['room_id'],
|
160
|
-
content: "You're welcome! 😊"
|
161
|
-
)
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
def handle_weather_command(command_data)
|
166
|
-
location = command_data['parameters'].first || 'your location'
|
167
|
-
weather_responses = [
|
168
|
-
"☀️ It's sunny and 72°F in #{location}!",
|
169
|
-
"🌧️ Looks like rain and 65°F in #{location}",
|
170
|
-
"❄️ Snow expected, 32°F in #{location}",
|
171
|
-
"⛅ Partly cloudy, 68°F in #{location}",
|
172
|
-
"🌪️ Tornado warning in #{location}! (Just kidding, it's nice)"
|
173
|
-
]
|
174
|
-
|
175
|
-
# Simulate API delay
|
176
|
-
Thread.new do
|
177
|
-
sleep(0.5)
|
178
|
-
send_bot_response(
|
179
|
-
room_id: command_data['room_id'],
|
180
|
-
content: weather_responses.sample
|
181
|
-
)
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
def handle_joke_command(command_data)
|
186
|
-
jokes = [
|
187
|
-
"Why don't scientists trust atoms? Because they make up everything! 😄",
|
188
|
-
"Why did the scarecrow win an award? He was outstanding in his field! 🌾",
|
189
|
-
"What do you call a fake noodle? An impasta! 🍝",
|
190
|
-
"Why don't eggs tell jokes? They'd crack each other up! 🥚",
|
191
|
-
"What do you call a sleeping bull? A bulldozer! 😴",
|
192
|
-
"Why don't robots ever panic? They have enough bytes! 🤖"
|
193
|
-
]
|
194
|
-
|
195
|
-
send_bot_response(
|
196
|
-
room_id: command_data['room_id'],
|
197
|
-
content: jokes.sample
|
198
|
-
)
|
199
|
-
end
|
200
|
-
|
201
|
-
def handle_help_command(command_data)
|
202
|
-
help_text = @capabilities.map do |cmd|
|
203
|
-
" /#{cmd} - #{get_command_description(cmd)}"
|
204
|
-
end.join("\n")
|
205
|
-
|
206
|
-
send_bot_response(
|
207
|
-
room_id: command_data['room_id'],
|
208
|
-
content: "🤖 #{@name} Commands:\n#{help_text}"
|
209
|
-
)
|
210
|
-
end
|
211
|
-
|
212
|
-
def handle_stats_command(command_data)
|
213
|
-
send_bot_response(
|
214
|
-
room_id: command_data['room_id'],
|
215
|
-
content: "📊 Bot Stats:\n" +
|
216
|
-
" • Active rooms: #{@active_rooms.length}\n" +
|
217
|
-
" • Commands processed: #{@command_count}\n" +
|
218
|
-
" • Capabilities: #{@capabilities.length}\n" +
|
219
|
-
" • Uptime: #{Time.now.strftime('%H:%M:%S')}"
|
220
|
-
)
|
221
|
-
end
|
222
|
-
|
223
|
-
def handle_time_command(command_data)
|
224
|
-
timezone = command_data['parameters'].first || 'local'
|
225
|
-
current_time = Time.now.strftime('%Y-%m-%d %H:%M:%S')
|
226
|
-
|
227
|
-
send_bot_response(
|
228
|
-
room_id: command_data['room_id'],
|
229
|
-
content: "🕒 Current time (#{timezone}): #{current_time}"
|
230
|
-
)
|
231
|
-
end
|
232
|
-
|
233
|
-
def handle_echo_command(command_data)
|
234
|
-
message = command_data['parameters'].join(' ')
|
235
|
-
if message.empty?
|
236
|
-
message = "Echo! Echo! Echo! 📢"
|
237
|
-
end
|
238
|
-
|
239
|
-
send_bot_response(
|
240
|
-
room_id: command_data['room_id'],
|
241
|
-
content: "🔊 Echo: #{message}"
|
242
|
-
)
|
243
|
-
end
|
244
|
-
|
245
|
-
def get_command_description(command)
|
246
|
-
descriptions = {
|
247
|
-
'weather' => 'Get weather information',
|
248
|
-
'joke' => 'Tell a random joke',
|
249
|
-
'help' => 'Show this help message',
|
250
|
-
'stats' => 'Show bot statistics',
|
251
|
-
'time' => 'Show current time',
|
252
|
-
'echo' => 'Echo your message'
|
253
|
-
}
|
254
|
-
|
255
|
-
descriptions[command] || 'No description available'
|
256
|
-
end
|
257
|
-
|
258
|
-
def send_bot_response(room_id:, content:)
|
259
|
-
send_message(room_id: room_id, content: content, message_type: 'bot')
|
260
|
-
log_display("💬 Replied to [#{room_id}]: #{content}")
|
261
|
-
end
|
262
|
-
end
|
263
|
-
|
264
|
-
# Main execution
|
265
|
-
if __FILE__ == $0
|
266
|
-
if ARGV.length < 2
|
267
|
-
puts "Usage: #{$0} <bot_id> <name> [capability1,capability2,...]"
|
268
|
-
puts "Example: #{$0} helpbot HelpBot help,stats,time"
|
269
|
-
exit 1
|
270
|
-
end
|
271
|
-
|
272
|
-
bot_id = ARGV[0]
|
273
|
-
name = ARGV[1]
|
274
|
-
capabilities = ARGV[2] ? ARGV[2].split(',') : ['help']
|
275
|
-
|
276
|
-
bot = BotChatAgent.new(bot_id: bot_id, name: name, capabilities: capabilities)
|
277
|
-
bot.run
|
278
|
-
end
|