@stainless-api/docs 0.1.0-beta.98 → 1.0.0-beta.140

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 (138) hide show
  1. package/CHANGELOG.md +404 -0
  2. package/ambient.d.ts +6 -0
  3. package/eslint-suppressions.json +22 -6
  4. package/{eslint.config.js → eslint.config.ts} +1 -7
  5. package/package.json +57 -40
  6. package/plugin/assets/languages/php.svg +4 -0
  7. package/plugin/buildAlgoliaIndex.ts +6 -12
  8. package/plugin/components/SDKSelect.astro +0 -6
  9. package/plugin/components/SnippetCode.tsx +6 -37
  10. package/plugin/components/search/SearchAlgolia.astro +1 -1
  11. package/plugin/components/search/SearchIsland.tsx +19 -13
  12. package/plugin/generateAPIReferenceLink.ts +0 -40
  13. package/plugin/globalJs/ai-dropdown-options.ts +26 -13
  14. package/plugin/globalJs/code-snippets.ts +5 -5
  15. package/plugin/globalJs/copy.ts +20 -91
  16. package/plugin/globalJs/navigation.ts +13 -13
  17. package/plugin/globalJs/summary-selection-tweak.ts +29 -0
  18. package/plugin/index.ts +107 -163
  19. package/plugin/languages.ts +2 -1
  20. package/plugin/loadPluginConfig.ts +50 -153
  21. package/plugin/markdown/highlighter.ts +100 -0
  22. package/plugin/markdown/index.ts +39 -0
  23. package/plugin/middlewareBuilder/stainlessMiddleware.d.ts +2 -0
  24. package/plugin/react/Routing.tsx +10 -244
  25. package/plugin/referencePlaceholderUtils.ts +1 -1
  26. package/plugin/replaceSidebarPlaceholderMiddleware.ts +1 -1
  27. package/plugin/routes/Docs.astro +3 -1
  28. package/plugin/routes/Overview.astro +14 -7
  29. package/plugin/routes/llms.ts +186 -0
  30. package/plugin/routes/markdown.ts +62 -13
  31. package/plugin/sidebar-utils/sidebar-builder.ts +38 -12
  32. package/plugin/specs/defaultSpecLoader.ts +192 -0
  33. package/plugin/specs/fetchSpecSSR.ts +1 -1
  34. package/plugin/specs/utils.ts +86 -0
  35. package/shared/conditionalIntegration.ts +28 -0
  36. package/shared/getProsePages.ts +6 -7
  37. package/shared/virtualModule.ts +1 -26
  38. package/stl-docs/aiChatExamples.ts +31 -0
  39. package/stl-docs/chat/docs-chat-handler.ts +17 -0
  40. package/stl-docs/chat/hook.ts +225 -0
  41. package/stl-docs/chat/schemas.ts +27 -0
  42. package/stl-docs/chat/ui/AiChat.module.css +591 -0
  43. package/stl-docs/chat/ui/AiChat.tsx +175 -0
  44. package/stl-docs/chat/ui/Trigger.tsx +154 -0
  45. package/stl-docs/chat/ui/components/ChatControls.tsx +51 -0
  46. package/stl-docs/chat/ui/components/ChatEmpty.tsx +42 -0
  47. package/stl-docs/chat/ui/components/ChatLog.tsx +93 -0
  48. package/stl-docs/chat/ui/components/ChatMessage.tsx +47 -0
  49. package/stl-docs/chat/ui/components/CodeBlock.tsx +33 -0
  50. package/stl-docs/chat/ui/components/MessageFeedback.tsx +106 -0
  51. package/stl-docs/chat/ui/components/Table.tsx +15 -0
  52. package/stl-docs/chat/ui/components/ToolCall.tsx +34 -0
  53. package/stl-docs/chat/ui/components/hljs-github.css +81 -0
  54. package/stl-docs/chat/ui/scroll-manager.ts +86 -0
  55. package/stl-docs/chat/ui/types.ts +45 -0
  56. package/stl-docs/components/AiChatIsland.tsx +10 -12
  57. package/stl-docs/components/ContentPanel.astro +9 -0
  58. package/stl-docs/components/Footer.astro +89 -0
  59. package/stl-docs/components/Header.astro +0 -5
  60. package/stl-docs/components/PageFrame.astro +23 -8
  61. package/stl-docs/components/PageSidebar.astro +11 -0
  62. package/stl-docs/components/StainlessLogo.svg +4 -0
  63. package/stl-docs/components/TwoColumnContent.astro +2 -0
  64. package/stl-docs/components/headers/DefaultHeader.astro +6 -8
  65. package/stl-docs/components/headers/StackedHeader.astro +5 -53
  66. package/stl-docs/components/mintlify-compat/Accordion.astro +2 -2
  67. package/stl-docs/components/mintlify-compat/AccordionGroup.astro +0 -4
  68. package/stl-docs/components/mintlify-compat/Columns.astro +2 -2
  69. package/stl-docs/components/mintlify-compat/Frame.astro +2 -2
  70. package/stl-docs/components/mintlify-compat/Tab.astro +2 -2
  71. package/stl-docs/components/mintlify-compat/callouts/Callout.astro +2 -2
  72. package/stl-docs/components/mintlify-compat/callouts/Check.astro +0 -4
  73. package/stl-docs/components/mintlify-compat/callouts/Danger.astro +0 -4
  74. package/stl-docs/components/mintlify-compat/callouts/Info.astro +0 -4
  75. package/stl-docs/components/mintlify-compat/callouts/Note.astro +0 -4
  76. package/stl-docs/components/mintlify-compat/callouts/Tip.astro +0 -4
  77. package/stl-docs/components/mintlify-compat/callouts/Warning.astro +0 -4
  78. package/stl-docs/components/nav-tabs/NavDropdown.astro +12 -7
  79. package/stl-docs/components/nav-tabs/NavTabs.astro +5 -3
  80. package/stl-docs/components/nav-tabs/buildNavLinks.ts +2 -0
  81. package/stl-docs/components/pagination/Pagination.astro +4 -2
  82. package/stl-docs/components/pagination/PaginationLinkEmphasized.astro +2 -2
  83. package/stl-docs/components/pagination/PaginationLinkQuiet.astro +2 -2
  84. package/stl-docs/components/pagination/util.ts +3 -3
  85. package/stl-docs/components/sidebars/BaseSidebar.astro +72 -1
  86. package/stl-docs/disableCalloutSyntax.ts +1 -1
  87. package/stl-docs/fonts.ts +5 -5
  88. package/stl-docs/index.ts +76 -53
  89. package/stl-docs/loadStlDocsConfig.ts +38 -8
  90. package/stl-docs/og-image/components/OpenGraphFunctionSignature.tsx +64 -0
  91. package/stl-docs/og-image/components/OpenGraphImage.tsx +126 -0
  92. package/stl-docs/og-image/config.ts +56 -0
  93. package/stl-docs/og-image/image-gen/generate-api-reference-og-image.tsx +188 -0
  94. package/stl-docs/og-image/image-gen/generate-og-image.tsx +119 -0
  95. package/stl-docs/og-image/image-gen/get-logo-url.ts +47 -0
  96. package/stl-docs/og-image/index.ts +135 -0
  97. package/stl-docs/og-image/routes/add-og-image.ts +45 -0
  98. package/stl-docs/og-image/routes/get-api-reference-og-image.ts +36 -0
  99. package/stl-docs/og-image/routes/get-og-image.ts +28 -0
  100. package/stl-docs/og-image/theme.ts +43 -0
  101. package/stl-docs/og-image/utils.ts +14 -0
  102. package/stl-docs/proseDocSync.test.ts +74 -0
  103. package/stl-docs/proseDocSync.ts +344 -0
  104. package/stl-docs/proseMarkdown/proseMarkdownIntegration.ts +4 -12
  105. package/stl-docs/schema-extension.ts +12 -0
  106. package/stl-docs/tabsMiddleware.ts +1 -1
  107. package/styles/overrides.css +2 -14
  108. package/styles/page.css +210 -71
  109. package/styles/sidebar.css +30 -17
  110. package/styles/sl-variables.css +3 -8
  111. package/styles/stldocs-variables.css +2 -2
  112. package/styles/toc.css +8 -0
  113. package/tsconfig.json +1 -1
  114. package/virtual-module.d.ts +35 -11
  115. package/playground-virtual-modules.d.ts +0 -96
  116. package/plugin/globalJs/create-playground.shim.ts +0 -3
  117. package/plugin/globalJs/playground-data.shim.ts +0 -1
  118. package/plugin/globalJs/playground-data.ts +0 -14
  119. package/plugin/specs/FileCache.ts +0 -99
  120. package/plugin/specs/generateSpec.ts +0 -112
  121. package/plugin/specs/index.ts +0 -132
  122. package/plugin/specs/inputResolver.ts +0 -146
  123. package/plugin/specs/worker.ts +0 -199
  124. package/plugin/vendor/preview.worker.docs.js +0 -26108
  125. package/plugin/vendor/templates/cli.md +0 -1
  126. package/plugin/vendor/templates/go.md +0 -316
  127. package/plugin/vendor/templates/java.md +0 -89
  128. package/plugin/vendor/templates/kotlin.md +0 -89
  129. package/plugin/vendor/templates/node.md +0 -235
  130. package/plugin/vendor/templates/python.md +0 -251
  131. package/plugin/vendor/templates/ruby.md +0 -147
  132. package/plugin/vendor/templates/terraform.md +0 -60
  133. package/plugin/vendor/templates/typescript.md +0 -319
  134. package/scripts/vendor_deps.ts +0 -50
  135. package/stl-docs/components/ClientRouterHead.astro +0 -41
  136. package/stl-docs/components/content-panel/ContentPanel.astro +0 -42
  137. package/stl-docs/components/headers/SplashMobileMenuToggle.astro +0 -65
  138. package/stl-docs/proseSearchIndexing.ts +0 -606
@@ -0,0 +1,225 @@
1
+ import type { AssistantTextMessage, AssistantToolCallMessage, ChatMessage, UserMessage } from './ui/types';
2
+ import { useCallback, useEffect, useReducer, useRef } from 'react';
3
+ import type { ResponseChunk } from './schemas';
4
+ import { DocsChatHandler } from './docs-chat-handler';
5
+
6
+ //
7
+ // Reducer
8
+ //
9
+
10
+ /**
11
+ * Splice a new assistant message into a ChatMessage[] stream based on its respondingTo property.
12
+ *
13
+ * if two responses are streaming at once, we want to put all the responses to user Message A
14
+ * before user message B
15
+ */
16
+ function spliceNewMessage(messages: ChatMessage[], newMessage: Extract<ChatMessage, { role: 'assistant' }>) {
17
+ // find the most recent assistant message that's responding to the same user message as we are
18
+ let insertAfterIdx = messages.findLastIndex(
19
+ (msg) =>
20
+ (msg.role === 'assistant' && msg.respondingTo === newMessage.respondingTo) ||
21
+ // if this is the first assistant message responding to this user message
22
+ (msg.role === 'user' && msg.id === newMessage.respondingTo),
23
+ );
24
+ insertAfterIdx = insertAfterIdx === -1 ? messages.length - 1 : insertAfterIdx;
25
+ return messages.toSpliced(insertAfterIdx + 1, 0, newMessage);
26
+ }
27
+
28
+ type ChatReducerAction =
29
+ | { type: 'addUserMessage'; content: UserMessage['content']; id: string }
30
+ | { type: 'beginAssistantMessage'; message: Omit<AssistantTextMessage, 'role' | 'isComplete'> }
31
+ | { type: 'streamMessage'; id: string; newContent: string }
32
+ | { type: 'completeMessage'; id: string }
33
+ | { type: 'addAssistantToolCall'; message: Omit<AssistantToolCallMessage, 'role' | 'id'> }
34
+ // a response potentially contains multiple messages / tool calls
35
+ | { type: 'completeResponse'; respondingTo: UserMessage['id']; spanId: string }
36
+ | { type: 'addError'; respondingTo: UserMessage['id']; errorMessage: string };
37
+
38
+ function chatReducer(state: ChatMessage[], action: ChatReducerAction) {
39
+ if (action.type === 'addUserMessage') {
40
+ return [...state, { role: 'user', content: action.content, id: action.id } satisfies ChatMessage];
41
+ }
42
+
43
+ if (action.type === 'beginAssistantMessage') {
44
+ return spliceNewMessage(state, {
45
+ role: 'assistant',
46
+ id: action.message.id,
47
+ respondingTo: action.message.respondingTo,
48
+ messageType: action.message.messageType satisfies 'text',
49
+ content: action.message.content,
50
+ isComplete: false,
51
+ });
52
+ }
53
+
54
+ if (action.type === 'streamMessage') {
55
+ return state.map((msg) =>
56
+ msg.id === action.id && 'content' in msg
57
+ ? ({ ...msg, content: `${msg.content}${action.newContent}` } satisfies ChatMessage)
58
+ : msg,
59
+ );
60
+ }
61
+
62
+ if (action.type === 'completeMessage') {
63
+ return state.map((msg) =>
64
+ msg.id === action.id && msg.role === 'assistant' && msg.messageType === 'text'
65
+ ? ({ ...msg, isComplete: true } satisfies ChatMessage)
66
+ : msg,
67
+ );
68
+ }
69
+
70
+ if (action.type === 'addAssistantToolCall') {
71
+ return spliceNewMessage(state, {
72
+ role: 'assistant',
73
+ id: crypto.randomUUID(),
74
+ messageType: action.message.messageType satisfies 'tool_use',
75
+ respondingTo: action.message.respondingTo,
76
+ toolName: action.message.toolName,
77
+ input: action.message.input,
78
+ });
79
+ }
80
+
81
+ if (action.type === 'completeResponse') {
82
+ return spliceNewMessage(state, {
83
+ role: 'assistant',
84
+ id: crypto.randomUUID(),
85
+ messageType: 'done',
86
+ respondingTo: action.respondingTo,
87
+ spanId: action.spanId,
88
+ } satisfies Extract<ChatMessage, { role: 'assistant' }>);
89
+ }
90
+
91
+ if (action.type === 'addError') {
92
+ return spliceNewMessage(state, {
93
+ role: 'assistant',
94
+ id: crypto.randomUUID(),
95
+ messageType: 'error',
96
+ respondingTo: action.respondingTo,
97
+ errorMessage: action.errorMessage,
98
+ });
99
+ }
100
+
101
+ return state;
102
+ }
103
+
104
+ //
105
+ // Consumable hook
106
+ //
107
+
108
+ export function useChat({ handler }: { handler: DocsChatHandler }) {
109
+ // Used to clean up stray streaming requests on unmount (prevent setState on unmounted component)
110
+ const abortControllerRef = useRef(new AbortController());
111
+ useEffect(() => {
112
+ abortControllerRef.current = abortControllerRef.current.signal.aborted
113
+ ? new AbortController()
114
+ : abortControllerRef.current;
115
+ const ac = abortControllerRef.current;
116
+ return () => ac.abort('Component unmounted');
117
+ }, []);
118
+
119
+ const [chatMessages, dispatch] = useReducer(chatReducer, []);
120
+
121
+ /** Send a message and stream back the response in chat */
122
+ const sendMessage = useCallback(
123
+ async (question: string) => {
124
+ const userMessageId = crypto.randomUUID();
125
+ dispatch({ type: 'addUserMessage', content: question, id: userMessageId });
126
+
127
+ let currentResponseId = crypto.randomUUID(); // for streaming text messages
128
+ let lastChunkType: ResponseChunk['type'] | undefined = undefined;
129
+
130
+ try {
131
+ let chunk: ResponseChunk | undefined = undefined;
132
+ let sawDone = false;
133
+ for await (chunk of handler.generateResponse(
134
+ {
135
+ query: question,
136
+ priorMessages: chatMessages.filter(
137
+ (msg) => msg.role === 'user' || (msg.role === 'assistant' && msg.messageType === 'text'),
138
+ ),
139
+ },
140
+ abortControllerRef.current.signal,
141
+ )) {
142
+ if (abortControllerRef.current.signal.aborted) break;
143
+
144
+ // mark complete when text messages finish streaming
145
+ if (lastChunkType === 'text' && chunk.type !== 'text') {
146
+ dispatch({ type: 'completeMessage', id: currentResponseId });
147
+ }
148
+
149
+ if (chunk.type === 'done') {
150
+ dispatch({ type: 'completeResponse', respondingTo: userMessageId, spanId: chunk.span_id });
151
+ sawDone = true;
152
+ // stop reading from the stream on done
153
+ break;
154
+ }
155
+
156
+ if (chunk.type === 'text') {
157
+ if (lastChunkType !== 'text') {
158
+ // start a new text message
159
+ currentResponseId = crypto.randomUUID();
160
+ dispatch({
161
+ type: 'beginAssistantMessage',
162
+ message: {
163
+ content: chunk.text,
164
+ id: currentResponseId,
165
+ messageType: chunk.type,
166
+ respondingTo: userMessageId,
167
+ },
168
+ });
169
+ } else {
170
+ // continue the current message with the new content
171
+ dispatch({ type: 'streamMessage', id: currentResponseId, newContent: chunk.text });
172
+ }
173
+ }
174
+
175
+ if (chunk.type === 'tool_use') {
176
+ dispatch({
177
+ type: 'addAssistantToolCall',
178
+ message: {
179
+ respondingTo: userMessageId,
180
+ messageType: chunk.type,
181
+ toolName: chunk.name,
182
+ input: chunk.input,
183
+ },
184
+ });
185
+ }
186
+
187
+ lastChunkType = chunk.type;
188
+ }
189
+ if (!chunk || lastChunkType === 'start_session') {
190
+ dispatch({
191
+ type: 'addError',
192
+ respondingTo: userMessageId,
193
+ errorMessage: 'No response received. Please try again.',
194
+ });
195
+ } else if (!sawDone && !abortControllerRef.current.signal.aborted) {
196
+ // Generator exhausted without a `done` chunk — synthesize completion.
197
+ if (lastChunkType === 'text') {
198
+ dispatch({ type: 'completeMessage', id: currentResponseId });
199
+ }
200
+ dispatch({ type: 'completeResponse', respondingTo: userMessageId, spanId: crypto.randomUUID() });
201
+ }
202
+ } catch {
203
+ dispatch({
204
+ type: 'addError',
205
+ respondingTo: userMessageId,
206
+ errorMessage: 'Something went wrong. Please try again.',
207
+ });
208
+ }
209
+ },
210
+ [chatMessages, handler],
211
+ );
212
+
213
+ const rateMessage = handler.onRate
214
+ ? async (spanId: string, rating: 'up' | 'down') => {
215
+ try {
216
+ await handler.onRate?.(spanId, { up: 1 as const, down: 0 as const }[rating]);
217
+ return true;
218
+ } catch {
219
+ return false;
220
+ }
221
+ }
222
+ : undefined;
223
+
224
+ return { chatMessages, sendMessage, rateMessage };
225
+ }
@@ -0,0 +1,27 @@
1
+ import z from 'zod';
2
+
3
+ export const responseChunk = z.discriminatedUnion('type', [
4
+ z.object({
5
+ type: z.literal('text'),
6
+ text: z.string(),
7
+ }),
8
+ z.object({
9
+ type: z.literal('tool_use'),
10
+ name: z.string(),
11
+ input: z.record(z.string(), z.unknown()).optional(),
12
+ }),
13
+ z.object({
14
+ type: z.literal('tool_result'),
15
+ tool_use_id: z.string(),
16
+ content: z.string(),
17
+ }),
18
+ z.object({
19
+ type: z.literal('done'),
20
+ span_id: z.string(),
21
+ }),
22
+ z.object({
23
+ type: z.literal('start_session'),
24
+ session_id: z.string(),
25
+ }),
26
+ ]);
27
+ export type ResponseChunk = z.infer<typeof responseChunk>;