feat(platform/library): Support UX for manual-setup triggers (#10309)

- Resolves #10234

### Preview

#### Manual setup triggers
![preview of the setup screen for manual-setup
triggers](https://github.com/user-attachments/assets/295d2968-ad11-4291-b360-2eb2acb03397)
![preview of the view for an active manual-setup
trigger](https://github.com/user-attachments/assets/d0ae2246-2305-48f5-aea8-8adb37336401)

#### Auto-setup triggers
![preview of the view for an active auto-setup
trigger](https://github.com/user-attachments/assets/63856311-fc99-450c-ae1f-86951e40dc26)

### 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:
Reinier van der Leer
2025-09-02 11:23:32 +01:00
committed by GitHub
parent dfdc71f97f
commit 0e755a5c85
17 changed files with 252 additions and 128 deletions

View File

@@ -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()

View File

@@ -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

View File

@@ -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,
}

View File

@@ -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")

View File

@@ -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,
)

View File

@@ -24,6 +24,7 @@
"type": "object"
},
"sub_graphs": [],
"trigger_setup_info": null,
"user_id": "test-user-id",
"version": 1
}

View File

@@ -23,6 +23,7 @@
"type": "object"
},
"sub_graphs": [],
"trigger_setup_info": null,
"user_id": "test-user-id",
"version": 1
}

View File

@@ -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)!
}

View File

@@ -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({

View File

@@ -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 &quot;Set up
trigger&quot; 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>

View File

@@ -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;

View File

@@ -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,

View File

@@ -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 ? (

View File

@@ -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,

View File

@@ -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;

View File

@@ -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": {

View File

@@ -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>;