vsm 0.1.0 → 0.2.0

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +144 -0
  3. data/Rakefile +1 -5
  4. data/examples/01_echo_tool.rb +5 -24
  5. data/examples/02_openai_streaming.rb +3 -3
  6. data/examples/02b_anthropic_streaming.rb +1 -4
  7. data/examples/03b_anthropic_tools.rb +1 -4
  8. data/examples/05_mcp_server_and_chattty.rb +63 -0
  9. data/examples/06_mcp_mount_reflection.rb +45 -0
  10. data/examples/07_connect_claude_mcp.rb +78 -0
  11. data/examples/08_custom_chattty.rb +63 -0
  12. data/examples/09_mcp_with_llm_calls.rb +49 -0
  13. data/examples/10_meta_read_only.rb +56 -0
  14. data/exe/vsm +17 -0
  15. data/lib/vsm/async_channel.rb +26 -3
  16. data/lib/vsm/capsule.rb +2 -0
  17. data/lib/vsm/cli.rb +78 -0
  18. data/lib/vsm/dsl.rb +41 -11
  19. data/lib/vsm/dsl_mcp.rb +36 -0
  20. data/lib/vsm/generator/new_project.rb +154 -0
  21. data/lib/vsm/generator/templates/Gemfile.erb +9 -0
  22. data/lib/vsm/generator/templates/README_md.erb +40 -0
  23. data/lib/vsm/generator/templates/Rakefile.erb +5 -0
  24. data/lib/vsm/generator/templates/bin_console.erb +11 -0
  25. data/lib/vsm/generator/templates/bin_setup.erb +7 -0
  26. data/lib/vsm/generator/templates/exe_name.erb +34 -0
  27. data/lib/vsm/generator/templates/gemspec.erb +24 -0
  28. data/lib/vsm/generator/templates/gitignore.erb +10 -0
  29. data/lib/vsm/generator/templates/lib_name_rb.erb +9 -0
  30. data/lib/vsm/generator/templates/lib_organism_rb.erb +44 -0
  31. data/lib/vsm/generator/templates/lib_ports_chat_tty_rb.erb +12 -0
  32. data/lib/vsm/generator/templates/lib_tools_read_file_rb.erb +32 -0
  33. data/lib/vsm/generator/templates/lib_version_rb.erb +6 -0
  34. data/lib/vsm/mcp/client.rb +80 -0
  35. data/lib/vsm/mcp/jsonrpc.rb +92 -0
  36. data/lib/vsm/mcp/remote_tool_capsule.rb +35 -0
  37. data/lib/vsm/meta/snapshot_builder.rb +121 -0
  38. data/lib/vsm/meta/snapshot_cache.rb +25 -0
  39. data/lib/vsm/meta/support.rb +35 -0
  40. data/lib/vsm/meta/tools.rb +498 -0
  41. data/lib/vsm/meta.rb +59 -0
  42. data/lib/vsm/ports/chat_tty.rb +112 -0
  43. data/lib/vsm/ports/mcp/server_stdio.rb +101 -0
  44. data/lib/vsm/roles/intelligence.rb +6 -2
  45. data/lib/vsm/version.rb +1 -1
  46. data/lib/vsm.rb +10 -0
  47. data/mcp_update.md +162 -0
  48. metadata +38 -18
  49. data/.rubocop.yml +0 -8
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+ require "json"
3
+ require "async"
4
+
5
+ module VSM
6
+ module Ports
7
+ module MCP
8
+ # Exposes the capsule's tools as an MCP server over stdio (NDJSON JSON-RPC).
9
+ # Implemented methods: tools/list, tools/call.
10
+ class ServerStdio < VSM::Port
11
+ def initialize(capsule:)
12
+ super(capsule: capsule)
13
+ @waiters = {}
14
+ @waiters_mutex = Mutex.new
15
+ end
16
+
17
+ def egress_subscribe
18
+ # Single subscriber that resolves tool_result waiters by corr_id
19
+ @capsule.bus.subscribe do |m|
20
+ next unless m.kind == :tool_result
21
+ q = nil
22
+ @waiters_mutex.synchronize { q = @waiters.delete(m.corr_id.to_s) }
23
+ q&.enqueue(m)
24
+ end
25
+ super
26
+ end
27
+
28
+ def loop
29
+ $stdout.sync = true
30
+ while (line = $stdin.gets)
31
+ begin
32
+ req = JSON.parse(line)
33
+ rescue => e
34
+ write_err(nil, code: -32700, message: "Parse error: #{e.message}")
35
+ next
36
+ end
37
+
38
+ id = req["id"]
39
+ method = req["method"]
40
+ params = req["params"] || {}
41
+ case method
42
+ when "tools/list"
43
+ write_ok(id, { tools: list_tools })
44
+ when "tools/call"
45
+ name = params["name"].to_s
46
+ args = params["arguments"] || {}
47
+ res = call_local_tool(id, name, args)
48
+ write_ok(id, { content: [{ type: "text", text: res.to_s }] })
49
+ else
50
+ write_err(id, code: -32601, message: "Method not found: #{method}")
51
+ end
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def list_tools
58
+ ops = @capsule.bus.context[:operations_children] || {}
59
+ ops.values
60
+ .select { _1.respond_to?(:tool_descriptor) }
61
+ .map { to_mcp_descriptor(_1.tool_descriptor) }
62
+ end
63
+
64
+ def to_mcp_descriptor(desc)
65
+ {
66
+ "name" => desc.name,
67
+ "description" => desc.description,
68
+ "input_schema" => desc.schema
69
+ }
70
+ end
71
+
72
+ def call_local_tool(req_id, name, args)
73
+ corr = req_id.to_s
74
+ q = Async::Queue.new
75
+ @waiters_mutex.synchronize { @waiters[corr] = q }
76
+ @capsule.bus.emit VSM::Message.new(
77
+ kind: :tool_call,
78
+ payload: { tool: name, args: args },
79
+ corr_id: corr,
80
+ meta: { session_id: "mcp:stdio" },
81
+ path: [:mcp, :server, name]
82
+ )
83
+ msg = q.dequeue
84
+ msg.payload
85
+ ensure
86
+ @waiters_mutex.synchronize { @waiters.delete(corr) }
87
+ end
88
+
89
+ def write_ok(id, result)
90
+ puts JSON.dump({ jsonrpc: "2.0", id: id, result: result })
91
+ $stdout.flush
92
+ end
93
+
94
+ def write_err(id, code:, message:)
95
+ puts JSON.dump({ jsonrpc: "2.0", id: id, error: { code: code, message: message } })
96
+ $stdout.flush
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -12,7 +12,9 @@ module VSM
12
12
  # - system_prompt(session_id) -> String
13
13
  # - offer_tools?(session_id, descriptor) -> true/false (filter tools)
14
14
  class Intelligence
15
- def initialize(driver:, system_prompt: nil)
15
+ attr_reader :driver
16
+
17
+ def initialize(driver: nil, system_prompt: nil)
16
18
  @driver = driver
17
19
  @system_prompt = system_prompt
18
20
  @sessions = Hash.new { |h,k| h[k] = new_session_state }
@@ -21,6 +23,9 @@ module VSM
21
23
  def observe(bus); end
22
24
 
23
25
  def handle(message, bus:, **)
26
+ # If no driver is configured, the base implementation is inert.
27
+ # Subclasses can override #handle to implement non-LLM behavior.
28
+ return false if @driver.nil?
24
29
  case message.kind
25
30
  when :user
26
31
  sid = message.meta&.dig(:session_id)
@@ -165,4 +170,3 @@ module VSM
165
170
  end
166
171
  end
167
172
  end
168
-
data/lib/vsm/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Vsm
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/vsm.rb CHANGED
@@ -20,6 +20,8 @@ require_relative "vsm/tool/descriptor"
20
20
  require_relative "vsm/tool/acts_as_tool"
21
21
  require_relative "vsm/tool/capsule"
22
22
 
23
+ require_relative "vsm/meta"
24
+
23
25
  require_relative "vsm/executors/fiber_executor"
24
26
  require_relative "vsm/executors/thread_executor"
25
27
 
@@ -35,6 +37,14 @@ require_relative "vsm/drivers/family"
35
37
 
36
38
  require_relative "vsm/lens"
37
39
 
40
+ # Optional/built-in ports and MCP integration
41
+ require_relative "vsm/ports/chat_tty"
42
+ require_relative "vsm/ports/mcp/server_stdio"
43
+ require_relative "vsm/mcp/jsonrpc"
44
+ require_relative "vsm/mcp/client"
45
+ require_relative "vsm/mcp/remote_tool_capsule"
46
+ require_relative "vsm/dsl_mcp"
47
+
38
48
  module Vsm
39
49
  class Error < StandardError; end
40
50
  # Your code goes here...
data/mcp_update.md ADDED
@@ -0,0 +1,162 @@
1
+ # MCP Integration Plan and Built‑In Ports
2
+
3
+ This document proposes minimal, practical support to:
4
+ - Expose any VSM capsule as an MCP server over stdio (JSON‑RPC) implementing `tools/list` and `tools/call`.
5
+ - Add two reusable ports to VSM: a generic, customizable Chat TTY port and an MCP stdio server port.
6
+ - Dynamically reflect tools from external MCP servers and wrap them as VSM tool capsules.
7
+
8
+ The design uses Ruby’s dynamic capabilities and integrates cleanly with existing VSM roles (Operations, Intelligence, Governance, etc.).
9
+
10
+ ## Scope (Phase 1)
11
+ - MCP methods: `tools/list`, `tools/call` only.
12
+ - Transport: JSON‑RPC over stdio (NDJSON framing to start; can evolve to LSP framing without API changes).
13
+ - No additional MCP features (Prompts/Resources/Logs) in this phase.
14
+
15
+ ## Components
16
+ - `VSM::Ports::ChatTTY` — Generic, customizable chat terminal port.
17
+ - `VSM::Ports::MCP::ServerStdio` — MCP server over stdio exposing capsule tools.
18
+ - `VSM::MCP::Client` — Thin stdio JSON‑RPC client for MCP reflection and calls.
19
+ - `VSM::MCP::RemoteToolCapsule` — Wraps a remote MCP tool as a local VSM `ToolCapsule`.
20
+ - `VSM::DSL::ChildrenBuilder#mcp_server` — Reflect and register remote tools with include/exclude/prefix controls.
21
+ - (Tiny core tweak) Inject `bus` into children that accept `bus=` to allow rich observability from wrappers.
22
+
23
+ ## Design Overview
24
+ - Client reflection: spawn an MCP server process, call `tools/list`, build `RemoteToolCapsule`s per tool, and add them as children. Include/exclude/prefix options shape the local tool namespace.
25
+ - Server exposure: reflect local tools via `tools/list`; on `tools/call`, emit a normal VSM `:tool_call` and await matching `:tool_result` (corr_id = JSON‑RPC id) to reply.
26
+ - Operations routing: unchanged for Phase 1. Reflected tools register as regular children; prefixing avoids collisions. (Optional namespacing router can be added later.)
27
+ - Observability: all bridges emit events into the bus so Lens shows clear lanes (client: `[:mcp, :client, server, tool]`; server: `[:mcp, :server, tool]`).
28
+ - Coexistence: ChatTTY targets the user’s real TTY (e.g., `IO.console`) or stderr; MCP server uses stdio exclusively. They can run together without interfering.
29
+
30
+ ## File Layout (proposed)
31
+ - `lib/vsm/ports/chat_tty.rb`
32
+ - `lib/vsm/ports/mcp/server_stdio.rb`
33
+ - `lib/vsm/mcp/jsonrpc.rb` (shared stdio JSON‑RPC util)
34
+ - `lib/vsm/mcp/client.rb`
35
+ - `lib/vsm/mcp/remote_tool_capsule.rb`
36
+ - `lib/vsm/dsl_mcp.rb` (adds `mcp_server` to the DSL ChildrenBuilder)
37
+ - (Core) optional `bus` injection in `lib/vsm/capsule.rb`
38
+
39
+ ## APIs and Usage
40
+
41
+ ### Expose a Capsule via CLI and MCP (simultaneously)
42
+ ```ruby
43
+ require "vsm"
44
+ require "vsm/ports/chat_tty"
45
+ require "vsm/ports/mcp/server_stdio"
46
+
47
+ cap = VSM::DSL.define(:demo) do
48
+ identity klass: VSM::Identity, args: { identity: "demo", invariants: [] }
49
+ governance klass: VSM::Governance
50
+ coordination klass: VSM::Coordination
51
+ intelligence klass: VSM::Intelligence, args: { driver: VSM::Drivers::OpenAI::AsyncDriver.new(api_key: ENV["OPENAI_API_KEY"], model: "gpt-4o-mini") }
52
+ monitoring klass: VSM::Monitoring
53
+ operations do
54
+ # local tools …
55
+ end
56
+ end
57
+
58
+ ports = [
59
+ VSM::Ports::MCP::ServerStdio.new(capsule: cap), # machine IO (stdio)
60
+ VSM::Ports::ChatTTY.new(capsule: cap) # human IO (TTY/console)
61
+ ]
62
+ VSM::Runtime.start(cap, ports: ports)
63
+ ```
64
+
65
+ ### Mount a Remote MCP Server (dynamic reflection)
66
+ ```ruby
67
+ require "vsm"
68
+ require "vsm/dsl_mcp"
69
+
70
+ cap = VSM::DSL.define(:with_remote) do
71
+ identity klass: VSM::Identity, args: { identity: "with_remote", invariants: [] }
72
+ governance klass: VSM::Governance
73
+ coordination klass: VSM::Coordination
74
+ intelligence klass: VSM::Intelligence, args: { driver: VSM::Drivers::Anthropic::AsyncDriver.new(api_key: ENV["ANTHROPIC_API_KEY"], model: "claude-sonnet-4.0") }
75
+ monitoring klass: VSM::Monitoring
76
+ operations do
77
+ mcp_server :smith, cmd: "smith-server --stdio", include: %w[search read], prefix: "smith_", env: { "SMITH_TOKEN" => ENV["SMITH_TOKEN"] }
78
+ end
79
+ end
80
+
81
+ VSM::Runtime.start(cap, ports: [VSM::Ports::ChatTTY.new(capsule: cap)])
82
+ ```
83
+
84
+ ### Filter Tools Offered to the Model (optional)
85
+ ```ruby
86
+ class GuardedIntel < VSM::Intelligence
87
+ def offer_tools?(sid, descriptor)
88
+ descriptor.name.start_with?("smith_") # only offer smith_* tools
89
+ end
90
+ end
91
+ ```
92
+
93
+ ## Customization (ChatTTY)
94
+ - Constructor options: `input:`, `output:`, `banner:`, `prompt:`, `theme:`.
95
+ - Defaults: reads/writes to `IO.console` if available; otherwise reads are disabled and output goes to a safe stream (stderr/console). Never interferes with MCP stdio.
96
+ - Override points: subclass and override `banner(io)` and/or `render_out(message)` while reusing the main input loop.
97
+
98
+ Example (options only):
99
+ ```ruby
100
+ tty = VSM::Ports::ChatTTY.new(
101
+ capsule: cap,
102
+ banner: ->(io) { io.puts "\e[96mMy App\e[0m — welcome!" },
103
+ prompt: "Me> "
104
+ )
105
+ ```
106
+
107
+ Example (subclass):
108
+ ```ruby
109
+ class FancyTTY < VSM::Ports::ChatTTY
110
+ def banner(io)
111
+ io.puts "\e[95m\n ███ MY APP ███\n\e[0m"
112
+ end
113
+ def render_out(m)
114
+ super
115
+ @out.puts("\e[92m✓ #{m.payload.to_s.slice(0,200)}\e[0m") if m.kind == :tool_result
116
+ end
117
+ end
118
+ ```
119
+
120
+ ## Coexistence and IO Routing
121
+ - MCP stdio server: reads `$stdin`, writes `$stdout` with strict JSON (one message per line). No TTY assumptions.
122
+ - ChatTTY: prefers `IO.console` for both input and output; falls back to `$stderr` for output and disables input if no TTY is present.
123
+ - Result: Both ports can run in the same process without corrupting MCP stdio.
124
+
125
+ ## Observability
126
+ - Client wrapper emits `:progress`/`:audit` with `path: [:mcp, :client, server, tool]` around calls.
127
+ - Server port emits `:audit` and wraps `tools/call` into standard `:tool_call`/`:tool_result` with `corr_id` mirrored to JSON‑RPC id.
128
+ - Lens will show clear lanes and full payloads, subject to Governance redaction (if any).
129
+
130
+ ## Governance and Operations
131
+ - Operations: unchanged; executes capsules for `:tool_call` and emits `:tool_result`.
132
+ - Governance: gate by name/prefix/regex; apply timeouts/rate limits/confirmations; redact args/results in Lens if needed.
133
+ - Execution mode: remote wrappers default to `:thread` to avoid blocking the reactor on stdio I/O.
134
+
135
+ ## Configuration and Authentication
136
+ - Default via ENV (e.g., tokens/keys). Per‑mount overrides available through `mcp_server env: { … }`.
137
+ - CLI flags can be introduced later in a helper script if needed.
138
+
139
+ ## Backward Compatibility
140
+ - No changes to `airb`. `VSM::Ports::ChatTTY` is a reusable, minimal alternative for new apps.
141
+
142
+ ## Future Extensions (not in Phase 1)
143
+ - Namespaced mounts (`smith.search`) with a tiny router enhancement in Operations.
144
+ - Code generation flow (`vsm mcp import …`) to create durable wrappers.
145
+ - Additional MCP features (prompts/resources/logs) and WebSocket transport.
146
+ - Web interaction port: HTTP chat with customizable UI surfaces.
147
+
148
+ ## Milestones
149
+ 1) Implement ports and client/wrapper (files above), plus optional `bus` injection.
150
+ 2) Add small README/usage and example snippet in `examples/`.
151
+ 3) Manual tests:
152
+ - Start capsule with both ChatTTY and MCP ports; verify no IO collision.
153
+ - Reflect a known MCP server; verify tool listing and calls.
154
+ - Lens shows client/server lanes with corr_id continuity.
155
+ 4) Optional: DSL include/exclude/prefix validation and guardrails.
156
+
157
+ ## Acceptance Criteria
158
+ - Starting a capsule with `VSM::Ports::MCP::ServerStdio` exposes working `tools/list` and `tools/call` on stdio.
159
+ - Starting a capsule with `VSM::Ports::ChatTTY` provides a working chat loop; banner/prompt are overridable without re‑implementing the loop.
160
+ - Running both ports concurrently does not corrupt MCP stdio.
161
+ - Reflecting a remote MCP server via `mcp_server` registers local tool capsules that work with `Intelligence` tool‑calling.
162
+ - Lens displays meaningful events for both client and server paths.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vsm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Werner
@@ -79,20 +79,6 @@ dependencies:
79
79
  - - "~>"
80
80
  - !ruby/object:Gem::Version
81
81
  version: '1.17'
82
- - !ruby/object:Gem::Dependency
83
- name: rubocop
84
- requirement: !ruby/object:Gem::Requirement
85
- requirements:
86
- - - "~>"
87
- - !ruby/object:Gem::Version
88
- version: '1.79'
89
- type: :development
90
- prerelease: false
91
- version_requirements: !ruby/object:Gem::Requirement
92
- requirements:
93
- - - "~>"
94
- - !ruby/object:Gem::Version
95
- version: '1.79'
96
82
  description: |
97
83
  VSM is a small Ruby framework for building agentic systems using a
98
84
  Viable System Model–style architecture. It gives you Capsules: self‑contained components
@@ -100,13 +86,13 @@ description: |
100
86
  Identity) plus an async runtime so many capsules can run concurrently.
101
87
  email:
102
88
  - scott@sublayer.com
103
- executables: []
89
+ executables:
90
+ - vsm
104
91
  extensions: []
105
92
  extra_rdoc_files: []
106
93
  files:
107
94
  - ".claude/settings.local.json"
108
95
  - ".rspec"
109
- - ".rubocop.yml"
110
96
  - CLAUDE.md
111
97
  - LICENSE.txt
112
98
  - README.md
@@ -118,25 +104,58 @@ files:
118
104
  - examples/03_openai_tools.rb
119
105
  - examples/03b_anthropic_tools.rb
120
106
  - examples/03c_gemini_tools.rb
107
+ - examples/05_mcp_server_and_chattty.rb
108
+ - examples/06_mcp_mount_reflection.rb
109
+ - examples/07_connect_claude_mcp.rb
110
+ - examples/08_custom_chattty.rb
111
+ - examples/09_mcp_with_llm_calls.rb
112
+ - examples/10_meta_read_only.rb
113
+ - exe/vsm
121
114
  - lib/vsm.rb
122
115
  - lib/vsm/async_channel.rb
123
116
  - lib/vsm/capsule.rb
117
+ - lib/vsm/cli.rb
124
118
  - lib/vsm/drivers/anthropic/async_driver.rb
125
119
  - lib/vsm/drivers/family.rb
126
120
  - lib/vsm/drivers/gemini/async_driver.rb
127
121
  - lib/vsm/drivers/openai/async_driver.rb
128
122
  - lib/vsm/dsl.rb
123
+ - lib/vsm/dsl_mcp.rb
129
124
  - lib/vsm/executors/fiber_executor.rb
130
125
  - lib/vsm/executors/thread_executor.rb
126
+ - lib/vsm/generator/new_project.rb
127
+ - lib/vsm/generator/templates/Gemfile.erb
128
+ - lib/vsm/generator/templates/README_md.erb
129
+ - lib/vsm/generator/templates/Rakefile.erb
130
+ - lib/vsm/generator/templates/bin_console.erb
131
+ - lib/vsm/generator/templates/bin_setup.erb
132
+ - lib/vsm/generator/templates/exe_name.erb
133
+ - lib/vsm/generator/templates/gemspec.erb
134
+ - lib/vsm/generator/templates/gitignore.erb
135
+ - lib/vsm/generator/templates/lib_name_rb.erb
136
+ - lib/vsm/generator/templates/lib_organism_rb.erb
137
+ - lib/vsm/generator/templates/lib_ports_chat_tty_rb.erb
138
+ - lib/vsm/generator/templates/lib_tools_read_file_rb.erb
139
+ - lib/vsm/generator/templates/lib_version_rb.erb
131
140
  - lib/vsm/homeostat.rb
132
141
  - lib/vsm/lens.rb
133
142
  - lib/vsm/lens/event_hub.rb
134
143
  - lib/vsm/lens/server.rb
135
144
  - lib/vsm/lens/stats.rb
136
145
  - lib/vsm/lens/tui.rb
146
+ - lib/vsm/mcp/client.rb
147
+ - lib/vsm/mcp/jsonrpc.rb
148
+ - lib/vsm/mcp/remote_tool_capsule.rb
137
149
  - lib/vsm/message.rb
150
+ - lib/vsm/meta.rb
151
+ - lib/vsm/meta/snapshot_builder.rb
152
+ - lib/vsm/meta/snapshot_cache.rb
153
+ - lib/vsm/meta/support.rb
154
+ - lib/vsm/meta/tools.rb
138
155
  - lib/vsm/observability/ledger.rb
139
156
  - lib/vsm/port.rb
157
+ - lib/vsm/ports/chat_tty.rb
158
+ - lib/vsm/ports/mcp/server_stdio.rb
140
159
  - lib/vsm/roles/coordination.rb
141
160
  - lib/vsm/roles/governance.rb
142
161
  - lib/vsm/roles/identity.rb
@@ -148,6 +167,7 @@ files:
148
167
  - lib/vsm/tool/descriptor.rb
149
168
  - lib/vsm/version.rb
150
169
  - llms.txt
170
+ - mcp_update.md
151
171
  - sig/vsm.rbs
152
172
  homepage: https://github.com/sublayerapp/vsm
153
173
  licenses:
@@ -169,7 +189,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
169
189
  - !ruby/object:Gem::Version
170
190
  version: '0'
171
191
  requirements: []
172
- rubygems_version: 3.6.9
192
+ rubygems_version: 3.7.2
173
193
  specification_version: 4
174
194
  summary: 'Async, recursive agent framework for Ruby (Viable System Model): capsules,
175
195
  tools-as-capsules, streaming tool calls, and observability.'
data/.rubocop.yml DELETED
@@ -1,8 +0,0 @@
1
- AllCops:
2
- TargetRubyVersion: 3.1
3
-
4
- Style/StringLiterals:
5
- EnforcedStyle: double_quotes
6
-
7
- Style/StringLiteralsInInterpolation:
8
- EnforcedStyle: double_quotes