@21st-sdk/nextjs 0.0.9 → 0.0.10
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 +1 -1
- package/README.md +13 -13
- package/dist/server.cjs +4 -1
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +3 -2
- package/dist/server.d.ts +3 -2
- package/dist/server.js +3 -1
- package/dist/server.js.map +1 -1
- package/docs/02-getting-started.md +8 -8
- package/docs/04-react-ui.md +13 -13
- package/docs/05-nextjs.md +15 -15
- package/docs/06-node-sdk.md +8 -8
- package/docs/07-cli.md +1 -1
- package/docs/08-custom-tools.md +2 -2
- package/package.json +5 -5
- package/src/server.ts +4 -1
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @21st-sdk/nextjs
|
|
2
2
|
|
|
3
|
-
Next.js integration for [
|
|
3
|
+
Next.js integration for [21st Agents](https://21st.dev/agents) AI agent chat. Provides a server-side token handler so your API key never reaches the client.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -14,19 +14,19 @@ npm install @21st-sdk/nextjs @21st-sdk/react ai @ai-sdk/react
|
|
|
14
14
|
|
|
15
15
|
```env
|
|
16
16
|
# .env.local
|
|
17
|
-
|
|
17
|
+
API_KEY_21ST=an_sk_your_key_here
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
Get your API key from [the
|
|
20
|
+
Get your API key from [the API keys page](https://21st.dev/agents/api-keys).
|
|
21
21
|
|
|
22
22
|
### 2. Create the token route (one line)
|
|
23
23
|
|
|
24
24
|
```ts
|
|
25
|
-
// app/api/
|
|
26
|
-
import {
|
|
25
|
+
// app/api/agent/token/route.ts
|
|
26
|
+
import { createTokenHandler } from "@21st-sdk/nextjs/server"
|
|
27
27
|
|
|
28
|
-
export const POST =
|
|
29
|
-
apiKey: process.env.
|
|
28
|
+
export const POST = createTokenHandler({
|
|
29
|
+
apiKey: process.env.API_KEY_21ST!,
|
|
30
30
|
})
|
|
31
31
|
```
|
|
32
32
|
|
|
@@ -37,15 +37,15 @@ export const POST = createAnTokenHandler({
|
|
|
37
37
|
"use client"
|
|
38
38
|
|
|
39
39
|
import { useChat } from "@ai-sdk/react"
|
|
40
|
-
import {
|
|
40
|
+
import { AgentChat, createAgentChat } from "@21st-sdk/nextjs"
|
|
41
41
|
import "@21st-sdk/react/styles.css"
|
|
42
42
|
import { useMemo } from "react"
|
|
43
43
|
|
|
44
44
|
export default function Chat() {
|
|
45
45
|
const chat = useMemo(
|
|
46
|
-
() =>
|
|
46
|
+
() => createAgentChat({
|
|
47
47
|
agent: "your-agent-slug",
|
|
48
|
-
tokenUrl: "/api/
|
|
48
|
+
tokenUrl: "/api/agent/token",
|
|
49
49
|
}),
|
|
50
50
|
[],
|
|
51
51
|
)
|
|
@@ -53,7 +53,7 @@ export default function Chat() {
|
|
|
53
53
|
const { messages, sendMessage, status, stop, error } = useChat({ chat })
|
|
54
54
|
|
|
55
55
|
return (
|
|
56
|
-
<
|
|
56
|
+
<AgentChat
|
|
57
57
|
messages={messages}
|
|
58
58
|
onSend={(msg) =>
|
|
59
59
|
sendMessage({ parts: [{ type: "text", text: msg.content }] })
|
|
@@ -71,9 +71,9 @@ That's it. Your `an_sk_` API key stays on the server. The client only receives s
|
|
|
71
71
|
## How It Works
|
|
72
72
|
|
|
73
73
|
```
|
|
74
|
-
Browser Your Next.js Server
|
|
74
|
+
Browser Your Next.js Server Relay
|
|
75
75
|
| | |
|
|
76
|
-
|-- POST /api/
|
|
76
|
+
|-- POST /api/agent/token ------>| |
|
|
77
77
|
| |-- POST /v1/tokens -------->|
|
|
78
78
|
| | (with an_sk_ key) |
|
|
79
79
|
| |<-- { token, expiresAt } ---|
|
package/dist/server.cjs
CHANGED
|
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var server_exports = {};
|
|
22
22
|
__export(server_exports, {
|
|
23
23
|
createAnTokenHandler: () => createAnTokenHandler,
|
|
24
|
+
createTokenHandler: () => createTokenHandler,
|
|
24
25
|
exchangeToken: () => exchangeToken
|
|
25
26
|
});
|
|
26
27
|
module.exports = __toCommonJS(server_exports);
|
|
@@ -50,7 +51,7 @@ async function exchangeToken(options) {
|
|
|
50
51
|
}
|
|
51
52
|
return res.json();
|
|
52
53
|
}
|
|
53
|
-
function
|
|
54
|
+
function createTokenHandler(options) {
|
|
54
55
|
return async function POST(req) {
|
|
55
56
|
try {
|
|
56
57
|
const body = await req.json().catch(() => ({}));
|
|
@@ -63,9 +64,11 @@ function createAnTokenHandler(options) {
|
|
|
63
64
|
}
|
|
64
65
|
};
|
|
65
66
|
}
|
|
67
|
+
var createAnTokenHandler = createTokenHandler;
|
|
66
68
|
// Annotate the CommonJS export names for ESM import in node:
|
|
67
69
|
0 && (module.exports = {
|
|
68
70
|
createAnTokenHandler,
|
|
71
|
+
createTokenHandler,
|
|
69
72
|
exchangeToken
|
|
70
73
|
});
|
|
71
74
|
//# sourceMappingURL=server.cjs.map
|
package/dist/server.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts"],"sourcesContent":["export interface TokenHandlerOptions {\n /** Your an_sk_ API key — keep in process.env, never expose to client */\n apiKey: string\n /** Relay URL. Default: \"https://relay.an.dev\" */\n relayUrl?: string\n /** Token expiry. Default: \"1h\" */\n expiresIn?: string\n}\n\nexport interface ExchangeTokenOptions extends TokenHandlerOptions {\n /** Agent slug to scope the token to */\n agent?: string\n /** User identifier for the token */\n userId?: string\n}\n\n/** Exchange an an_sk_ API key for a short-lived JWT via the relay */\nexport async function exchangeToken(options: ExchangeTokenOptions) {\n const {\n apiKey,\n relayUrl = \"https://relay.an.dev\",\n expiresIn = \"1h\",\n agent,\n userId,\n } = options\n\n const res = await fetch(`${relayUrl}/v1/tokens`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n userId,\n agents: agent ? [agent] : undefined,\n expiresIn,\n }),\n })\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({ error: \"Failed to exchange token\" }))\n throw new Error(err.error || `Token exchange failed: ${res.status}`)\n }\n\n return res.json() as Promise<{ token: string; expiresAt: string }>\n}\n\n/** Create a Next.js API route handler that exchanges an_sk_ keys for JWTs */\nexport function
|
|
1
|
+
{"version":3,"sources":["../src/server.ts"],"sourcesContent":["export interface TokenHandlerOptions {\n /** Your an_sk_ API key — keep in process.env, never expose to client */\n apiKey: string\n /** Relay URL. Default: \"https://relay.an.dev\" */\n relayUrl?: string\n /** Token expiry. Default: \"1h\" */\n expiresIn?: string\n}\n\nexport interface ExchangeTokenOptions extends TokenHandlerOptions {\n /** Agent slug to scope the token to */\n agent?: string\n /** User identifier for the token */\n userId?: string\n}\n\n/** Exchange an an_sk_ API key for a short-lived JWT via the relay */\nexport async function exchangeToken(options: ExchangeTokenOptions) {\n const {\n apiKey,\n relayUrl = \"https://relay.an.dev\",\n expiresIn = \"1h\",\n agent,\n userId,\n } = options\n\n const res = await fetch(`${relayUrl}/v1/tokens`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n userId,\n agents: agent ? [agent] : undefined,\n expiresIn,\n }),\n })\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({ error: \"Failed to exchange token\" }))\n throw new Error(err.error || `Token exchange failed: ${res.status}`)\n }\n\n return res.json() as Promise<{ token: string; expiresAt: string }>\n}\n\n/** Create a Next.js API route handler that exchanges an_sk_ keys for JWTs */\nexport function createTokenHandler(options: TokenHandlerOptions) {\n return async function POST(req: Request) {\n try {\n const body = await req.json().catch(() => ({}))\n const { agent, userId } = body as { agent?: string; userId?: string }\n\n const data = await exchangeToken({ ...options, agent, userId })\n return Response.json(data)\n } catch (err) {\n const message = err instanceof Error ? err.message : \"Internal error\"\n return Response.json({ error: message }, { status: 500 })\n }\n }\n}\n\n// Legacy handler alias kept for compatibility.\nexport const createAnTokenHandler = createTokenHandler\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBA,eAAsB,cAAc,SAA+B;AACjE,QAAM;AAAA,IACJ;AAAA,IACA,WAAW;AAAA,IACX,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,QAAM,MAAM,MAAM,MAAM,GAAG,QAAQ,cAAc;AAAA,IAC/C,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,eAAe,UAAU,MAAM;AAAA,IACjC;AAAA,IACA,MAAM,KAAK,UAAU;AAAA,MACnB;AAAA,MACA,QAAQ,QAAQ,CAAC,KAAK,IAAI;AAAA,MAC1B;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AAED,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,MAAM,MAAM,IAAI,KAAK,EAAE,MAAM,OAAO,EAAE,OAAO,2BAA2B,EAAE;AAChF,UAAM,IAAI,MAAM,IAAI,SAAS,0BAA0B,IAAI,MAAM,EAAE;AAAA,EACrE;AAEA,SAAO,IAAI,KAAK;AAClB;AAGO,SAAS,mBAAmB,SAA8B;AAC/D,SAAO,eAAe,KAAK,KAAc;AACvC,QAAI;AACF,YAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAC9C,YAAM,EAAE,OAAO,OAAO,IAAI;AAE1B,YAAM,OAAO,MAAM,cAAc,EAAE,GAAG,SAAS,OAAO,OAAO,CAAC;AAC9D,aAAO,SAAS,KAAK,IAAI;AAAA,IAC3B,SAAS,KAAK;AACZ,YAAM,UAAU,eAAe,QAAQ,IAAI,UAAU;AACrD,aAAO,SAAS,KAAK,EAAE,OAAO,QAAQ,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC1D;AAAA,EACF;AACF;AAGO,IAAM,uBAAuB;","names":[]}
|
package/dist/server.d.cts
CHANGED
|
@@ -18,6 +18,7 @@ declare function exchangeToken(options: ExchangeTokenOptions): Promise<{
|
|
|
18
18
|
expiresAt: string;
|
|
19
19
|
}>;
|
|
20
20
|
/** Create a Next.js API route handler that exchanges an_sk_ keys for JWTs */
|
|
21
|
-
declare function
|
|
21
|
+
declare function createTokenHandler(options: TokenHandlerOptions): (req: Request) => Promise<Response>;
|
|
22
|
+
declare const createAnTokenHandler: typeof createTokenHandler;
|
|
22
23
|
|
|
23
|
-
export { type ExchangeTokenOptions, type TokenHandlerOptions, createAnTokenHandler, exchangeToken };
|
|
24
|
+
export { type ExchangeTokenOptions, type TokenHandlerOptions, createAnTokenHandler, createTokenHandler, exchangeToken };
|
package/dist/server.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ declare function exchangeToken(options: ExchangeTokenOptions): Promise<{
|
|
|
18
18
|
expiresAt: string;
|
|
19
19
|
}>;
|
|
20
20
|
/** Create a Next.js API route handler that exchanges an_sk_ keys for JWTs */
|
|
21
|
-
declare function
|
|
21
|
+
declare function createTokenHandler(options: TokenHandlerOptions): (req: Request) => Promise<Response>;
|
|
22
|
+
declare const createAnTokenHandler: typeof createTokenHandler;
|
|
22
23
|
|
|
23
|
-
export { type ExchangeTokenOptions, type TokenHandlerOptions, createAnTokenHandler, exchangeToken };
|
|
24
|
+
export { type ExchangeTokenOptions, type TokenHandlerOptions, createAnTokenHandler, createTokenHandler, exchangeToken };
|
package/dist/server.js
CHANGED
|
@@ -25,7 +25,7 @@ async function exchangeToken(options) {
|
|
|
25
25
|
}
|
|
26
26
|
return res.json();
|
|
27
27
|
}
|
|
28
|
-
function
|
|
28
|
+
function createTokenHandler(options) {
|
|
29
29
|
return async function POST(req) {
|
|
30
30
|
try {
|
|
31
31
|
const body = await req.json().catch(() => ({}));
|
|
@@ -38,8 +38,10 @@ function createAnTokenHandler(options) {
|
|
|
38
38
|
}
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
|
+
var createAnTokenHandler = createTokenHandler;
|
|
41
42
|
export {
|
|
42
43
|
createAnTokenHandler,
|
|
44
|
+
createTokenHandler,
|
|
43
45
|
exchangeToken
|
|
44
46
|
};
|
|
45
47
|
//# sourceMappingURL=server.js.map
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts"],"sourcesContent":["export interface TokenHandlerOptions {\n /** Your an_sk_ API key — keep in process.env, never expose to client */\n apiKey: string\n /** Relay URL. Default: \"https://relay.an.dev\" */\n relayUrl?: string\n /** Token expiry. Default: \"1h\" */\n expiresIn?: string\n}\n\nexport interface ExchangeTokenOptions extends TokenHandlerOptions {\n /** Agent slug to scope the token to */\n agent?: string\n /** User identifier for the token */\n userId?: string\n}\n\n/** Exchange an an_sk_ API key for a short-lived JWT via the relay */\nexport async function exchangeToken(options: ExchangeTokenOptions) {\n const {\n apiKey,\n relayUrl = \"https://relay.an.dev\",\n expiresIn = \"1h\",\n agent,\n userId,\n } = options\n\n const res = await fetch(`${relayUrl}/v1/tokens`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n userId,\n agents: agent ? [agent] : undefined,\n expiresIn,\n }),\n })\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({ error: \"Failed to exchange token\" }))\n throw new Error(err.error || `Token exchange failed: ${res.status}`)\n }\n\n return res.json() as Promise<{ token: string; expiresAt: string }>\n}\n\n/** Create a Next.js API route handler that exchanges an_sk_ keys for JWTs */\nexport function
|
|
1
|
+
{"version":3,"sources":["../src/server.ts"],"sourcesContent":["export interface TokenHandlerOptions {\n /** Your an_sk_ API key — keep in process.env, never expose to client */\n apiKey: string\n /** Relay URL. Default: \"https://relay.an.dev\" */\n relayUrl?: string\n /** Token expiry. Default: \"1h\" */\n expiresIn?: string\n}\n\nexport interface ExchangeTokenOptions extends TokenHandlerOptions {\n /** Agent slug to scope the token to */\n agent?: string\n /** User identifier for the token */\n userId?: string\n}\n\n/** Exchange an an_sk_ API key for a short-lived JWT via the relay */\nexport async function exchangeToken(options: ExchangeTokenOptions) {\n const {\n apiKey,\n relayUrl = \"https://relay.an.dev\",\n expiresIn = \"1h\",\n agent,\n userId,\n } = options\n\n const res = await fetch(`${relayUrl}/v1/tokens`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n userId,\n agents: agent ? [agent] : undefined,\n expiresIn,\n }),\n })\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({ error: \"Failed to exchange token\" }))\n throw new Error(err.error || `Token exchange failed: ${res.status}`)\n }\n\n return res.json() as Promise<{ token: string; expiresAt: string }>\n}\n\n/** Create a Next.js API route handler that exchanges an_sk_ keys for JWTs */\nexport function createTokenHandler(options: TokenHandlerOptions) {\n return async function POST(req: Request) {\n try {\n const body = await req.json().catch(() => ({}))\n const { agent, userId } = body as { agent?: string; userId?: string }\n\n const data = await exchangeToken({ ...options, agent, userId })\n return Response.json(data)\n } catch (err) {\n const message = err instanceof Error ? err.message : \"Internal error\"\n return Response.json({ error: message }, { status: 500 })\n }\n }\n}\n\n// Legacy handler alias kept for compatibility.\nexport const createAnTokenHandler = createTokenHandler\n"],"mappings":";AAiBA,eAAsB,cAAc,SAA+B;AACjE,QAAM;AAAA,IACJ;AAAA,IACA,WAAW;AAAA,IACX,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,QAAM,MAAM,MAAM,MAAM,GAAG,QAAQ,cAAc;AAAA,IAC/C,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,eAAe,UAAU,MAAM;AAAA,IACjC;AAAA,IACA,MAAM,KAAK,UAAU;AAAA,MACnB;AAAA,MACA,QAAQ,QAAQ,CAAC,KAAK,IAAI;AAAA,MAC1B;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AAED,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,MAAM,MAAM,IAAI,KAAK,EAAE,MAAM,OAAO,EAAE,OAAO,2BAA2B,EAAE;AAChF,UAAM,IAAI,MAAM,IAAI,SAAS,0BAA0B,IAAI,MAAM,EAAE;AAAA,EACrE;AAEA,SAAO,IAAI,KAAK;AAClB;AAGO,SAAS,mBAAmB,SAA8B;AAC/D,SAAO,eAAe,KAAK,KAAc;AACvC,QAAI;AACF,YAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAC9C,YAAM,EAAE,OAAO,OAAO,IAAI;AAE1B,YAAM,OAAO,MAAM,cAAc,EAAE,GAAG,SAAS,OAAO,OAAO,CAAC;AAC9D,aAAO,SAAS,KAAK,IAAI;AAAA,IAC3B,SAAS,KAAK;AACZ,YAAM,UAAU,eAAe,QAAQ,IAAI,UAAU;AACrD,aAAO,SAAS,KAAK,EAAE,OAAO,QAAQ,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC1D;AAAA,EACF;AACF;AAGO,IAAM,uBAAuB;","names":[]}
|
|
@@ -56,11 +56,11 @@ npm install @21st-sdk/nextjs @21st-sdk/react ai @ai-sdk/react
|
|
|
56
56
|
Create a token route (keeps your API key on the server):
|
|
57
57
|
|
|
58
58
|
```ts
|
|
59
|
-
// app/api/
|
|
60
|
-
import {
|
|
59
|
+
// app/api/agent/token/route.ts
|
|
60
|
+
import { createTokenHandler } from "@21st-sdk/nextjs/server"
|
|
61
61
|
|
|
62
|
-
export const POST =
|
|
63
|
-
apiKey: process.env.
|
|
62
|
+
export const POST = createTokenHandler({
|
|
63
|
+
apiKey: process.env.API_KEY_21ST!,
|
|
64
64
|
})
|
|
65
65
|
```
|
|
66
66
|
|
|
@@ -71,15 +71,15 @@ Add the chat UI:
|
|
|
71
71
|
"use client"
|
|
72
72
|
|
|
73
73
|
import { useChat } from "@ai-sdk/react"
|
|
74
|
-
import {
|
|
74
|
+
import { AgentChat, createAgentChat } from "@21st-sdk/nextjs"
|
|
75
75
|
import "@21st-sdk/react/styles.css"
|
|
76
76
|
import { useMemo } from "react"
|
|
77
77
|
|
|
78
78
|
export default function Chat() {
|
|
79
79
|
const chat = useMemo(
|
|
80
|
-
() =>
|
|
80
|
+
() => createAgentChat({
|
|
81
81
|
agent: "your-agent-slug",
|
|
82
|
-
tokenUrl: "/api/
|
|
82
|
+
tokenUrl: "/api/agent/token",
|
|
83
83
|
}),
|
|
84
84
|
[],
|
|
85
85
|
)
|
|
@@ -87,7 +87,7 @@ export default function Chat() {
|
|
|
87
87
|
const { messages, sendMessage, status, stop, error } = useChat({ chat })
|
|
88
88
|
|
|
89
89
|
return (
|
|
90
|
-
<
|
|
90
|
+
<AgentChat
|
|
91
91
|
messages={messages}
|
|
92
92
|
onSend={(msg) =>
|
|
93
93
|
sendMessage({ parts: [{ type: "text", text: msg.content }] })
|
package/docs/04-react-ui.md
CHANGED
|
@@ -14,13 +14,13 @@ npm install @21st-sdk/react ai @ai-sdk/react
|
|
|
14
14
|
"use client"
|
|
15
15
|
|
|
16
16
|
import { useChat } from "@ai-sdk/react"
|
|
17
|
-
import {
|
|
17
|
+
import { AgentChat, createAgentChat } from "@21st-sdk/react"
|
|
18
18
|
import "@21st-sdk/react/styles.css"
|
|
19
19
|
import { useMemo } from "react"
|
|
20
20
|
|
|
21
21
|
export default function Chat() {
|
|
22
22
|
const chat = useMemo(
|
|
23
|
-
() =>
|
|
23
|
+
() => createAgentChat({
|
|
24
24
|
agent: "your-agent-slug",
|
|
25
25
|
getToken: async () => "your_an_sk_token",
|
|
26
26
|
}),
|
|
@@ -30,7 +30,7 @@ export default function Chat() {
|
|
|
30
30
|
const { messages, sendMessage, status, stop, error } = useChat({ chat })
|
|
31
31
|
|
|
32
32
|
return (
|
|
33
|
-
<
|
|
33
|
+
<AgentChat
|
|
34
34
|
messages={messages}
|
|
35
35
|
onSend={(msg) =>
|
|
36
36
|
sendMessage({ parts: [{ type: "text", text: msg.content }] })
|
|
@@ -43,12 +43,12 @@ export default function Chat() {
|
|
|
43
43
|
}
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
## `
|
|
46
|
+
## `createAgentChat(options)`
|
|
47
47
|
|
|
48
48
|
Creates an AI SDK `Chat` instance pointed at the AN Relay.
|
|
49
49
|
|
|
50
50
|
```ts
|
|
51
|
-
|
|
51
|
+
createAgentChat({
|
|
52
52
|
agent: string // Agent slug from dashboard
|
|
53
53
|
getToken: () => Promise<string> // Returns an_sk_ key or JWT
|
|
54
54
|
apiUrl?: string // Default: "https://relay.an.dev"
|
|
@@ -60,7 +60,7 @@ createAnChat({
|
|
|
60
60
|
|
|
61
61
|
For Next.js apps, use `tokenUrl` instead of `getToken` — see [Next.js Integration](./05-nextjs.md).
|
|
62
62
|
|
|
63
|
-
## `<
|
|
63
|
+
## `<AgentChat />` Props
|
|
64
64
|
|
|
65
65
|
| Prop | Type | Description |
|
|
66
66
|
|------|------|-------------|
|
|
@@ -69,10 +69,10 @@ For Next.js apps, use `tokenUrl` instead of `getToken` — see [Next.js Integrat
|
|
|
69
69
|
| `status` | `ChatStatus` | `"ready" \| "submitted" \| "streaming" \| "error"` |
|
|
70
70
|
| `onStop` | `() => void` | Stop generation |
|
|
71
71
|
| `error` | `Error` | Error to display |
|
|
72
|
-
| `theme` | `
|
|
72
|
+
| `theme` | `ChatTheme` | Theme from playground |
|
|
73
73
|
| `colorMode` | `"light" \| "dark" \| "auto"` | Color mode |
|
|
74
|
-
| `classNames` | `Partial<
|
|
75
|
-
| `slots` | `Partial<
|
|
74
|
+
| `classNames` | `Partial<ChatClassNames>` | Per-element CSS overrides |
|
|
75
|
+
| `slots` | `Partial<ChatSlots>` | Component swapping |
|
|
76
76
|
| `className` | `string` | Root element class |
|
|
77
77
|
| `style` | `CSSProperties` | Root element style |
|
|
78
78
|
|
|
@@ -85,13 +85,13 @@ Four levels, from simple to full control:
|
|
|
85
85
|
Apply a theme JSON from the [AN Playground](https://21st.dev/agents/playground):
|
|
86
86
|
|
|
87
87
|
```tsx
|
|
88
|
-
<
|
|
88
|
+
<AgentChat theme={playgroundTheme} colorMode="dark" />
|
|
89
89
|
```
|
|
90
90
|
|
|
91
91
|
### 2. Class overrides
|
|
92
92
|
|
|
93
93
|
```tsx
|
|
94
|
-
<
|
|
94
|
+
<AgentChat
|
|
95
95
|
classNames={{
|
|
96
96
|
root: "rounded-2xl border",
|
|
97
97
|
messageList: "px-8",
|
|
@@ -106,7 +106,7 @@ Apply a theme JSON from the [AN Playground](https://21st.dev/agents/playground):
|
|
|
106
106
|
Swap sub-components:
|
|
107
107
|
|
|
108
108
|
```tsx
|
|
109
|
-
<
|
|
109
|
+
<AgentChat
|
|
110
110
|
slots={{
|
|
111
111
|
InputBar: MyCustomInput,
|
|
112
112
|
UserMessage: MyUserBubble,
|
|
@@ -145,7 +145,7 @@ No Tailwind peer dependency — CSS is pre-compiled. All elements have stable `a
|
|
|
145
145
|
## Theme Type
|
|
146
146
|
|
|
147
147
|
```ts
|
|
148
|
-
interface
|
|
148
|
+
interface ChatTheme {
|
|
149
149
|
theme: Record<string, string> // Shared: font, spacing, accent
|
|
150
150
|
light: Record<string, string> // Light mode CSS vars
|
|
151
151
|
dark: Record<string, string> // Dark mode CSS vars
|
package/docs/05-nextjs.md
CHANGED
|
@@ -14,7 +14,7 @@ npm install @21st-sdk/nextjs @21st-sdk/react ai @ai-sdk/react
|
|
|
14
14
|
|
|
15
15
|
```env
|
|
16
16
|
# .env.local
|
|
17
|
-
|
|
17
|
+
API_KEY_21ST=an_sk_your_key_here
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
Get your API key from [the dashboard](https://21st.dev/agents/dashboard/api).
|
|
@@ -22,11 +22,11 @@ Get your API key from [the dashboard](https://21st.dev/agents/dashboard/api).
|
|
|
22
22
|
### 2. Create the token route
|
|
23
23
|
|
|
24
24
|
```ts
|
|
25
|
-
// app/api/
|
|
26
|
-
import {
|
|
25
|
+
// app/api/agent/token/route.ts
|
|
26
|
+
import { createTokenHandler } from "@21st-sdk/nextjs/server"
|
|
27
27
|
|
|
28
|
-
export const POST =
|
|
29
|
-
apiKey: process.env.
|
|
28
|
+
export const POST = createTokenHandler({
|
|
29
|
+
apiKey: process.env.API_KEY_21ST!,
|
|
30
30
|
})
|
|
31
31
|
```
|
|
32
32
|
|
|
@@ -37,15 +37,15 @@ export const POST = createAnTokenHandler({
|
|
|
37
37
|
"use client"
|
|
38
38
|
|
|
39
39
|
import { useChat } from "@ai-sdk/react"
|
|
40
|
-
import {
|
|
40
|
+
import { AgentChat, createAgentChat } from "@21st-sdk/nextjs"
|
|
41
41
|
import "@21st-sdk/react/styles.css"
|
|
42
42
|
import { useMemo } from "react"
|
|
43
43
|
|
|
44
44
|
export default function Chat() {
|
|
45
45
|
const chat = useMemo(
|
|
46
|
-
() =>
|
|
46
|
+
() => createAgentChat({
|
|
47
47
|
agent: "your-agent-slug",
|
|
48
|
-
tokenUrl: "/api/
|
|
48
|
+
tokenUrl: "/api/agent/token",
|
|
49
49
|
}),
|
|
50
50
|
[],
|
|
51
51
|
)
|
|
@@ -53,7 +53,7 @@ export default function Chat() {
|
|
|
53
53
|
const { messages, sendMessage, status, stop, error } = useChat({ chat })
|
|
54
54
|
|
|
55
55
|
return (
|
|
56
|
-
<
|
|
56
|
+
<AgentChat
|
|
57
57
|
messages={messages}
|
|
58
58
|
onSend={(msg) =>
|
|
59
59
|
sendMessage({ parts: [{ type: "text", text: msg.content }] })
|
|
@@ -71,7 +71,7 @@ export default function Chat() {
|
|
|
71
71
|
```
|
|
72
72
|
Browser Your Next.js Server AN Relay
|
|
73
73
|
| | |
|
|
74
|
-
|-- POST /api/
|
|
74
|
+
|-- POST /api/agent/token ------>| |
|
|
75
75
|
| |-- POST /v1/tokens -------->|
|
|
76
76
|
| | (with an_sk_ key) |
|
|
77
77
|
| |<-- { token, expiresAt } ---|
|
|
@@ -85,12 +85,12 @@ The client only receives short-lived JWTs. Your API key stays on the server.
|
|
|
85
85
|
|
|
86
86
|
## API
|
|
87
87
|
|
|
88
|
-
### `
|
|
88
|
+
### `createTokenHandler(options)`
|
|
89
89
|
|
|
90
90
|
Returns a Next.js `POST` route handler.
|
|
91
91
|
|
|
92
92
|
```ts
|
|
93
|
-
|
|
93
|
+
createTokenHandler({
|
|
94
94
|
apiKey: string // Your an_sk_ API key
|
|
95
95
|
relayUrl?: string // Default: "https://relay.an.dev"
|
|
96
96
|
expiresIn?: string // Default: "1h"
|
|
@@ -105,7 +105,7 @@ Lower-level function for custom token exchange logic.
|
|
|
105
105
|
import { exchangeToken } from "@21st-sdk/nextjs/server"
|
|
106
106
|
|
|
107
107
|
const { token, expiresAt } = await exchangeToken({
|
|
108
|
-
apiKey: process.env.
|
|
108
|
+
apiKey: process.env.API_KEY_21ST!,
|
|
109
109
|
relayUrl: "https://relay.an.dev",
|
|
110
110
|
expiresIn: "1h",
|
|
111
111
|
})
|
|
@@ -113,5 +113,5 @@ const { token, expiresAt } = await exchangeToken({
|
|
|
113
113
|
|
|
114
114
|
## Entry Points
|
|
115
115
|
|
|
116
|
-
- `@21st-sdk/nextjs` — Re-exports everything from `@21st-sdk/react` (components, types, `
|
|
117
|
-
- `@21st-sdk/nextjs/server` — Server-only: `
|
|
116
|
+
- `@21st-sdk/nextjs` — Re-exports everything from `@21st-sdk/react` (components, types, `createAgentChat`)
|
|
117
|
+
- `@21st-sdk/nextjs/server` — Server-only: `createTokenHandler`, `exchangeToken`
|
package/docs/06-node-sdk.md
CHANGED
|
@@ -11,32 +11,32 @@ npm install @21st-sdk/node
|
|
|
11
11
|
## Quick Start
|
|
12
12
|
|
|
13
13
|
```ts
|
|
14
|
-
import {
|
|
14
|
+
import { AgentClient } from "@21st-sdk/node"
|
|
15
15
|
|
|
16
|
-
const
|
|
17
|
-
apiKey: process.env.
|
|
16
|
+
const client = new AgentClient({
|
|
17
|
+
apiKey: process.env.API_KEY_21ST!, // an_sk_...
|
|
18
18
|
})
|
|
19
19
|
|
|
20
20
|
// Create a sandbox for your agent
|
|
21
|
-
const sandbox = await
|
|
21
|
+
const sandbox = await client.sandboxes.create({ agent: "my-agent" })
|
|
22
22
|
|
|
23
23
|
// Create a thread
|
|
24
|
-
const thread = await
|
|
24
|
+
const thread = await client.threads.create({
|
|
25
25
|
sandboxId: sandbox.sandboxId,
|
|
26
26
|
name: "Review PR #42",
|
|
27
27
|
})
|
|
28
28
|
|
|
29
29
|
// Generate a short-lived token for browser clients
|
|
30
|
-
const { token, expiresAt } = await
|
|
30
|
+
const { token, expiresAt } = await client.tokens.create({
|
|
31
31
|
agent: "my-agent",
|
|
32
32
|
expiresIn: "1h",
|
|
33
33
|
})
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
## `
|
|
36
|
+
## `AgentClient`
|
|
37
37
|
|
|
38
38
|
```ts
|
|
39
|
-
new
|
|
39
|
+
new AgentClient({
|
|
40
40
|
apiKey: string // Your an_sk_ API key
|
|
41
41
|
baseUrl?: string // Default: "https://relay.an.dev"
|
|
42
42
|
})
|
package/docs/07-cli.md
CHANGED
|
@@ -85,4 +85,4 @@ The CLI uses esbuild to bundle your agent code:
|
|
|
85
85
|
|
|
86
86
|
| Variable | Default | Description |
|
|
87
87
|
|----------|---------|-------------|
|
|
88
|
-
| `
|
|
88
|
+
| `API_URL_21ST` | `https://an.dev/api/v1` | Override API endpoint |
|
package/docs/08-custom-tools.md
CHANGED
|
@@ -24,7 +24,7 @@ These are rendered automatically when your agent uses standard tools:
|
|
|
24
24
|
To render your custom tools differently, use the `slots.ToolRenderer` prop:
|
|
25
25
|
|
|
26
26
|
```tsx
|
|
27
|
-
import {
|
|
27
|
+
import { AgentChat, ToolRenderer } from "@21st-sdk/react"
|
|
28
28
|
import type { ToolPart } from "@21st-sdk/react"
|
|
29
29
|
|
|
30
30
|
function MyToolRenderer(props: { part: ToolPart; status: string }) {
|
|
@@ -49,7 +49,7 @@ function MyToolRenderer(props: { part: ToolPart; status: string }) {
|
|
|
49
49
|
return <ToolRenderer part={part} status={status} />
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
<
|
|
52
|
+
<AgentChat
|
|
53
53
|
slots={{ ToolRenderer: MyToolRenderer }}
|
|
54
54
|
// ... other props
|
|
55
55
|
/>
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@21st-sdk/nextjs",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.10",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"description": "Next.js integration for
|
|
5
|
+
"description": "Next.js integration for 21st Agents chat",
|
|
6
6
|
"homepage": "https://21st.dev/agents",
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
@@ -49,8 +49,8 @@
|
|
|
49
49
|
"agent",
|
|
50
50
|
"chat",
|
|
51
51
|
"ai-sdk",
|
|
52
|
-
"
|
|
53
|
-
"
|
|
52
|
+
"21st",
|
|
53
|
+
"21st.dev"
|
|
54
54
|
],
|
|
55
55
|
"scripts": {
|
|
56
56
|
"prepack": "cp -r ../docs ./docs",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"react": "^18.0.0 || ^19.0.0",
|
|
65
65
|
"react-dom": "^18.0.0 || ^19.0.0",
|
|
66
66
|
"@ai-sdk/react": "^2.0.0",
|
|
67
|
-
"@21st-sdk/react": "^0.1.
|
|
67
|
+
"@21st-sdk/react": "^0.1.4",
|
|
68
68
|
"ai": "^5.0.0"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
package/src/server.ts
CHANGED
|
@@ -46,7 +46,7 @@ export async function exchangeToken(options: ExchangeTokenOptions) {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
/** Create a Next.js API route handler that exchanges an_sk_ keys for JWTs */
|
|
49
|
-
export function
|
|
49
|
+
export function createTokenHandler(options: TokenHandlerOptions) {
|
|
50
50
|
return async function POST(req: Request) {
|
|
51
51
|
try {
|
|
52
52
|
const body = await req.json().catch(() => ({}))
|
|
@@ -60,3 +60,6 @@ export function createAnTokenHandler(options: TokenHandlerOptions) {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
|
+
|
|
64
|
+
// Legacy handler alias kept for compatibility.
|
|
65
|
+
export const createAnTokenHandler = createTokenHandler
|