file_read: default 200 lines, total line count report, fix L_MAX dynamic calc
This commit is contained in:
@@ -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
19
ga.py
@@ -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,
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
选择规则:
|
选择规则:
|
||||||
- cwd下有 `TODO.txt` 时优先执行其中任务,完成后移除条目
|
- cwd下有 `TODO.txt` 时优先执行其中任务,完成后移除条目
|
||||||
- 不连续选择相同方向(TODO除外),选择前先读 history.txt 了解近期已做方向
|
- 不连续选择相同方向(TODO除外),选择前先读 history.txt 了解近期已做方向
|
||||||
|
- 方向平衡:近10轮内同一方向≤3次,同一具体主题(如"磁盘健康""书签")不重复
|
||||||
- 选定后先声明一句话预期收益,写入报告开头
|
- 选定后先声明一句话预期收益,写入报告开头
|
||||||
|
|
||||||
目标排序(按价值递减):
|
目标排序(按价值递减):
|
||||||
|
|||||||
@@ -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自己也可以处理其中一个)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user