Skip to content

Commit

Permalink
Merge pull request #419 from airtai/dev
Browse files Browse the repository at this point in the history
  • Loading branch information
kumaranvpl authored Jun 25, 2024
2 parents 0d5aa3c + 5d9d8f6 commit 477cffd
Show file tree
Hide file tree
Showing 24 changed files with 149 additions and 124 deletions.
4 changes: 2 additions & 2 deletions app/src/client/app/BuildPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import LLMs from '../components/buildPage/LLMs';
import Agents from '../components/buildPage/Agents';
import Teams from '../components/buildPage/Teams';
import ToolBoxes from '../components/buildPage/ToolBoxes';
import Application from '../components/buildPage/Applications';
import Deployment from '../components/buildPage/Deployments';
import LoadingComponent from '../components/LoadingComponent';
import { useBuildPage } from '../hooks/useBuildPage';
import { filerOutComponentData } from '../utils/buildPageUtils';
Expand All @@ -31,7 +31,7 @@ const componentsMap: componentsMapType = {
agent: Agents,
team: Teams,
toolbox: ToolBoxes,
application: Application,
deployment: Deployment,
};

interface HeaderProps {
Expand Down
2 changes: 1 addition & 1 deletion app/src/client/components/CustomSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ export const navLinkItems: NavLinkItem[] = [
<line className='st0' x1='1' y1='6' x2='17' y2='6' />
</svg>
),
componentName: 'application',
componentName: 'deployment',
},
];

Expand Down
28 changes: 14 additions & 14 deletions app/src/client/components/DynamicFormBuilder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,19 +90,19 @@ const DynamicFormBuilder: React.FC<DynamicFormBuilderProps> = ({
});
const [refValues, setRefValues] = useState<Record<string, any>>({});
const [missingDependency, setMissingDependency] = useState<string[]>([]);
const [instructionForApplication, setInstructionForApplication] = useState<Record<string, string> | null>(null);
const [instructionForDeployment, setInstructionForDeployment] = useState<Record<string, string> | null>(null);
const cancelButtonRef = useRef<HTMLButtonElement>(null);

const isApplication = type_name === 'application';
const isDeployment = type_name === 'deployment';

const missingDependencyNotificationMsg = `Please create atleast one item of type "${missingDependency.join(
', '
)}" to proceed.`;

const handleSubmit = async (event: React.FormEvent) => {
event.preventDefault();
// Avoid creating duplicate applications
if (instructionForApplication && !updateExistingModel) {
// Avoid creating duplicate deployments
if (instructionForDeployment && !updateExistingModel) {
return;
}
setIsLoading(true);
Expand All @@ -118,9 +118,9 @@ const DynamicFormBuilder: React.FC<DynamicFormBuilderProps> = ({
const response = await validateForm(formDataToSubmit, validationURL, isSecretUpdate);
const onSuccessCallbackResponse: any = await onSuccessCallback(response);

isApplication &&
isDeployment &&
!updateExistingModel &&
setInstructionForApplication((prevState) => ({
setInstructionForDeployment((prevState) => ({
...prevState,
gh_repo_url: response.gh_repo_url,
// @ts-ignore
Expand Down Expand Up @@ -191,11 +191,11 @@ const DynamicFormBuilder: React.FC<DynamicFormBuilderProps> = ({
}, [missingDependency?.length]);

useEffect(() => {
if (updateExistingModel && type_name === 'application') {
if (updateExistingModel && type_name === 'deployment') {
const msg = deploymentInprogressInstructions;

//@ts-ignore
setInstructionForApplication((prevState) => ({
setInstructionForDeployment((prevState) => ({
...prevState,
gh_repo_url: updateExistingModel.gh_repo_url,
flyio_app_url: updateExistingModel.flyio_app_url,
Expand All @@ -206,7 +206,7 @@ const DynamicFormBuilder: React.FC<DynamicFormBuilderProps> = ({
.replaceAll('<flyio_app_url>', updateExistingModel.flyio_app_url),
}));
}
}, [isApplication]);
}, [isDeployment]);

useEffect(() => {
const keyHandler = (event: KeyboardEvent) => {
Expand Down Expand Up @@ -243,12 +243,12 @@ Before you begin, ensure you have the following:

return (
<>
{!instructionForApplication && isApplication && (
{!instructionForDeployment && isDeployment && (
<div className='w-full mt-8 px-6.5 py-2'>
<AgentConversationHistory
agentConversationHistory={appDeploymentPrerequisites}
isDeploymentInstructions={true}
containerTitle='Prerequisites for Application Generation and Deployment'
containerTitle='Prerequisites for Deployment Generation and Deployment'
/>
</div>
)}
Expand Down Expand Up @@ -309,12 +309,12 @@ Before you begin, ensure you have the following:
</div>
);
})}
{instructionForApplication && instructionForApplication.instruction && (
{instructionForDeployment && instructionForDeployment.instruction && (
<div className='w-full mt-8'>
<AgentConversationHistory
agentConversationHistory={instructionForApplication.instruction}
agentConversationHistory={instructionForDeployment.instruction}
isDeploymentInstructions={true}
containerTitle='Application Details and Next Steps'
containerTitle='Deployment Details and Next Steps'
/>
</div>
)}
Expand Down
2 changes: 1 addition & 1 deletion app/src/client/components/ModelItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const ModelItem: React.FC<ModelItemProps> = ({ model, onClick }) => {
const svgClassName =
model.type_name === ('llm' || 'secret')
? 'text-airt-primary mt-1 ml-1'
: model.type_name === 'application'
: model.type_name === 'deployment'
? 'text-airt-primary mt-1 ml-2'
: 'text-airt-primary ml-1';
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import CustomBreadcrumb from '../CustomBreadcrumb';
import UserPropertyHandler from './UserPropertyHandler';
import { SecretsProps } from '../../interfaces/BuildPageInterfaces';

const Applications = ({ data }: SecretsProps) => {
const Deployments = ({ data }: SecretsProps) => {
return (
<>
<CustomBreadcrumb pageName='Deployments' />
Expand All @@ -18,4 +18,4 @@ const Applications = ({ data }: SecretsProps) => {
);
};

export default Applications;
export default Deployments;
11 changes: 3 additions & 8 deletions app/src/client/components/buildPage/UserPropertyHandler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ const UserPropertyHandler = ({ data }: SecretsProps) => {
addUserModelResponse = await addUserModels(filteredData);
}
refetchModels();
const isNewApplicationAdded = propertyName === 'application' && !updateExistingModel;
!isNewApplicationAdded && setShowAddModel(false);
const isNewDeploymentAdded = propertyName === 'deployment' && !updateExistingModel;
!isNewDeploymentAdded && setShowAddModel(false);
} catch (error) {
console.log('error: ', error, 'error.message: ');
// setNotificationErrorMessage(`Error adding/updating ${propertyName}. Please try again later.`);
Expand Down Expand Up @@ -140,12 +140,7 @@ const UserPropertyHandler = ({ data }: SecretsProps) => {
setNotificationErrorMessage(null);
};

const propertyHeader =
propertyName === 'llm'
? 'LLM'
: propertyName === 'application'
? 'Deployment'
: capitalizeFirstLetter(propertyName);
const propertyHeader = propertyName === 'llm' ? 'LLM' : capitalizeFirstLetter(propertyName);

return (
<div className='flex-col flex items-start p-6 gap-3 w-full'>
Expand Down
2 changes: 1 addition & 1 deletion app/src/client/tests/buildPageUtils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1606,7 +1606,7 @@ describe('buildPageUtils', () => {
$ref: '#/$defs/TwoAgentTeamRef',
},
],
description: 'The team that is used in the application',
description: 'The team that is used in the deployment',
title: 'Team name',
};
const expected = ['#/$defs/TwoAgentTeamRef'];
Expand Down
2 changes: 1 addition & 1 deletion app/src/client/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ export const propertyDependencyMap: PropertyDependencyMapProps = deepFreeze({
toolbox: [''],
agent: ['secret', 'llm'],
team: ['secret', 'llm', 'agent'],
application: ['secret', 'llm', 'agent', 'team'],
deployment: ['secret', 'llm', 'agent', 'team'],
});
32 changes: 31 additions & 1 deletion app/src/server/websocket/nats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ function generateNatsUrl(natsUrl: string | undefined, fastAgencyServerUrl: strin
const NATS_URL = generateNatsUrl(process.env['NATS_URL'], process.env['FASTAGENCY_SERVER_URL']);
console.log(`NATS_URL=${NATS_URL}`);

const timeoutErrorMsg = 'Oops! Something went wrong. Please create a new chat and try again.';

class NatsConnectionManager {
public static connections: Map<
string,
Expand All @@ -18,6 +20,7 @@ class NatsConnectionManager {
socketConversationHistory: string;
lastSocketMessage: string | null;
conversationId: number;
timeoutId: NodeJS.Timeout | null;
}
> = new Map();

Expand All @@ -30,6 +33,7 @@ class NatsConnectionManager {
socketConversationHistory: '',
lastSocketMessage: null,
conversationId: conversationId,
timeoutId: null,
});
console.log(`Connected to ${nc.getServer()} for threadId ${threadId}`);
}
Expand Down Expand Up @@ -86,6 +90,22 @@ class NatsConnectionManager {
connection.socketConversationHistory = '';
}
}

static setTimeout(threadId: string, callback: () => void, delay: number) {
const connection = this.connections.get(threadId);
if (connection) {
this.clearTimeout(threadId);
connection.timeoutId = setTimeout(callback, delay);
}
}

static clearTimeout(threadId: string) {
const connection = this.connections.get(threadId);
if (connection && connection.timeoutId) {
clearTimeout(connection.timeoutId);
connection.timeoutId = null;
}
}
}

async function setupSubscription(
Expand All @@ -109,6 +129,7 @@ async function setupSubscription(
}
(async () => {
for await (const m of sub) {
NatsConnectionManager.clearTimeout(threadId); // Clear the timeout if a message is received
const conversationHistory = NatsConnectionManager.getConversationHistory(threadId);
const conversationId = NatsConnectionManager.getConversationId(threadId);
const jm = jc.decode(m.data);
Expand All @@ -135,7 +156,7 @@ async function setupSubscription(
);
if (isChatTerminated) {
console.log('Terminating chat and cleaning up NATS connection and subscriptions.');
NatsConnectionManager.cleanup(threadId);
await NatsConnectionManager.cleanup(threadId);
}
} catch (err) {
console.error(`DB Update failed: ${err}`);
Expand Down Expand Up @@ -176,6 +197,15 @@ export async function sendMsgToNatsServer(
jc.encode({ user_id: userUUID, thread_id: threadId, team_id: selectedTeamUUID, msg: message })
);

const timeoutCallback = async () => {
console.error(`No response received in 45 seconds for ${subject}`);
await updateDB(context, currentChatDetails.id, timeoutErrorMsg, conversationId, '', true);
await NatsConnectionManager.cleanup(threadId);
socket.emit('streamFromTeamFinished');
};

NatsConnectionManager.setTimeout(threadId, timeoutCallback, 45000);

if (shouldCallInitiateChat) {
const clientInputSubject = `chat.client.messages.${threadId}`;
await setupSubscription(js, jc, clientInputSubject, threadId, socket, context, currentChatDetails);
Expand Down
8 changes: 4 additions & 4 deletions docs/docs/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ search:
- app
- [ChatRequest](api/fastagency/app/ChatRequest.md)
- [add_model](api/fastagency/app/add_model.md)
- [application_chat](api/fastagency/app/application_chat.md)
- [chat](api/fastagency/app/chat.md)
- [create_toolbox_for_new_user](api/fastagency/app/create_toolbox_for_new_user.md)
- [deployment_chat](api/fastagency/app/deployment_chat.md)
- [generate_chat_name](api/fastagency/app/generate_chat_name.md)
- [get_all_models](api/fastagency/app/get_all_models.md)
- [get_azure_llm_client](api/fastagency/app/get_azure_llm_client.md)
Expand Down Expand Up @@ -62,15 +62,15 @@ search:
- web_surfer
- [BingAPIKey](api/fastagency/models/agents/web_surfer/BingAPIKey.md)
- [WebSurferAgent](api/fastagency/models/agents/web_surfer/WebSurferAgent.md)
- applications
- application
- [Application](api/fastagency/models/applications/application/Application.md)
- base
- [Model](api/fastagency/models/base/Model.md)
- [ModelTypeFinder](api/fastagency/models/base/ModelTypeFinder.md)
- [ObjectReference](api/fastagency/models/base/ObjectReference.md)
- [create_reference_model](api/fastagency/models/base/create_reference_model.md)
- [get_reference_model](api/fastagency/models/base/get_reference_model.md)
- deployments
- deployment
- [Deployment](api/fastagency/models/deployments/deployment/Deployment.md)
- llms
- azure
- [AzureOAI](api/fastagency/models/llms/azure/AzureOAI.md)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ search:
boost: 0.5
---

::: fastagency.app.application_chat
::: fastagency.app.deployment_chat
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ search:
boost: 0.5
---

::: fastagency.models.applications.application.Application
::: fastagency.models.deployments.deployment.Deployment
6 changes: 3 additions & 3 deletions fastagency/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,9 +333,9 @@ async def chat(request: ChatRequest) -> Dict[str, Any]:
return default_response


@app.post("/application/{application_uuid}/chat")
async def application_chat(application_uuid: str) -> Dict[str, Any]:
found_model = await find_model_using_raw(model_uuid=application_uuid)
@app.post("/deployment/{deployment_uuid}/chat")
async def deployment_chat(deployment_uuid: str) -> Dict[str, Any]:
found_model = await find_model_using_raw(model_uuid=deployment_uuid)
team_name = found_model["json_str"]["name"]
team_uuid = found_model["json_str"]["team"]["uuid"]

Expand Down
4 changes: 2 additions & 2 deletions fastagency/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ async def validate_tokens_and_create_gh_repo(
fly_api_token=found_fly_token_uuid,
github_token=found_gh_token_uuid,
app_name=model["name"],
fastagency_application_uuid=model_uuid,
fastagency_deployment_uuid=model_uuid,
)

saas_app.validate_tokens()
Expand Down Expand Up @@ -104,7 +104,7 @@ async def add_model_to_user(
validated_model_json = validated_model.model_dump_json()
saas_app = None

if type_name == "application":
if type_name == "deployment":
saas_app = await validate_tokens_and_create_gh_repo(
validated_model_dict, model_uuid
)
Expand Down
2 changes: 1 addition & 1 deletion fastagency/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# from .registry import Registry # ModelSchema, ModelSchemas, Registry, Schemas

from . import agents, applications, llms, secrets, teams, toolboxes # noqa: F401
from . import agents, deployments, llms, secrets, teams, toolboxes # noqa: F401
from .registry import Registry

__all__ = ["Registry"]
2 changes: 0 additions & 2 deletions fastagency/models/applications/__init__.py

This file was deleted.

2 changes: 2 additions & 0 deletions fastagency/models/deployments/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from .. import teams # noqa: F401
from .deployment import Deployment # noqa: F401
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,30 @@
from ..secrets.fly_token import FlyToken
from ..secrets.github_token import GitHubToken

__all__ = ["Application"]
__all__ = ["Deployment"]

# Applications can work with any Team, so we construct a union of all Team references
# Deployments can work with any Team, so we construct a union of all Team references
team_type_refs: TypeAlias = Union[ # type: ignore[valid-type]
tuple(Registry.get_default().get_models_refs_by_type("team"))
]

# Applications can work with any FlyIO Tokens, so we construct a union of all FlyIO Token references
# Deployments can work with any FlyIO Tokens, so we construct a union of all FlyIO Token references
FlyTokenRef: TypeAlias = FlyToken.get_reference_model() # type: ignore[valid-type]

# Applications can work with any GitHub Tokens, so we construct a union of all GitHub Token references
# Deployments can work with any GitHub Tokens, so we construct a union of all GitHub Token references
GitHubTokenRef: TypeAlias = GitHubToken.get_reference_model() # type: ignore[valid-type]


@Registry.get_default().register("application")
class Application(Model):
@Registry.get_default().register("deployment")
class Deployment(Model):
name: Annotated[
str, Field(..., description="The name of the item", min_length=1, max_length=30)
]
team: Annotated[
team_type_refs,
Field(
title="Team name",
description="The team that is used in the application",
description="The team that is used in the deployment",
),
]
gh_token: GitHubTokenRef
Expand All @@ -45,7 +45,7 @@ async def create_autogen(cls, model_id: UUID, user_id: UUID) -> Any:

@field_validator("name")
@classmethod
def validate_name(cls: Type["Application"], value: Any) -> Any:
def validate_name(cls: Type["Deployment"], value: Any) -> Any:
if not re.match(r"^[a-zA-Z0-9\- ]+$", value):
raise ValueError(
"Name must contain only letters, numbers, spaces, and dashes."
Expand Down
Loading

0 comments on commit 477cffd

Please sign in to comment.