Commits on Source 9

  • Enrique Alcántara's avatar
    refactor(chat): render user messages through the message registry · 9e842b1d
    Enrique Alcántara authored
    User-message rendering was hard-coded in `duo_chat_message.vue`'s
    inline branch rather than contributed as a registry descriptor, so a
    host could not override it via `messageRenderers` — despite
    `message_registry.md` documenting that as the supported extension
    mechanism.
    
    It also left dead code: the registry already had a user descriptor,
    but real agentic user turns carry both `role: 'user'` and
    `message_type: 'user'`, so the inline branch always claimed them
    before `<message-map>` mounted. `message_user.vue` only ever rendered
    in specs and stories.
    
    User turns are now resolved by the registry like every other message
    type:
    
    - Add `DuoUserPromptMessage` (`message_types/message_user_prompt.vue`),
      which owns the sr-only label, the bubble and the user-variant
      context-item selections. It composes `MarkdownRenderer` directly
      rather than `BaseMessage`, whose error shell and root classes differ.
    - Add a shared `isUserMessage` matcher claiming both chat shapes:
      classic sends only `role`, agentic sends `role` and `message_type`.
      It replaces the old `message_type`-only descriptor in the same slot,
      so no other message type's resolution changes.
    - Narrow the inline branch in `duo_chat_message.vue` to assistant
      messages. It keeps `isUserMessage` for the container's `gl-pl-7`,
      and the error branch still precedes routing, so an errored user
      message renders the shared error box as before.
    - Delete `message_user.vue`, now unreachable and exported from
      neither index.
    
    Two supporting fixes in `MessageMap`:
    
    - Relax the `message` validator to accept `message_type` *or* `role`.
      Classic chat user turns carry no `message_type` and would trip a
      prop warning.
    - Declare and forward `get-context-item-content` and `open-file-path`.
      `open-file-path` was a latent bug: `duo_chat_message.vue` already
      listened for it, but `MessageMap` never declared or re-emitted it,
      so it worked accidentally under Vue 3 (listeners land in `$attrs`)
      and was dead under Vue 2.
    
    `trustedUrls` reaches the new component through `MessageMap`'s
    `$attrs` spread, bound only for user messages: bound unconditionally
    it leaves a stray `trusted-urls` attribute on every other renderer's
    root.
    
    Behaviour change: `alternatives` no longer apply to the user path.
    They read `agent_responses[last].content` — assistant state the host
    attaches to the terminator message — so this is unobservable in
    practice.
    
    Verified with a before/after DOM dump of a rendered user message: the
    only structural difference is one wrapper `<div>`, which re-creates
    the parent's flex column so layout is unchanged. Full suite green on
    Vue 2 and Vue 3.
    
    Co-Authored-By: default avatarClaude Opus 5 (1M context) <noreply@anthropic.com>
    9e842b1d
  • 🤖 GitLab Bot 🤖's avatar
    chore: update snapshots · 2cb95714
    🤖 GitLab Bot 🤖 authored
    2cb95714
  • Enrique Alcántara's avatar
    fix(chat): stop workingDirectory falling through to the user bubble · 76c6c665
    Enrique Alcántara authored
    `MessageMap` defaults a descriptor's props to
    `{ message, workingDirectory }`. `DuoUserPromptMessage` has no use for
    `workingDirectory`, so it landed in the component's `$attrs` and, with
    the default `inheritAttrs`, rendered on its root as a stray
    `workingdirectory` DOM attribute on every user message.
    
    Give the descriptor an explicit `defaultProps` passing only `message`,
    rather than declaring a prop the component never reads.
    
    Note this leak is pre-existing and not introduced here: `AgentMessage`
    (the inline fallback), `WorkflowEndMessage` and `MessageDelegation`
    all share it, verified by probe. Fixing those is left as a follow-up
    so this MR stays scoped.
    
    Co-Authored-By: default avatarClaude Opus 5 (1M context) <noreply@anthropic.com>
    76c6c665
  • Enrique Alcántara's avatar
    refactor(chat): simplify message-map bindings and move test ids · 817915a0
    Enrique Alcántara authored
    Address review feedback on how DuoChatMessage talks to MessageMap:
    
    - Always pass `trustedUrls`, dropping the `messageMapExtraProps`
      computed that scoped it to user messages. Any renderer showing
      markdown can use it, so withholding it was the odd case.
    - Drop the conditional `data-testid` on `message-map`. A test id
      identifies a message type, so it belongs to the component that
      renders it: `data-testid="user-message"` now lives on
      DuoUserPromptMessage. `workflow-message` named no type at all, so it
      is gone; the two specs using it assert on MessageMap instead.
    - Remove the explanatory comment above `message-map`.
    
    Two consequences worth noting:
    
    The user test id is no longer visible to DuoChatMessage under
    shallowMount, which is correct: those assertions moved to
    message_user_prompt.spec.js. What stays here is only what this
    component owes the registry, so the describe block is renamed and the
    two cases that were never user-specific (trusted URLs, event proxying)
    now cover a tool message too.
    
    Moving the test id also surfaced a latent Vue 3 bug: the root-level
    comment in message_user_prompt.vue made the component a fragment,
    which silently disables attribute fall-through, so the class and test
    id from MessageMap were dropped. The comment moved into the script and
    fall-through is now verified on both Vue 2 and Vue 3.
    
    Co-Authored-By: default avatarClaude Opus 5 (1M context) <noreply@anthropic.com>
    817915a0
  • Enrique Alcántara's avatar
    docs(chat): drop the notes added alongside the user message refactor · da0b45d9
    Enrique Alcántara authored
    Revert the additions to message_registry.md, message_map.md and
    duo_chat_message.md, and remove the explanatory comment on
    MessageMap's message validator. They restated what the code and the
    existing descriptor table already say.
    
    Co-Authored-By: default avatarClaude Opus 5 (1M context) <noreply@anthropic.com>
    da0b45d9
  • Enrique Alcántara's avatar
    refactor(chat): drop comments that restate the code · b9588c5e
    Enrique Alcántara authored
    Remove the describe-block header, the $attrs notes in two specs, the
    `.duo-chat-message` note, the story comment and the `isUserMessage`
    note in duo_chat_message.vue. Each repeated what the line below it
    already says.
    
    Keeps the four that record something the code cannot: the Vue 3
    single-root constraint, why the user descriptor passes only `message`,
    why it sits after the tool/request entries, and which fields each chat
    format sends for a user turn.
    
    Co-Authored-By: default avatarClaude Opus 5 (1M context) <noreply@anthropic.com>
    b9588c5e
  • Enrique Alcántara's avatar
    fix(chat): render user message errors and stop attribute fall-through · b6d38898
    Enrique Alcántara authored
    Addresses review feedback on
    !695
    
    `message.errors` was dropped. The deleted `message_user.vue` rendered
    them through `BaseMessage` — a warning icon plus the joined text — and
    the replacement rendered an empty bubble instead. Unreachable through
    `DuoChatMessage`, whose error branch runs first, but `MessageMap` is
    public and reaches it. Restore the icon and error text inside the
    bubble, which needed the bubble classes on a wrapper so the icon can
    sit beside the text.
    
    `MessageMap` also painted every attribute bound on `<message-map>`
    onto whichever renderer the registry resolved, so a user message
    rendered as `<div … with-feedback="true" trusted-urls="…">`. Two
    mechanisms fed it: the component inherits attributes despite rendering
    no element of its own, and `boundProps` re-added `$attrs` after
    `defaultProps` had filtered `messageProps`.
    
    Set `inheritAttrs: false` and bind only what the resolved renderer
    declares, from either source. A renderer declaring no props is left
    untouched, since it may be reading `$attrs` itself. This also clears
    the same leak on AgentMessage, WorkflowEndMessage and
    MessageDelegation, which were dropping `workingDirectory` onto their
    roots.
    
    That makes the user descriptor's `defaultProps` redundant, so it goes,
    along with the comment describing a mechanism that no longer applies.
    
    Co-Authored-By: default avatarClaude Opus 5 (1M context) <noreply@anthropic.com>
    b6d38898
  • Tomas Bulva's avatar
    Merge branch 'duo/refactor/extract-user-message-component' into 'main' · 612e92a4
    Tomas Bulva authored
    refactor(chat): render user messages through the message registry
    
    See merge request !695
    612e92a4
  • semantic-release-bot's avatar
    chore(release): 16.2.2 [skip ci] · 925d130e
    semantic-release-bot authored
    ## [16.2.2](v16.2.1...v16.2.2) (2026-09-07)
    
    ### Bug Fixes
    
    * **chat:** render user message errors and stop attribute fall-through ([b6d38898](b6d38898))
    * **chat:** stop workingDirectory falling through to the user bubble ([76c6c665](76c6c665))
    925d130e
Loading
Loading