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.
- checksums.yaml +4 -4
- data/README.md +144 -0
- data/Rakefile +1 -5
- data/examples/01_echo_tool.rb +5 -24
- data/examples/02_openai_streaming.rb +3 -3
- data/examples/02b_anthropic_streaming.rb +1 -4
- data/examples/03b_anthropic_tools.rb +1 -4
- data/examples/05_mcp_server_and_chattty.rb +63 -0
- data/examples/06_mcp_mount_reflection.rb +45 -0
- data/examples/07_connect_claude_mcp.rb +78 -0
- data/examples/08_custom_chattty.rb +63 -0
- data/examples/09_mcp_with_llm_calls.rb +49 -0
- data/examples/10_meta_read_only.rb +56 -0
- data/exe/vsm +17 -0
- data/lib/vsm/async_channel.rb +26 -3
- data/lib/vsm/capsule.rb +2 -0
- data/lib/vsm/cli.rb +78 -0
- data/lib/vsm/dsl.rb +41 -11
- data/lib/vsm/dsl_mcp.rb +36 -0
- data/lib/vsm/generator/new_project.rb +154 -0
- data/lib/vsm/generator/templates/Gemfile.erb +9 -0
- data/lib/vsm/generator/templates/README_md.erb +40 -0
- data/lib/vsm/generator/templates/Rakefile.erb +5 -0
- data/lib/vsm/generator/templates/bin_console.erb +11 -0
- data/lib/vsm/generator/templates/bin_setup.erb +7 -0
- data/lib/vsm/generator/templates/exe_name.erb +34 -0
- data/lib/vsm/generator/templates/gemspec.erb +24 -0
- data/lib/vsm/generator/templates/gitignore.erb +10 -0
- data/lib/vsm/generator/templates/lib_name_rb.erb +9 -0
- data/lib/vsm/generator/templates/lib_organism_rb.erb +44 -0
- data/lib/vsm/generator/templates/lib_ports_chat_tty_rb.erb +12 -0
- data/lib/vsm/generator/templates/lib_tools_read_file_rb.erb +32 -0
- data/lib/vsm/generator/templates/lib_version_rb.erb +6 -0
- data/lib/vsm/mcp/client.rb +80 -0
- data/lib/vsm/mcp/jsonrpc.rb +92 -0
- data/lib/vsm/mcp/remote_tool_capsule.rb +35 -0
- data/lib/vsm/meta/snapshot_builder.rb +121 -0
- data/lib/vsm/meta/snapshot_cache.rb +25 -0
- data/lib/vsm/meta/support.rb +35 -0
- data/lib/vsm/meta/tools.rb +498 -0
- data/lib/vsm/meta.rb +59 -0
- data/lib/vsm/ports/chat_tty.rb +112 -0
- data/lib/vsm/ports/mcp/server_stdio.rb +101 -0
- data/lib/vsm/roles/intelligence.rb +6 -2
- data/lib/vsm/version.rb +1 -1
- data/lib/vsm.rb +10 -0
- data/mcp_update.md +162 -0
- metadata +38 -18
- 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
|
-
|
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
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.
|
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.
|
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.'
|