Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

plugin-chatbot: 助手回答里的图表总排在全部文字之后,模型先出图也到不了首屏(cloud#3072) #13492

Closed

Description

@objectstack-fleet

立卡门 ①:用户可见的体验缺陷,落点具名,staging 已复现。reach: 公开入口(控制台助手侧栏)实测一次。

业务理由: 受益的是在应用里打开「助手」做开放式分析的业务用户。维护者在 cloud#3072 直派的验收标准是「首屏能看到结论和至少一张图」。cloud 那一侧已经让 visualize_data 先出图(data-explorer 规范的出图规则:开放式分析先出图),但聊天组件不论顺序,总把图表放到全部文字之后,所以这条验收在 cloud 侧怎么改都达不成。不修的话,用户在侧栏里要先翻过六段文字才看到唯一一张图。

动手的读者: objectui domain:ui 车道,改 packages/plugin-chatbot。cloud#3072 的 cloud 侧(记录链接、坐标轴标签翻译)由 repo:cloud#2 并行修,不依赖本卡。

现象

2026-10-25 staging 实测(cloud#3072 评论 6392379430):huayan.objectos.app,HotCRM 5.1.2,侧栏视口 627 px,提问「帮我分析一下客户」。唯一的图「客户健康度分布」从 785 px 才开始,压在六段文字下面。

原因(objectui main 6f629a73,cloud 当前 pin fb25620e 同此)

  • packages/plugin-chatbot/src/mapMessages.ts:extractText()(约第 99 行)把一条消息的所有文本 part 拼成一个 content。data-chart part 被单独提到 charts[](约第 1354–1364 行),流里的先后顺序就此丢失。
  • packages/plugin-chatbot/src/ChatbotEnhanced.tsx:先渲染 <MessageResponse>{message.content}</MessageResponse>(约第 4180 行),再在 data-testid="chat-charts" 一块里渲染全部图表(约第 4203 行)。
  • 所以即使模型先调了 visualize_data 再写文字,图也只能排在全部文字之后。

预期

助手消息按流里的 part 顺序渲染:文本段与 data-chart 交错,先到的先显示。先出图、后写字的回答,首屏就是图。不需要新的通用块或 spec 契约:用的还是现有的 data-chart part 和 SDUI <chart> 渲染器,变的只是 part 的排列顺序。

验收

  • 单测:一条消息的 parts 依次是 data-chart、text,渲染后图在文字之前;依次是 text、data-chart、text,三者按原顺序渲染。
  • 已存消息重新加载(re-hydrate)后顺序不变。
  • 长答折叠(objectui#13032)与记录链接(objectui#13037)的行为不回退。
  • staging 用同一句「帮我分析一下客户」重测:首屏能看到至少一张图。

查重(objectui,含已关):


Generated by Claude Code

Activity

  1. added
    area:aiAI-native — agent / tool / skill metadata, and the MCP surface an agent drives
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    on Oct 25, 2026
  2. objectstack-fleet commented on Oct 25, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade — bug · priority:p1 · domain:ui · area:ai · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-25T02:52Z

    ⛔ Not a claim, ⛔ not a dispatch.

    • p1: the acceptance criterion the maintainer set directly on objectstack-ai/cloud#3072 (p1) is 「首屏能看到结论和至少一张图」. Nothing on the cloud side can meet it while plugin-chatbot flattens the parts. It inherits the parent's grade.
    • Route: domain:ui, packages/plugin-chatbot only (mapMessages.ts, ChatbotEnhanced.tsx): render a message's parts in stream order. No new block and no spec contract. The cloud side then reaches it through its objectui pin, so cloud#3072's staging re-test waits for that pin round.

    Generated by Claude Code

  3. objectstack-fleet commented on Oct 25, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 3 · 2026-10-25T03:56Z
    Session: session_01VWbYRWtBm3f8J2T8HAt97o (card thread 「助手回答图表按顺序显示」, dispatched by the domain:ui seat 4 session session_01XWGTsmqrtrt1Zqh1ioWqsT)
    Account: os-elon-musk
    Branch: claude/project-thread-49319q (platform-assigned)
    Worktree: objectui-issue-13492
    Domain: domain:ui
    Seat: domain:ui#4
    File surface: packages/plugin-chatbot/src/** (mapMessages.ts, ChatbotEnhanced.tsx and the message types they share); their tests; .changeset/13492-*.md (stop on breach; explain in the report)
    Container & model: M, card thread, model: default tier (no path-derived mandate), effort: xhigh (p1)
    Clause-②: no
    Metadata-protocol: none
    Responsibility: plugin-chatbot flattens a message's parts into one text + a trailing charts[] block, dropping stream order | render text and data-chart parts in their stream order | business users reading an assistant analysis in the console sidebar (cloud#3072's "first screen shows at least one chart")
    Thread-read: 6392664020
    Premise: holds — on objectui main 85b6a48, mapMessages.ts:99 extractText() joins every text part, :1362–1387 lifts data-chart parts into charts[], and ChatbotEnhanced.tsx renders the content before the chat-charts block (:4204)
    Serial constraints cleared: objectstack-ai/objectstack#25913 / PR #13495 (manifest sideEffects only) merged; seat 1's #13442 / #13449 / #13450 declare no plugin-chatbot/** path; no other open claim on plugin-chatbot
    Writes: all PR, comment and label writes go only through objectstack's relay (scripts/pm/fleet-write); never write with GitHub MCP.

  4. objectstack-fleet commented on Oct 25, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 13492,
      "status": "done",
      "branch": "claude/project-thread-49319q",
      "pr": "https://github.com/objectstack-ai/objectui/pull/13500",
      "session": "session_01VWbYRWtBm3f8J2T8HAt97o — card thread 「助手回答图表按顺序显示」",
      "premise_still_valid": true,
      "summary": "mapMessages now records on each data-chart where it arrived among the text parts (ChatChart.textOffset = length of the text extractText joined before it; only when content is that join, never for a legacy string content). ChatbotEnhanced splits content at those offsets (layoutAnswer) and renders text runs through their own MessageResponse and chart runs through the unchanged chart markup (AnswerCharts), so a chart drawn first renders above the analysis. content and charts keep their shape; a chart with no offset trails the text exactly as before, and a message with no charts renders the same DOM. Changeset: plugin-chatbot patch.",
      "tests": "head cb0af96, repo root, verify lock. `pnpm exec vitest run --maxWorkers=2 packages/plugin-chatbot/` → Test Files 82 passed (82), Tests 787 passed (787). The 54 app-shell/console test files importing @object-ui/plugin-chatbot (root alias to src) → Test Files 54 passed (54), Tests 582 passed (582). New: mapMessages.chartOrder-13492.test.ts (6), ChatbotEnhanced.chartOrder-13492.test.tsx (7, incl. an old-layout CONTROL and the objectstack-ai/objectui#13032 fold / objectstack-ai/objectui#13037 record-link non-regression pins), useObjectChat.chartOrderRehydrate-13492.test.tsx (2, API-mode stored message with parts through the hook into the bubble). Ablations via objectstack scripts/ablation-replace.mjs, fix committed first, restore proven (blob == HEAD, git diff HEAD empty): renderer ignores textOffset → 6 tests red (5 render + 1 re-hydrate render), CONTROL / record-link / mapper tests green; mapper textOffset spread deleted → 13 red across 4 files incl. the existing exact-shape test in mapMessages.test.ts. No dist involved (tests import src).",
      "gates": "local: `pnpm turbo run type-check --filter=@object-ui/plugin-chatbot --concurrency=2 --continue` :: exit 2 (TS2322 in the new re-hydrate test), fixed in cb0af96, then `pnpm --filter @object-ui/plugin-chatbot run type-check` :: exit 0; `eslint --no-inline-config` on the 6 touched files :: exit 0 (0 errors, 11 warnings all on untouched lines); `node scripts/check-changeset-presence.mjs` :: exit 0; `node scripts/check-changeset-no-major.mjs` :: exit 0; `pnpm check:new-line-citations` :: exit 0 (0 new); check:vi-mock-specifiers / vi-mock-inherit / vi-mock-override-shape / test-path-roots / control-bytes / ui-root-lookups / unreferenced-sources :: exit 0 each. objectui has no dispatch-gates.mjs, so the list was hand-derived. CI check-runs on PR objectstack-ai/objectui#13500: in_progress at report time; full sharded pnpm test, pnpm lint, builds and remaining check:* families are CI's.",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "mcp_calls": "3 — mcp__github__issue_read x3 (card get + get_comments x2); read-only",
      "api_writes": "relay strokes only: (1) pr_create POST /repos/objectstack-ai/objectui/pulls → objectstack-ai/objectui#13500 (read-back identical, assignee os-elon-musk); (2) this stroke: comment POST /repos/objectstack-ai/objectui/issues/13492/comments + pr_request_reviewers POST /repos/objectstack-ai/objectui/pulls/13500/requested_reviewers; each stroke is one POST /repos/objectstack-ai/objectstack/dispatches",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: none (no carrier) · noted, not filed — read from code, reach not measured: no reload path in objectui restores a chart, so after a reload the chart is missing rather than misplaced. The server persists ModelMessage (spec contracts/ai-service.ts IAIConversationService.addMessage), which has no data parts; app-shell hydratedMessagesToChatMessages builds content + tool invocations only; sanitizeChatMessagesForCache writes text + tool parts only. Outside the claim's file surface. Whether cloud's visualize_data result can re-derive the chart is cloud-side. Dedupe words: chat chart lost after reload; data-chart rehydrate; visualize_data chart persistence; AI answer chart missing on refresh"
      ]
    }

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 25, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #13500 comment 6393435468 · domain:ui#4 · 2026-10-25T04:29Z. Handed to the merge queue under the maintainer's standing word; Fixes, so this closes on merge. The staging re-test (首屏能看到至少一张图) runs on cloud#3072 once cloud's pin carries the merge.

  6. objectstack-fleet commented on Oct 25, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:ui#4 · 2026-10-25T04:37Z

    PR #13500 merged at 2026-10-25T04:37Z, merge commit 76c560e95cd0a669aa63b89dc0f77a807f3b8c55. The card closed completed through Fixes; pm:dispatched comes off in this stroke. objectui merges publish nothing (the changesets release is a human act). The staging re-test (首屏能看到至少一张图) is owed on cloud#3072 once cloud's objectui pin carries this commit. A chart missing after a reload is filed separately as objectui#13502.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:aiAI-native — agent / tool / skill metadata, and the MCP surface an agent drivesbugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p1

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions