@stainless-api/docs 0.1.0-beta.121 → 0.1.0-beta.123
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 +16 -0
- package/package.json +1 -1
- package/plugin/vendor/preview.worker.docs.js +5672 -5616
- package/stl-docs/aiChatExamples.ts +95 -0
- package/stl-docs/index.ts +14 -5
- 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
|
@@ -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,7 +169,8 @@ 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) {
|
|
@@ -177,9 +179,7 @@ function stainlessDocsIntegration(
|
|
|
177
179
|
|
|
178
180
|
const base = astroConfig.base ?? '/';
|
|
179
181
|
const withBase = (link: string) =>
|
|
180
|
-
[
|
|
181
|
-
? link
|
|
182
|
-
: path.posix.join(base, link);
|
|
182
|
+
/^([a-z][a-z0-9+.-]*:|\/\/)/.test(link) ? link : path.posix.join(base, link);
|
|
183
183
|
|
|
184
184
|
const virtualModules = new Map(
|
|
185
185
|
Object.entries({
|
|
@@ -224,6 +224,15 @@ function stainlessDocsIntegration(
|
|
|
224
224
|
if (virtualModules.has(bare)) return virtualModules.get(bare);
|
|
225
225
|
},
|
|
226
226
|
},
|
|
227
|
+
...(config.aiChat
|
|
228
|
+
? [
|
|
229
|
+
await generateExamplesPlugin({
|
|
230
|
+
projectName: config.apiReference?.stainlessProject ?? undefined,
|
|
231
|
+
logger,
|
|
232
|
+
exampleOverrides: config.aiChat?.exampleOverrides,
|
|
233
|
+
}),
|
|
234
|
+
]
|
|
235
|
+
: []),
|
|
227
236
|
],
|
|
228
237
|
optimizeDeps: {
|
|
229
238
|
include: config.aiChat
|
|
@@ -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
|
|