Skip to content

更新支持流式输出#7

Closed
Taoxuan-168 wants to merge 3 commits intosipeed:mainfrom
Taoxuan-168:main
Closed

更新支持流式输出#7
Taoxuan-168 wants to merge 3 commits intosipeed:mainfrom
Taoxuan-168:main

Conversation

@Taoxuan-168
Copy link

流式输出功能说明

概述

PicoClaw 现在支持可选的流式输出功能,可以实时显示 AI 的思考过程和工具执行状态。该功能默认关闭,通过配置文件启用。

功能特性

默认模式(非流式,streaming: false

  • 等待完整响应后一次性显示
  • 简洁的输出格式
  • 最小资源占用
  • 向后兼容旧版本行为

流式模式(streaming: true

  • 💭 实时显示 AI 思考过程
  • 🔧 显示工具调用过程
  • ✓ 显示工具执行结果
  • ⏳ 显示处理进度
  • 打字机效果逐字显示 AI 回复
  • 支持 Ctrl+C 中断执行

配置方法

1. 通过配置文件启用

编辑 ~/.picoclaw/config.json

{
  "agents": {
    "defaults": {
      "workspace": "~/.picoclaw/workspace",
      "model": "glm-4.7-flash",
      "max_tokens": 8192,
      "temperature": 0.7,
      "max_tool_iterations": 20,
      "streaming": true
    }
  }
}

2. 通过环境变量启用

export PICOCLAW_AGENTS_DEFAULTS_STREAMING=true
./picoclaw agent -m "你的问题"

3. 示例配置

参考 config.example.json 中的配置示例(默认为 false)。

使用示例

非流式模式(默认)

$ ./picoclaw agent -m "What is 2+2?"
🦞 2 + 2 = **4**

流式模式

$ ./picoclaw agent -m "What is 2+2?"
🦞 💭 Starting to process request...
🦞 ⏳ Thinking... (iteration 1/20)
2 + 2 = **4** ✅
🦞 2 + 2 = **4**

技术实现

修改的文件

文件 改动说明 行数
pkg/config/config.go 添加 Streaming bool 配置字段 +2
config.example.json 添加配置示例 +1
pkg/agent/loop.go 添加条件判断逻辑 +15
cmd/picoclaw/main.go CLI 适配流式/非流式模式 +40

核心改动

1. 配置结构(pkg/config/config.go)

type AgentDefaults struct {
    Workspace         string  `json:"workspace"`
    Model             string  `json:"model"`
    MaxTokens         int     `json:"max_tokens"`
    Temperature       float64 `json:"temperature"`
    MaxToolIterations int     `json:"max_tool_iterations"`
    Streaming         bool    `json:"streaming"` // 新增字段
}

2. Agent 循环(pkg/agent/loop.go)

type AgentLoop struct {
    // ... 其他字段
    streaming bool // 新增字段
}

func (al *AgentLoop) Run(ctx context.Context) error {
    // 根据配置选择处理模式
    if al.streaming {
        response, err = al.processMessageStreaming(ctx, msg, ...)
    } else {
        response, err = al.processMessage(ctx, msg)
    }
}

3. CLI 适配(cmd/picoclaw/main.go)

if agentLoop.IsStreamingEnabled() {
    // 流式模式:显示实时更新
    response, err = agentLoop.ProcessDirectStreaming(ctx, input, sessionKey, callback)
} else {
    // 非流式模式:等待完整响应
    response, err = agentLoop.ProcessDirect(ctx, input, sessionKey)
}

向后兼容性

  • ✅ 现有配置文件无需修改,默认使用非流式模式
  • ✅ 不启用流式功能时,性能和行为与之前版本完全一致
  • ✅ 旧版本配置文件可以直接使用
  • ✅ API 接口保持不变

性能影响

模式 CPU 占用 内存占用 网络请求
非流式(默认) 基准 基准 单次请求
流式模式 +<1% +~50KB SSE 流式请求

故障排查

流式模式不工作

  1. 检查配置文件中 streaming 是否设置为 true
  2. 确认 API 提供商支持流式响应(SSE)
  3. 检查网络连接是否稳定

输出混乱

  • 某些终端可能不支持 \r 回车符刷新,建议使用现代终端模拟器

中断不响应

  • 确保使用 Ctrl+C 中断
  • 在某些模式下可能需要按两次

开发者信息

事件类型

流式模式支持以下事件类型:

  • thinking - AI 正在思考/推理
  • progress - 进度更新
  • tool_call - 即将执行工具
  • tool_result - 工具执行完成
  • content - 部分内容流式传输
  • complete - 处理完成
  • error - 发生错误

自定义回调

开发者可以通过 ProcessDirectStreaming() 方法自定义流式事件处理:

agentLoop.ProcessDirectStreaming(ctx, input, sessionKey, func(event bus.StreamEvent) {
    switch event.Type {
    case bus.StreamEventThinking:
        // 自定义处理思考事件
    case bus.StreamEventContent:
        // 自定义处理内容事件
    }
})

Nyukimin pushed a commit to Nyukimin/picoclaw_multiLLM that referenced this pull request Mar 2, 2026
伝説のアーキテクトレビューで発見された10個の致命的不備のうち、Phase 1(即時修正必須)を完了。

## 修正内容

### Issue #1: 承認フロー残骸削除 (🔴 CRITICAL)
- L328: Chat役割「承認管理」→「ユーザー対話」に変更
- L346-349: 承認フロー管理の責務削除、実行結果統合を追加
- L382: 「承認後に担当」→「即座に担当」に修正
- L384: 目的「承認フロー確実な動作」→「Worker即時実行確実な動作」
- L660: JobID コメント「承認ジョブ」→「Worker実行ジョブ」
- L835: CHAT ルート「承認管理」→「対話管理」
- L881: ルール辞書「承認して|approve」→「状態|status|確認」
- L1274-1278: Section 11.3「承認必須操作」完全削除
- L1285-1297: approval イベント削除、worker イベントに置換
- L1457: テスト「承認フロー」→「Worker即時実行」
- L2250: usecase.NewManageApproval 削除
- L2289: 付録差分「承認フロー仕様」→「(削除)」
- L2318: アグリゲート例「ApprovalFlow」→「Session」

### Issue sipeed#2: データベーススキーマ残骸削除 (🔴 CRITICAL)
- L288-293: db/migrations/ ディレクトリ削除
  - 001_create_events_table.sql
  - 002_create_jobs_table.sql
  - 003_create_auto_approve_policies_table.sql
- L2155-2194: Section 18.3「Job Repository」完全削除
  - SQLiteJobRepository実装
  - approval.ApprovalFlow 参照

### Issue sipeed#3, sipeed#4: EventStore、approval package参照削除 (🔴 CRITICAL)
- L1460: 実装プラン「Event Store, Worker実行」→「Worker即時実行、E2Eシナリオ」
- L2224-2226: Wire DI import削除
  - internal/domain/approval
  - internal/infrastructure/eventstore
  - internal/infrastructure/persistence/job
- L2233-2235: Wire DI provider削除
  - provideSQLiteDB
  - eventstore.NewSQLiteEventStore
  - job.NewSQLiteJobRepository
  - approval.NewAutoApprovePolicy
  - service.NewApprovalService
- L2220+: Wire DI import追加
  - internal/infrastructure/persistence/session
  - pkg/tools
  - provideToolRegistry
  - session.NewJSONSessionRepository

### Issue sipeed#5: セクション番号修正 (🟡 MEDIUM)
- 11章: ### 12.1, 12.2 → 11.1, 11.2
- 13章: ### 14.1, 13.2, 14.3 → 13.1, 13.2, 13.3
- 14章: ### 15.1 → 14.1
- 15章: ### 16.1, 16.2 → 15.1, 15.2
- 16章: ### 17.1 → 16.1
- 17章: ### 18.1 → 17.1
- 18章: ### 19.1 → 18.1

## 影響

### 修正前(システム破綻リスク)
- ❌ 承認フロー残骸13箇所
- ❌ 存在しないパッケージへの依存(ビルド失敗)
- ❌ 削除されたDB migrations参照
- ❌ Wire DI設定矛盾(起動不能)

### 修正後(実装可能)
- ✅ 承認フロー完全削除
- ✅ Worker即時実行への統一
- ✅ ビルド可能な依存関係
- ✅ 正しいWire DI設定

## 残存Issue(Phase 2で対応)

- Issue sipeed#6: workspace設定の統一(実装前に必須)
- Issue sipeed#7: parseMarkdownPatch正規表現修正(実装前に必須)
- Issue sipeed#8: コードブロック順序保証(実装前に必須)
- Issue sipeed#9: 保護ファイルチェック強化(実装前に必須)
- Issue sipeed#10: Git ロック機構追加(実装中に対応)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Nyukimin pushed a commit to Nyukimin/picoclaw_multiLLM that referenced this pull request Mar 2, 2026
Phase 2の4つのHIGH重大度不備を修正。実装開始時のトラブルを回避。

## 修正内容

### Issue sipeed#6: workspace設定の統一 (🟠 HIGH)
**問題**: WorkerConfig.Workspace と NewWorkerExecutionService(workspace) の二重管理

**修正**:
- L1728-1735: workerExecutionService構造体から `workspace string` フィールド削除
- L1737-1745: NewWorkerExecutionService引数から `workspace string` 削除
- L1934, 2031: `w.workspace` → `w.config.Workspace` に統一(全2箇所)

**効果**: workspace設定が WorkerConfig に一元化、設定の不整合を防止

---

### Issue sipeed#7: parseMarkdownPatch正規表現修正 (🟠 HIGH)
**問題**: 正規表現が複数行コードブロックに対応していない

**修正前**:
```go
reCodeBlock := regexp.MustCompile("```([a-z]+):([^\n]+)\n(.*?)\n```")
reShellBlock := regexp.MustCompile("```bash\n(.*?)\n```")
```
- `.*?` は改行にマッチしない(デフォルトDOTALLなし)
- 複数行のコードが切り詰められる

**修正後**:
```go
reCodeBlock := regexp.MustCompile("(?s)```([a-z]+):([^\n]+)\n(.*?)```")
reShellBlock := regexp.MustCompile("(?s)```bash\n(.*?)```")
```
- `(?s)` フラグ追加: DOTALL モード有効化
- `.` が改行を含むすべての文字にマッチ
- 複数行コードブロックを正しくパース可能

**効果**: 複数行のファイル編集、複数行シェルコマンドが正常動作

---

### Issue sipeed#8: コードブロック順序保証 (🟠 HIGH)
**問題**: Markdown出現順序を無視(ファイル編集 → シェルコマンドの順で強制実行)

**修正前のロジック**:
1. すべてのファイル編集コードブロックを抽出 → commands配列に追加
2. すべてのシェルコマンドブロックを抽出 → commands配列に追加
3. → **出現順序が狂う**(例: テスト実行 → ファイル編集の順が逆転)

**修正後のロジック**:
1. FindAllStringSubmatchIndex() で位置情報(pos)付きで抽出
2. positionedCommand{pos, cmd} 構造体で管理
3. sort.Slice() で pos 順にソート
4. → **Markdown出現順を保証**

**修正箇所**:
- L1867-1915: parseMarkdownPatch() 全体を書き換え
- positionedCommand型導入、位置情報管理
- FindAllStringSubmatchIndex()使用、ソート処理追加

**効果**: パッチの意図した実行順序を保証(例: ファイル編集 → go test の順序が正しく実行)

---

### Issue sipeed#9: 保護ファイルチェック強化 (🟠 HIGH)
**問題**: rename/copy のデスティネーションが保護ファイルチェックされない

**攻撃シナリオ**:
```json
{
  "type": "file_edit",
  "action": "copy",
  "target": "/tmp/dummy.txt",  // ← 通常ファイル(チェックOK)
  "content": ".env"             // ← 保護ファイル(チェックなし!)
}
```
→ `.env` が上書きされる脆弱性

**修正**:
- L1996: ActionRename のデスティネーション保護チェック追加
  ```go
  if w.isProtectedFile(cmd.Content) {
      return "", fmt.Errorf("cannot rename to protected file: %s", cmd.Content)
  }
  ```
- L2012: ActionCopy のデスティネーション保護チェック追加
  ```go
  if w.isProtectedFile(cmd.Content) {
      return "", fmt.Errorf("cannot copy to protected file: %s", cmd.Content)
  }
  ```

**効果**: 保護ファイル(.env*, *credentials*, *.key等)への上書き攻撃を完全ブロック

---

## 修正統計

| Issue | 修正箇所 | 追加行 | 削除行 | 変更行 |
|-------|---------|--------|--------|--------|
| sipeed#6 workspace統一 | 4箇所 | 2行 | 4行 | 2行 |
| sipeed#7 regex修正 | 2箇所 | 4行 | 2行 | 2行 |
| sipeed#8 順序保証 | 1関数 | 24行 | 18行 | 49行 |
| sipeed#9 保護強化 | 2箇所 | 6行 | 0行 | 6行 |
| **合計** | **9箇所** | **36行** | **24行** | **59行** |

## テストケース追加推奨

実装時に以下のテストケースを追加すべき:

### Issue sipeed#7: 複数行コードブロック
```go
func TestParseMarkdownPatch_MultilineCode(t *testing.T) {
    patch := "```go:main.go\npackage main\n\nfunc main() {\n    fmt.Println(\"test\")\n}\n```"
    commands, err := parseMarkdownPatch(patch)
    assert.NoError(t, err)
    assert.Contains(t, commands[0].Content, "func main()")
}
```

### Issue sipeed#8: 実行順序保証
```go
func TestParseMarkdownPatch_PreservesOrder(t *testing.T) {
    patch := "```go:file.go\ncode\n```\n```bash\ngo test\n```"
    commands, err := parseMarkdownPatch(patch)
    assert.Equal(t, "file_edit", commands[0].Type)
    assert.Equal(t, "shell_command", commands[1].Type)
}
```

### Issue sipeed#9: 保護ファイル攻撃防御
```go
func TestExecuteFileEdit_ProtectedDestination(t *testing.T) {
    cmd := PatchCommand{Action: "copy", Target: "/tmp/dummy", Content: ".env"}
    _, err := executeFileEdit(ctx, cmd)
    assert.Error(t, err)
    assert.Contains(t, err.Error(), "protected file")
}
```

---

## 残存Issue(Phase 3で対応)

- Issue sipeed#10: Git auto-commit race condition (🟡 MEDIUM)
  - 対応タイミング: 実装中(並行実行が必要になった時点)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Nyukimin pushed a commit to Nyukimin/picoclaw_multiLLM that referenced this pull request Mar 3, 2026
- HIGH sipeed#6: Agent名称統一テーブル(§1.4)追加、config key統一
- HIGH sipeed#7: ResultPayloadにModifiedFiles/DeletedFiles追加
- HIGH sipeed#8: Orchestrator移行設計(§2.4.1)新設、Adapterパターン方針明記
- HIGH sipeed#9: 並列実行スコープをv4.0(PatchCommand並列)/v4.1(タスク分割)に分離
- HIGH sipeed#10: truncate()をrune単位に変更し日本語破壊を防止
- HIGH sipeed#11: Sessionスレッドセーフ性(§7.1.1)の段階的方針を明記

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
amiyak-codespace added a commit to amiyak-codespace/picoclaw that referenced this pull request Mar 9, 2026
chore(sync): upstream main -> private main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants