agent-Specialization/api_doc/examples.md

265 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 示例curl / Python / JS / Flutter
本文提供“最小可用”的端到端示例:创建对话 → 发送消息 → 轮询输出 →(可选)停止任务 → 文件上传/下载。
请先阅读 `auth.md` 并准备好 token。
## 0. 统一变量
- `BASE_URL`:例如 `http://localhost:8091`
- `TOKEN`:你的 Bearer Token明文
---
## 1) curl完整对话流程
### 1.1 创建对话
```bash
BASE_URL="http://localhost:8091"
TOKEN="<TOKEN>"
curl -sS -X POST \
-H "Authorization: Bearer $TOKEN" \
"$BASE_URL/api/v1/conversations"
```
假设返回:
```json
{ "success": true, "conversation_id": "conv_20260123_234245_036" }
```
### 1.2 发送消息(创建任务)
```bash
curl -sS -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"conversation_id": "conv_20260123_234245_036",
"message": "请用中文简要介绍《明日方舟:终末地》",
"run_mode": "fast",
"max_iterations": 100
}' \
"$BASE_URL/api/v1/messages"
```
假设返回:
```json
{ "success": true, "task_id": "60322db3-...", "status": "running", "conversation_id": "conv_...", "created_at": 1769182965.30 }
```
### 1.3 轮询(建议脚本处理 next_offset
```bash
TASK_ID="60322db3-..."
OFFSET=0
curl -sS -H "Authorization: Bearer $TOKEN" \
"$BASE_URL/api/v1/tasks/$TASK_ID?from=$OFFSET"
```
---
## 2) Python轮询并实时拼接文本
依赖:`pip install requests`
```python
import time
import requests
BASE_URL = "http://localhost:8091"
TOKEN = "<TOKEN>"
H = {"Authorization": f"Bearer {TOKEN}"}
def post_json(path, payload):
r = requests.post(BASE_URL + path, json=payload, headers={**H, "Content-Type":"application/json"}, timeout=30)
r.raise_for_status()
return r.json()
def get_json(path, params=None):
r = requests.get(BASE_URL + path, params=params or {}, headers=H, timeout=30)
r.raise_for_status()
return r.json()
# 1) create conversation
conv = requests.post(BASE_URL + "/api/v1/conversations", headers=H, timeout=30).json()
assert conv["success"]
conversation_id = conv["conversation_id"]
# 2) send message
task = post_json("/api/v1/messages", {
"conversation_id": conversation_id,
"message": "请用中文简要介绍《明日方舟:终末地》",
"run_mode": "fast",
"max_iterations": 100
})
task_id = task["task_id"]
# 3) poll events
offset = 0
text_buf = []
think_buf = []
while True:
data = get_json(f"/api/v1/tasks/{task_id}", params={"from": offset})
if not data["success"]:
raise RuntimeError(data.get("error"))
info = data["data"]
events = info["events"]
offset = info["next_offset"]
for ev in events:
t = ev["type"]
d = ev["data"] or {}
if t == "text_chunk":
text_buf.append(d.get("content",""))
print(d.get("content",""), end="", flush=True)
elif t == "text_end":
print("\\n--- text_end ---\\n")
elif t == "thinking_chunk":
think_buf.append(d.get("content",""))
elif t == "tool_start":
print(f\"\\n[tool_start] {d.get('name')}\\n\")
elif t == "update_action":
# 工具状态更新
st = d.get("status") or ""
msg = d.get("message") or ""
if st or msg:
print(f\"\\n[update_action] {st} {msg}\\n\")
elif t == "error":
print(f\"\\n[error] {d.get('message')}\\n\")
if info["status"] != "running":
break
time.sleep(1.0)
final_text = "".join(text_buf)
final_thinking = "".join(think_buf)
print("final status:", info["status"])
print("final text length:", len(final_text))
print("final thinking length:", len(final_thinking))
```
---
## 3) JavaScript浏览器/Node要点
浏览器端直接跨域请求时,请确保服务端允许 CORS当前服务端已启用 CORS。请求示例
```js
const BASE_URL = "http://localhost:8091";
const TOKEN = "<TOKEN>";
async function api(path, options = {}) {
const resp = await fetch(BASE_URL + path, {
...options,
headers: {
"Authorization": `Bearer ${TOKEN}`,
...(options.headers || {})
}
});
const data = await resp.json();
if (!resp.ok || !data.success) throw new Error(data.error || resp.statusText);
return data;
}
const conv = await api("/api/v1/conversations", { method: "POST" });
const msg = await api("/api/v1/messages", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
conversation_id: conv.conversation_id,
message: "请用中文简要介绍《明日方舟:终末地》",
run_mode: "fast",
max_iterations: 100
})
});
let offset = 0;
let text = "";
while (true) {
const poll = await api(`/api/v1/tasks/${msg.task_id}?from=${offset}`);
const info = poll.data;
for (const ev of info.events) {
if (ev.type === "text_chunk") text += ev.data.content || "";
if (ev.type === "tool_start") console.log("tool:", ev.data.name);
}
offset = info.next_offset;
if (info.status !== "running") break;
await new Promise(r => setTimeout(r, 1000));
}
console.log("done:", text);
```
---
## 4) FlutterDart轮询示例伪代码
依赖:`http` 包或 `dio` 包均可,这里用 `http` 表达逻辑。
```dart
import 'dart:convert';
import 'dart:async';
import 'package:http/http.dart' as http;
const baseUrl = "http://localhost:8091";
const token = "<TOKEN>";
Map<String,String> headersJson() => {
"Authorization": "Bearer $token",
"Content-Type": "application/json",
};
Future<String> createConversation() async {
final resp = await http.post(Uri.parse("$baseUrl/api/v1/conversations"),
headers: {"Authorization":"Bearer $token"});
final data = jsonDecode(resp.body);
if (resp.statusCode != 200 || data["success"] != true) throw Exception(data["error"]);
return data["conversation_id"];
}
Future<String> sendMessage(String convId, String message) async {
final resp = await http.post(Uri.parse("$baseUrl/api/v1/messages"),
headers: headersJson(),
body: jsonEncode({
"conversation_id": convId,
"message": message,
"run_mode": "fast",
"max_iterations": 100,
}));
final data = jsonDecode(resp.body);
if (resp.statusCode != 202 || data["success"] != true) throw Exception(data["error"]);
return data["task_id"];
}
Stream<String> pollText(String taskId) async* {
int offset = 0;
while (true) {
final resp = await http.get(Uri.parse("$baseUrl/api/v1/tasks/$taskId?from=$offset"),
headers: {"Authorization":"Bearer $token"});
final data = jsonDecode(resp.body);
if (resp.statusCode != 200 || data["success"] != true) throw Exception(data["error"]);
final info = data["data"];
final events = (info["events"] as List);
for (final ev in events) {
if (ev["type"] == "text_chunk") {
yield (ev["data"]["content"] ?? "");
}
}
offset = info["next_offset"];
if (info["status"] != "running") break;
await Future.delayed(Duration(milliseconds: 800));
}
}
```
提示:
- Flutter UI 展示建议:把 `pollText()` 的输出 append 到一个 `StringBuffer`,并用 `setState()`/状态管理更新。
- 同时可以订阅 tool_* 事件在 UI 中显示“正在搜索/正在执行工具”等状态。