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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ examples/local/*
node_modules/
.vite
flo_ai/usecases
.env
File renamed without changes.
34 changes: 34 additions & 0 deletions docker-compose.dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
version: '3.8'

services:
postgres:
image: ankane/pgvector
container_name: postgres
restart: always
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=floware
ports:
- '5432:5432'
volumes:
- /var/lib/postgres-data:/var/lib/postgresql/data
- /var/lib/init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- floware-network

redis:
image: redis:7.4
container_name: redis
ports:
- "6379:6379"
networks:
- floware-network

volumes:
db:
driver: local

networks:
floware-network:
driver: bridge
File renamed without changes.
5 changes: 3 additions & 2 deletions wavefront/client/server.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const path = require('path');

const PORT = process.env.PORT || 3000;
const NAMESPACE = process.env.NAMESPACE || 'staging-aws';
const BASE_URL = process.env.BASE_URL || `https://${NAMESPACE}.rootflo.ai/wavefront`;
const BASE_URL = process.env.BASE_URL || `https://${NAMESPACE}.rootflo.ai/floconsole`;
const APP_ENV = process.env.APP_ENV || 'production';
const FEATURE_API_SERVICES = process.env.FEATURE_API_SERVICES || 'false';

Expand Down Expand Up @@ -51,6 +51,7 @@ app.get('*', (req, res) => {
// Generate nonce for CSP
const nonce = crypto.randomBytes(16).toString('base64');
const defaultSrc = `'self'`;
const connectSrc = `'self' ${new URL(BASE_URL).origin}`;
const scriptSrc = `'self' 'nonce-${nonce}'`;
const styleSrc = `'self' 'unsafe-inline'`;
const mediaSrc = `'self' https://storage.googleapis.com https://*.s3.amazonaws.com`;
Expand All @@ -61,7 +62,7 @@ app.get('*', (req, res) => {
'Cache-Control': 'no-store, no-cache, must-revalidate, private',
Pragma: 'no-cache',
Expires: '0',
'Content-Security-Policy': `default-src ${defaultSrc}; script-src ${scriptSrc}; style-src ${styleSrc}; frame-ancestors ${frameAncestors}; img-src ${imgSrc}; media-src ${mediaSrc}`,
'Content-Security-Policy': `default-src ${defaultSrc}; connect-src ${connectSrc} script-src ${scriptSrc}; style-src ${styleSrc}; frame-ancestors ${frameAncestors}; img-src ${imgSrc}; media-src ${mediaSrc}`,
'X-Content-Type-Options': 'nosniff',
'Strict-Transport-Security': 'max-age=63072000; includeSubDomains; preload',
});
Expand Down
8 changes: 6 additions & 2 deletions wavefront/client/src/api/app-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,12 @@ export class AppService {
return response;
}

async deleteApp(appId: string): Promise<DeleteAppResponse> {
const response: IApiResponse<DeleteAppData> = await this.http.delete(`/v1/apps/${appId}`);
async deleteApp(appId: string, deleteDeployment: boolean): Promise<DeleteAppResponse> {
const response: IApiResponse<DeleteAppData> = await this.http.delete(`/v1/apps/${appId}`, {
params: {
delete_deployment: deleteDeployment,
},
});
return response;
}

Expand Down
4 changes: 3 additions & 1 deletion wavefront/client/src/components/AppCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ const AppCard: React.FC<AppCardProps> = ({ app, onClick, onDeleteClick }) => {
<p className="text-xl font-medium text-[#101010]">{app.app_name}</p>
<p className="truncate text-base font-normal text-[#878787]">{app.public_url}</p>
</div>
<div className="text-sm font-normal text-[#B8B8B8]">{dayjs(app.updated_at).format('DD MMM YYYY')}</div>
<div className="text-sm font-normal text-[#B8B8B8]">
Updated on {dayjs(app.updated_at || app.created_at).format('DD/MM/YYYY')}
</div>
</div>
);
};
Expand Down
129 changes: 65 additions & 64 deletions wavefront/client/src/pages/apps/[appId]/agents/[id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,6 @@ const AgentDetail: React.FC = () => {
setUploadedImages([]);
} catch (error) {
console.error('Error running inference:', error);
notifyError('Failed to run inference. Please try again.');
} finally {
setRunningInference(false);
}
Expand Down Expand Up @@ -516,7 +515,7 @@ const AgentDetail: React.FC = () => {
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>{agent?.name || id}</BreadcrumbPage>
<BreadcrumbPage>{agent?.name}</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
Expand All @@ -526,71 +525,73 @@ const AgentDetail: React.FC = () => {
) : !agent ? (
<div className="flex items-center justify-center p-8 text-red-600">Agent not found</div>
) : (
<div className="flex w-full flex-1 flex-col gap-10">
<div className="flex items-start justify-between">
<p className="text-2xl leading-normal font-semibold text-black">{agent.name}</p>
<div className="flex gap-4">
<Button variant="outline" onClick={() => setEditDialogOpen(true)}>
Edit
</Button>
<Button variant="destructive" onClick={handleDeleteClick}>
Delete
</Button>
<>
<div className="flex w-full flex-1 flex-col gap-10">
<div className="flex items-start justify-between">
<p className="text-2xl leading-normal font-semibold text-black">{agent.name}</p>
<div className="flex gap-4">
<Button variant="outline" onClick={() => setEditDialogOpen(true)}>
Edit
</Button>
<Button variant="destructive" onClick={handleDeleteClick}>
Delete
</Button>
</div>
</div>
</div>
</div>
)}

<ChatBot
chatHistory={chatHistory}
runningInference={runningInference}
selectedLLMConfigId={selectedLLMConfigId}
setSelectedLLMConfigId={setSelectedLLMConfigId}
loadingConfigs={loadingConfigs}
llmConfigs={llmConfigs}
uploadedImages={uploadedImages}
uploadedDocuments={uploadedDocuments}
handleRemoveImage={handleRemoveImage}
handleRemoveDocument={handleRemoveDocument}
showUploadMenu={showUploadMenu}
setShowUploadMenu={setShowUploadMenu}
inferenceInput={inferenceInput}
setInferenceInput={setInferenceInput}
inferenceVariables={inferenceVariables}
setInferenceVariables={setInferenceVariables}
showVariablesInput={showVariablesInput}
setShowVariablesInput={setShowVariablesInput}
handleQuestionEntered={handleQuestionEntered}
handleImageUpload={handleImageUpload}
handleDocumentUpload={handleDocumentUpload}
uploadingImage={uploadingImage}
uploadingDocument={uploadingDocument}
/>

{/* Edit Agent Dialog */}
<EditAgentDialog
isOpen={editDialogOpen}
onOpenChange={setEditDialogOpen}
yamlContent={yamlContent}
selectedTools={selectedTools}
toolsDetails={toolsDetails}
onSave={async (updatedYamlContent, updatedSelectedTools) => {
setYamlContent(updatedYamlContent);
setSelectedTools(updatedSelectedTools);
handleSave(updatedYamlContent);
}}
saving={saving}
/>

{/* Delete Confirmation Dialog */}
<DeleteConfirmationDialog
isOpen={!!deleteItem}
title="Delete Agent"
message={`Are you sure you want to delete "${deleteItem?.name}"? This action cannot be undone.`}
onConfirm={handleDeleteConfirm}
onCancel={() => setDeleteItem(null)}
loading={deleteAgentMutation.isPending}
/>
<ChatBot
chatHistory={chatHistory}
runningInference={runningInference}
selectedLLMConfigId={selectedLLMConfigId}
setSelectedLLMConfigId={setSelectedLLMConfigId}
loadingConfigs={loadingConfigs}
llmConfigs={llmConfigs}
uploadedImages={uploadedImages}
uploadedDocuments={uploadedDocuments}
handleRemoveImage={handleRemoveImage}
handleRemoveDocument={handleRemoveDocument}
showUploadMenu={showUploadMenu}
setShowUploadMenu={setShowUploadMenu}
inferenceInput={inferenceInput}
setInferenceInput={setInferenceInput}
inferenceVariables={inferenceVariables}
setInferenceVariables={setInferenceVariables}
showVariablesInput={showVariablesInput}
setShowVariablesInput={setShowVariablesInput}
handleQuestionEntered={handleQuestionEntered}
handleImageUpload={handleImageUpload}
handleDocumentUpload={handleDocumentUpload}
uploadingImage={uploadingImage}
uploadingDocument={uploadingDocument}
/>

{/* Edit Agent Dialog */}
<EditAgentDialog
isOpen={editDialogOpen}
onOpenChange={setEditDialogOpen}
yamlContent={yamlContent}
selectedTools={selectedTools}
toolsDetails={toolsDetails}
onSave={async (updatedYamlContent, updatedSelectedTools) => {
setYamlContent(updatedYamlContent);
setSelectedTools(updatedSelectedTools);
handleSave(updatedYamlContent);
}}
saving={saving}
/>

{/* Delete Confirmation Dialog */}
<DeleteConfirmationDialog
isOpen={!!deleteItem}
title="Delete Agent"
message={`Are you sure you want to delete "${deleteItem?.name}"? This action cannot be undone.`}
onConfirm={handleDeleteConfirm}
onCancel={() => setDeleteItem(null)}
loading={deleteAgentMutation.isPending}
/>
</>
)}
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { useQueryClient } from '@tanstack/react-query';
import React, { useState } from 'react';
import { useNavigate, useParams } from 'react-router';
import CreateModelInferenceDialog from './CreateModelInferenceDialog';
import { Alert, AlertDescription, AlertTitle } from '@app/components/ui/alert';

const ModelManagement: React.FC = () => {
const { app: appId } = useParams<{ app: string }>();
Expand Down Expand Up @@ -140,6 +141,12 @@ const ModelManagement: React.FC = () => {
<Button onClick={handleCreateModel}>Upload Model</Button>
</div>
</div>
<div>
<Alert variant="info">
<AlertTitle> Coming soon</AlertTitle>
<AlertDescription>This feature is currently in alpha and is not ready for production.</AlertDescription>
</Alert>
</div>
<div className="grid gap-6 overflow-y-auto py-2 sm:grid-cols-2 lg:grid-cols-3">
{loading ? (
<>
Expand Down
1 change: 0 additions & 1 deletion wavefront/client/src/pages/apps/[appId]/workflows/[id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,6 @@ const WorkflowDetail: React.FC = () => {
}
} catch (error) {
console.error('Error running inference:', error);
notifyError('Failed to run inference. Please try again.');
} finally {
if (!listenEventsEnabled) {
setRunningInference(false);
Expand Down
6 changes: 2 additions & 4 deletions wavefront/client/src/pages/apps/create.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type TCreateAppInputSchema = z.infer<typeof createAppSchema>;

const CreateApp: React.FC = () => {
const navigate = useNavigate();
const { notifySuccess, notifyError } = useNotifyStore();
const { notifySuccess } = useNotifyStore();

const [creating, setCreating] = useState(false);
const [pollingAppId, setPollingAppId] = useState<string | null>(null);
Expand Down Expand Up @@ -58,10 +58,9 @@ const CreateApp: React.FC = () => {
}
setPollingAppId(null);
setCreating(false);
notifyError('Failed to check app status');
}
},
[notifySuccess, notifyError, navigate]
[navigate]
);

// Effect to handle polling
Expand Down Expand Up @@ -116,7 +115,6 @@ const CreateApp: React.FC = () => {
}
} catch (error) {
console.error('Error creating app:', error);
notifyError('Failed to create app');
setCreating(false);
}
};
Expand Down
3 changes: 2 additions & 1 deletion wavefront/client/src/pages/apps/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ const Dashboard: React.FC = () => {

setDeleting(true);
try {
await floConsoleService.appService.deleteApp(deleteItem.id);
const deleteDeployment = deleteItem.deployment_type === 'auto';
await floConsoleService.appService.deleteApp(deleteItem.id, deleteDeployment);
notifySuccess(`App "${deleteItem.app_name}" deleted successfully`);

// Refresh the apps list
Expand Down
9 changes: 7 additions & 2 deletions wavefront/client/src/pages/apps/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ const navItems = [
icon: ModelInferenceIcon,
link: `/apps/:appId/model-inference`,
description: 'Manage and configure model inference for this application',
alpha: true,
},
{
id: 'knowledge-bases',
Expand Down Expand Up @@ -120,9 +121,13 @@ const AppLayout: React.FC = () => {
<div className="flex items-center gap-2">
<item.icon color={isActive ? '#000' : '#fff'} />
<p
className={clsx(isActive ? 'font-medium text-[#101010]' : 'font-normal text-[#585858]', 'text-sm')}
className={clsx(
isActive ? 'font-medium text-[#101010]' : 'font-normal text-[#585858]',
'flex items-center gap-2 text-sm'
)}
>
{item.name}
<span>{item.name}</span>
{item.alpha && <span className="mb-2 text-[10px] text-green-500">alpha</span>}
</p>
</div>
<div
Expand Down
1 change: 1 addition & 0 deletions wavefront/client/src/types/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { IApiResponse } from '@app/lib/axios';
export interface App {
id: string;
app_name: string;
deployment_type: string;
created_at: string;
config: Record<string, string>;
public_url: string;
Expand Down
2 changes: 1 addition & 1 deletion wavefront/server/modules/agents_module/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ dependencies = [
"flo-utils",
"tools-module",
"api-services-module",
"flo-ai==1.1.0-rc5",
"flo-ai==1.1.0-rc6",
]

[tool.uv.sources]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ dependencies = [
"pandas~=2.2.3",
"ollama~=0.4.8",
"textract~=1.6.5",
"flo-ai==1.1.0-rc5",
"flo-ai==1.1.0-rc6",
"google-cloud-pubsub~=2.30.0",
"boto3<=1.38.40",
"pyyaml>=6.0.3,<7",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,5 @@ async def execute_message_processor(
except Exception as e:
return JSONResponse(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
content=response_formatter.buildErrorResponse(
f'Error executing message processor: {str(e)}'
),
content=response_formatter.buildErrorResponse(str(e)),
)
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,10 @@ def _do_request():
},
timeout=10,
)
resp.raise_for_status()
return resp.json()
resp_json = resp.json()
if resp.status_code != 200:
raise Exception(resp_json['details'])
return resp_json

loop = asyncio.get_running_loop()
return await loop.run_in_executor(None, _do_request)
Expand Down
2 changes: 1 addition & 1 deletion wavefront/server/modules/tools_module/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "tools_module"
version = "0.1.0"
description = "Tools module for Flo AI agent system"
dependencies = [
"flo-ai==1.1.0-rc5",
"flo-ai==1.1.0-rc6",
"flo_cloud",

"datasource",
Expand Down
Loading