file_read: default 200 lines, total line count report, fix L_MAX dynamic calc

This commit is contained in:
Liang Jiaqing
2026-02-24 09:24:40 +08:00
parent ac2f8ad1e1
commit e808ce6878
5 changed files with 16 additions and 10 deletions

View File

@@ -13,7 +13,7 @@
"parameters": {"type": "object", "properties": { "parameters": {"type": "object", "properties": {
"path": {"type": "string", "description": "文件相对或绝对路径。"}, "path": {"type": "string", "description": "文件相对或绝对路径。"},
"start": {"type": "integer", "description": "起始行号(从 1 开始)。", "default": 1}, "start": {"type": "integer", "description": "起始行号(从 1 开始)。", "default": 1},
"count": {"type": "integer", "description": "读取的行数。", "default": 100}, "count": {"type": "integer", "description": "读取的行数。", "default": 200},
"keyword": {"type": "string", "description": "可选搜索关键字。如果提供,将返回第一个匹配项(忽略大小写)及其周边的内容。"}, "keyword": {"type": "string", "description": "可选搜索关键字。如果提供,将返回第一个匹配项(忽略大小写)及其周边的内容。"},
"show_linenos": {"type": "boolean", "description": "是否显示行号,建议开启以辅助 file_patch 定位。", "default": true}}, "required": ["path"]} "show_linenos": {"type": "boolean", "description": "是否显示行号,建议开启以辅助 file_patch 定位。", "default": true}}, "required": ["path"]}
}}, }},

19
ga.py
View File

@@ -194,13 +194,9 @@ def file_patch(path: str, old_content: str, new_content: str):
return {"status": "error", "msg": str(e)} return {"status": "error", "msg": str(e)}
def file_read(path, start=1, keyword=None, count=200, show_linenos=True): def file_read(path, start=1, keyword=None, count=200, show_linenos=True):
L_MAX = max(100, 1024000//count); TAG = " ... [TRUNCATED]"
try: try:
with open(path, 'r', encoding='utf-8', errors='replace') as f: with open(path, 'r', encoding='utf-8', errors='replace') as f:
stream = ( stream = ((i, l.rstrip('\r\n')) for i, l in enumerate(f, 1))
(i, (l[:L_MAX].rstrip() + TAG if len(l) > L_MAX else l.rstrip('\r\n')))
for i, l in enumerate(f, 1)
)
stream = itertools.dropwhile(lambda x: x[0] < start, stream) stream = itertools.dropwhile(lambda x: x[0] < start, stream)
if keyword: if keyword:
before = collections.deque(maxlen=count//3) before = collections.deque(maxlen=count//3)
@@ -211,8 +207,15 @@ def file_read(path, start=1, keyword=None, count=200, show_linenos=True):
before.append((i, l)) before.append((i, l))
else: return f"Keyword '{keyword}' not found after line {start}. Falling back to content from line {start}:\n\n" \ else: return f"Keyword '{keyword}' not found after line {start}. Falling back to content from line {start}:\n\n" \
+ file_read(path, start, None, count, show_linenos) + file_read(path, start, None, count, show_linenos)
else: res = itertools.islice(stream, count) else: res = list(itertools.islice(stream, count))
return "\n".join(f"{i}|{l}" if show_linenos else l for i, l in res) realcnt = len(res); L_MAX = max(100, 512000//realcnt); TAG = " ... [TRUNCATED]"
remaining = sum(1 for _ in itertools.islice(stream, 5000))
total_lines = (start - 1) + realcnt + remaining
total_tag = "[FILE] Total " + (f"{total_lines}+" if remaining >= 5000 else str(total_lines)) + ' lines\n'
res = [(i, l if len(l) <= L_MAX else l[:L_MAX] + TAG) for i, l in res]
result = "\n".join(f"{i}|{l}" if show_linenos else l for i, l in res)
if show_linenos: result = total_tag + result
return result
except Exception as e: except Exception as e:
return f"Error: {str(e)}" return f"Error: {str(e)}"
@@ -370,7 +373,7 @@ class GenericAgentHandler(BaseHandler):
path = self._get_abs_path(args.get("path", "")) path = self._get_abs_path(args.get("path", ""))
yield f"\n[Action] Reading file: {path}\n" yield f"\n[Action] Reading file: {path}\n"
start = args.get("start", 1) start = args.get("start", 1)
count = args.get("count", 100) count = args.get("count", 200)
keyword = args.get("keyword") keyword = args.get("keyword")
show_linenos = args.get("show_linenos", True) show_linenos = args.get("show_linenos", True)
result = file_read(path, start=start, keyword=keyword, result = file_read(path, start=start, keyword=keyword,

View File

@@ -28,6 +28,7 @@
选择规则: 选择规则:
- cwd下有 `TODO.txt` 时优先执行其中任务,完成后移除条目 - cwd下有 `TODO.txt` 时优先执行其中任务,完成后移除条目
- 不连续选择相同方向TODO除外选择前先读 history.txt 了解近期已做方向 - 不连续选择相同方向TODO除外选择前先读 history.txt 了解近期已做方向
- 方向平衡近10轮内同一方向≤3次同一具体主题如"磁盘健康""书签")不重复
- 选定后先声明一句话预期收益,写入报告开头 - 选定后先声明一句话预期收益,写入报告开头
目标排序(按价值递减): 目标排序(按价值递减):

View File

@@ -9,6 +9,8 @@
- 共享资源冲突:键鼠/浏览器主体不可共享浏览器可分tab但需谨慎subagent任务应限于文件处理 - 共享资源冲突:键鼠/浏览器主体不可共享浏览器可分tab但需谨慎subagent任务应限于文件处理
- 不满足map模式的任务 → 主agent顺序执行即可别用subagent - 不满足map模式的任务 → 主agent顺序执行即可别用subagent
**额外场景SOP dry-run验证**——启动单个subagent执行目标SOP通过output日志发现SOP缺陷缺参数/选择器不准/步骤模糊主agent据此patch优化SOP。单subagent不存在资源冲突。
**标准流程map-reduce** **标准流程map-reduce**
1. 主agent准备阶段爬取/dump数据存为多个独立输入文件 1. 主agent准备阶段爬取/dump数据存为多个独立输入文件
2. 分发对每个文件启动一个subagent处理主agent自己也可以处理其中一个 2. 分发对每个文件启动一个subagent处理主agent自己也可以处理其中一个

View File

@@ -55,7 +55,7 @@ class ClaudeSession:
headers = {"x-api-key": self.api_key, "Content-Type": "application/json", "anthropic-version": "2023-06-01"} headers = {"x-api-key": self.api_key, "Content-Type": "application/json", "anthropic-version": "2023-06-01"}
payload = {"model": model, "messages": messages, "temperature": temperature, "max_tokens": max_tokens, "stream": True} payload = {"model": model, "messages": messages, "temperature": temperature, "max_tokens": max_tokens, "stream": True}
try: try:
with requests.post(f"{self.api_base}/v1/messages", headers=headers, json=payload, stream=True, timeout=(5,60)) as r: with requests.post(f"{self.api_base}/v1/messages", headers=headers, json=payload, stream=True, timeout=(5,30)) as r:
r.raise_for_status() r.raise_for_status()
for line in r.iter_lines(): for line in r.iter_lines():
if not line: continue if not line: continue