@inferencesh/ui 0.0.0-stage → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +68 -2
- package/components.json +22 -0
- package/package.json +231 -4
- package/src/components/audio-player.tsx +549 -0
- package/src/components/button.tsx +13 -0
- package/src/components/chart.tsx +403 -0
- package/src/components/circuit.tsx +276 -0
- package/src/components/code-block/code-block.tsx +260 -0
- package/src/components/code-block/index.ts +18 -0
- package/src/components/code-block/languages.ts +311 -0
- package/src/components/code-block/styles.ts +39 -0
- package/src/components/code-block/tokenizer.ts +290 -0
- package/src/components/code-block/types.ts +38 -0
- package/src/components/code-block/utils.ts +39 -0
- package/src/components/code.tsx +48 -0
- package/src/components/cookie-consent.tsx +137 -0
- package/src/components/copy-button.tsx +44 -0
- package/src/components/country-dropdown.tsx +188 -0
- package/src/components/glow-loader-fast.tsx +32 -0
- package/src/components/glow-loader-mono.tsx +33 -0
- package/src/components/glow-loader-sm-fast.tsx +32 -0
- package/src/components/glow-loader-sm-mono.tsx +34 -0
- package/src/components/glow-loader-sm.tsx +32 -0
- package/src/components/glow-loader.tsx +32 -0
- package/src/components/glow-logo.tsx +32 -0
- package/src/components/gradient.tsx +80 -0
- package/src/components/index.ts +45 -0
- package/src/components/inline-sidebar.tsx +351 -0
- package/src/components/input-color.tsx +349 -0
- package/src/components/logo-base.tsx +213 -0
- package/src/components/logo-color.tsx +23 -0
- package/src/components/logo-full.tsx +71 -0
- package/src/components/logo-svg.tsx +23 -0
- package/src/components/menu-navigation.tsx +359 -0
- package/src/components/multi-select.tsx +721 -0
- package/src/components/pastel-gradient.tsx +25 -0
- package/src/components/pixel-symmetry.tsx +151 -0
- package/src/components/progress.tsx +28 -0
- package/src/components/scroll-more.tsx +131 -0
- package/src/components/select.tsx +85 -0
- package/src/components/shimmering-text.tsx +108 -0
- package/src/components/sidebar-light.tsx +102 -0
- package/src/components/sonner.tsx +38 -0
- package/src/components/theme-switcher-sidebar.tsx +56 -0
- package/src/components/theme-switcher-simple.tsx +110 -0
- package/src/components/theme-switcher.tsx +47 -0
- package/src/components/toggle-group.tsx +55 -0
- package/src/components/tooltip-button.tsx +91 -0
- package/src/components/tooltip.tsx +71 -0
- package/src/components/tree-view.tsx +499 -0
- package/src/components/unglow-loader.tsx +33 -0
- package/src/components/waveform.tsx +1632 -0
- package/src/components/zoomable-image.tsx +76 -0
- package/src/docs/api-docs.tsx +763 -0
- package/src/docs/callout.tsx +160 -0
- package/src/docs/code-group.tsx +215 -0
- package/src/docs/copy-menu.tsx +143 -0
- package/src/docs/doc-tabs.tsx +84 -0
- package/src/docs/index.ts +16 -0
- package/src/docs/steps.tsx +105 -0
- package/src/docs/table-of-contents.tsx +174 -0
- package/src/examples/guide-markdown.ts +129 -0
- package/src/examples/index.ts +1153 -0
- package/src/global.d.ts +1 -0
- package/src/hooks/use-copy-to-clipboard.ts +36 -0
- package/src/hooks/use-mobile.ts +19 -0
- package/src/lib/display-name.ts +15 -0
- package/src/lib/example-input.ts +130 -0
- package/src/lib/plans.ts +44 -0
- package/src/lib/safe-content.ts +137 -0
- package/src/lib/schema.ts +320 -0
- package/src/lib/storage.ts +108 -0
- package/src/markdown/docs-markdown-renderer.tsx +518 -0
- package/src/markdown/helpers.ts +95 -0
- package/src/markdown/index.ts +24 -0
- package/src/markdown/markdown-renderer.tsx +232 -0
- package/src/markdown/youtube-embed.tsx +43 -0
- package/src/og/image.ts +312 -0
- package/src/og/index.tsx +430 -0
- package/src/og/query.ts +26 -0
- package/src/shadcn/accordion.tsx +71 -0
- package/src/shadcn/alert-dialog.tsx +187 -0
- package/src/shadcn/alert.tsx +75 -0
- package/src/shadcn/aspect-ratio.tsx +22 -0
- package/src/shadcn/attachment.tsx +207 -0
- package/src/shadcn/avatar.tsx +106 -0
- package/src/shadcn/badge.tsx +51 -0
- package/src/shadcn/breadcrumb.tsx +124 -0
- package/src/shadcn/bubble.tsx +127 -0
- package/src/shadcn/button-group.tsx +87 -0
- package/src/shadcn/button.tsx +57 -0
- package/src/shadcn/calendar.tsx +219 -0
- package/src/shadcn/card.tsx +102 -0
- package/src/shadcn/carousel.tsx +242 -0
- package/src/shadcn/chart.tsx +372 -0
- package/src/shadcn/checkbox.tsx +28 -0
- package/src/shadcn/collapsible.tsx +19 -0
- package/src/shadcn/combobox.tsx +297 -0
- package/src/shadcn/command.tsx +194 -0
- package/src/shadcn/context-menu.tsx +270 -0
- package/src/shadcn/dialog.tsx +158 -0
- package/src/shadcn/direction.tsx +4 -0
- package/src/shadcn/drawer.tsx +227 -0
- package/src/shadcn/dropdown-menu.tsx +265 -0
- package/src/shadcn/empty.tsx +103 -0
- package/src/shadcn/field.tsx +238 -0
- package/src/shadcn/form.tsx +173 -0
- package/src/shadcn/hover-card.tsx +50 -0
- package/src/shadcn/index.ts +53 -0
- package/src/shadcn/input-group.tsx +156 -0
- package/src/shadcn/input-otp.tsx +84 -0
- package/src/shadcn/input.tsx +19 -0
- package/src/shadcn/item.tsx +201 -0
- package/src/shadcn/kbd.tsx +26 -0
- package/src/shadcn/label.tsx +19 -0
- package/src/shadcn/marker.tsx +70 -0
- package/src/shadcn/menubar.tsx +278 -0
- package/src/shadcn/message-scroller.tsx +131 -0
- package/src/shadcn/message.tsx +91 -0
- package/src/shadcn/native-select.tsx +60 -0
- package/src/shadcn/navigation-menu.tsx +167 -0
- package/src/shadcn/pagination.tsx +130 -0
- package/src/shadcn/popover.tsx +87 -0
- package/src/shadcn/progress.tsx +82 -0
- package/src/shadcn/radio-group.tsx +35 -0
- package/src/shadcn/resizable.tsx +49 -0
- package/src/shadcn/scroll-area.tsx +52 -0
- package/src/shadcn/select.tsx +200 -0
- package/src/shadcn/separator.tsx +22 -0
- package/src/shadcn/sheet.tsx +136 -0
- package/src/shadcn/sidebar.tsx +721 -0
- package/src/shadcn/skeleton.tsx +13 -0
- package/src/shadcn/slider.tsx +51 -0
- package/src/shadcn/sonner.tsx +49 -0
- package/src/shadcn/spinner.tsx +10 -0
- package/src/shadcn/switch.tsx +29 -0
- package/src/shadcn/table.tsx +115 -0
- package/src/shadcn/tabs.tsx +79 -0
- package/src/shadcn/textarea.tsx +17 -0
- package/src/shadcn/toggle-group.tsx +89 -0
- package/src/shadcn/toggle.tsx +44 -0
- package/src/shadcn/tooltip.tsx +63 -0
- package/src/theme/config.ts +48 -0
- package/src/theme/css/base.css +92 -0
- package/src/theme/css/bitboy.css +75 -0
- package/src/theme/css/dark.css +47 -0
- package/src/theme/css/designer.css +122 -0
- package/src/theme/css/fonts.css +33 -0
- package/src/theme/css/globals.css +14 -0
- package/src/theme/css/hackintosh.css +57 -0
- package/src/theme/css/llama.css +103 -0
- package/src/theme/css/safelist.css +39 -0
- package/src/theme/css/shadcn.css +77 -0
- package/src/theme/css/theme.css +216 -0
- package/src/theme/embed-theme.ts +146 -0
- package/src/theme/fonts/FiraCode-VF.woff2 +0 -0
- package/src/theme/fonts/Hack-Regular.woff2 +0 -0
- package/src/theme/fonts/LICENSE-FiraCode.txt +93 -0
- package/src/theme/fonts/LICENSE-Hack.txt +45 -0
- package/src/theme/fonts/LICENSE-MonaSans.txt +93 -0
- package/src/theme/fonts/Mona-Sans.woff2 +0 -0
- package/src/theme/index.ts +15 -0
- package/src/utils/cn.ts +3 -0
- package/src/utils/index.ts +2 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { cn } from '../utils'
|
|
4
|
+
import { Check, Circle } from 'lucide-react'
|
|
5
|
+
import React, { useMemo } from 'react'
|
|
6
|
+
|
|
7
|
+
// =============================================================================
|
|
8
|
+
// Steps Component
|
|
9
|
+
// =============================================================================
|
|
10
|
+
|
|
11
|
+
interface StepInfo {
|
|
12
|
+
title: string
|
|
13
|
+
children: React.ReactNode
|
|
14
|
+
icon?: React.ReactNode
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function extractSteps(children: React.ReactNode): StepInfo[] {
|
|
18
|
+
const steps: StepInfo[] = []
|
|
19
|
+
|
|
20
|
+
React.Children.forEach(children, (child) => {
|
|
21
|
+
if (!React.isValidElement(child)) return
|
|
22
|
+
|
|
23
|
+
const type = child.type
|
|
24
|
+
const typeName = typeof type === 'string' ? type.toLowerCase() : ''
|
|
25
|
+
|
|
26
|
+
if (typeName === 'step' || (typeof type === 'function' && (type as React.FC).displayName === 'DocsStep')) {
|
|
27
|
+
const props = child.props as { title?: string; icon?: React.ReactNode; children?: React.ReactNode }
|
|
28
|
+
steps.push({
|
|
29
|
+
title: props.title || '',
|
|
30
|
+
icon: props.icon,
|
|
31
|
+
children: props.children,
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
return steps
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface StepsProps {
|
|
40
|
+
children: React.ReactNode
|
|
41
|
+
className?: string
|
|
42
|
+
/** Title text size: 'p' (default), 'h2', 'h3' */
|
|
43
|
+
titleSize?: 'p' | 'h2' | 'h3'
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function Steps({ children, className, titleSize = 'p' }: StepsProps) {
|
|
47
|
+
const steps = useMemo(() => extractSteps(children), [children])
|
|
48
|
+
|
|
49
|
+
if (steps.length === 0) {
|
|
50
|
+
return <div className={className}><span>{children}</span></div>
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const titleClasses = {
|
|
54
|
+
'p': 'text-base font-semibold',
|
|
55
|
+
'h2': 'text-xl font-bold',
|
|
56
|
+
'h3': 'text-lg font-semibold',
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<div className={cn('my-6 space-y-0', className)}>
|
|
61
|
+
{steps.map((step, i) => (
|
|
62
|
+
<div key={i} className="relative flex gap-4 pb-8 last:pb-0">
|
|
63
|
+
{/* Vertical line */}
|
|
64
|
+
{i < steps.length - 1 && (
|
|
65
|
+
<div className="absolute left-[15px] top-8 h-[calc(100%-16px)] w-px bg-border" />
|
|
66
|
+
)}
|
|
67
|
+
|
|
68
|
+
{/* Step number indicator */}
|
|
69
|
+
<div className="relative flex h-8 w-8 shrink-0 items-center justify-center rounded-full border-2 border-brand-pink bg-background text-sm font-semibold text-brand-pink">
|
|
70
|
+
{step.icon || i + 1}
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
{/* Content */}
|
|
74
|
+
<div className="flex-1 pt-0.5">
|
|
75
|
+
{step.title && (
|
|
76
|
+
<div className={cn(titleClasses[titleSize], 'mb-2')}>
|
|
77
|
+
{step.title}
|
|
78
|
+
</div>
|
|
79
|
+
)}
|
|
80
|
+
<div className="text-sm text-muted-foreground prose prose-sm dark:prose-invert max-w-none">
|
|
81
|
+
{step.children}
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
))}
|
|
86
|
+
</div>
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// =============================================================================
|
|
91
|
+
// Step Component (individual step)
|
|
92
|
+
// =============================================================================
|
|
93
|
+
|
|
94
|
+
export interface StepProps {
|
|
95
|
+
title?: string
|
|
96
|
+
icon?: React.ReactNode
|
|
97
|
+
children: React.ReactNode
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function Step({ children }: StepProps) {
|
|
101
|
+
// This component is just a marker - actual rendering happens in Steps
|
|
102
|
+
return <>{children}</>
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
Step.displayName = 'DocsStep'
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { cn } from '../utils'
|
|
4
|
+
import { useEffect, useMemo, useState } from 'react'
|
|
5
|
+
import { TableOfContentsIcon } from 'lucide-react'
|
|
6
|
+
|
|
7
|
+
export interface TocItem {
|
|
8
|
+
id: string
|
|
9
|
+
title: string
|
|
10
|
+
level?: number
|
|
11
|
+
children?: TocItem[]
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface TableOfContentsProps {
|
|
15
|
+
/** Markdown content to extract headings from */
|
|
16
|
+
content?: string
|
|
17
|
+
/** Pre-defined items (alternative to content extraction) */
|
|
18
|
+
items?: TocItem[]
|
|
19
|
+
/** Optional header slot (e.g., language selector) */
|
|
20
|
+
header?: React.ReactNode
|
|
21
|
+
/** Optional footer slot (e.g., link to full docs) */
|
|
22
|
+
footer?: React.ReactNode
|
|
23
|
+
className?: string
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Extract headings from markdown content (h2 and h3 only, h1 is page title)
|
|
27
|
+
// Nests h3s under their preceding h2
|
|
28
|
+
function extractHeadings(content: string): TocItem[] {
|
|
29
|
+
const result: TocItem[] = []
|
|
30
|
+
const lines = content.split('\n')
|
|
31
|
+
let currentH2: TocItem | null = null
|
|
32
|
+
|
|
33
|
+
for (const line of lines) {
|
|
34
|
+
const match = line.match(/^(#{2,3})\s+(.+)$/)
|
|
35
|
+
if (match) {
|
|
36
|
+
const level = match[1].length
|
|
37
|
+
const title = match[2].trim()
|
|
38
|
+
// Create a URL-safe ID from the heading text
|
|
39
|
+
const id = title
|
|
40
|
+
.toLowerCase()
|
|
41
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
42
|
+
.replace(/(^-|-$)/g, '')
|
|
43
|
+
|
|
44
|
+
if (level === 2) {
|
|
45
|
+
currentH2 = { id, title, level, children: [] }
|
|
46
|
+
result.push(currentH2)
|
|
47
|
+
} else if (level === 3) {
|
|
48
|
+
const item = { id, title, level }
|
|
49
|
+
if (currentH2) {
|
|
50
|
+
currentH2.children = currentH2.children || []
|
|
51
|
+
currentH2.children.push(item)
|
|
52
|
+
} else {
|
|
53
|
+
// h3 without preceding h2, add to root
|
|
54
|
+
result.push(item)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return result
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Flatten nested items for intersection observer
|
|
64
|
+
function flattenItems(items: TocItem[]): TocItem[] {
|
|
65
|
+
return items.flatMap(item => [item, ...(item.children || [])])
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function TableOfContents({ content, items, header, footer, className }: TableOfContentsProps) {
|
|
69
|
+
const [activeId, setActiveId] = useState<string>('')
|
|
70
|
+
|
|
71
|
+
// Use provided items or extract from markdown
|
|
72
|
+
const tocItems = useMemo(() => {
|
|
73
|
+
if (items) return items
|
|
74
|
+
if (content) return extractHeadings(content)
|
|
75
|
+
return []
|
|
76
|
+
}, [items, content])
|
|
77
|
+
|
|
78
|
+
// Flatten for observer
|
|
79
|
+
const allItems = useMemo(() => flattenItems(tocItems), [tocItems])
|
|
80
|
+
|
|
81
|
+
useEffect(() => {
|
|
82
|
+
const observer = new IntersectionObserver(
|
|
83
|
+
(entries) => {
|
|
84
|
+
entries.forEach((entry) => {
|
|
85
|
+
if (entry.isIntersecting) {
|
|
86
|
+
setActiveId(entry.target.id)
|
|
87
|
+
}
|
|
88
|
+
})
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
rootMargin: '-80px 0px -80% 0px',
|
|
92
|
+
threshold: 0,
|
|
93
|
+
}
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
// Observe all heading elements
|
|
97
|
+
allItems.forEach(({ id }) => {
|
|
98
|
+
const element = document.getElementById(id)
|
|
99
|
+
if (element) {
|
|
100
|
+
observer.observe(element)
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
return () => observer.disconnect()
|
|
105
|
+
}, [allItems])
|
|
106
|
+
|
|
107
|
+
if (tocItems.length === 0) {
|
|
108
|
+
return null
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const renderItem = (item: TocItem, isChild = false) => {
|
|
112
|
+
const isActive = activeId === item.id
|
|
113
|
+
const level = item.level || (isChild ? 3 : 2)
|
|
114
|
+
|
|
115
|
+
return (
|
|
116
|
+
<li key={item.id}>
|
|
117
|
+
<a
|
|
118
|
+
href={`#${item.id}`}
|
|
119
|
+
onClick={(e) => {
|
|
120
|
+
e.preventDefault()
|
|
121
|
+
const element = document.getElementById(item.id)
|
|
122
|
+
if (element) {
|
|
123
|
+
element.scrollIntoView({ behavior: 'smooth' })
|
|
124
|
+
setActiveId(item.id)
|
|
125
|
+
}
|
|
126
|
+
}}
|
|
127
|
+
className={cn(
|
|
128
|
+
'flex items-center text-[13px] py-1 -ml-px border-l transition-colors lowercase',
|
|
129
|
+
!isChild && 'pl-3 font-medium',
|
|
130
|
+
isChild && 'pl-4 text-xs',
|
|
131
|
+
isActive
|
|
132
|
+
? 'border-brand-pink text-brand-pink'
|
|
133
|
+
: 'border-transparent text-muted-foreground hover:text-foreground hover:border-muted-foreground'
|
|
134
|
+
)}
|
|
135
|
+
>
|
|
136
|
+
{isChild && (
|
|
137
|
+
<span className={cn(
|
|
138
|
+
"mr-1.5 text-[10px] font-mono",
|
|
139
|
+
isActive ? "text-brand-pink" : "text-muted-foreground/50"
|
|
140
|
+
)}>
|
|
141
|
+
└
|
|
142
|
+
</span>
|
|
143
|
+
)}
|
|
144
|
+
{item.title}
|
|
145
|
+
</a>
|
|
146
|
+
{item.children && item.children.length > 0 && (
|
|
147
|
+
<ul className="space-y-0.5">
|
|
148
|
+
{item.children.map(child => renderItem(child, true))}
|
|
149
|
+
</ul>
|
|
150
|
+
)}
|
|
151
|
+
</li>
|
|
152
|
+
)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return (
|
|
156
|
+
<nav className={cn('relative', className)}>
|
|
157
|
+
{header}
|
|
158
|
+
|
|
159
|
+
<div className="flex items-center gap-2 mb-3">
|
|
160
|
+
<TableOfContentsIcon className="h-4 w-4 text-muted-foreground" />
|
|
161
|
+
<p className="text-xs font-bold text-muted-foreground">
|
|
162
|
+
on this page
|
|
163
|
+
</p>
|
|
164
|
+
</div>
|
|
165
|
+
|
|
166
|
+
<ul className="space-y-1 border-l border-border">
|
|
167
|
+
{tocItems.map(item => renderItem(item))}
|
|
168
|
+
</ul>
|
|
169
|
+
|
|
170
|
+
{footer}
|
|
171
|
+
</nav>
|
|
172
|
+
)
|
|
173
|
+
}
|
|
174
|
+
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate a full API guide as markdown for an app.
|
|
3
|
+
* Used by CopyMenu on both app.inference.sh and inference shell SEO pages.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { apiKeySetup, generateBackgroundExamples, generateFileExamples, generateResultOnlyExamples, generateStreamingExamples, installCommands } from '.'
|
|
7
|
+
import { exampleInput } from '../lib/example-input'
|
|
8
|
+
import { getFieldsFromSchema } from '../lib/schema'
|
|
9
|
+
|
|
10
|
+
export type GuideLanguage = 'python' | 'typescript' | 'javascript' | 'swift' | 'curl' | 'belt'
|
|
11
|
+
|
|
12
|
+
export interface GuideApp {
|
|
13
|
+
name: string
|
|
14
|
+
namespace?: string
|
|
15
|
+
description?: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface GuideVersion {
|
|
19
|
+
short_id?: string
|
|
20
|
+
input_schema?: any
|
|
21
|
+
output_schema?: any
|
|
22
|
+
setup_schema?: any
|
|
23
|
+
functions?: Record<string, { name?: string; description?: string; input_schema?: any; output_schema?: any }>
|
|
24
|
+
default_function?: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Where a key is made. /settings/<path> on the app opens that settings page. */
|
|
28
|
+
export const API_KEYS_URL = 'https://app.inference.sh/settings/keys'
|
|
29
|
+
|
|
30
|
+
export function generateGuideMarkdown(
|
|
31
|
+
app: GuideApp,
|
|
32
|
+
version: GuideVersion | undefined,
|
|
33
|
+
language: GuideLanguage = 'curl',
|
|
34
|
+
functionName?: string | null,
|
|
35
|
+
keysUrl: string = API_KEYS_URL,
|
|
36
|
+
): string {
|
|
37
|
+
const namespace = app.namespace || ''
|
|
38
|
+
const shortId = version?.short_id
|
|
39
|
+
const defaultFn = version?.default_function || 'run'
|
|
40
|
+
const effectiveFn = functionName || defaultFn
|
|
41
|
+
const func = version?.functions?.[effectiveFn]
|
|
42
|
+
const schema = func?.input_schema || version?.input_schema || {}
|
|
43
|
+
const outputSchemaObj = func?.output_schema || version?.output_schema
|
|
44
|
+
|
|
45
|
+
// :function only when it is not the default of a multi-function app
|
|
46
|
+
const hasManyFunctions = version?.functions && Object.keys(version.functions).length > 1
|
|
47
|
+
const fnSuffix = (hasManyFunctions && effectiveFn !== defaultFn) ? `:${effectiveFn}` : ''
|
|
48
|
+
const versionSuffix = shortId ? `@${shortId}` : ''
|
|
49
|
+
const appRef = `${namespace}/${app.name}${versionSuffix}${fnSuffix}`
|
|
50
|
+
|
|
51
|
+
const params = { appRef, shortId, input: exampleInput(schema) }
|
|
52
|
+
const resultExamples = generateResultOnlyExamples(params)
|
|
53
|
+
const streamExamples = generateStreamingExamples(params)
|
|
54
|
+
const backgroundExamples = generateBackgroundExamples(params)
|
|
55
|
+
const fileEx = generateFileExamples(appRef)[language]
|
|
56
|
+
const keySetup = apiKeySetup[language] || apiKeySetup.curl
|
|
57
|
+
const installCmd = installCommands[language]
|
|
58
|
+
const codeLang = (language === 'curl' || language === 'belt') ? 'bash' : language
|
|
59
|
+
// swift installs through Package.swift, not a shell command
|
|
60
|
+
const installLang = language === 'swift' ? 'swift' : 'bash'
|
|
61
|
+
|
|
62
|
+
const inputFields = schema ? getFieldsFromSchema(schema).fields : []
|
|
63
|
+
const outputFields = outputSchemaObj ? getFieldsFromSchema(outputSchemaObj).fields : []
|
|
64
|
+
|
|
65
|
+
const code = (lang: string, body: string) => ['```' + lang, body.trim(), '```']
|
|
66
|
+
|
|
67
|
+
const lines = [
|
|
68
|
+
`# ${app.name} API Guide`,
|
|
69
|
+
'',
|
|
70
|
+
'## About',
|
|
71
|
+
`${app.description?.toLowerCase() || `Run ${app.name} via API.`}`,
|
|
72
|
+
'',
|
|
73
|
+
'## Get an API Key',
|
|
74
|
+
language === 'belt'
|
|
75
|
+
? `Create one in [settings → api keys](${keysUrl}), or sign in with \`belt login\`. The examples read it from \`${keySetup.variable}\`.`
|
|
76
|
+
: `Create one in [settings → api keys](${keysUrl}). The examples read it from \`${keySetup.variable}\`.`,
|
|
77
|
+
'',
|
|
78
|
+
...code('bash', keySetup.command),
|
|
79
|
+
'',
|
|
80
|
+
'## 1. Calling the API',
|
|
81
|
+
'',
|
|
82
|
+
...(installCmd
|
|
83
|
+
? ['### Install the Client', '', ...code(installLang, installCmd.command)]
|
|
84
|
+
: ['### Base URL', '', '`https://api.inference.sh`. No version prefix. Every response wraps its result in a `data` field.']),
|
|
85
|
+
'',
|
|
86
|
+
'### Run and Get Result',
|
|
87
|
+
language === 'curl'
|
|
88
|
+
? 'Send `"wait": true` to hold the connection until the task finishes. Without it the call returns right away with the task still running.'
|
|
89
|
+
: 'Submit a request and wait for the final result.',
|
|
90
|
+
'',
|
|
91
|
+
...code(codeLang, resultExamples[language] || ''),
|
|
92
|
+
'',
|
|
93
|
+
'### Stream Live Updates',
|
|
94
|
+
language === 'curl'
|
|
95
|
+
? 'Send `"stream": true` and the response is a server-sent event stream that ends when the task does.'
|
|
96
|
+
: 'Get real-time progress updates as the task runs.',
|
|
97
|
+
'',
|
|
98
|
+
...code(codeLang, streamExamples[language] || ''),
|
|
99
|
+
'',
|
|
100
|
+
'### Run in the Background',
|
|
101
|
+
'Start the task and get its id back right away, then check on it with `GET /tasks/{id}`. It is done when `status` is 10 (completed), 11 (failed) or 12 (cancelled).',
|
|
102
|
+
'',
|
|
103
|
+
...code(codeLang, backgroundExamples[language] || ''),
|
|
104
|
+
'',
|
|
105
|
+
'## 2. Files',
|
|
106
|
+
'',
|
|
107
|
+
'### Automatic Upload',
|
|
108
|
+
'',
|
|
109
|
+
...code(codeLang, fileEx.auto),
|
|
110
|
+
'',
|
|
111
|
+
'### Manual Upload',
|
|
112
|
+
'',
|
|
113
|
+
...code(codeLang, fileEx.manual),
|
|
114
|
+
'',
|
|
115
|
+
'## 3. Schema',
|
|
116
|
+
'',
|
|
117
|
+
'### Input',
|
|
118
|
+
inputFields.length > 0
|
|
119
|
+
? inputFields.map(f => `- **${f.key}** (${f.type || f.resolved?.type || 'any'})${f.isRequired ? ' *required*' : ''}: ${f.description || f.title || ''}`).join('\n')
|
|
120
|
+
: 'No input parameters defined.',
|
|
121
|
+
'',
|
|
122
|
+
'### Output',
|
|
123
|
+
outputFields.length > 0
|
|
124
|
+
? outputFields.map(f => `- **${f.key}** (${f.type || f.resolved?.type || 'any'}): ${f.description || f.title || ''}`).join('\n')
|
|
125
|
+
: 'See task output for result format.',
|
|
126
|
+
]
|
|
127
|
+
|
|
128
|
+
return lines.join('\n')
|
|
129
|
+
}
|