kubeflow / kubeflow/docs-agent
bug(frontend): the chat widget calls two functions that no longer exist
- Dominant language
- Python
- Stars
- 42
- Forks
- 111
- Avg merge
- 6d 23m
- Merged PRs (30d)
- 2
Description
## Problem
`chatbot.js` calls `escapeHtml` at three places and `formatMarkdown` at one. Neither is defined anywhere in the file:
```
$ grep -nE "^\s*(function|const|let|var)\s+(escapeHtml|formatMarkdown)\b" frontend/docs_scripts/chatbot.js
(no output)
$ grep -n "escapeHtml(\|formatMarkdown(" frontend/docs_scripts/chatbot.js
934: const formattedText = formatMarkdown(currentMessageContent.trim());
1257: ${escapeHtml(text)}
1882: ${escapeHtml(info.title)}
1883: ${escapeHtml(info.domain)}
```
Both were real functions until #234 (`b24399e`), which hoisted them out of the `DOMContentLoaded` closure and renamed them to `escapeMarkdownHtml` and `formatChatMarkdown`, alongside the new `tests/test_widget_markdown.py`. #234 converted every call site with them: at `b24399e` the file contains no reference to either old name. All four call sites above arrive at `9a1e5ab` (#237).
## What breaks
**The tool-status pill, on every tool-using turn.** `setToolStatus` (`:1257`) builds its markup with `escapeHtml`, so the "Searching Kubeflow documentation..." indicator #237 added never mounts, whether or not the turn returns citations.
**Citations, and the saved chat.** In the SSE handler the final event does:
```js
if (currentMessageDiv && pendingCitations.length > 0) {
renderCitationsOnDiv(currentMessageDiv, pendingCitations); // ReferenceError: escapeHtml
}
if (currentMessageContent.trim()) {
messagesHistory.push({ role: 'assistant', content: ... }); // never reached
}
...
autoSaveCurrentChat(); // never reached
```
`renderCitationsOnDiv` builds each pill with `escapeHtml`, so it throws on the first citation. The block sits inside `try { ... } catch (parseError) { // Ignore partial / heartbeat lines }`, which swallows the ReferenceError with no console output. The Sources accordion never mounts, and because the throw lands before `messagesHistory.push` and `autoSaveCurrentChat()`, the reply stays on screen but is never written to the saved chat, so it is gone on reload or chat switch. The agent's own context is server-side via `contextId` and is unaffected.
**Stop generation.** `stopGeneration` renders the partial answer with `formatMarkdown` (`:934`) before adding the interrupted badge and pushing to history, so the badge never appears, the partial is never saved, and `currentMessageDiv` / `currentMessageContent` are left uncleared. This path is not silent: `stopGeneration` is `async` and the click handler at `:1500` drops the promise, so it surfaces as an unhandled rejection.
## Why CI does not see it
`tests/test_widget_markdown.py` loads the file by splitting on `document.addEventListener('DOMContentLoaded'` and evaluating only the prelude. All four call sites are inside that closure, so nothing in the repo evaluates them. `node --check` passes, since an undefined reference is a runtime error rather than a syntax error.
## Suggested fix
Point the call sites at the helpers that exist, and add a check over the whole file that every bare `name(` call resolves to something the file declares or a known global.
Related: #242 resolves the `escapeHtml` half by adding an alias, as part of the XSS work for #175. It does not cover `formatMarkdown`.
**P.S.** I'll shortly open a PR addressing this.
Contributor guide
Research direction
Start with frontend/docs_scripts/chatbot.js and compare the four failing call sites with the existing escapeMarkdownHtml and formatChatMarkdown helpers introduced in #234. Run tests/test_widget_markdown.py and exercise citation, tool-status, saved-chat, and stop-generation paths; done means these flows complete without ReferenceError and the requested unresolved-call check is covered.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- frontend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100