@proveanything/smartlinks 2.0.5 → 2.0.9
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/dist/api/ai.d.ts +1 -1
- package/dist/api/ai.js +1 -1
- package/dist/api/analytics.d.ts +1 -1
- package/dist/api/analytics.js +1 -1
- package/dist/api/appConfiguration.d.ts +3 -3
- package/dist/api/appConfiguration.js +3 -3
- package/dist/api/appObjects.d.ts +1 -1
- package/dist/api/appObjects.js +1 -1
- package/dist/api/asset.d.ts +1 -1
- package/dist/api/asset.js +2 -2
- package/dist/api/async.d.ts +1 -1
- package/dist/api/async.js +1 -1
- package/dist/api/attestation.d.ts +1 -1
- package/dist/api/attestation.js +1 -1
- package/dist/api/attestations.d.ts +1 -1
- package/dist/api/attestations.js +1 -1
- package/dist/api/auth.d.ts +2 -2
- package/dist/api/auth.js +2 -2
- package/dist/api/authKit.d.ts +1 -1
- package/dist/api/authKit.js +1 -1
- package/dist/api/batch.d.ts +1 -1
- package/dist/api/batch.js +1 -1
- package/dist/api/broadcasts.d.ts +2 -2
- package/dist/api/broadcasts.js +1 -1
- package/dist/api/claimSet.d.ts +1 -1
- package/dist/api/claimSet.js +1 -1
- package/dist/api/collection.d.ts +1 -1
- package/dist/api/collection.js +1 -1
- package/dist/api/comms.d.ts +15 -15
- package/dist/api/comms.js +1 -1
- package/dist/api/config.d.ts +1 -1
- package/dist/api/config.js +1 -1
- package/dist/api/contact.d.ts +1 -1
- package/dist/api/contact.js +1 -1
- package/dist/api/containers.d.ts +1 -1
- package/dist/api/containers.js +1 -1
- package/dist/api/crate.d.ts +1 -1
- package/dist/api/crate.js +1 -1
- package/dist/api/facets.d.ts +1 -1
- package/dist/api/facets.js +1 -1
- package/dist/api/form.js +1 -1
- package/dist/api/http.js +1 -1
- package/dist/api/index.d.ts +46 -46
- package/dist/api/index.js +46 -46
- package/dist/api/integrations.d.ts +1 -1
- package/dist/api/integrations.js +1 -1
- package/dist/api/interactions.d.ts +1 -1
- package/dist/api/interactions.js +1 -1
- package/dist/api/jobs.d.ts +1 -1
- package/dist/api/jobs.js +1 -1
- package/dist/api/journeys.d.ts +1 -1
- package/dist/api/journeys.js +1 -1
- package/dist/api/journeysAnalytics.d.ts +1 -1
- package/dist/api/journeysAnalytics.js +1 -1
- package/dist/api/location.d.ts +1 -1
- package/dist/api/location.js +1 -1
- package/dist/api/lots.d.ts +1 -1
- package/dist/api/lots.js +1 -1
- package/dist/api/loyalty.d.ts +1 -1
- package/dist/api/loyalty.js +1 -1
- package/dist/api/navigation.d.ts +1 -1
- package/dist/api/navigation.js +1 -1
- package/dist/api/nfc.d.ts +1 -1
- package/dist/api/nfc.js +1 -1
- package/dist/api/order.d.ts +1 -1
- package/dist/api/order.js +1 -1
- package/dist/api/product.d.ts +1 -1
- package/dist/api/product.js +1 -1
- package/dist/api/products.d.ts +1 -1
- package/dist/api/products.js +1 -1
- package/dist/api/proof.d.ts +1 -1
- package/dist/api/proof.js +1 -1
- package/dist/api/qr.d.ts +1 -1
- package/dist/api/qr.js +1 -1
- package/dist/api/realtime.d.ts +1 -1
- package/dist/api/realtime.js +1 -1
- package/dist/api/research.d.ts +1 -1
- package/dist/api/research.js +1 -1
- package/dist/api/secrets.d.ts +1 -1
- package/dist/api/secrets.js +1 -1
- package/dist/api/segments.d.ts +1 -1
- package/dist/api/segments.js +1 -1
- package/dist/api/sequence.js +1 -1
- package/dist/api/tags.d.ts +1 -1
- package/dist/api/tags.js +1 -1
- package/dist/api/template.d.ts +1 -1
- package/dist/api/template.js +1 -1
- package/dist/api/translations.d.ts +1 -1
- package/dist/api/translations.js +2 -2
- package/dist/api/variant.d.ts +1 -1
- package/dist/api/variant.js +1 -1
- package/dist/containers/types.d.ts +1 -1
- package/dist/docs/API_SUMMARY.md +7 -7
- package/dist/docs/agent-tools.md +111 -0
- package/dist/docs/ai.md +14 -520
- package/dist/docs/analytics.md +41 -2
- package/dist/docs/app-data-storage.md +0 -38
- package/dist/docs/app-manifest.md +104 -7
- package/dist/docs/app-objects.md +0 -148
- package/dist/docs/app-records-pattern.md +2 -2
- package/dist/docs/building-react-components.md +6 -14
- package/dist/docs/caching.md +20 -21
- package/dist/docs/container-tracking.md +2 -0
- package/dist/docs/containers.md +14 -66
- package/dist/docs/deploying-apps.md +8 -3
- package/dist/docs/executor.md +4 -4
- package/dist/docs/host-dependency-contract.md +159 -0
- package/dist/docs/iframe-responder.md +308 -0
- package/dist/docs/item-context.md +0 -2
- package/dist/docs/manifests.md +3 -3
- package/dist/docs/mobile-admin-container.md +4 -4
- package/dist/docs/mpa.md +5 -5
- package/dist/docs/native-facade.md +1 -1
- package/dist/docs/overview.md +36 -15
- package/dist/docs/portal-back-button.md +2 -3
- package/dist/docs/sequences.md +1 -1
- package/dist/docs/server-functions.md +2 -3
- package/dist/docs/widgets.md +11 -69
- package/dist/http.d.ts +24 -8
- package/dist/http.js +32 -14
- package/dist/iframe.d.ts +2 -2
- package/dist/iframe.js +1 -1
- package/dist/iframeResponder.d.ts +7 -1
- package/dist/iframeResponder.js +45 -4
- package/dist/index.d.ts +30 -27
- package/dist/index.js +10 -8
- package/dist/mobile-admin/errors.d.ts +1 -1
- package/dist/mobile-admin/types.d.ts +2 -2
- package/dist/openapi.yaml +12 -0
- package/dist/shared-dependencies.d.ts +37 -0
- package/dist/shared-dependencies.js +79 -0
- package/dist/testing/index.d.ts +1 -1
- package/dist/translationCache.d.ts +1 -1
- package/dist/types/appManifest.d.ts +23 -0
- package/dist/types/broadcasts.d.ts +1 -1
- package/dist/types/collection.d.ts +2 -2
- package/dist/types/comms.d.ts +5 -5
- package/dist/types/contact.d.ts +1 -1
- package/dist/types/facets.d.ts +1 -1
- package/dist/types/iframeResponder.d.ts +3 -3
- package/dist/types/index.d.ts +44 -44
- package/dist/types/index.js +44 -44
- package/dist/types/interaction.d.ts +1 -1
- package/dist/types/itemContext.d.ts +1 -1
- package/dist/types/journeysAnalytics.d.ts +1 -1
- package/dist/types/navigation.d.ts +1 -1
- package/dist/types/product.d.ts +1 -1
- package/dist/types/proof.d.ts +1 -1
- package/dist/types/segments.d.ts +1 -1
- package/dist/types/widgets.d.ts +2 -2
- package/dist/utils/conditions.d.ts +1 -1
- package/dist/utils/index.d.ts +3 -3
- package/dist/utils/index.js +3 -3
- package/dist/utils/paths.d.ts +4 -4
- package/docs/API_SUMMARY.md +7 -7
- package/docs/agent-tools.md +111 -0
- package/docs/ai.md +14 -520
- package/docs/analytics.md +41 -2
- package/docs/app-data-storage.md +0 -38
- package/docs/app-manifest.md +104 -7
- package/docs/app-objects.md +0 -148
- package/docs/app-records-pattern.md +2 -2
- package/docs/building-react-components.md +6 -14
- package/docs/caching.md +20 -21
- package/docs/container-tracking.md +2 -0
- package/docs/containers.md +14 -66
- package/docs/deploying-apps.md +8 -3
- package/docs/executor.md +4 -4
- package/docs/host-dependency-contract.md +159 -0
- package/docs/iframe-responder.md +308 -0
- package/docs/item-context.md +0 -2
- package/docs/mobile-admin-container.md +4 -4
- package/docs/mpa.md +5 -5
- package/docs/native-facade.md +1 -1
- package/docs/overview.md +36 -15
- package/docs/portal-back-button.md +2 -3
- package/docs/sequences.md +1 -1
- package/docs/server-functions.md +2 -3
- package/docs/widgets.md +11 -69
- package/openapi.yaml +12 -0
- package/package.json +17 -6
- package/scripts/doctor.mjs +171 -0
- package/docs/analytics-metadata-conventions.md +0 -88
- package/docs/iframe-streaming-parent-changes.md +0 -308
- package/docs/manifests.md +0 -204
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Agent tools — exposing your app's actions to the SmartLinks agent
|
|
2
|
+
|
|
3
|
+
> **SmartLinks SDK 2.x.** Redraft of the earlier "Agent Skills & Tools" RFC, now built on
|
|
4
|
+
> [server functions](server-functions.md). **Staged rollout:** the *declaration + discovery* ship in
|
|
5
|
+
> V2 (do them now); the *live agent loop* (a parent chat agent calling your tools) lights up when the
|
|
6
|
+
> platform agent can consume them. Everything you declare is useful before then — a tool is a server
|
|
7
|
+
> function, already invocable via http/event.
|
|
8
|
+
|
|
9
|
+
## The model: app-authored capabilities
|
|
10
|
+
|
|
11
|
+
An app declares **capabilities** — app-authored logic the platform runs, each with a declared
|
|
12
|
+
security envelope (`visibility` / `authority` / `capabilities`). There is **one engine** (the
|
|
13
|
+
server-functions runtime) and several **triggers** into it: `http`, `event`, `cron`, and **`agent`**.
|
|
14
|
+
|
|
15
|
+
**An agent tool is not a new runtime — it's an MCP-shaped facade over a capability.** By default a
|
|
16
|
+
tool *is a server function*: the agent's `tools/call` routes into the same `(ctx, event) => result`
|
|
17
|
+
with the same capability envelope. You author the logic once; the agent is just another caller.
|
|
18
|
+
|
|
19
|
+
Use a **client tool** (a `postMessage` handler in your live admin iframe) only for genuinely
|
|
20
|
+
UI-coupled actions that must run in the open app. It is **not** the default — headless server
|
|
21
|
+
functions are, because they work whether or not your UI is mounted.
|
|
22
|
+
|
|
23
|
+
## Declaring a tool
|
|
24
|
+
|
|
25
|
+
You already declare server functions in `app.manifest.json` (see
|
|
26
|
+
[server-functions.md](server-functions.md)). Mark one **agent-invocable** and give the agent what it
|
|
27
|
+
needs to call it — a description and an input schema:
|
|
28
|
+
|
|
29
|
+
```jsonc
|
|
30
|
+
{
|
|
31
|
+
"functions": {
|
|
32
|
+
"files": { "js": { "umd": "dist/functions.umd.js" } },
|
|
33
|
+
"definitions": [
|
|
34
|
+
{
|
|
35
|
+
"name": "createFaq",
|
|
36
|
+
"trigger": { "type": "http", "methods": ["POST"] },
|
|
37
|
+
"visibility": "admin",
|
|
38
|
+
"authority": "collection",
|
|
39
|
+
"capabilities": ["sl:records:write"],
|
|
40
|
+
|
|
41
|
+
// ── makes it an agent tool ──
|
|
42
|
+
"agent": {
|
|
43
|
+
"tool": true,
|
|
44
|
+
"title": "Create an FAQ entry",
|
|
45
|
+
"description": "Add a question/answer to this collection's FAQ. Use when the user asks to add or draft an FAQ.",
|
|
46
|
+
"input": { /* JSON Schema for the arguments the agent supplies as event.body */ },
|
|
47
|
+
"approval": "auto" // auto | require (require = human confirmation before the call)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The handler is an ordinary server function — the agent-supplied arguments arrive as `event.body`:
|
|
56
|
+
|
|
57
|
+
```js
|
|
58
|
+
export async function createFaq(ctx, event) {
|
|
59
|
+
const { question, answer } = event.body || {}
|
|
60
|
+
// validate, then act with your declared authority/capabilities:
|
|
61
|
+
const rec = await ctx.sl.appRecords.create({ recordType: 'faq', data: { question, answer } })
|
|
62
|
+
return { id: rec.id }
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## What the agent sees (MCP shape)
|
|
67
|
+
|
|
68
|
+
The platform derives an **MCP tool list** from your manifest and drives the standard flow — `tools/list`
|
|
69
|
+
→ `tools/call` → structured result — with streaming, cancellation, and approval layered on. You don't
|
|
70
|
+
implement the wire protocol; you declare tools and write handlers. (The live loop is the staged part.)
|
|
71
|
+
|
|
72
|
+
## Security
|
|
73
|
+
|
|
74
|
+
Identical to server functions — nothing new to reason about:
|
|
75
|
+
- **`visibility`** — who may call (admin/public).
|
|
76
|
+
- **`authority`** — whose identity `ctx.sl` carries (`caller` vs `collection`).
|
|
77
|
+
- **`capabilities`** — least-privilege, capped even when elevated.
|
|
78
|
+
- **`agent.approval: "require"`** — the agent must get human confirmation before invoking (use for
|
|
79
|
+
destructive or public-facing actions).
|
|
80
|
+
|
|
81
|
+
Untrusted third-party tools run in the platform's isolated runner — the same boundary as untrusted
|
|
82
|
+
server functions.
|
|
83
|
+
|
|
84
|
+
## Replacing `app.admin.json` AI setup
|
|
85
|
+
|
|
86
|
+
This supersedes the `app.admin.json` "AI setup" schema-extraction model (the outer agent reading a
|
|
87
|
+
schema and handing back JSON blobs). Instead the app owns its domain logic and exposes **real,
|
|
88
|
+
capability-scoped actions** the agent invokes — with multi-turn and streaming. The AI-schema path is
|
|
89
|
+
**deprecated as of V2** (still works through the V2 line; removed later).
|
|
90
|
+
|
|
91
|
+
## What ships now vs staged
|
|
92
|
+
|
|
93
|
+
| Now (V2) | Staged (on the platform agent) |
|
|
94
|
+
|---|---|
|
|
95
|
+
| The `agent` declaration in the manifest | The live agent conversation calling your tools |
|
|
96
|
+
| SDK types for it; tool descriptors surfaced for discovery | `tools/call` streaming, cancellation, cross-app toolbelt arbitration |
|
|
97
|
+
| Your handlers run today via http/event | Human-approval UX for `approval: "require"` |
|
|
98
|
+
|
|
99
|
+
## Adopting this in an existing app
|
|
100
|
+
|
|
101
|
+
Do it in order — each step is a drop-in migration prompt (see the migration steps that ship with the
|
|
102
|
+
SDK). Roughly:
|
|
103
|
+
|
|
104
|
+
1. **Server functions** — add the `functions` block + build target + test harness (if the app
|
|
105
|
+
doesn't have them). See [server-functions.md](server-functions.md).
|
|
106
|
+
2. **Expose tools** — add the `agent` block to the functions you want the agent to call; give each a
|
|
107
|
+
title/description/input schema and an approval mode.
|
|
108
|
+
3. **Retire `app.admin.json` AI setup** — move any AI-authoring behaviour to tools; drop the
|
|
109
|
+
AI-schema block.
|
|
110
|
+
|
|
111
|
+
Steps 1–2 are safe to ship now; step 3 as you migrate each app off the old AI path.
|
package/dist/docs/ai.md
CHANGED
|
@@ -14,8 +14,7 @@ Build AI-powered SmartLinks experiences with a practical SDK guide for responses
|
|
|
14
14
|
- [RAG: Product Assistants](#rag-product-assistants)
|
|
15
15
|
- [Voice Integration](#voice-integration)
|
|
16
16
|
- [Podcast Generation](#podcast-generation)
|
|
17
|
-
- [
|
|
18
|
-
- [API Reference](#api-reference)
|
|
17
|
+
- [Types & API reference](#types--api-reference)
|
|
19
18
|
- [Usage Examples](#usage-examples)
|
|
20
19
|
- [Error Handling](#error-handling)
|
|
21
20
|
- [Rate Limiting](#rate-limiting)
|
|
@@ -38,6 +37,13 @@ This guide is written for SDK users building real products, not backend operator
|
|
|
38
37
|
| Add spoken input/output | Use [Voice Integration](#voice-integration) |
|
|
39
38
|
| Add progressive rendering | Use [Streaming Responses](#streaming-responses) or [Streaming Chat](#streaming-chat) |
|
|
40
39
|
|
|
40
|
+
> **Which AI chat API? Three surfaces, three jobs — don't confuse them:**
|
|
41
|
+
> - **`ai.chat.responses`** — the **default for new work**. Structured input, tool use, multi-agent, streaming; you manage any history. Reach for this first.
|
|
42
|
+
> - **`ai.chat.completions`** — **OpenAI-compatible** (`messages[]`). Use it *only* to drop into existing OpenAI-style code; prefer Responses for anything new.
|
|
43
|
+
> - **`ai.public.chat`** (+ `getSession` / `clearSession`) — the **public product assistant** with **server-managed conversation sessions** (RAG-grounded). This is the "ongoing conversation" surface, and it's public-facing.
|
|
44
|
+
>
|
|
45
|
+
> Responses and Completions are *generation* APIs (not single-shot vs conversation — both take history); `ai.public.chat` is the one that keeps a conversation for you.
|
|
46
|
+
|
|
41
47
|
### Recommended starting points
|
|
42
48
|
|
|
43
49
|
- New AI features: start with `ai.chat.responses.create(...)`
|
|
@@ -845,426 +851,16 @@ const audioUrl = URL.createObjectURL(audioBlob);
|
|
|
845
851
|
|
|
846
852
|
---
|
|
847
853
|
|
|
848
|
-
## Type Definitions
|
|
849
|
-
|
|
850
|
-
### Core Types
|
|
851
|
-
|
|
852
|
-
```typescript
|
|
853
|
-
/**
|
|
854
|
-
* Chat message with role and content
|
|
855
|
-
*/
|
|
856
|
-
interface ChatMessage {
|
|
857
|
-
role: 'system' | 'user' | 'assistant' | 'function' | 'tool';
|
|
858
|
-
content: string | ContentPart[];
|
|
859
|
-
name?: string;
|
|
860
|
-
function_call?: FunctionCall;
|
|
861
|
-
tool_calls?: ToolCall[];
|
|
862
|
-
tool_call_id?: string;
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
/**
|
|
866
|
-
* Chat completion request
|
|
867
|
-
*/
|
|
868
|
-
interface ChatCompletionRequest {
|
|
869
|
-
messages: ChatMessage[];
|
|
870
|
-
model?: string;
|
|
871
|
-
stream?: boolean;
|
|
872
|
-
tools?: ToolDefinition[];
|
|
873
|
-
tool_choice?: 'none' | 'auto' | 'required' | { type: 'function'; function: { name: string } };
|
|
874
|
-
temperature?: number; // 0-2, default: 0.7
|
|
875
|
-
max_tokens?: number;
|
|
876
|
-
top_p?: number;
|
|
877
|
-
frequency_penalty?: number;
|
|
878
|
-
presence_penalty?: number;
|
|
879
|
-
response_format?: { type: 'text' | 'json_object' };
|
|
880
|
-
user?: string;
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
/**
|
|
884
|
-
* Chat completion response
|
|
885
|
-
*/
|
|
886
|
-
interface ChatCompletionResponse {
|
|
887
|
-
id: string;
|
|
888
|
-
object: 'chat.completion';
|
|
889
|
-
created: number;
|
|
890
|
-
model: string;
|
|
891
|
-
choices: ChatCompletionChoice[];
|
|
892
|
-
usage: {
|
|
893
|
-
prompt_tokens: number;
|
|
894
|
-
completion_tokens: number;
|
|
895
|
-
total_tokens: number;
|
|
896
|
-
};
|
|
897
|
-
}
|
|
898
|
-
|
|
899
|
-
/**
|
|
900
|
-
* Streaming chunk
|
|
901
|
-
*/
|
|
902
|
-
interface ChatCompletionChunk {
|
|
903
|
-
id: string;
|
|
904
|
-
object: 'chat.completion.chunk';
|
|
905
|
-
created: number;
|
|
906
|
-
model: string;
|
|
907
|
-
choices: Array<{
|
|
908
|
-
index: number;
|
|
909
|
-
delta: Partial<ChatMessage>;
|
|
910
|
-
finish_reason: string | null;
|
|
911
|
-
}>;
|
|
912
|
-
}
|
|
913
|
-
```
|
|
914
|
-
|
|
915
|
-
### RAG Types
|
|
916
|
-
|
|
917
|
-
```typescript
|
|
918
|
-
/**
|
|
919
|
-
* Index document request
|
|
920
|
-
*/
|
|
921
|
-
interface IndexDocumentRequest {
|
|
922
|
-
productId: string;
|
|
923
|
-
text?: string; // Either text or documentUrl required
|
|
924
|
-
documentUrl?: string;
|
|
925
|
-
metadata?: Record<string, any>;
|
|
926
|
-
chunkSize?: number; // Default: 500
|
|
927
|
-
overlap?: number; // Default: 50
|
|
928
|
-
provider?: 'openai' | 'gemini';
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
/**
|
|
932
|
-
* Configure assistant request
|
|
933
|
-
*/
|
|
934
|
-
interface ConfigureAssistantRequest {
|
|
935
|
-
productId: string;
|
|
936
|
-
systemPrompt?: string;
|
|
937
|
-
model?: string;
|
|
938
|
-
maxTokensPerResponse?: number;
|
|
939
|
-
temperature?: number;
|
|
940
|
-
rateLimitPerUser?: number;
|
|
941
|
-
allowedTopics?: string[];
|
|
942
|
-
customInstructions?: Record<string, any>;
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
/**
|
|
946
|
-
* Public chat request
|
|
947
|
-
*/
|
|
948
|
-
interface PublicChatRequest {
|
|
949
|
-
productId: string;
|
|
950
|
-
userId: string;
|
|
951
|
-
message: string;
|
|
952
|
-
sessionId?: string;
|
|
953
|
-
stream?: boolean;
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
/**
|
|
957
|
-
* Public chat response
|
|
958
|
-
*/
|
|
959
|
-
interface PublicChatResponse {
|
|
960
|
-
message: string;
|
|
961
|
-
sessionId: string;
|
|
962
|
-
usage: {
|
|
963
|
-
prompt_tokens: number;
|
|
964
|
-
completion_tokens: number;
|
|
965
|
-
total_tokens: number;
|
|
966
|
-
};
|
|
967
|
-
context?: {
|
|
968
|
-
chunksUsed: number;
|
|
969
|
-
topSimilarity: number;
|
|
970
|
-
};
|
|
971
|
-
}
|
|
972
|
-
```
|
|
973
|
-
|
|
974
|
-
### Podcast Types
|
|
975
|
-
|
|
976
|
-
```typescript
|
|
977
|
-
/**
|
|
978
|
-
* Podcast generation request
|
|
979
|
-
*/
|
|
980
|
-
interface GeneratePodcastRequest {
|
|
981
|
-
productId: string;
|
|
982
|
-
documentText?: string; // Optional if document already indexed
|
|
983
|
-
duration?: number; // Target duration in minutes (default: 10)
|
|
984
|
-
style?: 'casual' | 'professional' | 'educational' | 'entertaining';
|
|
985
|
-
voices?: {
|
|
986
|
-
host1?: string; // Voice name for first host
|
|
987
|
-
host2?: string; // Voice name for second host
|
|
988
|
-
};
|
|
989
|
-
includeAudio?: boolean; // Generate audio files (default: false)
|
|
990
|
-
language?: string; // Default: 'en-US'
|
|
991
|
-
customInstructions?: string;
|
|
992
|
-
}
|
|
993
|
-
|
|
994
|
-
/**
|
|
995
|
-
* Podcast script segment
|
|
996
|
-
*/
|
|
997
|
-
interface PodcastSegment {
|
|
998
|
-
speaker: 'host1' | 'host2';
|
|
999
|
-
text: string;
|
|
1000
|
-
timestamp?: number; // Start time in seconds
|
|
1001
|
-
duration?: number; // Segment duration
|
|
1002
|
-
}
|
|
1003
|
-
|
|
1004
|
-
/**
|
|
1005
|
-
* Podcast script
|
|
1006
|
-
*/
|
|
1007
|
-
interface PodcastScript {
|
|
1008
|
-
title: string;
|
|
1009
|
-
description: string;
|
|
1010
|
-
segments: PodcastSegment[];
|
|
1011
|
-
}
|
|
1012
|
-
|
|
1013
|
-
/**
|
|
1014
|
-
* Podcast generation response
|
|
1015
|
-
*/
|
|
1016
|
-
interface GeneratePodcastResponse {
|
|
1017
|
-
success: boolean;
|
|
1018
|
-
podcastId: string;
|
|
1019
|
-
script: PodcastScript;
|
|
1020
|
-
audio?: {
|
|
1021
|
-
host1Url?: string; // URL to download host 1 audio
|
|
1022
|
-
host2Url?: string; // URL to download host 2 audio
|
|
1023
|
-
mixedUrl?: string; // URL to download mixed podcast
|
|
1024
|
-
};
|
|
1025
|
-
metadata: {
|
|
1026
|
-
duration: number; // Actual duration in seconds
|
|
1027
|
-
wordCount: number;
|
|
1028
|
-
generatedAt: string;
|
|
1029
|
-
};
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
/**
|
|
1033
|
-
* Podcast status
|
|
1034
|
-
*/
|
|
1035
|
-
interface PodcastStatus {
|
|
1036
|
-
podcastId: string;
|
|
1037
|
-
status: 'generating_script' | 'generating_audio' | 'mixing' | 'completed' | 'failed';
|
|
1038
|
-
progress: number; // 0-100
|
|
1039
|
-
estimatedTimeRemaining?: number; // Seconds
|
|
1040
|
-
error?: string;
|
|
1041
|
-
result?: GeneratePodcastResponse; // Available when completed
|
|
1042
|
-
}
|
|
1043
|
-
|
|
1044
|
-
/**
|
|
1045
|
-
* TTS request
|
|
1046
|
-
*/
|
|
1047
|
-
interface TTSRequest {
|
|
1048
|
-
text: string;
|
|
1049
|
-
voice?: 'alloy' | 'echo' | 'fable' | 'onyx' | 'nova' | 'shimmer';
|
|
1050
|
-
speed?: number; // 0.25 - 4.0, default: 1.0
|
|
1051
|
-
format?: 'mp3' | 'opus' | 'aac' | 'flac'; // Default: mp3
|
|
1052
|
-
}
|
|
1053
|
-
```
|
|
1054
|
-
|
|
1055
|
-
### Error Types
|
|
1056
|
-
|
|
1057
|
-
```typescript
|
|
1058
|
-
/**
|
|
1059
|
-
* API Error response
|
|
1060
|
-
*/
|
|
1061
|
-
interface AIError {
|
|
1062
|
-
error: {
|
|
1063
|
-
message: string;
|
|
1064
|
-
type: string;
|
|
1065
|
-
code: string;
|
|
1066
|
-
param?: string;
|
|
1067
|
-
resetAt?: string; // ISO 8601 timestamp (for rate limits)
|
|
1068
|
-
};
|
|
1069
|
-
}
|
|
1070
|
-
|
|
1071
|
-
/**
|
|
1072
|
-
* Custom error class
|
|
1073
|
-
*/
|
|
1074
|
-
class SmartLinksAIError extends Error {
|
|
1075
|
-
type: string;
|
|
1076
|
-
code: string;
|
|
1077
|
-
statusCode: number;
|
|
1078
|
-
resetAt?: string;
|
|
1079
|
-
|
|
1080
|
-
isRateLimitError(): boolean;
|
|
1081
|
-
isAuthError(): boolean;
|
|
1082
|
-
isNotFoundError(): boolean;
|
|
1083
|
-
}
|
|
1084
|
-
```
|
|
1085
|
-
|
|
1086
|
-
---
|
|
1087
|
-
|
|
1088
|
-
## API Reference
|
|
1089
|
-
|
|
1090
|
-
### Admin Endpoints
|
|
1091
|
-
|
|
1092
|
-
#### `ai.chat.completions.create(collectionId, request)`
|
|
1093
|
-
|
|
1094
|
-
Create a chat completion (OpenAI-compatible).
|
|
1095
|
-
|
|
1096
|
-
**Parameters:**
|
|
1097
|
-
- `collectionId` (string) - Collection ID
|
|
1098
|
-
- `request` (ChatCompletionRequest) - Request parameters
|
|
1099
|
-
|
|
1100
|
-
**Returns:** `Promise<ChatCompletionResponse | AsyncIterable<ChatCompletionChunk>>`
|
|
1101
|
-
|
|
1102
|
-
**Example:**
|
|
1103
|
-
```typescript
|
|
1104
|
-
const response = await ai.chat.completions.create('my-collection', {
|
|
1105
|
-
model: 'google/gemini-2.5-flash',
|
|
1106
|
-
messages: [{ role: 'user', content: 'Hello!' }]
|
|
1107
|
-
});
|
|
1108
|
-
```
|
|
1109
|
-
|
|
1110
|
-
---
|
|
1111
|
-
|
|
1112
|
-
#### `ai.models.list(collectionId)`
|
|
1113
|
-
|
|
1114
|
-
List available AI models.
|
|
1115
|
-
|
|
1116
|
-
**Returns:** `Promise<ModelList>`
|
|
1117
|
-
|
|
1118
|
-
---
|
|
1119
|
-
|
|
1120
|
-
#### `ai.models.get(collectionId, modelId)`
|
|
1121
854
|
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
**Parameters:**
|
|
1125
|
-
- `modelId` (string) - Model identifier (e.g., 'google/gemini-2.5-flash')
|
|
1126
|
-
|
|
1127
|
-
**Returns:** `Promise<AIModel>`
|
|
1128
|
-
|
|
1129
|
-
---
|
|
1130
|
-
|
|
1131
|
-
#### `ai.rag.indexDocument(collectionId, request)`
|
|
1132
|
-
|
|
1133
|
-
Index a document for RAG.
|
|
1134
|
-
|
|
1135
|
-
**Parameters:**
|
|
1136
|
-
- `request` (IndexDocumentRequest) - Document and indexing parameters
|
|
1137
|
-
|
|
1138
|
-
**Returns:** `Promise<IndexDocumentResponse>`
|
|
1139
|
-
|
|
1140
|
-
---
|
|
1141
|
-
|
|
1142
|
-
#### `ai.rag.configureAssistant(collectionId, request)`
|
|
1143
|
-
|
|
1144
|
-
Configure AI assistant behavior.
|
|
1145
|
-
|
|
1146
|
-
**Parameters:**
|
|
1147
|
-
- `request` (ConfigureAssistantRequest) - Assistant configuration
|
|
1148
|
-
|
|
1149
|
-
**Returns:** `Promise<ConfigureAssistantResponse>`
|
|
1150
|
-
|
|
1151
|
-
---
|
|
1152
|
-
|
|
1153
|
-
#### `ai.sessions.stats(collectionId)`
|
|
1154
|
-
|
|
1155
|
-
Get session statistics.
|
|
1156
|
-
|
|
1157
|
-
**Returns:** `Promise<SessionStatistics>`
|
|
1158
|
-
|
|
1159
|
-
---
|
|
1160
|
-
|
|
1161
|
-
#### `ai.rateLimit.reset(collectionId, userId)`
|
|
1162
|
-
|
|
1163
|
-
Reset rate limit for a user.
|
|
1164
|
-
|
|
1165
|
-
**Returns:** `Promise<{ success: boolean; userId: string }>`
|
|
1166
|
-
|
|
1167
|
-
---
|
|
855
|
+
## Types & API reference
|
|
1168
856
|
|
|
1169
|
-
|
|
857
|
+
Full TypeScript types and the per-endpoint HTTP reference for every `SL.ai.*` method live in the
|
|
858
|
+
**generated** references — they're not duplicated here so they can't drift:
|
|
1170
859
|
|
|
1171
|
-
|
|
860
|
+
- **[`API_SUMMARY.md`](API_SUMMARY.md)** — every function signature + type (search `ai.`).
|
|
861
|
+
- **[`openapi.yaml`](../openapi.yaml)** — the raw HTTP endpoints.
|
|
1172
862
|
|
|
1173
|
-
|
|
1174
|
-
- `request` (GeneratePodcastRequest) - Podcast generation parameters
|
|
1175
|
-
|
|
1176
|
-
**Returns:** `Promise<GeneratePodcastResponse>`
|
|
1177
|
-
|
|
1178
|
-
**Example:**
|
|
1179
|
-
```typescript
|
|
1180
|
-
const podcast = await ai.podcast.generate('my-collection', {
|
|
1181
|
-
productId: 'coffee-maker-deluxe',
|
|
1182
|
-
duration: 5,
|
|
1183
|
-
style: 'casual',
|
|
1184
|
-
voices: { host1: 'nova', host2: 'onyx' },
|
|
1185
|
-
includeAudio: true
|
|
1186
|
-
});
|
|
1187
|
-
```
|
|
1188
|
-
|
|
1189
|
-
---
|
|
1190
|
-
|
|
1191
|
-
#### `ai.podcast.getStatus(collectionId, podcastId)`
|
|
1192
|
-
|
|
1193
|
-
Get podcast generation status.
|
|
1194
|
-
|
|
1195
|
-
**Parameters:**
|
|
1196
|
-
- `podcastId` (string) - Podcast identifier
|
|
1197
|
-
|
|
1198
|
-
**Returns:** `Promise<PodcastStatus>`
|
|
1199
|
-
|
|
1200
|
-
---
|
|
1201
|
-
|
|
1202
|
-
#### `ai.tts.generate(collectionId, request)`
|
|
1203
|
-
|
|
1204
|
-
Generate text-to-speech audio.
|
|
1205
|
-
|
|
1206
|
-
**Parameters:**
|
|
1207
|
-
- `request` (TTSRequest) - TTS parameters
|
|
1208
|
-
|
|
1209
|
-
**Returns:** `Promise<Blob>`
|
|
1210
|
-
|
|
1211
|
-
**Example:**
|
|
1212
|
-
```typescript
|
|
1213
|
-
const audioBlob = await ai.tts.generate('my-collection', {
|
|
1214
|
-
text: 'Welcome to our podcast!',
|
|
1215
|
-
voice: 'nova',
|
|
1216
|
-
speed: 1.0
|
|
1217
|
-
});
|
|
1218
|
-
```
|
|
1219
|
-
|
|
1220
|
-
---
|
|
1221
|
-
|
|
1222
|
-
### Public Endpoints
|
|
1223
|
-
|
|
1224
|
-
#### `ai.public.chat(collectionId, request)`
|
|
1225
|
-
|
|
1226
|
-
Chat with product assistant (no auth required).
|
|
1227
|
-
|
|
1228
|
-
**Parameters:**
|
|
1229
|
-
- `request` (PublicChatRequest) - Chat parameters
|
|
1230
|
-
|
|
1231
|
-
**Returns:** `Promise<PublicChatResponse>`
|
|
1232
|
-
|
|
1233
|
-
**Rate Limited:** Yes (20 requests/hour per userId by default)
|
|
1234
|
-
|
|
1235
|
-
---
|
|
1236
|
-
|
|
1237
|
-
#### `ai.public.getSession(collectionId, sessionId)`
|
|
1238
|
-
|
|
1239
|
-
Get conversation history.
|
|
1240
|
-
|
|
1241
|
-
**Returns:** `Promise<Session>`
|
|
1242
|
-
|
|
1243
|
-
---
|
|
1244
|
-
|
|
1245
|
-
#### `ai.public.clearSession(collectionId, sessionId)`
|
|
1246
|
-
|
|
1247
|
-
Clear conversation history.
|
|
1248
|
-
|
|
1249
|
-
**Returns:** `Promise<{ success: boolean }>`
|
|
1250
|
-
|
|
1251
|
-
---
|
|
1252
|
-
|
|
1253
|
-
#### `ai.public.getRateLimit(collectionId, userId)`
|
|
1254
|
-
|
|
1255
|
-
Check rate limit status.
|
|
1256
|
-
|
|
1257
|
-
**Returns:** `Promise<RateLimitStatus>`
|
|
1258
|
-
|
|
1259
|
-
---
|
|
1260
|
-
|
|
1261
|
-
#### `ai.public.getToken(collectionId, request)`
|
|
1262
|
-
|
|
1263
|
-
Generate ephemeral token for Gemini Live.
|
|
1264
|
-
|
|
1265
|
-
**Returns:** `Promise<EphemeralTokenResponse>`
|
|
1266
|
-
|
|
1267
|
-
---
|
|
863
|
+
For inline types, use LSP hover / go-to-definition on `SL.ai.*`.
|
|
1268
864
|
|
|
1269
865
|
## Usage Examples
|
|
1270
866
|
|
|
@@ -1428,108 +1024,6 @@ function ProductHelp() {
|
|
|
1428
1024
|
}
|
|
1429
1025
|
```
|
|
1430
1026
|
|
|
1431
|
-
### Example 5: Voice Q&A
|
|
1432
|
-
|
|
1433
|
-
```typescript
|
|
1434
|
-
async function voiceQA() {
|
|
1435
|
-
if (!ai.voice.isSupported()) {
|
|
1436
|
-
console.error('Voice not supported in this browser');
|
|
1437
|
-
return;
|
|
1438
|
-
}
|
|
1439
|
-
|
|
1440
|
-
console.log('Speak your question...');
|
|
1441
|
-
|
|
1442
|
-
// Listen for voice input
|
|
1443
|
-
const question = await ai.voice.listen('en-US');
|
|
1444
|
-
console.log('You asked:', question);
|
|
1445
|
-
|
|
1446
|
-
// Get answer from AI
|
|
1447
|
-
const response = await ai.public.chat('my-collection', {
|
|
1448
|
-
productId: 'coffee-maker-deluxe',
|
|
1449
|
-
userId: 'user-123',
|
|
1450
|
-
message: question
|
|
1451
|
-
});
|
|
1452
|
-
|
|
1453
|
-
// Display answer
|
|
1454
|
-
console.log('Answer:', response.message);
|
|
1455
|
-
|
|
1456
|
-
// Speak answer
|
|
1457
|
-
await ai.voice.speak(response.message);
|
|
1458
|
-
}
|
|
1459
|
-
```
|
|
1460
|
-
|
|
1461
|
-
### Example 6: Generate Product Podcast
|
|
1462
|
-
|
|
1463
|
-
```typescript
|
|
1464
|
-
async function generateProductPodcast() {
|
|
1465
|
-
// Generate a casual 5-minute podcast about the coffee maker
|
|
1466
|
-
const podcast = await ai.podcast.generate('my-collection', {
|
|
1467
|
-
productId: 'coffee-maker-deluxe',
|
|
1468
|
-
duration: 5, // minutes
|
|
1469
|
-
style: 'casual', // Conversational style
|
|
1470
|
-
voices: {
|
|
1471
|
-
host1: 'nova', // Female voice
|
|
1472
|
-
host2: 'onyx' // Male voice
|
|
1473
|
-
},
|
|
1474
|
-
includeAudio: true
|
|
1475
|
-
});
|
|
1476
|
-
|
|
1477
|
-
console.log('Podcast Title:', podcast.script.title);
|
|
1478
|
-
console.log('Duration:', podcast.metadata.duration, 'seconds');
|
|
1479
|
-
|
|
1480
|
-
// Display script
|
|
1481
|
-
console.log('\nScript:');
|
|
1482
|
-
podcast.script.segments.forEach((segment, i) => {
|
|
1483
|
-
const speaker = segment.speaker === 'host1' ? 'Host 1' : 'Host 2';
|
|
1484
|
-
console.log(`\n${speaker}: ${segment.text}`);
|
|
1485
|
-
});
|
|
1486
|
-
|
|
1487
|
-
// Download audio
|
|
1488
|
-
if (podcast.audio?.mixedUrl) {
|
|
1489
|
-
console.log('\nDownload podcast:', podcast.audio.mixedUrl);
|
|
1490
|
-
}
|
|
1491
|
-
}
|
|
1492
|
-
```
|
|
1493
|
-
|
|
1494
|
-
### Example 7: Podcast with Progress Tracking
|
|
1495
|
-
|
|
1496
|
-
```typescript
|
|
1497
|
-
async function generatePodcastWithProgress() {
|
|
1498
|
-
// Start podcast generation
|
|
1499
|
-
const podcast = await ai.podcast.generate('my-collection', {
|
|
1500
|
-
productId: 'coffee-maker-deluxe',
|
|
1501
|
-
duration: 10,
|
|
1502
|
-
style: 'professional',
|
|
1503
|
-
includeAudio: true
|
|
1504
|
-
});
|
|
1505
|
-
|
|
1506
|
-
const podcastId = podcast.podcastId;
|
|
1507
|
-
|
|
1508
|
-
// Poll for status
|
|
1509
|
-
const checkStatus = async () => {
|
|
1510
|
-
const status = await ai.podcast.getStatus('my-collection', podcastId);
|
|
1511
|
-
|
|
1512
|
-
console.log(`Status: ${status.status} (${status.progress}%)`);
|
|
1513
|
-
|
|
1514
|
-
if (status.status === 'completed' && status.result) {
|
|
1515
|
-
console.log('Podcast ready!');
|
|
1516
|
-
console.log('Listen:', status.result.audio?.mixedUrl);
|
|
1517
|
-
return true;
|
|
1518
|
-
} else if (status.status === 'failed') {
|
|
1519
|
-
console.error('Generation failed:', status.error);
|
|
1520
|
-
return true;
|
|
1521
|
-
}
|
|
1522
|
-
|
|
1523
|
-
return false;
|
|
1524
|
-
};
|
|
1525
|
-
|
|
1526
|
-
// Check every 5 seconds
|
|
1527
|
-
const interval = setInterval(async () => {
|
|
1528
|
-
const done = await checkStatus();
|
|
1529
|
-
if (done) clearInterval(interval);
|
|
1530
|
-
}, 5000);
|
|
1531
|
-
}
|
|
1532
|
-
```
|
|
1533
1027
|
|
|
1534
1028
|
---
|
|
1535
1029
|
|