From fc6f8d77eba585a5208620b5318a08321da8b368 Mon Sep 17 00:00:00 2001 From: ruv Date: Wed, 27 May 2026 22:45:01 -0400 Subject: [PATCH] =?UTF-8?q?release:=20@ruvector/rvagent-wasm=200.2.0=20?= =?UTF-8?q?=E2=80=94=20ruflo=20ADR-129=20integration=20support?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- .github/workflows/publish-rvagent-wasm.yml | 102 +++++++++++++++++++++ Cargo.lock | 2 +- crates/rvAgent/rvagent-wasm/CHANGELOG.md | 48 ++++++++++ crates/rvAgent/rvagent-wasm/Cargo.toml | 2 +- crates/rvAgent/rvagent-wasm/README.md | 101 +++++++++++--------- crates/rvAgent/rvagent-wasm/src/lib.rs | 2 +- 6 files changed, 210 insertions(+), 47 deletions(-) create mode 100644 .github/workflows/publish-rvagent-wasm.yml create mode 100644 crates/rvAgent/rvagent-wasm/CHANGELOG.md diff --git a/.github/workflows/publish-rvagent-wasm.yml b/.github/workflows/publish-rvagent-wasm.yml new file mode 100644 index 000000000..ebf06e42f --- /dev/null +++ b/.github/workflows/publish-rvagent-wasm.yml @@ -0,0 +1,102 @@ +name: Publish @ruvector/rvagent-wasm + +on: + workflow_dispatch: + inputs: + version: + description: 'Version to publish (e.g., 0.2.0)' + required: true + type: string + default: '0.2.0' + dry_run: + description: 'Dry run (build only, no publish)' + required: false + type: boolean + default: false + +env: + CARGO_TERM_COLOR: always + +jobs: + publish: + name: Build and Publish @ruvector/rvagent-wasm + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + ref: release/rvagent-wasm-0.2.0 + + - name: Setup Rust + uses: dtolnay/rust-toolchain@stable + with: + targets: wasm32-unknown-unknown + + - name: Cache Rust + uses: Swatinem/rust-cache@v2 + with: + key: rvagent-wasm-${{ inputs.version }} + + - name: Install wasm-pack + run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh + + - name: Verify version matches input + working-directory: crates/rvAgent/rvagent-wasm + run: | + CARGO_VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/version = "//;s/"//') + echo "Cargo.toml version: $CARGO_VERSION" + echo "Input version: ${{ inputs.version }}" + if [ "$CARGO_VERSION" != "${{ inputs.version }}" ]; then + echo "ERROR: Version mismatch!" + exit 1 + fi + + - name: Run Rust tests + working-directory: crates/rvAgent/rvagent-wasm + run: cargo test + + - name: Build WASM (nodejs target) + working-directory: crates/rvAgent/rvagent-wasm + run: wasm-pack build --target nodejs --release + + - name: Fix pkg/package.json name and metadata + working-directory: crates/rvAgent/rvagent-wasm/pkg + run: | + # wasm-pack strips the @ruvector/ scope — restore it + node -e " + const pkg = JSON.parse(require('fs').readFileSync('package.json', 'utf8')); + pkg.name = '@ruvector/rvagent-wasm'; + pkg.type = 'module'; + pkg.sideEffects = ['./snippets/*']; + require('fs').writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n'); + " + echo "Fixed package.json:" + cat package.json + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + registry-url: 'https://registry.npmjs.org' + + - name: Publish to npm (dry run) + if: ${{ inputs.dry_run }} + working-directory: crates/rvAgent/rvagent-wasm/pkg + run: npm publish --access public --dry-run + + - name: Publish to npm + if: ${{ !inputs.dry_run }} + working-directory: crates/rvAgent/rvagent-wasm/pkg + run: npm publish --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Verify published version + if: ${{ !inputs.dry_run }} + run: | + sleep 10 + PUBLISHED=$(npm view @ruvector/rvagent-wasm@${{ inputs.version }} version 2>/dev/null || echo "not found") + echo "Published version: $PUBLISHED" + if [ "$PUBLISHED" != "${{ inputs.version }}" ]; then + echo "WARNING: Could not verify published version (may need more time to propagate)" + fi diff --git a/Cargo.lock b/Cargo.lock index 518ebf5cb..078e1b29f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11027,7 +11027,7 @@ dependencies = [ [[package]] name = "rvagent-wasm" -version = "0.1.0" +version = "0.2.0" dependencies = [ "js-sys", "serde", diff --git a/crates/rvAgent/rvagent-wasm/CHANGELOG.md b/crates/rvAgent/rvagent-wasm/CHANGELOG.md new file mode 100644 index 000000000..bd6e7f981 --- /dev/null +++ b/crates/rvAgent/rvagent-wasm/CHANGELOG.md @@ -0,0 +1,48 @@ +# Changelog — @ruvector/rvagent-wasm + +All notable changes to this package will be documented here. +Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). + +## [0.2.0] — 2026-05-27 + +### Added +- `CHANGELOG.md` (this file) +- ruflo / `@claude-flow/cli` integration documentation in README +- ADR-129 reference: documents `JsModelProvider` + `addMcpTools()` wiring patterns +- Explicit Node.js CommonJS usage examples (`require('@ruvector/rvagent-wasm/rvagent_wasm.js')`) +- `WasmRvfBuilder.addMcpTools()` usage example showing ruflo ADR-129 Gap 2 pattern +- `WasmGallery` direct API examples (Gap 3 / Gap 4 methods already implemented) +- Security limits documented: RVF 10 MB max, capability delegation depth 10, gallery 100 custom + +### Changed +- Version bumped from 0.1.0 to 0.2.0 +- README corrected: package name is `@ruvector/rvagent-wasm` (not unscoped `rvagent-wasm`) +- README corrected: published artifact uses `nodejs` wasm-pack target (not `web`) +- README: import example updated from browser ESM to Node.js CommonJS (primary usage) +- `pkg/package.json` name field fixed to `@ruvector/rvagent-wasm` (scoped) + +### No Rust changes +All WASM-level APIs are identical to 0.1.0. The full ADR-129 gap surface +(`JsModelProvider`, `set_model_provider`, `addMcpTools`, `get_state`, `get_todos`, `reset`, +all `WasmGallery` methods) was already implemented in 0.1.0. This release documents and +republishes with corrected metadata. + +### Compatible with +- `@claude-flow/cli >= 3.10.4` +- wasm-pack 0.14.x, 0.15.x +- Rust 1.80+, wasm32-unknown-unknown target + +--- + +## [0.1.0] — 2026-03-17 + +### Added +- Initial release +- `WasmAgent`: agent execution with virtual filesystem, conversation history, `JsModelProvider` callback +- `JsModelProvider`: JS-to-Rust model callback bridge (`async (messagesJson) => string`) +- `WasmRvfBuilder`: RVF cognitive container builder (tools, prompts, skills, mcp_tools, capabilities, orchestrator) +- `WasmGallery`: 6 built-in templates (coder, researcher, tester, reviewer, security, swarm-orchestrator) +- `WasmMcpServer`: MCP JSON-RPC server running in WASM +- Virtual filesystem tools: `read_file`, `write_file`, `edit_file`, `list_files`, `write_todos` +- SHA3-256 checksum on RVF containers +- Security: request size limits, path traversal protection, capability delegation depth limit diff --git a/crates/rvAgent/rvagent-wasm/Cargo.toml b/crates/rvAgent/rvagent-wasm/Cargo.toml index dc015bd29..718e871e4 100644 --- a/crates/rvAgent/rvagent-wasm/Cargo.toml +++ b/crates/rvAgent/rvagent-wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rvagent-wasm" -version = "0.1.0" +version = "0.2.0" edition = "2021" description = "rvAgent WASM bindings — browser and Node.js agent execution" license = "MIT OR Apache-2.0" diff --git a/crates/rvAgent/rvagent-wasm/README.md b/crates/rvAgent/rvagent-wasm/README.md index 8051b0573..5c249999f 100644 --- a/crates/rvAgent/rvagent-wasm/README.md +++ b/crates/rvAgent/rvagent-wasm/README.md @@ -13,22 +13,32 @@ WASM bindings for rvAgent — run AI agents entirely in the browser or Node.js. ## Installation ```bash -# Build from source -cd crates/rvAgent/rvagent-wasm -wasm-pack build --target web +npm install @ruvector/rvagent-wasm +``` -# Or use the pre-built package -npm install rvagent-wasm # (Not yet published) +## Building from Source + +```bash +cd crates/rvAgent/rvagent-wasm + +# Node.js target (used by ruflo / @claude-flow/cli >= 3.10.4) +wasm-pack build --target nodejs --release + +# Browser target +wasm-pack build --target web --release ``` ## Usage -### WasmAgent +### WasmAgent (Node.js / ruflo integration) ```javascript -import init, { WasmAgent } from 'rvagent-wasm'; +// Node.js CommonJS (used by ruflo / @claude-flow/cli) +const { WasmAgent, JsModelProvider } = require('@ruvector/rvagent-wasm/rvagent_wasm.js'); -await init(); +// Browser ESM +// import init, { WasmAgent } from '@ruvector/rvagent-wasm'; +// await init(); // Create an agent const agent = new WasmAgent(JSON.stringify({ @@ -38,15 +48,13 @@ const agent = new WasmAgent(JSON.stringify({ max_turns: 50 })); -// Connect a model provider (calls your LLM API) -agent.set_model_provider(async (messagesJson) => { +// Wire a real LLM via JsModelProvider (ADR-129 Gap 1 pattern) +const provider = new JsModelProvider(async (messagesJson) => { const messages = JSON.parse(messagesJson); - const response = await fetch('/api/chat', { - method: 'POST', - body: JSON.stringify({ messages }) - }); - return (await response.json()).content; + const response = await callYourLLM({ messages }); + return JSON.stringify({ role: 'assistant', content: response.content }); }); +agent.set_model_provider(provider.complete.bind(provider)); // Send a prompt const result = await agent.prompt("Write a hello world function"); @@ -66,9 +74,7 @@ console.log(agent.get_todos()); // [] Run an MCP server entirely in the browser: ```javascript -import init, { WasmMcpServer } from 'rvagent-wasm'; - -await init(); +const { WasmMcpServer } = require('@ruvector/rvagent-wasm/rvagent_wasm.js'); const mcp = new WasmMcpServer("rvagent-wasm"); @@ -92,32 +98,24 @@ const result = mcp.call_tool("write_file", JSON.stringify({ ### Gallery System -Access built-in agent templates: +Access built-in agent templates directly: ```javascript +const { WasmGallery } = require('@ruvector/rvagent-wasm/rvagent_wasm.js'); + +const gallery = new WasmGallery(); + // List all templates -const templates = mcp.handle_request(JSON.stringify({ - jsonrpc: "2.0", - id: 1, - method: "gallery/list", - params: {} -})); +const templates = gallery.list(); // Search templates -const searchResults = mcp.handle_request(JSON.stringify({ - jsonrpc: "2.0", - id: 2, - method: "gallery/search", - params: { query: "coding assistant" } -})); +const results = gallery.search("security testing"); -// Load a template -const loaded = mcp.handle_request(JSON.stringify({ - jsonrpc: "2.0", - id: 3, - method: "gallery/load", - params: { id: "claude-code" } -})); +// Get template details +const coder = gallery.get("coder"); + +// Load as RVF container +const rvfBytes = gallery.loadRvf("coder"); // Uint8Array ``` ## Available Tools @@ -183,20 +181,22 @@ const loaded = mcp.handle_request(JSON.stringify({ | `name()` | Get server name | | `version()` | Get server version | -## Building +## Development ```bash # Install wasm-pack cargo install wasm-pack +# Build for Node.js (published artifact) +wasm-pack build --target nodejs --release + # Build for web -wasm-pack build --target web +wasm-pack build --target web --release -# Build for Node.js -wasm-pack build --target nodejs - -# Run tests +# Run Rust unit tests (61 tests, no WASM runtime needed) cargo test + +# Run WASM tests in browser wasm-pack test --headless --chrome ``` @@ -226,6 +226,19 @@ rvagent-wasm/ └── rvagent_wasm_bg.wasm ``` +## ruflo / @claude-flow/cli Integration + +Compatible with `@claude-flow/cli >= 3.10.4`. ADR-129 closes two gaps in the ruflo-side wiring: + +- **Gap 1**: Wire `JsModelProvider` so `wasm_agent_prompt` uses a real LLM (not echo stub) +- **Gap 2**: Call `WasmRvfBuilder.addMcpTools()` in `buildRvfContainer` and expose `wasm_agent_compose` + +All needed methods (`JsModelProvider`, `set_model_provider`, `addMcpTools`, `get_state`, +`get_todos`, `reset`) are implemented in this WASM package. The gaps are purely TypeScript +wiring issues in the ruflo consumer layer. + +See [ADR-129](https://github.com/ruvnet/ruflo/blob/main/v3/docs/adr/ADR-129-rvagent-full-integration.md). + ## Related Crates | Crate | Description | diff --git a/crates/rvAgent/rvagent-wasm/src/lib.rs b/crates/rvAgent/rvagent-wasm/src/lib.rs index 5e4169d6e..c080ccee2 100644 --- a/crates/rvAgent/rvagent-wasm/src/lib.rs +++ b/crates/rvAgent/rvagent-wasm/src/lib.rs @@ -375,7 +375,7 @@ mod tests { #[test] fn test_version_string() { - assert_eq!(VERSION, "0.1.0"); + assert_eq!(VERSION, "0.2.0"); } #[test]