Skip to content

Commit a529d51

Browse files
committed
release: @ruvector/rvagent-wasm 0.2.0 — ruflo ADR-129 integration support
- Bump version 0.1.0 → 0.2.0 in Cargo.toml and test_version_string - Add CHANGELOG.md with 0.1.0 history and 0.2.0 changes - Update README: correct package name (@ruvector/rvagent-wasm, not rvagent-wasm) - Update README: Node.js target docs, JsModelProvider + addMcpTools examples (ADR-129) - Update README: ruflo/@claude-flow/cli >=3.10.4 compatibility note - Add .github/workflows/publish-rvagent-wasm.yml for one-shot npm publish via CI No Rust logic changes. All ADR-129 gap APIs (JsModelProvider, set_model_provider, addMcpTools, get_state, get_todos, reset, WasmGallery full surface) were already implemented in 0.1.0. Gaps are purely ruflo TypeScript wiring issues. Co-Authored-By: RuFlo <ruv@ruv.net>
1 parent a896934 commit a529d51

6 files changed

Lines changed: 209 additions & 46 deletions

File tree

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
name: Publish @ruvector/rvagent-wasm
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version:
7+
description: 'Version to publish (e.g., 0.2.0)'
8+
required: true
9+
type: string
10+
default: '0.2.0'
11+
dry_run:
12+
description: 'Dry run (build only, no publish)'
13+
required: false
14+
type: boolean
15+
default: false
16+
17+
env:
18+
CARGO_TERM_COLOR: always
19+
20+
jobs:
21+
publish:
22+
name: Build and Publish @ruvector/rvagent-wasm
23+
runs-on: ubuntu-latest
24+
25+
steps:
26+
- uses: actions/checkout@v4
27+
with:
28+
ref: release/rvagent-wasm-0.2.0
29+
30+
- name: Setup Rust
31+
uses: dtolnay/rust-toolchain@stable
32+
with:
33+
targets: wasm32-unknown-unknown
34+
35+
- name: Cache Rust
36+
uses: Swatinem/rust-cache@v2
37+
with:
38+
key: rvagent-wasm-${{ inputs.version }}
39+
40+
- name: Install wasm-pack
41+
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
42+
43+
- name: Verify version matches input
44+
working-directory: crates/rvAgent/rvagent-wasm
45+
run: |
46+
CARGO_VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/version = "//;s/"//')
47+
echo "Cargo.toml version: $CARGO_VERSION"
48+
echo "Input version: ${{ inputs.version }}"
49+
if [ "$CARGO_VERSION" != "${{ inputs.version }}" ]; then
50+
echo "ERROR: Version mismatch!"
51+
exit 1
52+
fi
53+
54+
- name: Run Rust tests
55+
working-directory: crates/rvAgent/rvagent-wasm
56+
run: cargo test
57+
58+
- name: Build WASM (nodejs target)
59+
working-directory: crates/rvAgent/rvagent-wasm
60+
run: wasm-pack build --target nodejs --release
61+
62+
- name: Fix pkg/package.json name and metadata
63+
working-directory: crates/rvAgent/rvagent-wasm/pkg
64+
run: |
65+
# wasm-pack strips the @ruvector/ scope — restore it
66+
node -e "
67+
const pkg = JSON.parse(require('fs').readFileSync('package.json', 'utf8'));
68+
pkg.name = '@ruvector/rvagent-wasm';
69+
pkg.type = 'module';
70+
pkg.sideEffects = ['./snippets/*'];
71+
require('fs').writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n');
72+
"
73+
echo "Fixed package.json:"
74+
cat package.json
75+
76+
- name: Setup Node.js
77+
uses: actions/setup-node@v4
78+
with:
79+
node-version: '20'
80+
registry-url: 'https://registry.npmjs.org'
81+
82+
- name: Publish to npm (dry run)
83+
if: ${{ inputs.dry_run }}
84+
working-directory: crates/rvAgent/rvagent-wasm/pkg
85+
run: npm publish --access public --dry-run
86+
87+
- name: Publish to npm
88+
if: ${{ !inputs.dry_run }}
89+
working-directory: crates/rvAgent/rvagent-wasm/pkg
90+
run: npm publish --access public
91+
env:
92+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
93+
94+
- name: Verify published version
95+
if: ${{ !inputs.dry_run }}
96+
run: |
97+
sleep 10
98+
PUBLISHED=$(npm view @ruvector/rvagent-wasm@${{ inputs.version }} version 2>/dev/null || echo "not found")
99+
echo "Published version: $PUBLISHED"
100+
if [ "$PUBLISHED" != "${{ inputs.version }}" ]; then
101+
echo "WARNING: Could not verify published version (may need more time to propagate)"
102+
fi

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Changelog — @ruvector/rvagent-wasm
2+
3+
All notable changes to this package will be documented here.
4+
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
5+
6+
## [0.2.0] — 2026-05-27
7+
8+
### Added
9+
- `CHANGELOG.md` (this file)
10+
- ruflo / `@claude-flow/cli` integration documentation in README
11+
- ADR-129 reference: documents `JsModelProvider` + `addMcpTools()` wiring patterns
12+
- Explicit Node.js CommonJS usage examples (`require('@ruvector/rvagent-wasm/rvagent_wasm.js')`)
13+
- `WasmRvfBuilder.addMcpTools()` usage example showing ruflo ADR-129 Gap 2 pattern
14+
- `WasmGallery` direct API examples (Gap 3 / Gap 4 methods already implemented)
15+
- Security limits documented: RVF 10 MB max, capability delegation depth 10, gallery 100 custom
16+
17+
### Changed
18+
- Version bumped from 0.1.0 to 0.2.0
19+
- README corrected: package name is `@ruvector/rvagent-wasm` (not unscoped `rvagent-wasm`)
20+
- README corrected: published artifact uses `nodejs` wasm-pack target (not `web`)
21+
- README: import example updated from browser ESM to Node.js CommonJS (primary usage)
22+
- `pkg/package.json` name field fixed to `@ruvector/rvagent-wasm` (scoped)
23+
24+
### No Rust changes
25+
All WASM-level APIs are identical to 0.1.0. The full ADR-129 gap surface
26+
(`JsModelProvider`, `set_model_provider`, `addMcpTools`, `get_state`, `get_todos`, `reset`,
27+
all `WasmGallery` methods) was already implemented in 0.1.0. This release documents and
28+
republishes with corrected metadata.
29+
30+
### Compatible with
31+
- `@claude-flow/cli >= 3.10.4`
32+
- wasm-pack 0.14.x, 0.15.x
33+
- Rust 1.80+, wasm32-unknown-unknown target
34+
35+
---
36+
37+
## [0.1.0] — 2026-03-17
38+
39+
### Added
40+
- Initial release
41+
- `WasmAgent`: agent execution with virtual filesystem, conversation history, `JsModelProvider` callback
42+
- `JsModelProvider`: JS-to-Rust model callback bridge (`async (messagesJson) => string`)
43+
- `WasmRvfBuilder`: RVF cognitive container builder (tools, prompts, skills, mcp_tools, capabilities, orchestrator)
44+
- `WasmGallery`: 6 built-in templates (coder, researcher, tester, reviewer, security, swarm-orchestrator)
45+
- `WasmMcpServer`: MCP JSON-RPC server running in WASM
46+
- Virtual filesystem tools: `read_file`, `write_file`, `edit_file`, `list_files`, `write_todos`
47+
- SHA3-256 checksum on RVF containers
48+
- Security: request size limits, path traversal protection, capability delegation depth limit

crates/rvAgent/rvagent-wasm/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "rvagent-wasm"
3-
version = "0.1.0"
3+
version = "0.2.0"
44
edition = "2021"
55
description = "rvAgent WASM bindings — browser and Node.js agent execution"
66
license = "MIT OR Apache-2.0"

crates/rvAgent/rvagent-wasm/README.md

Lines changed: 56 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,32 @@ WASM bindings for rvAgent — run AI agents entirely in the browser or Node.js.
1313
## Installation
1414

1515
```bash
16-
# Build from source
16+
npm install @ruvector/rvagent-wasm
17+
```
18+
19+
## Building from Source
20+
21+
```bash
1722
cd crates/rvAgent/rvagent-wasm
18-
wasm-pack build --target web
1923

20-
# Or use the pre-built package
21-
npm install rvagent-wasm # (Not yet published)
24+
# Node.js target (used by ruflo / @claude-flow/cli >= 3.10.4)
25+
wasm-pack build --target nodejs --release
26+
27+
# Browser target
28+
wasm-pack build --target web --release
2229
```
2330

2431
## Usage
2532

26-
### WasmAgent
33+
### WasmAgent (Node.js / ruflo integration)
2734

2835
```javascript
29-
import init, { WasmAgent } from 'rvagent-wasm';
36+
// Node.js CommonJS (used by ruflo / @claude-flow/cli)
37+
const { WasmAgent, JsModelProvider } = require('@ruvector/rvagent-wasm/rvagent_wasm.js');
3038

31-
await init();
39+
// Browser ESM
40+
// import init, { WasmAgent } from '@ruvector/rvagent-wasm';
41+
// await init();
3242

3343
// Create an agent
3444
const agent = new WasmAgent(JSON.stringify({
@@ -38,15 +48,13 @@ const agent = new WasmAgent(JSON.stringify({
3848
max_turns: 50
3949
}));
4050

41-
// Connect a model provider (calls your LLM API)
42-
agent.set_model_provider(async (messagesJson) => {
51+
// Wire a real LLM via JsModelProvider (ADR-129 Gap 1 pattern)
52+
const provider = new JsModelProvider(async (messagesJson) => {
4353
const messages = JSON.parse(messagesJson);
44-
const response = await fetch('/api/chat', {
45-
method: 'POST',
46-
body: JSON.stringify({ messages })
47-
});
48-
return (await response.json()).content;
54+
const response = await callYourLLM({ messages });
55+
return JSON.stringify({ role: 'assistant', content: response.content });
4956
});
57+
agent.set_model_provider(provider.complete.bind(provider));
5058

5159
// Send a prompt
5260
const result = await agent.prompt("Write a hello world function");
@@ -66,9 +74,7 @@ console.log(agent.get_todos()); // []
6674
Run an MCP server entirely in the browser:
6775

6876
```javascript
69-
import init, { WasmMcpServer } from 'rvagent-wasm';
70-
71-
await init();
77+
const { WasmMcpServer } = require('@ruvector/rvagent-wasm/rvagent_wasm.js');
7278

7379
const mcp = new WasmMcpServer("rvagent-wasm");
7480

@@ -92,32 +98,24 @@ const result = mcp.call_tool("write_file", JSON.stringify({
9298

9399
### Gallery System
94100

95-
Access built-in agent templates:
101+
Access built-in agent templates directly:
96102

97103
```javascript
104+
const { WasmGallery } = require('@ruvector/rvagent-wasm/rvagent_wasm.js');
105+
106+
const gallery = new WasmGallery();
107+
98108
// List all templates
99-
const templates = mcp.handle_request(JSON.stringify({
100-
jsonrpc: "2.0",
101-
id: 1,
102-
method: "gallery/list",
103-
params: {}
104-
}));
109+
const templates = gallery.list();
105110

106111
// Search templates
107-
const searchResults = mcp.handle_request(JSON.stringify({
108-
jsonrpc: "2.0",
109-
id: 2,
110-
method: "gallery/search",
111-
params: { query: "coding assistant" }
112-
}));
112+
const results = gallery.search("security testing");
113113

114-
// Load a template
115-
const loaded = mcp.handle_request(JSON.stringify({
116-
jsonrpc: "2.0",
117-
id: 3,
118-
method: "gallery/load",
119-
params: { id: "claude-code" }
120-
}));
114+
// Get template details
115+
const coder = gallery.get("coder");
116+
117+
// Load as RVF container
118+
const rvfBytes = gallery.loadRvf("coder"); // Uint8Array
121119
```
122120

123121
## Available Tools
@@ -183,20 +181,22 @@ const loaded = mcp.handle_request(JSON.stringify({
183181
| `name()` | Get server name |
184182
| `version()` | Get server version |
185183

186-
## Building
184+
## Development
187185

188186
```bash
189187
# Install wasm-pack
190188
cargo install wasm-pack
191189

192-
# Build for web
193-
wasm-pack build --target web
190+
# Build for Node.js (published artifact)
191+
wasm-pack build --target nodejs --release
194192

195-
# Build for Node.js
196-
wasm-pack build --target nodejs
193+
# Build for web
194+
wasm-pack build --target web --release
197195

198-
# Run tests
196+
# Run Rust unit tests (61 tests, no WASM runtime needed)
199197
cargo test
198+
199+
# Run WASM tests in browser
200200
wasm-pack test --headless --chrome
201201
```
202202

@@ -226,6 +226,19 @@ rvagent-wasm/
226226
└── rvagent_wasm_bg.wasm
227227
```
228228

229+
## ruflo / @claude-flow/cli Integration
230+
231+
Compatible with `@claude-flow/cli >= 3.10.4`. ADR-129 closes two gaps in the ruflo-side wiring:
232+
233+
- **Gap 1**: Wire `JsModelProvider` so `wasm_agent_prompt` uses a real LLM (not echo stub)
234+
- **Gap 2**: Call `WasmRvfBuilder.addMcpTools()` in `buildRvfContainer` and expose `wasm_agent_compose`
235+
236+
All needed methods (`JsModelProvider`, `set_model_provider`, `addMcpTools`, `get_state`,
237+
`get_todos`, `reset`) are implemented in this WASM package. The gaps are purely TypeScript
238+
wiring issues in the ruflo consumer layer.
239+
240+
See [ADR-129](https://github.com/ruvnet/ruflo/blob/main/v3/docs/adr/ADR-129-rvagent-full-integration.md).
241+
229242
## Related Crates
230243

231244
| Crate | Description |

crates/rvAgent/rvagent-wasm/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ mod tests {
373373

374374
#[test]
375375
fn test_version_string() {
376-
assert_eq!(VERSION, "0.1.0");
376+
assert_eq!(VERSION, "0.2.0");
377377
}
378378

379379
#[test]

0 commit comments

Comments
 (0)