feat: AD4M AI-assistant runtime — /v1 tool-calling + server-side subsystem (verified e2e) - #875
Draft
HexaField wants to merge 6 commits into
Draft
feat: AD4M AI-assistant runtime — /v1 tool-calling + server-side subsystem (verified e2e)#875HexaField wants to merge 6 commits into
HexaField wants to merge 6 commits into
Conversation
… decoding Makes /v1/chat/completions a real OpenAI tool-calling endpoint for local models: request tools/tool_choice/parallel_tool_calls, response tool_calls + finish_reason "tool_calls" (oneshot + streaming). Local output is held to a schema-valid <tool_call> by compiling each tool's JSON-Schema into a kalosm ArcParser (openai_compat/tool_grammar.rs). Multi-turn tool results fold into prompt text; the no-tools path is unchanged; Cargo.toml unchanged (kalosm-sample via re-export). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
A Rust subsystem in rust-executor that runs AI-assistant turns server-side — persistent, concurrent, surviving client disconnect. Watches perspectives for new WE Message turns, runs the context->model->tools->persist loop reusing the /v1 tool-calling machinery in-process, streams by rewriting Message.content (auto-publishes to WE), and resumes interrupted runs from a durable RunState.
- assistant_runtime/{entities,store,sdna,context,tools,run,registry,mod}
- Subject classes match the WE contract (coasys/we#95): Assistant/Personality/Skill/McpServer in we-root, Thread/Message in the neighbourhood perspective, we:// predicates.
- Built-in perspective/neighbourhood tools in-process; MCP client behind a trait seam (explicit error until rmcp client is wired — no silent stub).
- Boots beside the MCP/REST subsystems, gated on config.enable_assistants (default on).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
McpToolProvider now connects an assistant's configured McpServers via rmcp (stdio -> child process; http/streamable/sse -> streamable-HTTP; websocket unsupported by the pinned rmcp), discovers tools via list_tools -> ToolDef, and dispatches call_tool. Servers that fail to connect are logged and skipped (one bad server never fails the set). Enables rmcp client + transport-*-client features (server features retained). cargo check clean; 4 tools unit tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The assistant-runtime subsystem added Ad4mConfig.enable_assistants (rust-executor); the cli crate constructs Ad4mConfig and must supply it. Adds a --enable-assistants flag on the ad4m-executor bin (mirroring --enable-mcp; default on) and None in the dev/ad4m constructions. Fixes the E0063 that only surfaced building the downstream cli crate. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The run loop passed Assistant.model_id straight to AIService, whose LLM channel is keyed by the registered model uuid — so a friendly name like 'qwen2.5' never matched (Model not found in LLM channel). Resolve via the /v1 model_selector (id | name | 'default') first, the same as the /v1 endpoint. Caught by the live loop end-to-end test on real hardware. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…captured Qwen2.5 responses Adds a ModelBackend seam (AiServiceBackend prod pass-through + FixtureModelBackend test) so the run loop can be driven by recorded responses. Two e2e tests run the FULL subsystem — real in-process PerspectiveInstance, real subject-class read/write, the real loop, real built-in tool execution, real persistence — against raw model text derived from Qwen2.5-7B /v1 responses captured live on Apple Silicon (tests/fixtures/): - plain turn -> assistant message with the captured content, status complete, RunState done - tool loop -> real perspective_add_link executed (sky_color_blue--hasColor-->blue added), post-tool final answer, toolCalls recorded, role:tool message persisted, RunState done 24 assistant_runtime tests pass (22 unit + 2 e2e). Production path unchanged (real backend is a faithful pass-through). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
8 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
AD4M AI-assistant runtime (stacked on #854)
Turns AD4M into a local AI-assistant host — verified end-to-end on Apple Silicon with Qwen2.5-7B.
/v1gains real tool calling; a server-side subsystem runs assistant turns inside the executor (persistent, concurrent, surviving client disconnect). The WE front end is coasys/we#95.Commits
/v1tool/function calling (local, constrained decoding) — requesttools/tool_choice/parallel_tool_calls; responsetool_calls[]+finish_reason:"tool_calls"(oneshot + streaming).openai_compat/tool_grammar.rscompiles each tool's JSON-Schema at runtime into a kalosmArcParserthat masks the sampler, so a local model's output is always a schema-valid<tool_call>(Hermes/Qwen).auto/nonerecovered from text. No-tools path byte-identical;Cargo.tomlunchanged.rust-executor/src/assistant_runtime/) — watches perspectives for WEMessageturns; the loop resolves Thread→Assistant→model→personalities/skills/MCP, assembles context, callsprompt_messages_stream(reusing the grammar), executes tools, folds results back, repeats; streams by rewritingMessage.content(auto-publishes to WE); resumes from a durableRunState.we://predicates match WE exactly. Boots beside MCP/REST, gated on--enable-assistants(default on).McpToolProviderconnects an assistant'sMcpServers (stdio → child process; http/streamable/sse → streamable-HTTP; websocket unsupported),list_tools→ToolDef, dispatchescall_tool; failed servers logged + skipped.--enable-assistantsflag — thread the newAd4mConfigfield through the executor cli crate.AIService— the loop passedAssistant.model_idstraight through, but the LLM channel is keyed by the model uuid, so a name like "qwen2.5" never matched. Resolve via the/v1model_selectorfirst. Caught by the live end-to-end test.Verified end-to-end (live — Apple Silicon, metal,
Qwen2.5-7B-Instruct-Q4_K_M)/v1/chat/completions+tool_choice:"required"→ the real model returned a schema-validget_weather(location, unit)tool call withcontent:nullandfinish_reason:"tool_calls".Messageaswe://links → the runtime resolved everything, called the model, and wrote a real assistant reply (status:complete,RunState:done) back into the perspective — the whole watcher→loop→model→persist path, live.cargo checkclean (pinned Rust 1.92); 34 unit tests pass (13 grammar + 21 runtime).cc @lucksus @data-bot-coasys
🤖 Generated with Claude Code