@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.
Files changed (268) hide show
  1. package/LICENSE +33 -0
  2. package/README.md +415 -0
  3. package/bin/devdoc.js +13 -0
  4. package/dist/cli/commands/build.d.ts +5 -0
  5. package/dist/cli/commands/build.js +87 -0
  6. package/dist/cli/commands/check.d.ts +1 -0
  7. package/dist/cli/commands/check.js +143 -0
  8. package/dist/cli/commands/create.d.ts +24 -0
  9. package/dist/cli/commands/create.js +387 -0
  10. package/dist/cli/commands/deploy.d.ts +9 -0
  11. package/dist/cli/commands/deploy.js +433 -0
  12. package/dist/cli/commands/dev.d.ts +6 -0
  13. package/dist/cli/commands/dev.js +139 -0
  14. package/dist/cli/commands/init.d.ts +11 -0
  15. package/dist/cli/commands/init.js +238 -0
  16. package/dist/cli/commands/keys.d.ts +12 -0
  17. package/dist/cli/commands/keys.js +165 -0
  18. package/dist/cli/commands/start.d.ts +5 -0
  19. package/dist/cli/commands/start.js +56 -0
  20. package/dist/cli/commands/upload.d.ts +13 -0
  21. package/dist/cli/commands/upload.js +238 -0
  22. package/dist/cli/commands/whoami.d.ts +8 -0
  23. package/dist/cli/commands/whoami.js +91 -0
  24. package/dist/cli/index.d.ts +1 -0
  25. package/dist/cli/index.js +106 -0
  26. package/dist/config/index.d.ts +80 -0
  27. package/dist/config/index.js +133 -0
  28. package/dist/constants.d.ts +9 -0
  29. package/dist/constants.js +13 -0
  30. package/dist/index.d.ts +7 -0
  31. package/dist/index.js +12 -0
  32. package/dist/utils/logger.d.ts +16 -0
  33. package/dist/utils/logger.js +61 -0
  34. package/dist/utils/paths.d.ts +16 -0
  35. package/dist/utils/paths.js +50 -0
  36. package/package.json +51 -0
  37. package/renderer/app/api/assets/[...path]/route.ts +123 -0
  38. package/renderer/app/api/assets/route.ts +124 -0
  39. package/renderer/app/api/assets/upload/route.ts +177 -0
  40. package/renderer/app/api/auth-schemes/route.ts +77 -0
  41. package/renderer/app/api/chat/route.ts +858 -0
  42. package/renderer/app/api/codegen/route.ts +72 -0
  43. package/renderer/app/api/collections/route.ts +1016 -0
  44. package/renderer/app/api/debug/route.ts +53 -0
  45. package/renderer/app/api/deploy/route.ts +234 -0
  46. package/renderer/app/api/device/route.ts +42 -0
  47. package/renderer/app/api/docs/route.ts +187 -0
  48. package/renderer/app/api/keys/regenerate/route.ts +80 -0
  49. package/renderer/app/api/openapi-spec/route.ts +151 -0
  50. package/renderer/app/api/projects/[slug]/route.ts +153 -0
  51. package/renderer/app/api/projects/[slug]/stats/route.ts +96 -0
  52. package/renderer/app/api/projects/register/route.ts +152 -0
  53. package/renderer/app/api/proxy/route.ts +149 -0
  54. package/renderer/app/api/proxy-stream/route.ts +168 -0
  55. package/renderer/app/api/redirects/route.ts +47 -0
  56. package/renderer/app/api/schema/route.ts +65 -0
  57. package/renderer/app/api/subdomains/check/route.ts +172 -0
  58. package/renderer/app/api/suggestions/route.ts +144 -0
  59. package/renderer/app/favicon.ico +0 -0
  60. package/renderer/app/globals.css +1103 -0
  61. package/renderer/app/layout.tsx +47 -0
  62. package/renderer/app/llms-full.txt/route.ts +346 -0
  63. package/renderer/app/llms.txt/route.ts +279 -0
  64. package/renderer/app/page.tsx +14 -0
  65. package/renderer/app/robots.txt/route.ts +84 -0
  66. package/renderer/app/sitemap.xml/route.ts +199 -0
  67. package/renderer/components/docs/index.ts +12 -0
  68. package/renderer/components/docs/mdx/accordion.tsx +169 -0
  69. package/renderer/components/docs/mdx/badge.tsx +132 -0
  70. package/renderer/components/docs/mdx/callouts.tsx +154 -0
  71. package/renderer/components/docs/mdx/cards.tsx +213 -0
  72. package/renderer/components/docs/mdx/changelog.tsx +120 -0
  73. package/renderer/components/docs/mdx/code-block.tsx +186 -0
  74. package/renderer/components/docs/mdx/code-group.tsx +421 -0
  75. package/renderer/components/docs/mdx/file-embeds.tsx +105 -0
  76. package/renderer/components/docs/mdx/frame.tsx +112 -0
  77. package/renderer/components/docs/mdx/highlight.tsx +151 -0
  78. package/renderer/components/docs/mdx/iframe.tsx +134 -0
  79. package/renderer/components/docs/mdx/image.tsx +235 -0
  80. package/renderer/components/docs/mdx/index.ts +204 -0
  81. package/renderer/components/docs/mdx/mermaid.tsx +240 -0
  82. package/renderer/components/docs/mdx/param-field.tsx +200 -0
  83. package/renderer/components/docs/mdx/steps.tsx +113 -0
  84. package/renderer/components/docs/mdx/tabs.tsx +86 -0
  85. package/renderer/components/docs/mdx-renderer.tsx +100 -0
  86. package/renderer/components/docs/navigation/breadcrumbs.tsx +76 -0
  87. package/renderer/components/docs/navigation/index.ts +8 -0
  88. package/renderer/components/docs/navigation/page-nav.tsx +64 -0
  89. package/renderer/components/docs/navigation/sidebar.tsx +515 -0
  90. package/renderer/components/docs/navigation/toc.tsx +113 -0
  91. package/renderer/components/docs/notice.tsx +105 -0
  92. package/renderer/components/docs-header.tsx +274 -0
  93. package/renderer/components/docs-viewer/agent/agent-chat.tsx +2076 -0
  94. package/renderer/components/docs-viewer/agent/cards/debug-context-card.tsx +90 -0
  95. package/renderer/components/docs-viewer/agent/cards/endpoint-context-card.tsx +49 -0
  96. package/renderer/components/docs-viewer/agent/cards/index.tsx +50 -0
  97. package/renderer/components/docs-viewer/agent/cards/response-options-card.tsx +212 -0
  98. package/renderer/components/docs-viewer/agent/cards/types.ts +84 -0
  99. package/renderer/components/docs-viewer/agent/chat-message.tsx +17 -0
  100. package/renderer/components/docs-viewer/agent/index.tsx +6 -0
  101. package/renderer/components/docs-viewer/agent/messages/assistant-message.tsx +119 -0
  102. package/renderer/components/docs-viewer/agent/messages/chat-message.tsx +46 -0
  103. package/renderer/components/docs-viewer/agent/messages/index.ts +17 -0
  104. package/renderer/components/docs-viewer/agent/messages/tool-call-display.tsx +721 -0
  105. package/renderer/components/docs-viewer/agent/messages/types.ts +61 -0
  106. package/renderer/components/docs-viewer/agent/messages/typing-indicator.tsx +24 -0
  107. package/renderer/components/docs-viewer/agent/messages/user-message.tsx +51 -0
  108. package/renderer/components/docs-viewer/code-editor/index.tsx +2 -0
  109. package/renderer/components/docs-viewer/code-editor/notes-mode.tsx +1283 -0
  110. package/renderer/components/docs-viewer/content/changelog-page.tsx +331 -0
  111. package/renderer/components/docs-viewer/content/doc-page.tsx +285 -0
  112. package/renderer/components/docs-viewer/content/documentation-viewer.tsx +17 -0
  113. package/renderer/components/docs-viewer/content/index.tsx +29 -0
  114. package/renderer/components/docs-viewer/content/introduction.tsx +21 -0
  115. package/renderer/components/docs-viewer/content/request-details.tsx +330 -0
  116. package/renderer/components/docs-viewer/content/sections/auth.tsx +69 -0
  117. package/renderer/components/docs-viewer/content/sections/body.tsx +66 -0
  118. package/renderer/components/docs-viewer/content/sections/headers.tsx +43 -0
  119. package/renderer/components/docs-viewer/content/sections/overview.tsx +40 -0
  120. package/renderer/components/docs-viewer/content/sections/parameters.tsx +43 -0
  121. package/renderer/components/docs-viewer/content/sections/responses.tsx +87 -0
  122. package/renderer/components/docs-viewer/global-auth-modal.tsx +352 -0
  123. package/renderer/components/docs-viewer/index.tsx +1466 -0
  124. package/renderer/components/docs-viewer/playground/auth-editor.tsx +280 -0
  125. package/renderer/components/docs-viewer/playground/body-editor.tsx +221 -0
  126. package/renderer/components/docs-viewer/playground/code-editor.tsx +224 -0
  127. package/renderer/components/docs-viewer/playground/code-snippet.tsx +387 -0
  128. package/renderer/components/docs-viewer/playground/graphql-playground.tsx +745 -0
  129. package/renderer/components/docs-viewer/playground/index.tsx +671 -0
  130. package/renderer/components/docs-viewer/playground/key-value-editor.tsx +261 -0
  131. package/renderer/components/docs-viewer/playground/method-selector.tsx +60 -0
  132. package/renderer/components/docs-viewer/playground/request-builder.tsx +179 -0
  133. package/renderer/components/docs-viewer/playground/request-tabs.tsx +237 -0
  134. package/renderer/components/docs-viewer/playground/response-cards/idle-card.tsx +21 -0
  135. package/renderer/components/docs-viewer/playground/response-cards/index.tsx +93 -0
  136. package/renderer/components/docs-viewer/playground/response-cards/loading-card.tsx +16 -0
  137. package/renderer/components/docs-viewer/playground/response-cards/network-error-card.tsx +23 -0
  138. package/renderer/components/docs-viewer/playground/response-cards/response-body-card.tsx +268 -0
  139. package/renderer/components/docs-viewer/playground/response-cards/types.ts +82 -0
  140. package/renderer/components/docs-viewer/playground/response-viewer.tsx +43 -0
  141. package/renderer/components/docs-viewer/search/index.ts +2 -0
  142. package/renderer/components/docs-viewer/search/search-dialog.tsx +331 -0
  143. package/renderer/components/docs-viewer/search/use-search.ts +117 -0
  144. package/renderer/components/docs-viewer/shared/markdown-renderer.tsx +431 -0
  145. package/renderer/components/docs-viewer/shared/method-badge.tsx +41 -0
  146. package/renderer/components/docs-viewer/shared/schema-viewer.tsx +349 -0
  147. package/renderer/components/docs-viewer/sidebar/collection-tree.tsx +239 -0
  148. package/renderer/components/docs-viewer/sidebar/endpoint-options.tsx +316 -0
  149. package/renderer/components/docs-viewer/sidebar/index.tsx +343 -0
  150. package/renderer/components/docs-viewer/sidebar/right-sidebar.tsx +202 -0
  151. package/renderer/components/docs-viewer/sidebar/sidebar-group.tsx +118 -0
  152. package/renderer/components/docs-viewer/sidebar/sidebar-item.tsx +226 -0
  153. package/renderer/components/docs-viewer/sidebar/sidebar-section.tsx +52 -0
  154. package/renderer/components/theme-provider.tsx +11 -0
  155. package/renderer/components/theme-toggle.tsx +76 -0
  156. package/renderer/components/ui/badge.tsx +46 -0
  157. package/renderer/components/ui/button.tsx +59 -0
  158. package/renderer/components/ui/dialog.tsx +118 -0
  159. package/renderer/components/ui/dropdown-menu.tsx +257 -0
  160. package/renderer/components/ui/input.tsx +21 -0
  161. package/renderer/components/ui/label.tsx +24 -0
  162. package/renderer/components/ui/navigation-menu.tsx +168 -0
  163. package/renderer/components/ui/select.tsx +190 -0
  164. package/renderer/components/ui/spinner.tsx +114 -0
  165. package/renderer/components/ui/tabs.tsx +66 -0
  166. package/renderer/components/ui/tooltip.tsx +61 -0
  167. package/renderer/hooks/use-code-copy.ts +88 -0
  168. package/renderer/hooks/use-openapi-title.ts +44 -0
  169. package/renderer/lib/api-docs/agent/index.ts +6 -0
  170. package/renderer/lib/api-docs/agent/indexer.ts +323 -0
  171. package/renderer/lib/api-docs/agent/spec-summary.ts +335 -0
  172. package/renderer/lib/api-docs/agent/types.ts +116 -0
  173. package/renderer/lib/api-docs/auth/auth-context.tsx +225 -0
  174. package/renderer/lib/api-docs/auth/auth-storage.ts +87 -0
  175. package/renderer/lib/api-docs/auth/crypto.ts +89 -0
  176. package/renderer/lib/api-docs/auth/index.ts +4 -0
  177. package/renderer/lib/api-docs/code-editor/db.ts +164 -0
  178. package/renderer/lib/api-docs/code-editor/hooks.ts +266 -0
  179. package/renderer/lib/api-docs/code-editor/index.ts +6 -0
  180. package/renderer/lib/api-docs/code-editor/mode-context.tsx +207 -0
  181. package/renderer/lib/api-docs/code-editor/types.ts +105 -0
  182. package/renderer/lib/api-docs/codegen/definitions.ts +297 -0
  183. package/renderer/lib/api-docs/codegen/har.ts +251 -0
  184. package/renderer/lib/api-docs/codegen/index.ts +159 -0
  185. package/renderer/lib/api-docs/factories.ts +151 -0
  186. package/renderer/lib/api-docs/index.ts +17 -0
  187. package/renderer/lib/api-docs/mobile-context.tsx +112 -0
  188. package/renderer/lib/api-docs/navigation-context.tsx +88 -0
  189. package/renderer/lib/api-docs/parsers/graphql/README.md +129 -0
  190. package/renderer/lib/api-docs/parsers/graphql/index.ts +91 -0
  191. package/renderer/lib/api-docs/parsers/graphql/parser.ts +491 -0
  192. package/renderer/lib/api-docs/parsers/graphql/transformer.ts +246 -0
  193. package/renderer/lib/api-docs/parsers/graphql/types.ts +283 -0
  194. package/renderer/lib/api-docs/parsers/openapi/README.md +32 -0
  195. package/renderer/lib/api-docs/parsers/openapi/dereferencer.ts +60 -0
  196. package/renderer/lib/api-docs/parsers/openapi/extractors/auth.ts +574 -0
  197. package/renderer/lib/api-docs/parsers/openapi/extractors/body.ts +403 -0
  198. package/renderer/lib/api-docs/parsers/openapi/extractors/index.ts +232 -0
  199. package/renderer/lib/api-docs/parsers/openapi/index.ts +171 -0
  200. package/renderer/lib/api-docs/parsers/openapi/transformer.ts +277 -0
  201. package/renderer/lib/api-docs/parsers/openapi/validator.ts +31 -0
  202. package/renderer/lib/api-docs/playground/context.tsx +107 -0
  203. package/renderer/lib/api-docs/playground/navigation-context.tsx +124 -0
  204. package/renderer/lib/api-docs/playground/request-builder.ts +223 -0
  205. package/renderer/lib/api-docs/playground/request-runner.ts +282 -0
  206. package/renderer/lib/api-docs/playground/types.ts +35 -0
  207. package/renderer/lib/api-docs/types.ts +269 -0
  208. package/renderer/lib/api-docs/utils.ts +311 -0
  209. package/renderer/lib/cache.ts +193 -0
  210. package/renderer/lib/docs/config/index.ts +29 -0
  211. package/renderer/lib/docs/config/loader.ts +142 -0
  212. package/renderer/lib/docs/config/schema.ts +298 -0
  213. package/renderer/lib/docs/index.ts +12 -0
  214. package/renderer/lib/docs/mdx/compiler.ts +176 -0
  215. package/renderer/lib/docs/mdx/frontmatter.ts +80 -0
  216. package/renderer/lib/docs/mdx/index.ts +26 -0
  217. package/renderer/lib/docs/navigation/generator.ts +348 -0
  218. package/renderer/lib/docs/navigation/index.ts +12 -0
  219. package/renderer/lib/docs/navigation/types.ts +123 -0
  220. package/renderer/lib/docs-navigation-context.tsx +80 -0
  221. package/renderer/lib/multi-tenant/context.ts +105 -0
  222. package/renderer/lib/storage/blob.ts +845 -0
  223. package/renderer/lib/utils.ts +6 -0
  224. package/renderer/next.config.ts +76 -0
  225. package/renderer/package.json +66 -0
  226. package/renderer/postcss.config.mjs +5 -0
  227. package/renderer/public/assets/images/screenshot.png +0 -0
  228. package/renderer/public/assets/logo/dark.svg +9 -0
  229. package/renderer/public/assets/logo/light.svg +9 -0
  230. package/renderer/public/assets/logo.svg +9 -0
  231. package/renderer/public/file.svg +1 -0
  232. package/renderer/public/globe.svg +1 -0
  233. package/renderer/public/icon.png +0 -0
  234. package/renderer/public/logo.svg +9 -0
  235. package/renderer/public/window.svg +1 -0
  236. package/renderer/tsconfig.json +28 -0
  237. package/templates/basic/README.md +139 -0
  238. package/templates/basic/assets/favicon.svg +4 -0
  239. package/templates/basic/assets/logo.svg +9 -0
  240. package/templates/basic/docs.json +47 -0
  241. package/templates/basic/guides/configuration.mdx +149 -0
  242. package/templates/basic/guides/overview.mdx +96 -0
  243. package/templates/basic/index.mdx +39 -0
  244. package/templates/basic/package.json +14 -0
  245. package/templates/basic/quickstart.mdx +92 -0
  246. package/templates/basic/vercel.json +6 -0
  247. package/templates/graphql/README.md +139 -0
  248. package/templates/graphql/api-reference/schema.graphql +305 -0
  249. package/templates/graphql/assets/favicon.svg +4 -0
  250. package/templates/graphql/assets/logo.svg +9 -0
  251. package/templates/graphql/docs.json +54 -0
  252. package/templates/graphql/guides/configuration.mdx +149 -0
  253. package/templates/graphql/guides/overview.mdx +96 -0
  254. package/templates/graphql/index.mdx +39 -0
  255. package/templates/graphql/package.json +14 -0
  256. package/templates/graphql/quickstart.mdx +92 -0
  257. package/templates/graphql/vercel.json +6 -0
  258. package/templates/openapi/README.md +139 -0
  259. package/templates/openapi/api-reference/openapi.json +419 -0
  260. package/templates/openapi/assets/favicon.svg +4 -0
  261. package/templates/openapi/assets/logo.svg +9 -0
  262. package/templates/openapi/docs.json +61 -0
  263. package/templates/openapi/guides/configuration.mdx +149 -0
  264. package/templates/openapi/guides/overview.mdx +96 -0
  265. package/templates/openapi/index.mdx +39 -0
  266. package/templates/openapi/package.json +14 -0
  267. package/templates/openapi/quickstart.mdx +92 -0
  268. 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
+ }