mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-24 20:09:02 +00:00
"Search or ask AI" now has a door for the asking half
The field said search OR ask; only searching worked. Full-text matches TERMS, and a question is mostly terms that appear in no page — measured against production: "api key", "quickstart" and "kms" all return results, "how do I get an api key" returns none. The reader most in need of an answer got the emptiest screen, under a label that had promised otherwise. Ask AI was removed from this app deliberately — its floating button landed in the same corner as the Hanzo Edit launcher and the two overlapped — and the label was never taken down with it. This is not that button coming back, and not a chat surface bolted into a search dialog. It is the door this product already gives everywhere else: hand the question to the reader's own agent, carrying the setup that points it at Hanzo's models and the skills at hanzoskills.com. Same prompt as the Use Agent control, imported rather than restated, so there is one thing to keep true. It sits LAST in the list, because a question is the fallback when the terms did not land rather than a competitor to a page that did — and it appears from three characters, so it is there before the reader has finished discovering that nothing matched.
This commit is contained in:
@@ -16,13 +16,15 @@ import {
|
||||
import { useDocsSearch } from '@hanzo/docs/core/search/client';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@hanzo/docs-base-ui/components/ui/popover';
|
||||
import { ArrowRight, ChevronDown } from 'lucide-react';
|
||||
import { ArrowRight, Check, ChevronDown, Sparkle } from 'lucide-react';
|
||||
import { buttonVariants } from '@hanzo/docs-base-ui/components/ui/button';
|
||||
import { cn } from '@/lib/cn';
|
||||
import { useTreeContext } from '@hanzo/docs-base-ui/contexts/tree';
|
||||
import type { Item, Node } from '@hanzo/docs/core/page-tree';
|
||||
import { useRouter } from 'next/navigation';
|
||||
|
||||
import { AGENT_SETUP_PROMPT } from '@/lib/agent-setup-prompt';
|
||||
|
||||
const items = [
|
||||
{
|
||||
name: 'All',
|
||||
@@ -75,6 +77,50 @@ export default function CustomSearchDialog(props: SharedProps) {
|
||||
for (const item of full.children) onNode(item);
|
||||
return map;
|
||||
}, [full]);
|
||||
// ASKING IS A DIFFERENT INTENTION FROM FINDING, and until now only one of them
|
||||
// had a door. The field says "search or ask", full-text search matches TERMS,
|
||||
// and a question is mostly terms that are not in any page — measured, "api
|
||||
// key", "quickstart" and "kms" all return results while "how do I get an api
|
||||
// key" returns none. So the reader most in need of an answer got the emptiest
|
||||
// screen, under a label that had promised otherwise.
|
||||
//
|
||||
// The answer is not a chat surface bolted into this dialog. It is the one this
|
||||
// product already gives everywhere else: hand the question to the reader's own
|
||||
// agent, with the setup that points it at Hanzo's models and skills. Same
|
||||
// prompt as the Use Agent control, so there is one thing to keep true.
|
||||
const [asked, setAsked] = useState(false);
|
||||
const askAction = useMemo<SearchItemType | undefined>(() => {
|
||||
const q = search.trim();
|
||||
if (q.length < 3) return;
|
||||
return {
|
||||
id: 'ask-agent',
|
||||
type: 'action',
|
||||
node: (
|
||||
<div className="inline-flex items-center gap-2 text-fd-muted-foreground">
|
||||
{asked ? <Check className="size-4" /> : <Sparkle className="size-4" />}
|
||||
<p>
|
||||
{asked ? (
|
||||
'Copied — paste it into your agent'
|
||||
) : (
|
||||
<>
|
||||
Ask an agent<span className="font-medium text-fd-foreground"> “{q}”</span>
|
||||
</>
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
),
|
||||
onSelect: () => {
|
||||
void navigator.clipboard
|
||||
.writeText(
|
||||
`${AGENT_SETUP_PROMPT}\n\n---\n\nThen answer this using the Hanzo documentation at ` +
|
||||
`https://docs.hanzo.ai, and use the Hanzo skills at https://hanzoskills.com for any ` +
|
||||
`capability it touches:\n\n${q}`,
|
||||
)
|
||||
.then(() => setAsked(true));
|
||||
},
|
||||
};
|
||||
}, [asked, search]);
|
||||
|
||||
const pageTreeAction = useMemo<SearchItemType | undefined>(() => {
|
||||
if (search.length === 0) return;
|
||||
|
||||
@@ -109,10 +155,13 @@ export default function CustomSearchDialog(props: SharedProps) {
|
||||
</SearchDialogHeader>
|
||||
<SearchDialogList
|
||||
items={
|
||||
query.data !== 'empty' || pageTreeAction
|
||||
query.data !== 'empty' || pageTreeAction || askAction
|
||||
? [
|
||||
...(pageTreeAction ? [pageTreeAction] : []),
|
||||
...(Array.isArray(query.data) ? query.data : []),
|
||||
// LAST, always. A question is the fallback when the terms did
|
||||
// not land, not a competitor to a page that did.
|
||||
...(askAction ? [askAction] : []),
|
||||
]
|
||||
: null
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user