Run individual simulations in playground

This commit is contained in:
akhisud3195 2025-02-13 17:20:39 +05:30
parent 61d43149fa
commit dac517add4
3 changed files with 83 additions and 56 deletions

View file

@ -5,6 +5,7 @@ import { scenariosCollection } from "@/app/lib/mongodb";
import { z } from 'zod'; import { z } from 'zod';
import { projectAuthCheck } from "./project_actions"; import { projectAuthCheck } from "./project_actions";
import { Scenario, type WithStringId } from "@/app/lib/types"; import { Scenario, type WithStringId } from "@/app/lib/types";
import { SimulationScenarioData } from "@/app/lib/types";
export async function getScenarios(projectId: string): Promise<WithStringId<z.infer<typeof Scenario>>[]> { export async function getScenarios(projectId: string): Promise<WithStringId<z.infer<typeof Scenario>>[]> {
await projectAuthCheck(projectId); await projectAuthCheck(projectId);
@ -16,18 +17,22 @@ export async function getScenarios(projectId: string): Promise<WithStringId<z.in
})); }));
} }
export async function getScenario(projectId: string, scenarioId: string): Promise<WithStringId<z.infer<typeof Scenario>> | null> { export async function getScenario(projectId: string, scenarioId: string): Promise<WithStringId<z.infer<typeof SimulationScenarioData>>> {
await projectAuthCheck(projectId); await projectAuthCheck(projectId);
// fetch scenario
const scenario = await scenariosCollection.findOne({ const scenario = await scenariosCollection.findOne({
_id: new ObjectId(scenarioId), _id: new ObjectId(scenarioId),
projectId, projectId,
}); });
if (!scenario) {
if (!scenario) return null; throw new Error('Scenario not found');
}
const { _id, description, ...rest } = scenario;
return { return {
...scenario, ...rest,
_id: scenario._id.toString(), _id: _id.toString(),
scenario: description,
}; };
} }

View file

@ -1,14 +1,15 @@
'use client'; 'use client';
import { Dropdown, DropdownItem, DropdownMenu, DropdownTrigger, Spinner } from "@nextui-org/react"; import { Dropdown, DropdownItem, DropdownMenu, DropdownTrigger, Spinner } from "@nextui-org/react";
import { useEffect, useState, useMemo } from "react"; import { useEffect, useState, useMemo, useCallback } from "react";
import { z } from "zod"; import { z } from "zod";
import { PlaygroundChat, SimulationData, Workflow } from "@/app/lib/types"; import { PlaygroundChat, SimulationData, SimulationScenarioData, Workflow } from "@/app/lib/types";
import { SimulateScenarioOption, SimulateURLOption } from "./simulation-options"; import { SimulateScenarioOption, SimulateURLOption } from "./simulation-options";
import { Chat } from "./chat"; import { Chat } from "./chat";
import { useSearchParams } from "next/navigation"; import { useSearchParams } from "next/navigation";
import { ActionButton, Pane } from "../workflow/pane"; import { ActionButton, Pane } from "../workflow/pane";
import { apiV1 } from "rowboat-shared"; import { apiV1 } from "rowboat-shared";
import { EllipsisVerticalIcon, MessageSquarePlusIcon, PlayIcon } from "lucide-react"; import { EllipsisVerticalIcon, MessageSquarePlusIcon, PlayIcon } from "lucide-react";
import { getScenario } from "@/app/actions/simulation_actions";
function SimulateLabel() { function SimulateLabel() {
return <span>Simulate<sup className="pl-1">beta</sup></span>; return <span>Simulate<sup className="pl-1">beta</sup></span>;
@ -41,9 +42,42 @@ export function App({
systemMessage: defaultSystemMessage, systemMessage: defaultSystemMessage,
}); });
const beginSimulation = useCallback((data: z.infer<typeof SimulationData>) => {
setExistingChatId(null);
setViewSimulationMenu(false);
setCounter(counter + 1);
setChat({
projectId,
createdAt: new Date().toISOString(),
messages: [],
simulated: true,
simulationData: data,
});
}, [counter, projectId]);
useEffect(() => {
const scenarioId = localStorage.getItem('pendingScenarioId');
if (scenarioId && projectId) {
console.log('Scenario Effect triggered:', { scenarioId, projectId });
getScenario(projectId, scenarioId).then((scenario) => {
console.log('Scenario data received:', scenario);
beginSimulation(scenario as z.infer<typeof SimulationScenarioData>);
localStorage.removeItem('pendingScenarioId');
}).catch(error => {
console.error('Error fetching scenario:', error);
localStorage.removeItem('pendingScenarioId');
});
}
}, [projectId, beginSimulation]);
if (hidden) {
return <></>;
}
function handleSimulateButtonClick() { function handleSimulateButtonClick() {
setViewSimulationMenu(true); setViewSimulationMenu(true);
} }
function handleNewChatButtonClick() { function handleNewChatButtonClick() {
setExistingChatId(null); setExistingChatId(null);
setViewSimulationMenu(false); setViewSimulationMenu(false);
@ -56,52 +90,38 @@ export function App({
systemMessage: defaultSystemMessage, systemMessage: defaultSystemMessage,
}); });
} }
function beginSimulation(data: z.infer<typeof SimulationData>) {
setExistingChatId(null);
setViewSimulationMenu(false);
setCounter(counter + 1);
setChat({
projectId,
createdAt: new Date().toISOString(),
messages: [],
simulated: true,
simulationData: data,
});
}
if (hidden) { return (
return <></>; <Pane title={viewSimulationMenu ? <SimulateLabel /> : "Chat"} actions={[
} <ActionButton
key="new-chat"
return <Pane title={viewSimulationMenu ? <SimulateLabel /> : "Chat"} actions={[ icon={<MessageSquarePlusIcon size={16} />}
<ActionButton onClick={handleNewChatButtonClick}
key="new-chat" >
icon={<MessageSquarePlusIcon size={16} />} New chat
onClick={handleNewChatButtonClick} </ActionButton>,
> !viewSimulationMenu && <ActionButton
New chat key="simulate"
</ActionButton>, icon={<PlayIcon size={16} />}
!viewSimulationMenu && <ActionButton onClick={handleSimulateButtonClick}
key="simulate" >
icon={<PlayIcon size={16} />} Simulate
onClick={handleSimulateButtonClick} </ActionButton>,
> ]}>
Simulate <div className="h-full overflow-auto">
</ActionButton>, {!viewSimulationMenu && loadingChat && <div className="flex justify-center items-center h-full">
]}> <Spinner />
<div className="h-full overflow-auto"> </div>}
{!viewSimulationMenu && loadingChat && <div className="flex justify-center items-center h-full"> {!viewSimulationMenu && !loadingChat && <Chat
<Spinner /> key={existingChatId || 'chat-' + counter}
</div>} chat={chat}
{!viewSimulationMenu && !loadingChat && <Chat initialChatId={existingChatId || null}
key={existingChatId || 'chat-' + counter} projectId={projectId}
chat={chat} workflow={workflow}
initialChatId={existingChatId || null} messageSubscriber={messageSubscriber}
projectId={projectId} />}
workflow={workflow} {viewSimulationMenu && <SimulateScenarioOption beginSimulation={beginSimulation} projectId={projectId} />}
messageSubscriber={messageSubscriber} </div>
/>} </Pane>
{viewSimulationMenu && <SimulateScenarioOption beginSimulation={beginSimulation} projectId={projectId} />} );
</div>
</Pane>;
} }

View file

@ -156,8 +156,10 @@ export default function SimulationApp() {
}; };
const runSingleScenario = (scenario: ScenarioType) => { const runSingleScenario = (scenario: ScenarioType) => {
// Navigate to the workflow playground with the scenario // Store scenario ID in localStorage instead of URL parameter
router.push(`/projects/${projectId}/workflow/playground?scenarioId=${scenario._id}`); localStorage.setItem('pendingScenarioId', scenario._id);
// Navigate to the playground without query parameter
router.push(`/projects/${projectId}/workflow`);
setMenuOpenScenarioId(null); setMenuOpenScenarioId(null);
}; };