mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-05-13 17:22:37 +02:00
Run individual simulations in playground
This commit is contained in:
parent
61d43149fa
commit
dac517add4
3 changed files with 83 additions and 56 deletions
|
|
@ -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,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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>;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue