@brainfish-ai/devdoc 0.1.21
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.
- package/LICENSE +33 -0
- package/README.md +415 -0
- package/bin/devdoc.js +13 -0
- package/dist/cli/commands/build.d.ts +5 -0
- package/dist/cli/commands/build.js +87 -0
- package/dist/cli/commands/check.d.ts +1 -0
- package/dist/cli/commands/check.js +143 -0
- package/dist/cli/commands/create.d.ts +24 -0
- package/dist/cli/commands/create.js +387 -0
- package/dist/cli/commands/deploy.d.ts +9 -0
- package/dist/cli/commands/deploy.js +433 -0
- package/dist/cli/commands/dev.d.ts +6 -0
- package/dist/cli/commands/dev.js +139 -0
- package/dist/cli/commands/init.d.ts +11 -0
- package/dist/cli/commands/init.js +238 -0
- package/dist/cli/commands/keys.d.ts +12 -0
- package/dist/cli/commands/keys.js +165 -0
- package/dist/cli/commands/start.d.ts +5 -0
- package/dist/cli/commands/start.js +56 -0
- package/dist/cli/commands/upload.d.ts +13 -0
- package/dist/cli/commands/upload.js +238 -0
- package/dist/cli/commands/whoami.d.ts +8 -0
- package/dist/cli/commands/whoami.js +91 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +106 -0
- package/dist/config/index.d.ts +80 -0
- package/dist/config/index.js +133 -0
- package/dist/constants.d.ts +9 -0
- package/dist/constants.js +13 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +12 -0
- package/dist/utils/logger.d.ts +16 -0
- package/dist/utils/logger.js +61 -0
- package/dist/utils/paths.d.ts +16 -0
- package/dist/utils/paths.js +50 -0
- package/package.json +51 -0
- package/renderer/app/api/assets/[...path]/route.ts +123 -0
- package/renderer/app/api/assets/route.ts +124 -0
- package/renderer/app/api/assets/upload/route.ts +177 -0
- package/renderer/app/api/auth-schemes/route.ts +77 -0
- package/renderer/app/api/chat/route.ts +858 -0
- package/renderer/app/api/codegen/route.ts +72 -0
- package/renderer/app/api/collections/route.ts +1016 -0
- package/renderer/app/api/debug/route.ts +53 -0
- package/renderer/app/api/deploy/route.ts +234 -0
- package/renderer/app/api/device/route.ts +42 -0
- package/renderer/app/api/docs/route.ts +187 -0
- package/renderer/app/api/keys/regenerate/route.ts +80 -0
- package/renderer/app/api/openapi-spec/route.ts +151 -0
- package/renderer/app/api/projects/[slug]/route.ts +153 -0
- package/renderer/app/api/projects/[slug]/stats/route.ts +96 -0
- package/renderer/app/api/projects/register/route.ts +152 -0
- package/renderer/app/api/proxy/route.ts +149 -0
- package/renderer/app/api/proxy-stream/route.ts +168 -0
- package/renderer/app/api/redirects/route.ts +47 -0
- package/renderer/app/api/schema/route.ts +65 -0
- package/renderer/app/api/subdomains/check/route.ts +172 -0
- package/renderer/app/api/suggestions/route.ts +144 -0
- package/renderer/app/favicon.ico +0 -0
- package/renderer/app/globals.css +1103 -0
- package/renderer/app/layout.tsx +47 -0
- package/renderer/app/llms-full.txt/route.ts +346 -0
- package/renderer/app/llms.txt/route.ts +279 -0
- package/renderer/app/page.tsx +14 -0
- package/renderer/app/robots.txt/route.ts +84 -0
- package/renderer/app/sitemap.xml/route.ts +199 -0
- package/renderer/components/docs/index.ts +12 -0
- package/renderer/components/docs/mdx/accordion.tsx +169 -0
- package/renderer/components/docs/mdx/badge.tsx +132 -0
- package/renderer/components/docs/mdx/callouts.tsx +154 -0
- package/renderer/components/docs/mdx/cards.tsx +213 -0
- package/renderer/components/docs/mdx/changelog.tsx +120 -0
- package/renderer/components/docs/mdx/code-block.tsx +186 -0
- package/renderer/components/docs/mdx/code-group.tsx +421 -0
- package/renderer/components/docs/mdx/file-embeds.tsx +105 -0
- package/renderer/components/docs/mdx/frame.tsx +112 -0
- package/renderer/components/docs/mdx/highlight.tsx +151 -0
- package/renderer/components/docs/mdx/iframe.tsx +134 -0
- package/renderer/components/docs/mdx/image.tsx +235 -0
- package/renderer/components/docs/mdx/index.ts +204 -0
- package/renderer/components/docs/mdx/mermaid.tsx +240 -0
- package/renderer/components/docs/mdx/param-field.tsx +200 -0
- package/renderer/components/docs/mdx/steps.tsx +113 -0
- package/renderer/components/docs/mdx/tabs.tsx +86 -0
- package/renderer/components/docs/mdx-renderer.tsx +100 -0
- package/renderer/components/docs/navigation/breadcrumbs.tsx +76 -0
- package/renderer/components/docs/navigation/index.ts +8 -0
- package/renderer/components/docs/navigation/page-nav.tsx +64 -0
- package/renderer/components/docs/navigation/sidebar.tsx +515 -0
- package/renderer/components/docs/navigation/toc.tsx +113 -0
- package/renderer/components/docs/notice.tsx +105 -0
- package/renderer/components/docs-header.tsx +274 -0
- package/renderer/components/docs-viewer/agent/agent-chat.tsx +2076 -0
- package/renderer/components/docs-viewer/agent/cards/debug-context-card.tsx +90 -0
- package/renderer/components/docs-viewer/agent/cards/endpoint-context-card.tsx +49 -0
- package/renderer/components/docs-viewer/agent/cards/index.tsx +50 -0
- package/renderer/components/docs-viewer/agent/cards/response-options-card.tsx +212 -0
- package/renderer/components/docs-viewer/agent/cards/types.ts +84 -0
- package/renderer/components/docs-viewer/agent/chat-message.tsx +17 -0
- package/renderer/components/docs-viewer/agent/index.tsx +6 -0
- package/renderer/components/docs-viewer/agent/messages/assistant-message.tsx +119 -0
- package/renderer/components/docs-viewer/agent/messages/chat-message.tsx +46 -0
- package/renderer/components/docs-viewer/agent/messages/index.ts +17 -0
- package/renderer/components/docs-viewer/agent/messages/tool-call-display.tsx +721 -0
- package/renderer/components/docs-viewer/agent/messages/types.ts +61 -0
- package/renderer/components/docs-viewer/agent/messages/typing-indicator.tsx +24 -0
- package/renderer/components/docs-viewer/agent/messages/user-message.tsx +51 -0
- package/renderer/components/docs-viewer/code-editor/index.tsx +2 -0
- package/renderer/components/docs-viewer/code-editor/notes-mode.tsx +1283 -0
- package/renderer/components/docs-viewer/content/changelog-page.tsx +331 -0
- package/renderer/components/docs-viewer/content/doc-page.tsx +285 -0
- package/renderer/components/docs-viewer/content/documentation-viewer.tsx +17 -0
- package/renderer/components/docs-viewer/content/index.tsx +29 -0
- package/renderer/components/docs-viewer/content/introduction.tsx +21 -0
- package/renderer/components/docs-viewer/content/request-details.tsx +330 -0
- package/renderer/components/docs-viewer/content/sections/auth.tsx +69 -0
- package/renderer/components/docs-viewer/content/sections/body.tsx +66 -0
- package/renderer/components/docs-viewer/content/sections/headers.tsx +43 -0
- package/renderer/components/docs-viewer/content/sections/overview.tsx +40 -0
- package/renderer/components/docs-viewer/content/sections/parameters.tsx +43 -0
- package/renderer/components/docs-viewer/content/sections/responses.tsx +87 -0
- package/renderer/components/docs-viewer/global-auth-modal.tsx +352 -0
- package/renderer/components/docs-viewer/index.tsx +1466 -0
- package/renderer/components/docs-viewer/playground/auth-editor.tsx +280 -0
- package/renderer/components/docs-viewer/playground/body-editor.tsx +221 -0
- package/renderer/components/docs-viewer/playground/code-editor.tsx +224 -0
- package/renderer/components/docs-viewer/playground/code-snippet.tsx +387 -0
- package/renderer/components/docs-viewer/playground/graphql-playground.tsx +745 -0
- package/renderer/components/docs-viewer/playground/index.tsx +671 -0
- package/renderer/components/docs-viewer/playground/key-value-editor.tsx +261 -0
- package/renderer/components/docs-viewer/playground/method-selector.tsx +60 -0
- package/renderer/components/docs-viewer/playground/request-builder.tsx +179 -0
- package/renderer/components/docs-viewer/playground/request-tabs.tsx +237 -0
- package/renderer/components/docs-viewer/playground/response-cards/idle-card.tsx +21 -0
- package/renderer/components/docs-viewer/playground/response-cards/index.tsx +93 -0
- package/renderer/components/docs-viewer/playground/response-cards/loading-card.tsx +16 -0
- package/renderer/components/docs-viewer/playground/response-cards/network-error-card.tsx +23 -0
- package/renderer/components/docs-viewer/playground/response-cards/response-body-card.tsx +268 -0
- package/renderer/components/docs-viewer/playground/response-cards/types.ts +82 -0
- package/renderer/components/docs-viewer/playground/response-viewer.tsx +43 -0
- package/renderer/components/docs-viewer/search/index.ts +2 -0
- package/renderer/components/docs-viewer/search/search-dialog.tsx +331 -0
- package/renderer/components/docs-viewer/search/use-search.ts +117 -0
- package/renderer/components/docs-viewer/shared/markdown-renderer.tsx +431 -0
- package/renderer/components/docs-viewer/shared/method-badge.tsx +41 -0
- package/renderer/components/docs-viewer/shared/schema-viewer.tsx +349 -0
- package/renderer/components/docs-viewer/sidebar/collection-tree.tsx +239 -0
- package/renderer/components/docs-viewer/sidebar/endpoint-options.tsx +316 -0
- package/renderer/components/docs-viewer/sidebar/index.tsx +343 -0
- package/renderer/components/docs-viewer/sidebar/right-sidebar.tsx +202 -0
- package/renderer/components/docs-viewer/sidebar/sidebar-group.tsx +118 -0
- package/renderer/components/docs-viewer/sidebar/sidebar-item.tsx +226 -0
- package/renderer/components/docs-viewer/sidebar/sidebar-section.tsx +52 -0
- package/renderer/components/theme-provider.tsx +11 -0
- package/renderer/components/theme-toggle.tsx +76 -0
- package/renderer/components/ui/badge.tsx +46 -0
- package/renderer/components/ui/button.tsx +59 -0
- package/renderer/components/ui/dialog.tsx +118 -0
- package/renderer/components/ui/dropdown-menu.tsx +257 -0
- package/renderer/components/ui/input.tsx +21 -0
- package/renderer/components/ui/label.tsx +24 -0
- package/renderer/components/ui/navigation-menu.tsx +168 -0
- package/renderer/components/ui/select.tsx +190 -0
- package/renderer/components/ui/spinner.tsx +114 -0
- package/renderer/components/ui/tabs.tsx +66 -0
- package/renderer/components/ui/tooltip.tsx +61 -0
- package/renderer/hooks/use-code-copy.ts +88 -0
- package/renderer/hooks/use-openapi-title.ts +44 -0
- package/renderer/lib/api-docs/agent/index.ts +6 -0
- package/renderer/lib/api-docs/agent/indexer.ts +323 -0
- package/renderer/lib/api-docs/agent/spec-summary.ts +335 -0
- package/renderer/lib/api-docs/agent/types.ts +116 -0
- package/renderer/lib/api-docs/auth/auth-context.tsx +225 -0
- package/renderer/lib/api-docs/auth/auth-storage.ts +87 -0
- package/renderer/lib/api-docs/auth/crypto.ts +89 -0
- package/renderer/lib/api-docs/auth/index.ts +4 -0
- package/renderer/lib/api-docs/code-editor/db.ts +164 -0
- package/renderer/lib/api-docs/code-editor/hooks.ts +266 -0
- package/renderer/lib/api-docs/code-editor/index.ts +6 -0
- package/renderer/lib/api-docs/code-editor/mode-context.tsx +207 -0
- package/renderer/lib/api-docs/code-editor/types.ts +105 -0
- package/renderer/lib/api-docs/codegen/definitions.ts +297 -0
- package/renderer/lib/api-docs/codegen/har.ts +251 -0
- package/renderer/lib/api-docs/codegen/index.ts +159 -0
- package/renderer/lib/api-docs/factories.ts +151 -0
- package/renderer/lib/api-docs/index.ts +17 -0
- package/renderer/lib/api-docs/mobile-context.tsx +112 -0
- package/renderer/lib/api-docs/navigation-context.tsx +88 -0
- package/renderer/lib/api-docs/parsers/graphql/README.md +129 -0
- package/renderer/lib/api-docs/parsers/graphql/index.ts +91 -0
- package/renderer/lib/api-docs/parsers/graphql/parser.ts +491 -0
- package/renderer/lib/api-docs/parsers/graphql/transformer.ts +246 -0
- package/renderer/lib/api-docs/parsers/graphql/types.ts +283 -0
- package/renderer/lib/api-docs/parsers/openapi/README.md +32 -0
- package/renderer/lib/api-docs/parsers/openapi/dereferencer.ts +60 -0
- package/renderer/lib/api-docs/parsers/openapi/extractors/auth.ts +574 -0
- package/renderer/lib/api-docs/parsers/openapi/extractors/body.ts +403 -0
- package/renderer/lib/api-docs/parsers/openapi/extractors/index.ts +232 -0
- package/renderer/lib/api-docs/parsers/openapi/index.ts +171 -0
- package/renderer/lib/api-docs/parsers/openapi/transformer.ts +277 -0
- package/renderer/lib/api-docs/parsers/openapi/validator.ts +31 -0
- package/renderer/lib/api-docs/playground/context.tsx +107 -0
- package/renderer/lib/api-docs/playground/navigation-context.tsx +124 -0
- package/renderer/lib/api-docs/playground/request-builder.ts +223 -0
- package/renderer/lib/api-docs/playground/request-runner.ts +282 -0
- package/renderer/lib/api-docs/playground/types.ts +35 -0
- package/renderer/lib/api-docs/types.ts +269 -0
- package/renderer/lib/api-docs/utils.ts +311 -0
- package/renderer/lib/cache.ts +193 -0
- package/renderer/lib/docs/config/index.ts +29 -0
- package/renderer/lib/docs/config/loader.ts +142 -0
- package/renderer/lib/docs/config/schema.ts +298 -0
- package/renderer/lib/docs/index.ts +12 -0
- package/renderer/lib/docs/mdx/compiler.ts +176 -0
- package/renderer/lib/docs/mdx/frontmatter.ts +80 -0
- package/renderer/lib/docs/mdx/index.ts +26 -0
- package/renderer/lib/docs/navigation/generator.ts +348 -0
- package/renderer/lib/docs/navigation/index.ts +12 -0
- package/renderer/lib/docs/navigation/types.ts +123 -0
- package/renderer/lib/docs-navigation-context.tsx +80 -0
- package/renderer/lib/multi-tenant/context.ts +105 -0
- package/renderer/lib/storage/blob.ts +845 -0
- package/renderer/lib/utils.ts +6 -0
- package/renderer/next.config.ts +76 -0
- package/renderer/package.json +66 -0
- package/renderer/postcss.config.mjs +5 -0
- package/renderer/public/assets/images/screenshot.png +0 -0
- package/renderer/public/assets/logo/dark.svg +9 -0
- package/renderer/public/assets/logo/light.svg +9 -0
- package/renderer/public/assets/logo.svg +9 -0
- package/renderer/public/file.svg +1 -0
- package/renderer/public/globe.svg +1 -0
- package/renderer/public/icon.png +0 -0
- package/renderer/public/logo.svg +9 -0
- package/renderer/public/window.svg +1 -0
- package/renderer/tsconfig.json +28 -0
- package/templates/basic/README.md +139 -0
- package/templates/basic/assets/favicon.svg +4 -0
- package/templates/basic/assets/logo.svg +9 -0
- package/templates/basic/docs.json +47 -0
- package/templates/basic/guides/configuration.mdx +149 -0
- package/templates/basic/guides/overview.mdx +96 -0
- package/templates/basic/index.mdx +39 -0
- package/templates/basic/package.json +14 -0
- package/templates/basic/quickstart.mdx +92 -0
- package/templates/basic/vercel.json +6 -0
- package/templates/graphql/README.md +139 -0
- package/templates/graphql/api-reference/schema.graphql +305 -0
- package/templates/graphql/assets/favicon.svg +4 -0
- package/templates/graphql/assets/logo.svg +9 -0
- package/templates/graphql/docs.json +54 -0
- package/templates/graphql/guides/configuration.mdx +149 -0
- package/templates/graphql/guides/overview.mdx +96 -0
- package/templates/graphql/index.mdx +39 -0
- package/templates/graphql/package.json +14 -0
- package/templates/graphql/quickstart.mdx +92 -0
- package/templates/graphql/vercel.json +6 -0
- package/templates/openapi/README.md +139 -0
- package/templates/openapi/api-reference/openapi.json +419 -0
- package/templates/openapi/assets/favicon.svg +4 -0
- package/templates/openapi/assets/logo.svg +9 -0
- package/templates/openapi/docs.json +61 -0
- package/templates/openapi/guides/configuration.mdx +149 -0
- package/templates/openapi/guides/overview.mdx +96 -0
- package/templates/openapi/index.mdx +39 -0
- package/templates/openapi/package.json +14 -0
- package/templates/openapi/quickstart.mdx +92 -0
- package/templates/openapi/vercel.json +6 -0
|
@@ -0,0 +1,858 @@
|
|
|
1
|
+
import { streamText, stepCountIs, tool } from 'ai'
|
|
2
|
+
import { anthropic } from '@ai-sdk/anthropic'
|
|
3
|
+
import { z } from 'zod'
|
|
4
|
+
import type { EndpointIndex } from '@/lib/api-docs/agent/types'
|
|
5
|
+
|
|
6
|
+
// Use Node.js runtime for better compatibility
|
|
7
|
+
export const runtime = 'nodejs'
|
|
8
|
+
|
|
9
|
+
// Documentation page index entry
|
|
10
|
+
interface DocIndexEntry {
|
|
11
|
+
id: string
|
|
12
|
+
slug: string
|
|
13
|
+
title: string
|
|
14
|
+
description: string
|
|
15
|
+
group: string
|
|
16
|
+
groupId: string
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Changelog release entry
|
|
20
|
+
interface ChangelogEntry {
|
|
21
|
+
version: string
|
|
22
|
+
date: string
|
|
23
|
+
title: string
|
|
24
|
+
slug: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function buildSystemPrompt(
|
|
28
|
+
endpoints: EndpointIndex[],
|
|
29
|
+
docs: DocIndexEntry[],
|
|
30
|
+
changelog: ChangelogEntry[],
|
|
31
|
+
currentEndpointId?: string,
|
|
32
|
+
apiSummary?: string,
|
|
33
|
+
): string {
|
|
34
|
+
const endpointsList = endpoints
|
|
35
|
+
.map((ep, i) => {
|
|
36
|
+
const params = ep.parameters.length > 0 ? ` (params: ${ep.parameters.join(', ')})` : ''
|
|
37
|
+
return `${i + 1}. [${ep.method}] ${ep.name} - ${ep.path}${params}${ep.description ? ` - ${ep.description.slice(0, 100)}` : ''} (id: ${ep.id})`
|
|
38
|
+
})
|
|
39
|
+
.join('\n')
|
|
40
|
+
|
|
41
|
+
// Group docs by their group for better organization
|
|
42
|
+
const docsByGroup = docs.reduce((acc, doc) => {
|
|
43
|
+
if (!acc[doc.group]) acc[doc.group] = []
|
|
44
|
+
acc[doc.group].push(doc)
|
|
45
|
+
return acc
|
|
46
|
+
}, {} as Record<string, typeof docs>)
|
|
47
|
+
|
|
48
|
+
const docsList = Object.entries(docsByGroup)
|
|
49
|
+
.map(([group, pages]) => {
|
|
50
|
+
const pagesList = pages
|
|
51
|
+
.map(doc => ` - "${doc.title}" → slug: "${doc.slug}"${doc.description ? ` (${doc.description.slice(0, 60)})` : ''}`)
|
|
52
|
+
.join('\n')
|
|
53
|
+
return `### ${group}\n${pagesList}`
|
|
54
|
+
})
|
|
55
|
+
.join('\n\n')
|
|
56
|
+
|
|
57
|
+
const currentEndpoint = currentEndpointId
|
|
58
|
+
? endpoints.find(e => e.id === currentEndpointId)
|
|
59
|
+
: null
|
|
60
|
+
|
|
61
|
+
// Get today's date in a readable format
|
|
62
|
+
const today = new Date().toLocaleDateString('en-US', {
|
|
63
|
+
weekday: 'long',
|
|
64
|
+
year: 'numeric',
|
|
65
|
+
month: 'long',
|
|
66
|
+
day: 'numeric',
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
return `# Documentation Assistant
|
|
70
|
+
**Today's Date**: ${today}
|
|
71
|
+
|
|
72
|
+
You are a documentation assistant that ONLY answers questions about this specific documentation - including API endpoints, guides, tutorials, and reference materials. Be **concise and practical** - talk like a colleague, not a support bot.
|
|
73
|
+
|
|
74
|
+
## CRITICAL: Stay On Topic
|
|
75
|
+
- **ONLY** answer questions related to THIS documentation, its API endpoints, guides, changelog/releases, and content
|
|
76
|
+
- **ONLY** provide code examples relevant to THIS documentation
|
|
77
|
+
- Questions about "releases", "what's new", "latest version", "changelog", "updates" ARE on-topic - use the search tool with type: "changelog"
|
|
78
|
+
- If asked about unrelated topics (general coding questions, other APIs, off-topic subjects), politely redirect: "I can only help with questions about this documentation. Is there something specific I can help you with?"
|
|
79
|
+
- When analyzing images, ONLY discuss them in the context of this documentation (e.g., error screenshots, API responses, diagrams)
|
|
80
|
+
- Do NOT answer general knowledge questions, math problems, or anything unrelated to this documentation
|
|
81
|
+
|
|
82
|
+
${apiSummary ? `${apiSummary}\n` : ''}
|
|
83
|
+
|
|
84
|
+
${currentEndpoint ? `
|
|
85
|
+
## IMPORTANT: Current Endpoint Context
|
|
86
|
+
The user is currently viewing: **${currentEndpoint.name}** (${currentEndpoint.method} ${currentEndpoint.path})
|
|
87
|
+
Endpoint ID: ${currentEndpoint.id}
|
|
88
|
+
|
|
89
|
+
**When the user says "this endpoint", "this", "it", "current endpoint", "what does it do", "what is this", "what is this endpoint used for", or asks ANY contextual question about an endpoint without specifying which one - ALWAYS assume they mean the current endpoint above.**
|
|
90
|
+
|
|
91
|
+
Use get_endpoint_details with ID "${currentEndpoint.id}" to answer questions about this endpoint's parameters, body, authentication, etc.
|
|
92
|
+
` : '## No endpoint currently selected\nUser is browsing the API documentation. Help them find what they need.'}
|
|
93
|
+
|
|
94
|
+
${endpointsList ? `## Available API Endpoints
|
|
95
|
+
${endpointsList}` : ''}
|
|
96
|
+
|
|
97
|
+
${docsList ? `## Available Documentation Pages (use slug for navigation)
|
|
98
|
+
${docsList}` : ''}
|
|
99
|
+
|
|
100
|
+
${changelog.length > 0 ? `## Changelog / Releases
|
|
101
|
+
This documentation has a changelog with release history. Latest releases:
|
|
102
|
+
${changelog.slice(0, 5).map(c => `- **${c.version}** (${c.date}): ${c.title} → slug: "${c.slug}"`).join('\n')}
|
|
103
|
+
${changelog.length > 5 ? `\n...and ${changelog.length - 5} more releases` : ''}
|
|
104
|
+
|
|
105
|
+
**For any questions about releases, updates, what's new, changelog, or version history - ALWAYS use the search tool with type: "changelog"**` : ''}
|
|
106
|
+
|
|
107
|
+
## IMPORTANT: Proactive Search & Navigation
|
|
108
|
+
When a user asks about a topic:
|
|
109
|
+
1. Use **search** to find relevant content (docs, endpoints, changelog, etc.)
|
|
110
|
+
2. Use **navigate** IMMEDIATELY to show the most relevant result - do NOT ask permission
|
|
111
|
+
3. Use **scroll_to_section** if needed to scroll to a specific heading
|
|
112
|
+
4. Then provide a brief answer
|
|
113
|
+
|
|
114
|
+
Example flow for "how do I delete a project?":
|
|
115
|
+
1. search(query: "delete project") → finds Delete Project endpoint
|
|
116
|
+
2. navigate(type: "endpoint", id: "delete-project", title: "Delete Project")
|
|
117
|
+
3. Explain the answer
|
|
118
|
+
|
|
119
|
+
Example flow for "what's the latest release?" or "what's new?":
|
|
120
|
+
1. search(query: "latest release", type: "changelog") → finds changelog entries
|
|
121
|
+
2. navigate(type: "changelog", id: "<version-slug>", title: "<version>")
|
|
122
|
+
3. Explain the release highlights
|
|
123
|
+
|
|
124
|
+
Example flow for "how do I configure navigation?":
|
|
125
|
+
1. search(query: "navigation config", type: "docs") → finds Navigation page
|
|
126
|
+
2. navigate(type: "doc", id: "config/navigation", title: "Navigation")
|
|
127
|
+
3. scroll_to_section(query: "groups") if user asked about groups specifically
|
|
128
|
+
4. Explain the answer
|
|
129
|
+
|
|
130
|
+
Do NOT ask "Would you like me to show you...?" - just search, navigate, and explain.
|
|
131
|
+
|
|
132
|
+
## Response Style
|
|
133
|
+
- **Default**: Short, direct answers (1-3 sentences)
|
|
134
|
+
- **Only expand** when user asks "explain", "debug", "details", or "why"
|
|
135
|
+
- Use bullet points for lists, not paragraphs
|
|
136
|
+
- Skip pleasantries like "Great question!" or "I'd be happy to help"
|
|
137
|
+
- **Always ground answers in the API context** - reference specific endpoints, parameters, or documentation
|
|
138
|
+
- If you don't have information about something in the API, say so - don't make up answers
|
|
139
|
+
|
|
140
|
+
## Markdown Formatting Rules (CRITICAL - MUST FOLLOW)
|
|
141
|
+
|
|
142
|
+
**HEADINGS - ALWAYS add blank line before**:
|
|
143
|
+
- ✅ CORRECT: \`some text.\\n\\n## Heading\`
|
|
144
|
+
- ❌ WRONG: \`some text.## Heading\` (no newline)
|
|
145
|
+
|
|
146
|
+
**LISTS - ALWAYS put each item on NEW LINE**:
|
|
147
|
+
- ✅ CORRECT:
|
|
148
|
+
\`\`\`
|
|
149
|
+
Here are the endpoints:
|
|
150
|
+
|
|
151
|
+
- **List items** - GET /items
|
|
152
|
+
- **Create item** - POST /items
|
|
153
|
+
- **Get item** - GET /items/{id}
|
|
154
|
+
\`\`\`
|
|
155
|
+
- ❌ WRONG (WILL NOT RENDER PROPERLY):
|
|
156
|
+
\`\`\`
|
|
157
|
+
Here are the endpoints:- **List items** - GET- **Create item** - POST
|
|
158
|
+
\`\`\`
|
|
159
|
+
- ALWAYS add blank line before list starts
|
|
160
|
+
- ALWAYS add space after dash: \`- item\` not \`-item\`
|
|
161
|
+
- NEVER put multiple list items on same line
|
|
162
|
+
|
|
163
|
+
**Bold followed by list - add newline**:
|
|
164
|
+
- ✅ CORRECT: \`**Available:**\\n- item1\\n- item2\`
|
|
165
|
+
- ❌ WRONG: \`**Available:**- item1- item2\`
|
|
166
|
+
|
|
167
|
+
**Code**:
|
|
168
|
+
- Inline: \`\`code\`\`
|
|
169
|
+
- Block: Triple backticks with language
|
|
170
|
+
|
|
171
|
+
## Tools
|
|
172
|
+
|
|
173
|
+
**CRITICAL: ALWAYS SEARCH FIRST**
|
|
174
|
+
Before answering ANY question about this documentation, you MUST use search_docs or search_endpoints to find relevant content. DO NOT answer from general knowledge - only answer based on what you find in the documentation.
|
|
175
|
+
|
|
176
|
+
**search_docs**: Find documentation pages by topic or content
|
|
177
|
+
- **ALWAYS use this first** when user asks about concepts, guides, tutorials, how-to, deployment, getting started, etc.
|
|
178
|
+
- Returns matching documentation pages with their groups and slugs
|
|
179
|
+
- After finding a match, use navigate_to_doc_page with the slug to show the page
|
|
180
|
+
- Example flow: search_docs("deploy") → find deployment page → navigate_to_doc_page with slug
|
|
181
|
+
|
|
182
|
+
**search_endpoints**: Find API endpoints by description
|
|
183
|
+
- Use when user asks about specific API operations or endpoints
|
|
184
|
+
- 1 result → auto-navigate and briefly explain
|
|
185
|
+
- Multiple → list as bullets, ask which one
|
|
186
|
+
- None → suggest alternatives
|
|
187
|
+
|
|
188
|
+
**get_endpoint_details**: Get full schema (params, body, auth, responses)
|
|
189
|
+
- Use when asked about payload, fields, or schema
|
|
190
|
+
- Summarize briefly: "Requires JSON body: \`name\` (string), \`type\` (optional)"
|
|
191
|
+
|
|
192
|
+
**navigate_to_endpoint**: Navigate to a specific endpoint
|
|
193
|
+
- TRIGGERS: "navigate to", "go to", "take me to", "show me", "open", "navigate back", "go back"
|
|
194
|
+
- **IMPORTANT**: Only navigate when user EXPLICITLY asks to navigate to a different endpoint
|
|
195
|
+
- **DO NOT navigate** when user asks about "this endpoint", "fill params", "fill the params", "prefill", or any action on the current endpoint
|
|
196
|
+
- **When in doubt, ASK the user**: "Did you want me to fill the params on the current endpoint, or navigate to a different one?"
|
|
197
|
+
- If user is on endpoint A and asks a general question, assume they mean endpoint A
|
|
198
|
+
- **After navigating, call switch_to_docs** to show the documentation view
|
|
199
|
+
|
|
200
|
+
**navigate_to_doc_section**: Navigate to a documentation section
|
|
201
|
+
- Use when user asks about general topics: "authentication", "getting started", "rate limits", "errors", etc.
|
|
202
|
+
- Scrolls to that section in the Introduction/docs page
|
|
203
|
+
- Generate the sectionId as a slug (lowercase, hyphens): "Getting Started" → "getting-started"
|
|
204
|
+
|
|
205
|
+
**switch_to_docs**: Switch to Docs tab
|
|
206
|
+
- Use when user asks about an endpoint, wants documentation, or asks "what is", "how to use"
|
|
207
|
+
- Call this AFTER navigate_to_endpoint to show the documentation view
|
|
208
|
+
|
|
209
|
+
**prefill_parameters**: Fill in values user provides
|
|
210
|
+
- Use when user gives specific values like "user_id is 123", "set the name to John"
|
|
211
|
+
- Can fill params (query), headers, body, or pathVariables (URL path params)
|
|
212
|
+
- **IMPORTANT**: For URL path parameters like {id}, {document_id}, <<id>>, use pathVariables NOT params
|
|
213
|
+
- Example: If URL is /documents/{id}, use pathVariables: [{key: "id", value: "123"}]
|
|
214
|
+
- **IMPORTANT**: Call switch_to_api_client BEFORE prefilling so user can see the API Client
|
|
215
|
+
|
|
216
|
+
**switch_to_api_client**: Switch to API Client tab
|
|
217
|
+
- Use when helping users test endpoints, send requests, or prefill data
|
|
218
|
+
- Call this FIRST before prefill_parameters so user can see the changes
|
|
219
|
+
|
|
220
|
+
**check_request_validity**: Validate if request is ready to send
|
|
221
|
+
- Use BEFORE sending to check what's missing
|
|
222
|
+
- Returns status of: path params, query params, body fields, authentication
|
|
223
|
+
- Helps guide users through completing their request
|
|
224
|
+
|
|
225
|
+
**send_request**: Execute the API request
|
|
226
|
+
- Use when user says "send", "run", "try it", "execute", "test it"
|
|
227
|
+
- ALWAYS check_request_validity first if you haven't already
|
|
228
|
+
- Returns full response with status, body, headers, timing
|
|
229
|
+
|
|
230
|
+
**get_current_request**: Get the user's current request configuration from the API Client
|
|
231
|
+
- Use when user says "use my request", "use current payload", "based on my config", "copy from playground"
|
|
232
|
+
- Returns: method, URL, query params, headers, body - exactly as configured in the playground
|
|
233
|
+
- ALWAYS use this when generating code examples if user has configured a request
|
|
234
|
+
|
|
235
|
+
**list_notes**: List existing files in the Notes workspace
|
|
236
|
+
- **ALWAYS call this BEFORE creating a new file** to check for duplicates
|
|
237
|
+
- If a similar file exists (same topic, endpoint, or type), UPDATE it instead of creating new
|
|
238
|
+
- Returns file paths that can be filtered by name
|
|
239
|
+
|
|
240
|
+
**create_folder**: Create a folder in the Notes workspace for organizing related files
|
|
241
|
+
- Use when creating multiple related files (e.g., multiple examples, flows, docs)
|
|
242
|
+
- Good folder names: "auth-examples", "crud-operations", "error-handling", "api-flows"
|
|
243
|
+
|
|
244
|
+
**create_file**: Create a NEW file (only if no similar file exists)
|
|
245
|
+
- **Code Examples**: .py, .ts, .js, .go, .rb, .sh for curl
|
|
246
|
+
- **Mermaid Diagrams**: .mmd for visual flows/sequences
|
|
247
|
+
- **Markdown**: .md for detailed explanations
|
|
248
|
+
- With folders: "folder-name/file.ext"
|
|
249
|
+
|
|
250
|
+
**write_file**: Write content to any file (new or existing)
|
|
251
|
+
- Use after create_file for new files
|
|
252
|
+
- Use after open_file to UPDATE existing files
|
|
253
|
+
|
|
254
|
+
**delete_file**: Delete a file from the Notes workspace
|
|
255
|
+
- Use when user explicitly asks to delete/remove a file
|
|
256
|
+
- Use when switching implementations (e.g., "change to Node.js" → delete .py, create .js)
|
|
257
|
+
- Always confirm with user before deleting unless they explicitly requested it
|
|
258
|
+
|
|
259
|
+
**switch_to_notes**: Switch to the Notes workspace
|
|
260
|
+
- Use BEFORE creating/opening files so user can see them
|
|
261
|
+
|
|
262
|
+
## Rules
|
|
263
|
+
- **SEARCH FIRST, THEN ANSWER**: ALWAYS use search_docs or search_endpoints BEFORE answering any question. Do NOT answer from your general knowledge - only answer based on what you find in this documentation.
|
|
264
|
+
- **STAY ON TOPIC**: Only answer questions about THIS documentation. Decline off-topic requests politely.
|
|
265
|
+
- Use endpoint ID internally, NEVER show IDs to users
|
|
266
|
+
- NEVER output raw JSON - UI shows tool results
|
|
267
|
+
- Keep explanations brief unless asked for more
|
|
268
|
+
- **Current endpoint is THE context**: When user asks about "this", "this endpoint", "it", "current endpoint", "fill params", "prefill" or any contextual question - ALWAYS use the current endpoint from context above. DO NOT navigate away.
|
|
269
|
+
- **Navigation requires EXPLICIT intent**: Only navigate when user EXPLICITLY says "navigate to X", "go to X", "take me to X".
|
|
270
|
+
- **When ambiguous, ASK first**: If user's request could apply to current endpoint OR require navigation, ASK for clarification: "Do you want me to do this on the current endpoint, or navigate to a different one?"
|
|
271
|
+
- **NEVER assume navigation**: If user asks "fill the params" or "prefill", do it on the CURRENT endpoint - don't navigate elsewhere.
|
|
272
|
+
- **Use tools to verify**: When answering questions, USE search_docs or search_endpoints to get accurate information - don't make up answers.
|
|
273
|
+
|
|
274
|
+
## API Client Assistance (IMPORTANT)
|
|
275
|
+
|
|
276
|
+
When helping users build and send requests, follow this flow:
|
|
277
|
+
|
|
278
|
+
### 1. Path Parameters (URL params like {user_id}, <<id>>)
|
|
279
|
+
If endpoint has path params in the URL, ask for values:
|
|
280
|
+
- "What's the user_id you want to use?"
|
|
281
|
+
- Use prefill_parameters with **pathVariables** (NOT params) to fill them
|
|
282
|
+
- Example: prefill_parameters({ pathVariables: [{ key: "user_id", value: "123" }] })
|
|
283
|
+
|
|
284
|
+
### 2. Query Parameters
|
|
285
|
+
For required query params, prompt for values:
|
|
286
|
+
- "The search endpoint requires a 'q' parameter. What would you like to search for?"
|
|
287
|
+
- Mention optional params briefly: "You can also filter by category or price range."
|
|
288
|
+
|
|
289
|
+
### 3. Request Body
|
|
290
|
+
For POST/PUT/PATCH endpoints:
|
|
291
|
+
- Walk through required fields conversationally
|
|
292
|
+
- "To create a user, I need: email (required), name (required), phone (optional). What's the email?"
|
|
293
|
+
- Build the JSON body step by step
|
|
294
|
+
- Use prefill_parameters with body field to set it
|
|
295
|
+
|
|
296
|
+
### 4. Authentication
|
|
297
|
+
Before sending, verify auth is configured:
|
|
298
|
+
- If check_request_validity shows auth missing, tell user
|
|
299
|
+
- "This endpoint requires Bearer token auth. Would you like to set up your API credentials?"
|
|
300
|
+
- Guide to global auth modal if needed
|
|
301
|
+
|
|
302
|
+
### 5. Pre-Send Validation
|
|
303
|
+
When user wants to send:
|
|
304
|
+
1. Call check_request_validity first
|
|
305
|
+
2. If issues found, help fix them: "Almost ready! Just need the order_id parameter."
|
|
306
|
+
3. Once valid, confirm and send: "All set! Sending request..."
|
|
307
|
+
|
|
308
|
+
### 6. Post-Response Help
|
|
309
|
+
After request completes:
|
|
310
|
+
- On success: Brief summary of response
|
|
311
|
+
- On error (4xx/5xx): Explain the error, suggest fixes
|
|
312
|
+
- 401: "Authentication failed. Check your API token."
|
|
313
|
+
- 400: "Invalid request. The 'email' field format is wrong."
|
|
314
|
+
- 404: "Resource not found. Check the user_id value."
|
|
315
|
+
|
|
316
|
+
### Example Conversation Flow
|
|
317
|
+
User: "I want to create a new order"
|
|
318
|
+
→ Navigate to POST /orders endpoint
|
|
319
|
+
→ "To create an order, I need: customer_id and at least one item. What's the customer_id?"
|
|
320
|
+
|
|
321
|
+
User: "cust_123"
|
|
322
|
+
→ prefill_parameters with customer_id
|
|
323
|
+
→ "Got it! Now let's add items. What product_id and quantity?"
|
|
324
|
+
|
|
325
|
+
User: "prod_456, qty 2"
|
|
326
|
+
→ prefill_parameters with body containing items array
|
|
327
|
+
→ "Order ready! Want to add more items or send the request?"
|
|
328
|
+
|
|
329
|
+
User: "send it"
|
|
330
|
+
→ check_request_validity to verify all fields
|
|
331
|
+
→ send_request to execute
|
|
332
|
+
→ "Order created successfully! Order ID: ord_789"
|
|
333
|
+
|
|
334
|
+
## When to Use Notes (IMPORTANT)
|
|
335
|
+
|
|
336
|
+
**Notes are for IMPLEMENTATION ASSISTANCE** - help users quickly integrate the API into their codebase.
|
|
337
|
+
|
|
338
|
+
### Use Code Files (.py, .ts, .js, .go, .rb, .sh) for:
|
|
339
|
+
- **Copy-paste ready implementations** that users can drop into their projects
|
|
340
|
+
- Working examples with real values, not placeholders
|
|
341
|
+
- Include error handling, retries, and edge cases
|
|
342
|
+
- Add type definitions and interfaces (TypeScript, Python type hints)
|
|
343
|
+
|
|
344
|
+
### Code Quality Guidelines:
|
|
345
|
+
1. **Production-ready**: Include error handling, logging, timeouts
|
|
346
|
+
2. **Self-documented**: Clear variable names, comments explaining "why"
|
|
347
|
+
3. **Complete**: Import statements, dependencies, config at top
|
|
348
|
+
4. **Testable**: Include example test cases or curl commands to verify
|
|
349
|
+
5. **Secure**: Never hardcode secrets, use environment variables
|
|
350
|
+
|
|
351
|
+
### Use Mermaid Diagrams (.mmd) for:
|
|
352
|
+
- Authentication/authorization flows → sequenceDiagram
|
|
353
|
+
- Multi-endpoint workflows (e.g., "create order → add items → checkout")
|
|
354
|
+
- Error handling decision trees → flowchart
|
|
355
|
+
- Data transformation pipelines
|
|
356
|
+
|
|
357
|
+
**IMPORTANT: Always include theme styling** using the init directive at the start of every mermaid diagram. Choose colors that match the diagram's purpose:
|
|
358
|
+
|
|
359
|
+
- **Auth/Security flows**: Purple/violet tones (#8b5cf6, #a78bfa)
|
|
360
|
+
- **Success/Happy paths**: Green tones (#22c55e, #4ade80)
|
|
361
|
+
- **Error handling**: Red/orange tones (#ef4444, #f97316)
|
|
362
|
+
- **Data flows**: Blue tones (#3b82f6, #60a5fa)
|
|
363
|
+
- **CRUD operations**: Teal/cyan tones (#14b8a6, #2dd4bf)
|
|
364
|
+
- **Webhooks/Events**: Yellow/amber tones (#eab308, #fbbf24)
|
|
365
|
+
|
|
366
|
+
Example with theme:
|
|
367
|
+
\`\`\`mermaid
|
|
368
|
+
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#3b82f6', 'primaryTextColor': '#ffffff', 'primaryBorderColor': '#60a5fa', 'lineColor': '#94a3b8', 'secondaryColor': '#1e40af', 'tertiaryColor': '#dbeafe'}}}%%
|
|
369
|
+
sequenceDiagram
|
|
370
|
+
Client->>+API: POST /auth/token
|
|
371
|
+
API-->>-Client: access_token
|
|
372
|
+
Client->>+API: GET /data (Bearer token)
|
|
373
|
+
API-->>-Client: Response
|
|
374
|
+
\`\`\`
|
|
375
|
+
|
|
376
|
+
### Use Markdown (.md) for:
|
|
377
|
+
- Step-by-step integration guides with code snippets
|
|
378
|
+
- Troubleshooting common errors
|
|
379
|
+
- Migration guides between API versions
|
|
380
|
+
|
|
381
|
+
## IMPORTANT: Always Create IMPLEMENTATION-READY Code
|
|
382
|
+
|
|
383
|
+
When users ask for examples, create **complete, working implementations**:
|
|
384
|
+
|
|
385
|
+
**Instead of snippets, create full files:**
|
|
386
|
+
\`\`\`python
|
|
387
|
+
# BAD: Just a snippet
|
|
388
|
+
response = requests.post(url, json=data)
|
|
389
|
+
|
|
390
|
+
# GOOD: Complete implementation
|
|
391
|
+
import requests
|
|
392
|
+
import os
|
|
393
|
+
from typing import Optional
|
|
394
|
+
|
|
395
|
+
class APIClient:
|
|
396
|
+
def __init__(self):
|
|
397
|
+
self.base_url = os.getenv("API_BASE_URL", "https://api.example.com")
|
|
398
|
+
self.api_key = os.getenv("API_KEY")
|
|
399
|
+
|
|
400
|
+
def create_resource(self, data: dict) -> dict:
|
|
401
|
+
"""Create a new resource with error handling."""
|
|
402
|
+
response = requests.post(
|
|
403
|
+
f"{self.base_url}/resources",
|
|
404
|
+
json=data,
|
|
405
|
+
headers={"Authorization": f"Bearer {self.api_key}"},
|
|
406
|
+
timeout=30
|
|
407
|
+
)
|
|
408
|
+
response.raise_for_status()
|
|
409
|
+
return response.json()
|
|
410
|
+
\`\`\`
|
|
411
|
+
|
|
412
|
+
## Implementation File Templates
|
|
413
|
+
|
|
414
|
+
**For API calls, ALWAYS include:**
|
|
415
|
+
1. Configuration (base URL, API key from env vars)
|
|
416
|
+
2. Request function with proper typing
|
|
417
|
+
3. Error handling with meaningful messages
|
|
418
|
+
4. Example usage at the bottom
|
|
419
|
+
5. Comments explaining authentication and key parameters
|
|
420
|
+
|
|
421
|
+
**For workflows, create:**
|
|
422
|
+
1. A Mermaid diagram showing the flow (.mmd)
|
|
423
|
+
2. Implementation code files for each step
|
|
424
|
+
3. Optionally a README.md tying them together
|
|
425
|
+
|
|
426
|
+
## Steps (MUST follow this order):
|
|
427
|
+
1. If user mentions "my request" → use get_current_request FIRST
|
|
428
|
+
2. Use get_endpoint_details to get the full schema
|
|
429
|
+
3. **ALWAYS call list_notes** to check for existing similar files
|
|
430
|
+
4. **If similar file exists**: UPDATE it with open_file + write_file
|
|
431
|
+
5. **If NO similar file**: create_file + write_file
|
|
432
|
+
6. For multiple files: create_folder first, then files inside
|
|
433
|
+
|
|
434
|
+
**IMPORTANT**: Use EXACT values from get_current_request in generated code.
|
|
435
|
+
|
|
436
|
+
**File naming convention:**
|
|
437
|
+
- \`{endpoint-action}.{lang}\` → e.g., \`create-user.py\`, \`list-orders.ts\`
|
|
438
|
+
- \`{workflow-name}/\` folder for multi-step flows
|
|
439
|
+
|
|
440
|
+
## Concept Explanations → Implementation Guides
|
|
441
|
+
When users ask to "explain" something, create ACTIONABLE content:
|
|
442
|
+
1. Create a .mmd diagram showing the flow visually
|
|
443
|
+
2. Create implementation code showing how to do it
|
|
444
|
+
3. Optionally add .md only if complex steps need documentation
|
|
445
|
+
|
|
446
|
+
**Always pair explanations with working code:**
|
|
447
|
+
- "Explain authentication" → auth-flow.mmd + auth-implementation.py
|
|
448
|
+
- "How do webhooks work" → webhook-flow.mmd + webhook-handler.ts
|
|
449
|
+
- "Show the order process" → order-flow.mmd + create-order.py + process-payment.py
|
|
450
|
+
|
|
451
|
+
PREFER: Diagram + Working Code
|
|
452
|
+
AVOID: Long text explanations without code
|
|
453
|
+
`
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Raw message part from useChat
|
|
457
|
+
interface RawPart {
|
|
458
|
+
type: string
|
|
459
|
+
text?: string
|
|
460
|
+
image?: string
|
|
461
|
+
toolCallId?: string
|
|
462
|
+
toolName?: string
|
|
463
|
+
input?: Record<string, unknown>
|
|
464
|
+
args?: Record<string, unknown>
|
|
465
|
+
output?: unknown
|
|
466
|
+
result?: unknown
|
|
467
|
+
state?: string
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// Raw message from useChat
|
|
471
|
+
interface RawMessage {
|
|
472
|
+
id?: string
|
|
473
|
+
role: 'user' | 'assistant' | 'system'
|
|
474
|
+
content?: string
|
|
475
|
+
parts?: RawPart[]
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// Message types for the AI SDK
|
|
479
|
+
type TextPart = { type: 'text'; text: string }
|
|
480
|
+
type ImagePart = { type: 'image'; image: string }
|
|
481
|
+
type UserContentPart = TextPart | ImagePart
|
|
482
|
+
type ToolCallPart = { type: 'tool-call'; toolCallId: string; toolName: string; input: Record<string, unknown> }
|
|
483
|
+
type ToolResultOutput = { type: 'json'; value: unknown } | { type: 'text'; value: string }
|
|
484
|
+
type ToolResultPart = { type: 'tool-result'; toolCallId: string; toolName: string; output: ToolResultOutput }
|
|
485
|
+
|
|
486
|
+
type ModelMessage =
|
|
487
|
+
| { role: 'user'; content: string | UserContentPart[] }
|
|
488
|
+
| { role: 'assistant'; content: string | Array<TextPart | ToolCallPart> }
|
|
489
|
+
| { role: 'tool'; content: ToolResultPart[] }
|
|
490
|
+
|
|
491
|
+
// Convert raw UIMessages to model messages for the AI SDK
|
|
492
|
+
function convertToCoreMessages(messages: RawMessage[]): ModelMessage[] {
|
|
493
|
+
const coreMessages: ModelMessage[] = []
|
|
494
|
+
|
|
495
|
+
for (const msg of messages) {
|
|
496
|
+
if (msg.role === 'user') {
|
|
497
|
+
// Extract text and image content from user message
|
|
498
|
+
const contentParts: UserContentPart[] = []
|
|
499
|
+
|
|
500
|
+
if (msg.content) {
|
|
501
|
+
contentParts.push({ type: 'text', text: msg.content })
|
|
502
|
+
} else if (msg.parts) {
|
|
503
|
+
for (const part of msg.parts) {
|
|
504
|
+
if (part.type === 'text' && part.text) {
|
|
505
|
+
contentParts.push({ type: 'text', text: part.text })
|
|
506
|
+
} else if (part.type === 'image' && part.image) {
|
|
507
|
+
contentParts.push({ type: 'image', image: part.image })
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
if (contentParts.length > 0) {
|
|
513
|
+
// If only text (no images), send as simple string for efficiency
|
|
514
|
+
const hasImages = contentParts.some(p => p.type === 'image')
|
|
515
|
+
if (!hasImages && contentParts.length === 1 && contentParts[0].type === 'text') {
|
|
516
|
+
coreMessages.push({
|
|
517
|
+
role: 'user',
|
|
518
|
+
content: contentParts[0].text,
|
|
519
|
+
})
|
|
520
|
+
} else {
|
|
521
|
+
// Multimodal message with images
|
|
522
|
+
coreMessages.push({
|
|
523
|
+
role: 'user',
|
|
524
|
+
content: contentParts,
|
|
525
|
+
})
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
} else if (msg.role === 'assistant') {
|
|
529
|
+
if (!msg.parts || msg.parts.length === 0) {
|
|
530
|
+
// Simple text-only assistant message
|
|
531
|
+
if (msg.content) {
|
|
532
|
+
coreMessages.push({
|
|
533
|
+
role: 'assistant',
|
|
534
|
+
content: msg.content,
|
|
535
|
+
})
|
|
536
|
+
}
|
|
537
|
+
continue
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// Process assistant message with parts (may include tool calls)
|
|
541
|
+
const textParts: string[] = []
|
|
542
|
+
const toolCalls: ToolCallPart[] = []
|
|
543
|
+
const toolResults: Array<{
|
|
544
|
+
toolCallId: string
|
|
545
|
+
toolName: string
|
|
546
|
+
output: { type: 'json'; value: unknown }
|
|
547
|
+
}> = []
|
|
548
|
+
|
|
549
|
+
for (const part of msg.parts) {
|
|
550
|
+
// Skip step-start parts
|
|
551
|
+
if (part.type === 'step-start') continue
|
|
552
|
+
|
|
553
|
+
// Handle text parts
|
|
554
|
+
if (part.type === 'text' && part.text) {
|
|
555
|
+
textParts.push(part.text)
|
|
556
|
+
continue
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// Handle tool call/result parts (format: "tool-{toolName}")
|
|
560
|
+
if (part.type.startsWith('tool-') &&
|
|
561
|
+
part.type !== 'tool-call' &&
|
|
562
|
+
part.type !== 'tool-result' &&
|
|
563
|
+
part.toolCallId) {
|
|
564
|
+
|
|
565
|
+
const toolName = part.toolName || part.type.replace('tool-', '')
|
|
566
|
+
const input = part.input || part.args || {}
|
|
567
|
+
|
|
568
|
+
// Add tool call
|
|
569
|
+
toolCalls.push({
|
|
570
|
+
type: 'tool-call',
|
|
571
|
+
toolCallId: part.toolCallId,
|
|
572
|
+
toolName,
|
|
573
|
+
input,
|
|
574
|
+
})
|
|
575
|
+
|
|
576
|
+
// If output is available, add tool result
|
|
577
|
+
if (part.state === 'output-available' && part.output !== undefined) {
|
|
578
|
+
toolResults.push({
|
|
579
|
+
toolCallId: part.toolCallId,
|
|
580
|
+
toolName,
|
|
581
|
+
// Wrap output in the format expected by AI SDK
|
|
582
|
+
output: { type: 'json', value: part.output },
|
|
583
|
+
})
|
|
584
|
+
}
|
|
585
|
+
continue
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// Handle already-normalized tool-call parts
|
|
589
|
+
if (part.type === 'tool-call' && part.toolCallId) {
|
|
590
|
+
toolCalls.push({
|
|
591
|
+
type: 'tool-call',
|
|
592
|
+
toolCallId: part.toolCallId,
|
|
593
|
+
toolName: part.toolName || 'unknown',
|
|
594
|
+
input: part.input || part.args || {},
|
|
595
|
+
})
|
|
596
|
+
continue
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
// Handle already-normalized tool-result parts
|
|
600
|
+
if (part.type === 'tool-result' && part.toolCallId) {
|
|
601
|
+
const resultValue = part.output || part.result
|
|
602
|
+
toolResults.push({
|
|
603
|
+
toolCallId: part.toolCallId,
|
|
604
|
+
toolName: part.toolName || 'unknown',
|
|
605
|
+
// Wrap output in the format expected by AI SDK
|
|
606
|
+
output: { type: 'json', value: resultValue },
|
|
607
|
+
})
|
|
608
|
+
continue
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// Build assistant message content
|
|
613
|
+
if (toolCalls.length > 0) {
|
|
614
|
+
// Assistant message with tool calls
|
|
615
|
+
const content: Array<TextPart | ToolCallPart> = []
|
|
616
|
+
|
|
617
|
+
// Add text content first
|
|
618
|
+
if (textParts.length > 0) {
|
|
619
|
+
content.push({
|
|
620
|
+
type: 'text',
|
|
621
|
+
text: textParts.join(''),
|
|
622
|
+
})
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
// Add tool calls
|
|
626
|
+
for (const tc of toolCalls) {
|
|
627
|
+
content.push(tc)
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
coreMessages.push({
|
|
631
|
+
role: 'assistant',
|
|
632
|
+
content,
|
|
633
|
+
})
|
|
634
|
+
|
|
635
|
+
// Add tool results as separate tool messages
|
|
636
|
+
if (toolResults.length > 0) {
|
|
637
|
+
coreMessages.push({
|
|
638
|
+
role: 'tool',
|
|
639
|
+
content: toolResults.map(tr => ({
|
|
640
|
+
type: 'tool-result' as const,
|
|
641
|
+
toolCallId: tr.toolCallId,
|
|
642
|
+
toolName: tr.toolName,
|
|
643
|
+
output: tr.output, // Already wrapped in { type: 'json', value: ... }
|
|
644
|
+
})),
|
|
645
|
+
})
|
|
646
|
+
}
|
|
647
|
+
} else if (textParts.length > 0) {
|
|
648
|
+
// Text-only assistant message
|
|
649
|
+
coreMessages.push({
|
|
650
|
+
role: 'assistant',
|
|
651
|
+
content: textParts.join(''),
|
|
652
|
+
})
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
return coreMessages
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
export async function POST(req: Request) {
|
|
661
|
+
try {
|
|
662
|
+
const body = await req.json()
|
|
663
|
+
const { messages, endpointIndex, docIndex, changelogIndex, currentEndpointId, apiSummary } = body as {
|
|
664
|
+
messages: RawMessage[]
|
|
665
|
+
endpointIndex: EndpointIndex[]
|
|
666
|
+
docIndex?: DocIndexEntry[]
|
|
667
|
+
changelogIndex?: ChangelogEntry[]
|
|
668
|
+
currentEndpointId?: string
|
|
669
|
+
apiSummary?: string
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// Check for API key
|
|
673
|
+
const apiKey = process.env.ANTHROPIC_API_KEY
|
|
674
|
+
if (!apiKey) {
|
|
675
|
+
return new Response(
|
|
676
|
+
JSON.stringify({ error: 'ANTHROPIC_API_KEY not configured. Please add it to your .env.local file.' }),
|
|
677
|
+
{ status: 500, headers: { 'Content-Type': 'application/json' } }
|
|
678
|
+
)
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
// Convert to CoreMessage format
|
|
682
|
+
const coreMessages = convertToCoreMessages(messages)
|
|
683
|
+
|
|
684
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
685
|
+
const typedMessages = coreMessages as any
|
|
686
|
+
|
|
687
|
+
const result = streamText({
|
|
688
|
+
model: anthropic('claude-sonnet-4-5-20250929'),
|
|
689
|
+
system: buildSystemPrompt(endpointIndex || [], docIndex || [], changelogIndex || [], currentEndpointId, apiSummary),
|
|
690
|
+
messages: typedMessages,
|
|
691
|
+
tools: {
|
|
692
|
+
// === UNIFIED SEARCH & NAVIGATION ===
|
|
693
|
+
// These tools work across all content types (docs, endpoints, graphql, storybook, etc.)
|
|
694
|
+
|
|
695
|
+
search: tool({
|
|
696
|
+
description: 'Search across all documentation content including docs, API endpoints, and changelog. Use this to find relevant information before navigating. For release/changelog questions, this will find changelog entries.',
|
|
697
|
+
inputSchema: z.object({
|
|
698
|
+
query: z.string().describe('Search query'),
|
|
699
|
+
type: z.enum(['all', 'docs', 'endpoints', 'changelog']).optional().describe('Filter by content type. Default: "all". Use "changelog" for release/version queries.'),
|
|
700
|
+
}),
|
|
701
|
+
}),
|
|
702
|
+
|
|
703
|
+
navigate: tool({
|
|
704
|
+
description: 'Navigate to any content in the documentation. This automatically switches to the correct view and tab. Use IMMEDIATELY after search to show the user the relevant content.',
|
|
705
|
+
inputSchema: z.object({
|
|
706
|
+
type: z.enum(['doc', 'endpoint', 'changelog', 'section']).describe('Content type: "doc" for documentation pages, "endpoint" for API endpoints, "changelog" for release notes, "section" for scrolling within current page'),
|
|
707
|
+
id: z.string().describe('The identifier: slug for docs, endpointId for endpoints, version slug for changelog, or heading text for sections'),
|
|
708
|
+
title: z.string().optional().describe('Display title'),
|
|
709
|
+
}),
|
|
710
|
+
}),
|
|
711
|
+
|
|
712
|
+
scroll_to_section: tool({
|
|
713
|
+
description: 'Scroll to a section within the CURRENT page. Use this AFTER navigating to a page to scroll to the relevant content. Searches headings (h1-h6) for matching text.',
|
|
714
|
+
inputSchema: z.object({
|
|
715
|
+
query: z.string().describe('Text to search for in page headings (e.g., "authentication", "installation", "usage examples")'),
|
|
716
|
+
}),
|
|
717
|
+
}),
|
|
718
|
+
prefill_parameters: tool({
|
|
719
|
+
description: 'Prefill request parameters, headers, body, or path variables for the current endpoint. Use this when the user provides values they want to use. For URL path parameters like {id} or <<id>>, use pathVariables.',
|
|
720
|
+
inputSchema: z.object({
|
|
721
|
+
params: z.array(z.object({
|
|
722
|
+
key: z.string(),
|
|
723
|
+
value: z.string(),
|
|
724
|
+
})).optional().describe('Query parameters to prefill'),
|
|
725
|
+
headers: z.array(z.object({
|
|
726
|
+
key: z.string(),
|
|
727
|
+
value: z.string(),
|
|
728
|
+
})).optional().describe('Headers to prefill'),
|
|
729
|
+
body: z.string().optional().describe('JSON body to prefill'),
|
|
730
|
+
pathVariables: z.array(z.object({
|
|
731
|
+
key: z.string(),
|
|
732
|
+
value: z.string(),
|
|
733
|
+
})).optional().describe('URL path variables to prefill (e.g., {id}, <<document_id>>). These replace placeholders in the URL path.'),
|
|
734
|
+
}),
|
|
735
|
+
}),
|
|
736
|
+
get_endpoint_details: tool({
|
|
737
|
+
description: 'Get FULL details about a specific endpoint. Returns: parameters (name, description, required), headers, authentication requirements, request body schema (contentType, required fields, example payload), and response schemas with status codes. Use this when users ask about payload structure, required fields, body format, or how to call an endpoint.',
|
|
738
|
+
inputSchema: z.object({
|
|
739
|
+
endpointId: z.string().describe('The ID of the endpoint to get details for'),
|
|
740
|
+
}),
|
|
741
|
+
}),
|
|
742
|
+
|
|
743
|
+
get_current_request: tool({
|
|
744
|
+
description: 'Get the current request payload from the API Client playground. Returns the actual values the user has configured: HTTP method, URL, query parameters, headers, and request body. Use this when user asks to "use my request", "use current payload", "copy from playground", "based on my configuration", or wants code examples using their exact request setup.',
|
|
745
|
+
inputSchema: z.object({}),
|
|
746
|
+
}),
|
|
747
|
+
|
|
748
|
+
// === MODE SWITCHING TOOLS ===
|
|
749
|
+
switch_to_docs: tool({
|
|
750
|
+
description: 'Switch to the Docs tab to show endpoint documentation. Use this when user asks about an endpoint, wants to understand how it works, asks "what is", "how to use", "what does this do", or needs to see documentation. This shows the detailed documentation view.',
|
|
751
|
+
inputSchema: z.object({}),
|
|
752
|
+
}),
|
|
753
|
+
|
|
754
|
+
switch_to_api_client: tool({
|
|
755
|
+
description: 'Switch to the API Client tab to test/send requests. Use this when user wants to test an endpoint, send a request, try it out, or you need to prefill parameters. Call this BEFORE prefilling data so user can see the API Client.',
|
|
756
|
+
inputSchema: z.object({}),
|
|
757
|
+
}),
|
|
758
|
+
|
|
759
|
+
// === NOTES TOOLS ===
|
|
760
|
+
switch_to_notes: tool({
|
|
761
|
+
description: 'Switch to the Notes workspace. Call this FIRST before creating any files.',
|
|
762
|
+
inputSchema: z.object({}),
|
|
763
|
+
}),
|
|
764
|
+
|
|
765
|
+
list_notes: tool({
|
|
766
|
+
description: 'List all existing notes/files in the workspace. Use this BEFORE creating a new file to check if a similar file already exists. Returns file paths and can help avoid duplicates.',
|
|
767
|
+
inputSchema: z.object({
|
|
768
|
+
filter: z.string().optional().describe('Optional filter to search by filename or path (e.g., "auth", "python", ".py")'),
|
|
769
|
+
}),
|
|
770
|
+
}),
|
|
771
|
+
|
|
772
|
+
open_file: tool({
|
|
773
|
+
description: 'Open an existing file in the Notes workspace. Use this when user asks to select, open, view, or show a specific file.',
|
|
774
|
+
inputSchema: z.object({
|
|
775
|
+
path: z.string().describe('Path of the file to open (e.g., "search_campaigns.rb", "example.py")'),
|
|
776
|
+
}),
|
|
777
|
+
}),
|
|
778
|
+
|
|
779
|
+
create_folder: tool({
|
|
780
|
+
description: 'Create a folder in the Notes workspace. Use this FIRST when creating multiple related files to keep them organized. Call AFTER switch_to_notes.',
|
|
781
|
+
inputSchema: z.object({
|
|
782
|
+
path: z.string().describe('Folder path (e.g., "auth-examples", "api-flows", "error-handling")'),
|
|
783
|
+
description: z.string().describe('Brief description of what this folder will contain'),
|
|
784
|
+
}),
|
|
785
|
+
}),
|
|
786
|
+
|
|
787
|
+
create_file: tool({
|
|
788
|
+
description: 'Create a new empty file and open it in the editor. Call AFTER checking list_notes for existing similar files. If a similar file exists, use open_file + write_file to UPDATE it instead.',
|
|
789
|
+
inputSchema: z.object({
|
|
790
|
+
path: z.string().describe('File path with extension. Use folders for organization: "folder/file.ext". Extensions: .sh for curl, .py/.ts/.js/.go/.rb for code, .mmd for Mermaid diagrams, .md for docs'),
|
|
791
|
+
description: z.string().describe('Brief description of what this file will contain'),
|
|
792
|
+
}),
|
|
793
|
+
}),
|
|
794
|
+
|
|
795
|
+
write_file: tool({
|
|
796
|
+
description: 'Write content to a file. Works for both new files (after create_file) and existing files (after open_file). The content will appear in the editor.',
|
|
797
|
+
inputSchema: z.object({
|
|
798
|
+
path: z.string().describe('File path to write to'),
|
|
799
|
+
content: z.string().describe('Complete file content with working code and real example values'),
|
|
800
|
+
}),
|
|
801
|
+
}),
|
|
802
|
+
|
|
803
|
+
delete_file: tool({
|
|
804
|
+
description: 'Delete a file from the Notes workspace. Use when user wants to remove a file, or when switching implementations (e.g., from Python to Node.js - delete the .py file before creating .js file).',
|
|
805
|
+
inputSchema: z.object({
|
|
806
|
+
path: z.string().describe('Path of the file to delete'),
|
|
807
|
+
reason: z.string().optional().describe('Brief reason for deletion (e.g., "Switching from Python to Node.js")'),
|
|
808
|
+
}),
|
|
809
|
+
}),
|
|
810
|
+
|
|
811
|
+
delete_all_notes: tool({
|
|
812
|
+
description: 'Delete ALL notes/files in the workspace. Use when user explicitly asks to "delete all", "clear all notes", "remove everything", or "start fresh". IMPORTANT: Always ask for confirmation first before calling this tool. Set confirmed=true only after user confirms.',
|
|
813
|
+
inputSchema: z.object({
|
|
814
|
+
confirmed: z.boolean().describe('Must be true to proceed. Ask user for confirmation first: "Are you sure you want to delete all X notes? This cannot be undone."'),
|
|
815
|
+
}),
|
|
816
|
+
}),
|
|
817
|
+
|
|
818
|
+
// === API CLIENT ASSISTANCE TOOLS ===
|
|
819
|
+
check_request_validity: tool({
|
|
820
|
+
description: `Check if the current API request is ready to send. Returns validation status for:
|
|
821
|
+
- URL path parameters (e.g., {user_id}, {order_id})
|
|
822
|
+
- Required query parameters
|
|
823
|
+
- Required request body fields
|
|
824
|
+
- Authentication configuration
|
|
825
|
+
|
|
826
|
+
Use this BEFORE sending a request to help users complete missing fields. Returns a detailed breakdown of what's missing and what's configured correctly.`,
|
|
827
|
+
inputSchema: z.object({
|
|
828
|
+
endpointId: z.string().describe('The endpoint ID to validate'),
|
|
829
|
+
}),
|
|
830
|
+
}),
|
|
831
|
+
|
|
832
|
+
send_request: tool({
|
|
833
|
+
description: `Execute the API request from the playground. Use this when:
|
|
834
|
+
- User says "send", "execute", "run", "try it", "make the request", "call the API"
|
|
835
|
+
- After helping user fill in all required parameters
|
|
836
|
+
- User wants to test the endpoint
|
|
837
|
+
|
|
838
|
+
Returns the full response including status, headers, body, and timing. If the request fails, includes error details for debugging.`,
|
|
839
|
+
inputSchema: z.object({
|
|
840
|
+
confirmSend: z.boolean().describe('Set to true to confirm sending the request'),
|
|
841
|
+
}),
|
|
842
|
+
}),
|
|
843
|
+
},
|
|
844
|
+
stopWhen: stepCountIs(8),
|
|
845
|
+
})
|
|
846
|
+
|
|
847
|
+
return result.toUIMessageStreamResponse()
|
|
848
|
+
} catch (error) {
|
|
849
|
+
console.error('[Chat API] Error:', error)
|
|
850
|
+
|
|
851
|
+
const errorMessage = error instanceof Error ? error.message : 'Failed to process request'
|
|
852
|
+
|
|
853
|
+
return new Response(
|
|
854
|
+
JSON.stringify({ error: errorMessage }),
|
|
855
|
+
{ status: 500, headers: { 'Content-Type': 'application/json' } }
|
|
856
|
+
)
|
|
857
|
+
}
|
|
858
|
+
}
|