mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-11 12:17:45 +02:00
[aidan] feat/workflows-canvas: tag run and edit-chat sessions to suppress duplicate cards
This commit is contained in:
@@ -13,6 +13,8 @@ class AgentConfig(BaseModel):
|
||||
max_turns: Optional[int] = None
|
||||
target_directory: Optional[str] = None
|
||||
dashboard_id: Optional[str] = None
|
||||
workflow_run_id: Optional[str] = None
|
||||
workflow_edit_id: Optional[str] = None
|
||||
# App cards the user picked to edit. When exactly one resolves, launch binds the chat's cwd to that app instead of seeding a new "Untitled App".
|
||||
selected_app_output_ids: Optional[list[str]] = None
|
||||
|
||||
@@ -110,6 +112,10 @@ class AgentSession(BaseModel):
|
||||
dashboard_id: Optional[str] = None
|
||||
browser_id: Optional[str] = None
|
||||
parent_session_id: Optional[str] = None
|
||||
# Set when this session IS a workflow run's agent; the run renders in the Workflows monitor card, so the canvas suppresses the duplicate standalone agent card.
|
||||
workflow_run_id: Optional[str] = None
|
||||
# Set when this session IS a workflow's embedded edit/compose chat; it lives in the Workflows hub window, so the canvas suppresses its standalone card and docks its browser below the hub.
|
||||
workflow_edit_id: Optional[str] = None
|
||||
workflow_test_state: Optional[Literal["running", "complete", "error"]] = None
|
||||
# Browser memory signals, drive the subtle "remembered/learned" card chip so the user feels the agent getting smarter without lifting a finger.
|
||||
memory_recalled: bool = False
|
||||
|
||||
@@ -115,6 +115,8 @@ class AgentLaunch(AgentManagerProtocol):
|
||||
repo_url=repo_url,
|
||||
branch=branch_name,
|
||||
dashboard_id=config.dashboard_id,
|
||||
workflow_run_id=config.workflow_run_id,
|
||||
workflow_edit_id=config.workflow_edit_id,
|
||||
thinking_level=getattr(global_settings, "default_thinking_level", "auto"),
|
||||
)
|
||||
apply_context_window(session, global_settings)
|
||||
|
||||
@@ -64,7 +64,7 @@ def _resolve_allowed_tools(wf: Workflow) -> Optional[list[str]]:
|
||||
return list(wf.actions.configured_sets)
|
||||
|
||||
|
||||
def p_resolve_run_dashboard_id(wf: Workflow) -> Optional[str]:
|
||||
def resolve_workflow_dashboard_id(wf: Workflow) -> Optional[str]:
|
||||
"""Pick the dashboard this run's agent attaches to, so browser tools work like in chat.
|
||||
|
||||
Browser cards render only on the dashboard the renderer is currently showing, so we
|
||||
@@ -262,7 +262,8 @@ async def execute(
|
||||
allowed_tools=resolved_allowed_tools if resolved_allowed_tools is not None else [
|
||||
"Read", "Edit", "Write", "Bash", "Glob", "Grep", "AskUserQuestion",
|
||||
],
|
||||
dashboard_id=p_resolve_run_dashboard_id(wf),
|
||||
dashboard_id=resolve_workflow_dashboard_id(wf),
|
||||
workflow_run_id=run.id,
|
||||
)
|
||||
|
||||
session = await agent_manager.launch_agent(config)
|
||||
|
||||
@@ -279,7 +279,7 @@ export function useDashboardLifecycle({
|
||||
useEffect(() => {
|
||||
if (!layoutInitialized) return;
|
||||
const dashboardSessionIds = Object.values(sessions)
|
||||
.filter((s) => s.dashboard_id === dashboardId && s.mode !== 'browser-agent' && s.mode !== 'invoked-agent' && s.mode !== 'sub-agent')
|
||||
.filter((s) => s.dashboard_id === dashboardId && !s.workflow_run_id && !s.workflow_edit_id && s.mode !== 'browser-agent' && s.mode !== 'invoked-agent' && s.mode !== 'sub-agent')
|
||||
.map((s) => s.id);
|
||||
const liveIds = dashboardSessionIds.sort().join(',');
|
||||
if (liveIds === prevSessionIdsRef.current) return;
|
||||
|
||||
@@ -49,6 +49,18 @@ export function useDashboardController(dashboardId: string, isActive: boolean) {
|
||||
!!workflowsMonitorId && s.workflows.active.some((a) => a.workflow_id === workflowsMonitorId));
|
||||
const workflowsMonitorLabel = monitorIsLive ? 'Watching' : 'Viewing';
|
||||
|
||||
// The session id of the run the monitor is showing, mirroring RunMonitor's pinned-or-latest pick, so its browser tether can anchor to the monitor card.
|
||||
const workflowsMonitorRunId = useAppSelector((s) => s.dashboardLayout.workflowsMonitorRunId);
|
||||
const monitorRuns = useAppSelector((s) => (workflowsMonitorId ? s.workflows.runs[workflowsMonitorId] : undefined));
|
||||
const allRuns = useAppSelector((s) => s.workflows.allRuns);
|
||||
const monitorRunSessionId = useMemo(() => {
|
||||
if (!workflowsMonitorId) return null;
|
||||
const run = workflowsMonitorRunId
|
||||
? (monitorRuns || []).find((r) => r.id === workflowsMonitorRunId) || allRuns.find((r) => r.id === workflowsMonitorRunId)
|
||||
: (monitorRuns && monitorRuns[0]) || allRuns.find((r) => r.workflow_id === workflowsMonitorId);
|
||||
return run?.session_id || null;
|
||||
}, [workflowsMonitorId, workflowsMonitorRunId, monitorRuns, allRuns]);
|
||||
|
||||
const contentBounds = useMemo(
|
||||
() => computeContentBounds(cards, viewCards, browserCards, workflowCards, workflowsHub),
|
||||
[cards, viewCards, browserCards, workflowCards, workflowsHub],
|
||||
@@ -295,6 +307,7 @@ export function useDashboardController(dashboardId: string, isActive: boolean) {
|
||||
workflowsHub,
|
||||
workflowsMonitorCard,
|
||||
workflowsMonitorLabel,
|
||||
monitorRunSessionId,
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
@@ -93,6 +93,10 @@ export interface AgentSession {
|
||||
dashboard_id?: string;
|
||||
browser_id?: string | null;
|
||||
parent_session_id?: string | null;
|
||||
/** Set when this session IS a workflow run's agent; the run shows in the Workflows monitor, so it gets no standalone canvas card. */
|
||||
workflow_run_id?: string | null;
|
||||
/** Set when this session IS a workflow's embedded edit/compose chat; it lives in the Workflows hub, so it gets no standalone card and its browser docks below the hub. */
|
||||
workflow_edit_id?: string | null;
|
||||
/** Browser memory signals that drive the subtle "Remembered"/"Learned" card chip. */
|
||||
memory_recalled?: boolean;
|
||||
memory_learned?: boolean;
|
||||
|
||||
Reference in New Issue
Block a user