// 内置工具包 C:页面操作。给助手"在用户当前那张页面上填写/点击"的通用手脚。 // // 为什么沉在 soma-ai 而不是各宿主自己写:按 label 找输入框、按可见文字找按钮、 // 用原生 setter 赋值再冒泡 input/change 兼容受控组件——这套 DOM 手法与业务系统无关, // 每个宿主重写一遍只会各错各的。宿主之间真正不同的只有两件事:哪个 document 是 // "用户当前正在看的页面"(iframe 标签页 / 弹层 / 整页),以及失败了怎么告诉用户。 // 这两件事由宿主在浏览器侧用 mountPageOperateEffect 的适配点提供。 // // 与其余内置包不同,本包**缺省关闭**:工具执行体在服务端只发指令,真正动手的是 // 浏览器侧的事件桥。宿主没接桥就开了本包,模型会以为自己点了按钮、用户却什么也没看见—— // 这种"嘴上成功"的假象比少一个能力糟得多,所以要宿主显式开: // assistant: // toolkits: // page-operate: { enabled: true } import { createPageOperateTools } from '../page-operate/PageOperateTools'; import { PAGE_OPERATE_TOOL } from '../page-operate/PageOperateContract'; import type { AssistantToolBundle, AssistantToolDisplay, AssistantToolkit, } from './AssistantToolkit'; export const PAGE_OPERATE_TOOLKIT_NAME = 'page-operate'; /** 对用户只说"在页面上操作",不暴露选择器与 DOM 细节。 */ const PAGE_OPERATE_DISPLAY: AssistantToolDisplay = { pending: '正在操作页面…', done: '已在页面上执行操作', error: '页面操作失败', }; /** * 能力段刻意写"当前打开的页面",不提 iframe/标签页:宿主形态各异, * 提示词只描述用户视角的事实。 */ const PAGE_OPERATE_CAPABILITY = [ '- 页面操作:可以在用户当前打开的页面上代为填写输入框、选择下拉项、点击按钮,', '一次一步;控件用页面上看得见的文字指认(输入框用它的标签,按钮用按钮文字)。', '只操作用户当前正在看的那张页面:要操作别的页面,先把那个页面打开再操作。', '同一轮里某一步失败后,后续步骤会被系统拦下不再执行(避免拿没填上的数据去提交),', '所以不要在失败后继续下指令,应如实告知用户哪一步没做到。', '删除、停用、清空、审批这类不可逆操作需要用户自己点确认,你可以把用户带到那一步,但不要代点。', '每步的真实结果会在下一轮以「最近几步页面操作的真实结果」给到你;在拿到它之前,', '不要断言操作后的页面状态,也不要替用户宣布业务结果。', ].join(''); export const pageOperateToolkit: AssistantToolkit = { name: PAGE_OPERATE_TOOLKIT_NAME, defaultEnabled: false, create(): AssistantToolBundle { return { tools: createPageOperateTools(), display: { [PAGE_OPERATE_TOOL]: PAGE_OPERATE_DISPLAY }, systemPrompt: PAGE_OPERATE_CAPABILITY, }; }, };