@stainless-api/docs 0.1.0-beta.120 → 0.1.0-beta.122
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/CHANGELOG.md +24 -0
- package/package.json +5 -5
- package/plugin/components/search/SearchIsland.tsx +14 -13
- package/plugin/vendor/preview.worker.docs.js +5672 -5616
- package/stl-docs/aiChatExamples.ts +95 -0
- package/stl-docs/index.ts +24 -7
- package/stl-docs/loadStlDocsConfig.ts +5 -1
- package/virtual-module.d.ts +10 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { AstroIntegrationLogger } from 'astro';
|
|
2
|
+
import z from 'zod';
|
|
3
|
+
import {
|
|
4
|
+
buildVirtualModuleString,
|
|
5
|
+
makeAsyncVirtualModPlugin,
|
|
6
|
+
makeVirtualModPlugin,
|
|
7
|
+
} from '../shared/virtualModule';
|
|
8
|
+
import type * as virtualExampleModule from 'virtual:stl-docs-ai-chat-examples';
|
|
9
|
+
type VirtualExampleModule = typeof virtualExampleModule;
|
|
10
|
+
|
|
11
|
+
const exampleSchema = z.array(
|
|
12
|
+
z.object({
|
|
13
|
+
shortPrompt: z.string(),
|
|
14
|
+
longPrompt: z.string(),
|
|
15
|
+
icon: z.string(),
|
|
16
|
+
}),
|
|
17
|
+
);
|
|
18
|
+
export type ExamplePromptResponse = z.infer<typeof exampleSchema>;
|
|
19
|
+
|
|
20
|
+
// handles actually retrieving the information via the Stainless API
|
|
21
|
+
async function loadExamples(
|
|
22
|
+
projectName: string,
|
|
23
|
+
logger: AstroIntegrationLogger,
|
|
24
|
+
): Promise<ExamplePromptResponse | undefined> {
|
|
25
|
+
try {
|
|
26
|
+
const response = await fetch(`https://api.stainless.com/api/ai/steelie-examples/${projectName}`, {
|
|
27
|
+
method: 'GET',
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const text = await response.text();
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
logger.error(`failed to fetch AI chat examples: ${text}`);
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
const examples = exampleSchema.parse(JSON.parse(text));
|
|
36
|
+
return examples;
|
|
37
|
+
} catch (error) {
|
|
38
|
+
if (error instanceof Error) logger.error(`failed to fetch AI chat examples: ${error.message}`);
|
|
39
|
+
else throw error;
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export default async function generateExamplesPlugin({
|
|
45
|
+
projectName,
|
|
46
|
+
logger,
|
|
47
|
+
exampleOverrides,
|
|
48
|
+
}: {
|
|
49
|
+
projectName: string | undefined;
|
|
50
|
+
logger: AstroIntegrationLogger;
|
|
51
|
+
exampleOverrides?: ExamplePromptResponse;
|
|
52
|
+
}) {
|
|
53
|
+
// if the user has specified any examples, return those immediately
|
|
54
|
+
// instead of loading them via the web.
|
|
55
|
+
if (exampleOverrides) {
|
|
56
|
+
return makeVirtualModPlugin(
|
|
57
|
+
'virtual:stl-docs-ai-chat-examples',
|
|
58
|
+
generateVirtualModuleString(exampleOverrides),
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
// if we don't have a defined project name, don't try to fetch examples
|
|
62
|
+
if (!projectName) {
|
|
63
|
+
return makeVirtualModPlugin(
|
|
64
|
+
'virtual:stl-docs-ai-chat-examples',
|
|
65
|
+
buildVirtualModuleString({ examples: undefined } satisfies VirtualExampleModule),
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// otherwise, promise to get the right examples at some point later on
|
|
70
|
+
const examplesPromise = loadExamples(projectName, logger);
|
|
71
|
+
return makeAsyncVirtualModPlugin<VirtualExampleModule>('virtual:stl-docs-ai-chat-examples', async () => {
|
|
72
|
+
const examples = await examplesPromise;
|
|
73
|
+
return generateVirtualModuleString(examples);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function generateVirtualModuleString(examples: ExamplePromptResponse | undefined) {
|
|
78
|
+
if (!examples) return 'export const examples = undefined;';
|
|
79
|
+
|
|
80
|
+
// Generate icon imports
|
|
81
|
+
// prettier-ignore
|
|
82
|
+
const pascalToKebab = (str: string) => str.split(/(?=[A-Z])/).join('-').toLowerCase();
|
|
83
|
+
const iconImportPath = (iconName: string) =>
|
|
84
|
+
import.meta.resolve(`lucide-react/dist/esm/icons/${pascalToKebab(iconName)}.js`);
|
|
85
|
+
const iconImports = examples.map(
|
|
86
|
+
({ icon }) => `import ${icon} from ${JSON.stringify(iconImportPath(icon))}`,
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
// Reference icon imports in `examples` exported object
|
|
90
|
+
// "icon":"Sparkles" -> "icon":Sparkles
|
|
91
|
+
const iconStringsToIdents = (jsonBlob: string) => jsonBlob.replace(/"icon":\s*"(\w+)"/g, '"icon":$1');
|
|
92
|
+
const exportBody = `export const examples = ${iconStringsToIdents(JSON.stringify(examples))};`;
|
|
93
|
+
|
|
94
|
+
return [...iconImports, exportBody].join('\n');
|
|
95
|
+
}
|
package/stl-docs/index.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { disableCalloutSyntaxStarlightPlugin } from './disableCalloutSyntax';
|
|
|
6
6
|
import type { AstroIntegration } from 'astro';
|
|
7
7
|
|
|
8
8
|
import { normalizeRedirects, type NormalizedRedirectConfig } from './redirects';
|
|
9
|
-
import
|
|
9
|
+
import path from 'node:path';
|
|
10
10
|
import { mkdirSync, writeFileSync } from 'fs';
|
|
11
11
|
import {
|
|
12
12
|
parseStlDocsConfig,
|
|
@@ -20,12 +20,13 @@ import { buildVirtualModuleString } from '../shared/virtualModule';
|
|
|
20
20
|
import type * as StlDocsVirtualModule from 'virtual:stl-docs-virtual-module';
|
|
21
21
|
import { resolveSrcFile } from '../resolveSrcFile';
|
|
22
22
|
import { stainlessDocsMarkdownRenderer } from './proseMarkdown/proseMarkdownIntegration';
|
|
23
|
-
import { setSharedLogger } from '../shared/getSharedLogger';
|
|
23
|
+
import { getSharedLogger, setSharedLogger } from '../shared/getSharedLogger';
|
|
24
24
|
import { stainlessDocsVectorProseIndexing } from './proseDocSync';
|
|
25
25
|
import { stainlessDocsAlgoliaProseIndexing } from './proseSearchIndexing';
|
|
26
26
|
import { stainlessStarlight } from '../plugin';
|
|
27
27
|
import { getFontRoles, flattenFonts } from './fonts';
|
|
28
28
|
import conditionalIntegration from '../shared/conditionalIntegration';
|
|
29
|
+
import generateExamplesPlugin from './aiChatExamples';
|
|
29
30
|
|
|
30
31
|
export * from '../plugin';
|
|
31
32
|
|
|
@@ -168,19 +169,26 @@ function stainlessDocsIntegration(
|
|
|
168
169
|
return {
|
|
169
170
|
name: 'stl-docs-astro',
|
|
170
171
|
hooks: {
|
|
171
|
-
'astro:config:setup': ({ updateConfig, command, config: astroConfig }) => {
|
|
172
|
+
'astro:config:setup': async ({ updateConfig, command, config: astroConfig, logger: localLogger }) => {
|
|
173
|
+
const logger = getSharedLogger({ fallback: localLogger });
|
|
172
174
|
// we only handle redirects for builds
|
|
173
175
|
// in dev, Astro handles them for us
|
|
174
176
|
if (command === 'build' && astroConfig.redirects) {
|
|
175
177
|
redirects = normalizeRedirects(astroConfig.redirects);
|
|
176
178
|
}
|
|
177
179
|
|
|
180
|
+
const base = astroConfig.base ?? '/';
|
|
181
|
+
const withBase = (link: string) =>
|
|
182
|
+
['http://', 'https://', '//'].some((prefix) => link.startsWith(prefix))
|
|
183
|
+
? link
|
|
184
|
+
: path.posix.join(base, link);
|
|
185
|
+
|
|
178
186
|
const virtualModules = new Map(
|
|
179
187
|
Object.entries({
|
|
180
188
|
'virtual:stl-docs-virtual-module': buildVirtualModuleString({
|
|
181
|
-
TABS: config.tabs,
|
|
189
|
+
TABS: config.tabs.map((tab) => ({ ...tab, link: withBase(tab.link) })),
|
|
182
190
|
SPLIT_TABS_ENABLED: config.splitTabsEnabled,
|
|
183
|
-
HEADER_LINKS: config.header.links,
|
|
191
|
+
HEADER_LINKS: config.header.links.map((link) => ({ ...link, link: withBase(link.link) })),
|
|
184
192
|
HEADER_LAYOUT: config.header.layout,
|
|
185
193
|
ENABLE_CLIENT_ROUTER: config.enableClientRouter,
|
|
186
194
|
API_REFERENCE_BASE_PATH: apiReferenceBasePath ?? '/api',
|
|
@@ -218,6 +226,15 @@ function stainlessDocsIntegration(
|
|
|
218
226
|
if (virtualModules.has(bare)) return virtualModules.get(bare);
|
|
219
227
|
},
|
|
220
228
|
},
|
|
229
|
+
...(config.aiChat
|
|
230
|
+
? [
|
|
231
|
+
await generateExamplesPlugin({
|
|
232
|
+
projectName: config.apiReference?.stainlessProject ?? undefined,
|
|
233
|
+
logger,
|
|
234
|
+
exampleOverrides: config.aiChat?.exampleOverrides,
|
|
235
|
+
}),
|
|
236
|
+
]
|
|
237
|
+
: []),
|
|
221
238
|
],
|
|
222
239
|
optimizeDeps: {
|
|
223
240
|
include: config.aiChat
|
|
@@ -240,9 +257,9 @@ function stainlessDocsIntegration(
|
|
|
240
257
|
},
|
|
241
258
|
'astro:build:done': ({ dir }) => {
|
|
242
259
|
if (redirects !== null) {
|
|
243
|
-
const stainlessDir = join(dir.pathname, '_stainless');
|
|
260
|
+
const stainlessDir = path.join(dir.pathname, '_stainless');
|
|
244
261
|
mkdirSync(stainlessDir, { recursive: true });
|
|
245
|
-
const outputPath = join(stainlessDir, 'redirects.json');
|
|
262
|
+
const outputPath = path.join(stainlessDir, 'redirects.json');
|
|
246
263
|
writeFileSync(outputPath, JSON.stringify(redirects, null, 2), {
|
|
247
264
|
encoding: 'utf-8',
|
|
248
265
|
});
|
|
@@ -4,6 +4,7 @@ import type { ButtonVariant } from '@stainless-api/ui-primitives';
|
|
|
4
4
|
import type { AnchorHTMLAttributes } from 'react';
|
|
5
5
|
import type starlight from '@astrojs/starlight';
|
|
6
6
|
import { normalizeFonts, type StlDocsFontConfig } from './fonts';
|
|
7
|
+
import type { ExamplePromptResponse } from './aiChatExamples';
|
|
7
8
|
|
|
8
9
|
type StarlightConfig = Parameters<typeof starlight>[0];
|
|
9
10
|
|
|
@@ -79,7 +80,10 @@ export type StainlessDocsUserConfig = {
|
|
|
79
80
|
*/
|
|
80
81
|
disableProseMarkdownRendering?: boolean;
|
|
81
82
|
disableStainlessProseIndexing?: boolean;
|
|
82
|
-
aiChat?: {
|
|
83
|
+
aiChat?: {
|
|
84
|
+
chatComponentPath: string;
|
|
85
|
+
exampleOverrides?: ExamplePromptResponse;
|
|
86
|
+
};
|
|
83
87
|
/**
|
|
84
88
|
* Whether to link group titles to overview pages. Note: overview pages must already be present in the sidebar for this to work.
|
|
85
89
|
*
|
package/virtual-module.d.ts
CHANGED
|
@@ -75,6 +75,16 @@ declare module 'virtual:stl-docs/components/AiChat.tsx' {
|
|
|
75
75
|
export const STAINLESS_PROJECT: string | undefined;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
declare module 'virtual:stl-docs-ai-chat-examples' {
|
|
79
|
+
export type ExamplePrompt = {
|
|
80
|
+
longPrompt: string;
|
|
81
|
+
shortPrompt: string;
|
|
82
|
+
icon: React.ComponentType;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export const examples: ExamplePrompt[] | undefined;
|
|
86
|
+
}
|
|
87
|
+
|
|
78
88
|
declare module 'virtual:stainless-apis-manifest' {
|
|
79
89
|
import type { DocsLanguage } from '@stainless-api/docs-ui/routing';
|
|
80
90
|
|