diff --git a/apps/rowboat/app/lib/client_utils.ts b/apps/rowboat/app/lib/client_utils.ts index eea2bffb..90997d02 100644 --- a/apps/rowboat/app/lib/client_utils.ts +++ b/apps/rowboat/app/lib/client_utils.ts @@ -1,9 +1,11 @@ import { WorkflowTool, WorkflowAgent, WorkflowPrompt, WorkflowPipeline } from "./types/workflow_types"; import { z } from "zod"; +const ZFallbackSchema = z.object({}).passthrough(); + export function validateConfigChanges(configType: string, configChanges: Record, name: string) { let testObject: any; - let schema: z.ZodType; + let schema: z.ZodType = ZFallbackSchema; switch (configType) { case 'tool': { @@ -56,6 +58,10 @@ export function validateConfigChanges(configType: string, configChanges: Record< schema = WorkflowPipeline; break; } + case 'start_agent': { + testObject = {}; + break; + } default: return { error: `Unknown config type: ${configType}` }; } diff --git a/apps/rowboat/app/projects/[projectId]/copilot/components/actions.tsx b/apps/rowboat/app/projects/[projectId]/copilot/components/actions.tsx index 9f1c3bdc..001bb89c 100644 --- a/apps/rowboat/app/projects/[projectId]/copilot/components/actions.tsx +++ b/apps/rowboat/app/projects/[projectId]/copilot/components/actions.tsx @@ -51,9 +51,12 @@ export function Action({ const appliedFields = Object.keys(action.config_changes).filter(key => appliedChanges[getAppliedChangeKey(msgIndex, actionIndex, key)] ); - const allApplied = externallyApplied || Object.keys(action.config_changes).every(key => + let allApplied = externallyApplied || Object.keys(action.config_changes).every(key => appliedFields.includes(key) ); + if (!externallyApplied && (action.action === "delete" || action.config_type === 'start_agent')) { + allApplied = false; + } // Handle applying a single field change const handleFieldChange = (field: string) => { @@ -160,7 +163,8 @@ export function Action({ 'transition-shadow duration-150', { 'border-l-2 border-l-blue-500': !stale && !allApplied && action.action == 'create_new', - 'border-l-2 border-l-orange-500': !stale && !allApplied && action.action == 'edit', + 'border-l-2 border-l-yellow-500': !stale && !allApplied && action.action == 'edit', + 'border-l-2 border-l-red-500': !stale && !allApplied && action.action == 'delete', 'border-l-2 border-l-gray-400': stale || allApplied || action.error, } )}> @@ -171,14 +175,15 @@ export function Action({ 'inline-flex items-center justify-center rounded-full h-5 w-5 text-xs', { 'bg-blue-100 text-blue-600': action.action == 'create_new', - 'bg-orange-100 text-orange-600': action.action == 'edit', + 'bg-yellow-100 text-yellow-600': action.action == 'edit', + 'bg-red-100 text-red-600': action.action == 'delete', 'bg-gray-200 text-gray-600': stale || allApplied || action.error, } )}> - {action.config_type === 'agent' ? '🧑‍💼' : action.config_type === 'tool' ? '🛠️' : action.config_type === 'pipeline' ? '⚙️' : '💬'} + {action.config_type === 'agent' ? '🧑‍💼' : action.config_type === 'tool' ? '🛠️' : action.config_type === 'pipeline' ? '⚙️' : action.config_type === 'start_agent' ? '🏁' : action.config_type === 'prompt' ? '💬' : '💬'} - {action.action === 'create_new' ? 'Add' : 'Edit'} {action.config_type}: {action.name} + {action.action === 'create_new' ? 'Add' : action.action === 'edit' ? 'Edit' : 'Delete'} {action.config_type}: {action.name} {/* Action buttons - compact, icon only, show text on hover */}
@@ -195,13 +200,13 @@ export function Action({ {allApplied ? 'Applied' : 'Apply'} - + }
{/* Description of what happened */} @@ -341,8 +346,8 @@ export function StreamingAction({ loading, }: { action: { - action?: 'create_new' | 'edit'; - config_type?: 'tool' | 'agent' | 'prompt' | 'pipeline'; + action?: 'create_new' | 'edit' | 'delete'; + config_type?: 'tool' | 'agent' | 'prompt' | 'pipeline' | 'start_agent'; name?: string; }; loading: boolean; @@ -354,7 +359,8 @@ export function StreamingAction({ 'transition-shadow duration-150', { 'border-l-2 border-l-blue-500': action.action == 'create_new', - 'border-l-2 border-l-orange-500': action.action == 'edit', + 'border-l-2 border-l-yellow-500': action.action == 'edit', + 'border-l-2 border-l-red-500': action.action == 'delete', 'border-l-2 border-l-gray-400': !action.action, } )}> @@ -364,14 +370,15 @@ export function StreamingAction({ 'inline-flex items-center justify-center rounded-full h-5 w-5 text-xs', { 'bg-blue-100 text-blue-600': action.action == 'create_new', - 'bg-orange-100 text-orange-600': action.action == 'edit', + 'bg-yellow-100 text-yellow-600': action.action == 'edit', + 'bg-red-100 text-red-600': action.action == 'delete', 'bg-gray-200 text-gray-600': !action.action, } )}> - {action.config_type === 'agent' ? '🧑‍💼' : action.config_type === 'tool' ? '🛠️' : action.config_type === 'pipeline' ? '⚙️' : '💬'} + {action.config_type === 'agent' ? '🧑‍💼' : action.config_type === 'tool' ? '🛠️' : action.config_type === 'pipeline' ? '⚙️' : action.config_type === 'start_agent' ? '🏁' : '💬'} - {action.action === 'create_new' ? 'Add' : 'Edit'} {action.config_type}: {action.name} + {action.action === 'create_new' ? 'Add' : action.action === 'edit' ? 'Edit' : 'Delete'} {action.config_type}: {action.name} {/* Loading state body */} diff --git a/apps/rowboat/app/projects/[projectId]/copilot/components/messages.tsx b/apps/rowboat/app/projects/[projectId]/copilot/components/messages.tsx index 54fcf160..563bf798 100644 --- a/apps/rowboat/app/projects/[projectId]/copilot/components/messages.tsx +++ b/apps/rowboat/app/projects/[projectId]/copilot/components/messages.tsx @@ -70,8 +70,8 @@ function enrich(response: string): z.infer { return { type: 'action', action: { - action: metadata.action as 'create_new' | 'edit', - config_type: metadata.config_type as 'tool' | 'agent' | 'prompt' | 'pipeline', + action: metadata.action as 'create_new' | 'edit' | 'delete', + config_type: metadata.config_type as 'tool' | 'agent' | 'prompt' | 'pipeline' | 'start_agent', name: metadata.name, change_description: jsonData.change_description || '', config_changes: {}, @@ -83,8 +83,8 @@ function enrich(response: string): z.infer { return { type: 'action', action: { - action: metadata.action as 'create_new' | 'edit', - config_type: metadata.config_type as 'tool' | 'agent' | 'prompt' | 'pipeline', + action: metadata.action as 'create_new' | 'edit' | 'delete', + config_type: metadata.config_type as 'tool' | 'agent' | 'prompt' | 'pipeline' | 'start_agent', name: metadata.name, change_description: jsonData.change_description || '', config_changes: result.changes @@ -99,8 +99,8 @@ function enrich(response: string): z.infer { return { type: 'streaming_action', action: { - action: (metadata.action as 'create_new' | 'edit') || undefined, - config_type: (metadata.config_type as 'tool' | 'agent' | 'prompt' | 'pipeline') || undefined, + action: (metadata.action as 'create_new' | 'edit' | 'delete') || undefined, + config_type: (metadata.config_type as 'tool' | 'agent' | 'prompt' | 'pipeline' | 'start_agent') || undefined, name: metadata.name } }; @@ -289,6 +289,39 @@ function AssistantMessage({ pipeline: action.config_changes }); break; + case 'start_agent': + dispatch({ + type: 'set_main_agent', + name: action.name, + }) + break; + } + } else if (action.action === 'delete') { + switch (action.config_type) { + case 'agent': + dispatch({ + type: 'delete_agent', + name: action.name + }); + break; + case 'tool': + dispatch({ + type: 'delete_tool', + name: action.name + }); + break; + case 'prompt': + dispatch({ + type: 'delete_prompt', + name: action.name + }); + break; + case 'pipeline': + dispatch({ + type: 'delete_pipeline', + name: action.name + }); + break; } } }, [dispatch, workflow.agents, workflow.tools]); diff --git a/apps/rowboat/src/application/lib/copilot/example_multi_agent_1.ts b/apps/rowboat/src/application/lib/copilot/example_multi_agent_1.ts index 5aef81e3..946e48b7 100644 --- a/apps/rowboat/src/application/lib/copilot/example_multi_agent_1.ts +++ b/apps/rowboat/src/application/lib/copilot/example_multi_agent_1.ts @@ -990,4 +990,92 @@ This workflow is now ready. Once you apply the changes, it will automatically ha --- +### Example 7: Setting the start agent + +**User Request** +Can you set the start agent to the Meeting Prep Hub? + +**Copilot Response** + +Yes, I can set the start agent to the Meeting Prep Hub. + +\`\`\`copilot_change + +// action: edit +// config_type: start_agent +// name: Meeting Prep Hub +{ + "change_description": "Set the start agent to the Meeting Prep Hub.", + "config_changes": {}, +} +\`\`\` + + +--- + +### Example 8: Delete an agent + +**User Request:** +Can you delete the Slack Send Agent? + +**Copilot Response:** + +Yes, I can delete the Slack Send Agent. + +\`\`\`copilot_change +// action: delete +// config_type: agent +// name: Slack Send Agent +{ + "change_description": "Delete the Slack Send Agent.", + "config_changes": {}, + } +} +\`\`\` + +--- + +### Example 9: Delete a tool + +**User Request:** +Can you delete the Search tool? + +**Copilot Response:** + +Yes, I can delete the Search tool. + + +\`\`\`copilot_change +// action: delete +// config_type: tool +// name: Search +{ + "change_description": "Delete the Search tool.", + "config_changes": {}, +} +\`\`\` + +--- + +### Example 10: Delete a pipeline + +**User Request:** +Can you delete the Meeting Prep Pipeline? + +**Copilot Response:** + +Yes, I can delete the Meeting Prep Pipeline. + +\`\`\`copilot_change +// action: delete +// config_type: pipeline +// name: Meeting Prep Pipeline +{ + "change_description": "Delete the Meeting Prep Pipeline.", + "config_changes": {}, +} +\`\`\` + +--- + `; \ No newline at end of file diff --git a/apps/rowboat/src/application/lib/copilot/types.ts b/apps/rowboat/src/application/lib/copilot/types.ts index 5d42b0e8..5b54f9dc 100644 --- a/apps/rowboat/src/application/lib/copilot/types.ts +++ b/apps/rowboat/src/application/lib/copilot/types.ts @@ -21,8 +21,8 @@ export const CopilotAssistantMessageTextPart = z.object({ export const CopilotAssistantMessageActionPart = z.object({ type: z.literal("action"), content: z.object({ - config_type: z.union([z.literal('tool'), z.literal('agent'), z.literal('prompt'), z.literal('pipeline')]), - action: z.union([z.literal('create_new'), z.literal('edit')]), + config_type: z.enum(['tool', 'agent', 'prompt', 'pipeline', 'start_agent']), + action: z.enum(['create_new', 'edit', 'delete']), name: z.string(), change_description: z.string(), config_changes: z.record(z.string(), z.unknown()),