Merge branch 'dev' into swiftyos/sdk

This commit is contained in:
Swifty
2025-07-08 10:08:48 +02:00
committed by GitHub
9 changed files with 87 additions and 67 deletions

View File

@@ -669,17 +669,14 @@ async def execute_graph(
)
async def stop_graph_run(
graph_id: str, graph_exec_id: str, user_id: Annotated[str, Depends(get_user_id)]
) -> execution_db.GraphExecutionMeta:
) -> execution_db.GraphExecutionMeta | None:
res = await _stop_graph_run(
user_id=user_id,
graph_id=graph_id,
graph_exec_id=graph_exec_id,
)
if not res:
raise HTTPException(
status_code=HTTP_404_NOT_FOUND,
detail=f"Graph execution #{graph_exec_id} not found.",
)
return None
return res[0]

View File

@@ -1,5 +1,6 @@
import json
from typing import Any, Type, TypeVar, cast, get_args, get_origin
import types
from typing import Any, Type, TypeVar, Union, cast, get_args, get_origin, overload
from prisma import Json as PrismaJson
@@ -104,9 +105,37 @@ def __convert_bool(value: Any) -> bool:
return bool(value)
def _try_convert(value: Any, target_type: Type, raise_on_mismatch: bool) -> Any:
def _try_convert(value: Any, target_type: Any, raise_on_mismatch: bool) -> Any:
origin = get_origin(target_type)
args = get_args(target_type)
# Handle Union types (including Optional which is Union[T, None])
if origin is Union or origin is types.UnionType:
# Handle None values for Optional types
if value is None:
if type(None) in args:
return None
elif raise_on_mismatch:
raise TypeError(f"Value {value} is not of expected type {target_type}")
else:
return value
# Try to convert to each type in the union, excluding None
non_none_types = [arg for arg in args if arg is not type(None)]
# Try each type in the union, using the original raise_on_mismatch behavior
for arg_type in non_none_types:
try:
return _try_convert(value, arg_type, raise_on_mismatch)
except (TypeError, ValueError, ConversionError):
continue
# If no conversion succeeded
if raise_on_mismatch:
raise TypeError(f"Value {value} is not of expected type {target_type}")
else:
return value
if origin is None:
origin = target_type
if origin not in [list, dict, tuple, str, set, int, float, bool]:
@@ -189,11 +218,19 @@ def type_match(value: Any, target_type: Type[T]) -> T:
return cast(T, _try_convert(value, target_type, raise_on_mismatch=True))
def convert(value: Any, target_type: Type[T]) -> T:
@overload
def convert(value: Any, target_type: Type[T]) -> T: ...
@overload
def convert(value: Any, target_type: Any) -> Any: ...
def convert(value: Any, target_type: Any) -> Any:
try:
if isinstance(value, PrismaJson):
value = value.data
return cast(T, _try_convert(value, target_type, raise_on_mismatch=False))
return _try_convert(value, target_type, raise_on_mismatch=False)
except Exception as e:
raise ConversionError(f"Failed to convert {value} to {target_type}") from e
@@ -203,6 +240,7 @@ class FormattedStringType(str):
@classmethod
def __get_pydantic_core_schema__(cls, source_type, handler):
_ = source_type # unused parameter required by pydantic
return handler(str)
@classmethod

View File

@@ -1,3 +1,5 @@
from typing import List, Optional
from backend.util.type import convert
@@ -5,6 +7,8 @@ def test_type_conversion():
assert convert(5.5, int) == 5
assert convert("5.5", int) == 5
assert convert([1, 2, 3], int) == 3
assert convert("7", Optional[int]) == 7
assert convert("7", int | None) == 7
assert convert("5.5", float) == 5.5
assert convert(5, float) == 5.0
@@ -25,8 +29,6 @@ def test_type_conversion():
assert convert([1, 2, 3], dict) == {0: 1, 1: 2, 2: 3}
assert convert((1, 2, 3), dict) == {0: 1, 1: 2, 2: 3}
from typing import List
assert convert("5", List[int]) == [5]
assert convert("[5,4,2]", List[int]) == [5, 4, 2]
assert convert([5, 4, 2], List[str]) == ["5", "4", "2"]

View File

@@ -121,6 +121,7 @@
"msw": "2.10.2",
"msw-storybook-addon": "2.0.5",
"orval": "7.10.0",
"pbkdf2": "3.1.3",
"postcss": "8.5.6",
"prettier": "3.6.2",
"prettier-plugin-tailwindcss": "0.6.13",

View File

@@ -288,6 +288,9 @@ importers:
orval:
specifier: 7.10.0
version: 7.10.0(openapi-types@12.1.3)
pbkdf2:
specifier: 3.1.3
version: 3.1.3
postcss:
specifier: 8.5.6
version: 8.5.6
@@ -3812,11 +3815,6 @@ packages:
create-hmac@1.1.7:
resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==}
create-jest@29.7.0:
resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
hasBin: true
cross-env@7.0.3:
resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==}
engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'}
@@ -11175,7 +11173,7 @@ snapshots:
dependencies:
cipher-base: 1.0.6
inherits: 2.0.4
ripemd160: 2.0.1
ripemd160: 2.0.2
sha.js: 2.4.11
create-hash@1.2.0:
@@ -11195,21 +11193,6 @@ snapshots:
safe-buffer: 5.2.1
sha.js: 2.4.11
create-jest@29.7.0(@types/node@22.15.30):
dependencies:
'@jest/types': 29.6.3
chalk: 4.1.2
exit: 0.1.2
graceful-fs: 4.2.11
jest-config: 29.7.0(@types/node@22.15.30)
jest-util: 29.7.0
prompts: 2.4.2
transitivePeerDependencies:
- '@types/node'
- babel-plugin-macros
- supports-color
- ts-node
cross-env@7.0.3:
dependencies:
cross-spawn: 7.0.6

View File

@@ -1,23 +1,23 @@
"use client";
import SmartImage from "@/components/agptui/SmartImage";
import { useOnboarding } from "@/components/onboarding/onboarding-provider";
import OnboardingButton from "@/components/onboarding/OnboardingButton";
import {
OnboardingStep,
OnboardingHeader,
OnboardingStep,
} from "@/components/onboarding/OnboardingStep";
import { OnboardingText } from "@/components/onboarding/OnboardingText";
import StarRating from "@/components/onboarding/StarRating";
import { Play } from "lucide-react";
import { cn } from "@/lib/utils";
import { useCallback, useEffect, useState } from "react";
import { GraphMeta, StoreAgentDetails } from "@/lib/autogpt-server-api";
import { useBackendAPI } from "@/lib/autogpt-server-api/context";
import { useRouter } from "next/navigation";
import { useOnboarding } from "@/components/onboarding/onboarding-provider";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import SchemaTooltip from "@/components/SchemaTooltip";
import { TypeBasedInput } from "@/components/type-based-input";
import SmartImage from "@/components/agptui/SmartImage";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { useToast } from "@/components/ui/use-toast";
import { GraphMeta, StoreAgentDetails } from "@/lib/autogpt-server-api";
import { useBackendAPI } from "@/lib/autogpt-server-api/context";
import { cn } from "@/lib/utils";
import { Play } from "lucide-react";
import { useRouter } from "next/navigation";
import { useCallback, useEffect, useState } from "react";
export default function Page() {
const { state, updateState, setStep } = useOnboarding(
@@ -52,7 +52,7 @@ export default function Page() {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const update: { [key: string]: any } = {};
// Set default values from schema
Object.entries(agent.input_schema.properties).forEach(
Object.entries(agent.input_schema?.properties || {}).forEach(
([key, value]) => {
// Skip if already set
if (state.agentInput && state.agentInput[key]) {
@@ -224,7 +224,7 @@ export default function Page() {
<CardTitle className="font-poppins text-lg">Input</CardTitle>
</CardHeader>
<CardContent className="flex flex-col gap-4">
{Object.entries(agent?.input_schema.properties || {}).map(
{Object.entries(agent?.input_schema?.properties || {}).map(
([key, inputSubSchema]) => (
<div key={key} className="flex flex-col space-y-2">
<label className="flex items-center gap-1 text-sm font-medium">

View File

@@ -1,9 +1,8 @@
"use client";
import React, { useCallback, useMemo } from "react";
import { isEmpty } from "lodash";
import moment from "moment";
import React, { useCallback, useMemo } from "react";
import { useBackendAPI } from "@/lib/autogpt-server-api/context";
import {
Graph,
GraphExecution,
@@ -11,14 +10,15 @@ import {
GraphExecutionMeta,
LibraryAgent,
} from "@/lib/autogpt-server-api";
import { useBackendAPI } from "@/lib/autogpt-server-api/context";
import ActionButtonGroup from "@/components/agptui/action-button-group";
import type { ButtonAction } from "@/components/agptui/types";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { IconRefresh, IconSquare } from "@/components/ui/icons";
import { useToastOnFail } from "@/components/ui/use-toast";
import ActionButtonGroup from "@/components/agptui/action-button-group";
import LoadingBox from "@/components/ui/loading";
import { Input } from "@/components/ui/input";
import LoadingBox from "@/components/ui/loading";
import { useToastOnFail } from "@/components/ui/use-toast";
import {
AgentRunStatus,
@@ -199,7 +199,7 @@ export default function AgentRunDetailsView({
stopRun,
deleteRun,
graph.has_webhook_trigger,
graph.credentials_input_schema.properties,
graph.credentials_input_schema?.properties,
agent.can_access_graph,
run.graph_id,
run.graph_version,

View File

@@ -1,7 +1,6 @@
"use client";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { useBackendAPI } from "@/lib/autogpt-server-api/context";
import {
CredentialsMetaInput,
GraphExecutionID,
@@ -11,21 +10,21 @@ import {
LibraryAgentPresetUpdatable,
Schedule,
} from "@/lib/autogpt-server-api";
import { useBackendAPI } from "@/lib/autogpt-server-api/context";
import ActionButtonGroup from "@/components/agptui/action-button-group";
import type { ButtonAction } from "@/components/agptui/types";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { IconCross, IconPlay, IconSave } from "@/components/ui/icons";
import { CalendarClockIcon, Trash2Icon } from "lucide-react";
import { CronSchedulerDialog } from "@/components/cron-scheduler-dialog";
import { CredentialsInput } from "@/components/integrations/credentials-input";
import { TypeBasedInput } from "@/components/type-based-input";
import { useToastOnFail } from "@/components/ui/use-toast";
import ActionButtonGroup from "@/components/agptui/action-button-group";
import { useOnboarding } from "@/components/onboarding/onboarding-provider";
import SchemaTooltip from "@/components/SchemaTooltip";
import { useToast } from "@/components/ui/use-toast";
import { isEmpty } from "lodash";
import { TypeBasedInput } from "@/components/type-based-input";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { IconCross, IconPlay, IconSave } from "@/components/ui/icons";
import { Input } from "@/components/ui/input";
import { useToast, useToastOnFail } from "@/components/ui/use-toast";
import { isEmpty } from "lodash";
import { CalendarClockIcon, Trash2Icon } from "lucide-react";
export default function AgentRunDraftView({
agent,
@@ -91,14 +90,14 @@ export default function AgentRunDraftView({
const agentInputFields = useMemo(
() =>
Object.fromEntries(
Object.entries(agentInputSchema.properties).filter(
Object.entries(agentInputSchema?.properties || {}).filter(
([_, subSchema]) => !subSchema.hidden,
),
),
[agentInputSchema],
);
const agentCredentialsInputFields = useMemo(
() => agent.credentials_input_schema.properties,
() => agent.credentials_input_schema?.properties || {},
[agent],
);

View File

@@ -9,16 +9,16 @@ 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";
import { humanizeCronExpression } from "@/lib/cron-expression-utils";
import { AgentRunStatus } from "@/components/agents/agent-run-status-chip";
import { useToastOnFail } from "@/components/ui/use-toast";
import ActionButtonGroup from "@/components/agptui/action-button-group";
import { IconCross } from "@/components/ui/icons";
import { PlayIcon } from "lucide-react";
import LoadingBox from "@/components/ui/loading";
import { Input } from "@/components/ui/input";
import LoadingBox from "@/components/ui/loading";
import { useToastOnFail } from "@/components/ui/use-toast";
import { humanizeCronExpression } from "@/lib/cron-expression-utils";
import { PlayIcon } from "lucide-react";
export default function AgentScheduleDetailsView({
graph,