Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,27 @@ import {
} from "../../utils/tool-helpers";
import { ReadOnlyToolCall } from "../ReadOnlyToolCall";
import { AskUserQuestionToolCall } from "./components/AskUserQuestionToolCall";
import { CreateTaskToolCall } from "./components/CreateTaskToolCall";
import { CreateWorkspaceToolCall } from "./components/CreateWorkspaceToolCall";
import { DeleteTaskToolCall } from "./components/DeleteTaskToolCall";
import { DeleteWorkspaceToolCall } from "./components/DeleteWorkspaceToolCall";
import { EditToolExpandedDiff } from "./components/EditToolExpandedDiff";
import { GenericToolCall } from "./components/GenericToolCall";
import { GetAppContextToolCall } from "./components/GetAppContextToolCall";
import { GetTaskToolCall } from "./components/GetTaskToolCall";
import { GetWorkspaceDetailsToolCall } from "./components/GetWorkspaceDetailsToolCall";
import { ListDevicesToolCall } from "./components/ListDevicesToolCall";
import { ListMembersToolCall } from "./components/ListMembersToolCall";
import { ListProjectsToolCall } from "./components/ListProjectsToolCall";
import { ListTaskStatusesToolCall } from "./components/ListTaskStatusesToolCall";
import { ListTasksToolCall } from "./components/ListTasksToolCall";
import { ListWorkspacesToolCall } from "./components/ListWorkspacesToolCall";
import { StartAgentSessionToolCall } from "./components/StartAgentSessionToolCall";
import { SubagentToolCall } from "./components/SubagentToolCall";
import { SupersetToolCall } from "./components/SupersetToolCall";
import { SwitchWorkspaceToolCall } from "./components/SwitchWorkspaceToolCall";
import { UpdateTaskToolCall } from "./components/UpdateTaskToolCall";
import { UpdateWorkspaceToolCall } from "./components/UpdateWorkspaceToolCall";
import { getExecuteCommandViewModel } from "./utils/getExecuteCommandViewModel";
import { getWebSearchViewModel } from "./utils/getWebSearchViewModel";

Expand Down Expand Up @@ -470,6 +488,75 @@ export function MastraToolCallBlock({
);
}

// --- Superset MCP tools ---
if (toolName === "create_task") {
return <CreateTaskToolCall part={part} />;
}

if (toolName === "update_task") {
return <UpdateTaskToolCall part={part} />;
}

if (toolName === "list_tasks") {
return <ListTasksToolCall part={part} />;
}

if (toolName === "get_task") {
return <GetTaskToolCall part={part} />;
}

if (toolName === "delete_task") {
return <DeleteTaskToolCall part={part} />;
}

if (toolName === "list_task_statuses") {
return <ListTaskStatusesToolCall part={part} />;
}

if (toolName === "list_members") {
return <ListMembersToolCall part={part} />;
}

if (toolName === "list_devices") {
return <ListDevicesToolCall part={part} />;
}

if (toolName === "list_workspaces") {
return <ListWorkspacesToolCall part={part} />;
}

if (toolName === "list_projects") {
return <ListProjectsToolCall part={part} />;
}

if (toolName === "get_app_context") {
return <GetAppContextToolCall part={part} />;
}

if (toolName === "get_workspace_details") {
return <GetWorkspaceDetailsToolCall part={part} />;
}

if (toolName === "create_workspace") {
return <CreateWorkspaceToolCall part={part} />;
}

if (toolName === "switch_workspace") {
return <SwitchWorkspaceToolCall part={part} />;
}

if (toolName === "update_workspace") {
return <UpdateWorkspaceToolCall part={part} />;
}

if (toolName === "delete_workspace") {
return <DeleteWorkspaceToolCall part={part} />;
}

if (toolName === "start_agent_session") {
return <StartAgentSessionToolCall part={part} />;
}

// --- Read-only exploration tools ---
if (READ_ONLY_TOOLS.has(toolName)) {
return <ReadOnlyToolCall part={part} onOpenFileInPane={openFileInPane} />;
Expand All @@ -478,7 +565,7 @@ export function MastraToolCallBlock({
// --- Destructive workspace tools ---
if (toolName === "mastra_workspace_mkdir") {
return (
<GenericToolCall
<SupersetToolCall
part={part}
toolName="Create directory"
icon={FolderIcon}
Expand All @@ -488,24 +575,24 @@ export function MastraToolCallBlock({

if (toolName === "mastra_workspace_delete") {
return (
<GenericToolCall part={part} toolName="Delete path" icon={FileIcon} />
<SupersetToolCall part={part} toolName="Delete path" icon={FileIcon} />
);
}

if (toolName === "request_sandbox_access") {
return <GenericToolCall part={part} toolName="Request sandbox access" />;
return <SupersetToolCall part={part} toolName="Request sandbox access" />;
}

if (toolName === "task_write") {
return <GenericToolCall part={part} toolName="Write task list" />;
return <SupersetToolCall part={part} toolName="Write task list" />;
}

if (toolName === "task_check") {
return <GenericToolCall part={part} toolName="Update task status" />;
return <SupersetToolCall part={part} toolName="Update task status" />;
}

if (toolName === "submit_plan") {
return <GenericToolCall part={part} toolName="Submit plan" />;
return <SupersetToolCall part={part} toolName="Submit plan" />;
}

if (toolName === "subagent") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { UserQuestionTool } from "@superset/ui/ai-elements/user-question-tool";
import { MessageCircleQuestionIcon } from "lucide-react";
import { useEffect, useMemo, useState } from "react";
import type { ToolPart } from "../../../../utils/tool-helpers";
import { GenericToolCall } from "../GenericToolCall";
import { SupersetToolCall } from "../SupersetToolCall";

interface QuestionToolOption {
label: string;
Expand Down Expand Up @@ -222,7 +222,7 @@ export function AskUserQuestionToolCall({

if (!hasQuestions) {
return (
<GenericToolCall
<SupersetToolCall
part={part}
toolName="Question"
icon={MessageCircleQuestionIcon}
Expand All @@ -234,7 +234,7 @@ export function AskUserQuestionToolCall({
return (
<div className="space-y-2">
{messageBlock}
<GenericToolCall
<SupersetToolCall
part={part}
toolName="Question"
icon={MessageCircleQuestionIcon}
Expand All @@ -247,7 +247,7 @@ export function AskUserQuestionToolCall({
return (
<div className="space-y-2">
{messageBlock}
<GenericToolCall
<SupersetToolCall
part={part}
toolName="Question"
icon={MessageCircleQuestionIcon}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { useNavigate } from "@tanstack/react-router";
import { FilePlusIcon } from "lucide-react";
import type { ToolPart } from "../../../../utils/tool-helpers";
import { getArgs, getResult } from "../../../../utils/tool-helpers";
import {
formatTaskDate,
toRecord,
toStringArray,
} from "../../utils/taskToolCallHelpers";
import { SupersetToolCall } from "../SupersetToolCall";
import { TaskItemDisplay } from "../TaskItemDisplay";

interface CreateTaskToolCallProps {
part: ToolPart;
}

export function CreateTaskToolCall({ part }: CreateTaskToolCallProps) {
const navigate = useNavigate();
const args = getArgs(part);
const result = getResult(part);
const resultData =
typeof result.result === "object" && result.result !== null
? (result.result as Record<string, unknown>)
: result;
const created = Array.isArray(resultData.created)
? resultData.created.filter(
(item): item is Record<string, unknown> =>
typeof item === "object" && item !== null,
)
: [];
const requestedTasks = Array.isArray(args.tasks)
? args.tasks
.map((task) => toRecord(task))
.filter((task): task is Record<string, unknown> => task !== null)
: Object.keys(args).length > 0
? [toRecord(args)].filter(
(task): task is Record<string, unknown> => task !== null,
)
: [];

return (
<SupersetToolCall
part={part}
toolName="Create task"
icon={FilePlusIcon}
details={
<div className="space-y-2">
{created.length > 0 ? (
<div className="space-y-1">
<div className="font-medium text-foreground">
Created ({created.length})
</div>
<div className="space-y-1">
{created.map((task) => {
const taskId = typeof task.id === "string" ? task.id : null;
const slug = typeof task.slug === "string" ? task.slug : null;
const requested =
requestedTasks.find((candidate) => {
if (!candidate) return false;
if (
taskId &&
typeof candidate.taskId === "string" &&
candidate.taskId === taskId
) {
return true;
}
if (
slug &&
typeof candidate.slug === "string" &&
candidate.slug === slug
) {
return true;
}
return false;
}) ??
(requestedTasks.length === 1 ? requestedTasks[0] : null);
const title =
typeof task.title === "string"
? task.title
: typeof requested?.title === "string"
? requested.title
: "Untitled task";
const openTaskId = taskId ?? slug;
const priority =
typeof requested?.priority === "string"
? requested.priority
: null;
const assignee =
typeof requested?.assigneeId === "string"
? requested.assigneeId
: null;
const dueDate = formatTaskDate(requested?.dueDate);
const labels = toStringArray(requested?.labels);
const description =
typeof requested?.description === "string"
? requested.description
: null;

return (
<TaskItemDisplay
key={taskId ?? slug ?? title}
assignee={assignee}
description={description}
dueDate={dueDate}
labels={labels}
priority={priority}
slug={slug}
taskId={taskId}
title={title}
onClick={
openTaskId
? () =>
navigate({
to: "/tasks/$taskId",
params: { taskId: openTaskId },
})
: undefined
}
/>
);
})}
</div>
</div>
) : (
<div className="text-muted-foreground">
No created tasks in result.
</div>
)}
</div>
}
/>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { CreateTaskToolCall } from "./CreateTaskToolCall";
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { FolderPlusIcon } from "lucide-react";
import type { ToolPart } from "../../../../utils/tool-helpers";
import { SupersetToolCall } from "../SupersetToolCall";

interface CreateWorkspaceToolCallProps {
part: ToolPart;
}

export function CreateWorkspaceToolCall({
part,
}: CreateWorkspaceToolCallProps) {
return (
<SupersetToolCall
part={part}
toolName="Create workspace"
icon={FolderPlusIcon}
/>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { CreateWorkspaceToolCall } from "./CreateWorkspaceToolCall";
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { useNavigate } from "@tanstack/react-router";
import { FileXIcon } from "lucide-react";
import type { ToolPart } from "../../../../utils/tool-helpers";
import { getResult } from "../../../../utils/tool-helpers";
import { SupersetToolCall } from "../SupersetToolCall";
import { TaskItemDisplay } from "../TaskItemDisplay";

interface DeleteTaskToolCallProps {
part: ToolPart;
}

export function DeleteTaskToolCall({ part }: DeleteTaskToolCallProps) {
const navigate = useNavigate();
const result = getResult(part);
const resultData =
typeof result.result === "object" && result.result !== null
? (result.result as Record<string, unknown>)
: result;
const deleted = Array.isArray(resultData.deleted)
? resultData.deleted.map((item) => String(item))
: [];

return (
<SupersetToolCall
part={part}
toolName="Delete task"
icon={FileXIcon}
details={
<div className="space-y-2">
{deleted.length > 0 ? (
<div className="space-y-1">
<div className="font-medium text-foreground">
Deleted ({deleted.length})
</div>
<div className="space-y-1">
{deleted.map((taskId) => (
<TaskItemDisplay
key={taskId}
status="Deleted"
taskId={taskId}
title="Deleted task"
onClick={() =>
navigate({
to: "/tasks/$taskId",
params: { taskId },
})
}
/>
))}
</div>
</div>
) : (
<div className="text-muted-foreground">
No deleted tasks in result.
</div>
)}
</div>
}
/>
);
}
Loading
Loading