simple_acp 0.0.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.
Files changed (80) hide show
  1. checksums.yaml +7 -0
  2. data/.envrc +1 -0
  3. data/CHANGELOG.md +5 -0
  4. data/COMMITS.md +196 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.md +385 -0
  7. data/Rakefile +13 -0
  8. data/docs/api/client-base.md +383 -0
  9. data/docs/api/index.md +159 -0
  10. data/docs/api/models.md +286 -0
  11. data/docs/api/server-base.md +379 -0
  12. data/docs/api/storage.md +347 -0
  13. data/docs/assets/images/simple_acp.jpg +0 -0
  14. data/docs/client/index.md +279 -0
  15. data/docs/client/sessions.md +324 -0
  16. data/docs/client/streaming.md +345 -0
  17. data/docs/client/sync-async.md +308 -0
  18. data/docs/core-concepts/agents.md +253 -0
  19. data/docs/core-concepts/events.md +337 -0
  20. data/docs/core-concepts/index.md +147 -0
  21. data/docs/core-concepts/messages.md +211 -0
  22. data/docs/core-concepts/runs.md +278 -0
  23. data/docs/core-concepts/sessions.md +281 -0
  24. data/docs/examples.md +659 -0
  25. data/docs/getting-started/configuration.md +166 -0
  26. data/docs/getting-started/index.md +62 -0
  27. data/docs/getting-started/installation.md +95 -0
  28. data/docs/getting-started/quick-start.md +189 -0
  29. data/docs/index.md +119 -0
  30. data/docs/server/creating-agents.md +360 -0
  31. data/docs/server/http-endpoints.md +411 -0
  32. data/docs/server/index.md +218 -0
  33. data/docs/server/multi-turn.md +329 -0
  34. data/docs/server/streaming.md +315 -0
  35. data/docs/storage/custom.md +414 -0
  36. data/docs/storage/index.md +176 -0
  37. data/docs/storage/memory.md +198 -0
  38. data/docs/storage/postgresql.md +350 -0
  39. data/docs/storage/redis.md +287 -0
  40. data/examples/01_basic/client.rb +88 -0
  41. data/examples/01_basic/server.rb +100 -0
  42. data/examples/02_async_execution/client.rb +107 -0
  43. data/examples/02_async_execution/server.rb +56 -0
  44. data/examples/03_run_management/client.rb +115 -0
  45. data/examples/03_run_management/server.rb +84 -0
  46. data/examples/04_rich_messages/client.rb +160 -0
  47. data/examples/04_rich_messages/server.rb +180 -0
  48. data/examples/05_await_resume/client.rb +164 -0
  49. data/examples/05_await_resume/server.rb +114 -0
  50. data/examples/06_agent_metadata/client.rb +188 -0
  51. data/examples/06_agent_metadata/server.rb +192 -0
  52. data/examples/README.md +252 -0
  53. data/examples/run_demo.sh +137 -0
  54. data/lib/simple_acp/client/base.rb +448 -0
  55. data/lib/simple_acp/client/sse.rb +141 -0
  56. data/lib/simple_acp/models/agent_manifest.rb +129 -0
  57. data/lib/simple_acp/models/await.rb +123 -0
  58. data/lib/simple_acp/models/base.rb +147 -0
  59. data/lib/simple_acp/models/errors.rb +102 -0
  60. data/lib/simple_acp/models/events.rb +256 -0
  61. data/lib/simple_acp/models/message.rb +235 -0
  62. data/lib/simple_acp/models/message_part.rb +225 -0
  63. data/lib/simple_acp/models/metadata.rb +161 -0
  64. data/lib/simple_acp/models/run.rb +298 -0
  65. data/lib/simple_acp/models/session.rb +137 -0
  66. data/lib/simple_acp/models/types.rb +210 -0
  67. data/lib/simple_acp/server/agent.rb +116 -0
  68. data/lib/simple_acp/server/app.rb +264 -0
  69. data/lib/simple_acp/server/base.rb +510 -0
  70. data/lib/simple_acp/server/context.rb +210 -0
  71. data/lib/simple_acp/server/falcon_runner.rb +61 -0
  72. data/lib/simple_acp/storage/base.rb +129 -0
  73. data/lib/simple_acp/storage/memory.rb +108 -0
  74. data/lib/simple_acp/storage/postgresql.rb +233 -0
  75. data/lib/simple_acp/storage/redis.rb +178 -0
  76. data/lib/simple_acp/version.rb +5 -0
  77. data/lib/simple_acp.rb +91 -0
  78. data/mkdocs.yml +152 -0
  79. data/sig/simple_acp.rbs +4 -0
  80. metadata +418 -0
@@ -0,0 +1,347 @@
1
+ # Storage
2
+
3
+ Storage backend interface and implementations.
4
+
5
+ ## Interface
6
+
7
+ All storage backends extend `SimpleAcp::Storage::Base`.
8
+
9
+ ### Class: SimpleAcp::Storage::Base
10
+
11
+ #### Constructor
12
+
13
+ ```ruby
14
+ SimpleAcp::Storage::Base.new(options = {})
15
+ ```
16
+
17
+ #### Abstract Methods
18
+
19
+ These methods must be implemented by subclasses:
20
+
21
+ ---
22
+
23
+ ##### #get_run
24
+
25
+ Retrieve a run by ID.
26
+
27
+ ```ruby
28
+ storage.get_run(run_id)
29
+ ```
30
+
31
+ **Parameters:**
32
+
33
+ | Name | Type | Description |
34
+ |------|------|-------------|
35
+ | `run_id` | `String` | Run ID |
36
+
37
+ **Returns:** `Models::Run` or `nil`
38
+
39
+ ---
40
+
41
+ ##### #save_run
42
+
43
+ Save a run.
44
+
45
+ ```ruby
46
+ storage.save_run(run)
47
+ ```
48
+
49
+ **Parameters:**
50
+
51
+ | Name | Type | Description |
52
+ |------|------|-------------|
53
+ | `run` | `Models::Run` | Run to save |
54
+
55
+ **Returns:** `Models::Run`
56
+
57
+ ---
58
+
59
+ ##### #delete_run
60
+
61
+ Delete a run and its events.
62
+
63
+ ```ruby
64
+ storage.delete_run(run_id)
65
+ ```
66
+
67
+ **Parameters:**
68
+
69
+ | Name | Type | Description |
70
+ |------|------|-------------|
71
+ | `run_id` | `String` | Run ID |
72
+
73
+ **Returns:** `void`
74
+
75
+ ---
76
+
77
+ ##### #list_runs
78
+
79
+ List runs with optional filtering.
80
+
81
+ ```ruby
82
+ storage.list_runs(agent_name: nil, session_id: nil, limit: 10, offset: 0)
83
+ ```
84
+
85
+ **Parameters:**
86
+
87
+ | Name | Type | Default | Description |
88
+ |------|------|---------|-------------|
89
+ | `agent_name` | `String` | `nil` | Filter by agent |
90
+ | `session_id` | `String` | `nil` | Filter by session |
91
+ | `limit` | `Integer` | `10` | Max results |
92
+ | `offset` | `Integer` | `0` | Skip count |
93
+
94
+ **Returns:** `Hash` with `:runs` and `:total`
95
+
96
+ ```ruby
97
+ { runs: [Run, ...], total: 42 }
98
+ ```
99
+
100
+ ---
101
+
102
+ ##### #get_session
103
+
104
+ Retrieve a session by ID.
105
+
106
+ ```ruby
107
+ storage.get_session(session_id)
108
+ ```
109
+
110
+ **Parameters:**
111
+
112
+ | Name | Type | Description |
113
+ |------|------|-------------|
114
+ | `session_id` | `String` | Session ID |
115
+
116
+ **Returns:** `Models::Session` or `nil`
117
+
118
+ ---
119
+
120
+ ##### #save_session
121
+
122
+ Save a session.
123
+
124
+ ```ruby
125
+ storage.save_session(session)
126
+ ```
127
+
128
+ **Parameters:**
129
+
130
+ | Name | Type | Description |
131
+ |------|------|-------------|
132
+ | `session` | `Models::Session` | Session to save |
133
+
134
+ **Returns:** `Models::Session`
135
+
136
+ ---
137
+
138
+ ##### #delete_session
139
+
140
+ Delete a session.
141
+
142
+ ```ruby
143
+ storage.delete_session(session_id)
144
+ ```
145
+
146
+ **Parameters:**
147
+
148
+ | Name | Type | Description |
149
+ |------|------|-------------|
150
+ | `session_id` | `String` | Session ID |
151
+
152
+ **Returns:** `void`
153
+
154
+ ---
155
+
156
+ ##### #add_event
157
+
158
+ Add an event to a run.
159
+
160
+ ```ruby
161
+ storage.add_event(run_id, event)
162
+ ```
163
+
164
+ **Parameters:**
165
+
166
+ | Name | Type | Description |
167
+ |------|------|-------------|
168
+ | `run_id` | `String` | Run ID |
169
+ | `event` | `Event` | Event to add |
170
+
171
+ **Returns:** `Event`
172
+
173
+ ---
174
+
175
+ ##### #get_events
176
+
177
+ Get events for a run.
178
+
179
+ ```ruby
180
+ storage.get_events(run_id, limit: 100, offset: 0)
181
+ ```
182
+
183
+ **Parameters:**
184
+
185
+ | Name | Type | Default | Description |
186
+ |------|------|---------|-------------|
187
+ | `run_id` | `String` | required | Run ID |
188
+ | `limit` | `Integer` | `100` | Max events |
189
+ | `offset` | `Integer` | `0` | Skip count |
190
+
191
+ **Returns:** `Array<Event>`
192
+
193
+ ---
194
+
195
+ #### Optional Methods
196
+
197
+ These have default implementations:
198
+
199
+ ##### #close
200
+
201
+ Close the storage connection.
202
+
203
+ ```ruby
204
+ storage.close
205
+ ```
206
+
207
+ **Default:** No-op
208
+
209
+ ---
210
+
211
+ ##### #ping
212
+
213
+ Check if storage is accessible.
214
+
215
+ ```ruby
216
+ storage.ping
217
+ ```
218
+
219
+ **Returns:** `Boolean`
220
+
221
+ **Default:** Returns `true`
222
+
223
+ ---
224
+
225
+ ## Implementations
226
+
227
+ ### Memory
228
+
229
+ ```ruby
230
+ storage = SimpleAcp::Storage::Memory.new
231
+ ```
232
+
233
+ **Additional Methods:**
234
+
235
+ ```ruby
236
+ storage.clear! # Clear all data
237
+ storage.stats # Get counts { runs: N, sessions: N, events: N }
238
+ ```
239
+
240
+ ---
241
+
242
+ ### Redis
243
+
244
+ ```ruby
245
+ require 'simple_acp/storage/redis'
246
+
247
+ storage = SimpleAcp::Storage::Redis.new(
248
+ url: "redis://localhost:6379",
249
+ ttl: 86400, # TTL in seconds (default: 24 hours)
250
+ prefix: "acp:", # Key prefix (default: "acp:")
251
+ redis: nil # Existing Redis connection
252
+ )
253
+ ```
254
+
255
+ **Additional Methods:**
256
+
257
+ ```ruby
258
+ storage.clear! # Delete all keys with prefix
259
+ ```
260
+
261
+ ---
262
+
263
+ ### PostgreSQL
264
+
265
+ ```ruby
266
+ require 'simple_acp/storage/postgresql'
267
+
268
+ storage = SimpleAcp::Storage::PostgreSQL.new(
269
+ url: "postgres://localhost/simple_acp",
270
+ skip_setup: false, # Skip table creation (default: false)
271
+ db: nil # Existing Sequel database
272
+ )
273
+ ```
274
+
275
+ **Additional Methods:**
276
+
277
+ ```ruby
278
+ storage.clear! # Truncate all tables
279
+ ```
280
+
281
+ ---
282
+
283
+ ## Custom Implementation
284
+
285
+ ```ruby
286
+ class MyStorage < SimpleAcp::Storage::Base
287
+ def initialize(options = {})
288
+ super
289
+ # Setup
290
+ end
291
+
292
+ def get_run(run_id)
293
+ # Implementation
294
+ end
295
+
296
+ def save_run(run)
297
+ # Implementation
298
+ end
299
+
300
+ def delete_run(run_id)
301
+ # Implementation
302
+ end
303
+
304
+ def list_runs(agent_name: nil, session_id: nil, limit: 10, offset: 0)
305
+ # Implementation
306
+ end
307
+
308
+ def get_session(session_id)
309
+ # Implementation
310
+ end
311
+
312
+ def save_session(session)
313
+ # Implementation
314
+ end
315
+
316
+ def delete_session(session_id)
317
+ # Implementation
318
+ end
319
+
320
+ def add_event(run_id, event)
321
+ # Implementation
322
+ end
323
+
324
+ def get_events(run_id, limit: 100, offset: 0)
325
+ # Implementation
326
+ end
327
+
328
+ def close
329
+ # Cleanup
330
+ end
331
+
332
+ def ping
333
+ # Health check
334
+ true
335
+ end
336
+ end
337
+ ```
338
+
339
+ ---
340
+
341
+ ## See Also
342
+
343
+ - [Storage Overview](../storage/index.md)
344
+ - [Memory Storage](../storage/memory.md)
345
+ - [Redis Storage](../storage/redis.md)
346
+ - [PostgreSQL Storage](../storage/postgresql.md)
347
+ - [Custom Backends](../storage/custom.md)
Binary file
@@ -0,0 +1,279 @@
1
+ # Client Guide
2
+
3
+ The SimpleAcp client provides a clean interface for communicating with ACP servers over HTTP.
4
+
5
+ ## Overview
6
+
7
+ ```mermaid
8
+ graph LR
9
+ C[Client::Base] -->|HTTP| S[Server]
10
+ C -->|SSE| S
11
+ C --> A[Agents]
12
+ C --> R[Runs]
13
+ C --> SE[Sessions]
14
+ ```
15
+
16
+ ## Quick Start
17
+
18
+ ```ruby
19
+ require 'simple_acp'
20
+
21
+ client = SimpleAcp::Client::Base.new(base_url: "http://localhost:8000")
22
+
23
+ # Check connection
24
+ puts client.ping ? "Connected!" : "Failed"
25
+
26
+ # List agents
27
+ agents = client.agents
28
+ puts agents.agents.map(&:name)
29
+
30
+ # Run an agent
31
+ run = client.run_sync(
32
+ agent: "echo",
33
+ input: [SimpleAcp::Models::Message.user("Hello!")]
34
+ )
35
+ puts run.output.first.text_content
36
+ ```
37
+
38
+ ## In This Section
39
+
40
+ <div class="grid cards" markdown>
41
+
42
+ - :material-sync:{ .lg .middle } **Sync & Async**
43
+
44
+ ---
45
+
46
+ Learn about synchronous and asynchronous execution
47
+
48
+ [:octicons-arrow-right-24: Sync & Async](sync-async.md)
49
+
50
+ - :material-play-speed:{ .lg .middle } **Streaming**
51
+
52
+ ---
53
+
54
+ Handle real-time streaming responses
55
+
56
+ [:octicons-arrow-right-24: Streaming](streaming.md)
57
+
58
+ - :material-history:{ .lg .middle } **Session Management**
59
+
60
+ ---
61
+
62
+ Maintain state across interactions
63
+
64
+ [:octicons-arrow-right-24: Sessions](sessions.md)
65
+
66
+ </div>
67
+
68
+ ## Client Configuration
69
+
70
+ ### Basic Setup
71
+
72
+ ```ruby
73
+ client = SimpleAcp::Client::Base.new(
74
+ base_url: "http://localhost:8000"
75
+ )
76
+ ```
77
+
78
+ ### With Timeout
79
+
80
+ ```ruby
81
+ client = SimpleAcp::Client::Base.new(
82
+ base_url: "http://localhost:8000",
83
+ timeout: 60 # seconds
84
+ )
85
+ ```
86
+
87
+ ### With Headers
88
+
89
+ ```ruby
90
+ client = SimpleAcp::Client::Base.new(
91
+ base_url: "http://localhost:8000",
92
+ headers: {
93
+ "Authorization" => "Bearer #{ENV['API_TOKEN']}",
94
+ "X-Request-ID" => SecureRandom.uuid
95
+ }
96
+ )
97
+ ```
98
+
99
+ ## Discovery Methods
100
+
101
+ ### Health Check
102
+
103
+ ```ruby
104
+ if client.ping
105
+ puts "Server is healthy"
106
+ else
107
+ puts "Server unavailable"
108
+ end
109
+ ```
110
+
111
+ ### List Agents
112
+
113
+ ```ruby
114
+ response = client.agents
115
+ response.agents.each do |agent|
116
+ puts "#{agent.name}: #{agent.description}"
117
+ end
118
+ ```
119
+
120
+ ### Get Agent Details
121
+
122
+ ```ruby
123
+ manifest = client.agent("echo")
124
+ puts manifest.name
125
+ puts manifest.description
126
+ puts manifest.input_content_types
127
+ puts manifest.output_content_types
128
+ ```
129
+
130
+ ## Execution Methods
131
+
132
+ ### Synchronous
133
+
134
+ Wait for completion:
135
+
136
+ ```ruby
137
+ run = client.run_sync(
138
+ agent: "processor",
139
+ input: [SimpleAcp::Models::Message.user("Process this")]
140
+ )
141
+
142
+ case run.status
143
+ when "completed"
144
+ puts run.output.first.text_content
145
+ when "failed"
146
+ puts "Error: #{run.error.message}"
147
+ when "awaiting"
148
+ # Handle await...
149
+ end
150
+ ```
151
+
152
+ ### Asynchronous
153
+
154
+ Start and poll:
155
+
156
+ ```ruby
157
+ run = client.run_async(
158
+ agent: "slow-processor",
159
+ input: [SimpleAcp::Models::Message.user("Data")]
160
+ )
161
+
162
+ puts "Started: #{run.run_id}"
163
+
164
+ # Poll until complete
165
+ loop do
166
+ run = client.run_status(run.run_id)
167
+ break if run.terminal?
168
+ sleep 1
169
+ end
170
+
171
+ puts run.output
172
+ ```
173
+
174
+ ### Streaming
175
+
176
+ Real-time events:
177
+
178
+ ```ruby
179
+ client.run_stream(
180
+ agent: "chat",
181
+ input: [SimpleAcp::Models::Message.user("Hello")]
182
+ ) do |event|
183
+ case event
184
+ when SimpleAcp::Models::MessagePartEvent
185
+ print event.part.content
186
+ when SimpleAcp::Models::RunCompletedEvent
187
+ puts "\nDone!"
188
+ end
189
+ end
190
+ ```
191
+
192
+ ## Run Management
193
+
194
+ ### Get Status
195
+
196
+ ```ruby
197
+ run = client.run_status("run-id-here")
198
+ puts run.status
199
+ ```
200
+
201
+ ### Get Events
202
+
203
+ ```ruby
204
+ events = client.run_events("run-id-here")
205
+ events.each do |event|
206
+ puts event.type
207
+ end
208
+ ```
209
+
210
+ ### Cancel Run
211
+
212
+ ```ruby
213
+ client.run_cancel("run-id-here")
214
+ ```
215
+
216
+ ### Resume Awaited Run
217
+
218
+ ```ruby
219
+ run = client.run_resume_sync(
220
+ run_id: "run-id-here",
221
+ await_resume: SimpleAcp::Models::MessageAwaitResume.new(
222
+ message: SimpleAcp::Models::Message.user("My response")
223
+ )
224
+ )
225
+ ```
226
+
227
+ ## Session Management
228
+
229
+ ### Use a Session
230
+
231
+ ```ruby
232
+ client.use_session("my-session-id")
233
+
234
+ # All runs now use this session
235
+ client.run_sync(agent: "chat", input: [...])
236
+ client.run_sync(agent: "chat", input: [...])
237
+ ```
238
+
239
+ ### Clear Session
240
+
241
+ ```ruby
242
+ client.clear_session
243
+ ```
244
+
245
+ ### Get Session Info
246
+
247
+ ```ruby
248
+ session = client.session("my-session-id")
249
+ puts session.history.length
250
+ puts session.state
251
+ ```
252
+
253
+ ## Error Handling
254
+
255
+ ```ruby
256
+ begin
257
+ run = client.run_sync(agent: "unknown", input: [...])
258
+ rescue SimpleAcp::Error => e
259
+ puts "ACP Error: #{e.message}"
260
+ rescue Faraday::TimeoutError
261
+ puts "Request timed out"
262
+ rescue Faraday::ConnectionFailed
263
+ puts "Could not connect to server"
264
+ end
265
+ ```
266
+
267
+ ## Best Practices
268
+
269
+ 1. **Reuse clients** - Create one client and reuse it
270
+ 2. **Handle errors** - Always catch and handle exceptions
271
+ 3. **Use appropriate mode** - Sync for quick ops, async/stream for long ops
272
+ 4. **Manage sessions** - Clear sessions when done
273
+ 5. **Set timeouts** - Configure appropriate timeout values
274
+
275
+ ## Next Steps
276
+
277
+ - Learn about [Sync & Async](sync-async.md) execution
278
+ - Master [Streaming](streaming.md) responses
279
+ - Explore [Session Management](sessions.md)