ai.matey.react.nextjs 0.2.0

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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 AI Matey Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ /**
3
+ * Next.js Client Utilities
4
+ *
5
+ * Client-side hooks and utilities for Next.js.
6
+ *
7
+ * @module
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.useChat = useChat;
11
+ exports.useCompletion = useCompletion;
12
+ exports.generateAIMetadata = generateAIMetadata;
13
+ const ai_matey_react_core_1 = require("ai.matey.react.core");
14
+ /**
15
+ * useChat hook optimized for Next.js.
16
+ *
17
+ * Wraps the core useChat hook with Next.js-specific defaults.
18
+ *
19
+ * @example
20
+ * ```tsx
21
+ * 'use client';
22
+ *
23
+ * import { useChat } from 'ai.matey.react.nextjs';
24
+ *
25
+ * export function ChatComponent() {
26
+ * const { messages, input, handleInputChange, handleSubmit } = useChat();
27
+ *
28
+ * return (
29
+ * <form onSubmit={handleSubmit}>
30
+ * {messages.map((m) => <div key={m.id}>{m.content}</div>)}
31
+ * <input value={input} onChange={handleInputChange} />
32
+ * </form>
33
+ * );
34
+ * }
35
+ * ```
36
+ */
37
+ function useChat(options = {}) {
38
+ const { serverAction, experimental, ...coreOptions } = options;
39
+ // Default API to Next.js convention
40
+ const api = coreOptions.api ?? '/api/chat';
41
+ return (0, ai_matey_react_core_1.useChat)({
42
+ ...coreOptions,
43
+ api,
44
+ // Use SSE stream protocol by default for Next.js
45
+ streamProtocol: coreOptions.streamProtocol ?? 'data',
46
+ });
47
+ }
48
+ /**
49
+ * useCompletion hook optimized for Next.js.
50
+ *
51
+ * @example
52
+ * ```tsx
53
+ * 'use client';
54
+ *
55
+ * import { useCompletion } from 'ai.matey.react.nextjs';
56
+ *
57
+ * export function CompletionComponent() {
58
+ * const { completion, input, handleInputChange, handleSubmit } = useCompletion();
59
+ *
60
+ * return (
61
+ * <form onSubmit={handleSubmit}>
62
+ * <input value={input} onChange={handleInputChange} />
63
+ * <p>{completion}</p>
64
+ * </form>
65
+ * );
66
+ * }
67
+ * ```
68
+ */
69
+ function useCompletion(options = {}) {
70
+ const { serverAction, ...coreOptions } = options;
71
+ // Default API to Next.js convention
72
+ const api = coreOptions.api ?? '/api/completion';
73
+ return (0, ai_matey_react_core_1.useCompletion)({
74
+ ...coreOptions,
75
+ api,
76
+ streamProtocol: coreOptions.streamProtocol ?? 'data',
77
+ });
78
+ }
79
+ /**
80
+ * Generate Next.js metadata from AI response.
81
+ *
82
+ * Useful for SEO when AI generates page content.
83
+ *
84
+ * @param content - AI-generated content
85
+ * @param aiMetadata - AI generation metadata
86
+ * @param options - Metadata options
87
+ * @returns Next.js Metadata object
88
+ *
89
+ * @example
90
+ * ```typescript
91
+ * // app/blog/[slug]/page.tsx
92
+ * import { generateMetadata } from 'ai.matey.react.nextjs';
93
+ *
94
+ * export async function generateMetadata({ params }) {
95
+ * const article = await getAIArticle(params.slug);
96
+ * return generateAIMetadata(article.content, article.aiMetadata);
97
+ * }
98
+ * ```
99
+ */
100
+ function generateAIMetadata(content, aiMetadata, options = {}) {
101
+ const { titleTemplate, descriptionTemplate, includeAttribution = false } = options;
102
+ // Extract title (first line or heading)
103
+ const titleMatch = content.match(/^#\s+(.+)$/m) || content.match(/^(.+)$/m);
104
+ const rawTitle = titleMatch?.[1]?.trim() || 'Untitled';
105
+ const title = titleTemplate ? titleTemplate.replace('%s', rawTitle) : rawTitle;
106
+ // Extract description (first paragraph)
107
+ const paragraphs = content.split('\n\n').filter((p) => !p.startsWith('#'));
108
+ const rawDescription = paragraphs[0]?.trim().slice(0, 160) || '';
109
+ const description = descriptionTemplate
110
+ ? descriptionTemplate.replace('%s', rawDescription)
111
+ : rawDescription;
112
+ const metadata = {
113
+ title,
114
+ description,
115
+ };
116
+ // Add AI attribution if requested
117
+ if (includeAttribution && aiMetadata) {
118
+ const attribution = [];
119
+ if (aiMetadata.provider)
120
+ attribution.push(`Provider: ${aiMetadata.provider}`);
121
+ if (aiMetadata.model)
122
+ attribution.push(`Model: ${aiMetadata.model}`);
123
+ metadata.other = {
124
+ 'ai-generated': 'true',
125
+ ...(attribution.length > 0 && { 'ai-attribution': attribution.join(', ') }),
126
+ };
127
+ }
128
+ return metadata;
129
+ }
130
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ /**
3
+ * AI Matey React Next.js
4
+ *
5
+ * Next.js integration for AI Matey.
6
+ *
7
+ * For server-side utilities, import from 'ai.matey.react.nextjs/server'.
8
+ *
9
+ * @packageDocumentation
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.generateAIMetadata = exports.useCompletion = exports.useChat = void 0;
13
+ // Re-export core hooks for convenience
14
+ var client_js_1 = require("./client.js");
15
+ Object.defineProperty(exports, "useChat", { enumerable: true, get: function () { return client_js_1.useChat; } });
16
+ Object.defineProperty(exports, "useCompletion", { enumerable: true, get: function () { return client_js_1.useCompletion; } });
17
+ Object.defineProperty(exports, "generateAIMetadata", { enumerable: true, get: function () { return client_js_1.generateAIMetadata; } });
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAEH,uCAAuC;AACvC,yCAAyE;AAAhE,oGAAA,OAAO,OAAA;AAAE,0GAAA,aAAa,OAAA;AAAE,+GAAA,kBAAkB,OAAA"}
@@ -0,0 +1,257 @@
1
+ "use strict";
2
+ /**
3
+ * Next.js Server Utilities
4
+ *
5
+ * Server-side utilities for Next.js App Router and API Routes.
6
+ *
7
+ * @module
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.createStreamingResponse = createStreamingResponse;
11
+ exports.createSSEResponse = createSSEResponse;
12
+ exports.createChatHandler = createChatHandler;
13
+ exports.createChatAction = createChatAction;
14
+ /**
15
+ * Create a streaming Response for Next.js App Router.
16
+ *
17
+ * @param stream - Async iterable of chunks
18
+ * @param options - Response options
19
+ * @returns Web Response with streaming body
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * // app/api/chat/route.ts
24
+ * import { createStreamingResponse } from 'ai.matey.react.nextjs/server';
25
+ * import { Bridge } from 'ai.matey.core';
26
+ *
27
+ * export async function POST(request: Request) {
28
+ * const { messages } = await request.json();
29
+ * const bridge = new Bridge({ backend, frontend });
30
+ *
31
+ * const stream = bridge.chatStream({ messages });
32
+ * return createStreamingResponse(stream);
33
+ * }
34
+ * ```
35
+ */
36
+ function createStreamingResponse(stream, options = {}) {
37
+ const { headers = {}, status = 200 } = options;
38
+ let body;
39
+ if (stream instanceof ReadableStream) {
40
+ body = stream;
41
+ }
42
+ else {
43
+ // Convert async iterable to ReadableStream
44
+ const encoder = new TextEncoder();
45
+ body = new ReadableStream({
46
+ async start(controller) {
47
+ try {
48
+ for await (const chunk of stream) {
49
+ controller.enqueue(encoder.encode(chunk));
50
+ }
51
+ controller.close();
52
+ }
53
+ catch (error) {
54
+ controller.error(error);
55
+ }
56
+ },
57
+ });
58
+ }
59
+ return new Response(body, {
60
+ status,
61
+ headers: {
62
+ 'Content-Type': 'text/event-stream',
63
+ 'Cache-Control': 'no-cache, no-transform',
64
+ Connection: 'keep-alive',
65
+ ...headers,
66
+ },
67
+ });
68
+ }
69
+ /**
70
+ * Create a Server-Sent Events (SSE) response.
71
+ *
72
+ * @param stream - Async iterable of data objects
73
+ * @param options - Response options
74
+ * @returns Web Response with SSE body
75
+ *
76
+ * @example
77
+ * ```typescript
78
+ * // app/api/chat/route.ts
79
+ * import { createSSEResponse } from 'ai.matey.react.nextjs/server';
80
+ *
81
+ * export async function POST(request: Request) {
82
+ * const stream = generateChatStream();
83
+ * return createSSEResponse(stream);
84
+ * }
85
+ * ```
86
+ */
87
+ function createSSEResponse(stream, options = {}) {
88
+ const { headers = {}, status = 200 } = options;
89
+ const encoder = new TextEncoder();
90
+ const body = new ReadableStream({
91
+ async start(controller) {
92
+ try {
93
+ for await (const data of stream) {
94
+ const sseMessage = `data: ${JSON.stringify(data)}\n\n`;
95
+ controller.enqueue(encoder.encode(sseMessage));
96
+ }
97
+ // Send done signal
98
+ controller.enqueue(encoder.encode('data: [DONE]\n\n'));
99
+ controller.close();
100
+ }
101
+ catch (error) {
102
+ controller.error(error);
103
+ }
104
+ },
105
+ });
106
+ return new Response(body, {
107
+ status,
108
+ headers: {
109
+ 'Content-Type': 'text/event-stream',
110
+ 'Cache-Control': 'no-cache, no-transform',
111
+ Connection: 'keep-alive',
112
+ ...headers,
113
+ },
114
+ });
115
+ }
116
+ /**
117
+ * Create a chat API route handler for Next.js.
118
+ *
119
+ * @param options - Handler options
120
+ * @returns Route handler function
121
+ *
122
+ * @example
123
+ * ```typescript
124
+ * // app/api/chat/route.ts
125
+ * import { createChatHandler } from 'ai.matey.react.nextjs/server';
126
+ * import { Bridge } from 'ai.matey.core';
127
+ * import { OpenAIBackend } from 'ai.matey.backend/openai';
128
+ *
129
+ * const bridge = new Bridge({
130
+ * backend: new OpenAIBackend({ apiKey: process.env.OPENAI_API_KEY }),
131
+ * });
132
+ *
133
+ * export const POST = createChatHandler({ bridge });
134
+ * ```
135
+ */
136
+ function createChatHandler(options) {
137
+ const { bridge: bridgeOrFactory, validate, transformRequest, transformChunk, onError } = options;
138
+ return async function handler(request) {
139
+ try {
140
+ // Parse request body
141
+ const body = (await request.json());
142
+ // Validate if provided
143
+ if (validate && !validate(body)) {
144
+ return new Response(JSON.stringify({ error: 'Invalid request body' }), {
145
+ status: 400,
146
+ headers: { 'Content-Type': 'application/json' },
147
+ });
148
+ }
149
+ // Get bridge instance
150
+ const bridge = typeof bridgeOrFactory === 'function' ? await bridgeOrFactory() : bridgeOrFactory;
151
+ // Transform request if provided
152
+ const processedBody = transformRequest ? transformRequest(body) : body;
153
+ // Check if streaming is requested
154
+ const shouldStream = processedBody.stream !== false;
155
+ if (shouldStream) {
156
+ // Streaming response
157
+ const stream = bridge.chatStream({
158
+ messages: processedBody.messages.map((m) => ({
159
+ role: m.role,
160
+ content: m.content,
161
+ })),
162
+ model: processedBody.model,
163
+ temperature: processedBody.temperature,
164
+ maxTokens: processedBody.maxTokens,
165
+ });
166
+ // Transform chunks if needed
167
+ const transformedStream = transformChunk
168
+ ? transformStreamChunks(stream, transformChunk)
169
+ : stream;
170
+ return createSSEResponse(transformedStream);
171
+ }
172
+ else {
173
+ // Non-streaming response
174
+ const response = await bridge.chat({
175
+ messages: processedBody.messages.map((m) => ({
176
+ role: m.role,
177
+ content: m.content,
178
+ })),
179
+ model: processedBody.model,
180
+ temperature: processedBody.temperature,
181
+ maxTokens: processedBody.maxTokens,
182
+ });
183
+ return new Response(JSON.stringify(response), {
184
+ status: 200,
185
+ headers: { 'Content-Type': 'application/json' },
186
+ });
187
+ }
188
+ }
189
+ catch (error) {
190
+ if (onError) {
191
+ return onError(error instanceof Error ? error : new Error(String(error)));
192
+ }
193
+ console.error('Chat handler error:', error);
194
+ return new Response(JSON.stringify({
195
+ error: error instanceof Error ? error.message : 'Internal server error',
196
+ }), {
197
+ status: 500,
198
+ headers: { 'Content-Type': 'application/json' },
199
+ });
200
+ }
201
+ };
202
+ }
203
+ /**
204
+ * Transform stream chunks.
205
+ */
206
+ async function* transformStreamChunks(stream, transform) {
207
+ for await (const chunk of stream) {
208
+ if (typeof chunk === 'string') {
209
+ yield transform(chunk);
210
+ }
211
+ else if (chunk &&
212
+ typeof chunk === 'object' &&
213
+ 'content' in chunk &&
214
+ typeof chunk.content === 'string') {
215
+ yield {
216
+ ...chunk,
217
+ content: transform(chunk.content),
218
+ };
219
+ }
220
+ else {
221
+ yield chunk;
222
+ }
223
+ }
224
+ }
225
+ /**
226
+ * Server action for chat completion.
227
+ *
228
+ * @example
229
+ * ```typescript
230
+ * // app/actions.ts
231
+ * 'use server';
232
+ *
233
+ * import { createChatAction } from 'ai.matey.react.nextjs/server';
234
+ * import { bridge } from './bridge';
235
+ *
236
+ * export const chatAction = createChatAction({ bridge });
237
+ *
238
+ * // In component:
239
+ * const result = await chatAction({ messages: [...] });
240
+ * ```
241
+ */
242
+ function createChatAction(options) {
243
+ return async function chatAction(body) {
244
+ const bridge = typeof options.bridge === 'function' ? await options.bridge() : options.bridge;
245
+ const response = await bridge.chat({
246
+ messages: body.messages.map((m) => ({
247
+ role: m.role,
248
+ content: m.content,
249
+ })),
250
+ model: body.model,
251
+ temperature: body.temperature,
252
+ maxTokens: body.maxTokens,
253
+ });
254
+ return response;
255
+ };
256
+ }
257
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAoCH,0DAoCC;AAoBD,8CAiCC;AA2DD,8CA8EC;AA6CD,4CAgBC;AArTD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,SAAgB,uBAAuB,CACrC,MAA0D,EAC1D,UAAoC,EAAE;IAEtC,MAAM,EAAE,OAAO,GAAG,EAAE,EAAE,MAAM,GAAG,GAAG,EAAE,GAAG,OAAO,CAAC;IAE/C,IAAI,IAAgC,CAAC;IAErC,IAAI,MAAM,YAAY,cAAc,EAAE,CAAC;QACrC,IAAI,GAAG,MAAM,CAAC;IAChB,CAAC;SAAM,CAAC;QACN,2CAA2C;QAC3C,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;QAClC,IAAI,GAAG,IAAI,cAAc,CAAC;YACxB,KAAK,CAAC,KAAK,CAAC,UAAU;gBACpB,IAAI,CAAC;oBACH,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;wBACjC,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;oBAC5C,CAAC;oBACD,UAAU,CAAC,KAAK,EAAE,CAAC;gBACrB,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBAC1B,CAAC;YACH,CAAC;SACF,CAAC,CAAC;IACL,CAAC;IAED,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE;QACxB,MAAM;QACN,OAAO,EAAE;YACP,cAAc,EAAE,mBAAmB;YACnC,eAAe,EAAE,wBAAwB;YACzC,UAAU,EAAE,YAAY;YACxB,GAAG,OAAO;SACX;KACF,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAgB,iBAAiB,CAC/B,MAAwB,EACxB,UAAoC,EAAE;IAEtC,MAAM,EAAE,OAAO,GAAG,EAAE,EAAE,MAAM,GAAG,GAAG,EAAE,GAAG,OAAO,CAAC;IAC/C,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAElC,MAAM,IAAI,GAAG,IAAI,cAAc,CAAC;QAC9B,KAAK,CAAC,KAAK,CAAC,UAAU;YACpB,IAAI,CAAC;gBACH,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;oBAChC,MAAM,UAAU,GAAG,SAAS,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC;oBACvD,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;gBACjD,CAAC;gBAED,mBAAmB;gBACnB,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC;gBACvD,UAAU,CAAC,KAAK,EAAE,CAAC;YACrB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;KACF,CAAC,CAAC;IAEH,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE;QACxB,MAAM;QACN,OAAO,EAAE;YACP,cAAc,EAAE,mBAAmB;YACnC,eAAe,EAAE,wBAAwB;YACzC,UAAU,EAAE,YAAY;YACxB,GAAG,OAAO;SACX;KACF,CAAC,CAAC;AACL,CAAC;AAuCD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,SAAgB,iBAAiB,CAAC,OAAiC;IACjE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,QAAQ,EAAE,gBAAgB,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAEjG,OAAO,KAAK,UAAU,OAAO,CAAC,OAAgB;QAC5C,IAAI,CAAC;YACH,qBAAqB;YACrB,MAAM,IAAI,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,EAAE,CAAoB,CAAC;YAEvD,uBAAuB;YACvB,IAAI,QAAQ,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChC,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,CAAC,EAAE;oBACrE,MAAM,EAAE,GAAG;oBACX,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;iBAChD,CAAC,CAAC;YACL,CAAC;YAED,sBAAsB;YACtB,MAAM,MAAM,GACV,OAAO,eAAe,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,eAAe,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC;YAEpF,gCAAgC;YAChC,MAAM,aAAa,GAAG,gBAAgB,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAEvE,kCAAkC;YAClC,MAAM,YAAY,GAAG,aAAa,CAAC,MAAM,KAAK,KAAK,CAAC;YAEpD,IAAI,YAAY,EAAE,CAAC;gBACjB,qBAAqB;gBACrB,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC;oBAC/B,QAAQ,EAAE,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;wBAC3C,IAAI,EAAE,CAAC,CAAC,IAAI;wBACZ,OAAO,EAAE,CAAC,CAAC,OAAO;qBACnB,CAAC,CAAC;oBACH,KAAK,EAAE,aAAa,CAAC,KAAK;oBAC1B,WAAW,EAAE,aAAa,CAAC,WAAW;oBACtC,SAAS,EAAE,aAAa,CAAC,SAAS;iBACnC,CAAC,CAAC;gBAEH,6BAA6B;gBAC7B,MAAM,iBAAiB,GAAG,cAAc;oBACtC,CAAC,CAAC,qBAAqB,CAAC,MAAM,EAAE,cAAc,CAAC;oBAC/C,CAAC,CAAC,MAAM,CAAC;gBAEX,OAAO,iBAAiB,CAAC,iBAAiB,CAAC,CAAC;YAC9C,CAAC;iBAAM,CAAC;gBACN,yBAAyB;gBACzB,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC;oBACjC,QAAQ,EAAE,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;wBAC3C,IAAI,EAAE,CAAC,CAAC,IAAI;wBACZ,OAAO,EAAE,CAAC,CAAC,OAAO;qBACnB,CAAC,CAAC;oBACH,KAAK,EAAE,aAAa,CAAC,KAAK;oBAC1B,WAAW,EAAE,aAAa,CAAC,WAAW;oBACtC,SAAS,EAAE,aAAa,CAAC,SAAS;iBACnC,CAAC,CAAC;gBAEH,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE;oBAC5C,MAAM,EAAE,GAAG;oBACX,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;iBAChD,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,OAAO,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC5E,CAAC;YAED,OAAO,CAAC,KAAK,CAAC,qBAAqB,EAAE,KAAK,CAAC,CAAC;YAC5C,OAAO,IAAI,QAAQ,CACjB,IAAI,CAAC,SAAS,CAAC;gBACb,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB;aACxE,CAAC,EACF;gBACE,MAAM,EAAE,GAAG;gBACX,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;aAChD,CACF,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,KAAK,SAAS,CAAC,CAAC,qBAAqB,CACnC,MAA8B,EAC9B,SAAoC;IAEpC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QACjC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,SAAS,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC;aAAM,IACL,KAAK;YACL,OAAO,KAAK,KAAK,QAAQ;YACzB,SAAS,IAAI,KAAK;YAClB,OAAQ,KAA6B,CAAC,OAAO,KAAK,QAAQ,EAC1D,CAAC;YACD,MAAM;gBACJ,GAAG,KAAK;gBACR,OAAO,EAAE,SAAS,CAAE,KAA6B,CAAC,OAAO,CAAC;aAC3D,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,SAAgB,gBAAgB,CAAC,OAA8D;IAC7F,OAAO,KAAK,UAAU,UAAU,CAAC,IAAqB;QACpD,MAAM,MAAM,GAAG,OAAO,OAAO,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;QAE9F,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC;YACjC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAClC,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,OAAO,EAAE,CAAC,CAAC,OAAO;aACnB,CAAC,CAAC;YACH,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC,CAAC;QAEH,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Next.js Client Utilities
3
+ *
4
+ * Client-side hooks and utilities for Next.js.
5
+ *
6
+ * @module
7
+ */
8
+ import { useChat as useChatCore, useCompletion as useCompletionCore } from 'ai.matey.react.core';
9
+ /**
10
+ * useChat hook optimized for Next.js.
11
+ *
12
+ * Wraps the core useChat hook with Next.js-specific defaults.
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * 'use client';
17
+ *
18
+ * import { useChat } from 'ai.matey.react.nextjs';
19
+ *
20
+ * export function ChatComponent() {
21
+ * const { messages, input, handleInputChange, handleSubmit } = useChat();
22
+ *
23
+ * return (
24
+ * <form onSubmit={handleSubmit}>
25
+ * {messages.map((m) => <div key={m.id}>{m.content}</div>)}
26
+ * <input value={input} onChange={handleInputChange} />
27
+ * </form>
28
+ * );
29
+ * }
30
+ * ```
31
+ */
32
+ export function useChat(options = {}) {
33
+ const { serverAction, experimental, ...coreOptions } = options;
34
+ // Default API to Next.js convention
35
+ const api = coreOptions.api ?? '/api/chat';
36
+ return useChatCore({
37
+ ...coreOptions,
38
+ api,
39
+ // Use SSE stream protocol by default for Next.js
40
+ streamProtocol: coreOptions.streamProtocol ?? 'data',
41
+ });
42
+ }
43
+ /**
44
+ * useCompletion hook optimized for Next.js.
45
+ *
46
+ * @example
47
+ * ```tsx
48
+ * 'use client';
49
+ *
50
+ * import { useCompletion } from 'ai.matey.react.nextjs';
51
+ *
52
+ * export function CompletionComponent() {
53
+ * const { completion, input, handleInputChange, handleSubmit } = useCompletion();
54
+ *
55
+ * return (
56
+ * <form onSubmit={handleSubmit}>
57
+ * <input value={input} onChange={handleInputChange} />
58
+ * <p>{completion}</p>
59
+ * </form>
60
+ * );
61
+ * }
62
+ * ```
63
+ */
64
+ export function useCompletion(options = {}) {
65
+ const { serverAction, ...coreOptions } = options;
66
+ // Default API to Next.js convention
67
+ const api = coreOptions.api ?? '/api/completion';
68
+ return useCompletionCore({
69
+ ...coreOptions,
70
+ api,
71
+ streamProtocol: coreOptions.streamProtocol ?? 'data',
72
+ });
73
+ }
74
+ /**
75
+ * Generate Next.js metadata from AI response.
76
+ *
77
+ * Useful for SEO when AI generates page content.
78
+ *
79
+ * @param content - AI-generated content
80
+ * @param aiMetadata - AI generation metadata
81
+ * @param options - Metadata options
82
+ * @returns Next.js Metadata object
83
+ *
84
+ * @example
85
+ * ```typescript
86
+ * // app/blog/[slug]/page.tsx
87
+ * import { generateMetadata } from 'ai.matey.react.nextjs';
88
+ *
89
+ * export async function generateMetadata({ params }) {
90
+ * const article = await getAIArticle(params.slug);
91
+ * return generateAIMetadata(article.content, article.aiMetadata);
92
+ * }
93
+ * ```
94
+ */
95
+ export function generateAIMetadata(content, aiMetadata, options = {}) {
96
+ const { titleTemplate, descriptionTemplate, includeAttribution = false } = options;
97
+ // Extract title (first line or heading)
98
+ const titleMatch = content.match(/^#\s+(.+)$/m) || content.match(/^(.+)$/m);
99
+ const rawTitle = titleMatch?.[1]?.trim() || 'Untitled';
100
+ const title = titleTemplate ? titleTemplate.replace('%s', rawTitle) : rawTitle;
101
+ // Extract description (first paragraph)
102
+ const paragraphs = content.split('\n\n').filter((p) => !p.startsWith('#'));
103
+ const rawDescription = paragraphs[0]?.trim().slice(0, 160) || '';
104
+ const description = descriptionTemplate
105
+ ? descriptionTemplate.replace('%s', rawDescription)
106
+ : rawDescription;
107
+ const metadata = {
108
+ title,
109
+ description,
110
+ };
111
+ // Add AI attribution if requested
112
+ if (includeAttribution && aiMetadata) {
113
+ const attribution = [];
114
+ if (aiMetadata.provider)
115
+ attribution.push(`Provider: ${aiMetadata.provider}`);
116
+ if (aiMetadata.model)
117
+ attribution.push(`Model: ${aiMetadata.model}`);
118
+ metadata.other = {
119
+ 'ai-generated': 'true',
120
+ ...(attribution.length > 0 && { 'ai-attribution': attribution.join(', ') }),
121
+ };
122
+ }
123
+ return metadata;
124
+ }
125
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * AI Matey React Next.js
3
+ *
4
+ * Next.js integration for AI Matey.
5
+ *
6
+ * For server-side utilities, import from 'ai.matey.react.nextjs/server'.
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+ // Re-export core hooks for convenience
11
+ export { useChat, useCompletion, generateAIMetadata } from './client.js';
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,uCAAuC;AACvC,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC"}