develop #3
60
Cargo.lock
generated
60
Cargo.lock
generated
|
|
@ -631,6 +631,36 @@ version = "0.8.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77"
|
||||
|
||||
[[package]]
|
||||
name = "llm-worker"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"clap",
|
||||
"dotenv",
|
||||
"eventsource-stream",
|
||||
"futures",
|
||||
"llm-worker-macros",
|
||||
"reqwest",
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "llm-worker-macros"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.29"
|
||||
|
|
@ -1567,36 +1597,6 @@ version = "0.46.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
|
||||
|
||||
[[package]]
|
||||
name = "worker"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"clap",
|
||||
"dotenv",
|
||||
"eventsource-stream",
|
||||
"futures",
|
||||
"reqwest",
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"worker-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "worker-macros"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "writeable"
|
||||
version = "0.6.2"
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
[workspace]
|
||||
resolver = "2"
|
||||
members = [
|
||||
"worker",
|
||||
"worker-macros",
|
||||
"llm-worker",
|
||||
"llm-worker-macros",
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
|
|
|
|||
35
README.md
35
README.md
|
|
@ -1,5 +1,36 @@
|
|||
# llm-worker-rs
|
||||
# llm-worker
|
||||
|
||||
Rusty, Efficient, and Agentic LLM Client Library
|
||||
|
||||
`llm-worker-rs` is a Rust library designed for building robust and efficient LLM applications. It unifies interactions with multiple LLM providers (Anthropic, Gemini, OpenAI, Ollama) under a single abstraction, with type-safe state management, efficient context caching, and a powerful event-driven architecture.
|
||||
`llm-worker` is a Rust library for building autonomous LLM-powered systems. Define tools, register hooks, and let the Worker handle the agentic loop — tool calls are executed automatically until the task completes.
|
||||
|
||||
## Features
|
||||
|
||||
- Autonomous Execution: The `Worker` manages the full request-response-tool cycle. You provide tools and input; it loops until done.
|
||||
- Multi-Provider Support: Unified interface for Anthropic, Gemini, OpenAI, and Ollama.
|
||||
- Tool System: Define tools as async functions. The Worker automatically parses LLM tool calls, executes them in parallel, and feeds results back.
|
||||
- Hook System: Intercept execution flow with `before_tool_call`, `after_tool_call`, and `on_turn_end` hooks for validation, logging, or self-correction.
|
||||
- Event-Driven Streaming: Subscribe to real-time events (text deltas, tool calls, usage) for responsive UIs.
|
||||
- Cache-Aware State Management: Type-state pattern (`Mutable` → `Locked`) ensures KV cache efficiency by protecting the conversation prefix.
|
||||
|
||||
## Quick Start
|
||||
|
||||
```rust
|
||||
use llm_worker::{Worker, Message};
|
||||
|
||||
// Create a Worker with your LLM client
|
||||
let mut worker = Worker::new(client)
|
||||
.system_prompt("You are a helpful assistant.");
|
||||
|
||||
// Register tools (optional)
|
||||
worker.register_tool(SearchTool::new());
|
||||
worker.register_tool(CalculatorTool::new());
|
||||
|
||||
// Run — the Worker handles tool calls automatically
|
||||
let history = worker.run("What is 2+2?").await?;
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
[package]
|
||||
name = "worker-macros"
|
||||
name = "llm-worker-macros"
|
||||
version = "0.1.0"
|
||||
publish.workspace = true
|
||||
edition.workspace = true
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
//! worker-macros - Tool生成用手続きマクロ
|
||||
//! llm-worker-macros - Tool生成用手続きマクロ
|
||||
//!
|
||||
//! `#[tool_registry]` と `#[tool]` マクロを提供し、
|
||||
//! ユーザー定義のメソッドから `Tool` トレイト実装を自動生成する。
|
||||
|
|
@ -193,7 +193,7 @@ fn generate_tool_impl(self_ty: &Type, method: &syn::ImplItemFn) -> proc_macro2::
|
|||
quote! {
|
||||
match result {
|
||||
Ok(val) => Ok(format!("{:?}", val)),
|
||||
Err(e) => Err(::worker::tool::ToolError::ExecutionFailed(format!("{}", e))),
|
||||
Err(e) => Err(::llm_worker::tool::ToolError::ExecutionFailed(format!("{}", e))),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -230,7 +230,7 @@ fn generate_tool_impl(self_ty: &Type, method: &syn::ImplItemFn) -> proc_macro2::
|
|||
} else {
|
||||
quote! {
|
||||
let args: #args_struct_name = serde_json::from_str(input_json)
|
||||
.map_err(|e| ::worker::tool::ToolError::InvalidArgument(e.to_string()))?;
|
||||
.map_err(|e| ::llm_worker::tool::ToolError::InvalidArgument(e.to_string()))?;
|
||||
|
||||
let result = self.ctx.#method_name(#(#arg_names),*)#awaiter;
|
||||
#result_handling
|
||||
|
|
@ -246,7 +246,7 @@ fn generate_tool_impl(self_ty: &Type, method: &syn::ImplItemFn) -> proc_macro2::
|
|||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl ::worker::tool::Tool for #tool_struct_name {
|
||||
impl ::llm_worker::tool::Tool for #tool_struct_name {
|
||||
fn name(&self) -> &str {
|
||||
#tool_name
|
||||
}
|
||||
|
|
@ -260,7 +260,7 @@ fn generate_tool_impl(self_ty: &Type, method: &syn::ImplItemFn) -> proc_macro2::
|
|||
serde_json::to_value(schema).unwrap_or(serde_json::json!({}))
|
||||
}
|
||||
|
||||
async fn execute(&self, input_json: &str) -> Result<String, ::worker::tool::ToolError> {
|
||||
async fn execute(&self, input_json: &str) -> Result<String, ::llm_worker::tool::ToolError> {
|
||||
#execute_body
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
[package]
|
||||
name = "worker"
|
||||
name = "llm-worker"
|
||||
description = ""
|
||||
version = "0.1.0"
|
||||
publish.workspace = true
|
||||
|
|
@ -17,7 +17,7 @@ futures = "0.3"
|
|||
tokio = { version = "1.49", features = ["macros", "rt-multi-thread"] }
|
||||
reqwest = { version = "0.13.1", default-features = false, features = ["stream", "json", "native-tls"] }
|
||||
eventsource-stream = "0.2"
|
||||
worker-macros = { path = "../worker-macros", version = "0.1" }
|
||||
llm-worker-macros = { path = "../llm-worker-macros", version = "0.1" }
|
||||
|
||||
[dev-dependencies]
|
||||
clap = { version = "4.5", features = ["derive", "env"] }
|
||||
|
|
@ -20,9 +20,9 @@ mod recorder;
|
|||
mod scenarios;
|
||||
|
||||
use clap::{Parser, ValueEnum};
|
||||
use worker::llm_client::providers::anthropic::AnthropicClient;
|
||||
use worker::llm_client::providers::gemini::GeminiClient;
|
||||
use worker::llm_client::providers::openai::OpenAIClient;
|
||||
use llm_worker::llm_client::providers::anthropic::AnthropicClient;
|
||||
use llm_worker::llm_client::providers::gemini::GeminiClient;
|
||||
use llm_worker::llm_client::providers::openai::OpenAIClient;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
|
|
@ -101,7 +101,7 @@ async fn run_scenario_with_ollama(
|
|||
subdir: &str,
|
||||
model: Option<String>,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
use worker::llm_client::providers::ollama::OllamaClient;
|
||||
use llm_worker::llm_client::providers::ollama::OllamaClient;
|
||||
// Ollama typically runs local, no key needed or placeholder
|
||||
let model = model.as_deref().unwrap_or("llama3"); // default example
|
||||
let client = OllamaClient::new(model); // base_url placeholder, handled by client default
|
||||
|
|
@ -8,7 +8,7 @@ use std::path::Path;
|
|||
use std::time::{Instant, SystemTime, UNIX_EPOCH};
|
||||
|
||||
use futures::StreamExt;
|
||||
use worker::llm_client::{LlmClient, Request};
|
||||
use llm_worker::llm_client::{LlmClient, Request};
|
||||
|
||||
/// 記録されたイベント
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
//!
|
||||
//! 各シナリオのリクエストと出力ファイル名を定義
|
||||
|
||||
use worker::llm_client::{Request, ToolDefinition};
|
||||
use llm_worker::llm_client::{Request, ToolDefinition};
|
||||
|
||||
/// テストシナリオ
|
||||
pub struct TestScenario {
|
||||
|
|
@ -39,7 +39,7 @@ use tracing::info;
|
|||
use tracing_subscriber::EnvFilter;
|
||||
|
||||
use clap::{Parser, ValueEnum};
|
||||
use worker::{
|
||||
use llm_worker::{
|
||||
Worker,
|
||||
hook::{ControlFlow, HookError, ToolResult, WorkerHook},
|
||||
llm_client::{
|
||||
|
|
@ -51,7 +51,7 @@ use worker::{
|
|||
},
|
||||
timeline::{Handler, TextBlockEvent, TextBlockKind, ToolUseBlockEvent, ToolUseBlockKind},
|
||||
};
|
||||
use worker_macros::tool_registry;
|
||||
use llm_worker_macros::tool_registry;
|
||||
|
||||
// 必要なマクロ展開用インポート
|
||||
use schemars;
|
||||
|
|
@ -32,7 +32,7 @@ pub trait Kind {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// use worker::timeline::{Handler, TextBlockEvent, TextBlockKind};
|
||||
/// use llm_worker::timeline::{Handler, TextBlockEvent, TextBlockKind};
|
||||
///
|
||||
/// struct TextCollector {
|
||||
/// texts: Vec<String>,
|
||||
|
|
@ -109,8 +109,8 @@ pub enum HookError {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// use worker::hook::{ControlFlow, HookError, ToolCall, TurnResult, WorkerHook};
|
||||
/// use worker::Message;
|
||||
/// use llm_worker::hook::{ControlFlow, HookError, ToolCall, TurnResult, WorkerHook};
|
||||
/// use llm_worker::Message;
|
||||
///
|
||||
/// struct ValidationHook;
|
||||
///
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
//! worker - LLMワーカーライブラリ
|
||||
//! llm-worker - LLMワーカーライブラリ
|
||||
//!
|
||||
//! LLMとの対話を管理するコンポーネントを提供します。
|
||||
//!
|
||||
|
|
@ -12,14 +12,14 @@
|
|||
//! # Quick Start
|
||||
//!
|
||||
//! ```ignore
|
||||
//! use worker::{Worker, Message};
|
||||
//! use llm_worker::{Worker, Message};
|
||||
//!
|
||||
//! // Workerを作成
|
||||
//! let mut worker = Worker::new(client)
|
||||
//! .system_prompt("You are a helpful assistant.");
|
||||
//!
|
||||
//! // ツールを登録(オプション)
|
||||
//! use worker::tool::Tool;
|
||||
//! use llm_worker::tool::Tool;
|
||||
//! worker.register_tool(my_tool);
|
||||
//!
|
||||
//! // 対話を実行
|
||||
|
|
@ -20,7 +20,7 @@ pub enum Role {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// use worker::Message;
|
||||
/// use llm_worker::Message;
|
||||
///
|
||||
/// // ユーザーメッセージ
|
||||
/// let user_msg = Message::user("Hello!");
|
||||
|
|
@ -79,7 +79,7 @@ impl Message {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// use worker::Message;
|
||||
/// use llm_worker::Message;
|
||||
/// let msg = Message::user("こんにちは");
|
||||
/// ```
|
||||
pub fn user(content: impl Into<String>) -> Self {
|
||||
|
|
@ -24,7 +24,7 @@ mod private {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// use worker::Worker;
|
||||
/// use llm_worker::Worker;
|
||||
///
|
||||
/// let mut worker = Worker::new(client)
|
||||
/// .system_prompt("You are helpful.");
|
||||
|
|
@ -33,8 +33,8 @@ use crate::{
|
|||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// use worker::subscriber::WorkerSubscriber;
|
||||
/// use worker::timeline::TextBlockEvent;
|
||||
/// use llm_worker::subscriber::WorkerSubscriber;
|
||||
/// use llm_worker::timeline::TextBlockEvent;
|
||||
///
|
||||
/// struct StreamPrinter;
|
||||
///
|
||||
|
|
@ -328,7 +328,7 @@ where
|
|||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// use worker::{Timeline, Handler, TextBlockKind, TextBlockEvent};
|
||||
/// use llm_worker::{Timeline, Handler, TextBlockKind, TextBlockEvent};
|
||||
///
|
||||
/// struct MyHandler;
|
||||
/// impl Handler<TextBlockKind> for MyHandler {
|
||||
|
|
@ -31,7 +31,7 @@ pub enum ToolError {
|
|||
/// 通常は`#[tool]`マクロを使用して自動実装します:
|
||||
///
|
||||
/// ```ignore
|
||||
/// use worker::tool;
|
||||
/// use llm_worker::tool;
|
||||
///
|
||||
/// #[tool(description = "Search the web for information")]
|
||||
/// async fn search(query: String) -> String {
|
||||
|
|
@ -43,7 +43,7 @@ pub enum ToolError {
|
|||
/// # 手動実装
|
||||
///
|
||||
/// ```ignore
|
||||
/// use worker::tool::{Tool, ToolError};
|
||||
/// use llm_worker::tool::{Tool, ToolError};
|
||||
/// use serde_json::{json, Value};
|
||||
///
|
||||
/// struct MyTool;
|
||||
|
|
@ -95,7 +95,7 @@ impl<S: WorkerSubscriber + 'static> TurnNotifier for SubscriberTurnNotifier<S> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// use worker::{Worker, Message};
|
||||
/// use llm_worker::{Worker, Message};
|
||||
///
|
||||
/// // Workerを作成してツールを登録
|
||||
/// let mut worker = Worker::new(client)
|
||||
|
|
@ -163,7 +163,7 @@ impl<C: LlmClient, S: WorkerState> Worker<C, S> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// use worker::{Worker, WorkerSubscriber, TextBlockEvent};
|
||||
/// use llm_worker::{Worker, WorkerSubscriber, TextBlockEvent};
|
||||
///
|
||||
/// struct MyPrinter;
|
||||
/// impl WorkerSubscriber for MyPrinter {
|
||||
|
|
@ -211,7 +211,7 @@ impl<C: LlmClient, S: WorkerState> Worker<C, S> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// use worker::Worker;
|
||||
/// use llm_worker::Worker;
|
||||
/// use my_tools::SearchTool;
|
||||
///
|
||||
/// worker.register_tool(SearchTool::new());
|
||||
|
|
@ -236,7 +236,7 @@ impl<C: LlmClient, S: WorkerState> Worker<C, S> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// use worker::{Worker, WorkerHook, ControlFlow, ToolCall};
|
||||
/// use llm_worker::{Worker, WorkerHook, ControlFlow, ToolCall};
|
||||
///
|
||||
/// struct LoggingHook;
|
||||
///
|
||||
|
|
@ -8,9 +8,9 @@ use std::sync::{Arc, Mutex};
|
|||
|
||||
use async_trait::async_trait;
|
||||
use futures::Stream;
|
||||
use worker::llm_client::event::{BlockType, DeltaContent, Event};
|
||||
use worker::llm_client::{ClientError, LlmClient, Request};
|
||||
use worker::timeline::{Handler, TextBlockEvent, TextBlockKind, Timeline};
|
||||
use llm_worker::llm_client::event::{BlockType, DeltaContent, Event};
|
||||
use llm_worker::llm_client::{ClientError, LlmClient, Request};
|
||||
use llm_worker::timeline::{Handler, TextBlockEvent, TextBlockKind, Timeline};
|
||||
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
|
|
@ -267,7 +267,7 @@ pub fn assert_timeline_integration(subdir: &str) {
|
|||
});
|
||||
|
||||
for event in &events {
|
||||
let timeline_event: worker::timeline::event::Event = event.clone().into();
|
||||
let timeline_event: llm_worker::timeline::event::Event = event.clone().into();
|
||||
timeline.dispatch(&timeline_event);
|
||||
}
|
||||
|
||||
|
|
@ -7,10 +7,10 @@ use std::sync::atomic::{AtomicUsize, Ordering};
|
|||
use std::time::{Duration, Instant};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use worker::Worker;
|
||||
use worker::hook::{ControlFlow, HookError, ToolCall, ToolResult, WorkerHook};
|
||||
use worker::llm_client::event::{Event, ResponseStatus, StatusEvent};
|
||||
use worker::tool::{Tool, ToolError};
|
||||
use llm_worker::Worker;
|
||||
use llm_worker::hook::{ControlFlow, HookError, ToolCall, ToolResult, WorkerHook};
|
||||
use llm_worker::llm_client::event::{Event, ResponseStatus, StatusEvent};
|
||||
use llm_worker::tool::{Tool, ToolError};
|
||||
|
||||
mod common;
|
||||
use common::MockLlmClient;
|
||||
|
|
@ -7,12 +7,12 @@ mod common;
|
|||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use common::MockLlmClient;
|
||||
use worker::Worker;
|
||||
use worker::hook::ToolCall;
|
||||
use worker::llm_client::event::{Event, ResponseStatus, StatusEvent as ClientStatusEvent};
|
||||
use worker::subscriber::WorkerSubscriber;
|
||||
use worker::timeline::event::{ErrorEvent, StatusEvent, UsageEvent};
|
||||
use worker::timeline::{TextBlockEvent, ToolUseBlockEvent};
|
||||
use llm_worker::Worker;
|
||||
use llm_worker::hook::ToolCall;
|
||||
use llm_worker::llm_client::event::{Event, ResponseStatus, StatusEvent as ClientStatusEvent};
|
||||
use llm_worker::subscriber::WorkerSubscriber;
|
||||
use llm_worker::timeline::event::{ErrorEvent, StatusEvent, UsageEvent};
|
||||
use llm_worker::timeline::{TextBlockEvent, ToolUseBlockEvent};
|
||||
|
||||
// =============================================================================
|
||||
// Test Subscriber
|
||||
|
|
@ -9,8 +9,8 @@ use std::sync::atomic::{AtomicUsize, Ordering};
|
|||
use schemars;
|
||||
use serde;
|
||||
|
||||
use worker::tool::Tool;
|
||||
use worker_macros::tool_registry;
|
||||
use llm_worker::tool::Tool;
|
||||
use llm_worker_macros::tool_registry;
|
||||
|
||||
// =============================================================================
|
||||
// Test: Basic Tool Generation
|
||||
|
|
@ -11,8 +11,8 @@ use std::sync::atomic::{AtomicUsize, Ordering};
|
|||
|
||||
use async_trait::async_trait;
|
||||
use common::MockLlmClient;
|
||||
use worker::Worker;
|
||||
use worker::tool::{Tool, ToolError};
|
||||
use llm_worker::Worker;
|
||||
use llm_worker::tool::{Tool, ToolError};
|
||||
|
||||
/// フィクスチャディレクトリのパス
|
||||
fn fixtures_dir() -> std::path::PathBuf {
|
||||
|
|
@ -100,7 +100,7 @@ fn test_mock_client_from_fixture() {
|
|||
/// fixtureファイルを使わず、プログラムでイベントを構築してクライアントを作成する。
|
||||
#[test]
|
||||
fn test_mock_client_from_events() {
|
||||
use worker::llm_client::event::Event;
|
||||
use llm_worker::llm_client::event::Event;
|
||||
|
||||
// 直接イベントを指定
|
||||
let events = vec![
|
||||
|
|
@ -178,7 +178,7 @@ async fn test_worker_tool_call() {
|
|||
/// テストの独立性を高め、外部ファイルへの依存を排除したい場合に有用。
|
||||
#[tokio::test]
|
||||
async fn test_worker_with_programmatic_events() {
|
||||
use worker::llm_client::event::{Event, ResponseStatus, StatusEvent};
|
||||
use llm_worker::llm_client::event::{Event, ResponseStatus, StatusEvent};
|
||||
|
||||
// プログラムでイベントシーケンスを構築
|
||||
let events = vec![
|
||||
|
|
@ -205,8 +205,8 @@ async fn test_worker_with_programmatic_events() {
|
|||
/// id, name, input(JSON)を正しく抽出できることを検証する。
|
||||
#[tokio::test]
|
||||
async fn test_tool_call_collector_integration() {
|
||||
use worker::llm_client::event::Event;
|
||||
use worker::timeline::{Timeline, ToolCallCollector};
|
||||
use llm_worker::llm_client::event::Event;
|
||||
use llm_worker::timeline::{Timeline, ToolCallCollector};
|
||||
|
||||
// ToolUseブロックを含むイベントシーケンス
|
||||
let events = vec![
|
||||
|
|
@ -222,7 +222,7 @@ async fn test_tool_call_collector_integration() {
|
|||
|
||||
// イベントをディスパッチ
|
||||
for event in &events {
|
||||
let timeline_event: worker::timeline::event::Event = event.clone().into();
|
||||
let timeline_event: llm_worker::timeline::event::Event = event.clone().into();
|
||||
timeline.dispatch(&timeline_event);
|
||||
}
|
||||
|
||||
|
|
@ -6,9 +6,9 @@
|
|||
mod common;
|
||||
|
||||
use common::MockLlmClient;
|
||||
use worker::Worker;
|
||||
use worker::llm_client::event::{Event, ResponseStatus, StatusEvent};
|
||||
use worker::{Message, MessageContent};
|
||||
use llm_worker::Worker;
|
||||
use llm_worker::llm_client::event::{Event, ResponseStatus, StatusEvent};
|
||||
use llm_worker::{Message, MessageContent};
|
||||
|
||||
// =============================================================================
|
||||
// Mutable状態のテスト
|
||||
Loading…
Reference in New Issue
Block a user