end_user_search
Search published website content using exact text matching, AI semantic analysis, or combined hybrid mode to find relevant pages and information.
Instructions
Search published content using full-text exact match, semantic (AI) similarity, or hybrid mode. Returns page titles, paths, and snippets.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max results 1-50 (default 10) | |
| mode | No | Search mode: exact, semantic, or hybrid (default hybrid) | |
| query | Yes | Search query,required |
Implementation Reference
- static/js/chat-widget.js:263-356 (handler)The `runQuery` function handles the "end_user_search" logic by querying the /api/chat endpoint and processing SSE streaming responses.
function runQuery(query, cfg, bodyId, inputId, sendId) { var body = document.getElementById(bodyId); var sendBtn = document.getElementById(sendId); var input = document.getElementById(inputId); body.innerHTML = '<div class="lc-loading"><div class="lc-dot"></div><div class="lc-dot"></div><div class="lc-dot"></div></div>'; sendBtn.disabled = true; var loadingRemoved = false; var answerEl = null; var sourcesEl = null; var rawAnswer = ''; function removeLoading() { if (!loadingRemoved) { var l = body.querySelector('.lc-loading'); if (l) l.remove(); loadingRemoved = true; } } function ensureAnswer() { if (!answerEl) { removeLoading(); answerEl = document.createElement('div'); answerEl.className = 'lc-answer'; body.appendChild(answerEl); } return answerEl; } function handleEvent(evt) { if (evt.type === 'token' && evt.text) { rawAnswer += evt.text; ensureAnswer().innerHTML = renderMarkdown(rawAnswer); body.scrollTop = body.scrollHeight; } else if (evt.type === 'sources') { removeLoading(); var results = evt.results || []; if (results.length === 0 && !answerEl) { body.innerHTML = '<p class="lc-no-results">No results found. Try rephrasing your question.</p>'; return; } if (results.length > 0) { sourcesEl = document.createElement('div'); sourcesEl.className = 'lc-sources'; var html = '<div class="lc-sources-label">Sources</div>'; for (var i = 0; i < results.length; i++) { var r = results[i]; html += '<a class="lc-result" href="' + escHtml(r.url) + '">' + '<span class="lc-result-arrow">↗</span>' + '<span class="lc-result-title">' + escHtml(r.title) + '</span>' + '</a>'; } sourcesEl.innerHTML = html; body.appendChild(sourcesEl); body.scrollTop = body.scrollHeight; } } else if (evt.type === 'done') { sendBtn.disabled = false; input.value = ''; input.focus(); } } fetch(baseURL + '/api/chat?q=' + encodeURIComponent(query)) .then(function (res) { if (!res.ok || !res.body) throw new Error('HTTP ' + res.status); var reader = res.body.getReader(); var decoder = new TextDecoder(); var buffer = ''; function pump() { return reader.read().then(function (result) { if (result.done) { sendBtn.disabled = false; return; } buffer += decoder.decode(result.value, { stream: true }); var parts = buffer.split('\n\n'); buffer = parts.pop(); for (var i = 0; i < parts.length; i++) { var p = parts[i].trim(); if (p.indexOf('data: ') === 0) { try { handleEvent(JSON.parse(p.slice(6))); } catch (e) {} } } return pump(); }); } return pump(); }) .catch(function () { sendBtn.disabled = false; body.innerHTML = '<p class="lc-no-results">Something went wrong. Please try again.</p>'; }); }