mirror of
https://github.com/FlowiseAI/Flowise.git
synced 2026-10-11 21:59:56 +00:00
feat(agentflow): update agentflow sdk contract and fix lint configs (#5752)
This commit is contained in:
+1
-1
@@ -14,7 +14,7 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
parser: '@typescript-eslint/parser',
|
||||
ignorePatterns: ['**/node_modules', '**/dist', '**/build', '**/package-lock.json'],
|
||||
ignorePatterns: ['**/node_modules', '**/dist', '**/build', '**/coverage', '**/package-lock.json'],
|
||||
plugins: ['unused-imports'],
|
||||
rules: {
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
|
||||
@@ -137,7 +137,7 @@ module.exports = {
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['examples/**/*.{js,jsx,ts,tsx}'],
|
||||
files: ['examples/**/*.{js,jsx,ts,tsx}', '**/*.md/**'],
|
||||
rules: {
|
||||
'no-console': 'off',
|
||||
'@typescript-eslint/no-non-null-assertion': 'off'
|
||||
|
||||
@@ -43,12 +43,94 @@ import '@flowise/agentflow/flowise.css'
|
||||
export default function App() {
|
||||
return (
|
||||
<div style={{ width: '100vw', height: '100vh' }}>
|
||||
<Agentflow instanceUrl='http://localhost:3000' token='your-api-key' />
|
||||
<Agentflow apiBaseUrl='http://localhost:3000' token='your-api-key' />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### With Initial Flow Data and Callbacks
|
||||
|
||||
```tsx
|
||||
import { useRef } from 'react'
|
||||
|
||||
import { Agentflow, type AgentFlowInstance, type FlowData } from '@flowise/agentflow'
|
||||
|
||||
import '@flowise/agentflow/flowise.css'
|
||||
|
||||
export default function App() {
|
||||
const ref = useRef<AgentFlowInstance>(null)
|
||||
|
||||
const initialFlow: FlowData = {
|
||||
nodes: [
|
||||
{
|
||||
id: 'startAgentflow_0',
|
||||
type: 'agentflowNode',
|
||||
position: { x: 100, y: 100 },
|
||||
data: {
|
||||
id: 'startAgentflow_0',
|
||||
name: 'startAgentflow',
|
||||
label: 'Start',
|
||||
color: '#7EE787',
|
||||
hideInput: true,
|
||||
outputAnchors: [{ id: 'startAgentflow_0-output-0', name: 'start', label: 'Start', type: 'start' }]
|
||||
}
|
||||
}
|
||||
],
|
||||
edges: [],
|
||||
viewport: { x: 0, y: 0, zoom: 1 }
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ width: '100vw', height: '100vh' }}>
|
||||
<Agentflow
|
||||
ref={ref}
|
||||
apiBaseUrl='http://localhost:3000'
|
||||
token='your-api-key'
|
||||
initialFlow={initialFlow}
|
||||
onFlowChange={(flow) => console.log('Flow changed:', flow)}
|
||||
onSave={(flow) => console.log('Flow saved:', flow)}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `apiBaseUrl` | `string` | **(required)** | Flowise API server endpoint |
|
||||
| `token` | `string` | — | Authentication token for API calls |
|
||||
| `initialFlow` | `FlowData` | — | Initial flow data to render (uncontrolled — only used on mount) |
|
||||
| `flowId` | `string` | — | Flow ID for loading an existing flow from the API |
|
||||
| `components` | `string[]` | — | Restrict which node types appear in the palette |
|
||||
| `onFlowChange` | `(flow: FlowData) => void` | — | Called when the flow changes (node/edge add, remove, move) |
|
||||
| `onSave` | `(flow: FlowData) => void` | — | Called when the user triggers a save |
|
||||
| `onFlowGenerated` | `(flow: FlowData) => void` | — | Called when a flow is generated via AI |
|
||||
| `theme` | `'light' \| 'dark' \| 'system'` | `'system'` | Theme override |
|
||||
| `readOnly` | `boolean` | `false` | Disable editing (nodes not draggable/connectable) |
|
||||
| `showDefaultHeader` | `boolean` | `true` | Show built-in header (ignored if `renderHeader` provided) |
|
||||
| `showDefaultPalette` | `boolean` | `true` | Show built-in node palette |
|
||||
| `enableGenerator` | `boolean` | `true` | Show the AI flow generator button |
|
||||
| `renderHeader` | `(props: HeaderRenderProps) => ReactNode` | — | Custom header renderer |
|
||||
| `renderNodePalette` | `(props: PaletteRenderProps) => ReactNode` | — | Custom node palette renderer |
|
||||
|
||||
### Imperative Methods (via `ref`)
|
||||
|
||||
| Method | Return Type | Description |
|
||||
|--------|-------------|-------------|
|
||||
| `getFlow()` | `FlowData` | Get current flow data |
|
||||
| `toJSON()` | `string` | Export flow as JSON string |
|
||||
| `validate()` | `ValidationResult` | Validate the current flow |
|
||||
| `fitView()` | `void` | Fit all nodes into view |
|
||||
| `clear()` | `void` | Remove all nodes and edges |
|
||||
| `addNode(name)` | `void` | Add a node by component name |
|
||||
|
||||
### Design Note
|
||||
|
||||
`<Agentflow>` is an **uncontrolled component**. The `initialFlow` prop seeds the canvas state on mount, but the component owns its own state afterward. Use the `ref` for imperative access and `onFlowChange` to observe changes.
|
||||
|
||||
## Development
|
||||
|
||||
```bash
|
||||
|
||||
@@ -36,10 +36,10 @@ The examples app uses environment variables for configuration. To set up:
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
2. Edit `.env` to configure your Flowise instance:
|
||||
2. Edit `.env` to configure your Flowise API server:
|
||||
|
||||
```bash
|
||||
# Flowise Instance Configuration
|
||||
# Flowise API Base URL
|
||||
VITE_INSTANCE_URL=http://localhost:3000
|
||||
|
||||
# API Key (required for authenticated endpoints)
|
||||
@@ -62,7 +62,7 @@ The examples app uses environment variables for configuration. To set up:
|
||||
|
||||
**Environment Variables:**
|
||||
|
||||
- `VITE_INSTANCE_URL`: Base URL of your Flowise instance (default: `http://localhost:3000`)
|
||||
- `VITE_INSTANCE_URL`: Flowise API server endpoint (maps to `apiBaseUrl` prop, default: `http://localhost:3000`)
|
||||
- `VITE_API_TOKEN`: Flowise API Key for programmatic access (required for authenticated endpoints)
|
||||
|
||||
**Note**: The `.env` file is gitignored and will not be committed to version control. Add your actual API key to `.env`, not `.env.example`.
|
||||
@@ -94,11 +94,12 @@ Common causes:
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic Usage (`App.tsx`)
|
||||
### Basic Usage (`BasicExample.tsx`)
|
||||
|
||||
The default export shows:
|
||||
Demonstrates core usage:
|
||||
|
||||
- Basic canvas rendering with `<Agentflow>` component
|
||||
- Passing `apiBaseUrl` and `initialFlow` props
|
||||
- Using the `ref` to access imperative methods (`validate`, `fitView`, `getFlow`, `clear`)
|
||||
- Handling `onFlowChange` and `onSave` callbacks
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import { type ComponentType, lazy, Suspense, useState } from 'react'
|
||||
|
||||
import { instanceUrl, token } from './config'
|
||||
import { apiBaseUrl, token } from './config'
|
||||
import {
|
||||
AllNodeTypesExampleProps,
|
||||
BasicExampleProps,
|
||||
@@ -108,8 +108,8 @@ export default function App() {
|
||||
const actualProps = currentExample?.props
|
||||
? Object.fromEntries(
|
||||
Object.entries(currentExample.props).map(([key, value]) => {
|
||||
if (key === 'instanceUrl' && typeof value === 'string' && value.includes('environment variables')) {
|
||||
return [key, instanceUrl]
|
||||
if (key === 'apiBaseUrl' && typeof value === 'string' && value.includes('environment variables')) {
|
||||
return [key, apiBaseUrl]
|
||||
}
|
||||
if (key === 'token' && typeof value === 'string' && value.includes('environment variables')) {
|
||||
return [key, token ? `${token.substring(0, 20)}...` : 'undefined']
|
||||
@@ -163,9 +163,9 @@ export default function App() {
|
||||
</select>
|
||||
{currentExample && <span style={{ color: '#666', fontSize: '13px' }}>{currentExample.description}</span>}
|
||||
|
||||
{/* Instance URL Display */}
|
||||
{/* API Base URL Display */}
|
||||
<div style={{ marginLeft: 'auto', display: 'flex', alignItems: 'center', gap: '12px' }}>
|
||||
<span style={{ fontSize: '12px', color: '#999' }}>{instanceUrl}</span>
|
||||
<span style={{ fontSize: '12px', color: '#999' }}>{apiBaseUrl}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Application configuration from environment variables
|
||||
*/
|
||||
export const instanceUrl = import.meta.env.VITE_INSTANCE_URL || 'http://localhost:3000'
|
||||
export const apiBaseUrl = import.meta.env.VITE_INSTANCE_URL || 'http://localhost:3000'
|
||||
export const token = import.meta.env.VITE_API_TOKEN || undefined
|
||||
|
||||
@@ -10,7 +10,7 @@ import { useRef } from 'react'
|
||||
import type { AgentFlowInstance, FlowData } from '@flowise/agentflow'
|
||||
import { Agentflow } from '@flowise/agentflow'
|
||||
|
||||
import { instanceUrl, token } from '../config'
|
||||
import { apiBaseUrl, token } from '../config'
|
||||
|
||||
// Showcase all node types in a grid layout
|
||||
const allNodesFlow: FlowData = {
|
||||
@@ -238,9 +238,9 @@ export function AllNodeTypesExample() {
|
||||
<div style={{ flex: 1 }}>
|
||||
<Agentflow
|
||||
ref={agentflowRef}
|
||||
instanceUrl={instanceUrl}
|
||||
apiBaseUrl={apiBaseUrl}
|
||||
token={token ?? undefined}
|
||||
flow={allNodesFlow}
|
||||
initialFlow={allNodesFlow}
|
||||
showDefaultHeader={false}
|
||||
readOnly={true}
|
||||
/>
|
||||
@@ -250,9 +250,9 @@ export function AllNodeTypesExample() {
|
||||
}
|
||||
|
||||
export const AllNodeTypesExampleProps = {
|
||||
instanceUrl: instanceUrl,
|
||||
apiBaseUrl: apiBaseUrl,
|
||||
token: token,
|
||||
flow: 'FlowData (15 node types)',
|
||||
initialFlow: 'FlowData (15 node types)',
|
||||
readOnly: true,
|
||||
showDefaultHeader: false,
|
||||
enableGenerator: false
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useRef, useState } from 'react'
|
||||
import type { AgentFlowInstance, FlowData, ValidationResult } from '@flowise/agentflow'
|
||||
import { Agentflow } from '@flowise/agentflow'
|
||||
|
||||
import { instanceUrl, token } from '../config'
|
||||
import { apiBaseUrl, token } from '../config'
|
||||
|
||||
// Example flow data
|
||||
const initialFlow: FlowData = {
|
||||
@@ -102,9 +102,9 @@ export function BasicExample() {
|
||||
<div style={{ flex: 1 }}>
|
||||
<Agentflow
|
||||
ref={agentflowRef}
|
||||
instanceUrl={instanceUrl}
|
||||
apiBaseUrl={apiBaseUrl}
|
||||
token={token ?? undefined}
|
||||
flow={initialFlow}
|
||||
initialFlow={initialFlow}
|
||||
onFlowChange={handleFlowChange}
|
||||
onSave={handleSave}
|
||||
showDefaultHeader={true}
|
||||
@@ -115,9 +115,9 @@ export function BasicExample() {
|
||||
}
|
||||
|
||||
export const BasicExampleProps = {
|
||||
instanceUrl: '{from environment variables}',
|
||||
apiBaseUrl: '{from environment variables}',
|
||||
token: '{from environment variables}',
|
||||
flow: 'FlowData',
|
||||
initialFlow: 'FlowData',
|
||||
onFlowChange: '(flow: FlowData) => void',
|
||||
onSave: '(flow: FlowData) => void',
|
||||
showDefaultHeader: true
|
||||
|
||||
@@ -10,7 +10,7 @@ import { useRef, useState } from 'react'
|
||||
import type { AgentFlowInstance, FlowData, HeaderRenderProps, PaletteRenderProps } from '@flowise/agentflow'
|
||||
import { Agentflow } from '@flowise/agentflow'
|
||||
|
||||
import { instanceUrl, token } from '../config'
|
||||
import { apiBaseUrl, token } from '../config'
|
||||
|
||||
const initialFlow: FlowData = {
|
||||
nodes: [
|
||||
@@ -256,9 +256,9 @@ export function CustomUIExample() {
|
||||
<div style={{ width: '100%', height: '100vh' }}>
|
||||
<Agentflow
|
||||
ref={agentflowRef}
|
||||
instanceUrl={instanceUrl}
|
||||
apiBaseUrl={apiBaseUrl}
|
||||
token={token ?? undefined}
|
||||
flow={initialFlow}
|
||||
initialFlow={initialFlow}
|
||||
renderHeader={(props) => <CustomHeader {...props} />}
|
||||
renderNodePalette={(props) => <CustomPalette {...props} />}
|
||||
showDefaultHeader={false}
|
||||
@@ -273,9 +273,9 @@ export function CustomUIExample() {
|
||||
}
|
||||
|
||||
export const CustomUIExampleProps = {
|
||||
instanceUrl: '{from environment variables}',
|
||||
apiBaseUrl: '{from environment variables}',
|
||||
token: '{from environment variables}',
|
||||
flow: 'FlowData',
|
||||
initialFlow: 'FlowData',
|
||||
renderHeader: '(props: HeaderRenderProps) => ReactNode',
|
||||
renderNodePalette: '(props: PaletteRenderProps) => ReactNode',
|
||||
showDefaultHeader: false,
|
||||
|
||||
@@ -12,7 +12,7 @@ import { Agentflow } from '@flowise/agentflow'
|
||||
import CssBaseline from '@mui/material/CssBaseline'
|
||||
import { createTheme, ThemeProvider } from '@mui/material/styles'
|
||||
|
||||
import { instanceUrl, token } from '../config'
|
||||
import { apiBaseUrl, token } from '../config'
|
||||
|
||||
const sampleFlow: FlowData = {
|
||||
nodes: [
|
||||
@@ -137,9 +137,9 @@ export function DarkModeExample() {
|
||||
<div style={{ flex: 1 }}>
|
||||
<Agentflow
|
||||
ref={agentflowRef}
|
||||
instanceUrl={instanceUrl}
|
||||
apiBaseUrl={apiBaseUrl}
|
||||
token={token ?? undefined}
|
||||
flow={sampleFlow}
|
||||
initialFlow={sampleFlow}
|
||||
theme={isDark ? 'dark' : 'light'}
|
||||
showDefaultHeader={false}
|
||||
/>
|
||||
@@ -150,9 +150,9 @@ export function DarkModeExample() {
|
||||
}
|
||||
|
||||
export const DarkModeExampleProps = {
|
||||
instanceUrl: '{from environment variables}',
|
||||
apiBaseUrl: '{from environment variables}',
|
||||
token: '{from environment variables}',
|
||||
flow: 'FlowData (sample flow)',
|
||||
initialFlow: 'FlowData (sample flow)',
|
||||
theme: '{isDark ? "dark" : "light"}',
|
||||
showDefaultHeader: false
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { useRef, useState } from 'react'
|
||||
import type { AgentFlowInstance, FlowData } from '@flowise/agentflow'
|
||||
import { Agentflow } from '@flowise/agentflow'
|
||||
|
||||
import { instanceUrl, token } from '../config'
|
||||
import { apiBaseUrl, token } from '../config'
|
||||
|
||||
const initialFlow: FlowData = {
|
||||
nodes: [
|
||||
@@ -142,9 +142,9 @@ export function FilteredComponentsExample() {
|
||||
<div style={{ flex: 1 }} key={key}>
|
||||
<Agentflow
|
||||
ref={agentflowRef}
|
||||
instanceUrl={instanceUrl}
|
||||
apiBaseUrl={apiBaseUrl}
|
||||
token={token ?? undefined}
|
||||
flow={initialFlow}
|
||||
initialFlow={initialFlow}
|
||||
components={currentPreset.components}
|
||||
showDefaultHeader={false}
|
||||
/>
|
||||
@@ -154,9 +154,9 @@ export function FilteredComponentsExample() {
|
||||
}
|
||||
|
||||
export const FilteredComponentsExampleProps = {
|
||||
instanceUrl: '{from environment variables}',
|
||||
apiBaseUrl: '{from environment variables}',
|
||||
token: '{from environment variables}',
|
||||
flow: 'FlowData',
|
||||
initialFlow: 'FlowData',
|
||||
components: 'string[] (preset-based)',
|
||||
showDefaultHeader: false
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { useRef } from 'react'
|
||||
import type { AgentFlowInstance, FlowData } from '@flowise/agentflow'
|
||||
import { Agentflow } from '@flowise/agentflow'
|
||||
|
||||
import { instanceUrl, token } from '../config'
|
||||
import { apiBaseUrl, token } from '../config'
|
||||
|
||||
// A complete translation agent flow
|
||||
const translationFlow: FlowData = {
|
||||
@@ -152,9 +152,9 @@ export function MultiNodeFlow() {
|
||||
<div style={{ width: '100%', height: '100vh' }}>
|
||||
<Agentflow
|
||||
ref={agentflowRef}
|
||||
instanceUrl={instanceUrl}
|
||||
apiBaseUrl={apiBaseUrl}
|
||||
token={token ?? undefined}
|
||||
flow={translationFlow}
|
||||
initialFlow={translationFlow}
|
||||
showDefaultHeader={true}
|
||||
onFlowChange={(flow) => console.log('Flow changed:', flow.nodes.length, 'nodes')}
|
||||
/>
|
||||
@@ -163,9 +163,9 @@ export function MultiNodeFlow() {
|
||||
}
|
||||
|
||||
export const MultiNodeFlowProps = {
|
||||
instanceUrl: '{from environment variables}',
|
||||
apiBaseUrl: '{from environment variables}',
|
||||
token: '{from environment variables}',
|
||||
flow: 'FlowData (multiple nodes)',
|
||||
initialFlow: 'FlowData (multiple nodes)',
|
||||
showDefaultHeader: true,
|
||||
onFlowChange: '(flow: FlowData) => void'
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import { useRef, useState } from 'react'
|
||||
import type { AgentFlowInstance, FlowData, FlowNode } from '@flowise/agentflow'
|
||||
import { Agentflow } from '@flowise/agentflow'
|
||||
|
||||
import { instanceUrl, token } from '../config'
|
||||
import { apiBaseUrl, token } from '../config'
|
||||
|
||||
const createFlowWithStatuses = (): FlowData => ({
|
||||
nodes: [
|
||||
@@ -237,9 +237,9 @@ export function StatusIndicatorsExample() {
|
||||
<div style={{ flex: 1 }}>
|
||||
<Agentflow
|
||||
ref={agentflowRef}
|
||||
instanceUrl={instanceUrl}
|
||||
apiBaseUrl={apiBaseUrl}
|
||||
token={token ?? undefined}
|
||||
flow={flow}
|
||||
initialFlow={flow}
|
||||
showDefaultHeader={false}
|
||||
readOnly={true}
|
||||
/>
|
||||
@@ -249,9 +249,9 @@ export function StatusIndicatorsExample() {
|
||||
}
|
||||
|
||||
export const StatusIndicatorsExampleProps = {
|
||||
instanceUrl: '{from environment variables}',
|
||||
apiBaseUrl: '{from environment variables}',
|
||||
token: '{from environment variables}',
|
||||
flow: 'FlowData (status indicators)',
|
||||
initialFlow: 'FlowData (status indicators)',
|
||||
showDefaultHeader: false,
|
||||
readOnly: true
|
||||
}
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
"dev:example": "vite --config examples/vite.config.ts",
|
||||
"format": "prettier --write \"{src,examples}/**/*.{ts,tsx,js,jsx,json,css,md}\"",
|
||||
"format:check": "prettier --check \"{src,examples}/**/*.{ts,tsx,js,jsx,json,css,md}\"",
|
||||
"lint": "eslint \"{src,examples/src}/**/*.{js,jsx,ts,tsx}\"",
|
||||
"lint:fix": "eslint \"{src,examples/src}/**/*.{js,jsx,ts,tsx}\" --fix",
|
||||
"lint": "eslint \"{src,examples/src}/**/*.{js,jsx,ts,tsx,json,md}\"",
|
||||
"lint:fix": "eslint \"{src,examples/src}/**/*.{js,jsx,ts,tsx,json,md}\" --fix",
|
||||
"test": "jest",
|
||||
"test:watch": "jest --watch",
|
||||
"test:coverage": "jest --coverage",
|
||||
|
||||
@@ -203,7 +203,7 @@ function AgentflowCanvas({
|
||||
* function App() {
|
||||
* return (
|
||||
* <Agentflow
|
||||
* instanceUrl="https://flowise-url.com"
|
||||
* apiBaseUrl="https://flowise-url.com"
|
||||
* token="your-auth-token"
|
||||
* components={['agentAgentflow', 'llmAgentflow']}
|
||||
* />
|
||||
@@ -213,9 +213,9 @@ function AgentflowCanvas({
|
||||
*/
|
||||
export const Agentflow = forwardRef<AgentFlowInstance, AgentflowProps>(function Agentflow(props, ref) {
|
||||
const {
|
||||
instanceUrl,
|
||||
apiBaseUrl,
|
||||
token,
|
||||
flow,
|
||||
initialFlow,
|
||||
components,
|
||||
onFlowChange,
|
||||
onSave,
|
||||
@@ -231,17 +231,17 @@ export const Agentflow = forwardRef<AgentFlowInstance, AgentflowProps>(function
|
||||
|
||||
return (
|
||||
<AgentflowProvider
|
||||
instanceUrl={instanceUrl}
|
||||
apiBaseUrl={apiBaseUrl}
|
||||
token={token}
|
||||
theme={theme}
|
||||
components={components}
|
||||
readOnly={readOnly}
|
||||
initialFlow={flow}
|
||||
initialFlow={initialFlow}
|
||||
>
|
||||
<ReactFlowProvider>
|
||||
<AgentflowCanvasWithRef
|
||||
ref={ref}
|
||||
initialFlow={flow}
|
||||
initialFlow={initialFlow}
|
||||
readOnly={readOnly}
|
||||
onFlowChange={onFlowChange}
|
||||
onSave={onSave}
|
||||
|
||||
@@ -5,8 +5,8 @@ import type { FlowData } from './core/types'
|
||||
import { AgentflowStateProvider, ApiProvider, ConfigProvider } from './infrastructure/store'
|
||||
|
||||
interface AgentflowProviderProps {
|
||||
/** Base URL of the Flowise server */
|
||||
instanceUrl: string
|
||||
/** Flowise API server endpoint */
|
||||
apiBaseUrl: string
|
||||
/** Authentication token for API calls */
|
||||
token?: string
|
||||
/** Theme override */
|
||||
@@ -26,7 +26,7 @@ interface AgentflowProviderProps {
|
||||
* Sets up all required contexts for API access, configuration, and state management.
|
||||
*/
|
||||
export function AgentflowProvider({
|
||||
instanceUrl,
|
||||
apiBaseUrl,
|
||||
token,
|
||||
theme = 'system',
|
||||
components,
|
||||
@@ -36,7 +36,7 @@ export function AgentflowProvider({
|
||||
}: AgentflowProviderProps) {
|
||||
return (
|
||||
<ReactFlowProvider>
|
||||
<ApiProvider instanceUrl={instanceUrl} token={token}>
|
||||
<ApiProvider apiBaseUrl={apiBaseUrl} token={token}>
|
||||
<ConfigProvider theme={theme} components={components} readOnly={readOnly}>
|
||||
<AgentflowStateProvider initialFlow={initialFlow}>{children}</AgentflowStateProvider>
|
||||
</ConfigProvider>
|
||||
|
||||
@@ -174,14 +174,14 @@ export interface PaletteRenderProps {
|
||||
// ============================================================================
|
||||
|
||||
export interface AgentflowProps {
|
||||
/** Base URL of the Flowise server (e.g., "https://flowise-url.com") */
|
||||
instanceUrl: string
|
||||
/** Flowise API server endpoint (e.g., "https://flowise-url.com") */
|
||||
apiBaseUrl: string
|
||||
|
||||
/** Authentication token for API calls */
|
||||
token?: string
|
||||
|
||||
/** Initial flow data to render */
|
||||
flow?: FlowData
|
||||
initialFlow?: FlowData
|
||||
|
||||
/** Flow ID for loading existing flow */
|
||||
flowId?: string
|
||||
@@ -253,7 +253,7 @@ export interface AgentFlowInstance {
|
||||
|
||||
export interface ApiContextValue {
|
||||
client: AxiosInstance
|
||||
instanceUrl: string
|
||||
apiBaseUrl: string
|
||||
}
|
||||
|
||||
export interface ConfigContextValue {
|
||||
|
||||
@@ -5,10 +5,10 @@ import { renderNodeIcon } from '../nodeIcons'
|
||||
|
||||
export interface NodeIconProps {
|
||||
data: NodeData
|
||||
instanceUrl: string
|
||||
apiBaseUrl: string
|
||||
}
|
||||
|
||||
function NodeIconComponent({ data, instanceUrl }: NodeIconProps) {
|
||||
function NodeIconComponent({ data, apiBaseUrl }: NodeIconProps) {
|
||||
if (data.color && !data.icon) {
|
||||
return (
|
||||
<div
|
||||
@@ -41,7 +41,7 @@ function NodeIconComponent({ data, instanceUrl }: NodeIconProps) {
|
||||
>
|
||||
<img
|
||||
style={{ width: '100%', height: '100%', padding: 5, objectFit: 'contain' }}
|
||||
src={`${instanceUrl}/api/v1/node-icon/${data.name}`}
|
||||
src={`${apiBaseUrl}/api/v1/node-icon/${data.name}`}
|
||||
alt={data.name}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -17,7 +17,7 @@ export interface NodeModelConfigsProps {
|
||||
* Displays model configuration badges on a node
|
||||
*/
|
||||
function NodeModelConfigsComponent({ inputs }: NodeModelConfigsProps) {
|
||||
const { instanceUrl } = useApiContext()
|
||||
const { apiBaseUrl } = useApiContext()
|
||||
const { isDarkMode } = useConfigContext()
|
||||
|
||||
if (!inputs) return null
|
||||
@@ -51,7 +51,7 @@ function NodeModelConfigsComponent({ inputs }: NodeModelConfigsProps) {
|
||||
>
|
||||
<img
|
||||
style={{ width: 20, height: 20, objectFit: 'contain' }}
|
||||
src={`${instanceUrl}/api/v1/node-icon/${item.model}`}
|
||||
src={`${apiBaseUrl}/api/v1/node-icon/${item.model}`}
|
||||
alt={item.model as string}
|
||||
/>
|
||||
<Typography sx={{ fontSize: '0.7rem', ml: 0.5 }}>{item.config?.modelName || item.config?.model}</Typography>
|
||||
|
||||
@@ -24,7 +24,7 @@ export interface AgentFlowNodeProps {
|
||||
*/
|
||||
function AgentFlowNodeComponent({ data }: AgentFlowNodeProps) {
|
||||
const { isDarkMode } = useConfigContext()
|
||||
const { instanceUrl } = useApiContext()
|
||||
const { apiBaseUrl } = useApiContext()
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
const updateNodeInternals = useUpdateNodeInternals()
|
||||
|
||||
@@ -99,7 +99,7 @@ function AgentFlowNodeComponent({ data }: AgentFlowNodeProps) {
|
||||
|
||||
<div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
|
||||
<Box style={{ padding: 10 }}>
|
||||
<NodeIcon data={data} instanceUrl={instanceUrl} />
|
||||
<NodeIcon data={data} apiBaseUrl={apiBaseUrl} />
|
||||
</Box>
|
||||
<Box>
|
||||
<Typography
|
||||
|
||||
@@ -25,7 +25,7 @@ export interface IterationNodeProps {
|
||||
function IterationNodeComponent({ data }: IterationNodeProps) {
|
||||
const theme = useTheme()
|
||||
const { isDarkMode } = useConfigContext()
|
||||
const { instanceUrl } = useApiContext()
|
||||
const { apiBaseUrl } = useApiContext()
|
||||
const { state } = useAgentflowContext()
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
const reactFlowWrapper = useRef<HTMLDivElement>(null)
|
||||
@@ -83,7 +83,7 @@ function IterationNodeComponent({ data }: IterationNodeProps) {
|
||||
<div ref={ref} onMouseEnter={() => setIsHovered(true)} onMouseLeave={() => setIsHovered(false)}>
|
||||
<NodeToolbar align='start' isVisible={true}>
|
||||
<Box style={{ display: 'flex', alignItems: 'center', flexDirection: 'row' }}>
|
||||
<NodeIcon data={data} instanceUrl={instanceUrl} />
|
||||
<NodeIcon data={data} apiBaseUrl={apiBaseUrl} />
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: '0.85rem',
|
||||
|
||||
@@ -44,7 +44,7 @@ interface ChatModel {
|
||||
*/
|
||||
function GenerateFlowDialogComponent({ open, onClose, onGenerated }: GenerateFlowDialogProps) {
|
||||
const theme = useTheme()
|
||||
const { chatflowsApi, instanceUrl } = useApiContext()
|
||||
const { chatflowsApi, apiBaseUrl } = useApiContext()
|
||||
const { isDarkMode: _isDarkMode } = useConfigContext()
|
||||
|
||||
const [prompt, setPrompt] = useState('')
|
||||
@@ -235,7 +235,7 @@ function GenerateFlowDialogComponent({ open, onClose, onGenerated }: GenerateFlo
|
||||
<MenuItem key={model.name} value={model.name}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||
<img
|
||||
src={`${instanceUrl}/api/v1/node-icon/${model.name}`}
|
||||
src={`${apiBaseUrl}/api/v1/node-icon/${model.name}`}
|
||||
alt={model.label}
|
||||
style={{ width: 24, height: 24, borderRadius: '50%' }}
|
||||
onError={(e) => {
|
||||
|
||||
@@ -47,7 +47,7 @@ export interface AddNodesDrawerProps {
|
||||
*/
|
||||
function AddNodesDrawerComponent({ nodes, onDragStart, onNodeClick }: AddNodesDrawerProps) {
|
||||
const theme = useTheme()
|
||||
const { instanceUrl } = useApiContext()
|
||||
const { apiBaseUrl } = useApiContext()
|
||||
const { isDarkMode: _isDarkMode } = useConfigContext()
|
||||
|
||||
const [searchValue, setSearchValue] = useState('')
|
||||
@@ -331,7 +331,7 @@ function AddNodesDrawerComponent({ nodes, onDragStart, onNodeClick }: AddNodesDr
|
||||
objectFit: 'contain'
|
||||
}}
|
||||
alt={node.name}
|
||||
src={`${instanceUrl}/api/v1/node-icon/${node.name}`}
|
||||
src={`${apiBaseUrl}/api/v1/node-icon/${node.name}`}
|
||||
/>
|
||||
</div>
|
||||
</ListItemAvatar>
|
||||
|
||||
@@ -2,10 +2,10 @@ import axios, { AxiosInstance } from 'axios'
|
||||
|
||||
/**
|
||||
* Creates a configured axios client for API calls
|
||||
* @param instanceUrl - Base URL of the Flowise server
|
||||
* @param apiBaseUrl - Base URL of the Flowise server
|
||||
* @param token - Authentication token (optional)
|
||||
*/
|
||||
export function createApiClient(instanceUrl: string, token?: string): AxiosInstance {
|
||||
export function createApiClient(apiBaseUrl: string, token?: string): AxiosInstance {
|
||||
const headers: Record<string, string> = {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
@@ -15,7 +15,7 @@ export function createApiClient(instanceUrl: string, token?: string): AxiosInsta
|
||||
}
|
||||
|
||||
const client = axios.create({
|
||||
baseURL: `${instanceUrl}/api/v1`,
|
||||
baseURL: `${apiBaseUrl}/api/v1`,
|
||||
headers
|
||||
})
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import { type ChatflowsApi, createApiClient, createChatflowsApi, createNodesApi,
|
||||
|
||||
interface ApiContextValue {
|
||||
client: AxiosInstance
|
||||
instanceUrl: string
|
||||
apiBaseUrl: string
|
||||
nodesApi: NodesApi
|
||||
chatflowsApi: ChatflowsApi
|
||||
}
|
||||
@@ -14,24 +14,24 @@ interface ApiContextValue {
|
||||
const ApiContext = createContext<ApiContextValue | null>(null)
|
||||
|
||||
interface ApiProviderProps {
|
||||
instanceUrl: string
|
||||
apiBaseUrl: string
|
||||
token?: string
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
export function ApiProvider({ instanceUrl, token, children }: ApiProviderProps) {
|
||||
export function ApiProvider({ apiBaseUrl, token, children }: ApiProviderProps) {
|
||||
const value = useMemo(() => {
|
||||
const client = createApiClient(instanceUrl, token)
|
||||
const client = createApiClient(apiBaseUrl, token)
|
||||
const nodesApi = createNodesApi(client)
|
||||
const chatflowsApi = createChatflowsApi(client)
|
||||
|
||||
return {
|
||||
client,
|
||||
instanceUrl,
|
||||
apiBaseUrl,
|
||||
nodesApi,
|
||||
chatflowsApi
|
||||
}
|
||||
}, [instanceUrl, token])
|
||||
}, [apiBaseUrl, token])
|
||||
|
||||
return <ApiContext.Provider value={value}>{children}</ApiContext.Provider>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user