Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
a547d6b
Bugfix: 修复GraphAgent中AgentNode的last_response被设为「思考/中间轮文本」的问题
weimch Jul 6, 2026
cbb6979
feat(a2a): support optional app_name for TrpcA2aAgentService
yangenle6-alt Jul 7, 2026
3f0d67c
Add internal pipeline test
CongkeChen Jul 7, 2026
e08db6d
fix pipeline example paths
CongkeChen Jul 7, 2026
96fcee4
test internal pipeline trigger
CongkeChen Jul 7, 2026
9ed2cfb
Update internal_pipeline_test_trigger.txt
CongkeChen Jul 7, 2026
778ca59
fix internal pipeline example scripts
CongkeChen Jul 8, 2026
f10f08c
feat(sessions): list_sessions 支持 user_id 为 None 时获取 app_name 下全部 sess…
weimch Jul 8, 2026
4336564
docs: add docs index (#146)
raychen911 Jul 9, 2026
8fdf6d8
fix(docs): correct README installation command syntax
Phil-Fan Jul 9, 2026
89c44ce
fix(docs): fix pip install command formatting
Phil-Fan Jul 9, 2026
bbd07eb
feat: 动态创建子Agent支持在运行时产生的事件直接转发到父流程的事件流中的能力
bochencwx Jul 10, 2026
14d78cd
Bugfix: 修复模型调用失败未显示异常信息的问题
weimch Jul 10, 2026
059a355
version: 发布1.1.12版本
raychen911 Jul 10, 2026
17316d0
Fix examples and Build Full Pipeline
CongkeChen Jul 10, 2026
e113610
add release workflow
CongkeChen Jul 10, 2026
f8b05ba
Code Review (#191)
CongkeChen Jul 16, 2026
1903a9f
Code Review
CongkeChen Jul 16, 2026
0174c7c
remove ai review prompt file
CongkeChen Jul 16, 2026
9cd6bc3
Feat: tRPC-Agent对齐Claude Code Plan Mod能力 (#148)
jinfengliu-688 Jul 17, 2026
eac046f
Runner: avoid data copy
helloopenworld Jul 16, 2026
5d44031
feat: trpc-agent框架web工具支持tavily
weimch Jul 16, 2026
f2a34ff
version: 发布1.1.13版本
raychen911 Jul 17, 2026
5ca3bf2
feat: 新增脚本支持在 uv 安装方式在 macOS 上运行,更新相关安装文档和README文档 (#203)
Rook1ex Jul 21, 2026
189b3dd
test(sessions): add Session/Memory/Summary multi-backend replay consi…
coder-mtj Jul 21, 2026
7114161
chore: trigger CI re-run for CLA check
coder-mtj Jul 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions .github/code_review/prompts/findings.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
你现在的任务不是重新做代码审查,而是将已经生成的 `review.md` 提取为结构化结果,供后续脚本用于行内评论、阻断判断和其他自动化处理。

输入文件:
1. 仓库根目录下的 `review.md`:这是主依据,包含第一阶段已经确认的问题。
2. 仓库根目录下的 `pr.diff`:仅用于辅助定位文件路径和行号,必要时可用于补全位置;不要基于 `pr.diff` 新增问题。

任务要求:
1. 只提取 `review.md` 中已经明确列出的问题,不要新增、扩展或重写任何新问题。
2. 不要重新判断代码是否有问题;第一阶段 review 的结论已经成立,你的任务只是标准化提取。
3. 如果 `review.md` 中某个问题缺少明确的文件路径或行号,不要编造;但不要跳过该问题,仍应保留该 finding,并将 `inline_candidate` 设为 `false`。在这种情况下,`path`、`start_line`、`end_line` 可留空字符串、0 或与定位失败一致的保守值,但不能让该问题从结果中消失。
4. 允许参考 `pr.diff` 来确认问题对应的目标文件路径、起始行和结束行,但不要因此新增新的发现。
5. 输出必须是严格合法的 JSON,且只能输出 JSON,不要输出 Markdown、解释文字、代码块、前后缀或额外说明。
6. 输出必须直接以 `{` 开始、以 `}` 结束;不要使用 ```json、``` 或任何其他 Markdown 代码块围栏包裹 JSON。

严重级别映射:
- `Critical` -> `critical`
- `Warning` -> `warning`
- `Suggestion` -> `suggestion`

输出 JSON 格式:
```json
{
"findings": [
{
"severity": "critical",
"path": "relative/path/to/file.py",
"start_line": 12,
"end_line": 12,
"title": "问题标题",
"body": "1-3 句简洁说明,适合直接用于 GitHub 行内评论。",
"inline_candidate": true
}
]
}
```

字段要求:
1. `severity`:必须是 `critical`、`warning`、`suggestion` 之一。
2. `path`:仓库相对路径,例如 `tests/ai_test.py`;如果确实无法稳定定位,可为空字符串,但该 finding 仍需保留。
3. `start_line`:问题起始行号,必须优先使用变更后文件的目标行号;如果确实无法稳定定位,可为 `0`,但该 finding 仍需保留。
4. `end_line`:
- 单行问题时,填写与 `start_line` 相同的值;
- 范围问题时,填写结束行号。
5. `title`:简短问题标题,适合作为行内评论标题,不要过长。
6. `body`:1-3 句简洁说明,说明风险和建议修复方向,适合直接显示在代码旁边。
7. `inline_candidate`:
- `true`:适合做行内评论,问题能明确归因到一个文件的一行或一小段范围,且适合直接挂在代码旁解释。
- `false`:更适合放在总评论中,例如跨文件、跨逻辑链路、整体性结论、位置不稳定或无法明确锚定到 diff 行的问题。

提取规则:
1. 如果 `review.md` 中同一个问题覆盖多个独立位置,只有在这些位置都适合单独挂行内评论时,才拆成多条 findings;否则保持为一条并将 `inline_candidate` 设为 `false`。
2. 如果一个问题已经在第一阶段被合并表述为一个综合问题(例如“命令注入 + 路径穿越”),不要在这里再次拆分成多个新问题,除非 `review.md` 本身已经明确拆开。
3. `body` 不要照抄整段 review 原文;应提炼成适合行内评论展示的短说明。
4. 不允许因为定位失败、信息缺失或不适合行内评论而省略第一阶段已经明确列出的问题;这类问题必须保留在 `findings` 中,并通过 `inline_candidate=false` 与保守字段值表达。
5. 如果 `review.md` 中没有任何问题,输出:
```json
{"findings":[]}
```

校验要求:
1. 输出必须能被标准 JSON 解析器直接解析。
2. 所有字符串必须使用双引号。
3. 不要在 JSON 外再输出任何额外字符。
4. 不要输出 ```json 或 ```,也不要输出任何注释。
78 changes: 78 additions & 0 deletions .github/code_review/prompts/review.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
你是一个资深代码审查助手。请审查当前 PR 的代码变更,并给出稳定、可复用、可执行的 review 结论。

审查范围:
1. 以仓库根目录下的 `pr.diff` 作为审查主范围,只反馈落在 diff 变更中的问题。
2. 允许结合仓库中的相关上下文辅助判断 diff 是否存在问题,例如被调用方、配置、类型定义、测试、公共函数和上下游调用关系;但不要脱离 diff 单独审查未修改代码。
3. 不要修改任何文件,不要提交代码。
4. 只反馈可以从 diff 及其相关仓库上下文中定位和验证的问题;不要基于猜测扩展到未修改代码。
5. 每个问题必须标注文件路径和行号。行号优先使用 diff 中新增代码对应的目标文件行号;如果只能定位到代码块,请说明“附近行”。

审查重点:
1. 正确性:逻辑错误、状态流转错误、条件判断错误、返回值或异常处理错误。
2. 安全性:凭证泄露、命令注入、路径穿越、不可信输入未校验、权限绕过、敏感信息输出。
3. 稳定性:边界条件缺失、空值处理、并发或异步时序问题、资源未释放、超时和重试缺失。
4. 兼容性:公开 API、配置项、持久化数据、CI/workflow 行为的破坏性变更。
5. 测试有效性:高风险逻辑缺少必要测试,或测试没有覆盖实际风险路径。
6. 可维护性:仅在影响理解、扩展或长期维护时提出,不输出泛泛的代码风格建议。

质量等级定义:
- 🚨 Critical:必须修复的问题。包括安全漏洞、明确的逻辑错误、会导致核心功能失败、数据错误、权限问题、CI 阻塞或线上风险的问题。
- ⚠️ Warning:建议修复的问题。包括性能隐患、边界条件缺失、异常路径不完整、兼容性风险、测试覆盖不足等可能导致问题但不一定立即失败的情况。
- 💡 Suggestion:可选优化。包括代码可读性、结构简化、维护性提升、轻微重复等不影响当前正确性的改进建议。

输出要求:
1. 使用 Markdown 输出,保持简洁,避免长篇解释。
2. 先列问题,再给总结。
3. 按 Critical、Warning、Suggestion 的顺序输出;同级别内按风险从高到低排序。
4. 合并同类问题:同一根因、同一文件相邻代码、同一修复方式的问题应合并为一条,不要重复展开,也不要用不同表述重复描述同一问题。
5. 优先输出高价值问题。Critical 和 Warning 不限数量但要合并;Suggestion 最多 2 条,且只有在确实有维护价值时输出。
6. 每条问题控制在 2-3 句话内:说明问题、影响和修复方向即可,不要分别展开大段“问题/影响/建议”。
7. 问题位置必须使用反引号包裹的 `文件路径:行号` 或 `文件路径:起始行-结束行` 格式,便于评论自动生成 GitHub 跳转链接。
8. 如果没有发现明确问题,请直接说明“未发现明显阻塞问题”,不要为了完整性补充低价值建议。
9. 如果同一段代码同时涉及多个相关风险(如命令注入、路径穿越),优先合并成一条,除非修复方式或影响范围明显不同。
10. 对测试代码、示例代码、演示代码也按真实执行风险评估;如果这些代码会进入 CI、测试运行路径或被其他开发者复用,不要因为“仅用于示例/测试”而降低问题等级。
11. 仅当问题离开具体代码片段不易理解时,才附带 3-8 行最小必要代码片段;前后可用 `...` 省略,不要默认给每个问题都附代码块,也不要贴大段代码。
12. 结论要尽量确定:只有在确实无法从 diff 验证时,才使用“可能”“疑似”等措辞。

输出格式:

## 发现的问题

如果存在问题,请按下面格式逐条输出。每条尽量一行位置 + 一段简短说明:

### 🚨 Critical

- `文件路径:行号`:问题标题
- 简要说明具体风险和建议修复方式。
- 如有必要,可附最小必要代码片段:
```python
...
问题代码
...
```

### ⚠️ Warning

- `文件路径:行号`:问题标题
- 简要说明具体风险和建议修复方式。
- 如有必要,可附最小必要代码片段:
```python
...
问题代码
...
```

### 💡 Suggestion

- `文件路径:行号`:问题标题
- 简要说明维护性影响和可选优化方式。

如果某个等级没有问题,可以省略该等级。

## 总结

用 1-2 句话说明整体风险,以及是否存在必须修复的问题。

## 测试建议

如果需要补充测试,用 1-2 条说明建议覆盖的场景;如果不需要,请说明“暂无额外测试建议”。
24 changes: 24 additions & 0 deletions .github/code_review/scripts/evaluate_gate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env python3

import json
import os
import sys


def main():
findings_path = os.environ.get("FINDINGS_PATH", "findings.json")
with open(findings_path, "r", encoding="utf-8") as f:
data = json.load(f)

findings = data.get("findings", [])
for finding in findings:
if finding.get("severity") == "critical":
print("Critical issues found in AI Code Review, blocking pipeline")
return 1

print("No critical findings, pipeline can continue")
return 0


if __name__ == "__main__":
sys.exit(main())
170 changes: 170 additions & 0 deletions .github/code_review/scripts/post_inline_comments.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
#!/usr/bin/env python3

import json
import os
import re
import sys
import urllib.error
import urllib.request


def read_findings(path):
with open(path, "r", encoding="utf-8") as f:
data = json.load(f)
return data.get("findings", [])


def build_position_map(diff_path):
with open(diff_path, "r", encoding="utf-8") as f:
lines = f.readlines()

position_map = {}
current_path = None
new_line_no = None
position = 0
in_hunk = False

for raw in lines:
line = raw.rstrip("\n")

if line.startswith("diff --git "):
current_path = None
new_line_no = None
position = 0
in_hunk = False
continue

if line.startswith("+++ b/"):
current_path = line[6:]
if current_path not in position_map:
position_map[current_path] = {}
continue

if line.startswith("@@ "):
match = re.match(r"@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@", line)
if match:
new_line_no = int(match.group(1))
in_hunk = True
continue

if not in_hunk or current_path is None:
continue

if not line:
continue

prefix = line[0]
if prefix not in (" ", "+", "-"):
continue

position += 1

if prefix == " ":
position_map[current_path][new_line_no] = position
new_line_no += 1
elif prefix == "+":
position_map[current_path][new_line_no] = position
new_line_no += 1
elif prefix == "-":
continue

return position_map


def build_payload(commit_id, path, position, title, body):
comment_body = "**%s**" % title
if body:
comment_body += "\n\n%s" % body
return {
"body": comment_body,
"commit_id": commit_id,
"path": path,
"position": position,
}


def post_inline_comment(api_url, token, payload):
data = json.dumps(payload).encode("utf-8")
req = urllib.request.Request(
api_url,
data=data,
method="POST",
headers={
"Authorization": "Bearer %s" % token,
"Accept": "application/vnd.github+json",
"Content-Type": "application/json",
},
)
try:
with urllib.request.urlopen(req) as resp:
return True, "status=%s" % resp.status
except urllib.error.HTTPError as e:
try:
err = e.read().decode("utf-8", errors="ignore")
except Exception:
err = ""
return False, "status=%s body=%s" % (e.code, err)


def main():
findings_path = os.environ.get("FINDINGS_PATH", "findings.json")
diff_path = os.environ.get("PR_DIFF_PATH", "pr.diff")
api_url = os.environ["INLINE_COMMENT_API_URL"]
token = os.environ["GITHUB_TOKEN"]
commit_id = os.environ["GITHUB_HEAD_SHA"]

findings = read_findings(findings_path)
if not findings:
print("no findings found, skip inline comments")
return 0

position_map = build_position_map(diff_path)
created = 0

for finding in findings:
if finding.get("severity") != "critical":
continue
if not finding.get("inline_candidate"):
continue

path = finding.get("path")
start_line = finding.get("start_line")
end_line = finding.get("end_line")
title = finding.get("title", "").strip()
body = finding.get("body", "").strip()

if not path or not start_line or not title:
print("skip finding without required fields: %s" % json.dumps(finding, ensure_ascii=False))
continue

start_line = int(start_line)
end_line = int(end_line) if end_line else None
target_line = start_line

file_positions = position_map.get(path, {})
position = file_positions.get(target_line)
if position is None and end_line and end_line > start_line:
position = file_positions.get(end_line)
if position is not None:
target_line = end_line

target = "%s:%s-%s" % (path, start_line, end_line) if end_line and end_line > start_line else "%s:%s" % (path, start_line)

if position is None:
print("skip finding without diff position: %s" % target)
continue

payload = build_payload(commit_id, path, position, title, body)
ok, msg = post_inline_comment(api_url, token, payload)
if ok:
created += 1
print("inline comment created: %s position=%s %s" % (target, position, msg))
else:
print("inline comment failed: %s position=%s %s" % (target, position, msg))

print("inline comments created: %s" % created)
return 0


if __name__ == "__main__":
sys.exit(main())
Loading
Loading