0.5.1: MCPの設定読み込みの削除
This commit is contained in:
+41
-42
@@ -31,7 +31,7 @@ pub struct HookManager {
|
||||
pub enum HookEvent {
|
||||
OnMessageSend,
|
||||
PreToolUse,
|
||||
PostToolUse,
|
||||
PostToolUse,
|
||||
OnTurnCompleted,
|
||||
}
|
||||
```
|
||||
@@ -181,10 +181,10 @@ impl HookContext {
|
||||
impl HookContext {
|
||||
// ストリーミング中にメッセージを送信
|
||||
pub fn stream_message(&self, content: String, role: Role);
|
||||
|
||||
|
||||
// ストリーミング中にシステム通知を送信
|
||||
pub fn stream_system_message(&self, content: String);
|
||||
|
||||
|
||||
// ストリーミング中にデバッグ情報を送信
|
||||
pub fn stream_debug(&self, title: String, data: serde_json::Value);
|
||||
}
|
||||
@@ -198,22 +198,22 @@ Hook関数は以下のいずれかの結果を返す必要があります:
|
||||
pub enum HookResult {
|
||||
// 処理を続行
|
||||
Continue,
|
||||
|
||||
|
||||
// コンテンツを変更して続行
|
||||
ModifyContent(String),
|
||||
|
||||
|
||||
// システムメッセージを追加して続行
|
||||
AddMessage(String, Role),
|
||||
|
||||
|
||||
// 複数のメッセージを追加して続行
|
||||
AddMessages(Vec<Message>),
|
||||
|
||||
|
||||
// ターンを強制完了
|
||||
Complete,
|
||||
|
||||
|
||||
// エラーでターンを終了
|
||||
Error(String),
|
||||
|
||||
|
||||
// Hook処理をスキップ(デバッグ用)
|
||||
Skip,
|
||||
}
|
||||
@@ -282,7 +282,7 @@ pub async fn dangerous_command_hook(context: HookContext) -> HookResult {
|
||||
if let Some(args) = &context.tool_args {
|
||||
if let Some(command) = args.get("command").and_then(|v| v.as_str()) {
|
||||
let dangerous_commands = ["rm -rf", "format", "dd if="];
|
||||
|
||||
|
||||
for dangerous in &dangerous_commands {
|
||||
if command.contains(dangerous) {
|
||||
return HookResult::Error(format!(
|
||||
@@ -293,7 +293,7 @@ pub async fn dangerous_command_hook(context: HookContext) -> HookResult {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HookResult::Continue
|
||||
}
|
||||
```
|
||||
@@ -326,7 +326,7 @@ pub async fn auto_read_hook(mut context: HookContext) -> HookResult {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HookResult::Continue
|
||||
}
|
||||
```
|
||||
@@ -361,7 +361,7 @@ worker.register_hooks(tui_hooks);
|
||||
```rust
|
||||
// 実行順序の例
|
||||
worker.register_hook(Box::new(TimestampHook)); // 1番目
|
||||
worker.register_hook(Box::new(ValidationHook)); // 2番目
|
||||
worker.register_hook(Box::new(ValidationHook)); // 2番目
|
||||
worker.register_hook(Box::new(LoggingHook)); // 3番目
|
||||
```
|
||||
|
||||
@@ -375,13 +375,13 @@ worker.register_hook(Box::new(LoggingHook)); // 3番目
|
||||
impl Worker {
|
||||
// Hook一覧を取得
|
||||
pub fn list_hooks(&self) -> Vec<(&str, &str)>; // (name, hook_type)
|
||||
|
||||
|
||||
// 特定のHookを削除
|
||||
pub fn remove_hook(&mut self, hook_name: &str) -> bool;
|
||||
|
||||
|
||||
// フェーズ別Hookを削除
|
||||
pub fn remove_hooks_by_phase(&mut self, hook_type: &str);
|
||||
|
||||
|
||||
// すべてのHookをクリア
|
||||
pub fn clear_hooks(&mut self);
|
||||
}
|
||||
@@ -395,16 +395,16 @@ impl Worker {
|
||||
// worker/src/lib.rs の process_with_shared_state より
|
||||
stream! {
|
||||
// ... LLM応答処理中 ...
|
||||
|
||||
|
||||
// ツール呼び出し検出時
|
||||
if let Some(tool_calls) = &response.tool_calls {
|
||||
for tool_call in tool_calls {
|
||||
// PreToolUse hooks 実行
|
||||
let (context, hook_result) = execute_hooks(
|
||||
HookEvent::PreToolUse,
|
||||
HookEvent::PreToolUse,
|
||||
tool_call.name.clone()
|
||||
).await;
|
||||
|
||||
|
||||
match hook_result {
|
||||
HookResult::Error(msg) => {
|
||||
yield Ok(StreamEvent::Error(msg));
|
||||
@@ -413,16 +413,16 @@ stream! {
|
||||
HookResult::Complete => break,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
||||
// ツール実行
|
||||
let result = execute_tool(tool_call).await;
|
||||
|
||||
|
||||
// PostToolUse hooks 実行(ストリーミング中)
|
||||
let (context, hook_result) = execute_hooks(
|
||||
HookEvent::PostToolUse,
|
||||
tool_call.name.clone()
|
||||
).await;
|
||||
|
||||
|
||||
// Hook結果を即座にストリーミング
|
||||
if let HookResult::AddMessage(msg, role) = hook_result {
|
||||
yield Ok(StreamEvent::HookMessage {
|
||||
@@ -468,13 +468,13 @@ pub async fn performance_aware_hook(context: HookContext) -> HookResult {
|
||||
// 大きなコンテンツの場合はスキップ
|
||||
return HookResult::Skip;
|
||||
}
|
||||
|
||||
|
||||
// 非同期処理は適切にawaitする
|
||||
let result = tokio::time::timeout(
|
||||
Duration::from_secs(5),
|
||||
expensive_operation(&context)
|
||||
).await;
|
||||
|
||||
|
||||
match result {
|
||||
Ok(output) => HookResult::AddMessage(output, Role::System),
|
||||
Err(_) => {
|
||||
@@ -495,20 +495,20 @@ pub async fn configurable_hook(mut context: HookContext) -> HookResult {
|
||||
.unwrap_or_default()
|
||||
.parse::<bool>()
|
||||
.unwrap_or(false);
|
||||
|
||||
|
||||
if !enabled {
|
||||
return HookResult::Skip;
|
||||
}
|
||||
|
||||
|
||||
// 設定ファイルからオプション読み込み
|
||||
let config_path = format!("{}/.nia/hook_config.json", context.workspace_path);
|
||||
let config_path = format!("{}/hook_config.json", context.workspace_path);
|
||||
if let Ok(config_content) = tokio::fs::read_to_string(&config_path).await {
|
||||
if let Ok(config) = serde_json::from_str::<HookConfig>(&config_content) {
|
||||
// 設定に基づく処理
|
||||
return process_with_config(&mut context, &config).await;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HookResult::Continue
|
||||
}
|
||||
```
|
||||
@@ -523,7 +523,7 @@ pub async fn conditional_hook(context: HookContext) -> HookResult {
|
||||
let is_rust_project = tokio::fs::metadata(
|
||||
format!("{}/Cargo.toml", context.workspace_path)
|
||||
).await.is_ok();
|
||||
|
||||
|
||||
match (is_git_repo, is_rust_project) {
|
||||
(true, true) => {
|
||||
// Rustプロジェクト + Git
|
||||
@@ -548,7 +548,7 @@ pub async fn conditional_hook(context: HookContext) -> HookResult {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use worker::types::*;
|
||||
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_timestamp_hook() {
|
||||
let mut context = HookContext {
|
||||
@@ -561,9 +561,9 @@ mod tests {
|
||||
tool_args: None,
|
||||
tool_result: None,
|
||||
};
|
||||
|
||||
|
||||
let result = add_timestamp_hook(context).await;
|
||||
|
||||
|
||||
match result {
|
||||
HookResult::ModifyContent(content) => {
|
||||
assert!(content.contains("Hello, world!"));
|
||||
@@ -587,7 +587,7 @@ pub async fn debug_hook(context: HookContext) -> HookResult {
|
||||
context.tools.len(),
|
||||
context.message_history.len()
|
||||
);
|
||||
|
||||
|
||||
// デバッグ情報をストリーミング
|
||||
context.stream_debug(
|
||||
"Hook Debug Info".to_string(),
|
||||
@@ -598,7 +598,7 @@ pub async fn debug_hook(context: HookContext) -> HookResult {
|
||||
"workspace": context.workspace_path
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
HookResult::Continue
|
||||
}
|
||||
```
|
||||
@@ -625,13 +625,13 @@ impl WorkerHook for StatefulHook {
|
||||
fn name(&self) -> &str { "stateful_hook" }
|
||||
fn hook_type(&self) -> &str { "OnTurnCompleted" }
|
||||
fn matcher(&self) -> &str { "" }
|
||||
|
||||
|
||||
async fn execute(&self, mut context: HookContext) -> (HookContext, HookResult) {
|
||||
let mut count = self.counter.lock().unwrap();
|
||||
*count += 1;
|
||||
|
||||
|
||||
context.set_variable("turn_count".to_string(), count.to_string());
|
||||
|
||||
|
||||
if *count % 10 == 0 {
|
||||
(
|
||||
context,
|
||||
@@ -658,7 +658,7 @@ impl HookChain {
|
||||
pub fn new() -> Self {
|
||||
Self { hooks: Vec::new() }
|
||||
}
|
||||
|
||||
|
||||
pub fn add_hook(mut self, hook: Box<dyn WorkerHook>) -> Self {
|
||||
self.hooks.push(hook);
|
||||
self
|
||||
@@ -670,18 +670,18 @@ impl WorkerHook for HookChain {
|
||||
fn name(&self) -> &str { "hook_chain" }
|
||||
fn hook_type(&self) -> &str { "OnMessageSend" }
|
||||
fn matcher(&self) -> &str { "" }
|
||||
|
||||
|
||||
async fn execute(&self, mut context: HookContext) -> (HookContext, HookResult) {
|
||||
for hook in &self.hooks {
|
||||
let (new_context, result) = hook.execute(context).await;
|
||||
context = new_context;
|
||||
|
||||
|
||||
match result {
|
||||
HookResult::Continue | HookResult::Skip => continue,
|
||||
other => return (context, other),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
(context, HookResult::Continue)
|
||||
}
|
||||
}
|
||||
@@ -715,4 +715,3 @@ A: `HookResult::Error`を返すと、そのターンは中断されます。継
|
||||
- [worker-macro.md](worker-macro.md) - マクロシステム
|
||||
- `worker/src/lib.rs` - Hook実装コード
|
||||
- `worker-types/src/lib.rs` - Hook型定義
|
||||
- `nia-cli/src/tui/hooks/` - TUI用Hook実装例
|
||||
@@ -6,7 +6,7 @@ v0.3.0 はプロンプトリソースの解決責務を利用側へ完全に移
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
- `ConfigParser::resolve_path` を削除し、`#nia/` `#workspace/` 等のプレフィックス解決をライブラリ利用者実装の `ResourceLoader` に委譲しました。
|
||||
- `ConfigParser::resolve_path` を削除し、`#user/` `#workspace/` 等のプレフィックス解決をライブラリ利用者実装の `ResourceLoader` に委譲しました。
|
||||
- `WorkerBuilder::build()` は `resource_loader(...)` が未指定の場合エラーを返すようになりました。ワーカー構築前に必ずローダーを提供してください。
|
||||
|
||||
## 新機能 / 仕様変更
|
||||
@@ -19,7 +19,6 @@ v0.3.0 はプロンプトリソースの解決責務を利用側へ完全に移
|
||||
## 不具合修正
|
||||
|
||||
- `include_file` ヘルパーがカスタムローダーを利用せずにファイルアクセスしていた問題を修正。
|
||||
- `ConfigParser` が存在しない `#nia/` プレフィックスを静的に解決しようとしていた挙動を除去し、誤ったパスが静かに通ることを防止。
|
||||
|
||||
## 移行ガイド
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ v0.4.0 は Worker が `Role` や YAML 設定を扱わず、システムプロン
|
||||
|
||||
## 不具合修正
|
||||
|
||||
- Worker から NIA 固有の設定コードを除去し、環境依存の副作用を縮小。
|
||||
- Worker から旧プロジェクト固有の設定コードを除去し、環境依存の副作用を縮小。
|
||||
|
||||
## 移行ガイド
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
**Release Date**: 2025-10-25
|
||||
|
||||
v0.5.0 introduces the Worker Blueprint API and removes the old type-state builder. Configuration now lives on the blueprint, while instantiated workers keep only the materialised system prompt and runtime state.
|
||||
v0.5.0 introduces the Worker Blueprint API and removes the old type-state builder. Configuration now lives on the blueprint, while instantiated workers keep only the materialised system prompt, model metadata, and runtime state.
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
@@ -12,9 +12,10 @@ v0.5.0 introduces the Worker Blueprint API and removes the old type-state builde
|
||||
|
||||
## New Features / Behaviour
|
||||
|
||||
- `WorkerBlueprint` stores provider/model/api keys, tools, hooks, and optional precomputed system prompt strings. `instantiate()` evaluates the prompt (if not already cached) and hands the final string to the `Worker`.
|
||||
- Instantiated workers retain only the composed system prompt string; the generator function lives solely on the blueprint and is dropped after instantiation.
|
||||
- `WorkerBlueprint` stores provider/model/api keys, tools, hooks, optional precomputed system prompt messages, and optional model feature flags. `instantiate()` evaluates the prompt (if not already cached) and hands the final string to the `Worker`.
|
||||
- Instantiated workers retain the composed system prompt, the original generator closure, and a `Model` struct describing provider/model/features; the generator only runs again if a new session requires it.
|
||||
- System prompts are no longer recomputed per turn. Tool metadata is appended dynamically as plain text when native tool support is unavailable.
|
||||
- Worker now exposes a `Model` struct (`provider`, `name`, `features`) in place of the previous loose strings and `supports_native_tools` helper. Capability heuristics remain for built-in providers but applications can override them via `WorkerBlueprint::model_features`.
|
||||
|
||||
## Migration Guide
|
||||
|
||||
|
||||
Reference in New Issue
Block a user