Archived
汇报流:活动按步序位置推视图,容器沙箱渲染
「flow:按**步序位置**推送声明的模版」(AM 07)。原先这条链只有写面没有读面,
活动的 viewTemplates 是一行占位字符串,工作台视图区永远只显示一份硬编码概览。
补齐整条链:
· 步声明新增 `view`:这一步呈现哪张模版 —— 推什么由声明给定,不由临场决定。
· 新增模版填数的纯函数(interaction/domain):`data-slot` 取值、`data-rows` 逐条展开。
**填数只做取值与转义**,没有表达式、没有分支、没有循环 —— 一旦模版能算,
它就成了代码,容器的「无脚本执行权」也就形同虚设。填充**消费槽位**,
交出去的是干净 HTML,不是带模板属性的半成品。
· interaction 补读面 `viewOf`;desk 路由把推送的 HTML 交给前端;
ViewRegion 经 `@ui` 的 ViewContainer(sandbox="" 的 iframe)渲染 —— feature 不碰 innerHTML。
· A1 写了三张真模版(事态全景 / 打标判据 / 成果预览),内联自带样式
(沙箱页面不继承工作台 CSS),按步序位置挂在 S3 / S5 / S6 上。
沿路两处修:
① 取值路径遇到**本身带点号的键**(台账地址 `域.对象`)会被拆成两级、永远取不到。
改为整键优先、找不到再下行;`view-render` 与 `step-sequence` 两处同修。
② 「本单交付」不能画成台账全表:任务视图是正式版 + 我的草稿的合并结果,
直接拿来列会把**别单**放行过的记录一并列出。本单自己写下的行单独放在
`mine:域.对象` 下(整键,取值不歧义)。
另:视图推送失败原先静默吞掉 —— 会让「视图区一直空着」变成查不出原因的怪事;
改为留痕(仍不影响步序推进,呈现是投影)。
实测:一封 RFQ 入站 → 放行前那一屏列出本单交付 LM358DR / TI / 12000 / 8.2 / 10周,
以及 Type A「直接快答」的分类结论与四项打标判据。
gates: tsc / eslint / depcruise(321 模块)/ api-report / 423 测试 全绿
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
This commit is contained in:
@@ -82,17 +82,19 @@ export function registerDeskRoutes(app: Hono<AppEnv>, container: Container): voi
|
||||
const taskId = taskIdSchema.parse(c.req.param('taskId'));
|
||||
const task = await container.task.get(taskId);
|
||||
|
||||
const [workOrders, chat, lines] = await Promise.all([
|
||||
const [workOrders, chat, lines, pushed] = await Promise.all([
|
||||
container.humanTool.openWorkOrders(taskId),
|
||||
container.interaction.timeline(taskId),
|
||||
container.memory.taskLog(taskId),
|
||||
container.interaction.viewOf(taskId),
|
||||
]);
|
||||
const cards = await container.humanTool.chatCards(taskId);
|
||||
|
||||
// 对话流 = 时间线 + 对话卡族,按时间全序 —— 与任务记忆同源、不同筛选
|
||||
const merged: ChatMessage[] = [...chat, ...cards].sort((a, b) => (a.at < b.at ? -1 : a.at > b.at ? 1 : 0));
|
||||
|
||||
// 视图区:活动推送的结构化块(尚无推送时给一份进度概览,不留空屏)
|
||||
// 视图区:活动推的 HTML 优先(它是活动按局面组织的完整一屏);
|
||||
// 尚无推送时给一份进度概览,不留空屏
|
||||
const view: ViewBlock[] = [
|
||||
{
|
||||
t: 'kv',
|
||||
@@ -119,7 +121,8 @@ export function registerDeskRoutes(app: Hono<AppEnv>, container: Container): voi
|
||||
deliverables: [],
|
||||
workOrders,
|
||||
chat: merged,
|
||||
view,
|
||||
view: pushed?.blocks !== undefined ? [...pushed.blocks] : view,
|
||||
...(pushed?.html === undefined ? {} : { viewHtml: pushed.html }),
|
||||
log: lines.map((l) => ({
|
||||
id: l.id,
|
||||
at: l.at,
|
||||
|
||||
@@ -10,6 +10,7 @@ import type { LedgerService } from '@modules/ledger';
|
||||
import type { MemoryService } from '@modules/memory';
|
||||
import type { ToolboxService, ToolInvoker } from '@modules/toolbox';
|
||||
import type { HumanToolService } from '@modules/human-tool';
|
||||
import { renderView } from '@modules/interaction';
|
||||
import type { InteractionService } from '@modules/interaction';
|
||||
import type { MessageService } from '@modules/message';
|
||||
import type { OrgService } from '@modules/org';
|
||||
@@ -285,6 +286,31 @@ export function wireEngines(deps: EngineWiringDeps): EngineWiring {
|
||||
data: taskData,
|
||||
tools: { ...toolGateway, invoke: (i) => toolGateway.invoke(i) },
|
||||
schemas: deps.schemas,
|
||||
views: {
|
||||
/*
|
||||
* 按名取模版 → 填数 → 推给前端。
|
||||
* 模版取自**该任务装载时的资产版本**(经 registry),不是「当前最新」——
|
||||
* 在途任务按其启动时版本跑完,呈现也该跟着那一版。
|
||||
*/
|
||||
async push({ taskId, activityId, template, scope }) {
|
||||
const manifest = await deps.registry.manifestOf(activityId);
|
||||
const found = manifest.assets.viewTemplates.find((t) => t.name === template);
|
||||
if (found === undefined) return;
|
||||
|
||||
/*
|
||||
* 视图作用域 = 任务视图 + **本单自己写下的行**。
|
||||
* 两者要分得开:任务视图里的 `域.对象` 是正式版 + 我的草稿的合并结果,
|
||||
* 拿它画「本单交付」会把别单放行过的记录一并列出来。
|
||||
* 本单的行放在 `mine:域.对象` 下 —— 整键,取值不歧义。
|
||||
*/
|
||||
const own: Record<string, unknown[]> = {};
|
||||
for (const draft of await deps.ledger.taskDrafts(taskId)) {
|
||||
const key = `mine:${draft.domain}.${draft.object}`;
|
||||
(own[key] ??= []).push({ ...draft.key, ...draft.patch });
|
||||
}
|
||||
await deps.interaction.pushViewHtml(taskId, renderView(found.html, { ...scope, ...own }));
|
||||
},
|
||||
},
|
||||
llm: {
|
||||
async generate(input) {
|
||||
// LLM 在 flow 里只以「被调用的工具」出现,不是调度者
|
||||
|
||||
Reference in New Issue
Block a user