新增: Agent 中继模式——u-relay 客户端接入远端 agent 指令链
This commit is contained in:
@@ -547,6 +547,45 @@ export async function chat(opts: {
|
||||
return { reply: r.reply, op: normalizeOp(r.op) }
|
||||
}
|
||||
|
||||
/** SEP 分隔标记(对话回复与 JSON 操作的分隔),导出给 relay 等 Transport 复用 */
|
||||
export const CHAT_SEP = SEP
|
||||
|
||||
/**
|
||||
* 解析 chat 协议回复文本:SEP 前为自然语言回复,SEP 后为 JSON 操作。
|
||||
* 供 AiPanel(SSE 路径)与 AgentPanel(relay 路径)共用,避免复制粘贴。
|
||||
*/
|
||||
export function parseChatReply(text: string): { reply: string; op: AiOp | null } {
|
||||
const parts = text.split(SEP)
|
||||
return {
|
||||
reply: (parts[0] || '').trim(),
|
||||
op: parts.length > 1 ? normalizeOp(tryParse(parts.slice(1).join(SEP))) : null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装 Agent 请求 prompt:用户指令 + chat 协议要求 + deck 上下文。
|
||||
* 大 deck(序列化 >700KB)降级为「当前页完整 JSON + 全deck大纲摘要」,防超 1MiB 帧上限。
|
||||
*/
|
||||
export function buildAgentPrompt(input: string): string {
|
||||
const SYS_AGENT =
|
||||
SYS_BASE +
|
||||
'\n任务:你是通过中继接入的远程 Agent。根据用户指令编辑当前演示。\n' +
|
||||
'回复格式:先用中文说明你将做什么,如需修改 PPT,在回复最后另起一行输出分隔标记 ' + SEP + ',紧随其后输出 JSON 操作。\n' +
|
||||
'JSON 操作格式:{"action":"add_page|update_page|create_all|answer","slides":[...],"target":页码(从1开始,可选)}\n' +
|
||||
'- add_page:在 target 页后插入新页;- update_page:替换 target 页;- create_all:整体替换;- answer:仅回答不改稿。\n' +
|
||||
'没有改动时不要输出分隔标记。不要使用 markdown 代码块。'
|
||||
const deck = store.getDeck()
|
||||
let body: string
|
||||
const full = JSON.stringify(deck)
|
||||
if (full.length > 700 * 1024) {
|
||||
// 超大 deck 降级:大纲摘要 + 当前页完整 JSON
|
||||
body = deckContext(store.getCurrentIndex(), null)
|
||||
} else {
|
||||
body = '完整 deck JSON:\n' + full + '\n当前页码:第 ' + (store.getCurrentIndex() + 1) + ' 页'
|
||||
}
|
||||
return SYS_AGENT + '\n\n' + body + '\n\n用户指令:' + input
|
||||
}
|
||||
|
||||
function normalizeOp(json: any): AiOp | null {
|
||||
if (!json) return null
|
||||
let action: AiOp['action'] = json.action || 'answer'
|
||||
|
||||
Reference in New Issue
Block a user