mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-02-24 03:00:28 -05:00
Compare commits
1 Commits
dev
...
fix/micros
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
11cfd8756c |
@@ -192,3 +192,8 @@ POSTHOG_HOST=https://eu.i.posthog.com
|
|||||||
|
|
||||||
# Other Services
|
# Other Services
|
||||||
AUTOMOD_API_KEY=
|
AUTOMOD_API_KEY=
|
||||||
|
|
||||||
|
# Agent Generator Service
|
||||||
|
# The Agent Generator microservice handles AI-powered agent creation from natural language
|
||||||
|
AGENTGENERATOR_HOST=localhost
|
||||||
|
AGENTGENERATOR_PORT=8009
|
||||||
|
|||||||
@@ -364,11 +364,11 @@ class Config(UpdateTrackingModel["Config"], BaseSettings):
|
|||||||
)
|
)
|
||||||
|
|
||||||
agentgenerator_host: str = Field(
|
agentgenerator_host: str = Field(
|
||||||
default="",
|
default="localhost",
|
||||||
description="The host for the Agent Generator service (empty to use built-in)",
|
description="The host for the Agent Generator service",
|
||||||
)
|
)
|
||||||
agentgenerator_port: int = Field(
|
agentgenerator_port: int = Field(
|
||||||
default=8000,
|
default=8009,
|
||||||
description="The port for the Agent Generator service",
|
description="The port for the Agent Generator service",
|
||||||
)
|
)
|
||||||
agentgenerator_timeout: int = Field(
|
agentgenerator_timeout: int = Field(
|
||||||
|
|||||||
@@ -11,11 +11,6 @@ import {
|
|||||||
MessageResponse,
|
MessageResponse,
|
||||||
} from "@/components/ai-elements/message";
|
} from "@/components/ai-elements/message";
|
||||||
import { Text } from "@/components/atoms/Text/Text";
|
import { Text } from "@/components/atoms/Text/Text";
|
||||||
import {
|
|
||||||
CredentialsProvidersContext,
|
|
||||||
type CredentialsProviderData,
|
|
||||||
type CredentialsProvidersContextType,
|
|
||||||
} from "@/providers/agent-credentials/credentials-provider";
|
|
||||||
import { CopilotChatActionsProvider } from "../components/CopilotChatActionsProvider/CopilotChatActionsProvider";
|
import { CopilotChatActionsProvider } from "../components/CopilotChatActionsProvider/CopilotChatActionsProvider";
|
||||||
import { CreateAgentTool } from "../tools/CreateAgent/CreateAgent";
|
import { CreateAgentTool } from "../tools/CreateAgent/CreateAgent";
|
||||||
import { EditAgentTool } from "../tools/EditAgent/EditAgent";
|
import { EditAgentTool } from "../tools/EditAgent/EditAgent";
|
||||||
@@ -102,65 +97,6 @@ function uid() {
|
|||||||
return `sg-${++_id}`;
|
return `sg-${++_id}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// Mock credential providers for setup-requirements demos
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
const noop = () => Promise.reject(new Error("Styleguide mock"));
|
|
||||||
|
|
||||||
function makeMockProvider(
|
|
||||||
provider: string,
|
|
||||||
providerName: string,
|
|
||||||
savedCredentials: CredentialsProviderData["savedCredentials"] = [],
|
|
||||||
): CredentialsProviderData {
|
|
||||||
return {
|
|
||||||
provider,
|
|
||||||
providerName,
|
|
||||||
savedCredentials,
|
|
||||||
isSystemProvider: false,
|
|
||||||
oAuthCallback: noop as CredentialsProviderData["oAuthCallback"],
|
|
||||||
mcpOAuthCallback: noop as CredentialsProviderData["mcpOAuthCallback"],
|
|
||||||
createAPIKeyCredentials:
|
|
||||||
noop as CredentialsProviderData["createAPIKeyCredentials"],
|
|
||||||
createUserPasswordCredentials:
|
|
||||||
noop as CredentialsProviderData["createUserPasswordCredentials"],
|
|
||||||
createHostScopedCredentials:
|
|
||||||
noop as CredentialsProviderData["createHostScopedCredentials"],
|
|
||||||
deleteCredentials: noop as CredentialsProviderData["deleteCredentials"],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provider context where the user already has saved credentials
|
|
||||||
* so the credential picker shows a selection list.
|
|
||||||
*/
|
|
||||||
const MOCK_PROVIDERS_WITH_CREDENTIALS: CredentialsProvidersContextType = {
|
|
||||||
google: makeMockProvider("google", "Google", [
|
|
||||||
{
|
|
||||||
id: "cred-google-1",
|
|
||||||
provider: "google",
|
|
||||||
type: "oauth2",
|
|
||||||
title: "work@company.com",
|
|
||||||
scopes: ["email", "calendar"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "cred-google-2",
|
|
||||||
provider: "google",
|
|
||||||
type: "oauth2",
|
|
||||||
title: "personal@gmail.com",
|
|
||||||
scopes: ["email", "calendar"],
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provider context where the user has NO saved credentials,
|
|
||||||
* so the credential picker shows an "add new" flow.
|
|
||||||
*/
|
|
||||||
const MOCK_PROVIDERS_WITHOUT_CREDENTIALS: CredentialsProvidersContextType = {
|
|
||||||
openweathermap: makeMockProvider("openweathermap", "OpenWeatherMap"),
|
|
||||||
};
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Page
|
// Page
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -618,80 +554,45 @@ export default function StyleguidePage() {
|
|||||||
/>
|
/>
|
||||||
</SubSection>
|
</SubSection>
|
||||||
|
|
||||||
<SubSection label="Setup requirements — no credentials (add new)">
|
<SubSection label="Output available (setup requirements)">
|
||||||
<CredentialsProvidersContext.Provider
|
<RunBlockTool
|
||||||
value={MOCK_PROVIDERS_WITHOUT_CREDENTIALS}
|
part={{
|
||||||
>
|
type: "tool-run_block",
|
||||||
<RunBlockTool
|
toolCallId: uid(),
|
||||||
part={{
|
state: "output-available",
|
||||||
type: "tool-run_block",
|
input: { block_id: "weather-block-123" },
|
||||||
toolCallId: uid(),
|
output: {
|
||||||
state: "output-available",
|
type: ResponseType.setup_requirements,
|
||||||
input: { block_id: "weather-block-123" },
|
message:
|
||||||
output: {
|
"This block requires API credentials to run. Please configure them below.",
|
||||||
type: ResponseType.setup_requirements,
|
setup_info: {
|
||||||
message:
|
agent_name: "Weather Agent",
|
||||||
"This block requires API credentials to run. Please configure them below.",
|
requirements: {
|
||||||
setup_info: {
|
inputs: [
|
||||||
agent_id: "agent-weather-1",
|
{
|
||||||
agent_name: "Weather Agent",
|
name: "city",
|
||||||
requirements: {
|
title: "City",
|
||||||
inputs: [
|
type: "string",
|
||||||
{
|
required: true,
|
||||||
name: "city",
|
description: "The city to get weather for",
|
||||||
title: "City",
|
},
|
||||||
type: "string",
|
],
|
||||||
required: true,
|
},
|
||||||
description: "The city to get weather for",
|
user_readiness: {
|
||||||
},
|
missing_credentials: {
|
||||||
],
|
openweathermap: {
|
||||||
},
|
provider: "openweathermap",
|
||||||
user_readiness: {
|
credentials_type: "api_key",
|
||||||
missing_credentials: {
|
title: "OpenWeatherMap API Key",
|
||||||
openweathermap_key: {
|
description:
|
||||||
provider: "openweathermap",
|
"Required to access weather data. Get your key at openweathermap.org",
|
||||||
types: ["api_key"],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}}
|
},
|
||||||
/>
|
}}
|
||||||
</CredentialsProvidersContext.Provider>
|
/>
|
||||||
</SubSection>
|
|
||||||
|
|
||||||
<SubSection label="Setup requirements — has credentials (pick from list)">
|
|
||||||
<CredentialsProvidersContext.Provider
|
|
||||||
value={MOCK_PROVIDERS_WITH_CREDENTIALS}
|
|
||||||
>
|
|
||||||
<RunBlockTool
|
|
||||||
part={{
|
|
||||||
type: "tool-run_block",
|
|
||||||
toolCallId: uid(),
|
|
||||||
state: "output-available",
|
|
||||||
input: { block_id: "calendar-block-456" },
|
|
||||||
output: {
|
|
||||||
type: ResponseType.setup_requirements,
|
|
||||||
message:
|
|
||||||
"This block requires Google credentials. Pick an account below or connect a new one.",
|
|
||||||
setup_info: {
|
|
||||||
agent_id: "agent-calendar-1",
|
|
||||||
agent_name: "Calendar Agent",
|
|
||||||
user_readiness: {
|
|
||||||
missing_credentials: {
|
|
||||||
google_oauth: {
|
|
||||||
provider: "google",
|
|
||||||
types: ["oauth2"],
|
|
||||||
scopes: ["email", "calendar"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</CredentialsProvidersContext.Provider>
|
|
||||||
</SubSection>
|
</SubSection>
|
||||||
|
|
||||||
<SubSection label="Output available (error)">
|
<SubSection label="Output available (error)">
|
||||||
@@ -948,71 +849,34 @@ export default function StyleguidePage() {
|
|||||||
/>
|
/>
|
||||||
</SubSection>
|
</SubSection>
|
||||||
|
|
||||||
<SubSection label="Setup requirements — no credentials (add new)">
|
<SubSection label="Output available (setup requirements)">
|
||||||
<CredentialsProvidersContext.Provider
|
<RunAgentTool
|
||||||
value={MOCK_PROVIDERS_WITHOUT_CREDENTIALS}
|
part={{
|
||||||
>
|
type: "tool-run_agent",
|
||||||
<RunAgentTool
|
toolCallId: uid(),
|
||||||
part={{
|
state: "output-available",
|
||||||
type: "tool-run_agent",
|
input: { username_agent_slug: "creator/my-agent" },
|
||||||
toolCallId: uid(),
|
output: {
|
||||||
state: "output-available",
|
type: ResponseType.setup_requirements,
|
||||||
input: { username_agent_slug: "creator/weather-agent" },
|
message: "This agent requires additional setup.",
|
||||||
output: {
|
setup_info: {
|
||||||
type: ResponseType.setup_requirements,
|
agent_name: "YouTube Summarizer",
|
||||||
message:
|
requirements: {},
|
||||||
"This agent requires an API key. Add your credentials below.",
|
user_readiness: {
|
||||||
setup_info: {
|
missing_credentials: {
|
||||||
agent_id: "agent-weather-1",
|
youtube_api: {
|
||||||
agent_name: "Weather Agent",
|
provider: "youtube",
|
||||||
requirements: {},
|
credentials_type: "api_key",
|
||||||
user_readiness: {
|
title: "YouTube Data API Key",
|
||||||
missing_credentials: {
|
description:
|
||||||
openweathermap_key: {
|
"Required to access YouTube video data.",
|
||||||
provider: "openweathermap",
|
|
||||||
types: ["api_key"],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}}
|
},
|
||||||
/>
|
}}
|
||||||
</CredentialsProvidersContext.Provider>
|
/>
|
||||||
</SubSection>
|
|
||||||
|
|
||||||
<SubSection label="Setup requirements — has credentials (pick from list)">
|
|
||||||
<CredentialsProvidersContext.Provider
|
|
||||||
value={MOCK_PROVIDERS_WITH_CREDENTIALS}
|
|
||||||
>
|
|
||||||
<RunAgentTool
|
|
||||||
part={{
|
|
||||||
type: "tool-run_agent",
|
|
||||||
toolCallId: uid(),
|
|
||||||
state: "output-available",
|
|
||||||
input: { username_agent_slug: "creator/calendar-agent" },
|
|
||||||
output: {
|
|
||||||
type: ResponseType.setup_requirements,
|
|
||||||
message:
|
|
||||||
"This agent needs Google credentials. Pick an account or connect a new one.",
|
|
||||||
setup_info: {
|
|
||||||
agent_id: "agent-calendar-1",
|
|
||||||
agent_name: "Google Calendar Agent",
|
|
||||||
requirements: {},
|
|
||||||
user_readiness: {
|
|
||||||
missing_credentials: {
|
|
||||||
google_oauth: {
|
|
||||||
provider: "google",
|
|
||||||
types: ["oauth2"],
|
|
||||||
scopes: ["email", "calendar"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</CredentialsProvidersContext.Provider>
|
|
||||||
</SubSection>
|
</SubSection>
|
||||||
|
|
||||||
<SubSection label="Output available (need login)">
|
<SubSection label="Output available (need login)">
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import {
|
|||||||
ContentCardDescription,
|
ContentCardDescription,
|
||||||
ContentCodeBlock,
|
ContentCodeBlock,
|
||||||
ContentGrid,
|
ContentGrid,
|
||||||
|
ContentHint,
|
||||||
ContentMessage,
|
ContentMessage,
|
||||||
} from "../../components/ToolAccordion/AccordionContent";
|
} from "../../components/ToolAccordion/AccordionContent";
|
||||||
import { ToolAccordion } from "../../components/ToolAccordion/ToolAccordion";
|
import { ToolAccordion } from "../../components/ToolAccordion/ToolAccordion";
|
||||||
@@ -23,8 +24,8 @@ import {
|
|||||||
ClarificationQuestionsCard,
|
ClarificationQuestionsCard,
|
||||||
ClarifyingQuestion,
|
ClarifyingQuestion,
|
||||||
} from "./components/ClarificationQuestionsCard";
|
} from "./components/ClarificationQuestionsCard";
|
||||||
import sparklesImg from "../../components/MiniGame/assets/sparkles.png";
|
import sparklesImg from "./components/MiniGame/assets/sparkles.png";
|
||||||
import { MiniGame } from "../../components/MiniGame/MiniGame";
|
import { MiniGame } from "./components/MiniGame/MiniGame";
|
||||||
import { SuggestedGoalCard } from "./components/SuggestedGoalCard";
|
import { SuggestedGoalCard } from "./components/SuggestedGoalCard";
|
||||||
import {
|
import {
|
||||||
AccordionIcon,
|
AccordionIcon,
|
||||||
@@ -92,7 +93,9 @@ function getAccordionMeta(output: CreateAgentToolOutput) {
|
|||||||
) {
|
) {
|
||||||
return {
|
return {
|
||||||
icon,
|
icon,
|
||||||
title: output.message || "Agent creation started",
|
title:
|
||||||
|
"Creating agent, this may take a few minutes. Play while you wait.",
|
||||||
|
expanded: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@@ -166,22 +169,15 @@ export function CreateAgentTool({ part }: Props) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{isStreaming && (
|
|
||||||
<ToolAccordion
|
|
||||||
icon={<AccordionIcon />}
|
|
||||||
title="Creating agent, this may take a few minutes. Play while you wait."
|
|
||||||
expanded
|
|
||||||
>
|
|
||||||
<ContentGrid>
|
|
||||||
<MiniGame />
|
|
||||||
</ContentGrid>
|
|
||||||
</ToolAccordion>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{hasExpandableContent && output && (
|
{hasExpandableContent && output && (
|
||||||
<ToolAccordion {...getAccordionMeta(output)}>
|
<ToolAccordion {...getAccordionMeta(output)}>
|
||||||
{isOperating && output.message && (
|
{isOperating && (
|
||||||
<ContentMessage>{output.message}</ContentMessage>
|
<ContentGrid>
|
||||||
|
<MiniGame />
|
||||||
|
<ContentHint>
|
||||||
|
This could take a few minutes — play while you wait!
|
||||||
|
</ContentHint>
|
||||||
|
</ContentGrid>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isAgentSavedOutput(output) && (
|
{isAgentSavedOutput(output) && (
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 8.0 KiB |
@@ -4,15 +4,17 @@ import { WarningDiamondIcon } from "@phosphor-icons/react";
|
|||||||
import type { ToolUIPart } from "ai";
|
import type { ToolUIPart } from "ai";
|
||||||
import { useCopilotChatActions } from "../../components/CopilotChatActionsProvider/useCopilotChatActions";
|
import { useCopilotChatActions } from "../../components/CopilotChatActionsProvider/useCopilotChatActions";
|
||||||
import { MorphingTextAnimation } from "../../components/MorphingTextAnimation/MorphingTextAnimation";
|
import { MorphingTextAnimation } from "../../components/MorphingTextAnimation/MorphingTextAnimation";
|
||||||
|
import { OrbitLoader } from "../../components/OrbitLoader/OrbitLoader";
|
||||||
import {
|
import {
|
||||||
ContentCardDescription,
|
ContentCardDescription,
|
||||||
ContentCodeBlock,
|
ContentCodeBlock,
|
||||||
ContentGrid,
|
ContentGrid,
|
||||||
|
ContentHint,
|
||||||
ContentLink,
|
ContentLink,
|
||||||
ContentMessage,
|
ContentMessage,
|
||||||
} from "../../components/ToolAccordion/AccordionContent";
|
} from "../../components/ToolAccordion/AccordionContent";
|
||||||
import { ToolAccordion } from "../../components/ToolAccordion/ToolAccordion";
|
import { ToolAccordion } from "../../components/ToolAccordion/ToolAccordion";
|
||||||
import { MiniGame } from "../../components/MiniGame/MiniGame";
|
import { MiniGame } from "../CreateAgent/components/MiniGame/MiniGame";
|
||||||
import {
|
import {
|
||||||
ClarificationQuestionsCard,
|
ClarificationQuestionsCard,
|
||||||
ClarifyingQuestion,
|
ClarifyingQuestion,
|
||||||
@@ -79,8 +81,9 @@ function getAccordionMeta(output: EditAgentToolOutput): {
|
|||||||
isOperationInProgressOutput(output)
|
isOperationInProgressOutput(output)
|
||||||
) {
|
) {
|
||||||
return {
|
return {
|
||||||
icon,
|
icon: <OrbitLoader size={32} />,
|
||||||
title: output.message || "Agent editing started",
|
title: "Editing agent, this may take a few minutes. Play while you wait.",
|
||||||
|
expanded: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@@ -145,22 +148,15 @@ export function EditAgentTool({ part }: Props) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{isStreaming && (
|
|
||||||
<ToolAccordion
|
|
||||||
icon={<AccordionIcon />}
|
|
||||||
title="Editing agent, this may take a few minutes. Play while you wait."
|
|
||||||
expanded
|
|
||||||
>
|
|
||||||
<ContentGrid>
|
|
||||||
<MiniGame />
|
|
||||||
</ContentGrid>
|
|
||||||
</ToolAccordion>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{hasExpandableContent && output && (
|
{hasExpandableContent && output && (
|
||||||
<ToolAccordion {...getAccordionMeta(output)}>
|
<ToolAccordion {...getAccordionMeta(output)}>
|
||||||
{isOperating && output.message && (
|
{isOperating && (
|
||||||
<ContentMessage>{output.message}</ContentMessage>
|
<ContentGrid>
|
||||||
|
<MiniGame />
|
||||||
|
<ContentHint>
|
||||||
|
This could take a few minutes — play while you wait!
|
||||||
|
</ContentHint>
|
||||||
|
</ContentGrid>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isAgentSavedOutput(output) && (
|
{isAgentSavedOutput(output) && (
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
ContentHint,
|
ContentHint,
|
||||||
ContentMessage,
|
ContentMessage,
|
||||||
} from "../../components/ToolAccordion/AccordionContent";
|
} from "../../components/ToolAccordion/AccordionContent";
|
||||||
import { MiniGame } from "../../components/MiniGame/MiniGame";
|
import { MiniGame } from "../CreateAgent/components/MiniGame/MiniGame";
|
||||||
import {
|
import {
|
||||||
getAccordionMeta,
|
getAccordionMeta,
|
||||||
getAnimationText,
|
getAnimationText,
|
||||||
@@ -47,25 +47,14 @@ export function RunAgentTool({ part }: Props) {
|
|||||||
const isError =
|
const isError =
|
||||||
part.state === "output-error" ||
|
part.state === "output-error" ||
|
||||||
(!!output && isRunAgentErrorOutput(output));
|
(!!output && isRunAgentErrorOutput(output));
|
||||||
const isOutputAvailable = part.state === "output-available" && !!output;
|
|
||||||
|
|
||||||
const setupRequirementsOutput =
|
|
||||||
isOutputAvailable && isRunAgentSetupRequirementsOutput(output)
|
|
||||||
? output
|
|
||||||
: null;
|
|
||||||
|
|
||||||
const agentDetailsOutput =
|
|
||||||
isOutputAvailable && isRunAgentAgentDetailsOutput(output) ? output : null;
|
|
||||||
|
|
||||||
const needLoginOutput =
|
|
||||||
isOutputAvailable && isRunAgentNeedLoginOutput(output) ? output : null;
|
|
||||||
|
|
||||||
const hasExpandableContent =
|
const hasExpandableContent =
|
||||||
isOutputAvailable &&
|
part.state === "output-available" &&
|
||||||
!setupRequirementsOutput &&
|
!!output &&
|
||||||
!agentDetailsOutput &&
|
(isRunAgentExecutionStartedOutput(output) ||
|
||||||
!needLoginOutput &&
|
isRunAgentAgentDetailsOutput(output) ||
|
||||||
(isRunAgentExecutionStartedOutput(output) || isRunAgentErrorOutput(output));
|
isRunAgentSetupRequirementsOutput(output) ||
|
||||||
|
isRunAgentNeedLoginOutput(output) ||
|
||||||
|
isRunAgentErrorOutput(output));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="py-2">
|
<div className="py-2">
|
||||||
@@ -92,30 +81,24 @@ export function RunAgentTool({ part }: Props) {
|
|||||||
</ToolAccordion>
|
</ToolAccordion>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{setupRequirementsOutput && (
|
|
||||||
<div className="mt-2">
|
|
||||||
<SetupRequirementsCard output={setupRequirementsOutput} />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{agentDetailsOutput && (
|
|
||||||
<div className="mt-2">
|
|
||||||
<AgentDetailsCard output={agentDetailsOutput} />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{needLoginOutput && (
|
|
||||||
<div className="mt-2">
|
|
||||||
<ContentMessage>{needLoginOutput.message}</ContentMessage>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{hasExpandableContent && output && (
|
{hasExpandableContent && output && (
|
||||||
<ToolAccordion {...getAccordionMeta(output)}>
|
<ToolAccordion {...getAccordionMeta(output)}>
|
||||||
{isRunAgentExecutionStartedOutput(output) && (
|
{isRunAgentExecutionStartedOutput(output) && (
|
||||||
<ExecutionStartedCard output={output} />
|
<ExecutionStartedCard output={output} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{isRunAgentAgentDetailsOutput(output) && (
|
||||||
|
<AgentDetailsCard output={output} />
|
||||||
|
)}
|
||||||
|
|
||||||
|
{isRunAgentSetupRequirementsOutput(output) && (
|
||||||
|
<SetupRequirementsCard output={output} />
|
||||||
|
)}
|
||||||
|
|
||||||
|
{isRunAgentNeedLoginOutput(output) && (
|
||||||
|
<ContentMessage>{output.message}</ContentMessage>
|
||||||
|
)}
|
||||||
|
|
||||||
{isRunAgentErrorOutput(output) && <ErrorCard output={output} />}
|
{isRunAgentErrorOutput(output) && <ErrorCard output={output} />}
|
||||||
</ToolAccordion>
|
</ToolAccordion>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import type { SetupRequirementsResponse } from "@/app/api/__generated__/models/setupRequirementsResponse";
|
|
||||||
import { Button } from "@/components/atoms/Button/Button";
|
|
||||||
import { Text } from "@/components/atoms/Text/Text";
|
|
||||||
import { CredentialsGroupedView } from "@/components/contextual/CredentialsInput/components/CredentialsGroupedView/CredentialsGroupedView";
|
|
||||||
import type { CredentialsMetaInput } from "@/lib/autogpt-server-api/types";
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { CredentialsGroupedView } from "@/components/contextual/CredentialsInput/components/CredentialsGroupedView/CredentialsGroupedView";
|
||||||
|
import { Button } from "@/components/atoms/Button/Button";
|
||||||
|
import type { CredentialsMetaInput } from "@/lib/autogpt-server-api/types";
|
||||||
|
import type { SetupRequirementsResponse } from "@/app/api/__generated__/models/setupRequirementsResponse";
|
||||||
import { useCopilotChatActions } from "../../../../components/CopilotChatActionsProvider/useCopilotChatActions";
|
import { useCopilotChatActions } from "../../../../components/CopilotChatActionsProvider/useCopilotChatActions";
|
||||||
import {
|
import {
|
||||||
ContentBadge,
|
ContentBadge,
|
||||||
@@ -39,40 +38,40 @@ export function SetupRequirementsCard({ output }: Props) {
|
|||||||
setInputCredentials((prev) => ({ ...prev, [key]: value }));
|
setInputCredentials((prev) => ({ ...prev, [key]: value }));
|
||||||
}
|
}
|
||||||
|
|
||||||
const needsCredentials = credentialFields.length > 0;
|
const isAllComplete =
|
||||||
const isAllCredentialsComplete =
|
credentialFields.length > 0 &&
|
||||||
needsCredentials &&
|
|
||||||
[...requiredCredentials].every((key) => !!inputCredentials[key]);
|
[...requiredCredentials].every((key) => !!inputCredentials[key]);
|
||||||
|
|
||||||
const canProceed =
|
|
||||||
!hasSent && (!needsCredentials || isAllCredentialsComplete);
|
|
||||||
|
|
||||||
function handleProceed() {
|
function handleProceed() {
|
||||||
setHasSent(true);
|
setHasSent(true);
|
||||||
const message = needsCredentials
|
onSend(
|
||||||
? "I've configured the required credentials. Please check if everything is ready and proceed with running the agent."
|
"I've configured the required credentials. Please check if everything is ready and proceed with running the agent.",
|
||||||
: "Please proceed with running the agent.";
|
);
|
||||||
onSend(message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid gap-2">
|
<div className="grid gap-2">
|
||||||
<ContentMessage>{output.message}</ContentMessage>
|
<ContentMessage>{output.message}</ContentMessage>
|
||||||
|
|
||||||
{needsCredentials && (
|
{credentialFields.length > 0 && (
|
||||||
<div className="rounded-2xl border bg-background p-3">
|
<div className="rounded-2xl border bg-background p-3">
|
||||||
<Text variant="small" className="w-fit border-b text-zinc-500">
|
<CredentialsGroupedView
|
||||||
Agent credentials
|
credentialFields={credentialFields}
|
||||||
</Text>
|
requiredCredentials={requiredCredentials}
|
||||||
<div className="mt-6">
|
inputCredentials={inputCredentials}
|
||||||
<CredentialsGroupedView
|
inputValues={{}}
|
||||||
credentialFields={credentialFields}
|
onCredentialChange={handleCredentialChange}
|
||||||
requiredCredentials={requiredCredentials}
|
/>
|
||||||
inputCredentials={inputCredentials}
|
{isAllComplete && !hasSent && (
|
||||||
inputValues={{}}
|
<Button
|
||||||
onCredentialChange={handleCredentialChange}
|
variant="primary"
|
||||||
/>
|
size="small"
|
||||||
</div>
|
className="mt-3 w-full"
|
||||||
|
onClick={handleProceed}
|
||||||
|
>
|
||||||
|
Proceed
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -101,18 +100,6 @@ export function SetupRequirementsCard({ output }: Props) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{(needsCredentials || expectedInputs.length > 0) && (
|
|
||||||
<Button
|
|
||||||
variant="primary"
|
|
||||||
size="small"
|
|
||||||
className="mt-4 w-fit"
|
|
||||||
disabled={!canProceed}
|
|
||||||
onClick={handleProceed}
|
|
||||||
>
|
|
||||||
Proceed
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,19 +39,12 @@ export function RunBlockTool({ part }: Props) {
|
|||||||
const isError =
|
const isError =
|
||||||
part.state === "output-error" ||
|
part.state === "output-error" ||
|
||||||
(!!output && isRunBlockErrorOutput(output));
|
(!!output && isRunBlockErrorOutput(output));
|
||||||
const setupRequirementsOutput =
|
|
||||||
part.state === "output-available" &&
|
|
||||||
output &&
|
|
||||||
isRunBlockSetupRequirementsOutput(output)
|
|
||||||
? output
|
|
||||||
: null;
|
|
||||||
|
|
||||||
const hasExpandableContent =
|
const hasExpandableContent =
|
||||||
part.state === "output-available" &&
|
part.state === "output-available" &&
|
||||||
!!output &&
|
!!output &&
|
||||||
!setupRequirementsOutput &&
|
|
||||||
(isRunBlockBlockOutput(output) ||
|
(isRunBlockBlockOutput(output) ||
|
||||||
isRunBlockDetailsOutput(output) ||
|
isRunBlockDetailsOutput(output) ||
|
||||||
|
isRunBlockSetupRequirementsOutput(output) ||
|
||||||
isRunBlockErrorOutput(output));
|
isRunBlockErrorOutput(output));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -64,12 +57,6 @@ export function RunBlockTool({ part }: Props) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{setupRequirementsOutput && (
|
|
||||||
<div className="mt-2">
|
|
||||||
<SetupRequirementsCard output={setupRequirementsOutput} />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{hasExpandableContent && output && (
|
{hasExpandableContent && output && (
|
||||||
<ToolAccordion {...getAccordionMeta(output)}>
|
<ToolAccordion {...getAccordionMeta(output)}>
|
||||||
{isRunBlockBlockOutput(output) && <BlockOutputCard output={output} />}
|
{isRunBlockBlockOutput(output) && <BlockOutputCard output={output} />}
|
||||||
@@ -78,6 +65,10 @@ export function RunBlockTool({ part }: Props) {
|
|||||||
<BlockDetailsCard output={output} />
|
<BlockDetailsCard output={output} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{isRunBlockSetupRequirementsOutput(output) && (
|
||||||
|
<SetupRequirementsCard output={output} />
|
||||||
|
)}
|
||||||
|
|
||||||
{isRunBlockErrorOutput(output) && <ErrorCard output={output} />}
|
{isRunBlockErrorOutput(output) && <ErrorCard output={output} />}
|
||||||
</ToolAccordion>
|
</ToolAccordion>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -6,9 +6,15 @@ import { Text } from "@/components/atoms/Text/Text";
|
|||||||
import { CredentialsGroupedView } from "@/components/contextual/CredentialsInput/components/CredentialsGroupedView/CredentialsGroupedView";
|
import { CredentialsGroupedView } from "@/components/contextual/CredentialsInput/components/CredentialsGroupedView/CredentialsGroupedView";
|
||||||
import { FormRenderer } from "@/components/renderers/InputRenderer/FormRenderer";
|
import { FormRenderer } from "@/components/renderers/InputRenderer/FormRenderer";
|
||||||
import type { CredentialsMetaInput } from "@/lib/autogpt-server-api/types";
|
import type { CredentialsMetaInput } from "@/lib/autogpt-server-api/types";
|
||||||
|
import { AnimatePresence, motion } from "framer-motion";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useCopilotChatActions } from "../../../../components/CopilotChatActionsProvider/useCopilotChatActions";
|
import { useCopilotChatActions } from "../../../../components/CopilotChatActionsProvider/useCopilotChatActions";
|
||||||
import { ContentMessage } from "../../../../components/ToolAccordion/AccordionContent";
|
import {
|
||||||
|
ContentBadge,
|
||||||
|
ContentCardDescription,
|
||||||
|
ContentCardTitle,
|
||||||
|
ContentMessage,
|
||||||
|
} from "../../../../components/ToolAccordion/AccordionContent";
|
||||||
import {
|
import {
|
||||||
buildExpectedInputsSchema,
|
buildExpectedInputsSchema,
|
||||||
coerceCredentialFields,
|
coerceCredentialFields,
|
||||||
@@ -25,8 +31,10 @@ export function SetupRequirementsCard({ output }: Props) {
|
|||||||
const [inputCredentials, setInputCredentials] = useState<
|
const [inputCredentials, setInputCredentials] = useState<
|
||||||
Record<string, CredentialsMetaInput | undefined>
|
Record<string, CredentialsMetaInput | undefined>
|
||||||
>({});
|
>({});
|
||||||
|
const [hasSentCredentials, setHasSentCredentials] = useState(false);
|
||||||
|
|
||||||
|
const [showInputForm, setShowInputForm] = useState(false);
|
||||||
const [inputValues, setInputValues] = useState<Record<string, unknown>>({});
|
const [inputValues, setInputValues] = useState<Record<string, unknown>>({});
|
||||||
const [hasSent, setHasSent] = useState(false);
|
|
||||||
|
|
||||||
const { credentialFields, requiredCredentials } = coerceCredentialFields(
|
const { credentialFields, requiredCredentials } = coerceCredentialFields(
|
||||||
output.setup_info.user_readiness?.missing_credentials,
|
output.setup_info.user_readiness?.missing_credentials,
|
||||||
@@ -42,49 +50,27 @@ export function SetupRequirementsCard({ output }: Props) {
|
|||||||
setInputCredentials((prev) => ({ ...prev, [key]: value }));
|
setInputCredentials((prev) => ({ ...prev, [key]: value }));
|
||||||
}
|
}
|
||||||
|
|
||||||
const needsCredentials = credentialFields.length > 0;
|
|
||||||
const isAllCredentialsComplete =
|
const isAllCredentialsComplete =
|
||||||
needsCredentials &&
|
credentialFields.length > 0 &&
|
||||||
[...requiredCredentials].every((key) => !!inputCredentials[key]);
|
[...requiredCredentials].every((key) => !!inputCredentials[key]);
|
||||||
|
|
||||||
const needsInputs = inputSchema !== null;
|
function handleProceedCredentials() {
|
||||||
const requiredInputNames = expectedInputs
|
setHasSentCredentials(true);
|
||||||
.filter((i) => i.required)
|
onSend(
|
||||||
.map((i) => i.name);
|
"I've configured the required credentials. Please re-run the block now.",
|
||||||
const isAllInputsComplete =
|
);
|
||||||
needsInputs &&
|
}
|
||||||
requiredInputNames.every((name) => {
|
|
||||||
const v = inputValues[name];
|
|
||||||
return v !== undefined && v !== null && v !== "";
|
|
||||||
});
|
|
||||||
|
|
||||||
const canRun =
|
function handleRunWithInputs() {
|
||||||
!hasSent &&
|
const nonEmpty = Object.fromEntries(
|
||||||
(!needsCredentials || isAllCredentialsComplete) &&
|
Object.entries(inputValues).filter(
|
||||||
(!needsInputs || isAllInputsComplete);
|
([, v]) => v !== undefined && v !== null && v !== "",
|
||||||
|
),
|
||||||
function handleRun() {
|
);
|
||||||
setHasSent(true);
|
onSend(
|
||||||
|
`Run the block with these inputs: ${JSON.stringify(nonEmpty, null, 2)}`,
|
||||||
const parts: string[] = [];
|
);
|
||||||
if (needsCredentials) {
|
setShowInputForm(false);
|
||||||
parts.push("I've configured the required credentials.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needsInputs) {
|
|
||||||
const nonEmpty = Object.fromEntries(
|
|
||||||
Object.entries(inputValues).filter(
|
|
||||||
([, v]) => v !== undefined && v !== null && v !== "",
|
|
||||||
),
|
|
||||||
);
|
|
||||||
parts.push(
|
|
||||||
`Run the block with these inputs: ${JSON.stringify(nonEmpty, null, 2)}`,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
parts.push("Please re-run the block now.");
|
|
||||||
}
|
|
||||||
|
|
||||||
onSend(parts.join(" "));
|
|
||||||
setInputValues({});
|
setInputValues({});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,54 +78,119 @@ export function SetupRequirementsCard({ output }: Props) {
|
|||||||
<div className="grid gap-2">
|
<div className="grid gap-2">
|
||||||
<ContentMessage>{output.message}</ContentMessage>
|
<ContentMessage>{output.message}</ContentMessage>
|
||||||
|
|
||||||
{needsCredentials && (
|
{credentialFields.length > 0 && (
|
||||||
<div className="rounded-2xl border bg-background p-3">
|
<div className="rounded-2xl border bg-background p-3">
|
||||||
<Text variant="small" className="w-fit border-b text-zinc-500">
|
<CredentialsGroupedView
|
||||||
Block credentials
|
credentialFields={credentialFields}
|
||||||
</Text>
|
requiredCredentials={requiredCredentials}
|
||||||
<div className="mt-6">
|
inputCredentials={inputCredentials}
|
||||||
<CredentialsGroupedView
|
inputValues={{}}
|
||||||
credentialFields={credentialFields}
|
onCredentialChange={handleCredentialChange}
|
||||||
requiredCredentials={requiredCredentials}
|
/>
|
||||||
inputCredentials={inputCredentials}
|
{isAllCredentialsComplete && !hasSentCredentials && (
|
||||||
inputValues={{}}
|
<Button
|
||||||
onCredentialChange={handleCredentialChange}
|
variant="primary"
|
||||||
/>
|
size="small"
|
||||||
</div>
|
className="mt-3 w-full"
|
||||||
|
onClick={handleProceedCredentials}
|
||||||
|
>
|
||||||
|
Proceed
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{inputSchema && (
|
{inputSchema && (
|
||||||
<div className="rounded-2xl border bg-background p-3 pt-4">
|
<div className="flex gap-2 pt-2">
|
||||||
<Text variant="small" className="w-fit border-b text-zinc-500">
|
<Button
|
||||||
Block inputs
|
variant="outline"
|
||||||
</Text>
|
size="small"
|
||||||
<FormRenderer
|
className="w-fit"
|
||||||
jsonSchema={inputSchema}
|
onClick={() => setShowInputForm((prev) => !prev)}
|
||||||
className="mb-3 mt-3"
|
>
|
||||||
handleChange={(v) => setInputValues(v.formData ?? {})}
|
{showInputForm ? "Hide inputs" : "Fill in inputs"}
|
||||||
uiSchema={{
|
</Button>
|
||||||
"ui:submitButtonOptions": { norender: true },
|
|
||||||
}}
|
|
||||||
initialValues={inputValues}
|
|
||||||
formContext={{
|
|
||||||
showHandles: false,
|
|
||||||
size: "small",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{(needsCredentials || needsInputs) && (
|
<AnimatePresence initial={false}>
|
||||||
<Button
|
{showInputForm && inputSchema && (
|
||||||
variant="primary"
|
<motion.div
|
||||||
size="small"
|
initial={{ height: 0, opacity: 0, filter: "blur(6px)" }}
|
||||||
className="w-fit"
|
animate={{ height: "auto", opacity: 1, filter: "blur(0px)" }}
|
||||||
disabled={!canRun}
|
exit={{ height: 0, opacity: 0, filter: "blur(6px)" }}
|
||||||
onClick={handleRun}
|
transition={{
|
||||||
>
|
height: { type: "spring", bounce: 0.15, duration: 0.5 },
|
||||||
Proceed
|
opacity: { duration: 0.25 },
|
||||||
</Button>
|
filter: { duration: 0.2 },
|
||||||
|
}}
|
||||||
|
className="overflow-hidden"
|
||||||
|
style={{ willChange: "height, opacity, filter" }}
|
||||||
|
>
|
||||||
|
<div className="rounded-2xl border bg-background p-3 pt-4">
|
||||||
|
<Text variant="body-medium">Block inputs</Text>
|
||||||
|
<FormRenderer
|
||||||
|
jsonSchema={inputSchema}
|
||||||
|
handleChange={(v) => setInputValues(v.formData ?? {})}
|
||||||
|
uiSchema={{
|
||||||
|
"ui:submitButtonOptions": { norender: true },
|
||||||
|
}}
|
||||||
|
initialValues={inputValues}
|
||||||
|
formContext={{
|
||||||
|
showHandles: false,
|
||||||
|
size: "small",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className="-mt-8 flex gap-2">
|
||||||
|
<Button
|
||||||
|
variant="primary"
|
||||||
|
size="small"
|
||||||
|
className="w-fit"
|
||||||
|
onClick={handleRunWithInputs}
|
||||||
|
>
|
||||||
|
Run
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
size="small"
|
||||||
|
className="w-fit"
|
||||||
|
onClick={() => {
|
||||||
|
setShowInputForm(false);
|
||||||
|
setInputValues({});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
|
|
||||||
|
{expectedInputs.length > 0 && !inputSchema && (
|
||||||
|
<div className="rounded-2xl border bg-background p-3">
|
||||||
|
<ContentCardTitle className="text-xs">
|
||||||
|
Expected inputs
|
||||||
|
</ContentCardTitle>
|
||||||
|
<div className="mt-2 grid gap-2">
|
||||||
|
{expectedInputs.map((input) => (
|
||||||
|
<div key={input.name} className="rounded-xl border p-2">
|
||||||
|
<div className="flex items-center justify-between gap-2">
|
||||||
|
<ContentCardTitle className="text-xs">
|
||||||
|
{input.title}
|
||||||
|
</ContentCardTitle>
|
||||||
|
<ContentBadge>
|
||||||
|
{input.required ? "Required" : "Optional"}
|
||||||
|
</ContentBadge>
|
||||||
|
</div>
|
||||||
|
<ContentCardDescription className="mt-1">
|
||||||
|
{input.name} • {input.type}
|
||||||
|
{input.description ? ` \u2022 ${input.description}` : ""}
|
||||||
|
</ContentCardDescription>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ export function CredentialsFlatView({
|
|||||||
) : (
|
) : (
|
||||||
!readOnly && (
|
!readOnly && (
|
||||||
<Button
|
<Button
|
||||||
variant="primary"
|
variant="secondary"
|
||||||
size="small"
|
size="small"
|
||||||
onClick={onAddCredential}
|
onClick={onAddCredential}
|
||||||
className="w-fit"
|
className="w-fit"
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import { cn } from "@/lib/utils";
|
|
||||||
import { RJSFSchema } from "@rjsf/utils";
|
import { RJSFSchema } from "@rjsf/utils";
|
||||||
|
import { preprocessInputSchema } from "./utils/input-schema-pre-processor";
|
||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
|
import { customValidator } from "./utils/custom-validator";
|
||||||
import Form from "./registry";
|
import Form from "./registry";
|
||||||
import { ExtendedFormContextType } from "./types";
|
import { ExtendedFormContextType } from "./types";
|
||||||
import { customValidator } from "./utils/custom-validator";
|
|
||||||
import { generateUiSchemaForCustomFields } from "./utils/generate-ui-schema";
|
import { generateUiSchemaForCustomFields } from "./utils/generate-ui-schema";
|
||||||
import { preprocessInputSchema } from "./utils/input-schema-pre-processor";
|
|
||||||
|
|
||||||
type FormRendererProps = {
|
type FormRendererProps = {
|
||||||
jsonSchema: RJSFSchema;
|
jsonSchema: RJSFSchema;
|
||||||
@@ -13,17 +12,15 @@ type FormRendererProps = {
|
|||||||
uiSchema: any;
|
uiSchema: any;
|
||||||
initialValues: any;
|
initialValues: any;
|
||||||
formContext: ExtendedFormContextType;
|
formContext: ExtendedFormContextType;
|
||||||
className?: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export function FormRenderer({
|
export const FormRenderer = ({
|
||||||
jsonSchema,
|
jsonSchema,
|
||||||
handleChange,
|
handleChange,
|
||||||
uiSchema,
|
uiSchema,
|
||||||
initialValues,
|
initialValues,
|
||||||
formContext,
|
formContext,
|
||||||
className,
|
}: FormRendererProps) => {
|
||||||
}: FormRendererProps) {
|
|
||||||
const preprocessedSchema = useMemo(() => {
|
const preprocessedSchema = useMemo(() => {
|
||||||
return preprocessInputSchema(jsonSchema);
|
return preprocessInputSchema(jsonSchema);
|
||||||
}, [jsonSchema]);
|
}, [jsonSchema]);
|
||||||
@@ -34,10 +31,7 @@ export function FormRenderer({
|
|||||||
}, [preprocessedSchema, uiSchema]);
|
}, [preprocessedSchema, uiSchema]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div className={"mb-6 mt-4"} data-tutorial-id="input-handles">
|
||||||
className={cn("mb-6 mt-4", className)}
|
|
||||||
data-tutorial-id="input-handles"
|
|
||||||
>
|
|
||||||
<Form
|
<Form
|
||||||
formContext={formContext}
|
formContext={formContext}
|
||||||
idPrefix="agpt"
|
idPrefix="agpt"
|
||||||
@@ -51,4 +45,4 @@ export function FormRenderer({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -218,17 +218,6 @@ If you initially installed Docker with Hyper-V, you **don’t need to reinstall*
|
|||||||
|
|
||||||
For more details, refer to [Docker's official documentation](https://docs.docker.com/desktop/windows/wsl/).
|
For more details, refer to [Docker's official documentation](https://docs.docker.com/desktop/windows/wsl/).
|
||||||
|
|
||||||
### ⚠️ Podman Not Supported
|
|
||||||
|
|
||||||
AutoGPT requires **Docker** (Docker Desktop or Docker Engine). **Podman and podman-compose are not supported** and may cause path resolution issues, particularly on Windows.
|
|
||||||
|
|
||||||
If you see errors like:
|
|
||||||
```text
|
|
||||||
Error: the specified Containerfile or Dockerfile does not exist, ..\..\autogpt_platform\backend\Dockerfile
|
|
||||||
```
|
|
||||||
|
|
||||||
This indicates you're using Podman instead of Docker. Please install [Docker Desktop](https://docs.docker.com/desktop/) and use `docker compose` instead of `podman-compose`.
|
|
||||||
|
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user