Files
next-tjwater-agent/.opencode/tools/present_answer.ts
T
jiang 6336157ff4
Generic Container CI/CD / test-build-publish (push) Successful in 1m6s
Agent CI/CD / build-test-publish-and-deploy (push) Successful in 1m7s
feat: upgrade investigation and presentation runtime
2026-10-30 17:30:19 +08:00

45 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { tool } from "../tool.js";
import { answerUiInputSchema } from "../../src/chat/answer-ui.js";
import catalog from "../../src/chat/answer-ui-catalog.json" with { type: "json" };
// These complete call pairs also serve as executable contract examples in tests.
export const answerUiExamples: Array<{
present_answer: ReturnType<typeof answerUiInputSchema.parse>;
final_answer: { answer: string; ui_block_ids: string[] };
}> = [
{
present_answer: {
phase: "final" as const, block_id: "demo_comparison", fallback_text: "演练资料:甲管径 300 mm,乙管径 200 mm。",
spec: { root: "table", elements: { table: {
type: "Table", props: { title: "管径比较(用户提供的演练资料)", columns: ["对象", "管径(mm)"], rows: [["甲", "300"], ["乙", "200"]] }, children: [],
} } },
},
final_answer: { answer: "甲的管径较大,不能仅凭管径判断实际供水能力。\n\n[[ui:demo_comparison]]", ui_block_ids: ["demo_comparison"] },
},
{
present_answer: {
phase: "final" as const, block_id: "demo_trend", fallback_text: "演练资料:08:00、09:00、10:00 压力依次为 0.30、0.28、0.18 MPa。",
spec: { root: "chart", elements: { chart: {
type: "Chart", props: { title: "压力变化(MPa)", chart_type: "line", x_data: ["08:00", "09:00", "10:00"], series: [{ name: "压力(MPa)", data: [0.30, 0.28, 0.18] }], source: "用户提供的演练资料,非现场实测" }, children: [],
} } },
},
final_answer: { answer: "演练序列中后一个时段下降更明显,原因仍需其他证据判断。\n\n[[ui:demo_trend]]", ui_block_ids: ["demo_trend"] },
},
];
export default tool({
description: "把已有资料发布为保留在聊天中的交互内容。多对象同类字段比较优先用 Table,数值时间序列分析优先用 Chart,不等用户指定组件;简单解释、单个事实和简短确认直接用文字。用户明确要求纯文字时遵从。工作台窗口与地图动作另用 present_view。spec 是 root + elements 的扁平树,每个元素包括 type、props、children;单个组件可以直接作为 root。关键指标用 Metric,复杂结果用 Result(status 必须有真实依据),可复核依据用 Evidence,反复定位入口用 MapLocation,最终答复后的可选补充用 FollowUpForm。只组织查询结果或用户提供的资料,保留来源、单位、范围及演练标识;缺数不补造、不补零,不为布局凑卡片。无脚本、URL、CSS 或任意代码。Result 不执行动作,演练或记录成功不等于现场成功;发布不执行地图或业务动作,也不等待浏览器。Stack 的 columns/gap 仍必填,可选 intent=response|comparison|report、density=compact|comfortable;Section 可选 role=result|analysis|evidence|follow_up,Text 可选 title。需要保留的内容直接显式 phase=final,无须先发布 process;仅临时过程材料用 phase=process,省略仍默认 process。相同 block_id 只能同 phase 更新;过程材料转为最终内容须另用 block_id。final_answer 前完成所有更新,并通过独立正文锚点和 ui_block_ids 引用 final 块,正文不抄写整表或重复全文。下列是两组独立的最小调用示例,实际调用必须替换为本轮资料和 ID,不能复用演练数值:" + JSON.stringify(answerUiExamples) + "。组件参数的 JSON Schema:" + JSON.stringify(catalog.props),
args: {
phase: tool.schema.enum(["process", "final"]).optional().describe("保留在最终答复中的内容显式填 final;临时核查材料填 process。省略默认 process。"),
block_id: tool.schema.string().regex(/^[a-zA-Z0-9_-]{1,80}$/),
fallback_text: tool.schema.string().min(1).max(4000),
spec: tool.schema.object({ root: tool.schema.string(), elements: tool.schema.record(tool.schema.string(), tool.schema.object({
type: tool.schema.string(), props: tool.schema.record(tool.schema.string(), tool.schema.unknown()), children: tool.schema.array(tool.schema.string()).max(48),
}).strict()) }).strict(),
},
async execute(args) {
const value = answerUiInputSchema.parse(args);
return JSON.stringify({ version: "answer-ui@1", ...value, phase: value.phase ?? "process", recorded: true });
},
});