@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,1153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized SDK Code Examples
|
|
3
|
+
*
|
|
4
|
+
* All SDK usage examples in one place for easy maintenance.
|
|
5
|
+
* Used by: app ApiUsage component, docs, README files
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The one API key variable: belt, the SDKs and curl examples all read it.
|
|
10
|
+
* belt still accepts INFSH_API_KEY as a deprecated fallback (go/cli internal/config).
|
|
11
|
+
*/
|
|
12
|
+
export const API_KEY_ENV = 'INFERENCE_API_KEY';
|
|
13
|
+
|
|
14
|
+
/** @deprecated Use API_KEY_ENV. */
|
|
15
|
+
export const SDK_API_KEY_ENV = API_KEY_ENV;
|
|
16
|
+
|
|
17
|
+
/** @deprecated Use API_KEY_ENV. belt reads INFERENCE_API_KEY now. */
|
|
18
|
+
export const CLI_API_KEY_ENV = API_KEY_ENV;
|
|
19
|
+
|
|
20
|
+
export interface ExampleParams {
|
|
21
|
+
/** App reference: namespace/name@shortId */
|
|
22
|
+
appRef: string;
|
|
23
|
+
/** Short ID of the version (for comments) */
|
|
24
|
+
shortId?: string;
|
|
25
|
+
/** Input data */
|
|
26
|
+
input?: Record<string, unknown>;
|
|
27
|
+
/** Setup data (optional) */
|
|
28
|
+
setup?: Record<string, unknown>;
|
|
29
|
+
/** Infrastructure mode */
|
|
30
|
+
infra?: string;
|
|
31
|
+
/** Worker IDs for private infra */
|
|
32
|
+
workers?: string[];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface ExampleOptions {
|
|
36
|
+
/** Include streaming example */
|
|
37
|
+
includeStreaming?: boolean;
|
|
38
|
+
/** Include fire-and-forget example */
|
|
39
|
+
includeFireAndForget?: boolean;
|
|
40
|
+
/** JSON indentation */
|
|
41
|
+
indent?: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Build the request data object used in all examples
|
|
46
|
+
*/
|
|
47
|
+
export function buildRequestData(params: ExampleParams): Record<string, unknown> {
|
|
48
|
+
const { appRef, input, setup, infra, workers } = params;
|
|
49
|
+
const hasSetup = setup && Object.keys(setup).length > 0;
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
app: appRef,
|
|
53
|
+
...(hasSetup && { setup }),
|
|
54
|
+
input: input || {},
|
|
55
|
+
...(infra && infra !== 'cloud' && { infra }),
|
|
56
|
+
...(infra === 'private' && workers && { workers }),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Generate Python SDK example
|
|
62
|
+
*/
|
|
63
|
+
export function generatePythonExample(
|
|
64
|
+
params: ExampleParams,
|
|
65
|
+
options: ExampleOptions = {}
|
|
66
|
+
): string {
|
|
67
|
+
const { shortId } = params;
|
|
68
|
+
const { includeStreaming = true } = options;
|
|
69
|
+
const requestData = buildRequestData(params);
|
|
70
|
+
const jsonStr = formatJson(requestData, 4, ' ');
|
|
71
|
+
|
|
72
|
+
const versionComment = shortId
|
|
73
|
+
? `# version @${shortId} pinned`
|
|
74
|
+
: ``;
|
|
75
|
+
|
|
76
|
+
let code = `import os
|
|
77
|
+
from inferencesh import inference, TaskStatus
|
|
78
|
+
|
|
79
|
+
# initialize client
|
|
80
|
+
client = inference(api_key=os.environ["INFERENCE_API_KEY"])
|
|
81
|
+
|
|
82
|
+
${versionComment}
|
|
83
|
+
# run and wait for completion (default)
|
|
84
|
+
task = client.tasks.run(${jsonStr})
|
|
85
|
+
|
|
86
|
+
print(f"Task ID: {task['id']}")
|
|
87
|
+
|
|
88
|
+
if task["status"] == TaskStatus.COMPLETED:
|
|
89
|
+
print("Task completed!")
|
|
90
|
+
print(f"Output: {task['output']}")
|
|
91
|
+
elif task["status"] == TaskStatus.FAILED:
|
|
92
|
+
print(f"Task failed: {task.get('error')}")`;
|
|
93
|
+
|
|
94
|
+
if (includeStreaming) {
|
|
95
|
+
code += `
|
|
96
|
+
|
|
97
|
+
# stream updates for real-time progress
|
|
98
|
+
for update in client.tasks.run(${jsonStr}, stream=True):
|
|
99
|
+
print(f"Status: {update['status']}")
|
|
100
|
+
if update["status"] == TaskStatus.COMPLETED:
|
|
101
|
+
print(f"Result: {update['output']}")`;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return code;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Generate TypeScript SDK example
|
|
109
|
+
*/
|
|
110
|
+
export function generateTypeScriptExample(
|
|
111
|
+
params: ExampleParams,
|
|
112
|
+
options: ExampleOptions = {}
|
|
113
|
+
): string {
|
|
114
|
+
const { shortId } = params;
|
|
115
|
+
const { includeStreaming = true, includeFireAndForget = true } = options;
|
|
116
|
+
const requestData = buildRequestData(params);
|
|
117
|
+
const jsonStr = formatJson(requestData, 2);
|
|
118
|
+
|
|
119
|
+
const versionComment = shortId
|
|
120
|
+
? `// version @${shortId} pinned`
|
|
121
|
+
: ``;
|
|
122
|
+
|
|
123
|
+
let code = `import { inference, TaskStatusCompleted, TaskStatusFailed } from '@inferencesh/sdk'
|
|
124
|
+
|
|
125
|
+
// initialize client
|
|
126
|
+
const client = inference({ apiKey: process.env.INFERENCE_API_KEY })
|
|
127
|
+
|
|
128
|
+
${versionComment}
|
|
129
|
+
// run and wait for completion (default)
|
|
130
|
+
const task = await client.tasks.run(${jsonStr})
|
|
131
|
+
|
|
132
|
+
console.log("Task ID:", task.id)
|
|
133
|
+
|
|
134
|
+
if (task.status === TaskStatusCompleted) {
|
|
135
|
+
console.log("Task completed!")
|
|
136
|
+
console.log("Output:", task.output)
|
|
137
|
+
} else if (task.status === TaskStatusFailed) {
|
|
138
|
+
console.log("Task failed:", task.error)
|
|
139
|
+
}`;
|
|
140
|
+
|
|
141
|
+
if (includeStreaming) {
|
|
142
|
+
code += `
|
|
143
|
+
|
|
144
|
+
// with real-time status updates
|
|
145
|
+
const result = await client.tasks.run(
|
|
146
|
+
${jsonStr},
|
|
147
|
+
{
|
|
148
|
+
onUpdate: (update) => {
|
|
149
|
+
console.log("Status:", update.status)
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
)`;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (includeFireAndForget) {
|
|
156
|
+
code += `
|
|
157
|
+
|
|
158
|
+
// fire and forget (returns immediately)
|
|
159
|
+
const pending = await client.tasks.run(
|
|
160
|
+
${jsonStr},
|
|
161
|
+
{ wait: false }
|
|
162
|
+
)
|
|
163
|
+
console.log("Task submitted:", pending.id)`;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return code;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Generate JavaScript (CommonJS) SDK example
|
|
171
|
+
*/
|
|
172
|
+
export function generateJavaScriptExample(
|
|
173
|
+
params: ExampleParams,
|
|
174
|
+
options: ExampleOptions = {}
|
|
175
|
+
): string {
|
|
176
|
+
const { shortId } = params;
|
|
177
|
+
const { includeStreaming = true, includeFireAndForget = true } = options;
|
|
178
|
+
const requestData = buildRequestData(params);
|
|
179
|
+
const jsonStr = formatJson(requestData, 2);
|
|
180
|
+
|
|
181
|
+
const versionComment = shortId
|
|
182
|
+
? `// version @${shortId} pinned`
|
|
183
|
+
: ``;
|
|
184
|
+
|
|
185
|
+
let code = `const { inference, TaskStatusCompleted, TaskStatusFailed } = require('@inferencesh/sdk')
|
|
186
|
+
|
|
187
|
+
// initialize client
|
|
188
|
+
const client = inference({ apiKey: process.env.INFERENCE_API_KEY })
|
|
189
|
+
|
|
190
|
+
${versionComment}
|
|
191
|
+
// run and wait for completion (default)
|
|
192
|
+
const task = await client.tasks.run(${jsonStr})
|
|
193
|
+
|
|
194
|
+
console.log("Task ID:", task.id)
|
|
195
|
+
|
|
196
|
+
if (task.status === TaskStatusCompleted) {
|
|
197
|
+
console.log("Task completed!")
|
|
198
|
+
console.log("Output:", task.output)
|
|
199
|
+
} else if (task.status === TaskStatusFailed) {
|
|
200
|
+
console.log("Task failed:", task.error)
|
|
201
|
+
}`;
|
|
202
|
+
|
|
203
|
+
if (includeStreaming) {
|
|
204
|
+
code += `
|
|
205
|
+
|
|
206
|
+
// with real-time status updates
|
|
207
|
+
const result = await client.tasks.run(
|
|
208
|
+
${jsonStr},
|
|
209
|
+
{
|
|
210
|
+
onUpdate: (update) => {
|
|
211
|
+
console.log("Status:", update.status)
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
)`;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (includeFireAndForget) {
|
|
218
|
+
code += `
|
|
219
|
+
|
|
220
|
+
// fire and forget (returns immediately)
|
|
221
|
+
const pending = await client.tasks.run(
|
|
222
|
+
${jsonStr},
|
|
223
|
+
{ wait: false }
|
|
224
|
+
)
|
|
225
|
+
console.log("Task submitted:", pending.id)`;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return code;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// =============================================================================
|
|
232
|
+
// Swift helpers
|
|
233
|
+
// =============================================================================
|
|
234
|
+
|
|
235
|
+
const SWIFT_INDENT = ' ';
|
|
236
|
+
|
|
237
|
+
/** Escape a string as a Swift string literal (quotes included). */
|
|
238
|
+
export function swiftString(value: string): string {
|
|
239
|
+
let out = '"';
|
|
240
|
+
for (const ch of value) {
|
|
241
|
+
switch (ch) {
|
|
242
|
+
case '\\': out += '\\\\'; break;
|
|
243
|
+
case '"': out += '\\"'; break;
|
|
244
|
+
case '\n': out += '\\n'; break;
|
|
245
|
+
case '\r': out += '\\r'; break;
|
|
246
|
+
case '\t': out += '\\t'; break;
|
|
247
|
+
case '\0': out += '\\0'; break;
|
|
248
|
+
default: {
|
|
249
|
+
const code = ch.codePointAt(0)!;
|
|
250
|
+
// other control characters (and line/paragraph separators) as \u{...}
|
|
251
|
+
if (code < 0x20 || code === 0x7f || code === 0x2028 || code === 0x2029) {
|
|
252
|
+
out += `\\u{${code.toString(16)}}`;
|
|
253
|
+
} else {
|
|
254
|
+
out += ch;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return out + '"';
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Format a JSON value as a Swift literal for a `JSONValue` context
|
|
264
|
+
* (dictionaries, arrays, strings, numbers, booleans, `nil`).
|
|
265
|
+
* Continuation lines are indented relative to `level`.
|
|
266
|
+
*/
|
|
267
|
+
export function formatSwiftValue(value: unknown, level: number = 0): string {
|
|
268
|
+
if (value === null || value === undefined) return 'nil';
|
|
269
|
+
if (typeof value === 'string') return swiftString(value);
|
|
270
|
+
if (typeof value === 'boolean') return value ? 'true' : 'false';
|
|
271
|
+
if (typeof value === 'number' || typeof value === 'bigint') {
|
|
272
|
+
const n = Number(value);
|
|
273
|
+
if (!Number.isFinite(n)) return 'nil';
|
|
274
|
+
// integers beyond Int64 would overflow an integer literal; emit a float literal
|
|
275
|
+
if (Number.isInteger(n) && !Number.isSafeInteger(n)) {
|
|
276
|
+
const s = String(n);
|
|
277
|
+
return /[.e]/i.test(s) ? s : `${s}.0`;
|
|
278
|
+
}
|
|
279
|
+
return String(n);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const pad = SWIFT_INDENT.repeat(level + 1);
|
|
283
|
+
const closePad = SWIFT_INDENT.repeat(level);
|
|
284
|
+
|
|
285
|
+
if (Array.isArray(value)) {
|
|
286
|
+
if (value.length === 0) return '[]';
|
|
287
|
+
// short arrays of scalars stay on one line: ["a", "b"], [512, 768]
|
|
288
|
+
if (value.every((v) => v === null || typeof v !== 'object')) {
|
|
289
|
+
const inline = `[${value.map((v) => formatSwiftValue(v, level)).join(', ')}]`;
|
|
290
|
+
if (inline.length <= 60) return inline;
|
|
291
|
+
}
|
|
292
|
+
const items = value.map((v) => `${pad}${formatSwiftValue(v, level + 1)},`);
|
|
293
|
+
return `[\n${items.join('\n')}\n${closePad}]`;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (typeof value === 'object') {
|
|
297
|
+
const entries = Object.entries(value as Record<string, unknown>).filter(([, v]) => v !== undefined);
|
|
298
|
+
if (entries.length === 0) return '[:]';
|
|
299
|
+
const items = entries.map(([k, v]) => `${pad}${swiftString(k)}: ${formatSwiftValue(v, level + 1)},`);
|
|
300
|
+
return `[\n${items.join('\n')}\n${closePad}]`;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return swiftString(String(value));
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/** Swift expression for an infra value (`Infra` is a string-backed struct). */
|
|
307
|
+
function swiftInfra(infra: string): string {
|
|
308
|
+
switch (infra) {
|
|
309
|
+
case 'cloud': return '.cloud';
|
|
310
|
+
case 'private': return '.private';
|
|
311
|
+
case 'private_first': return '.privateFirst';
|
|
312
|
+
default: return `Infra(rawValue: ${swiftString(infra)})`;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
export interface SwiftAppRunRequestFields {
|
|
317
|
+
app: string;
|
|
318
|
+
infra?: string;
|
|
319
|
+
workers?: string[];
|
|
320
|
+
webhook?: string;
|
|
321
|
+
setup?: Record<string, unknown>;
|
|
322
|
+
input?: Record<string, unknown>;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Format an `ApiAppRunRequest(...)` initializer call.
|
|
327
|
+
* Labels follow the initializer's declaration order
|
|
328
|
+
* (app, infra, workers, webhook, setup, input).
|
|
329
|
+
*/
|
|
330
|
+
export function formatSwiftAppRunRequest(fields: SwiftAppRunRequestFields, level: number = 0): string {
|
|
331
|
+
const pad = SWIFT_INDENT.repeat(level + 1);
|
|
332
|
+
const args: string[] = [`app: ${swiftString(fields.app)}`];
|
|
333
|
+
if (fields.infra) args.push(`infra: ${swiftInfra(fields.infra)}`);
|
|
334
|
+
if (fields.workers) args.push(`workers: ${formatSwiftValue(fields.workers, level + 1)}`);
|
|
335
|
+
if (fields.webhook) args.push(`webhook: ${swiftString(fields.webhook)}`);
|
|
336
|
+
if (fields.setup) args.push(`setup: ${formatSwiftValue(fields.setup, level + 1)}`);
|
|
337
|
+
args.push(`input: ${formatSwiftValue(fields.input || {}, level + 1)}`);
|
|
338
|
+
return `ApiAppRunRequest(\n${args.map((a) => pad + a).join(',\n')}\n${SWIFT_INDENT.repeat(level)})`;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/** The app run request for the example params, as a Swift initializer call. */
|
|
342
|
+
function swiftRequest(params: ExampleParams, level: number = 0): string {
|
|
343
|
+
const data = buildRequestData(params) as {
|
|
344
|
+
app: string;
|
|
345
|
+
setup?: Record<string, unknown>;
|
|
346
|
+
input: Record<string, unknown>;
|
|
347
|
+
infra?: string;
|
|
348
|
+
workers?: string[];
|
|
349
|
+
};
|
|
350
|
+
return formatSwiftAppRunRequest(data, level);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Generate Swift SDK example
|
|
355
|
+
*/
|
|
356
|
+
export function generateSwiftExample(
|
|
357
|
+
params: ExampleParams,
|
|
358
|
+
options: ExampleOptions = {}
|
|
359
|
+
): string {
|
|
360
|
+
const { shortId } = params;
|
|
361
|
+
const { includeStreaming = true, includeFireAndForget = true } = options;
|
|
362
|
+
|
|
363
|
+
const versionComment = shortId
|
|
364
|
+
? `// version @${shortId} pinned`
|
|
365
|
+
: ``;
|
|
366
|
+
|
|
367
|
+
let code = `import Foundation
|
|
368
|
+
import InferenceSDK
|
|
369
|
+
|
|
370
|
+
// initialize client
|
|
371
|
+
let client = InferenceClient(apiKey: ProcessInfo.processInfo.environment["INFERENCE_API_KEY"] ?? "")
|
|
372
|
+
|
|
373
|
+
${versionComment}
|
|
374
|
+
let request = ${swiftRequest(params)}
|
|
375
|
+
|
|
376
|
+
// run and wait for completion (default)
|
|
377
|
+
do {
|
|
378
|
+
let task = try await client.tasks.run(request)
|
|
379
|
+
print("Task ID:", task.id)
|
|
380
|
+
print("Output:", task.output)
|
|
381
|
+
} catch let error as TaskRunError {
|
|
382
|
+
// failed and cancelled tasks throw
|
|
383
|
+
print("Task failed:", error.localizedDescription)
|
|
384
|
+
}`;
|
|
385
|
+
|
|
386
|
+
if (includeStreaming) {
|
|
387
|
+
code += `
|
|
388
|
+
|
|
389
|
+
// with real-time status updates
|
|
390
|
+
let result = try await client.tasks.run(
|
|
391
|
+
request,
|
|
392
|
+
options: TaskRunOptions(onUpdate: { update in
|
|
393
|
+
print("Status:", update.status.rawValue)
|
|
394
|
+
})
|
|
395
|
+
)
|
|
396
|
+
print("Output:", result.output)`;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
if (includeFireAndForget) {
|
|
400
|
+
code += `
|
|
401
|
+
|
|
402
|
+
// fire and forget (returns immediately)
|
|
403
|
+
let pending = try await client.tasks.run(
|
|
404
|
+
request,
|
|
405
|
+
options: TaskRunOptions(wait: false)
|
|
406
|
+
)
|
|
407
|
+
print("Task submitted:", pending.id)`;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
return code;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Swift file upload examples (the Swift SDK does not auto-upload local files)
|
|
415
|
+
*/
|
|
416
|
+
export function generateSwiftFileExamples(appRef: string): { auto: string; manual: string } {
|
|
417
|
+
return {
|
|
418
|
+
auto: `// pass file URLs directly as input
|
|
419
|
+
let result = try await client.tasks.run(ApiAppRunRequest(
|
|
420
|
+
app: ${swiftString(appRef)},
|
|
421
|
+
input: [
|
|
422
|
+
"image": "https://example.com/image.png",
|
|
423
|
+
]
|
|
424
|
+
))`,
|
|
425
|
+
manual: `// upload a local file and pass its hosted URL
|
|
426
|
+
let data = try Data(contentsOf: URL(fileURLWithPath: "/path/to/file.png"))
|
|
427
|
+
let file = try await client.files.upload(data, filename: "file.png", contentType: "image/png")
|
|
428
|
+
print(file.uri) // https://cloud.inference.sh/...`,
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Swift webhook example (fire and forget, result POSTed to the webhook)
|
|
434
|
+
*/
|
|
435
|
+
export function generateSwiftWebhookExample(appRef: string, input: Record<string, unknown>): string {
|
|
436
|
+
return `let task = try await client.tasks.run(
|
|
437
|
+
${formatSwiftAppRunRequest({ app: appRef, webhook: 'https://your-server.com/webhook', input }, 1)},
|
|
438
|
+
options: TaskRunOptions(wait: false)
|
|
439
|
+
)`;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Generate cURL example
|
|
444
|
+
*/
|
|
445
|
+
export function generateCurlExample(params: ExampleParams): string {
|
|
446
|
+
const { shortId } = params;
|
|
447
|
+
const requestData = buildRequestData(params);
|
|
448
|
+
const jsonStr = JSON.stringify(requestData, null, 2).split('\n').join('\n ');
|
|
449
|
+
|
|
450
|
+
const versionComment = shortId
|
|
451
|
+
? `# version @${shortId} pinned`
|
|
452
|
+
: ``;
|
|
453
|
+
|
|
454
|
+
const waitJson = JSON.stringify({ ...requestData, wait: true }, null, 2).split('\n').join('\n ');
|
|
455
|
+
const streamJson = JSON.stringify({ ...requestData, stream: true }, null, 2).split('\n').join('\n ');
|
|
456
|
+
|
|
457
|
+
return `${versionComment}
|
|
458
|
+
# run and wait for the result
|
|
459
|
+
curl -X POST https://api.inference.sh/apps/run \\
|
|
460
|
+
-H "Authorization: Bearer $INFERENCE_API_KEY" \\
|
|
461
|
+
-H "Content-Type: application/json" \\
|
|
462
|
+
-d ${shellQuote(waitJson)}
|
|
463
|
+
|
|
464
|
+
# or stream live updates (server-sent events)
|
|
465
|
+
curl -N -X POST https://api.inference.sh/apps/run \\
|
|
466
|
+
-H "Authorization: Bearer $INFERENCE_API_KEY" \\
|
|
467
|
+
-H "Content-Type: application/json" \\
|
|
468
|
+
-d ${shellQuote(streamJson)}`;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Generate all examples for a given set of parameters
|
|
473
|
+
*/
|
|
474
|
+
export function generateAllExamples(
|
|
475
|
+
params: ExampleParams,
|
|
476
|
+
options: ExampleOptions = {}
|
|
477
|
+
): Record<string, string> {
|
|
478
|
+
return {
|
|
479
|
+
python: generatePythonExample(params, options),
|
|
480
|
+
typescript: generateTypeScriptExample(params, options),
|
|
481
|
+
javascript: generateJavaScriptExample(params, options),
|
|
482
|
+
swift: generateSwiftExample(params, options),
|
|
483
|
+
curl: generateCurlExample(params),
|
|
484
|
+
belt: generateBeltExample(params),
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* Generate result-only examples (no streaming, just wait for completion)
|
|
490
|
+
*/
|
|
491
|
+
export function generateResultOnlyExamples(params: ExampleParams): Record<string, string> {
|
|
492
|
+
const requestData = buildRequestData(params);
|
|
493
|
+
const { shortId } = params;
|
|
494
|
+
|
|
495
|
+
const versionCommentPy = shortId
|
|
496
|
+
? `# version @${shortId} pinned`
|
|
497
|
+
: ``;
|
|
498
|
+
|
|
499
|
+
const versionCommentJs = shortId
|
|
500
|
+
? `// version @${shortId} pinned`
|
|
501
|
+
: ``;
|
|
502
|
+
|
|
503
|
+
const jsonStrPy = formatJson(requestData, 4, ' ');
|
|
504
|
+
const jsonStrJs = formatJson(requestData, 2);
|
|
505
|
+
const jsonStrCurl = JSON.stringify({ ...requestData, wait: true }, null, 2).split('\n').join('\n ');
|
|
506
|
+
const swiftReq = swiftRequest(params);
|
|
507
|
+
|
|
508
|
+
return {
|
|
509
|
+
python: `import os
|
|
510
|
+
from inferencesh import inference
|
|
511
|
+
|
|
512
|
+
client = inference(api_key=os.environ["INFERENCE_API_KEY"])
|
|
513
|
+
|
|
514
|
+
${versionCommentPy}
|
|
515
|
+
result = client.run(${jsonStrPy})
|
|
516
|
+
|
|
517
|
+
print(result["output"])`,
|
|
518
|
+
|
|
519
|
+
typescript: `import { inference } from "@inferencesh/sdk"
|
|
520
|
+
|
|
521
|
+
const client = inference({ apiKey: process.env.INFERENCE_API_KEY })
|
|
522
|
+
|
|
523
|
+
${versionCommentJs}
|
|
524
|
+
const result = await client.run(${jsonStrJs})
|
|
525
|
+
|
|
526
|
+
console.log(result.output)`,
|
|
527
|
+
|
|
528
|
+
javascript: `const { inference } = require("@inferencesh/sdk")
|
|
529
|
+
|
|
530
|
+
const client = inference({ apiKey: process.env.INFERENCE_API_KEY })
|
|
531
|
+
|
|
532
|
+
${versionCommentJs}
|
|
533
|
+
const result = await client.run(${jsonStrJs})
|
|
534
|
+
|
|
535
|
+
console.log(result.output)`,
|
|
536
|
+
|
|
537
|
+
swift: `import Foundation
|
|
538
|
+
import InferenceSDK
|
|
539
|
+
|
|
540
|
+
let client = InferenceClient(apiKey: ProcessInfo.processInfo.environment["INFERENCE_API_KEY"] ?? "")
|
|
541
|
+
|
|
542
|
+
${versionCommentJs}
|
|
543
|
+
let result = try await client.tasks.run(${swiftReq})
|
|
544
|
+
|
|
545
|
+
print(result.output)`,
|
|
546
|
+
|
|
547
|
+
curl: `${versionCommentPy}
|
|
548
|
+
# "wait": true holds the connection until the task finishes.
|
|
549
|
+
# the response is {"data": {"id", "status", "status_text", "output", ...}}
|
|
550
|
+
curl -X POST https://api.inference.sh/apps/run \\
|
|
551
|
+
-H "Authorization: Bearer $INFERENCE_API_KEY" \\
|
|
552
|
+
-H "Content-Type: application/json" \\
|
|
553
|
+
-d ${shellQuote(jsonStrCurl)}`,
|
|
554
|
+
|
|
555
|
+
belt: `${versionCommentPy}
|
|
556
|
+
belt app run ${params.appRef} --input ${shellQuote(JSON.stringify(requestData.input || {}))}`,
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* Generate streaming examples (real-time updates)
|
|
562
|
+
*/
|
|
563
|
+
export function generateStreamingExamples(params: ExampleParams): Record<string, string> {
|
|
564
|
+
const requestData = buildRequestData(params);
|
|
565
|
+
const { shortId } = params;
|
|
566
|
+
|
|
567
|
+
const versionCommentPy = shortId
|
|
568
|
+
? `# version @${shortId} pinned`
|
|
569
|
+
: ``;
|
|
570
|
+
|
|
571
|
+
const versionCommentJs = shortId
|
|
572
|
+
? `// version @${shortId} pinned`
|
|
573
|
+
: ``;
|
|
574
|
+
|
|
575
|
+
const jsonStrPy = formatJson(requestData, 4, ' ');
|
|
576
|
+
const jsonStrJs = formatJson(requestData, 2);
|
|
577
|
+
const jsonStrCurl = JSON.stringify({ ...requestData, stream: true }, null, 2).split('\n').join('\n ');
|
|
578
|
+
|
|
579
|
+
return {
|
|
580
|
+
python: `import os
|
|
581
|
+
from inferencesh import inference
|
|
582
|
+
|
|
583
|
+
client = inference(api_key=os.environ["INFERENCE_API_KEY"])
|
|
584
|
+
|
|
585
|
+
${versionCommentPy}
|
|
586
|
+
# stream=True yields updates as they arrive
|
|
587
|
+
for update in client.run(${jsonStrPy}, stream=True):
|
|
588
|
+
if update.get("progress"):
|
|
589
|
+
print(f"progress: {update['progress']}%")
|
|
590
|
+
if update.get("output"):
|
|
591
|
+
print(f"output: {update['output']}")`,
|
|
592
|
+
|
|
593
|
+
typescript: `import { inference } from "@inferencesh/sdk"
|
|
594
|
+
|
|
595
|
+
const client = inference({ apiKey: process.env.INFERENCE_API_KEY })
|
|
596
|
+
|
|
597
|
+
${versionCommentJs}
|
|
598
|
+
// onUpdate callback fires on each status change
|
|
599
|
+
const result = await client.run(${jsonStrJs}, {
|
|
600
|
+
onUpdate: (update) => {
|
|
601
|
+
if (update.progress) {
|
|
602
|
+
console.log(\`progress: \${update.progress}%\`)
|
|
603
|
+
}
|
|
604
|
+
if (update.output) {
|
|
605
|
+
console.log("output:", update.output)
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
})`,
|
|
609
|
+
|
|
610
|
+
javascript: `const { inference } = require("@inferencesh/sdk")
|
|
611
|
+
|
|
612
|
+
const client = inference({ apiKey: process.env.INFERENCE_API_KEY })
|
|
613
|
+
|
|
614
|
+
${versionCommentJs}
|
|
615
|
+
// onUpdate callback fires on each status change
|
|
616
|
+
const result = await client.run(${jsonStrJs}, {
|
|
617
|
+
onUpdate: (update) => {
|
|
618
|
+
if (update.progress) {
|
|
619
|
+
console.log(\`progress: \${update.progress}%\`)
|
|
620
|
+
}
|
|
621
|
+
if (update.output) {
|
|
622
|
+
console.log("output:", update.output)
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
})`,
|
|
626
|
+
|
|
627
|
+
swift: `import Foundation
|
|
628
|
+
import InferenceSDK
|
|
629
|
+
|
|
630
|
+
let client = InferenceClient(apiKey: ProcessInfo.processInfo.environment["INFERENCE_API_KEY"] ?? "")
|
|
631
|
+
|
|
632
|
+
${versionCommentJs}
|
|
633
|
+
// onUpdate fires on each status change
|
|
634
|
+
let result = try await client.tasks.run(
|
|
635
|
+
${swiftRequest(params, 1)},
|
|
636
|
+
options: TaskRunOptions(onUpdate: { update in
|
|
637
|
+
print("status:", update.status.rawValue)
|
|
638
|
+
})
|
|
639
|
+
)
|
|
640
|
+
|
|
641
|
+
print("output:", result.output)`,
|
|
642
|
+
|
|
643
|
+
curl: `${versionCommentPy}
|
|
644
|
+
# "stream": true answers with server-sent events until the task finishes
|
|
645
|
+
curl -N -X POST https://api.inference.sh/apps/run \\
|
|
646
|
+
-H "Authorization: Bearer $INFERENCE_API_KEY" \\
|
|
647
|
+
-H "Content-Type: application/json" \\
|
|
648
|
+
-d ${shellQuote(jsonStrCurl)}`,
|
|
649
|
+
|
|
650
|
+
belt: `${versionCommentPy}
|
|
651
|
+
# belt streams progress by default
|
|
652
|
+
belt app run ${params.appRef} --input ${shellQuote(JSON.stringify(requestData.input || {}))}`,
|
|
653
|
+
};
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
/**
|
|
657
|
+
* Run without waiting, then check on the task later.
|
|
658
|
+
* Each SDK returns the task right away; GET /tasks/{id} reads its state.
|
|
659
|
+
*/
|
|
660
|
+
export function generateBackgroundExamples(params: ExampleParams): Record<string, string> {
|
|
661
|
+
const requestData = buildRequestData(params);
|
|
662
|
+
const jsonStrPy = formatJson(requestData, 4, ' ');
|
|
663
|
+
const jsonStrJs = formatJson(requestData, 2);
|
|
664
|
+
const jsonStrCurl = JSON.stringify(requestData, null, 2).split('\n').join('\n ');
|
|
665
|
+
const jsClient = (importLine: string) => `${importLine}
|
|
666
|
+
|
|
667
|
+
const client = inference({ apiKey: process.env.INFERENCE_API_KEY })
|
|
668
|
+
|
|
669
|
+
// returns as soon as the task is created
|
|
670
|
+
const task = await client.run(${jsonStrJs}, { wait: false })
|
|
671
|
+
|
|
672
|
+
// later: read its current state
|
|
673
|
+
const { data: state } = await client.tasks.get(task.id)
|
|
674
|
+
if (state.status === TaskStatusCompleted) {
|
|
675
|
+
console.log(state.output)
|
|
676
|
+
}`;
|
|
677
|
+
|
|
678
|
+
return {
|
|
679
|
+
python: `import os
|
|
680
|
+
from inferencesh import inference, TaskStatus
|
|
681
|
+
|
|
682
|
+
client = inference(api_key=os.environ["INFERENCE_API_KEY"])
|
|
683
|
+
|
|
684
|
+
# returns as soon as the task is created
|
|
685
|
+
task = client.run(${jsonStrPy}, wait=False)
|
|
686
|
+
|
|
687
|
+
# later: read its current state
|
|
688
|
+
state = client.tasks.get(task["id"]).data
|
|
689
|
+
if state["status"] == TaskStatus.COMPLETED:
|
|
690
|
+
print(state["output"])`,
|
|
691
|
+
|
|
692
|
+
typescript: jsClient(`import { inference, TaskStatusCompleted } from "@inferencesh/sdk"`),
|
|
693
|
+
javascript: jsClient(`const { inference, TaskStatusCompleted } = require("@inferencesh/sdk")`),
|
|
694
|
+
|
|
695
|
+
swift: `import Foundation
|
|
696
|
+
import InferenceSDK
|
|
697
|
+
|
|
698
|
+
let client = InferenceClient(apiKey: ProcessInfo.processInfo.environment["INFERENCE_API_KEY"] ?? "")
|
|
699
|
+
|
|
700
|
+
// returns as soon as the task is created
|
|
701
|
+
let task = try await client.tasks.run(
|
|
702
|
+
${swiftRequest(params, 1)},
|
|
703
|
+
options: TaskRunOptions(wait: false)
|
|
704
|
+
)
|
|
705
|
+
|
|
706
|
+
// later: read its current state
|
|
707
|
+
let state = try await client.tasks.get(task.id)
|
|
708
|
+
print(state.status, state.output)`,
|
|
709
|
+
|
|
710
|
+
curl: `# without "wait" the call returns the task right away (status 1, "received")
|
|
711
|
+
TASK_ID=$(curl -s -X POST https://api.inference.sh/apps/run \\
|
|
712
|
+
-H "Authorization: Bearer $INFERENCE_API_KEY" \\
|
|
713
|
+
-H "Content-Type: application/json" \\
|
|
714
|
+
-d ${shellQuote(jsonStrCurl)} | jq -r '.data.id')
|
|
715
|
+
|
|
716
|
+
# later: read its state. done when status is 10 (completed), 11 (failed) or 12 (cancelled)
|
|
717
|
+
curl -s https://api.inference.sh/tasks/$TASK_ID \\
|
|
718
|
+
-H "Authorization: Bearer $INFERENCE_API_KEY" | jq '.data | {status, status_text, output}'`,
|
|
719
|
+
|
|
720
|
+
belt: `# returns the task id without waiting
|
|
721
|
+
belt app run ${params.appRef} --input ${shellQuote(JSON.stringify(requestData.input || {}))} --no-wait
|
|
722
|
+
|
|
723
|
+
# later: read its state (-f follows it until it finishes)
|
|
724
|
+
belt task get TASK_ID -f`,
|
|
725
|
+
};
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
/**
|
|
729
|
+
* File input examples: passing files in, and uploading one by hand.
|
|
730
|
+
*/
|
|
731
|
+
export function generateFileExamples(appRef: string): Record<string, { auto: string; manual: string }> {
|
|
732
|
+
const js = {
|
|
733
|
+
auto: `// File/Blob objects and data URIs are automatically uploaded
|
|
734
|
+
const result = await client.run({
|
|
735
|
+
app: "${appRef}",
|
|
736
|
+
input: {
|
|
737
|
+
image: fileInput.files[0], // File from <input> - uploaded
|
|
738
|
+
photo: await fetch(url).then(r => r.blob()), // Blob - uploaded
|
|
739
|
+
icon: "data:image/png;base64,...", // data URI - uploaded
|
|
740
|
+
}
|
|
741
|
+
})`,
|
|
742
|
+
manual: `// upload and get a hosted URL
|
|
743
|
+
const file = await client.files.upload(blob, {
|
|
744
|
+
filename: "image.png",
|
|
745
|
+
contentType: "image/png"
|
|
746
|
+
})
|
|
747
|
+
console.log(file.uri) // https://cloud.inference.sh/...`,
|
|
748
|
+
};
|
|
749
|
+
return {
|
|
750
|
+
python: {
|
|
751
|
+
auto: `# local file paths are automatically uploaded
|
|
752
|
+
result = client.run({
|
|
753
|
+
"app": "${appRef}",
|
|
754
|
+
"input": {
|
|
755
|
+
"image": "/path/to/local/image.png", # detected & uploaded
|
|
756
|
+
"audio": "https://example.com/audio.mp3", # url passed through
|
|
757
|
+
}
|
|
758
|
+
})`,
|
|
759
|
+
manual: `# upload and get a hosted URL
|
|
760
|
+
file = client.files.upload("/path/to/file.png")
|
|
761
|
+
print(file.uri) # https://cloud.inference.sh/...`,
|
|
762
|
+
},
|
|
763
|
+
typescript: js,
|
|
764
|
+
javascript: js,
|
|
765
|
+
swift: generateSwiftFileExamples(appRef),
|
|
766
|
+
curl: {
|
|
767
|
+
auto: `# pass URLs or data URIs as input values
|
|
768
|
+
curl -X POST https://api.inference.sh/apps/run \\
|
|
769
|
+
-H "Authorization: Bearer $INFERENCE_API_KEY" \\
|
|
770
|
+
-H "Content-Type: application/json" \\
|
|
771
|
+
-d '{
|
|
772
|
+
"app": "${appRef}",
|
|
773
|
+
"input": {
|
|
774
|
+
"image": "https://example.com/image.png",
|
|
775
|
+
"audio": "data:audio/mp3;base64,..."
|
|
776
|
+
},
|
|
777
|
+
"wait": true
|
|
778
|
+
}'`,
|
|
779
|
+
manual: `# 1. create the file: the response has an upload_url and the file's uri
|
|
780
|
+
FILE=$(curl -s -X POST https://api.inference.sh/files \\
|
|
781
|
+
-H "Authorization: Bearer $INFERENCE_API_KEY" \\
|
|
782
|
+
-H "Content-Type: application/json" \\
|
|
783
|
+
-d '{"files": [{"filename": "image.png", "content_type": "image/png"}]}')
|
|
784
|
+
|
|
785
|
+
# 2. PUT the bytes to upload_url
|
|
786
|
+
curl -X PUT "$(echo "$FILE" | jq -r '.data[0].upload_url')" \\
|
|
787
|
+
-H "Content-Type: image/png" \\
|
|
788
|
+
--data-binary @image.png
|
|
789
|
+
|
|
790
|
+
# 3. pass the uri as an input value
|
|
791
|
+
echo "$FILE" | jq -r '.data[0].uri'`,
|
|
792
|
+
},
|
|
793
|
+
belt: {
|
|
794
|
+
auto: `# belt uploads local paths in the input for you
|
|
795
|
+
belt app run ${appRef} --input '{"image": "/path/to/local/image.png"}'`,
|
|
796
|
+
manual: `# files are handled automatically by belt
|
|
797
|
+
# pass local paths or URLs in the input JSON`,
|
|
798
|
+
},
|
|
799
|
+
};
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
/**
|
|
803
|
+
* Generate belt CLI example
|
|
804
|
+
*/
|
|
805
|
+
export function generateBeltExample(params: ExampleParams): string {
|
|
806
|
+
const { appRef, input } = params;
|
|
807
|
+
const inputJson = shellQuote(JSON.stringify(input || {}));
|
|
808
|
+
|
|
809
|
+
return `# install belt
|
|
810
|
+
curl -fsSL https://cli.inference.sh | sh
|
|
811
|
+
|
|
812
|
+
# sign in (or set ${API_KEY_ENV} on a headless machine)
|
|
813
|
+
belt login
|
|
814
|
+
|
|
815
|
+
# run and wait for result
|
|
816
|
+
belt app run ${appRef} --input ${inputJson}
|
|
817
|
+
|
|
818
|
+
# save output to file
|
|
819
|
+
belt app run ${appRef} --input ${inputJson} -o result.json
|
|
820
|
+
|
|
821
|
+
# get app details and schema
|
|
822
|
+
belt app get ${appRef}`;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
/**
|
|
826
|
+
* Install commands for each language
|
|
827
|
+
*/
|
|
828
|
+
export const installCommands: Record<string, { command: string; label: string } | null> = {
|
|
829
|
+
python: { command: 'pip install inferencesh', label: '$' },
|
|
830
|
+
typescript: { command: 'npm install @inferencesh/sdk', label: '$' },
|
|
831
|
+
javascript: { command: 'npm install @inferencesh/sdk', label: '$' },
|
|
832
|
+
swift: { command: '.package(url: "https://github.com/inference-sh/sdk-swift", from: "0.1.0")', label: 'spm' },
|
|
833
|
+
curl: null,
|
|
834
|
+
belt: { command: 'curl -fsSL https://cli.inference.sh | sh', label: '$' },
|
|
835
|
+
};
|
|
836
|
+
|
|
837
|
+
/**
|
|
838
|
+
* How each language picks up the API key. Every tool reads the same variable,
|
|
839
|
+
* API_KEY_ENV; belt also uses its saved login.
|
|
840
|
+
*/
|
|
841
|
+
export const apiKeySetup: Record<string, { variable: string; command: string }> = {
|
|
842
|
+
python: { variable: API_KEY_ENV, command: `export ${API_KEY_ENV}="inf_your_key"` },
|
|
843
|
+
typescript: { variable: API_KEY_ENV, command: `export ${API_KEY_ENV}="inf_your_key"` },
|
|
844
|
+
javascript: { variable: API_KEY_ENV, command: `export ${API_KEY_ENV}="inf_your_key"` },
|
|
845
|
+
swift: { variable: API_KEY_ENV, command: `export ${API_KEY_ENV}="inf_your_key"` },
|
|
846
|
+
curl: { variable: API_KEY_ENV, command: `export ${API_KEY_ENV}="inf_your_key"` },
|
|
847
|
+
belt: {
|
|
848
|
+
variable: API_KEY_ENV,
|
|
849
|
+
command: `# sign in from a browser
|
|
850
|
+
belt login
|
|
851
|
+
|
|
852
|
+
# or, on a headless machine
|
|
853
|
+
export ${API_KEY_ENV}="inf_your_key"`,
|
|
854
|
+
},
|
|
855
|
+
};
|
|
856
|
+
|
|
857
|
+
/** Quote a string for a POSIX shell: single quotes, with any single quote spliced in. */
|
|
858
|
+
export function shellQuote(value: string): string {
|
|
859
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
// Helper to format JSON with custom indentation for nested content
|
|
863
|
+
function formatJson(obj: Record<string, unknown>, indent: number, prefix: string = ''): string {
|
|
864
|
+
const json = JSON.stringify(obj, null, indent);
|
|
865
|
+
if (!prefix) return json;
|
|
866
|
+
return json.split('\n').map((line, i) => i === 0 ? line : prefix + line).join('\n');
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
// =============================================================================
|
|
870
|
+
// Agent Examples
|
|
871
|
+
// =============================================================================
|
|
872
|
+
|
|
873
|
+
export interface AgentExampleParams {
|
|
874
|
+
/** Agent reference: namespace/name@shortVersionId */
|
|
875
|
+
agentRef: string;
|
|
876
|
+
/** Short version ID (for comments) */
|
|
877
|
+
shortVersionId?: string;
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
/**
|
|
881
|
+
* Generate Python Agent SDK example
|
|
882
|
+
*/
|
|
883
|
+
export function generateAgentPythonExample(params: AgentExampleParams): string {
|
|
884
|
+
const { agentRef, shortVersionId } = params;
|
|
885
|
+
|
|
886
|
+
const versionComment = shortVersionId
|
|
887
|
+
? `# version @${shortVersionId} pinned`
|
|
888
|
+
: ``;
|
|
889
|
+
|
|
890
|
+
return `import os
|
|
891
|
+
from inferencesh import inference
|
|
892
|
+
|
|
893
|
+
# initialize client
|
|
894
|
+
client = inference(api_key=os.environ["INFERENCE_API_KEY"])
|
|
895
|
+
|
|
896
|
+
${versionComment}
|
|
897
|
+
# create agent from template
|
|
898
|
+
agent = client.agents.create("${agentRef}")
|
|
899
|
+
|
|
900
|
+
# send a message
|
|
901
|
+
response = agent.send_message("Hello!")
|
|
902
|
+
print(response)
|
|
903
|
+
|
|
904
|
+
# with streaming
|
|
905
|
+
def on_message(msg):
|
|
906
|
+
if msg.get("content"):
|
|
907
|
+
print(msg["content"], end="", flush=True)
|
|
908
|
+
|
|
909
|
+
def on_tool_call(call):
|
|
910
|
+
print(f"\\n[Tool: {call.name}]")
|
|
911
|
+
result = handle_tool(call.name, call.args)
|
|
912
|
+
agent.submit_tool_result(call.id, result)
|
|
913
|
+
|
|
914
|
+
response = agent.send_message(
|
|
915
|
+
"Help me with something",
|
|
916
|
+
on_message=on_message,
|
|
917
|
+
on_tool_call=on_tool_call
|
|
918
|
+
)
|
|
919
|
+
|
|
920
|
+
# get chat history
|
|
921
|
+
chat = agent.get_chat()
|
|
922
|
+
print(f"Chat ID: {chat['id']}")
|
|
923
|
+
|
|
924
|
+
# stop generation
|
|
925
|
+
agent.stop_chat()
|
|
926
|
+
|
|
927
|
+
# start fresh conversation
|
|
928
|
+
agent.reset()`;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
/**
|
|
932
|
+
* Generate TypeScript Agent SDK example
|
|
933
|
+
*/
|
|
934
|
+
export function generateAgentTypeScriptExample(params: AgentExampleParams): string {
|
|
935
|
+
const { agentRef, shortVersionId } = params;
|
|
936
|
+
|
|
937
|
+
const versionComment = shortVersionId
|
|
938
|
+
? `// version @${shortVersionId} pinned`
|
|
939
|
+
: ``;
|
|
940
|
+
|
|
941
|
+
return `import { inference } from '@inferencesh/sdk'
|
|
942
|
+
|
|
943
|
+
// initialize client
|
|
944
|
+
const client = inference({ apiKey: process.env.INFERENCE_API_KEY })
|
|
945
|
+
|
|
946
|
+
${versionComment}
|
|
947
|
+
// create agent from template
|
|
948
|
+
const agent = client.agents.create('${agentRef}')
|
|
949
|
+
|
|
950
|
+
// send a message
|
|
951
|
+
const response = await agent.sendMessage('Hello!')
|
|
952
|
+
console.log(response)
|
|
953
|
+
|
|
954
|
+
// with streaming
|
|
955
|
+
await agent.sendMessage('Help me with something', {
|
|
956
|
+
onMessage: (msg) => {
|
|
957
|
+
if (msg.content) {
|
|
958
|
+
for (const c of msg.content) {
|
|
959
|
+
if (c.type === 'text' && c.text) {
|
|
960
|
+
process.stdout.write(c.text)
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
},
|
|
965
|
+
onToolCall: async (call) => {
|
|
966
|
+
console.log(\`\\n[Tool: \${call.name}]\`)
|
|
967
|
+
const result = await handleTool(call.name, call.args)
|
|
968
|
+
await agent.submitToolResult(call.id, result)
|
|
969
|
+
}
|
|
970
|
+
})
|
|
971
|
+
|
|
972
|
+
// get chat history
|
|
973
|
+
const chat = await agent.getChat()
|
|
974
|
+
console.log('Chat ID:', chat?.id)
|
|
975
|
+
|
|
976
|
+
// stop generation
|
|
977
|
+
await agent.stopChat()
|
|
978
|
+
|
|
979
|
+
// cleanup
|
|
980
|
+
agent.disconnect()`;
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
/**
|
|
984
|
+
* Generate JavaScript Agent SDK example
|
|
985
|
+
*/
|
|
986
|
+
export function generateAgentJavaScriptExample(params: AgentExampleParams): string {
|
|
987
|
+
const { agentRef, shortVersionId } = params;
|
|
988
|
+
|
|
989
|
+
const versionComment = shortVersionId
|
|
990
|
+
? `// version @${shortVersionId} pinned`
|
|
991
|
+
: ``;
|
|
992
|
+
|
|
993
|
+
return `const { inference } = require('@inferencesh/sdk')
|
|
994
|
+
|
|
995
|
+
// initialize client
|
|
996
|
+
const client = inference({ apiKey: process.env.INFERENCE_API_KEY })
|
|
997
|
+
|
|
998
|
+
${versionComment}
|
|
999
|
+
// create agent from template
|
|
1000
|
+
const agent = client.agents.create('${agentRef}')
|
|
1001
|
+
|
|
1002
|
+
// send a message
|
|
1003
|
+
const response = await agent.sendMessage('Hello!')
|
|
1004
|
+
console.log(response)
|
|
1005
|
+
|
|
1006
|
+
// with streaming
|
|
1007
|
+
await agent.sendMessage('Help me with something', {
|
|
1008
|
+
onMessage: (msg) => {
|
|
1009
|
+
if (msg.content) {
|
|
1010
|
+
for (const c of msg.content) {
|
|
1011
|
+
if (c.type === 'text' && c.text) {
|
|
1012
|
+
process.stdout.write(c.text)
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
},
|
|
1017
|
+
onToolCall: async (call) => {
|
|
1018
|
+
console.log(\`\\n[Tool: \${call.name}]\`)
|
|
1019
|
+
const result = await handleTool(call.name, call.args)
|
|
1020
|
+
await agent.submitToolResult(call.id, result)
|
|
1021
|
+
}
|
|
1022
|
+
})
|
|
1023
|
+
|
|
1024
|
+
// get chat history
|
|
1025
|
+
const chat = await agent.getChat()
|
|
1026
|
+
console.log('Chat ID:', chat?.id)
|
|
1027
|
+
|
|
1028
|
+
// stop generation
|
|
1029
|
+
await agent.stopChat()
|
|
1030
|
+
|
|
1031
|
+
// cleanup
|
|
1032
|
+
agent.disconnect()`;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
/**
|
|
1036
|
+
* Generate Swift Agent SDK example
|
|
1037
|
+
*/
|
|
1038
|
+
export function generateAgentSwiftExample(params: AgentExampleParams): string {
|
|
1039
|
+
const { agentRef, shortVersionId } = params;
|
|
1040
|
+
|
|
1041
|
+
const versionComment = shortVersionId
|
|
1042
|
+
? `// version @${shortVersionId} pinned`
|
|
1043
|
+
: ``;
|
|
1044
|
+
|
|
1045
|
+
return `import InferenceSDK
|
|
1046
|
+
|
|
1047
|
+
// initialize client
|
|
1048
|
+
let client = InferenceClient(apiKey: ProcessInfo.processInfo.environment["INFERENCE_API_KEY"] ?? "")
|
|
1049
|
+
|
|
1050
|
+
${versionComment}
|
|
1051
|
+
// one-shot run: streams snapshots of the reply until it finishes
|
|
1052
|
+
let request = ApiAgentRunRequest(agent: ${swiftString(agentRef)}, input: LLMInput(text: "Hello!"))
|
|
1053
|
+
for try await message in client.runAgentStream(request) {
|
|
1054
|
+
if message.status.isTerminal {
|
|
1055
|
+
print(message.text)
|
|
1056
|
+
break
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
// chat session: keeps the conversation and follows its stream
|
|
1061
|
+
// (AgentChatSession is @MainActor)
|
|
1062
|
+
let session = AgentChatSession(client: client, agent: ${swiftString(agentRef)})
|
|
1063
|
+
|
|
1064
|
+
session.onChange = { state in
|
|
1065
|
+
// every state change: messages, chat status, connection, errors
|
|
1066
|
+
if let last = state.messages.last {
|
|
1067
|
+
print(last.role.rawValue, last.text)
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
session.callbacks.onTurnEnd = { chat in
|
|
1071
|
+
print("Chat ID:", chat.id)
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
// send a message
|
|
1075
|
+
await session.sendMessage("Help me with something")
|
|
1076
|
+
|
|
1077
|
+
// tool calls that need the user wait in message.toolInvocations:
|
|
1078
|
+
// try await session.approveTool(invocation.id)
|
|
1079
|
+
// try await session.submitToolResult(invocation.id, result: resultJSON)
|
|
1080
|
+
|
|
1081
|
+
// stop generation
|
|
1082
|
+
session.stopGeneration()
|
|
1083
|
+
|
|
1084
|
+
// start fresh conversation
|
|
1085
|
+
session.reset()`;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
/**
|
|
1089
|
+
* Generate cURL Agent example
|
|
1090
|
+
*/
|
|
1091
|
+
export function generateAgentCurlExample(params: AgentExampleParams): string {
|
|
1092
|
+
const { agentRef, shortVersionId } = params;
|
|
1093
|
+
|
|
1094
|
+
const versionComment = shortVersionId
|
|
1095
|
+
? `# Using pinned version @${shortVersionId} (recommended for production)`
|
|
1096
|
+
: `# Using latest version (add version_id for production stability)`;
|
|
1097
|
+
|
|
1098
|
+
return `${versionComment}
|
|
1099
|
+
# send a message with streaming
|
|
1100
|
+
curl -N -X POST \\
|
|
1101
|
+
-H "Authorization: Bearer $INFERENCE_API_KEY" \\
|
|
1102
|
+
-H "Content-Type: application/json" \\
|
|
1103
|
+
-d '{
|
|
1104
|
+
"agent": "${agentRef}",
|
|
1105
|
+
"input": {"text": "Hello!", "role": "user"},
|
|
1106
|
+
"stream": true
|
|
1107
|
+
}' \\
|
|
1108
|
+
https://api.inference.sh/agents/run
|
|
1109
|
+
|
|
1110
|
+
# without streaming (returns JSON with chat_id)
|
|
1111
|
+
curl -X POST \\
|
|
1112
|
+
-H "Authorization: Bearer $INFERENCE_API_KEY" \\
|
|
1113
|
+
-H "Content-Type: application/json" \\
|
|
1114
|
+
-d '{
|
|
1115
|
+
"agent": "${agentRef}",
|
|
1116
|
+
"input": {"text": "Hello!", "role": "user"}
|
|
1117
|
+
}' \\
|
|
1118
|
+
https://api.inference.sh/agents/run
|
|
1119
|
+
|
|
1120
|
+
# continue conversation (use chat_id from previous response)
|
|
1121
|
+
curl -N -X POST \\
|
|
1122
|
+
-H "Authorization: Bearer $INFERENCE_API_KEY" \\
|
|
1123
|
+
-H "Content-Type: application/json" \\
|
|
1124
|
+
-d '{
|
|
1125
|
+
"agent": "${agentRef}",
|
|
1126
|
+
"chat_id": "CHAT_ID",
|
|
1127
|
+
"input": {"text": "Tell me more", "role": "user"},
|
|
1128
|
+
"stream": true
|
|
1129
|
+
}' \\
|
|
1130
|
+
https://api.inference.sh/agents/run
|
|
1131
|
+
|
|
1132
|
+
# stop generation
|
|
1133
|
+
curl -X POST \\
|
|
1134
|
+
-H "Authorization: Bearer $INFERENCE_API_KEY" \\
|
|
1135
|
+
https://api.inference.sh/chats/CHAT_ID/stop`;
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
/**
|
|
1139
|
+
* Generate all agent examples
|
|
1140
|
+
*/
|
|
1141
|
+
export function generateAllAgentExamples(params: AgentExampleParams): Record<string, string> {
|
|
1142
|
+
return {
|
|
1143
|
+
python: generateAgentPythonExample(params),
|
|
1144
|
+
typescript: generateAgentTypeScriptExample(params),
|
|
1145
|
+
javascript: generateAgentJavaScriptExample(params),
|
|
1146
|
+
swift: generateAgentSwiftExample(params),
|
|
1147
|
+
curl: generateAgentCurlExample(params),
|
|
1148
|
+
};
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
// Re-export guide markdown generator
|
|
1152
|
+
export { generateGuideMarkdown } from './guide-markdown'
|
|
1153
|
+
export type { GuideApp, GuideVersion, GuideLanguage } from './guide-markdown'
|