Skip to content

feat(mingo): wire Guide Mode V3 source metadata and remote tools - #356

Open
pavlo-flamingo wants to merge 6 commits into
mainfrom
feat/mingo-guide-mode-v3
Open

pavlo-flamingo wants to merge 6 commits into
mainfrom
feat/mingo-guide-mode-v3

Conversation

@pavlo-flamingo

@pavlo-flamingo pavlo-flamingo commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Depends on flamingo-stack/openframe-oss-lib#2115. Pinned to its prerelease 0.0.610-2115.5931.1; swap to the plain release once that merges.

What this is

The lib half decodes an answer's GUIDE/SOURCES metadata and renders its citation strip and entity cards. This is the app half: fetching that metadata back on reload, gating the remote tools behind their flag, and giving the cards a working Display action.

It replaces the vibe-coded #313, which pinned the lib to a prerelease off an unmerged branch 45 commits behind main — regressing the package ~19 releases for the whole app.

History

dialogs-queries selects GuideData.payload, so a reloaded dialog shows the citations the live turn did.

Two constraints shaped the fragment:

  • GuideData.text is deliberately not selected. Payload-only records persist it as an empty string, which replays as an empty text segment.
  • SourcesData is not named at all. It is the contract the backend is moving to, but it is not in the tenant schema yet, and a fragment on a type the schema lacks fails the whole query — not just that selection. The lib decoder accepts both names, so switching later is a one-line change here.
  • AskData.text is aliased. It is nullable where TextData.text is not, and GraphQL's SameResponseShape rule rejects the entire query over that conflict rather than the one field.

Flag

ai-mingo-remote-tools. With it off, the slash-command list is filtered to the four commands the backend's HubMcpPromptPolicy.REPLACED_LOCAL_COMMANDS allows MCP prompts to replace.

The interceptor awaits the flags rather than reading them optimistically (whenFeatureFlagsResolved()). It rewrites a response the lib caches with staleTime: Infinity, so a guess made before the flags land is not a brief flicker — it is the command catalog the panel keeps for the rest of the session. The filter itself is a pure function, so the policy is testable without mounting a panel.

Display action on cards

Built from the ref's own sourceRepo, falling back to a documentType→table map, and only when the catalog actually has a display action for that source: offering it for a search-only source would run a query instead of showing the row, so the affordance does not render at all on a V2 catalog. The invocation goes through the lib's quoting helper rather than a second escaping rule here.

One note on the mapper

mapMingoMessageToUnified spreads what it does not destructure, so per-message metadata the lib adds later rides through without a change here. That is the same seam that silently dropped sources/refs on the lib side — a mapper that enumerates fields is the shape of that bug, and its test asserts the pass-through rather than the field list.

Before merge

@flamingo-stack/openframe-frontend-core is pinned to 0.0.610-2115.5931.1, the prerelease built from openframe-oss-lib#2115. Exact, not caret — a caret range on a prerelease matches only other prereleases of the same version, which is not what a ^ reads as. Swap it for the plain release once #2115 merges.

Verification

tsc ✓, lint:ci ✓, Prettier ✓, 203 tests ✓ (22 new, covering the history normalizer, the visibility policy, the flag gate and the display-command builder) — all run against the published prerelease, not a local link. npm run test:node is unchanged at 30/1: the registration-attribution failure is pre-existing on main.

@pavlo-flamingo
pavlo-flamingo requested review from a team as code owners September 8, 2026 17:09
The lib now decodes an answer's `GUIDE`/`SOURCES` metadata and renders its
citation strip and entity cards (openframe-oss-lib#2115). This is the app
half: fetching that metadata back on reload, gating the tools behind their
flag, and giving the cards a working Display action.

- `dialogs-queries` selects `GuideData.payload` so a reloaded dialog shows
  the citations the live turn did. `GuideData.text` is deliberately NOT
  selected — payload-only records persist it as an empty string, which
  replays as an empty text segment. `SourcesData` is not in the tenant
  schema yet, and a fragment for a type the schema lacks fails the WHOLE
  query, so only `GuideData` is named here; the lib decoder accepts both.
- `AskData.text` is aliased. It is nullable where `TextData.text` is not,
  and GraphQL's SameResponseShape rule rejects the entire query over that
  conflict rather than the one field.
- `feature-flags` gains `ai-mingo-remote-tools` and
  `whenFeatureFlagsResolved()`. The slash-command interceptor rewrites a
  response the lib caches with `staleTime: Infinity`, so a guess made
  before the flags land is the catalog the panel keeps for the whole
  session — it has to await them, not read them optimistically.
- With the flag off, the command list is filtered to the four the backend's
  `HubMcpPromptPolicy` allows MCP prompts to replace. The filter is a pure
  function so the policy is testable without a panel.
- Entity cards get a Display action built from the ref's own `sourceRepo`,
  falling back to a documentType→table map, and only when the catalog
  actually has a `display` action for that source — offering it for a
  search-only source would run a query instead of showing the row. The
  invocation is formatted through the lib's quoting helper rather than a
  second escaping rule here.
- `mapMingoMessageToUnified` spreads what it does not destructure, so
  per-message metadata the lib adds later rides through without a change
  here. That is the same seam that silently dropped `sources`/`refs` on the
  lib side; a mapper that enumerates fields is the shape of that bug.

Requires a core-lib version carrying openframe-oss-lib#2115 — the bump is
NOT in this commit and must land before merge.
`0.0.610-2115.5931.1`, built from openframe-oss-lib#2115 — the branch this
PR needs. Exact, not caret: a caret range on a prerelease only matches other
prereleases of the SAME version, which is a resolution rule nobody reads a
`^` as meaning.

Replace with the plain release once #2115 merges.
@pavlo-flamingo
pavlo-flamingo force-pushed the feat/mingo-guide-mode-v3 branch from 757a842 to 67fbc8c Compare September 8, 2026 17:27
Picks up the ordered-list start fix (openframe-oss-lib#2181), so cards in a
numbered Guide Mode V3 answer are no longer all numbered 1.
…viewer's list

hubspot_ticket_anon cards are other customers' tickets, so the session-scoped
/help-center/tickets list answered "No tickets found". The hub mints them with
url: null on purpose; dropping our override lets the lib's noComposedHref keep
the card unlinked, with "Ask Mingo" as its only action.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant