ref: simplify feishu history injection, tune web_scan/plan_sop/driver
This commit is contained in:
@@ -102,11 +102,9 @@ class GeneraticAgent:
|
|||||||
handler.key_info += '\n[SYSTEM] 若开始新任务,先更新或清除工作记忆\n'
|
handler.key_info += '\n[SYSTEM] 若开始新任务,先更新或清除工作记忆\n'
|
||||||
self.handler = handler
|
self.handler = handler
|
||||||
self.llmclient.backend = self.llmclient.backends[self.llm_no]
|
self.llmclient.backend = self.llmclient.backends[self.llm_no]
|
||||||
# 如果有历史记录且来自飞书,注入到首轮 user_input 中(支持/restore恢复上下文)
|
|
||||||
user_input = raw_query
|
user_input = raw_query
|
||||||
if source == 'feishu' and len(self.history) > 1: # 飞书场景且有之前的对话记录
|
if source == 'feishu' and len(self.history) > 1: # 如果有历史记录且来自飞书,注入到首轮 user_input 中(支持/restore恢复上下文)
|
||||||
h_str = "\n".join(self.history[-20:])
|
user_input = handler._get_anchor_prompt() + f"\n\n### 用户当前消息\n{raw_query}"
|
||||||
user_input = f"### [WORKING MEMORY]\n<history>\n{h_str}\n</history>\n\n### 用户当前消息\n{raw_query}"
|
|
||||||
gen = agent_runner_loop(self.llmclient, sys_prompt, user_input,
|
gen = agent_runner_loop(self.llmclient, sys_prompt, user_input,
|
||||||
handler, TOOLS_SCHEMA, max_turns=40, verbose=self.verbose)
|
handler, TOOLS_SCHEMA, max_turns=40, verbose=self.verbose)
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -45,16 +45,13 @@
|
|||||||
console.log(log_prefix + `检测到opener,丢弃继承的window.name: ${window.name}`);
|
console.log(log_prefix + `检测到opener,丢弃继承的window.name: ${window.name}`);
|
||||||
window.name = '';
|
window.name = '';
|
||||||
} else {
|
} else {
|
||||||
sid = (window.name && window.name.startsWith('ljq_')) ?
|
sid = (window.name && window.name.startsWith('ljq_')) ? window.name : null;
|
||||||
window.name : window.sessionStorage.getItem('ljq_driver_sid');
|
|
||||||
}
|
}
|
||||||
if (!sid) {
|
if (!sid) {
|
||||||
sid = `ljq_${Date.now().toString().slice(-2)}${Math.random().toString(36).slice(2, 4)}`;
|
sid = `ljq_${Date.now().toString().slice(-2)}${Math.random().toString(36).slice(2, 4)}`;
|
||||||
window.sessionStorage.setItem('ljq_driver_sid', sid);
|
|
||||||
window.name = sid;
|
window.name = sid;
|
||||||
console.log(log_prefix + `创建新会话ID: ${sid}`);
|
console.log(log_prefix + `创建新会话ID: ${sid}`);
|
||||||
} else {
|
} else {
|
||||||
if (window.name !== sid) window.name = sid;
|
|
||||||
console.log(log_prefix + `使用现有会话ID: ${sid}`);
|
console.log(log_prefix + `使用现有会话ID: ${sid}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
4
ga.py
4
ga.py
@@ -135,7 +135,7 @@ def web_scan(tabs_only=False, switch_tab_id=None):
|
|||||||
"active_tab": driver.default_session_id
|
"active_tab": driver.default_session_id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if not tabs_only: result["content"] = get_html(driver, cutlist=True, maxchars=23000)
|
if not tabs_only: result["content"] = get_html(driver, cutlist=True, maxchars=28000)
|
||||||
return result
|
return result
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return {"status": "error", "msg": format_error(e)}
|
return {"status": "error", "msg": format_error(e)}
|
||||||
@@ -485,7 +485,7 @@ class GenericAgentHandler(BaseHandler):
|
|||||||
return prompt
|
return prompt
|
||||||
|
|
||||||
def next_prompt_patcher(self, next_prompt, outcome, turn):
|
def next_prompt_patcher(self, next_prompt, outcome, turn):
|
||||||
if turn % 30 == 0:
|
if turn % 35 == 0 and 'plan' not in str(self.related_sop):
|
||||||
next_prompt += f"\n\n[DANGER] 已连续执行第 {turn} 轮。你必须总结情况进行ask_user,不允许继续重试。"
|
next_prompt += f"\n\n[DANGER] 已连续执行第 {turn} 轮。你必须总结情况进行ask_user,不允许继续重试。"
|
||||||
elif turn % 7 == 0:
|
elif turn % 7 == 0:
|
||||||
next_prompt += f"\n\n[DANGER] 已连续执行第 {turn} 轮。禁止无效重试。若无有效进展,必须切换策略:1. 探测物理边界 2. 请求用户协助。如有需要,可调用 update_working_checkpoint 保存关键上下文。"
|
next_prompt += f"\n\n[DANGER] 已连续执行第 {turn} 轮。禁止无效重试。若无有效进展,必须切换策略:1. 探测物理边界 2. 请求用户协助。如有需要,可调用 update_working_checkpoint 保存关键上下文。"
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ L3: ../memory/ (记录库层 - 包含 .md/.py 等各类文件)
|
|||||||
| L2/L3 修改值 | 若不影响场景定位则不动 L1 |
|
| L2/L3 修改值 | 若不影响场景定位则不动 L1 |
|
||||||
| 发现通用避坑规律 | 压缩为一句加入 RULES |
|
| 发现通用避坑规律 | 压缩为一句加入 RULES |
|
||||||
|
|
||||||
> **同步红线**:L1 只写关键词/名称,禁搬细节。
|
> **同步红线**:L1 只写关键词/名称,禁搬细节。需要评估L1中的token数和索引效用。
|
||||||
|
|
||||||
---
|
---
|
||||||
## 信息分类快速决策树
|
## 信息分类快速决策树
|
||||||
|
|||||||
@@ -1,36 +1,70 @@
|
|||||||
# Plan Mode SOP
|
# Plan Mode SOP
|
||||||
|
|
||||||
> 简单任务(1-2步可完成)无需本SOP,直接做。
|
> 简单任务(1-2步可完成)禁用本SOP,直接做。
|
||||||
|
|
||||||
## 0. 基本协议
|
文件命名:`./plan_XXX.md`(XXX = 任务英文短名)。结果文件放 `./`,路径回填计划文件。禁建子目录。
|
||||||
|
|
||||||
进入 plan mode 后,立即调用 `update_working_checkpoint`,内容包含:
|
---
|
||||||
|
|
||||||
1. **PLAN**:初始为 `[ ] 规划` `[ ] 执行`,规划完成后展开为详细 checklist
|
## 规划态(按序执行,不可跳步)
|
||||||
2. **RULES**(以下三条原文写入,每次 update 必须保留):
|
|
||||||
- 一次只做一步,完成后标 [x] 并 update checkpoint
|
|
||||||
- 每次 checkpoint 必须保留完整 PLAN + RULES
|
|
||||||
- 全部 [x] 才可收尾
|
|
||||||
|
|
||||||
## 1. 规划阶段
|
[] **步骤1:存checkpoint(含格式模板)**
|
||||||
|
|
||||||
初始 checkpoint:`[ ] 规划` `[ ] 执行`。"规划"完成 = 展开执行步骤并 update checkpoint。
|
调用 `update_working_checkpoint`,**必须**使用以下格式([格式]字段不可省略):
|
||||||
|
```
|
||||||
|
[任务] 产出 plan_XXX.md | [需求] 用户原始需求一句话
|
||||||
|
[格式] 骨架每项必须用 - [ ] 开头,禁止###标题。模板:- [ ] 项目简述 | 方法:做法 | 验证:判据
|
||||||
|
[进度] 即将读领域SOP | ⚡写完plan后必须重读本SOP步骤3,按其模板切checkpoint再执行
|
||||||
|
```
|
||||||
|
|
||||||
### 1a. 读 SOP
|
[] **步骤2:读领域SOP → 写plan骨架 `./plan_XXX.md`**
|
||||||
查 insight 找相关 SOP 并读取——SOP 提供任务骨架,直接指导分解。无则跳过。不确定性最高的环节先探,其结果可能推翻整个计划。
|
|
||||||
|
|
||||||
### 1b. 分类
|
先读取相关领域SOP了解步骤,然后**立即**写骨架。不需要完美,**允许方法写"⚠待确认"**。禁止以"还没调研清楚"为由推迟。
|
||||||
从依赖关系读出结构:有依赖→Sequential | 无依赖→MAP | 条件未知→Branch。可嵌套。
|
|
||||||
|
|
||||||
### 1c. 分解
|
**⚠ 骨架格式以checkpoint中[格式]字段为准,不要模仿领域SOP的排版。**
|
||||||
按结构展开 checklist。**每个子任务必须具体列出,禁止笼统描述**(如"批量处理所有文件"必须展开为每个文件的具体条目)。每步须有独立完成判据,否则继续拆。update checkpoint 并标 `[x] 规划`。
|
|
||||||
- Seq: `[ ]A → [ ]B → [ ]C`
|
|
||||||
- MAP: `[ ]D1 [ ]D2 [ ]D3 … → [ ]汇总`(汇总为最后一步,中心化执行)
|
|
||||||
- Branch: `[ ]尝试X → 成功:[ ]Y / 失败:[ ]Z`
|
|
||||||
|
|
||||||
## 2. 执行注意
|
骨架模板:
|
||||||
|
```
|
||||||
|
# 任务标题
|
||||||
|
需求:一句话 | 约束:关键限制
|
||||||
|
|
||||||
- 计划有误时回到规划修正,不硬凑;不可逆操作前多验证一步
|
- [ ] 项目1简述 | 方法:具体做法 | 验证:完成判据
|
||||||
- MAP 的子任务可用 subagent 并行执行
|
- [ ] 项目2简述 | 方法:⚠待确认 | 验证:完成判据
|
||||||
- 步骤间用尽量用文件传递中间结果和汇总,不靠上下文记忆
|
- [ ] 项目3简述 | 方法:具体做法 | 验证:完成判据
|
||||||
- 收尾:全部 `[x]` 后汇总结果,清理 checkpoint
|
```
|
||||||
|
|
||||||
|
- 有⚠待确认项 → 逐项探索补充,**每轮必须更新plan文件 + checkpoint的[进度]**
|
||||||
|
- 连续3轮探索无实质进展 → **必须停止**,用当前最佳方案替代
|
||||||
|
- 无⚠待确认项 → 直接进入步骤3
|
||||||
|
|
||||||
|
**⛔ 写完骨架后禁止执行任何项目。必须先完成步骤3。**
|
||||||
|
|
||||||
|
[] **步骤3:转入执行态(⛔ 不可跳过)**
|
||||||
|
|
||||||
|
**写完plan骨架后,必须先执行此步骤再开始做任何项目。**
|
||||||
|
调用 `update_working_checkpoint`,只放**当前一步**(禁止塞全部步骤):
|
||||||
|
```
|
||||||
|
[执行] plan_XXX.md | 当前:Step1简述 | ⚡完成后必须:1.file_patch plan把当前步[ ]改[x] 2.读plan找下个[ ] 3.update_working_checkpoint为下步(保留本模板格式)
|
||||||
|
```
|
||||||
|
|
||||||
|
**执行循环(每步重复):**
|
||||||
|
1. 读 `plan_XXX.md` → 定位当前 `- [ ]` 项
|
||||||
|
2. 执行该项(参照领域SOP)
|
||||||
|
3. 按checkpoint中⚡指令完成收尾(标[x]→找下步→更新checkpoint)
|
||||||
|
4. 全部完成 → 汇总结果 → 清理checkpoint
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 项目类型(三选一或嵌套)
|
||||||
|
- **步骤**:有先后依赖,顺序执行
|
||||||
|
- **方面**:并行独立,无依赖
|
||||||
|
- **分支**:条件未知,尝试X → 成功走Y / 失败走Z
|
||||||
|
|
||||||
|
## 强制约束
|
||||||
|
|
||||||
|
- 每项**必须**有独立完成判据,禁止笼统描述
|
||||||
|
- 禁止出现"处理所有文件"类表述,**必须**展开为具体条目
|
||||||
|
- 一次只做一项,禁止批量执行
|
||||||
|
- 计划有误回到规划态修正,禁止硬凑
|
||||||
|
- 不可逆操作前多验证一步
|
||||||
|
- 并行方面可用 subagent 执行
|
||||||
@@ -84,7 +84,11 @@ document.body.appendChild(el); // 响应写回el.textContent
|
|||||||
- 验证码canvas/img:JS `canvas.toDataURL()` 直接拿base64最干净
|
- 验证码canvas/img:JS `canvas.toDataURL()` 直接拿base64最干净
|
||||||
- 备选:`window.open(location.href,'_blank')` 前台开新标签→win32截图→完后close
|
- 备选:`window.open(location.href,'_blank')` 前台开新标签→win32截图→完后close
|
||||||
- GM_openInTab在web_execute_js不可用(非油猴上下文)
|
- GM_openInTab在web_execute_js不可用(非油猴上下文)
|
||||||
- 浏览器无JS API切标签页,只能开新的来保证前台
|
|
||||||
|
## 直接import(仅作调试使用)
|
||||||
|
- `sys.path.insert(0, GenericAgent根目录)`, `from TMWebDriver import TMWebDriver`
|
||||||
|
- `d=TMWebDriver()`, `d.set_session('url_pattern')`, `d.execute_js('code')` → 返回`{'data': value}`(非裸值)
|
||||||
|
- 配合simphtml:`str(simphtml.optimize_html_for_tokens(html))` → 注意返回BS4 Tag需str()
|
||||||
|
|
||||||
## 跨域iframe操控(postMessage中继)
|
## 跨域iframe操控(postMessage中继)
|
||||||
- 跨域iframe的contentDocument不可访问,web_execute_js只在顶层执行
|
- 跨域iframe的contentDocument不可访问,web_execute_js只在顶层执行
|
||||||
|
|||||||
Reference in New Issue
Block a user