Files
GenericAgent/reflect/goal_mode.py
T
dd3xp 362b7d601c chore: sync framework to upstream lsdefine/GenericAgent @ 1eb8c4c
Content-overlay update of all GA framework files from upstream base
b4393af (2026-05-18) to 1eb8c4c (2026-05-25). Applied as an overlay
because GADesktop and upstream share no common git history.

- 26 framework files brought to upstream: tui_v3 (new), fsapp rework,
  llmcore hardening, plugins/hooks lifecycle hooks, goal_mode prompt
  rewrite, supergrok_proxy, qq/tg/wechat/st apps, cost_tracker py3.9
  compat, docs; removed obsolete install scripts.
- Desktop frontend (frontends/desktop/*) and desktop_bridge.py left
  untouched. Upstream's only overlapping change (bridge mykey.txt->
  mykey.py) is already present in our version, so it is a no-op.
2026-05-25 22:03:19 +08:00

104 lines
3.6 KiB
Python

# reflect/goal_mode.py — Goal Mode: 持续自驱直到预算耗尽
# 启动: set GOAL_STATE=temp/xxx.json && python agentmain.py --reflect reflect/goal_mode.py
# 配置: agent按SOP写好state json,通过环境变量GOAL_STATE指定路径
import os, json, time
INTERVAL = 3 # check间隔短,agent跑完立刻再检查
ONCE = False
_dir = os.path.dirname(os.path.abspath(__file__))
STATE_FILE = ''
def init(a):
global STATE_FILE
STATE_FILE = a.get('goal_state') or os.environ.get('GOAL_STATE') or os.path.join(_dir, '../temp/goal_state.json')
if not os.path.isabs(STATE_FILE): STATE_FILE = os.path.join(_dir, '..', STATE_FILE)
# --- state 管理 ---
def _load():
if not os.path.isfile(STATE_FILE): return None
with open(STATE_FILE, 'r', encoding='utf-8') as f:
return json.load(f)
def _save(state):
with open(STATE_FILE, 'w', encoding='utf-8') as f:
json.dump(state, f, ensure_ascii=False, indent=2)
# --- prompt 模板 ---
CONTINUATION_PROMPT = """[Goal Mode — 持续推进]
<objective>
{objective}
</objective>
⏱ 已用 {elapsed_min:.0f} 分钟,剩余约 {remaining_min:.0f} 分钟。第 {turn} 次唤醒。
你正在 Goal Mode 下工作:
1. 禁止说"已完成,是否继续"——预算没到就不准停,不准提前交付,围绕核心成果质量不要额外产出。
2. 在 cwd 下建立工作文件夹存放成果和进度,读取记忆中可能对成果质量有帮助的原则。
3. 核心完成后,选你认为最能提升成果质量的方向,深入打磨。
如果多轮都是同类型的小修——换一个完全不同的角度重新审视,
找到新的薄弱点再深入。包括但不限于测试/边界case/性能/安全/文档/代码质量。
4. 换角度的方法:假装你是第一次看到这个成果的使用者/审阅者/攻击者,
找到它最容易出问题的地方,然后修它。
5. 要为了目标持续推进,在工作文件夹中记录进度,不要更新全局记忆。
"""
BUDGET_LIMIT_PROMPT = """[Goal Mode — 预算耗尽,收口]
<objective>
{objective}
</objective>
⏱ 预算已耗尽({budget_min:.0f} 分钟)。这是最后一轮。
请执行收口:
1. 总结本次 goal 的所有进展(列表)
2. 列出未完成的事项和建议的 next step
3. 确保工作文件夹中记录了关键成果
4. 清理一些确定无用的中间临时文件和不再用的进程
{done_prompt}
"""
# --- 主逻辑 ---
def check():
state = _load()
if state is None: return '/exit'
status = state.get('status', 'running')
if status != 'running': return '/exit'
start_time = state.get('start_time', time.time())
budget_sec = state.get('budget_seconds', 1800) # 默认30分钟
elapsed = time.time() - start_time
remaining = budget_sec - elapsed
turn = state.get('turns_used', 0) + 1
max_turns = state.get('max_turns', 50) # 防空转上限
# 预算耗尽或轮次上限
if remaining <= 0 or turn > max_turns:
state['status'] = 'wrapping_up'
_save(state)
return BUDGET_LIMIT_PROMPT.format(
objective=state['objective'],
budget_min=budget_sec / 60,
done_prompt=state.get('done_prompt', '')
)
# 正常continuation
state['turns_used'] = turn
_save(state)
return CONTINUATION_PROMPT.format(
objective=state['objective'],
elapsed_min=elapsed / 60,
remaining_min=remaining / 60,
turn=turn
)
def on_done(result):
state = _load()
if state is None: return
if state.get('status') == 'wrapping_up':
state['status'] = 'done_budget'
state['end_time'] = time.time()
_save(state)