at least it runs

This commit is contained in:
2026-07-09 11:49:28 +08:00
parent 2cf3953bad
commit 964e7e040a
5 changed files with 769 additions and 1 deletions
+2
View File
@@ -3152,10 +3152,12 @@ dependencies = [
name = "module-editor-agent"
version = "0.1.0"
dependencies = [
"platform-llm",
"serde",
"serde_json",
"shared-kernel",
"spacetimedb",
"tokio",
]
[[package]]
@@ -9,7 +9,11 @@ default = []
spacetime-types = ["dep:spacetimedb"]
[dependencies]
platform-llm = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
shared-kernel = { workspace = true }
spacetimedb = { workspace = true, optional = true }
spacetimedb = { workspace = true, optional = true }
[dev-dependencies]
tokio = { workspace = true, features = ["macros", "rt", "rt-multi-thread"] }
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,151 @@
//! Rig-like agent traits for Genarrative generic, LLM-agnostic abstractions for
//! building agents that can be backed by any LLM provider via [`platform_llm`].
//!
//! These traits follow the pattern popularized by the [`rig`](https://github.com/0xPlaygrounds/rig)
//! library: define [`Agent`], [`Tool`], [`AgentMemory`], and [`AgentBuilder`] as generic
//! building blocks, then plug in concrete implementations with `platform_llm::LlmClient`.
use std::future::Future;
use serde::{Deserialize, Serialize};
// ---------------------------------------------------------------------------
// Error
// ---------------------------------------------------------------------------
/// Errors that can occur during agent execution.
#[derive(Debug, Clone)]
pub enum PromptError {
/// LLM completion API call failed.
CompletionError(String),
/// A tool execution failed.
ToolError(String),
/// Maximum conversation turns reached without producing a final response.
MaxTurnsReached { max_turns: usize },
}
impl std::fmt::Display for PromptError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::CompletionError(msg) => write!(f, "completion error: {msg}"),
Self::ToolError(msg) => write!(f, "tool error: {msg}"),
Self::MaxTurnsReached { max_turns } => {
write!(f, "max turns reached: {max_turns}")
}
}
}
}
impl std::error::Error for PromptError {}
// ---------------------------------------------------------------------------
// Core data types
// ---------------------------------------------------------------------------
/// A tool call request emitted by the LLM.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolCall {
pub id: String,
pub name: String,
pub args: serde_json::Value,
}
/// Output of a single prompt cycle.
#[derive(Debug, Clone)]
pub struct PromptOutput {
pub text: String,
pub tool_calls: Vec<ToolCall>,
}
/// Result of executing a single tool call — holds the tool name and the
/// serialized output so the agent loop can feed it back into the conversation.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolCallResult {
pub tool_name: String,
pub output: serde_json::Value,
}
/// Flow control for tool execution within the agent loop.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Flow {
/// Proceed with the tool call.
Continue,
/// Skip this tool call but continue processing other responses.
Skip,
/// Stop the agent execution entirely.
Stop,
}
// ---------------------------------------------------------------------------
// Core traits
// ---------------------------------------------------------------------------
/// Core agent trait: processes a message and returns text output with optional
/// tool calls.
///
/// The generic `Message` type represents the format of conversation messages
/// (e.g., `Vec<LlmMessage>` when integrated with [`platform_llm`]).
pub trait Agent<Message> {
/// Process a prompt and return the output.
fn prompt(
&self,
prompt: impl Into<Message> + Send,
) -> impl Future<Output = Result<PromptOutput, PromptError>> + Send;
/// Called before executing a tool call to decide whether to continue, skip,
/// or stop.
fn before_tool_call(&self, tool_call: &ToolCall) -> Flow {
let _ = tool_call;
Flow::Continue
}
}
/// Conversation memory storing message history.
pub trait AgentMemory<Message> {
/// Returns a reference to the stored messages.
fn get_memory(&self) -> &[Message];
/// Appends a single message to the end of the memory.
fn append_message(&mut self, message: Message);
}
/// Builder pattern for constructing an agent with a system prompt, tools, and
/// memory.
pub trait AgentBuilder<Message, T: Agent<Message>> {
/// Creates a new builder.
fn new() -> Self;
/// Sets the system prompt.
fn system_prompt(self, system_prompt: impl Into<String>) -> Self;
/// Registers a tool.
fn tool(self, tool: impl Tool) -> Self;
/// Sets the conversation memory.
fn memory(self, memory: impl AgentMemory<Message>) -> Self;
/// Builds the final agent.
fn build(self) -> T;
}
/// A tool that can be invoked by an agent.
pub trait Tool: Sized {
/// Unique name identifier for the tool.
const NAME: &'static str;
/// Error type returned by [`Tool::call`].
type Error: std::error::Error + 'static;
/// Arguments type, deserialized from the LLM's tool call JSON.
type Args: for<'a> Deserialize<'a>;
/// Output type from tool execution, serializable for the agent response.
type Output: Serialize;
/// Returns the tool's name at runtime (defaults to [`Tool::NAME`]).
fn tool_name(&self) -> &'static str {
Self::NAME
}
/// Human-readable description of what the tool does.
fn description(&self) -> String;
/// JSON Schema describing the tool's parameters.
fn parameters(&self) -> serde_json::Value;
/// Execute the tool with the given arguments.
fn call(
&self,
args: Self::Args,
) -> impl Future<Output = Result<Self::Output, Self::Error>> + Send;
}
@@ -1,3 +1,4 @@
pub mod agent;
mod application;
mod commands;
mod domain;