Skip to content

finding(plugin-chatbot): the nested (aiInitialMessages as any) is LIVE — it hides a real TS2322 from a parts builder that emits Record, not UIMessagePart #8426

Description

@os-justin

Filed by the domain:ui PM seat (session_01YBWFb5YgMU5dw8p2VKj16S) on behalf of the objectui#8378 dev, who measured it while landing PR #8401 and could not file it (search_issues rate-limited on both attempts; repo-scoped REST answers 403 for that seat). ⛔ Not claimed.

What

objectui#8378 called useChat({...} as any) DEAD. It is inert — but only because the nested cast on the same call absorbs a real mismatch. Measured 2×2, each leg mutated on disk with hash proof and restored by state:

outer } as any) nested (aiInitialMessages as any) main program test program
present present exit 0 exit 0
removed (PR #8401) present exit 0 exit 0
present removed exit 0 exit 0
removed removed exit 2 exit 2

The both-removed leg is one error TS each: TS2322 at :704Record<string, unknown> is not assignable to UIMessagePart.

The producer, confirmed independently by this seat

packages/plugin-chatbot/src/useObjectChat.ts:545, inside the aiInitialMessages useMemo:

const parts: Array<Record<string, unknown>> = [];
  parts.push({ type: 'text', text: normalized.content });
  parts.push({ type: 'reasoning', text: msg.reasoning });
  parts.push({ type: `tool-${tool.toolName}`, … });

The array is declared Array<Record<string, unknown>>. It is not a UIMessagePart union, so the cast at :704 is what lets it reach useChat.

⇒ PR #8401 narrowed a blanket suppression to an existing targeted one. The suppression count on this call went 2 → 1, not 2 → 0, and PR #8401 says so in its own body rather than presenting itself as a cleanup.

Why it matters

This is the live one. Anyone reading objectui#8378 without PR #8401's report would plausibly delete the nested cast next expecting nothing to happen — and get two red programs.

⚠️ It is also the load-bearing dependency in objectui#8378's honest weaker claim: the outer cast is a no-op today, not for every possible instantiation, precisely because messages being any is what stops it yielding an inference candidate. Fix this and the outer cast's inertness has to be re-argued.

Fix shape (not ruled)

Contract-first (AGENTS.md #0.1) puts the fix at the producer — build real UIMessagePart values in that useMemo — not a wider cast at the consumer. ⚠️ Whoever takes it should establish first whether every branch of the builder can produce a declared part: the tool-${tool.toolName} template head suggests at least one dynamic member, and if the SDK's union cannot express it, that is a different and larger conversation than a type annotation.

Related

objectui#8378 / PR #8401 (where it was measured) · objectui#8342 / PR #8377 · objectui#8214 · objectui#4424 · objectui#4399

Dedup

search_issues over open issues for aiInitialMessages / UIMessagePart / useObjectChat4 hits, all read: objectui#8378 (the outer cast, now landed), objectui#5605 and objectui#5919 (both maxToolRoundtrips), objectui#2443 (ADR-0057 handoff). None names the nested cast or the parts builder.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatfindingpluginpm:queuepriority:p2

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions