|
9 | 9 | GET /api-implement?ep_url=<enhancement-pr-url>&cwd=<operator-repo-path> |
10 | 10 | """ |
11 | 11 |
|
| 12 | +import json |
| 13 | +import logging |
12 | 14 | import os |
13 | 15 | import re |
14 | | -import json |
| 16 | +import traceback |
15 | 17 | from pathlib import Path |
16 | | - |
17 | | -import anyio |
18 | 18 | from fastapi import FastAPI, HTTPException, Query |
19 | 19 | from claude_agent_sdk import ( |
20 | 20 | query, |
|
46 | 46 | PLUGIN_DIR = str(Path(__file__).resolve().parent.parent / "plugins" / "oape") |
47 | 47 | print(PLUGIN_DIR) |
48 | 48 |
|
| 49 | +CONVERSATION_LOG = Path("/tmp/conversation.log") |
| 50 | + |
| 51 | +conv_logger = logging.getLogger("conversation") |
| 52 | +conv_logger.setLevel(logging.INFO) |
| 53 | +_handler = logging.FileHandler(CONVERSATION_LOG) |
| 54 | +_handler.setFormatter(logging.Formatter("%(message)s")) |
| 55 | +conv_logger.addHandler(_handler) |
| 56 | + |
49 | 57 |
|
50 | 58 | @app.get("/api-implement") |
51 | 59 | async def api_implement( |
@@ -94,27 +102,42 @@ async def api_implement( |
94 | 102 |
|
95 | 103 | # --- Run the agent --- |
96 | 104 | output_parts: list[str] = [] |
| 105 | + conversation: list[dict] = [] |
97 | 106 | cost_usd = 0.0 |
98 | 107 |
|
| 108 | + def _log(role: str, content, **extra): |
| 109 | + entry = {"role": role, "content": content, **extra} |
| 110 | + conversation.append(entry) |
| 111 | + conv_logger.info(f"[{role}] {content}") |
| 112 | + |
| 113 | + conv_logger.info(f"\n{'=' * 60}\n[request] ep_url={ep_url} cwd={working_dir}\n{'=' * 60}") |
| 114 | + |
99 | 115 | try: |
100 | 116 | async for message in query( |
101 | 117 | prompt=f"/oape:api-implement {ep_url}", |
102 | | - # prompt="explain the enhancement proposal to me like I'm 5 in 10 sentences, {ep_url}", |
103 | 118 | options=options, |
104 | 119 | ): |
105 | 120 | if isinstance(message, AssistantMessage): |
106 | 121 | for block in message.content: |
107 | 122 | if isinstance(block, TextBlock): |
108 | 123 | output_parts.append(block.text) |
| 124 | + _log("assistant", block.text) |
| 125 | + else: |
| 126 | + _log(f"assistant:{type(block).__name__}", |
| 127 | + json.dumps(getattr(block, "__dict__", str(block)), default=str)) |
109 | 128 | elif isinstance(message, ResultMessage): |
110 | 129 | cost_usd = message.total_cost_usd |
111 | 130 | if message.result: |
112 | 131 | output_parts.append(message.result) |
| 132 | + _log("result", message.result, cost_usd=cost_usd) |
| 133 | + else: |
| 134 | + _log(type(message).__name__, |
| 135 | + json.dumps(getattr(message, "__dict__", str(message)), default=str)) |
113 | 136 | except Exception as exc: |
114 | | - raise HTTPException( |
115 | | - status_code=500, |
116 | | - detail=f"Agent execution failed: {exc}", |
117 | | - ) |
| 137 | + conv_logger.info(f"[error] {traceback.format_exc()}") |
| 138 | + raise HTTPException(status_code=500, detail=f"Agent execution failed: {exc}") |
| 139 | + |
| 140 | + conv_logger.info(f"[done] cost=${cost_usd:.4f} parts={len(output_parts)}\n") |
118 | 141 |
|
119 | 142 | return { |
120 | 143 | "status": "success", |
|
0 commit comments