Skip to content

Commit 0486565

Browse files
committed
Initial commit
0 parents  commit 0486565

File tree

13 files changed

+463
-0
lines changed

13 files changed

+463
-0
lines changed

.eslintrc.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
module.exports = {
2+
extends: [
3+
'eslint:recommended',
4+
'plugin:@typescript-eslint/recommended',
5+
'plugin:prettier/recommended',
6+
],
7+
parser: '@typescript-eslint/parser',
8+
plugins: ['@typescript-eslint', 'unused-imports', 'prettier'],
9+
ignorePatterns: [
10+
'**/node_modules',
11+
'**/dist',
12+
'**/build',
13+
'**/package-lock.json',
14+
],
15+
rules: {
16+
'@typescript-eslint/explicit-module-boundary-types': 'off',
17+
'no-unused-vars': 'off',
18+
'unused-imports/no-unused-imports': 'warn',
19+
'unused-imports/no-unused-vars': [
20+
'warn',
21+
{
22+
vars: 'all',
23+
varsIgnorePattern: '^_',
24+
args: 'after-used',
25+
argsIgnorePattern: '^_',
26+
},
27+
],
28+
'no-undef': 'off',
29+
'no-console': [
30+
process.env.CI ? 'error' : 'warn',
31+
{ allow: ['warn', 'error', 'info'] },
32+
],
33+
'prettier/prettier': 'error',
34+
"@typescript-eslint/no-explicit-any": "off",
35+
"@typescript-eslint/ban-ts-comment": "off"
36+
},
37+
};

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
node_modules/
2+
dist/
3+
.DS_Store
4+
*.log
5+
package-lock.json

.npmignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
src/
2+
tests/
3+
.gitignore
4+
tsconfig.json
5+
jest.config.js
6+
*.log

.prettierrc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"semi": true,
3+
"singleQuote": true,
4+
"printWidth": 80,
5+
"tabWidth": 4,
6+
"trailingComma": "es5"
7+
}
8+

LICENSE.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) [year] [fullname]
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.

README.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Flowise SDK
2+
3+
A TypeScript SDK for interacting with the Flowise API.
4+
5+
## Installation
6+
7+
```bash
8+
npm install flowise-sdk
9+
```
10+
11+
## Usage
12+
13+
```typescript
14+
import { FlowiseClient } from 'flowise-sdk';
15+
16+
const flowise = new FlowiseClient({ baseUrl: 'http://localhost:3000' });
17+
18+
async function main() {
19+
const completion = await flowise.createPrediction({
20+
chatflowId: '<id>',
21+
question: "hello",
22+
streaming: true
23+
});
24+
25+
for await (const chunk of completion) {
26+
console.log(chunk);
27+
}
28+
}
29+
30+
main();
31+
```
32+
33+
## API Reference
34+
35+
### `FlowiseClient`
36+
37+
The main class for interacting with the Flowise API.
38+
39+
#### Constructor
40+
41+
```typescript
42+
new FlowiseClient(baseUrl?: string)
43+
```
44+
45+
- `baseUrl`: Optional. The base URL for the Flowise API. Defaults to 'http://localhost:3000'.
46+
47+
#### Methods
48+
49+
##### `predictions.create(params: PredictionParams): Promise<PredictionResponse>`
50+
51+
Creates a new prediction.
52+
53+
- `params`: An object containing the following properties:
54+
- `chatflowId`: string - Chatflow ID to execute prediction
55+
- `question`: string - The question to ask.
56+
- `streaming`: boolean (optional) - Whether to stream the response.
57+
- `chatId`: string (optional) - Chat ID of the session
58+
- `overrideConfig`: object (optional) - Override configuration
59+
60+
61+
## License
62+
63+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

examples/example.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Actual import
2+
// import { FlowiseClient } from 'flowise-sdk';
3+
import { FlowiseClient } from '../src';
4+
5+
async function main() {
6+
const flowise = new FlowiseClient({ baseUrl: 'http://localhost:3000' });
7+
8+
try {
9+
const completion = await flowise.createPrediction({
10+
chatflowId: 'fe1145fa-1b2b-45b7-b2ba-bcc5aaeb5ffd',
11+
question: 'hello there',
12+
streaming: true,
13+
});
14+
15+
// Process each chunk of data as it is streamed
16+
for await (const chunk of completion) {
17+
console.log('Received chunk:', chunk);
18+
}
19+
} catch (error) {
20+
console.error('Error:', error);
21+
}
22+
}
23+
24+
main();

jest.config.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module.exports = {
2+
preset: 'ts-jest',
3+
testEnvironment: 'node',
4+
roots: ['<rootDir>/tests'],
5+
testMatch: ['**/*.test.ts'],
6+
moduleFileExtensions: ['ts', 'js', 'json', 'node'],
7+
};

package.json

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{
2+
"name": "flowise-sdk",
3+
"version": "1.0.5",
4+
"description": "Flowise SDK for streaming API responses.",
5+
"main": "dist/index.js",
6+
"types": "dist/index.d.ts",
7+
"scripts": {
8+
"build": "tsc",
9+
"start": "node dist/examples/example.js",
10+
"test": "jest",
11+
"lint": "eslint \"**/*.{ts,tsx}\" --fix",
12+
"prepare": "npm run build"
13+
},
14+
"keywords": [
15+
"flowise",
16+
"sdk",
17+
"typescript"
18+
],
19+
"author": "Your Name",
20+
"license": "MIT",
21+
"dependencies": {
22+
"node-fetch": "^3.3.0"
23+
},
24+
"devDependencies": {
25+
"@types/jest": "^29.5.2",
26+
"@types/node": "^20.3.1",
27+
"@types/node-fetch": "^2.6.4",
28+
"@typescript-eslint/eslint-plugin": "^6.7.0",
29+
"@typescript-eslint/parser": "^6.7.0",
30+
"eslint": "^8.49.0",
31+
"eslint-config-prettier": "^9.1.0",
32+
"eslint-plugin-prettier": "^5.0.1",
33+
"eslint-plugin-unused-imports": "^3.0.0",
34+
"jest": "^29.5.0",
35+
"prettier": "^3.3.3",
36+
"ts-jest": "^29.1.0",
37+
"typescript": "^5.1.3"
38+
}
39+
}

src/flowise-sdk.ts

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
export interface PredictionData {
2+
chatflowId: string;
3+
question: string;
4+
overrideConfig?: Record<string, any>;
5+
chatId?: string;
6+
streaming?: boolean;
7+
}
8+
9+
interface FlowiseClientOptions {
10+
baseUrl?: string;
11+
}
12+
13+
type PredictionResponse<T extends PredictionData> = T['streaming'] extends true
14+
? AsyncGenerator<string, void, unknown> // Streaming returns an async generator
15+
: Record<string, any>;
16+
17+
export default class FlowiseClient {
18+
private baseUrl: string;
19+
20+
constructor(options: FlowiseClientOptions = {}) {
21+
this.baseUrl = options.baseUrl || 'http://localhost:3000';
22+
}
23+
24+
// Method to create a new prediction and handle streaming response
25+
async createPrediction<T extends PredictionData>(
26+
data: T
27+
): Promise<PredictionResponse<T>> {
28+
const { chatflowId, streaming } = data;
29+
30+
// Check if chatflow is available to stream
31+
const chatFlowStreamingUrl = `${this.baseUrl}/api/v1/chatflows-streaming/${chatflowId}`;
32+
const resp = await fetch(chatFlowStreamingUrl, {
33+
method: 'GET',
34+
headers: {
35+
'Content-Type': 'application/json',
36+
},
37+
});
38+
39+
const chatFlowStreamingData = await resp.json();
40+
const isChatFlowAvailableToStream =
41+
chatFlowStreamingData.isStreaming || false;
42+
43+
const predictionUrl = `${this.baseUrl}/api/v1/prediction/${chatflowId}`;
44+
45+
if (isChatFlowAvailableToStream && streaming) {
46+
return {
47+
async *[Symbol.asyncIterator]() {
48+
const response = await fetch(predictionUrl, {
49+
method: 'POST',
50+
headers: {
51+
'Content-Type': 'application/json',
52+
},
53+
body: JSON.stringify(data),
54+
});
55+
56+
if (!response.ok) {
57+
throw new Error(
58+
`HTTP error! status: ${response.status}`
59+
);
60+
}
61+
62+
//@ts-ignore
63+
const reader = response.body.getReader();
64+
const decoder = new TextDecoder();
65+
let buffer = '';
66+
67+
try {
68+
while (true) {
69+
const { done, value } = await reader.read();
70+
if (done) break;
71+
72+
buffer += decoder.decode(value, { stream: true });
73+
const lines = buffer.split('\n');
74+
buffer = lines.pop() || '';
75+
76+
for (const line of lines) {
77+
if (line.trim() === '') continue;
78+
if (line.startsWith('data:')) {
79+
const stringifiedJson = line.replace(
80+
'data:',
81+
''
82+
);
83+
const event = JSON.parse(stringifiedJson);
84+
yield event;
85+
}
86+
}
87+
}
88+
} finally {
89+
reader.releaseLock();
90+
}
91+
},
92+
} as unknown as Promise<PredictionResponse<T>>;
93+
} else {
94+
// Make a POST request and handle streaming response
95+
const options = {
96+
method: 'POST',
97+
headers: {
98+
'Content-Type': 'application/json',
99+
},
100+
body: JSON.stringify(data),
101+
};
102+
103+
try {
104+
const response = await fetch(predictionUrl, options);
105+
const resp = await response.json();
106+
return resp as Promise<PredictionResponse<T>>;
107+
} catch (error) {
108+
throw new Error('Error creating prediction');
109+
}
110+
}
111+
}
112+
}

0 commit comments

Comments
 (0)