Skip to content

Commit e604792

Browse files
authored
📦 NEW: usePipe support (#84)
* 📦 NEW: usePipe support * 👌 IMPROVE: Config
1 parent 7a0463c commit e604792

File tree

11 files changed

+3436
-2793
lines changed

11 files changed

+3436
-2793
lines changed

examples/nextjs/app/langbase/pipe/run-stream/route.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {Langbase} from 'langbase';
22
import {NextRequest} from 'next/server';
33

44
export async function POST(req: NextRequest) {
5-
const {prompt} = await req.json();
5+
const options = await req.json();
66

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

1212
// 2. Generate a stream by asking a question
1313
const {stream, threadId} = await langbase.pipe.run({
14-
messages: [{role: 'user', content: prompt}],
14+
messages: options.messages,
1515
stream: true,
1616
name: 'summary',
1717
});
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
'use client';
2+
import { Button } from '@/components/ui/button';
3+
import { Input } from '@/components/ui/input';
4+
import { Message } from 'langbase';
5+
import { usePipe } from 'langbase/react';
6+
import React, { useCallback } from 'react';
7+
8+
const ChatAdvanced: React.FC = () => {
9+
const handleResponse = useCallback(
10+
(message: Message) => {
11+
console.log(
12+
'Received response:',
13+
message.content?.slice(0, 50) + '...',
14+
);
15+
},
16+
[],
17+
);
18+
19+
const handleFinish = useCallback(
20+
(messages: Message[]) => {
21+
console.log(
22+
`Conversation finished. Total messages: ${messages.length}`,
23+
);
24+
},
25+
[],
26+
);
27+
28+
const handleError = useCallback((error: Error) => {
29+
console.error('An error occurred:', error);
30+
}, []);
31+
32+
const {
33+
messages,
34+
input,
35+
handleInputChange,
36+
handleSubmit,
37+
isLoading,
38+
error,
39+
regenerate,
40+
stop,
41+
setMessages,
42+
threadId,
43+
sendMessage,
44+
} = usePipe({
45+
stream: true,
46+
apiRoute: '/langbase/pipe/run-stream',
47+
onResponse: handleResponse,
48+
onFinish: handleFinish,
49+
onError: handleError,
50+
// initialMessages: [
51+
// {role: 'assistant', content: 'Hello! How can I help you?'},
52+
// {role: 'user', content: 'Who is an AI engineer?'},
53+
// ], // You can set initial messages here if needed
54+
// You can set a threadId here if needed to change the thread manually,
55+
// otherwise it will be generated automatically persistented in the browser.
56+
// threadId: '',
57+
});
58+
59+
const handleClearChat = () => {
60+
setMessages([]);
61+
};
62+
63+
const handleRegenerateWithOptions = () => {
64+
regenerate({
65+
headers: { 'Custom-Header': 'Regenerate' },
66+
body: { customOption: 'regenerateValue' },
67+
});
68+
};
69+
70+
const handleCustomMessage = () => {
71+
sendMessage('This is a custom message', {
72+
data: { context: 'custom context' },
73+
allowEmptySubmit: false,
74+
});
75+
};
76+
77+
return (
78+
<div className="flex flex-col h-[80vh] max-w-2xl mx-auto p-4 w-full">
79+
<div className="mb-4">
80+
<strong>Thread ID:</strong> {threadId || 'Not available'}
81+
</div>
82+
<div className="flex-1 overflow-y-auto mb-4 space-y-4 pb-32 w-full">
83+
{messages.map((m, index) => (
84+
<div
85+
key={index}
86+
className={`p-2 rounded ${m.role === 'user' ? 'bg-indigo-200' : 'bg-gray-100'
87+
}`}
88+
>
89+
<strong>{m.role === 'user' ? 'You: ' : 'AI: '}</strong>
90+
{m.content}
91+
</div>
92+
))}
93+
</div>
94+
95+
<div className="fixed bottom-0 left-0 right-0 bg-white p-4 max-w-2xl mx-auto">
96+
{isLoading && (
97+
<div className="text-center text-gray-500 mb-8">
98+
AI is thinking...
99+
</div>
100+
)}
101+
102+
{error && (
103+
<div className="text-center text-red-500 mb-2">
104+
Error: {error.message}
105+
</div>
106+
)}
107+
108+
<div className="flex space-x-2 mb-2">
109+
<Button
110+
onClick={handleRegenerateWithOptions}
111+
disabled={isLoading || messages.length === 0}
112+
size="sm"
113+
>
114+
Regenerate
115+
</Button>
116+
<Button onClick={stop} disabled={!isLoading} size="sm">
117+
Stop
118+
</Button>
119+
<Button
120+
onClick={handleClearChat}
121+
variant="outline"
122+
size="sm"
123+
>
124+
Clear Chat
125+
</Button>
126+
<Button
127+
onClick={handleCustomMessage}
128+
variant="outline"
129+
size="sm"
130+
>
131+
Send Custom
132+
</Button>
133+
</div>
134+
135+
<form
136+
onSubmit={e => handleSubmit(e, { allowEmptySubmit: true })}
137+
className="flex space-x-2"
138+
>
139+
<Input
140+
className="flex-1"
141+
value={input}
142+
onChange={handleInputChange}
143+
placeholder="Type your message..."
144+
disabled={isLoading}
145+
autoFocus
146+
/>
147+
<Button type="submit">Send</Button>
148+
</form>
149+
</div>
150+
</div>
151+
);
152+
};
153+
154+
export default ChatAdvanced;

examples/nextjs/components/langbase/run-stream.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export default function RunStreamExample() {
2020
try {
2121
const response = await fetch('/langbase/pipe/run-stream', {
2222
method: 'POST',
23-
body: JSON.stringify({prompt}),
23+
body: JSON.stringify([{role: 'user', content: prompt}]),
2424
headers: {'Content-Type': 'text/plain'},
2525
});
2626

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,15 @@
2929
"update-examples": "npx tsx .github/scripts/update-examples.ts"
3030
},
3131
"devDependencies": {
32-
"@langbase/eslint-config": "workspace:*",
3332
"@changesets/cli": "^2.27.5",
33+
"@langbase/eslint-config": "workspace:*",
3434
"@types/node": "^20.11.24",
3535
"eslint": "^8.57.0",
3636
"husky": "^9.0.11",
3737
"lint-staged": "^15.2.7",
3838
"prettier": "^3.3.2",
3939
"publint": "^0.2.8",
40-
"turbo": "^2.0.4",
40+
"turbo": "^2.1.2",
4141
"vitest": "^1.6.0"
4242
},
4343
"packageManager": "pnpm@9.4.0",

packages/langbase/package.json

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@
77
"module": "./dist/index.mjs",
88
"types": "./dist/index.d.ts",
99
"files": [
10-
"dist/**"
10+
"dist/**",
11+
"react/dist/**"
1112
],
1213
"scripts": {
13-
"build": "tsup src/index.ts --format esm,cjs --dts --external react",
14-
"dev": "tsup src/index.ts --format esm,cjs --watch --dts --external react",
14+
"build": "tsup --config tsup.config.ts --format esm,cjs --dts --external react",
15+
"dev": "tsup --config tsup.config.ts --format esm,cjs --watch --dts --external react",
1516
"xdev": "tsup --watch",
1617
"lint": "eslint \"src/**/*.ts*\"",
1718
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist",
@@ -39,11 +40,14 @@
3940
"@langbase/eslint-config": "workspace:*",
4041
"@langbase/tsconfig": "workspace:*",
4142
"@playwright/test": "^1.44.1",
43+
"@testing-library/react": "^16.0.1",
4244
"@types/node": "^20.11.24",
45+
"@types/react": "^18.3.9",
4346
"@vitejs/plugin-react": "^4.3.1",
4447
"eslint": "^8.57.0",
4548
"jsdom": "^24.1.0",
46-
"tsup": "^8.0.2",
49+
"react": "^18",
50+
"tsup": "^8.3.6",
4751
"typescript": "^5.3.3",
4852
"vitest": "1.6.0"
4953
},
@@ -56,6 +60,11 @@
5660
"types": "./dist/index.d.ts",
5761
"import": "./dist/index.mjs",
5862
"require": "./dist/index.js"
63+
},
64+
"./react": {
65+
"types": "./react/dist/index.d.ts",
66+
"require": "./react/dist/index.js",
67+
"import": "./react/dist/index.mjs"
5968
}
6069
},
6170
"engines": {
@@ -79,5 +88,13 @@
7988
"langbase",
8089
"langbase.com",
8190
"generative AI"
82-
]
91+
],
92+
"peerDependencies": {
93+
"react": "^18 || ^19"
94+
},
95+
"peerDependenciesMeta": {
96+
"react": {
97+
"optional": true
98+
}
99+
}
83100
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './use-pipe';

0 commit comments

Comments
 (0)