@agent-native/core 0.66.0 → 0.66.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,7 +7,7 @@ import { cn } from "./utils.js";
7
7
  import { useSession } from "./use-session.js";
8
8
  import { getFeedbackClientContext } from "./feedback-context.js";
9
9
  const DEFAULT_FEEDBACK_URL = "https://forms.agent-native.com/f/agent-native-feedback/_16ewV";
10
- const DEFAULT_PLACEHOLDER = 'What\'s working, what\'s broken, or what would you change?\n\ne.g. "The Send button isn\'t obvious", "I wish I could change the theme", "Search is slow when…"';
10
+ const DEFAULT_PLACEHOLDER = "What's working, what's broken, or what would you change?";
11
11
  const DEFAULT_SUBMIT_TEXT = "Send feedback";
12
12
  const DEFAULT_SUCCESS_MESSAGE = "Thanks for the feedback!";
13
13
  function parseTarget(url) {
@@ -1 +1 @@
1
- {"version":3,"file":"FeedbackButton.js","sourceRoot":"","sources":["../../src/client/FeedbackButton.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n useState,\n useEffect,\n useRef,\n useCallback,\n type CSSProperties,\n type FormEvent,\n type ReactNode,\n} from \"react\";\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\";\nimport * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\nimport { IconMessage2, IconCheck } from \"@tabler/icons-react\";\nimport { cn } from \"./utils.js\";\nimport { useSession } from \"./use-session.js\";\nimport { getFeedbackClientContext } from \"./feedback-context.js\";\n\nconst DEFAULT_FEEDBACK_URL =\n \"https://forms.agent-native.com/f/agent-native-feedback/_16ewV\";\n\ninterface ParsedTarget {\n endpoint: string;\n slug: string;\n}\n\ninterface FormSchema {\n formId: string;\n fieldId: string;\n}\n\nconst DEFAULT_PLACEHOLDER =\n 'What\\'s working, what\\'s broken, or what would you change?\\n\\ne.g. \"The Send button isn\\'t obvious\", \"I wish I could change the theme\", \"Search is slow when…\"';\nconst DEFAULT_SUBMIT_TEXT = \"Send feedback\";\nconst DEFAULT_SUCCESS_MESSAGE = \"Thanks for the feedback!\";\n\nfunction parseTarget(url: string): ParsedTarget | null {\n try {\n const u = new URL(url);\n const idx = u.pathname.indexOf(\"/f/\");\n if (idx === -1) return null;\n const slug = u.pathname.slice(idx + 3).replace(/\\/$/, \"\");\n if (!slug) return null;\n return { endpoint: u.origin, slug };\n } catch {\n return null;\n }\n}\n\nconst schemaCache = new Map<string, Promise<FormSchema>>();\n\nasync function loadSchema(target: ParsedTarget): Promise<FormSchema> {\n const key = `${target.endpoint}|${target.slug}`;\n let pending = schemaCache.get(key);\n if (pending) return pending;\n pending = (async () => {\n const res = await fetch(\n `${target.endpoint}/api/forms/public/${encodeURIComponent(target.slug)}`,\n { headers: { Accept: \"application/json\" } },\n );\n if (!res.ok) throw new Error(`form fetch ${res.status}`);\n const body = (await res.json()) as {\n id: string;\n fields: Array<{ id: string; type: string }>;\n };\n const field =\n body.fields.find((f) => f.type === \"textarea\") ??\n body.fields.find((f) => f.type === \"text\") ??\n body.fields[0];\n if (!field) throw new Error(\"form has no fields\");\n return { formId: body.id, fieldId: field.id };\n })();\n pending.catch(() => schemaCache.delete(key));\n schemaCache.set(key, pending);\n return pending;\n}\n\nexport interface FeedbackButtonProps {\n /**\n * \"sidebar\" renders a full-width row with icon + label (for app left sidebars).\n * \"icon\" renders a small icon-only button (for dense toolbars, e.g. the agent panel header).\n * \"outlined\" renders an outlined pill button with icon + label (for top-nav bars, e.g. docs).\n */\n variant?: \"sidebar\" | \"icon\" | \"outlined\";\n label?: string;\n url?: string;\n className?: string;\n /** Which side the popover opens on. Defaults match the variant. */\n side?: \"top\" | \"bottom\" | \"left\" | \"right\";\n align?: \"start\" | \"center\" | \"end\";\n /** Placeholder text for the textarea. */\n placeholder?: string;\n /** Current chat session/thread id, when the host already knows it. */\n chatSessionId?: string | null;\n /** Chat localStorage namespace, when the host uses per-app chat storage. */\n chatStorageKey?: string | null;\n /** Controlled popover open state for hosts that trigger feedback from a menu. */\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Optional custom trigger element. */\n trigger?: ReactNode;\n}\n\nconst surfaceStyle: CSSProperties = {\n width: \"min(380px, calc(100vw - 32px))\",\n};\n\nconst honeypotStyle: CSSProperties = {\n position: \"absolute\",\n left: \"-10000px\",\n top: \"auto\",\n width: \"1px\",\n height: \"1px\",\n overflow: \"hidden\",\n};\n\nexport function FeedbackButton({\n variant = \"sidebar\",\n label = \"Feedback\",\n url = DEFAULT_FEEDBACK_URL,\n className,\n side,\n align = \"end\",\n placeholder,\n chatSessionId,\n chatStorageKey,\n open: controlledOpen,\n onOpenChange,\n trigger: customTrigger,\n}: FeedbackButtonProps) {\n const target = parseTarget(url);\n const { session } = useSession();\n\n const [uncontrolledOpen, setUncontrolledOpen] = useState(false);\n const open = controlledOpen ?? uncontrolledOpen;\n const setOpen = useCallback(\n (nextOpen: boolean) => {\n if (controlledOpen === undefined) setUncontrolledOpen(nextOpen);\n onOpenChange?.(nextOpen);\n },\n [controlledOpen, onOpenChange],\n );\n const [value, setValue] = useState(\"\");\n const [honeypot, setHoneypot] = useState(\"\");\n const [submitting, setSubmitting] = useState(false);\n const [submitted, setSubmitted] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [schema, setSchema] = useState<FormSchema | null>(null);\n const openedAtRef = useRef<number>(0);\n const closeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const textareaRef = useRef<HTMLTextAreaElement | null>(null);\n\n // Reset transient state and kick off schema load on each open.\n useEffect(() => {\n if (!open) return;\n openedAtRef.current = Date.now();\n setValue(\"\");\n setHoneypot(\"\");\n setSubmitting(false);\n setSubmitted(false);\n setError(null);\n setSchema(null);\n if (target) {\n loadSchema(target)\n .then((s) => setSchema(s))\n .catch((err) => {\n console.error(\"[FeedbackButton] schema load failed\", err);\n setError(\"Couldn't load feedback form\");\n });\n } else {\n setError(\"Invalid feedback URL\");\n }\n const t = setTimeout(() => textareaRef.current?.focus(), 30);\n return () => {\n clearTimeout(t);\n if (closeTimerRef.current) {\n clearTimeout(closeTimerRef.current);\n closeTimerRef.current = null;\n }\n };\n }, [open, url]);\n\n const submit = useCallback(\n async (e?: FormEvent) => {\n e?.preventDefault();\n if (!target || submitting) return;\n const trimmed = value.trim();\n if (!trimmed) {\n setError(\"Please write something first\");\n return;\n }\n setSubmitting(true);\n setError(null);\n try {\n const resolvedSchema = schema ?? (await loadSchema(target));\n if (!schema) setSchema(resolvedSchema);\n const submitterEmail = session?.email;\n const feedbackContext = getFeedbackClientContext({\n chatSessionId,\n storageKey: chatStorageKey,\n });\n const res = await fetch(\n `${target.endpoint}/api/submit/${encodeURIComponent(resolvedSchema.formId)}`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n data: { [resolvedSchema.fieldId]: trimmed },\n _t: openedAtRef.current,\n _hp: honeypot,\n _meta: {\n ...(submitterEmail ? { submitterEmail } : {}),\n ...feedbackContext,\n },\n }),\n },\n );\n if (!res.ok) {\n const body = (await res.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(body.error || `submit failed (${res.status})`);\n }\n setSubmitted(true);\n closeTimerRef.current = setTimeout(() => setOpen(false), 1400);\n } catch (err) {\n setSubmitting(false);\n setError(err instanceof Error ? err.message : \"Couldn't send feedback\");\n }\n },\n [\n target,\n schema,\n value,\n honeypot,\n submitting,\n session?.email,\n chatSessionId,\n chatStorageKey,\n setOpen,\n ],\n );\n\n let trigger;\n if (customTrigger) {\n trigger = (\n <PopoverPrimitive.Trigger asChild>\n {customTrigger}\n </PopoverPrimitive.Trigger>\n );\n } else if (variant === \"icon\") {\n trigger = (\n <TooltipPrimitive.Provider delayDuration={200}>\n <TooltipPrimitive.Root>\n <TooltipPrimitive.Trigger asChild>\n <PopoverPrimitive.Trigger asChild>\n <button\n type=\"button\"\n aria-label={label}\n className={cn(\n \"flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:text-foreground hover:bg-accent/50\",\n className,\n )}\n >\n <IconMessage2 size={14} />\n </button>\n </PopoverPrimitive.Trigger>\n </TooltipPrimitive.Trigger>\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n sideOffset={6}\n className=\"z-[300] overflow-hidden rounded-md border border-border bg-popover px-2 py-1 text-[11px] text-foreground shadow-md animate-in fade-in-0 zoom-in-95\"\n >\n {label}\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n </TooltipPrimitive.Root>\n </TooltipPrimitive.Provider>\n );\n } else if (variant === \"outlined\") {\n trigger = (\n <PopoverPrimitive.Trigger asChild>\n <button\n type=\"button\"\n aria-label={label}\n className={cn(\n \"flex h-8 items-center gap-2 rounded-md border border-border bg-transparent px-3 text-sm text-muted-foreground transition hover:border-foreground/40 hover:text-foreground\",\n className,\n )}\n >\n <IconMessage2 size={14} stroke={1.5} />\n <span>{label}</span>\n </button>\n </PopoverPrimitive.Trigger>\n );\n } else {\n trigger = (\n <PopoverPrimitive.Trigger asChild>\n <button\n type=\"button\"\n className={cn(\n \"flex w-full items-center gap-3 rounded-lg px-3 py-2 text-sm text-muted-foreground transition-colors hover:bg-accent/50 hover:text-foreground\",\n className,\n )}\n >\n <IconMessage2 className=\"h-4 w-4\" />\n <span>{label}</span>\n </button>\n </PopoverPrimitive.Trigger>\n );\n }\n\n const resolvedSide = side ?? (variant === \"sidebar\" ? \"top\" : \"bottom\");\n const resolvedPlaceholder = placeholder ?? DEFAULT_PLACEHOLDER;\n\n return (\n <PopoverPrimitive.Root open={open} onOpenChange={setOpen}>\n {trigger}\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n side={resolvedSide}\n align={align}\n sideOffset={8}\n collisionPadding={16}\n className=\"z-[300] overflow-hidden rounded-lg border border-border bg-popover shadow-xl outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\"\n style={surfaceStyle}\n >\n {submitted ? (\n <div className=\"flex flex-col items-center justify-center gap-3 px-6 py-10 text-center\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-full bg-emerald-500/10 text-emerald-500\">\n <IconCheck size={20} stroke={2.5} />\n </div>\n <div className=\"text-sm font-medium text-foreground\">\n {DEFAULT_SUCCESS_MESSAGE}\n </div>\n </div>\n ) : (\n <form onSubmit={submit} className=\"flex flex-col gap-3 p-3\">\n <textarea\n ref={textareaRef}\n value={value}\n onChange={(e) => setValue(e.target.value)}\n onKeyDown={(e) => {\n if ((e.metaKey || e.ctrlKey) && e.key === \"Enter\") submit();\n }}\n placeholder={resolvedPlaceholder}\n rows={5}\n maxLength={10000}\n className=\"w-full resize-none rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring\"\n />\n <input\n type=\"text\"\n tabIndex={-1}\n autoComplete=\"off\"\n aria-hidden=\"true\"\n value={honeypot}\n onChange={(e) => setHoneypot(e.target.value)}\n style={honeypotStyle}\n />\n <div className=\"flex items-center justify-between gap-3\">\n <div\n className={cn(\n \"text-[11px]\",\n error ? \"text-destructive\" : \"text-muted-foreground/75\",\n )}\n >\n {error ??\n `${/Mac|iPhone|iPad/.test(navigator.userAgent) ? \"⌘\" : \"Ctrl\"}+Enter to send`}\n </div>\n <button\n type=\"submit\"\n disabled={submitting || !value.trim()}\n className=\"inline-flex h-8 items-center justify-center rounded-md bg-primary px-3 text-xs font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50\"\n >\n {submitting ? \"Sending…\" : DEFAULT_SUBMIT_TEXT}\n </button>\n </div>\n </form>\n )}\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </PopoverPrimitive.Root>\n );\n}\n"]}
1
+ {"version":3,"file":"FeedbackButton.js","sourceRoot":"","sources":["../../src/client/FeedbackButton.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n useState,\n useEffect,\n useRef,\n useCallback,\n type CSSProperties,\n type FormEvent,\n type ReactNode,\n} from \"react\";\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\";\nimport * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\nimport { IconMessage2, IconCheck } from \"@tabler/icons-react\";\nimport { cn } from \"./utils.js\";\nimport { useSession } from \"./use-session.js\";\nimport { getFeedbackClientContext } from \"./feedback-context.js\";\n\nconst DEFAULT_FEEDBACK_URL =\n \"https://forms.agent-native.com/f/agent-native-feedback/_16ewV\";\n\ninterface ParsedTarget {\n endpoint: string;\n slug: string;\n}\n\ninterface FormSchema {\n formId: string;\n fieldId: string;\n}\n\nconst DEFAULT_PLACEHOLDER =\n \"What's working, what's broken, or what would you change?\";\nconst DEFAULT_SUBMIT_TEXT = \"Send feedback\";\nconst DEFAULT_SUCCESS_MESSAGE = \"Thanks for the feedback!\";\n\nfunction parseTarget(url: string): ParsedTarget | null {\n try {\n const u = new URL(url);\n const idx = u.pathname.indexOf(\"/f/\");\n if (idx === -1) return null;\n const slug = u.pathname.slice(idx + 3).replace(/\\/$/, \"\");\n if (!slug) return null;\n return { endpoint: u.origin, slug };\n } catch {\n return null;\n }\n}\n\nconst schemaCache = new Map<string, Promise<FormSchema>>();\n\nasync function loadSchema(target: ParsedTarget): Promise<FormSchema> {\n const key = `${target.endpoint}|${target.slug}`;\n let pending = schemaCache.get(key);\n if (pending) return pending;\n pending = (async () => {\n const res = await fetch(\n `${target.endpoint}/api/forms/public/${encodeURIComponent(target.slug)}`,\n { headers: { Accept: \"application/json\" } },\n );\n if (!res.ok) throw new Error(`form fetch ${res.status}`);\n const body = (await res.json()) as {\n id: string;\n fields: Array<{ id: string; type: string }>;\n };\n const field =\n body.fields.find((f) => f.type === \"textarea\") ??\n body.fields.find((f) => f.type === \"text\") ??\n body.fields[0];\n if (!field) throw new Error(\"form has no fields\");\n return { formId: body.id, fieldId: field.id };\n })();\n pending.catch(() => schemaCache.delete(key));\n schemaCache.set(key, pending);\n return pending;\n}\n\nexport interface FeedbackButtonProps {\n /**\n * \"sidebar\" renders a full-width row with icon + label (for app left sidebars).\n * \"icon\" renders a small icon-only button (for dense toolbars, e.g. the agent panel header).\n * \"outlined\" renders an outlined pill button with icon + label (for top-nav bars, e.g. docs).\n */\n variant?: \"sidebar\" | \"icon\" | \"outlined\";\n label?: string;\n url?: string;\n className?: string;\n /** Which side the popover opens on. Defaults match the variant. */\n side?: \"top\" | \"bottom\" | \"left\" | \"right\";\n align?: \"start\" | \"center\" | \"end\";\n /** Placeholder text for the textarea. */\n placeholder?: string;\n /** Current chat session/thread id, when the host already knows it. */\n chatSessionId?: string | null;\n /** Chat localStorage namespace, when the host uses per-app chat storage. */\n chatStorageKey?: string | null;\n /** Controlled popover open state for hosts that trigger feedback from a menu. */\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Optional custom trigger element. */\n trigger?: ReactNode;\n}\n\nconst surfaceStyle: CSSProperties = {\n width: \"min(380px, calc(100vw - 32px))\",\n};\n\nconst honeypotStyle: CSSProperties = {\n position: \"absolute\",\n left: \"-10000px\",\n top: \"auto\",\n width: \"1px\",\n height: \"1px\",\n overflow: \"hidden\",\n};\n\nexport function FeedbackButton({\n variant = \"sidebar\",\n label = \"Feedback\",\n url = DEFAULT_FEEDBACK_URL,\n className,\n side,\n align = \"end\",\n placeholder,\n chatSessionId,\n chatStorageKey,\n open: controlledOpen,\n onOpenChange,\n trigger: customTrigger,\n}: FeedbackButtonProps) {\n const target = parseTarget(url);\n const { session } = useSession();\n\n const [uncontrolledOpen, setUncontrolledOpen] = useState(false);\n const open = controlledOpen ?? uncontrolledOpen;\n const setOpen = useCallback(\n (nextOpen: boolean) => {\n if (controlledOpen === undefined) setUncontrolledOpen(nextOpen);\n onOpenChange?.(nextOpen);\n },\n [controlledOpen, onOpenChange],\n );\n const [value, setValue] = useState(\"\");\n const [honeypot, setHoneypot] = useState(\"\");\n const [submitting, setSubmitting] = useState(false);\n const [submitted, setSubmitted] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [schema, setSchema] = useState<FormSchema | null>(null);\n const openedAtRef = useRef<number>(0);\n const closeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const textareaRef = useRef<HTMLTextAreaElement | null>(null);\n\n // Reset transient state and kick off schema load on each open.\n useEffect(() => {\n if (!open) return;\n openedAtRef.current = Date.now();\n setValue(\"\");\n setHoneypot(\"\");\n setSubmitting(false);\n setSubmitted(false);\n setError(null);\n setSchema(null);\n if (target) {\n loadSchema(target)\n .then((s) => setSchema(s))\n .catch((err) => {\n console.error(\"[FeedbackButton] schema load failed\", err);\n setError(\"Couldn't load feedback form\");\n });\n } else {\n setError(\"Invalid feedback URL\");\n }\n const t = setTimeout(() => textareaRef.current?.focus(), 30);\n return () => {\n clearTimeout(t);\n if (closeTimerRef.current) {\n clearTimeout(closeTimerRef.current);\n closeTimerRef.current = null;\n }\n };\n }, [open, url]);\n\n const submit = useCallback(\n async (e?: FormEvent) => {\n e?.preventDefault();\n if (!target || submitting) return;\n const trimmed = value.trim();\n if (!trimmed) {\n setError(\"Please write something first\");\n return;\n }\n setSubmitting(true);\n setError(null);\n try {\n const resolvedSchema = schema ?? (await loadSchema(target));\n if (!schema) setSchema(resolvedSchema);\n const submitterEmail = session?.email;\n const feedbackContext = getFeedbackClientContext({\n chatSessionId,\n storageKey: chatStorageKey,\n });\n const res = await fetch(\n `${target.endpoint}/api/submit/${encodeURIComponent(resolvedSchema.formId)}`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n data: { [resolvedSchema.fieldId]: trimmed },\n _t: openedAtRef.current,\n _hp: honeypot,\n _meta: {\n ...(submitterEmail ? { submitterEmail } : {}),\n ...feedbackContext,\n },\n }),\n },\n );\n if (!res.ok) {\n const body = (await res.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(body.error || `submit failed (${res.status})`);\n }\n setSubmitted(true);\n closeTimerRef.current = setTimeout(() => setOpen(false), 1400);\n } catch (err) {\n setSubmitting(false);\n setError(err instanceof Error ? err.message : \"Couldn't send feedback\");\n }\n },\n [\n target,\n schema,\n value,\n honeypot,\n submitting,\n session?.email,\n chatSessionId,\n chatStorageKey,\n setOpen,\n ],\n );\n\n let trigger;\n if (customTrigger) {\n trigger = (\n <PopoverPrimitive.Trigger asChild>\n {customTrigger}\n </PopoverPrimitive.Trigger>\n );\n } else if (variant === \"icon\") {\n trigger = (\n <TooltipPrimitive.Provider delayDuration={200}>\n <TooltipPrimitive.Root>\n <TooltipPrimitive.Trigger asChild>\n <PopoverPrimitive.Trigger asChild>\n <button\n type=\"button\"\n aria-label={label}\n className={cn(\n \"flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:text-foreground hover:bg-accent/50\",\n className,\n )}\n >\n <IconMessage2 size={14} />\n </button>\n </PopoverPrimitive.Trigger>\n </TooltipPrimitive.Trigger>\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n sideOffset={6}\n className=\"z-[300] overflow-hidden rounded-md border border-border bg-popover px-2 py-1 text-[11px] text-foreground shadow-md animate-in fade-in-0 zoom-in-95\"\n >\n {label}\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n </TooltipPrimitive.Root>\n </TooltipPrimitive.Provider>\n );\n } else if (variant === \"outlined\") {\n trigger = (\n <PopoverPrimitive.Trigger asChild>\n <button\n type=\"button\"\n aria-label={label}\n className={cn(\n \"flex h-8 items-center gap-2 rounded-md border border-border bg-transparent px-3 text-sm text-muted-foreground transition hover:border-foreground/40 hover:text-foreground\",\n className,\n )}\n >\n <IconMessage2 size={14} stroke={1.5} />\n <span>{label}</span>\n </button>\n </PopoverPrimitive.Trigger>\n );\n } else {\n trigger = (\n <PopoverPrimitive.Trigger asChild>\n <button\n type=\"button\"\n className={cn(\n \"flex w-full items-center gap-3 rounded-lg px-3 py-2 text-sm text-muted-foreground transition-colors hover:bg-accent/50 hover:text-foreground\",\n className,\n )}\n >\n <IconMessage2 className=\"h-4 w-4\" />\n <span>{label}</span>\n </button>\n </PopoverPrimitive.Trigger>\n );\n }\n\n const resolvedSide = side ?? (variant === \"sidebar\" ? \"top\" : \"bottom\");\n const resolvedPlaceholder = placeholder ?? DEFAULT_PLACEHOLDER;\n\n return (\n <PopoverPrimitive.Root open={open} onOpenChange={setOpen}>\n {trigger}\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n side={resolvedSide}\n align={align}\n sideOffset={8}\n collisionPadding={16}\n className=\"z-[300] overflow-hidden rounded-lg border border-border bg-popover shadow-xl outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\"\n style={surfaceStyle}\n >\n {submitted ? (\n <div className=\"flex flex-col items-center justify-center gap-3 px-6 py-10 text-center\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-full bg-emerald-500/10 text-emerald-500\">\n <IconCheck size={20} stroke={2.5} />\n </div>\n <div className=\"text-sm font-medium text-foreground\">\n {DEFAULT_SUCCESS_MESSAGE}\n </div>\n </div>\n ) : (\n <form onSubmit={submit} className=\"flex flex-col gap-3 p-3\">\n <textarea\n ref={textareaRef}\n value={value}\n onChange={(e) => setValue(e.target.value)}\n onKeyDown={(e) => {\n if ((e.metaKey || e.ctrlKey) && e.key === \"Enter\") submit();\n }}\n placeholder={resolvedPlaceholder}\n rows={5}\n maxLength={10000}\n className=\"w-full resize-none rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring\"\n />\n <input\n type=\"text\"\n tabIndex={-1}\n autoComplete=\"off\"\n aria-hidden=\"true\"\n value={honeypot}\n onChange={(e) => setHoneypot(e.target.value)}\n style={honeypotStyle}\n />\n <div className=\"flex items-center justify-between gap-3\">\n <div\n className={cn(\n \"text-[11px]\",\n error ? \"text-destructive\" : \"text-muted-foreground/75\",\n )}\n >\n {error ??\n `${/Mac|iPhone|iPad/.test(navigator.userAgent) ? \"⌘\" : \"Ctrl\"}+Enter to send`}\n </div>\n <button\n type=\"submit\"\n disabled={submitting || !value.trim()}\n className=\"inline-flex h-8 items-center justify-center rounded-md bg-primary px-3 text-xs font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50\"\n >\n {submitting ? \"Sending…\" : DEFAULT_SUBMIT_TEXT}\n </button>\n </div>\n </form>\n )}\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </PopoverPrimitive.Root>\n );\n}\n"]}
@@ -1,12 +1,13 @@
1
1
  ---
2
2
  title: "Getting Started"
3
- description: "Create an agent app with a chat UI or headless — add an action, and watch the agent call it."
3
+ description: "Create an agent app, understand instructions, skills, and actions, then watch the agent call its first action."
4
4
  ---
5
5
 
6
6
  # Getting Started
7
7
 
8
8
  Agent-Native apps give an AI agent and your UI the same actions, data, and
9
- state. The smallest useful app is a single action.
9
+ state. A basic agent is made from instructions that guide it, skills that teach
10
+ repeatable behavior, and actions that let it do real work.
10
11
 
11
12
  **Want a complete app to start from?** Clone one of our rich templates —
12
13
  [Chat](/docs/template-chat), [Mail](/docs/template-mail),
@@ -15,15 +16,23 @@ state. The smallest useful app is a single action.
15
16
  each a full-featured app you customize.
16
17
 
17
18
  Building from scratch? The only choice up front is whether you want a UI —
18
- everything after (defining actions, running the agent) is the same either way.
19
+ everything after (writing instructions, adding skills, defining actions, running
20
+ the agent) is the same either way.
19
21
 
20
- ```an-diagram title="The three-step on-ramp" summary="Create an app, add one action, run it. The action is then reachable from every surface."
22
+ ```an-file-tree title="A basic Agent-Native agent"
21
23
  {
22
- "html": "<div class=\"diagram-flow\"><div class=\"diagram-card\"><span class=\"diagram-pill\">1</span><strong>Create</strong><small class=\"diagram-muted\">chat template or headless</small></div><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">&rarr;</div><div class=\"diagram-card\"><span class=\"diagram-pill\">2</span><strong>Add an action</strong><small class=\"diagram-muted\">one defineAction file</small></div><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">&rarr;</div><div class=\"diagram-card\"><span class=\"diagram-pill accent\">3</span><strong>Run it</strong><small class=\"diagram-muted\">CLI, agent, or browser</small></div></div>",
23
- "css": ".diagram-flow{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.diagram-flow .diagram-card{display:flex;flex-direction:column;gap:6px;padding:14px 16px;min-width:140px}.diagram-flow .diagram-arrow{font-size:22px;line-height:1}"
24
+ "entries": [
25
+ { "path": "AGENTS.md", "note": "always-on instructions: purpose, rules, tone, and the map of what the agent can do" },
26
+ { "path": ".agents/skills/customer-research/SKILL.md", "note": "a reusable playbook the agent loads when the task matches" },
27
+ { "path": "actions/summarize-week.ts", "note": "typed code the agent, UI, CLI, HTTP, MCP, A2A, jobs, and webhooks can run" }
28
+ ]
24
29
  }
25
30
  ```
26
31
 
32
+ This is true whether you start with a chat UI, a headless agent, or a full app.
33
+ The UI changes the surface; instructions, skills, and actions give the agent its
34
+ guidance and behavior.
35
+
27
36
  ## 1. Create your app
28
37
 
29
38
  You'll need [Node.js 22+](https://nodejs.org) and [pnpm](https://pnpm.io).
@@ -51,10 +60,10 @@ loop, no UI shell:
51
60
  npx @agent-native/core@latest create my-agent --headless
52
61
  ```
53
62
 
54
- Then install:
63
+ Then install from the folder you created:
55
64
 
56
65
  ```bash
57
- cd my-app
66
+ cd my-agent # or my-app if you chose the Chat template
58
67
  pnpm install
59
68
  ```
60
69
 
@@ -80,8 +89,13 @@ ship with this example:
80
89
  }
81
90
  ```
82
91
 
83
- Replace `hello` with the smallest real operation in your domain. You define it
84
- once; every surface picks it up.
92
+ Replace `hello` with the first real operation in your domain. You define it once;
93
+ every surface picks it up.
94
+
95
+ Use `AGENTS.md` for guidance that should apply every turn. Use a skill when the
96
+ agent needs a reusable workflow or domain procedure. Use an action when the
97
+ agent needs a typed, testable way to read data, write data, call an API, or
98
+ perform an approval.
85
99
 
86
100
  ## 3. Run it
87
101
 
@@ -182,7 +196,8 @@ my-app/
182
196
  actions/ # Agent-callable actions
183
197
  app/ # React frontend (UI templates only; omitted when headless)
184
198
  server/ # Nitro API server (routes, plugins)
185
- .agents/ # Agent instructions and skills
199
+ AGENTS.md # Always-on agent instructions
200
+ .agents/ # Skills the agent can pull in when relevant
186
201
  data/app.db # Local SQLite state when DATABASE_URL is unset
187
202
  ```
188
203
 
@@ -26,6 +26,33 @@ Every agent-native app is three things working together:
26
26
 
27
27
  Headless apps can run the same production app-agent loop from the folder with `pnpm agent`, while UI apps mount the embedded agent panel and run locally with `pnpm dev`. In the cloud, Builder.io provides a managed frame — the environment that hosts the agent next to your app — with collaboration, visual editing, and managed infrastructure for teams.
28
28
 
29
+ ## Agent building blocks {#agent-building-blocks}
30
+
31
+ Every agent-native app has the same agent building blocks, regardless of whether
32
+ the product surface is headless, chat-first, or a full UI:
33
+
34
+ ```an-file-tree title="Guidance and behavior"
35
+ {
36
+ "entries": [
37
+ { "path": "AGENTS.md", "note": "always-on instructions: purpose, core rules, state keys, action index, skills index" },
38
+ { "path": ".agents/skills/<name>/SKILL.md", "note": "reusable behavior: workflow steps, policies, examples, references, and do/don't lists" },
39
+ { "path": "actions/<name>.ts", "note": "executable capability: typed operation exposed to the agent, UI, CLI, HTTP, MCP, A2A, jobs, and webhooks" }
40
+ ]
41
+ }
42
+ ```
43
+
44
+ | Building block | Use it for | Loaded when |
45
+ | ---------------- | --------------------------------------------------------------------------------------------------- | ----------------------------------------------------- |
46
+ | **Instructions** | Stable guidance the agent should carry into every task: what the app is, invariants, tone, indexes | Every turn |
47
+ | **Skills** | Reusable behavior: how to follow a workflow, apply a policy, inspect evidence, or verify an output | On demand when the skill description matches the task |
48
+ | **Actions** | Real operations: read or write data, call APIs, send messages, run approvals, produce typed results | Listed as tools every turn; executed only when called |
49
+
50
+ Skills and actions work together. A skill teaches the agent how to do a class of
51
+ work; an action is the code path it can call while doing that work. For example,
52
+ a `customer-research` skill might tell the agent which sources to inspect and
53
+ how to summarize evidence, while `search-crm` and `create-brief` actions fetch
54
+ and write the actual data.
55
+
29
56
  Six rules govern the architecture:
30
57
 
31
58
  1. **Data lives in SQL** — all app state lives in the database via Drizzle ORM
@@ -114,6 +114,26 @@ defineAction({
114
114
  });
115
115
  ```
116
116
 
117
+ ## Skills vs actions {#skills-vs-actions}
118
+
119
+ Skills and actions are complementary. A skill is guidance the agent reads; an
120
+ action is code the agent can run.
121
+
122
+ | Need | Use |
123
+ | ---------------------------------------------------------------------- | ---------------------------------- |
124
+ | The agent needs to follow a workflow, policy, checklist, or rubric | **Skill** |
125
+ | The agent needs examples, reference material, or domain-specific rules | **Skill** |
126
+ | The agent needs to read or write app data | **Action** |
127
+ | The agent needs to call an external API or perform an approval | **Action** |
128
+ | The agent calls the right operation but in the wrong way | Improve the **skill** |
129
+ | The agent cannot reliably invoke the operation | Improve the **action** |
130
+ | The agent chooses the wrong tool | Improve the **action description** |
131
+
132
+ Most real features use both: the skill explains how to approach the task, and
133
+ the action provides the typed operation. For example, an `invoice-review` skill
134
+ can explain the review policy and escalation rules, while `list-invoices`,
135
+ `flag-invoice`, and `approve-invoice` actions do the actual reads and writes.
136
+
117
137
  ## Bake in anti-fabrication and verify-before-done {#anti-fabrication}
118
138
 
119
139
  App instructions should make honesty and verification the default behavior:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.66.0",
3
+ "version": "0.66.1",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=22"