delete_project: Conform confirm dialog + _sys_delete_project + system action bypass
This commit is contained in:
parent
dedb2a60e1
commit
a2106e4365
@ -161,9 +161,14 @@ async def _exec_tool(sor, tool, params, ctx, uid, org_id):
|
||||
return f'OK: 已创建并切换到「{name}」'
|
||||
elif tool == 'delete_project':
|
||||
name = (p.get('project','') or '').strip()
|
||||
confirm = (p.get('confirm','') or '').strip()
|
||||
if not name: return 'FAIL: 需要项目名称'
|
||||
if confirm != name: return f'FAIL: 确认不匹配(需输入"{name}"确认)'
|
||||
proj = await _find_project(sor, name)
|
||||
if not proj: return f'FAIL: 项目「{name}」不存在'
|
||||
# Yield Conform widget — actual deletion happens via _sys_delete_project
|
||||
return json.dumps({"widgettype":"Conform","options":{"message":f"确定要删除项目「{name}」吗?此操作不可撤销,将清除所有关联数据。","conform":{"label":"确认删除","name":"conform"},"discard":{"label":"取消","name":"discard"},"_action":"_sys_delete_project","_payload":{"project":name}}},ensure_ascii=False)
|
||||
elif tool == '_sys_delete_project':
|
||||
name = (p.get('project','') or '').strip()
|
||||
if not name: return 'FAIL: 缺少项目名称'
|
||||
proj = await _find_project(sor, name)
|
||||
if not proj: return f'FAIL: 项目「{name}」不存在'
|
||||
pid = proj.id
|
||||
@ -360,6 +365,19 @@ if action == 'send_message':
|
||||
user_model_id = inner.get('model_id') or inner.get('llmid') or user_model_id
|
||||
if not message_text: return json.dumps({"error":"message_text is required"},ensure_ascii=False)
|
||||
|
||||
# ── System action: bypass LLM, execute directly ──
|
||||
sys_action = p.get('_system_action', '')
|
||||
if sys_action:
|
||||
async def sys_stream():
|
||||
async with DBPools().sqlorContext(dbname) as sor:
|
||||
uid = await get_user()
|
||||
org_id = await get_userorgid() or '0'
|
||||
ctx = await _load_ctx(sor, uid)
|
||||
result = await _exec_tool(sor, sys_action, p, ctx, uid, org_id)
|
||||
d = json.dumps(_w_text(result), ensure_ascii=False)+'\n'
|
||||
yield d
|
||||
return await stream_response(request, sys_stream, 'text/plain; charset=utf-8')
|
||||
|
||||
blocked, reason = _security_scan(message_text)
|
||||
if blocked: return json.dumps({"success":True,"agent_reply":f"⚠️ {reason}"},ensure_ascii=False)
|
||||
|
||||
@ -398,8 +416,12 @@ if action == 'send_message':
|
||||
debug(f"YIELD progress: {d[:60]}")
|
||||
yield d
|
||||
result = await _exec_tool(sor, tool, act.get('params',{}), ctx, uid, org_id)
|
||||
ok = result.startswith("OK:")
|
||||
d = json.dumps(_w_card(label, _w_text(result), "success" if ok else "error"), ensure_ascii=False)+'\n'
|
||||
# If result is a raw widget descriptor, yield it directly
|
||||
if result.startswith('{"widgettype":'):
|
||||
d = result + '\n'
|
||||
else:
|
||||
ok = result.startswith("OK:")
|
||||
d = json.dumps(_w_card(label, _w_text(result), "success" if ok else "error"), ensure_ascii=False)+'\n'
|
||||
debug(f"YIELD result: {d[:60]}")
|
||||
yield d
|
||||
msgs.append({"role":"assistant","content":raw})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user