mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-02-18 02:32:04 -05:00
Compare commits
2 Commits
docs/deplo
...
feat/fix-h
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c12894698e | ||
|
|
2f37aeec12 |
@@ -49,6 +49,7 @@ from .tools.models import (
|
|||||||
OperationPendingResponse,
|
OperationPendingResponse,
|
||||||
OperationStartedResponse,
|
OperationStartedResponse,
|
||||||
SetupRequirementsResponse,
|
SetupRequirementsResponse,
|
||||||
|
SuggestedGoalResponse,
|
||||||
UnderstandingUpdatedResponse,
|
UnderstandingUpdatedResponse,
|
||||||
)
|
)
|
||||||
from .tracking import track_user_message
|
from .tracking import track_user_message
|
||||||
@@ -1051,6 +1052,7 @@ ToolResponseUnion = (
|
|||||||
| AgentPreviewResponse
|
| AgentPreviewResponse
|
||||||
| AgentSavedResponse
|
| AgentSavedResponse
|
||||||
| ClarificationNeededResponse
|
| ClarificationNeededResponse
|
||||||
|
| SuggestedGoalResponse
|
||||||
| BlockListResponse
|
| BlockListResponse
|
||||||
| BlockDetailsResponse
|
| BlockDetailsResponse
|
||||||
| BlockOutputResponse
|
| BlockOutputResponse
|
||||||
|
|||||||
@@ -120,6 +120,8 @@ Adapt flexibly to the conversation context. Not every interaction requires all s
|
|||||||
- Find reusable components with `find_block`
|
- Find reusable components with `find_block`
|
||||||
- Create custom solutions with `create_agent` if nothing suitable exists
|
- Create custom solutions with `create_agent` if nothing suitable exists
|
||||||
- Modify existing library agents with `edit_agent`
|
- Modify existing library agents with `edit_agent`
|
||||||
|
- **When `create_agent` returns `suggested_goal`**: Present the suggestion to the user and ask "Would you like me to proceed with this refined goal?" If they accept, call `create_agent` again with the suggested goal.
|
||||||
|
- **When `create_agent` returns `clarifying_questions`**: After the user answers, call `create_agent` again with the original description AND the answers in the `context` parameter.
|
||||||
|
|
||||||
5. **Execute**: Run automations immediately, schedule them, or set up webhooks using `run_agent`. Test specific components with `run_block`.
|
5. **Execute**: Run automations immediately, schedule them, or set up webhooks using `run_agent`. Test specific components with `run_block`.
|
||||||
|
|
||||||
@@ -166,6 +168,11 @@ Adapt flexibly to the conversation context. Not every interaction requires all s
|
|||||||
- Use `add_understanding` to capture valuable business context
|
- Use `add_understanding` to capture valuable business context
|
||||||
- When tool calls fail, try alternative approaches
|
- When tool calls fail, try alternative approaches
|
||||||
|
|
||||||
|
**Handle Feedback Loops:**
|
||||||
|
- When a tool returns a suggested alternative (like a refined goal), present it clearly and ask the user for confirmation before proceeding
|
||||||
|
- When clarifying questions are answered, immediately re-call the tool with the accumulated context
|
||||||
|
- Don't ask redundant questions if the user has already provided context in the conversation
|
||||||
|
|
||||||
## CRITICAL REMINDER
|
## CRITICAL REMINDER
|
||||||
|
|
||||||
You are NOT a chatbot. You are NOT documentation. You are a partner who helps busy business owners get value quickly by showing proof through working automations. Bias toward action over explanation."""
|
You are NOT a chatbot. You are NOT documentation. You are a partner who helps busy business owners get value quickly by showing proof through working automations. Bias toward action over explanation."""
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ from .models import (
|
|||||||
ClarificationNeededResponse,
|
ClarificationNeededResponse,
|
||||||
ClarifyingQuestion,
|
ClarifyingQuestion,
|
||||||
ErrorResponse,
|
ErrorResponse,
|
||||||
|
SuggestedGoalResponse,
|
||||||
ToolResponseBase,
|
ToolResponseBase,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -186,26 +187,25 @@ class CreateAgentTool(BaseTool):
|
|||||||
if decomposition_result.get("type") == "unachievable_goal":
|
if decomposition_result.get("type") == "unachievable_goal":
|
||||||
suggested = decomposition_result.get("suggested_goal", "")
|
suggested = decomposition_result.get("suggested_goal", "")
|
||||||
reason = decomposition_result.get("reason", "")
|
reason = decomposition_result.get("reason", "")
|
||||||
return ErrorResponse(
|
return SuggestedGoalResponse(
|
||||||
message=(
|
message=(
|
||||||
f"This goal cannot be accomplished with the available blocks. "
|
f"This goal cannot be accomplished with the available blocks. {reason}"
|
||||||
f"{reason} "
|
|
||||||
f"Suggestion: {suggested}"
|
|
||||||
),
|
),
|
||||||
error="unachievable_goal",
|
suggested_goal=suggested,
|
||||||
details={"suggested_goal": suggested, "reason": reason},
|
reason=reason,
|
||||||
|
original_goal=description,
|
||||||
|
goal_type="unachievable",
|
||||||
session_id=session_id,
|
session_id=session_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
if decomposition_result.get("type") == "vague_goal":
|
if decomposition_result.get("type") == "vague_goal":
|
||||||
suggested = decomposition_result.get("suggested_goal", "")
|
suggested = decomposition_result.get("suggested_goal", "")
|
||||||
return ErrorResponse(
|
return SuggestedGoalResponse(
|
||||||
message=(
|
message="The goal is too vague to create a specific workflow.",
|
||||||
f"The goal is too vague to create a specific workflow. "
|
suggested_goal=suggested,
|
||||||
f"Suggestion: {suggested}"
|
reason="The goal needs more specific details",
|
||||||
),
|
original_goal=description,
|
||||||
error="vague_goal",
|
goal_type="vague",
|
||||||
details={"suggested_goal": suggested},
|
|
||||||
session_id=session_id,
|
session_id=session_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,142 @@
|
|||||||
|
"""Tests for CreateAgentTool response types."""
|
||||||
|
|
||||||
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from backend.api.features.chat.tools.create_agent import CreateAgentTool
|
||||||
|
from backend.api.features.chat.tools.models import (
|
||||||
|
ClarificationNeededResponse,
|
||||||
|
ErrorResponse,
|
||||||
|
SuggestedGoalResponse,
|
||||||
|
)
|
||||||
|
|
||||||
|
from ._test_data import make_session
|
||||||
|
|
||||||
|
_TEST_USER_ID = "test-user-create-agent"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def tool():
|
||||||
|
return CreateAgentTool()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def session():
|
||||||
|
return make_session(_TEST_USER_ID)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_missing_description_returns_error(tool, session):
|
||||||
|
"""Missing description returns ErrorResponse."""
|
||||||
|
result = await tool._execute(user_id=_TEST_USER_ID, session=session, description="")
|
||||||
|
assert isinstance(result, ErrorResponse)
|
||||||
|
assert result.error == "Missing description parameter"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_vague_goal_returns_suggested_goal_response(tool, session):
|
||||||
|
"""vague_goal decomposition result returns SuggestedGoalResponse, not ErrorResponse."""
|
||||||
|
vague_result = {
|
||||||
|
"type": "vague_goal",
|
||||||
|
"suggested_goal": "Monitor Twitter mentions for a specific keyword and send a daily digest email",
|
||||||
|
}
|
||||||
|
|
||||||
|
with (
|
||||||
|
patch(
|
||||||
|
"backend.api.features.chat.tools.create_agent.get_all_relevant_agents_for_generation",
|
||||||
|
new_callable=AsyncMock,
|
||||||
|
return_value=[],
|
||||||
|
),
|
||||||
|
patch(
|
||||||
|
"backend.api.features.chat.tools.create_agent.decompose_goal",
|
||||||
|
new_callable=AsyncMock,
|
||||||
|
return_value=vague_result,
|
||||||
|
),
|
||||||
|
):
|
||||||
|
result = await tool._execute(
|
||||||
|
user_id=_TEST_USER_ID,
|
||||||
|
session=session,
|
||||||
|
description="monitor social media",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert isinstance(result, SuggestedGoalResponse)
|
||||||
|
assert result.goal_type == "vague"
|
||||||
|
assert result.suggested_goal == vague_result["suggested_goal"]
|
||||||
|
assert result.original_goal == "monitor social media"
|
||||||
|
assert result.reason == "The goal needs more specific details"
|
||||||
|
assert not isinstance(result, ErrorResponse)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_unachievable_goal_returns_suggested_goal_response(tool, session):
|
||||||
|
"""unachievable_goal decomposition result returns SuggestedGoalResponse, not ErrorResponse."""
|
||||||
|
unachievable_result = {
|
||||||
|
"type": "unachievable_goal",
|
||||||
|
"suggested_goal": "Summarize the latest news articles on a topic and send them by email",
|
||||||
|
"reason": "There are no blocks for mind-reading.",
|
||||||
|
}
|
||||||
|
|
||||||
|
with (
|
||||||
|
patch(
|
||||||
|
"backend.api.features.chat.tools.create_agent.get_all_relevant_agents_for_generation",
|
||||||
|
new_callable=AsyncMock,
|
||||||
|
return_value=[],
|
||||||
|
),
|
||||||
|
patch(
|
||||||
|
"backend.api.features.chat.tools.create_agent.decompose_goal",
|
||||||
|
new_callable=AsyncMock,
|
||||||
|
return_value=unachievable_result,
|
||||||
|
),
|
||||||
|
):
|
||||||
|
result = await tool._execute(
|
||||||
|
user_id=_TEST_USER_ID,
|
||||||
|
session=session,
|
||||||
|
description="read my mind",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert isinstance(result, SuggestedGoalResponse)
|
||||||
|
assert result.goal_type == "unachievable"
|
||||||
|
assert result.suggested_goal == unachievable_result["suggested_goal"]
|
||||||
|
assert result.original_goal == "read my mind"
|
||||||
|
assert result.reason == unachievable_result["reason"]
|
||||||
|
assert not isinstance(result, ErrorResponse)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_clarifying_questions_returns_clarification_needed_response(
|
||||||
|
tool, session
|
||||||
|
):
|
||||||
|
"""clarifying_questions decomposition result returns ClarificationNeededResponse."""
|
||||||
|
clarifying_result = {
|
||||||
|
"type": "clarifying_questions",
|
||||||
|
"questions": [
|
||||||
|
{
|
||||||
|
"question": "What platform should be monitored?",
|
||||||
|
"keyword": "platform",
|
||||||
|
"example": "Twitter, Reddit",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
with (
|
||||||
|
patch(
|
||||||
|
"backend.api.features.chat.tools.create_agent.get_all_relevant_agents_for_generation",
|
||||||
|
new_callable=AsyncMock,
|
||||||
|
return_value=[],
|
||||||
|
),
|
||||||
|
patch(
|
||||||
|
"backend.api.features.chat.tools.create_agent.decompose_goal",
|
||||||
|
new_callable=AsyncMock,
|
||||||
|
return_value=clarifying_result,
|
||||||
|
),
|
||||||
|
):
|
||||||
|
result = await tool._execute(
|
||||||
|
user_id=_TEST_USER_ID,
|
||||||
|
session=session,
|
||||||
|
description="monitor social media and alert me",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert isinstance(result, ClarificationNeededResponse)
|
||||||
|
assert len(result.questions) == 1
|
||||||
|
assert result.questions[0].keyword == "platform"
|
||||||
@@ -50,6 +50,8 @@ class ResponseType(str, Enum):
|
|||||||
# Feature request types
|
# Feature request types
|
||||||
FEATURE_REQUEST_SEARCH = "feature_request_search"
|
FEATURE_REQUEST_SEARCH = "feature_request_search"
|
||||||
FEATURE_REQUEST_CREATED = "feature_request_created"
|
FEATURE_REQUEST_CREATED = "feature_request_created"
|
||||||
|
# Goal refinement
|
||||||
|
SUGGESTED_GOAL = "suggested_goal"
|
||||||
|
|
||||||
|
|
||||||
# Base response model
|
# Base response model
|
||||||
@@ -296,6 +298,22 @@ class ClarificationNeededResponse(ToolResponseBase):
|
|||||||
questions: list[ClarifyingQuestion] = Field(default_factory=list)
|
questions: list[ClarifyingQuestion] = Field(default_factory=list)
|
||||||
|
|
||||||
|
|
||||||
|
class SuggestedGoalResponse(ToolResponseBase):
|
||||||
|
"""Response when the goal needs refinement with a suggested alternative."""
|
||||||
|
|
||||||
|
type: ResponseType = ResponseType.SUGGESTED_GOAL
|
||||||
|
suggested_goal: str = Field(description="The suggested alternative goal")
|
||||||
|
reason: str = Field(
|
||||||
|
default="", description="Why the original goal needs refinement"
|
||||||
|
)
|
||||||
|
original_goal: str = Field(
|
||||||
|
default="", description="The user's original goal for context"
|
||||||
|
)
|
||||||
|
goal_type: str = Field(
|
||||||
|
default="vague", description="Type: 'vague' or 'unachievable'"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Documentation search models
|
# Documentation search models
|
||||||
class DocSearchResult(BaseModel):
|
class DocSearchResult(BaseModel):
|
||||||
"""A single documentation search result."""
|
"""A single documentation search result."""
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import {
|
|||||||
ClarifyingQuestion,
|
ClarifyingQuestion,
|
||||||
} from "./components/ClarificationQuestionsCard";
|
} from "./components/ClarificationQuestionsCard";
|
||||||
import { MiniGame } from "./components/MiniGame/MiniGame";
|
import { MiniGame } from "./components/MiniGame/MiniGame";
|
||||||
|
import { SuggestedGoalCard } from "./components/SuggestedGoalCard";
|
||||||
import {
|
import {
|
||||||
AccordionIcon,
|
AccordionIcon,
|
||||||
formatMaybeJson,
|
formatMaybeJson,
|
||||||
@@ -37,6 +38,7 @@ import {
|
|||||||
isOperationInProgressOutput,
|
isOperationInProgressOutput,
|
||||||
isOperationPendingOutput,
|
isOperationPendingOutput,
|
||||||
isOperationStartedOutput,
|
isOperationStartedOutput,
|
||||||
|
isSuggestedGoalOutput,
|
||||||
ToolIcon,
|
ToolIcon,
|
||||||
truncateText,
|
truncateText,
|
||||||
type CreateAgentToolOutput,
|
type CreateAgentToolOutput,
|
||||||
@@ -76,6 +78,13 @@ function getAccordionMeta(output: CreateAgentToolOutput) {
|
|||||||
expanded: true,
|
expanded: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if (isSuggestedGoalOutput(output)) {
|
||||||
|
return {
|
||||||
|
icon,
|
||||||
|
title: "Goal needs refinement",
|
||||||
|
expanded: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
isOperationStartedOutput(output) ||
|
isOperationStartedOutput(output) ||
|
||||||
isOperationPendingOutput(output) ||
|
isOperationPendingOutput(output) ||
|
||||||
@@ -123,8 +132,13 @@ export function CreateAgentTool({ part }: Props) {
|
|||||||
isAgentPreviewOutput(output) ||
|
isAgentPreviewOutput(output) ||
|
||||||
isAgentSavedOutput(output) ||
|
isAgentSavedOutput(output) ||
|
||||||
isClarificationNeededOutput(output) ||
|
isClarificationNeededOutput(output) ||
|
||||||
|
isSuggestedGoalOutput(output) ||
|
||||||
isErrorOutput(output));
|
isErrorOutput(output));
|
||||||
|
|
||||||
|
function handleUseSuggestedGoal(goal: string) {
|
||||||
|
onSend(`Please create an agent with this goal: ${goal}`);
|
||||||
|
}
|
||||||
|
|
||||||
function handleClarificationAnswers(answers: Record<string, string>) {
|
function handleClarificationAnswers(answers: Record<string, string>) {
|
||||||
const questions =
|
const questions =
|
||||||
output && isClarificationNeededOutput(output)
|
output && isClarificationNeededOutput(output)
|
||||||
@@ -239,6 +253,15 @@ export function CreateAgentTool({ part }: Props) {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{isSuggestedGoalOutput(output) && (
|
||||||
|
<SuggestedGoalCard
|
||||||
|
message={output.message}
|
||||||
|
suggestedGoal={output.suggested_goal}
|
||||||
|
goalType={output.goal_type ?? "vague"}
|
||||||
|
onUseSuggestedGoal={handleUseSuggestedGoal}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
{isErrorOutput(output) && (
|
{isErrorOutput(output) && (
|
||||||
<ContentGrid>
|
<ContentGrid>
|
||||||
<ContentMessage>{output.message}</ContentMessage>
|
<ContentMessage>{output.message}</ContentMessage>
|
||||||
@@ -252,6 +275,22 @@ export function CreateAgentTool({ part }: Props) {
|
|||||||
{formatMaybeJson(output.details)}
|
{formatMaybeJson(output.details)}
|
||||||
</ContentCodeBlock>
|
</ContentCodeBlock>
|
||||||
)}
|
)}
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="small"
|
||||||
|
onClick={() => onSend("Please try creating the agent again.")}
|
||||||
|
>
|
||||||
|
Try again
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="small"
|
||||||
|
onClick={() => onSend("Can you help me simplify this goal?")}
|
||||||
|
>
|
||||||
|
Simplify goal
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</ContentGrid>
|
</ContentGrid>
|
||||||
)}
|
)}
|
||||||
</ToolAccordion>
|
</ToolAccordion>
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { Button } from "@/components/atoms/Button/Button";
|
||||||
|
import { Text } from "@/components/atoms/Text/Text";
|
||||||
|
import { ArrowRightIcon, LightbulbIcon } from "@phosphor-icons/react";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
message: string;
|
||||||
|
suggestedGoal: string;
|
||||||
|
goalType: string;
|
||||||
|
onUseSuggestedGoal: (goal: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SuggestedGoalCard({
|
||||||
|
message,
|
||||||
|
suggestedGoal,
|
||||||
|
goalType,
|
||||||
|
onUseSuggestedGoal,
|
||||||
|
}: Props) {
|
||||||
|
return (
|
||||||
|
<div className="rounded-xl border border-amber-200 bg-amber-50/50 p-4">
|
||||||
|
<div className="flex items-start gap-3">
|
||||||
|
<LightbulbIcon
|
||||||
|
size={20}
|
||||||
|
weight="fill"
|
||||||
|
className="mt-0.5 text-amber-600"
|
||||||
|
/>
|
||||||
|
<div className="flex-1 space-y-3">
|
||||||
|
<div>
|
||||||
|
<Text variant="body-medium" className="font-medium text-slate-900">
|
||||||
|
{goalType === "unachievable"
|
||||||
|
? "Goal cannot be accomplished"
|
||||||
|
: "Goal needs more detail"}
|
||||||
|
</Text>
|
||||||
|
<Text variant="small" className="text-slate-600">
|
||||||
|
{message}
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="rounded-lg border border-amber-300 bg-white p-3">
|
||||||
|
<Text variant="small" className="mb-1 font-semibold text-amber-800">
|
||||||
|
Suggested alternative:
|
||||||
|
</Text>
|
||||||
|
<Text variant="body-medium" className="text-slate-900">
|
||||||
|
{suggestedGoal}
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
onClick={() => onUseSuggestedGoal(suggestedGoal)}
|
||||||
|
variant="primary"
|
||||||
|
>
|
||||||
|
<span className="inline-flex items-center gap-1.5">
|
||||||
|
Use this goal <ArrowRightIcon size={14} weight="bold" />
|
||||||
|
</span>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import type { OperationInProgressResponse } from "@/app/api/__generated__/models
|
|||||||
import type { OperationPendingResponse } from "@/app/api/__generated__/models/operationPendingResponse";
|
import type { OperationPendingResponse } from "@/app/api/__generated__/models/operationPendingResponse";
|
||||||
import type { OperationStartedResponse } from "@/app/api/__generated__/models/operationStartedResponse";
|
import type { OperationStartedResponse } from "@/app/api/__generated__/models/operationStartedResponse";
|
||||||
import { ResponseType } from "@/app/api/__generated__/models/responseType";
|
import { ResponseType } from "@/app/api/__generated__/models/responseType";
|
||||||
|
import type { SuggestedGoalResponse } from "@/app/api/__generated__/models/suggestedGoalResponse";
|
||||||
import {
|
import {
|
||||||
PlusCircleIcon,
|
PlusCircleIcon,
|
||||||
PlusIcon,
|
PlusIcon,
|
||||||
@@ -21,6 +22,7 @@ export type CreateAgentToolOutput =
|
|||||||
| AgentPreviewResponse
|
| AgentPreviewResponse
|
||||||
| AgentSavedResponse
|
| AgentSavedResponse
|
||||||
| ClarificationNeededResponse
|
| ClarificationNeededResponse
|
||||||
|
| SuggestedGoalResponse
|
||||||
| ErrorResponse;
|
| ErrorResponse;
|
||||||
|
|
||||||
function parseOutput(output: unknown): CreateAgentToolOutput | null {
|
function parseOutput(output: unknown): CreateAgentToolOutput | null {
|
||||||
@@ -43,6 +45,7 @@ function parseOutput(output: unknown): CreateAgentToolOutput | null {
|
|||||||
type === ResponseType.agent_preview ||
|
type === ResponseType.agent_preview ||
|
||||||
type === ResponseType.agent_saved ||
|
type === ResponseType.agent_saved ||
|
||||||
type === ResponseType.clarification_needed ||
|
type === ResponseType.clarification_needed ||
|
||||||
|
type === ResponseType.suggested_goal ||
|
||||||
type === ResponseType.error
|
type === ResponseType.error
|
||||||
) {
|
) {
|
||||||
return output as CreateAgentToolOutput;
|
return output as CreateAgentToolOutput;
|
||||||
@@ -55,6 +58,7 @@ function parseOutput(output: unknown): CreateAgentToolOutput | null {
|
|||||||
if ("agent_id" in output && "library_agent_id" in output)
|
if ("agent_id" in output && "library_agent_id" in output)
|
||||||
return output as AgentSavedResponse;
|
return output as AgentSavedResponse;
|
||||||
if ("questions" in output) return output as ClarificationNeededResponse;
|
if ("questions" in output) return output as ClarificationNeededResponse;
|
||||||
|
if ("suggested_goal" in output) return output as SuggestedGoalResponse;
|
||||||
if ("error" in output || "details" in output)
|
if ("error" in output || "details" in output)
|
||||||
return output as ErrorResponse;
|
return output as ErrorResponse;
|
||||||
}
|
}
|
||||||
@@ -114,6 +118,14 @@ export function isClarificationNeededOutput(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isSuggestedGoalOutput(
|
||||||
|
output: CreateAgentToolOutput,
|
||||||
|
): output is SuggestedGoalResponse {
|
||||||
|
return (
|
||||||
|
output.type === ResponseType.suggested_goal || "suggested_goal" in output
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function isErrorOutput(
|
export function isErrorOutput(
|
||||||
output: CreateAgentToolOutput,
|
output: CreateAgentToolOutput,
|
||||||
): output is ErrorResponse {
|
): output is ErrorResponse {
|
||||||
@@ -139,6 +151,7 @@ export function getAnimationText(part: {
|
|||||||
if (isAgentSavedOutput(output)) return `Saved "${output.agent_name}"`;
|
if (isAgentSavedOutput(output)) return `Saved "${output.agent_name}"`;
|
||||||
if (isAgentPreviewOutput(output)) return `Preview "${output.agent_name}"`;
|
if (isAgentPreviewOutput(output)) return `Preview "${output.agent_name}"`;
|
||||||
if (isClarificationNeededOutput(output)) return "Needs clarification";
|
if (isClarificationNeededOutput(output)) return "Needs clarification";
|
||||||
|
if (isSuggestedGoalOutput(output)) return "Goal needs refinement";
|
||||||
return "Error creating agent";
|
return "Error creating agent";
|
||||||
}
|
}
|
||||||
case "output-error":
|
case "output-error":
|
||||||
|
|||||||
@@ -1052,6 +1052,7 @@
|
|||||||
{
|
{
|
||||||
"$ref": "#/components/schemas/ClarificationNeededResponse"
|
"$ref": "#/components/schemas/ClarificationNeededResponse"
|
||||||
},
|
},
|
||||||
|
{ "$ref": "#/components/schemas/SuggestedGoalResponse" },
|
||||||
{ "$ref": "#/components/schemas/BlockListResponse" },
|
{ "$ref": "#/components/schemas/BlockListResponse" },
|
||||||
{ "$ref": "#/components/schemas/BlockDetailsResponse" },
|
{ "$ref": "#/components/schemas/BlockDetailsResponse" },
|
||||||
{ "$ref": "#/components/schemas/BlockOutputResponse" },
|
{ "$ref": "#/components/schemas/BlockOutputResponse" },
|
||||||
@@ -10766,7 +10767,8 @@
|
|||||||
"bash_exec",
|
"bash_exec",
|
||||||
"operation_status",
|
"operation_status",
|
||||||
"feature_request_search",
|
"feature_request_search",
|
||||||
"feature_request_created"
|
"feature_request_created",
|
||||||
|
"suggested_goal"
|
||||||
],
|
],
|
||||||
"title": "ResponseType",
|
"title": "ResponseType",
|
||||||
"description": "Types of tool responses."
|
"description": "Types of tool responses."
|
||||||
@@ -11647,6 +11649,46 @@
|
|||||||
"enum": ["DRAFT", "PENDING", "APPROVED", "REJECTED"],
|
"enum": ["DRAFT", "PENDING", "APPROVED", "REJECTED"],
|
||||||
"title": "SubmissionStatus"
|
"title": "SubmissionStatus"
|
||||||
},
|
},
|
||||||
|
"SuggestedGoalResponse": {
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"$ref": "#/components/schemas/ResponseType",
|
||||||
|
"default": "suggested_goal"
|
||||||
|
},
|
||||||
|
"message": { "type": "string", "title": "Message" },
|
||||||
|
"session_id": {
|
||||||
|
"anyOf": [{ "type": "string" }, { "type": "null" }],
|
||||||
|
"title": "Session Id"
|
||||||
|
},
|
||||||
|
"suggested_goal": {
|
||||||
|
"type": "string",
|
||||||
|
"title": "Suggested Goal",
|
||||||
|
"description": "The suggested alternative goal"
|
||||||
|
},
|
||||||
|
"reason": {
|
||||||
|
"type": "string",
|
||||||
|
"title": "Reason",
|
||||||
|
"description": "Why the original goal needs refinement",
|
||||||
|
"default": ""
|
||||||
|
},
|
||||||
|
"original_goal": {
|
||||||
|
"type": "string",
|
||||||
|
"title": "Original Goal",
|
||||||
|
"description": "The user's original goal for context",
|
||||||
|
"default": ""
|
||||||
|
},
|
||||||
|
"goal_type": {
|
||||||
|
"type": "string",
|
||||||
|
"title": "Goal Type",
|
||||||
|
"description": "Type: 'vague' or 'unachievable'",
|
||||||
|
"default": "vague"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object",
|
||||||
|
"required": ["message", "suggested_goal"],
|
||||||
|
"title": "SuggestedGoalResponse",
|
||||||
|
"description": "Response when the goal needs refinement with a suggested alternative."
|
||||||
|
},
|
||||||
"SuggestionsResponse": {
|
"SuggestionsResponse": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"otto_suggestions": {
|
"otto_suggestions": {
|
||||||
|
|||||||
Reference in New Issue
Block a user