mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-04-08 03:00:28 -04:00
feat(platform/library): Support UX for manual-setup triggers (#10309)
- Resolves #10234 ### Preview #### Manual setup triggers   #### Auto-setup triggers  ### Changes 🏗️ - Add "Trigger status" section to `AgentRunDraftView` - Add `AgentPreset.webhook`, so we can show webhook URL in library - Add `AGENT_PRESET_INCLUDE` to `backend.data.includes` - Add `BaseGraph.trigger_setup_info` (computed field) - Rename `LibraryAgentTriggerInfo` to `GraphTriggerInfo`; move to `backend.data.graph` Refactor: - Move contents of `@/components/agents/` to `@/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/` - Fix small type difference between legacy & generated `LibraryAgent.image_url` ### Checklist 📋 #### For code changes: - [x] I have clearly listed my changes in the PR description - [x] I have made a test plan - [x] I have tested my changes according to the test plan: - [x] Setting up GitHub trigger works - [x] Setting up manual trigger works - [x] Enabling/disabling manual trigger through Library works
This commit is contained in:
committed by
GitHub
parent
dfdc71f97f
commit
0e755a5c85
@@ -1,5 +1,8 @@
|
||||
from backend.server.v2.library.model import LibraryAgentPreset
|
||||
|
||||
from .graph import NodeModel
|
||||
from .integrations import Webhook # noqa: F401
|
||||
|
||||
# Resolve Webhook <- NodeModel forward reference
|
||||
# Resolve Webhook forward references
|
||||
NodeModel.model_rebuild()
|
||||
LibraryAgentPreset.model_rebuild()
|
||||
|
||||
@@ -12,7 +12,7 @@ from prisma.types import (
|
||||
AgentNodeLinkCreateInput,
|
||||
StoreListingVersionWhereInput,
|
||||
)
|
||||
from pydantic import Field, JsonValue, create_model
|
||||
from pydantic import BaseModel, Field, JsonValue, create_model
|
||||
from pydantic.fields import computed_field
|
||||
|
||||
from backend.blocks.agent import AgentExecutorBlock
|
||||
@@ -205,6 +205,35 @@ class BaseGraph(BaseDbModel):
|
||||
None,
|
||||
)
|
||||
|
||||
@computed_field
|
||||
@property
|
||||
def trigger_setup_info(self) -> "GraphTriggerInfo | None":
|
||||
if not (
|
||||
self.webhook_input_node
|
||||
and (trigger_block := self.webhook_input_node.block).webhook_config
|
||||
):
|
||||
return None
|
||||
|
||||
return GraphTriggerInfo(
|
||||
provider=trigger_block.webhook_config.provider,
|
||||
config_schema={
|
||||
**(json_schema := trigger_block.input_schema.jsonschema()),
|
||||
"properties": {
|
||||
pn: sub_schema
|
||||
for pn, sub_schema in json_schema["properties"].items()
|
||||
if not is_credentials_field_name(pn)
|
||||
},
|
||||
"required": [
|
||||
pn
|
||||
for pn in json_schema.get("required", [])
|
||||
if not is_credentials_field_name(pn)
|
||||
],
|
||||
},
|
||||
credentials_input_name=next(
|
||||
iter(trigger_block.input_schema.get_credentials_fields()), None
|
||||
),
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _generate_schema(
|
||||
*props: tuple[type[AgentInputBlock.Input] | type[AgentOutputBlock.Input], dict],
|
||||
@@ -238,6 +267,14 @@ class BaseGraph(BaseDbModel):
|
||||
}
|
||||
|
||||
|
||||
class GraphTriggerInfo(BaseModel):
|
||||
provider: ProviderName
|
||||
config_schema: dict[str, Any] = Field(
|
||||
description="Input schema for the trigger block"
|
||||
)
|
||||
credentials_input_name: Optional[str]
|
||||
|
||||
|
||||
class Graph(BaseGraph):
|
||||
sub_graphs: list[BaseGraph] = [] # Flattened sub-graphs
|
||||
|
||||
|
||||
@@ -75,3 +75,9 @@ def library_agent_include(user_id: str) -> prisma.types.LibraryAgentInclude:
|
||||
},
|
||||
"Creator": True,
|
||||
}
|
||||
|
||||
|
||||
AGENT_PRESET_INCLUDE: prisma.types.AgentPresetInclude = {
|
||||
"InputPresets": True,
|
||||
"Webhook": True,
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import backend.server.v2.store.media as store_media
|
||||
from backend.data.block import BlockInput
|
||||
from backend.data.db import transaction
|
||||
from backend.data.execution import get_graph_execution
|
||||
from backend.data.includes import library_agent_include
|
||||
from backend.data.includes import AGENT_PRESET_INCLUDE, library_agent_include
|
||||
from backend.data.model import CredentialsMetaInput
|
||||
from backend.integrations.creds_manager import IntegrationCredentialsManager
|
||||
from backend.integrations.webhooks.graph_lifecycle_hooks import on_graph_activate
|
||||
@@ -617,7 +617,7 @@ async def list_presets(
|
||||
where=query_filter,
|
||||
skip=(page - 1) * page_size,
|
||||
take=page_size,
|
||||
include={"InputPresets": True},
|
||||
include=AGENT_PRESET_INCLUDE,
|
||||
)
|
||||
total_items = await prisma.models.AgentPreset.prisma().count(where=query_filter)
|
||||
total_pages = (total_items + page_size - 1) // page_size
|
||||
@@ -662,7 +662,7 @@ async def get_preset(
|
||||
try:
|
||||
preset = await prisma.models.AgentPreset.prisma().find_unique(
|
||||
where={"id": preset_id},
|
||||
include={"InputPresets": True},
|
||||
include=AGENT_PRESET_INCLUDE,
|
||||
)
|
||||
if not preset or preset.userId != user_id or preset.isDeleted:
|
||||
return None
|
||||
@@ -717,7 +717,7 @@ async def create_preset(
|
||||
]
|
||||
},
|
||||
),
|
||||
include={"InputPresets": True},
|
||||
include=AGENT_PRESET_INCLUDE,
|
||||
)
|
||||
return library_model.LibraryAgentPreset.from_db(new_preset)
|
||||
except prisma.errors.PrismaError as e:
|
||||
@@ -834,7 +834,7 @@ async def update_preset(
|
||||
updated = await prisma.models.AgentPreset.prisma(tx).update(
|
||||
where={"id": preset_id},
|
||||
data=update_data,
|
||||
include={"InputPresets": True},
|
||||
include=AGENT_PRESET_INCLUDE,
|
||||
)
|
||||
if not updated:
|
||||
raise RuntimeError(f"AgentPreset #{preset_id} vanished while updating")
|
||||
@@ -849,7 +849,7 @@ async def set_preset_webhook(
|
||||
) -> library_model.LibraryAgentPreset:
|
||||
current = await prisma.models.AgentPreset.prisma().find_unique(
|
||||
where={"id": preset_id},
|
||||
include={"InputPresets": True},
|
||||
include=AGENT_PRESET_INCLUDE,
|
||||
)
|
||||
if not current or current.userId != user_id:
|
||||
raise NotFoundError(f"Preset #{preset_id} not found")
|
||||
@@ -861,7 +861,7 @@ async def set_preset_webhook(
|
||||
if webhook_id
|
||||
else {"Webhook": {"disconnect": True}}
|
||||
),
|
||||
include={"InputPresets": True},
|
||||
include=AGENT_PRESET_INCLUDE,
|
||||
)
|
||||
if not updated:
|
||||
raise RuntimeError(f"AgentPreset #{preset_id} vanished while updating")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import datetime
|
||||
from enum import Enum
|
||||
from typing import Any, Optional
|
||||
from typing import TYPE_CHECKING, Any, Optional
|
||||
|
||||
import prisma.enums
|
||||
import prisma.models
|
||||
@@ -9,9 +9,11 @@ import pydantic
|
||||
import backend.data.block as block_model
|
||||
import backend.data.graph as graph_model
|
||||
from backend.data.model import CredentialsMetaInput, is_credentials_field_name
|
||||
from backend.integrations.providers import ProviderName
|
||||
from backend.util.models import Pagination
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from backend.data.integrations import Webhook
|
||||
|
||||
|
||||
class LibraryAgentStatus(str, Enum):
|
||||
COMPLETED = "COMPLETED" # All runs completed
|
||||
@@ -20,14 +22,6 @@ class LibraryAgentStatus(str, Enum):
|
||||
ERROR = "ERROR" # Agent is in an error state
|
||||
|
||||
|
||||
class LibraryAgentTriggerInfo(pydantic.BaseModel):
|
||||
provider: ProviderName
|
||||
config_schema: dict[str, Any] = pydantic.Field(
|
||||
description="Input schema for the trigger block"
|
||||
)
|
||||
credentials_input_name: Optional[str]
|
||||
|
||||
|
||||
class LibraryAgent(pydantic.BaseModel):
|
||||
"""
|
||||
Represents an agent in the library, including metadata for display and
|
||||
@@ -59,7 +53,7 @@ class LibraryAgent(pydantic.BaseModel):
|
||||
has_external_trigger: bool = pydantic.Field(
|
||||
description="Whether the agent has an external trigger (e.g. webhook) node"
|
||||
)
|
||||
trigger_setup_info: Optional[LibraryAgentTriggerInfo] = None
|
||||
trigger_setup_info: Optional[graph_model.GraphTriggerInfo] = None
|
||||
|
||||
# Indicates whether there's a new output (based on recent runs)
|
||||
new_output: bool
|
||||
@@ -132,30 +126,7 @@ class LibraryAgent(pydantic.BaseModel):
|
||||
graph.credentials_input_schema if sub_graphs is not None else None
|
||||
),
|
||||
has_external_trigger=graph.has_external_trigger,
|
||||
trigger_setup_info=(
|
||||
LibraryAgentTriggerInfo(
|
||||
provider=trigger_block.webhook_config.provider,
|
||||
config_schema={
|
||||
**(json_schema := trigger_block.input_schema.jsonschema()),
|
||||
"properties": {
|
||||
pn: sub_schema
|
||||
for pn, sub_schema in json_schema["properties"].items()
|
||||
if not is_credentials_field_name(pn)
|
||||
},
|
||||
"required": [
|
||||
pn
|
||||
for pn in json_schema.get("required", [])
|
||||
if not is_credentials_field_name(pn)
|
||||
],
|
||||
},
|
||||
credentials_input_name=next(
|
||||
iter(trigger_block.input_schema.get_credentials_fields()), None
|
||||
),
|
||||
)
|
||||
if graph.webhook_input_node
|
||||
and (trigger_block := graph.webhook_input_node.block).webhook_config
|
||||
else None
|
||||
),
|
||||
trigger_setup_info=graph.trigger_setup_info,
|
||||
new_output=new_output,
|
||||
can_access_graph=can_access_graph,
|
||||
is_latest_version=is_latest_version,
|
||||
@@ -284,10 +255,18 @@ class LibraryAgentPreset(LibraryAgentPresetCreatable):
|
||||
user_id: str
|
||||
updated_at: datetime.datetime
|
||||
|
||||
webhook: "Webhook | None"
|
||||
|
||||
@classmethod
|
||||
def from_db(cls, preset: prisma.models.AgentPreset) -> "LibraryAgentPreset":
|
||||
from backend.data.integrations import Webhook
|
||||
|
||||
if preset.InputPresets is None:
|
||||
raise ValueError("InputPresets must be included in AgentPreset query")
|
||||
if preset.webhookId and preset.Webhook is None:
|
||||
raise ValueError(
|
||||
"Webhook must be included in AgentPreset query when webhookId is set"
|
||||
)
|
||||
|
||||
input_data: block_model.BlockInput = {}
|
||||
input_credentials: dict[str, CredentialsMetaInput] = {}
|
||||
@@ -312,6 +291,7 @@ class LibraryAgentPreset(LibraryAgentPresetCreatable):
|
||||
inputs=input_data,
|
||||
credentials=input_credentials,
|
||||
webhook_id=preset.webhookId,
|
||||
webhook=Webhook.from_db(preset.Webhook) if preset.Webhook else None,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
"type": "object"
|
||||
},
|
||||
"sub_graphs": [],
|
||||
"trigger_setup_info": null,
|
||||
"user_id": "test-user-id",
|
||||
"version": 1
|
||||
}
|
||||
@@ -23,6 +23,7 @@
|
||||
"type": "object"
|
||||
},
|
||||
"sub_graphs": [],
|
||||
"trigger_setup_info": null,
|
||||
"user_id": "test-user-id",
|
||||
"version": 1
|
||||
}
|
||||
|
||||
@@ -519,7 +519,6 @@ export function OldAgentLibraryView() {
|
||||
/* Draft new runs / Create new presets */
|
||||
<AgentRunDraftView
|
||||
graph={graph}
|
||||
triggerSetupInfo={agent.trigger_setup_info}
|
||||
onRun={selectRun}
|
||||
onCreateSchedule={onCreateSchedule}
|
||||
onCreatePreset={onCreatePreset}
|
||||
@@ -529,7 +528,6 @@ export function OldAgentLibraryView() {
|
||||
/* Edit & update presets */
|
||||
<AgentRunDraftView
|
||||
graph={graph}
|
||||
triggerSetupInfo={agent.trigger_setup_info}
|
||||
agentPreset={
|
||||
agentPresets.find((preset) => preset.id == selectedView.id)!
|
||||
}
|
||||
|
||||
@@ -30,10 +30,7 @@ import {
|
||||
} from "@/components/ui/tooltip";
|
||||
import { useToastOnFail } from "@/components/molecules/Toast/use-toast";
|
||||
|
||||
import {
|
||||
AgentRunStatus,
|
||||
agentRunStatusMap,
|
||||
} from "@/components/agents/agent-run-status-chip";
|
||||
import { AgentRunStatus, agentRunStatusMap } from "./agent-run-status-chip";
|
||||
import useCredits from "@/hooks/useCredits";
|
||||
|
||||
export function AgentRunDetailsView({
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
LibraryAgentPreset,
|
||||
LibraryAgentPresetID,
|
||||
LibraryAgentPresetUpdatable,
|
||||
LibraryAgentTriggerInfo,
|
||||
Schedule,
|
||||
} from "@/lib/autogpt-server-api";
|
||||
import { useBackendAPI } from "@/lib/autogpt-server-api/context";
|
||||
@@ -24,16 +23,19 @@ import { RunAgentInputs } from "@/app/(platform)/library/agents/[id]/components/
|
||||
import { useOnboarding } from "@/components/onboarding/onboarding-provider";
|
||||
import { cn, isEmpty } from "@/lib/utils";
|
||||
import SchemaTooltip from "@/components/SchemaTooltip";
|
||||
import { CopyIcon } from "@phosphor-icons/react";
|
||||
import { Button } from "@/components/atoms/Button/Button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import {
|
||||
useToast,
|
||||
useToastOnFail,
|
||||
} from "@/components/molecules/Toast/use-toast";
|
||||
|
||||
import { AgentStatus, AgentStatusChip } from "./agent-status-chip";
|
||||
|
||||
export function AgentRunDraftView({
|
||||
graph,
|
||||
agentPreset,
|
||||
triggerSetupInfo,
|
||||
doRun: _doRun,
|
||||
onRun,
|
||||
onCreatePreset,
|
||||
@@ -45,7 +47,6 @@ export function AgentRunDraftView({
|
||||
className,
|
||||
}: {
|
||||
graph: GraphMeta;
|
||||
triggerSetupInfo?: LibraryAgentTriggerInfo;
|
||||
agentActions?: ButtonAction[];
|
||||
doRun?: (
|
||||
inputs: Record<string, any>,
|
||||
@@ -101,8 +102,8 @@ export function AgentRunDraftView({
|
||||
}, [agentPreset]);
|
||||
|
||||
const agentInputSchema = useMemo(
|
||||
() => triggerSetupInfo?.config_schema ?? graph.input_schema,
|
||||
[graph, triggerSetupInfo],
|
||||
() => graph.trigger_setup_info?.config_schema ?? graph.input_schema,
|
||||
[graph],
|
||||
);
|
||||
const agentInputFields = useMemo(
|
||||
() =>
|
||||
@@ -284,23 +285,13 @@ export function AgentRunDraftView({
|
||||
|
||||
const doSetupTrigger = useCallback(async () => {
|
||||
// Setting up a trigger for non-webhook-triggered agents is not supported
|
||||
if (!triggerSetupInfo || !onCreatePreset) return;
|
||||
if (!graph.trigger_setup_info || !onCreatePreset) return;
|
||||
|
||||
if (!presetName || !allRequiredInputsAreSet || !allCredentialsAreSet) {
|
||||
notifyMissingInputs();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!triggerSetupInfo.credentials_input_name) {
|
||||
// FIXME: implement support for manual-setup webhooks
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "🚧 Feature under construction",
|
||||
description: "Setting up non-auto-setup triggers is not yet supported.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
await api
|
||||
.setupAgentTrigger({
|
||||
name: presetName,
|
||||
@@ -507,9 +498,73 @@ export function AgentRunDraftView({
|
||||
],
|
||||
);
|
||||
|
||||
const triggerStatus: AgentStatus | null = !agentPreset
|
||||
? null
|
||||
: !agentPreset.webhook
|
||||
? "broken"
|
||||
: agentPreset.is_active
|
||||
? "active"
|
||||
: "inactive";
|
||||
|
||||
return (
|
||||
<div className={cn("agpt-div flex gap-6", className)}>
|
||||
<div className="flex min-w-0 flex-1 flex-col gap-4">
|
||||
{graph.trigger_setup_info && agentPreset && (
|
||||
<Card className="agpt-box">
|
||||
<CardHeader className="flex-row items-center justify-between">
|
||||
<CardTitle className="font-poppins text-lg">
|
||||
Trigger status
|
||||
</CardTitle>
|
||||
{triggerStatus && <AgentStatusChip status={triggerStatus} />}
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col gap-4">
|
||||
{!agentPreset.webhook_id ? (
|
||||
/* Shouldn't happen, but technically possible */
|
||||
<p className="text-sm text-destructive">
|
||||
This trigger is not attached to a webhook. Use "Set up
|
||||
trigger" to fix this.
|
||||
</p>
|
||||
) : !graph.trigger_setup_info.credentials_input_name ? (
|
||||
/* Expose webhook URL if not auto-setup */
|
||||
<div className="text-sm">
|
||||
<p>
|
||||
This trigger is ready to be used. Use the Webhook URL below
|
||||
to set up the trigger connection with the service of your
|
||||
choosing.
|
||||
</p>
|
||||
<div className="nodrag mt-5 flex flex-col gap-1">
|
||||
Webhook URL:
|
||||
<div className="flex gap-2 rounded-md bg-gray-50 p-2">
|
||||
<code className="select-all text-sm">
|
||||
{agentPreset.webhook.url}
|
||||
</code>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
className="size-7 flex-none p-1"
|
||||
onClick={() =>
|
||||
agentPreset.webhook &&
|
||||
navigator.clipboard.writeText(agentPreset.webhook.url)
|
||||
}
|
||||
title="Copy webhook URL"
|
||||
>
|
||||
<CopyIcon className="size-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-sm text-muted-foreground">
|
||||
This agent trigger is{" "}
|
||||
{agentPreset.is_active
|
||||
? "ready. When a trigger is received, it will run with the provided settings."
|
||||
: "disabled. It will not respond to triggers until you enable it."}
|
||||
</p>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
<Card className="agpt-box">
|
||||
<CardHeader>
|
||||
<CardTitle className="font-poppins text-lg">Input</CardTitle>
|
||||
|
||||
@@ -50,7 +50,7 @@ const statusStyles = {
|
||||
"bg-slate-100 text-slate-800 hover:bg-slate-100 hover:text-slate-800",
|
||||
};
|
||||
|
||||
export default function AgentRunStatusChip({
|
||||
export function AgentRunStatusChip({
|
||||
status,
|
||||
}: {
|
||||
status: AgentRunStatus;
|
||||
@@ -13,12 +13,8 @@ import {
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
|
||||
import AgentRunStatusChip, {
|
||||
AgentRunStatus,
|
||||
} from "@/components/agents/agent-run-status-chip";
|
||||
import AgentStatusChip, {
|
||||
AgentStatus,
|
||||
} from "@/components/agents/agent-status-chip";
|
||||
import { AgentStatus, AgentStatusChip } from "./agent-status-chip";
|
||||
import { AgentRunStatus, AgentRunStatusChip } from "./agent-run-status-chip";
|
||||
|
||||
export type AgentRunSummaryProps = (
|
||||
| {
|
||||
@@ -43,7 +39,7 @@ export type AgentRunSummaryProps = (
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export default function AgentRunSummaryCard({
|
||||
export function AgentRunSummaryCard({
|
||||
type,
|
||||
status,
|
||||
title,
|
||||
@@ -16,17 +16,16 @@ import { cn } from "@/lib/utils";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/atoms/Button/Button";
|
||||
import LoadingBox from "@/components/ui/loading";
|
||||
import { InfiniteScroll } from "@/components/contextual/InfiniteScroll/InfiniteScroll";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
|
||||
import { agentRunStatusMap } from "@/components/agents/agent-run-status-chip";
|
||||
import AgentRunSummaryCard from "@/components/agents/agent-run-summary-card";
|
||||
import { AgentRunsQuery } from "../use-agent-runs";
|
||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
import { Flag, useGetFlag } from "@/services/feature-flags/use-get-flag";
|
||||
import { RunAgentModal } from "../../AgentRunsView/components/RunAgentModal/RunAgentModal";
|
||||
import { PlusIcon } from "@phosphor-icons/react";
|
||||
import { LibraryAgent as GeneratedLibraryAgent } from "@/app/api/__generated__/models/libraryAgent";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
import { InfiniteScroll } from "@/components/contextual/InfiniteScroll/InfiniteScroll";
|
||||
import { Flag, useGetFlag } from "@/services/feature-flags/use-get-flag";
|
||||
|
||||
import { RunAgentModal } from "../../AgentRunsView/components/RunAgentModal/RunAgentModal";
|
||||
import { AgentRunsQuery } from "../use-agent-runs";
|
||||
import { agentRunStatusMap } from "./agent-run-status-chip";
|
||||
import { AgentRunSummaryCard } from "./agent-run-summary-card";
|
||||
|
||||
interface AgentRunsSelectorListProps {
|
||||
agent: LibraryAgent;
|
||||
@@ -92,7 +91,7 @@ export function AgentRunsSelectorList({
|
||||
<PlusIcon size={20} /> New Run
|
||||
</Button>
|
||||
}
|
||||
agent={agent as unknown as GeneratedLibraryAgent}
|
||||
agent={agent}
|
||||
agentId={agent.id.toString()}
|
||||
/>
|
||||
) : allowDraftNewRun ? (
|
||||
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
} from "@/lib/autogpt-server-api";
|
||||
import { useBackendAPI } from "@/lib/autogpt-server-api/context";
|
||||
|
||||
import { AgentRunStatus } from "@/components/agents/agent-run-status-chip";
|
||||
import ActionButtonGroup from "@/components/agptui/action-button-group";
|
||||
import type { ButtonAction } from "@/components/agptui/types";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
@@ -22,6 +21,8 @@ import { formatScheduleTime } from "@/lib/timezone-utils";
|
||||
import { useGetV1GetUserTimezone } from "@/app/api/__generated__/endpoints/auth/auth";
|
||||
import { PlayIcon } from "lucide-react";
|
||||
|
||||
import { AgentRunStatus } from "./agent-run-status-chip";
|
||||
|
||||
export function AgentScheduleDetailsView({
|
||||
graph,
|
||||
schedule,
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from "react";
|
||||
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
|
||||
export type AgentStatus = "active" | "inactive" | "error";
|
||||
export type AgentStatus = "active" | "inactive" | "error" | "broken";
|
||||
|
||||
const statusData: Record<
|
||||
AgentStatus,
|
||||
@@ -10,6 +10,7 @@ const statusData: Record<
|
||||
> = {
|
||||
active: { label: "Active", variant: "success" },
|
||||
error: { label: "Error", variant: "destructive" },
|
||||
broken: { label: "Broken", variant: "destructive" },
|
||||
inactive: { label: "Inactive", variant: "secondary" },
|
||||
};
|
||||
|
||||
@@ -24,7 +25,7 @@ const statusStyles = {
|
||||
"bg-slate-100 text-slate-800 hover:bg-slate-100 hover:text-slate-800",
|
||||
};
|
||||
|
||||
export default function AgentStatusChip({
|
||||
export function AgentStatusChip({
|
||||
status,
|
||||
}: {
|
||||
status: AgentStatus;
|
||||
@@ -4732,6 +4732,13 @@
|
||||
"type": "boolean",
|
||||
"title": "Has External Trigger",
|
||||
"readOnly": true
|
||||
},
|
||||
"trigger_setup_info": {
|
||||
"anyOf": [
|
||||
{ "$ref": "#/components/schemas/GraphTriggerInfo" },
|
||||
{ "type": "null" }
|
||||
],
|
||||
"readOnly": true
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
@@ -4740,7 +4747,8 @@
|
||||
"description",
|
||||
"input_schema",
|
||||
"output_schema",
|
||||
"has_external_trigger"
|
||||
"has_external_trigger",
|
||||
"trigger_setup_info"
|
||||
],
|
||||
"title": "BaseGraph"
|
||||
},
|
||||
@@ -5430,6 +5438,13 @@
|
||||
"title": "Has External Trigger",
|
||||
"readOnly": true
|
||||
},
|
||||
"trigger_setup_info": {
|
||||
"anyOf": [
|
||||
{ "$ref": "#/components/schemas/GraphTriggerInfo" },
|
||||
{ "type": "null" }
|
||||
],
|
||||
"readOnly": true
|
||||
},
|
||||
"credentials_input_schema": {
|
||||
"additionalProperties": true,
|
||||
"type": "object",
|
||||
@@ -5445,6 +5460,7 @@
|
||||
"input_schema",
|
||||
"output_schema",
|
||||
"has_external_trigger",
|
||||
"trigger_setup_info",
|
||||
"credentials_input_schema"
|
||||
],
|
||||
"title": "GraphMeta"
|
||||
@@ -5504,6 +5520,13 @@
|
||||
"title": "Has External Trigger",
|
||||
"readOnly": true
|
||||
},
|
||||
"trigger_setup_info": {
|
||||
"anyOf": [
|
||||
{ "$ref": "#/components/schemas/GraphTriggerInfo" },
|
||||
{ "type": "null" }
|
||||
],
|
||||
"readOnly": true
|
||||
},
|
||||
"credentials_input_schema": {
|
||||
"additionalProperties": true,
|
||||
"type": "object",
|
||||
@@ -5519,10 +5542,33 @@
|
||||
"input_schema",
|
||||
"output_schema",
|
||||
"has_external_trigger",
|
||||
"trigger_setup_info",
|
||||
"credentials_input_schema"
|
||||
],
|
||||
"title": "GraphModel"
|
||||
},
|
||||
"GraphTriggerInfo": {
|
||||
"properties": {
|
||||
"provider": {
|
||||
"type": "string",
|
||||
"title": "Provider",
|
||||
"description": "Provider name for integrations. Can be any string value, including custom provider names."
|
||||
},
|
||||
"config_schema": {
|
||||
"additionalProperties": true,
|
||||
"type": "object",
|
||||
"title": "Config Schema",
|
||||
"description": "Input schema for the trigger block"
|
||||
},
|
||||
"credentials_input_name": {
|
||||
"anyOf": [{ "type": "string" }, { "type": "null" }],
|
||||
"title": "Credentials Input Name"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": ["provider", "config_schema", "credentials_input_name"],
|
||||
"title": "GraphTriggerInfo"
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"properties": {
|
||||
"detail": {
|
||||
@@ -5645,7 +5691,7 @@
|
||||
},
|
||||
"trigger_setup_info": {
|
||||
"anyOf": [
|
||||
{ "$ref": "#/components/schemas/LibraryAgentTriggerInfo" },
|
||||
{ "$ref": "#/components/schemas/GraphTriggerInfo" },
|
||||
{ "type": "null" }
|
||||
]
|
||||
},
|
||||
@@ -5715,6 +5761,12 @@
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"title": "Updated At"
|
||||
},
|
||||
"webhook": {
|
||||
"anyOf": [
|
||||
{ "$ref": "#/components/schemas/Webhook" },
|
||||
{ "type": "null" }
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
@@ -5727,7 +5779,8 @@
|
||||
"description",
|
||||
"id",
|
||||
"user_id",
|
||||
"updated_at"
|
||||
"updated_at",
|
||||
"webhook"
|
||||
],
|
||||
"title": "LibraryAgentPreset",
|
||||
"description": "Represents a preset configuration for a library agent."
|
||||
@@ -5868,28 +5921,6 @@
|
||||
"enum": ["COMPLETED", "HEALTHY", "WAITING", "ERROR"],
|
||||
"title": "LibraryAgentStatus"
|
||||
},
|
||||
"LibraryAgentTriggerInfo": {
|
||||
"properties": {
|
||||
"provider": {
|
||||
"type": "string",
|
||||
"title": "Provider",
|
||||
"description": "Provider name for integrations. Can be any string value, including custom provider names."
|
||||
},
|
||||
"config_schema": {
|
||||
"additionalProperties": true,
|
||||
"type": "object",
|
||||
"title": "Config Schema",
|
||||
"description": "Input schema for the trigger block"
|
||||
},
|
||||
"credentials_input_name": {
|
||||
"anyOf": [{ "type": "string" }, { "type": "null" }],
|
||||
"title": "Credentials Input Name"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": ["provider", "config_schema", "credentials_input_name"],
|
||||
"title": "LibraryAgentTriggerInfo"
|
||||
},
|
||||
"LibraryAgentUpdateRequest": {
|
||||
"properties": {
|
||||
"auto_update_version": {
|
||||
|
||||
@@ -299,9 +299,17 @@ export type GraphMeta = {
|
||||
forked_from_version?: number | null;
|
||||
input_schema: GraphIOSchema;
|
||||
output_schema: GraphIOSchema;
|
||||
has_external_trigger: boolean;
|
||||
credentials_input_schema: CredentialsInputSchema;
|
||||
};
|
||||
} & (
|
||||
| {
|
||||
has_external_trigger: true;
|
||||
trigger_setup_info: GraphTriggerInfo;
|
||||
}
|
||||
| {
|
||||
has_external_trigger: false;
|
||||
trigger_setup_info: null;
|
||||
}
|
||||
);
|
||||
|
||||
export type GraphID = Brand<string, "GraphID">;
|
||||
|
||||
@@ -327,6 +335,13 @@ export type CredentialsInputSchema = {
|
||||
required: (keyof CredentialsInputSchema["properties"])[];
|
||||
};
|
||||
|
||||
/* Mirror of backend/data/graph.py:GraphTriggerInfo */
|
||||
export type GraphTriggerInfo = {
|
||||
provider: CredentialsProviderName;
|
||||
config_schema: BlockIORootSchema;
|
||||
credentials_input_name: string | null;
|
||||
};
|
||||
|
||||
/* Mirror of backend/data/graph.py:Graph */
|
||||
export type Graph = GraphMeta & {
|
||||
nodes: Node[];
|
||||
@@ -346,6 +361,7 @@ export type GraphUpdateable = Omit<
|
||||
| "output_schema"
|
||||
| "credentials_input_schema"
|
||||
| "has_external_trigger"
|
||||
| "trigger_setup_info"
|
||||
> & {
|
||||
version?: number;
|
||||
is_active?: boolean;
|
||||
@@ -399,7 +415,7 @@ export type LibraryAgent = {
|
||||
id: LibraryAgentID;
|
||||
graph_id: GraphID;
|
||||
graph_version: number;
|
||||
image_url?: string;
|
||||
image_url: string | null;
|
||||
creator_name: string;
|
||||
creator_image_url: string;
|
||||
status: AgentStatus;
|
||||
@@ -415,22 +431,16 @@ export type LibraryAgent = {
|
||||
} & (
|
||||
| {
|
||||
has_external_trigger: true;
|
||||
trigger_setup_info: LibraryAgentTriggerInfo;
|
||||
trigger_setup_info: GraphTriggerInfo;
|
||||
}
|
||||
| {
|
||||
has_external_trigger: false;
|
||||
trigger_setup_info?: undefined;
|
||||
trigger_setup_info: null;
|
||||
}
|
||||
);
|
||||
|
||||
export type LibraryAgentID = Brand<string, "LibraryAgentID">;
|
||||
|
||||
export type LibraryAgentTriggerInfo = {
|
||||
provider: CredentialsProviderName;
|
||||
config_schema: BlockIORootSchema;
|
||||
credentials_input_name?: string;
|
||||
};
|
||||
|
||||
export enum AgentStatus {
|
||||
COMPLETED = "COMPLETED",
|
||||
HEALTHY = "HEALTHY",
|
||||
@@ -453,8 +463,16 @@ export type LibraryAgentPreset = {
|
||||
name: string;
|
||||
description: string;
|
||||
is_active: boolean;
|
||||
webhook_id?: string;
|
||||
};
|
||||
} & (
|
||||
| {
|
||||
webhook_id: string;
|
||||
webhook: Webhook;
|
||||
}
|
||||
| {
|
||||
webhook_id?: undefined;
|
||||
webhook?: undefined;
|
||||
}
|
||||
);
|
||||
|
||||
export type LibraryAgentPresetID = Brand<string, "LibraryAgentPresetID">;
|
||||
|
||||
@@ -594,9 +612,9 @@ export type Webhook = {
|
||||
id: string;
|
||||
url: string;
|
||||
provider: CredentialsProviderName;
|
||||
credentials_id: string;
|
||||
credentials_id: string; // empty string if not appicable
|
||||
webhook_type: string;
|
||||
resource?: string;
|
||||
resource: string; // empty string if not appicable
|
||||
events: string[];
|
||||
secret: string;
|
||||
config: Record<string, any>;
|
||||
|
||||
Reference in New Issue
Block a user