Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/nextjs/app/langbase/pipe/run-stream/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {Langbase} from 'langbase';
import {NextRequest} from 'next/server';

export async function POST(req: NextRequest) {
const {prompt} = await req.json();
const options = await req.json();

// 1. Initiate the Pipe.
const langbase = new Langbase({
Expand All @@ -11,7 +11,7 @@ export async function POST(req: NextRequest) {

// 2. Generate a stream by asking a question
const {stream, threadId} = await langbase.pipe.run({
messages: [{role: 'user', content: prompt}],
messages: options.messages,
stream: true,
name: 'summary',
});
Expand Down
154 changes: 154 additions & 0 deletions examples/nextjs/components/langbase/chat-advanced.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
'use client';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Message } from 'langbase';
import { usePipe } from 'langbase/react';
import React, { useCallback } from 'react';

const ChatAdvanced: React.FC = () => {
const handleResponse = useCallback(
(message: Message) => {
console.log(
'Received response:',
message.content?.slice(0, 50) + '...',
);
},
[],
);

const handleFinish = useCallback(
(messages: Message[]) => {
console.log(
`Conversation finished. Total messages: ${messages.length}`,
);
},
[],
);

const handleError = useCallback((error: Error) => {
console.error('An error occurred:', error);
}, []);

const {
messages,
input,
handleInputChange,
handleSubmit,
isLoading,
error,
regenerate,
stop,
setMessages,
threadId,
sendMessage,
} = usePipe({
stream: true,
apiRoute: '/langbase/pipe/run-stream',
onResponse: handleResponse,
onFinish: handleFinish,
onError: handleError,
// initialMessages: [
// {role: 'assistant', content: 'Hello! How can I help you?'},
// {role: 'user', content: 'Who is an AI engineer?'},
// ], // You can set initial messages here if needed
// You can set a threadId here if needed to change the thread manually,
// otherwise it will be generated automatically persistented in the browser.
// threadId: '',
});

const handleClearChat = () => {
setMessages([]);
};

const handleRegenerateWithOptions = () => {
regenerate({
headers: { 'Custom-Header': 'Regenerate' },
body: { customOption: 'regenerateValue' },
});
};

const handleCustomMessage = () => {
sendMessage('This is a custom message', {
data: { context: 'custom context' },
allowEmptySubmit: false,
});
};

return (
<div className="flex flex-col h-[80vh] max-w-2xl mx-auto p-4 w-full">
<div className="mb-4">
<strong>Thread ID:</strong> {threadId || 'Not available'}
</div>
<div className="flex-1 overflow-y-auto mb-4 space-y-4 pb-32 w-full">
{messages.map((m, index) => (
<div
key={index}
className={`p-2 rounded ${m.role === 'user' ? 'bg-indigo-200' : 'bg-gray-100'
}`}
>
<strong>{m.role === 'user' ? 'You: ' : 'AI: '}</strong>
{m.content}
</div>
))}
</div>

<div className="fixed bottom-0 left-0 right-0 bg-white p-4 max-w-2xl mx-auto">
{isLoading && (
<div className="text-center text-gray-500 mb-8">
AI is thinking...
</div>
)}

{error && (
<div className="text-center text-red-500 mb-2">
Error: {error.message}
</div>
)}

<div className="flex space-x-2 mb-2">
<Button
onClick={handleRegenerateWithOptions}
disabled={isLoading || messages.length === 0}
size="sm"
>
Regenerate
</Button>
<Button onClick={stop} disabled={!isLoading} size="sm">
Stop
</Button>
<Button
onClick={handleClearChat}
variant="outline"
size="sm"
>
Clear Chat
</Button>
<Button
onClick={handleCustomMessage}
variant="outline"
size="sm"
>
Send Custom
</Button>
</div>

<form
onSubmit={e => handleSubmit(e, { allowEmptySubmit: true })}
className="flex space-x-2"
>
<Input
className="flex-1"
value={input}
onChange={handleInputChange}
placeholder="Type your message..."
disabled={isLoading}
autoFocus
/>
<Button type="submit">Send</Button>
</form>
</div>
</div>
);
};

export default ChatAdvanced;
2 changes: 1 addition & 1 deletion examples/nextjs/components/langbase/run-stream.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default function RunStreamExample() {
try {
const response = await fetch('/langbase/pipe/run-stream', {
method: 'POST',
body: JSON.stringify({prompt}),
body: JSON.stringify([{role: 'user', content: prompt}]),
headers: {'Content-Type': 'text/plain'},
});

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@
"update-examples": "npx tsx .github/scripts/update-examples.ts"
},
"devDependencies": {
"@langbase/eslint-config": "workspace:*",
"@changesets/cli": "^2.27.5",
"@langbase/eslint-config": "workspace:*",
"@types/node": "^20.11.24",
"eslint": "^8.57.0",
"husky": "^9.0.11",
"lint-staged": "^15.2.7",
"prettier": "^3.3.2",
"publint": "^0.2.8",
"turbo": "^2.0.4",
"turbo": "^2.1.2",
"vitest": "^1.6.0"
},
"packageManager": "pnpm@9.4.0",
Expand Down
27 changes: 22 additions & 5 deletions packages/langbase/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"files": [
"dist/**"
"dist/**",
"react/dist/**"
],
"scripts": {
"build": "tsup src/index.ts --format esm,cjs --dts --external react",
"dev": "tsup src/index.ts --format esm,cjs --watch --dts --external react",
"build": "tsup --config tsup.config.ts --format esm,cjs --dts --external react",
"dev": "tsup --config tsup.config.ts --format esm,cjs --watch --dts --external react",
"xdev": "tsup --watch",
"lint": "eslint \"src/**/*.ts*\"",
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist",
Expand Down Expand Up @@ -39,11 +40,14 @@
"@langbase/eslint-config": "workspace:*",
"@langbase/tsconfig": "workspace:*",
"@playwright/test": "^1.44.1",
"@testing-library/react": "^16.0.1",
"@types/node": "^20.11.24",
"@types/react": "^18.3.9",
"@vitejs/plugin-react": "^4.3.1",
"eslint": "^8.57.0",
"jsdom": "^24.1.0",
"tsup": "^8.0.2",
"react": "^18",
"tsup": "^8.3.6",
"typescript": "^5.3.3",
"vitest": "1.6.0"
},
Expand All @@ -56,6 +60,11 @@
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.js"
},
"./react": {
"types": "./react/dist/index.d.ts",
"require": "./react/dist/index.js",
"import": "./react/dist/index.mjs"
}
},
"engines": {
Expand All @@ -79,5 +88,13 @@
"langbase",
"langbase.com",
"generative AI"
]
],
"peerDependencies": {
"react": "^18 || ^19"
},
"peerDependenciesMeta": {
"react": {
"optional": true
}
}
}
1 change: 1 addition & 0 deletions packages/langbase/src/react/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './use-pipe';
Loading
Loading