mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-02-17 02:03:00 -05:00
Compare commits
2 Commits
fix/claude
...
docs/podma
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b00336b66b | ||
|
|
23ea6bd38c |
9
.github/workflows/platform-backend-ci.yml
vendored
9
.github/workflows/platform-backend-ci.yml
vendored
@@ -41,18 +41,13 @@ jobs:
|
|||||||
ports:
|
ports:
|
||||||
- 6379:6379
|
- 6379:6379
|
||||||
rabbitmq:
|
rabbitmq:
|
||||||
image: rabbitmq:4.1.4
|
image: rabbitmq:3.12-management
|
||||||
ports:
|
ports:
|
||||||
- 5672:5672
|
- 5672:5672
|
||||||
|
- 15672:15672
|
||||||
env:
|
env:
|
||||||
RABBITMQ_DEFAULT_USER: ${{ env.RABBITMQ_DEFAULT_USER }}
|
RABBITMQ_DEFAULT_USER: ${{ env.RABBITMQ_DEFAULT_USER }}
|
||||||
RABBITMQ_DEFAULT_PASS: ${{ env.RABBITMQ_DEFAULT_PASS }}
|
RABBITMQ_DEFAULT_PASS: ${{ env.RABBITMQ_DEFAULT_PASS }}
|
||||||
options: >-
|
|
||||||
--health-cmd "rabbitmq-diagnostics -q ping"
|
|
||||||
--health-interval 30s
|
|
||||||
--health-timeout 10s
|
|
||||||
--health-retries 5
|
|
||||||
--health-start-period 10s
|
|
||||||
clamav:
|
clamav:
|
||||||
image: clamav/clamav-debian:latest
|
image: clamav/clamav-debian:latest
|
||||||
ports:
|
ports:
|
||||||
|
|||||||
6
.github/workflows/platform-frontend-ci.yml
vendored
6
.github/workflows/platform-frontend-ci.yml
vendored
@@ -6,16 +6,10 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- ".github/workflows/platform-frontend-ci.yml"
|
- ".github/workflows/platform-frontend-ci.yml"
|
||||||
- "autogpt_platform/frontend/**"
|
- "autogpt_platform/frontend/**"
|
||||||
- "autogpt_platform/backend/Dockerfile"
|
|
||||||
- "autogpt_platform/docker-compose.yml"
|
|
||||||
- "autogpt_platform/docker-compose.platform.yml"
|
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- ".github/workflows/platform-frontend-ci.yml"
|
- ".github/workflows/platform-frontend-ci.yml"
|
||||||
- "autogpt_platform/frontend/**"
|
- "autogpt_platform/frontend/**"
|
||||||
- "autogpt_platform/backend/Dockerfile"
|
|
||||||
- "autogpt_platform/docker-compose.yml"
|
|
||||||
- "autogpt_platform/docker-compose.platform.yml"
|
|
||||||
merge_group:
|
merge_group:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,63 @@ COPY autogpt_platform/backend/backend/data/partial_types.py ./backend/data/parti
|
|||||||
COPY autogpt_platform/backend/gen_prisma_types_stub.py ./
|
COPY autogpt_platform/backend/gen_prisma_types_stub.py ./
|
||||||
RUN poetry run prisma generate && poetry run gen-prisma-stub
|
RUN poetry run prisma generate && poetry run gen-prisma-stub
|
||||||
|
|
||||||
|
# ============================== BACKEND SERVER ============================== #
|
||||||
|
|
||||||
|
FROM debian:13-slim AS server
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
ENV POETRY_HOME=/opt/poetry \
|
||||||
|
POETRY_NO_INTERACTION=1 \
|
||||||
|
POETRY_VIRTUALENVS_CREATE=true \
|
||||||
|
POETRY_VIRTUALENVS_IN_PROJECT=true \
|
||||||
|
DEBIAN_FRONTEND=noninteractive
|
||||||
|
ENV PATH=/opt/poetry/bin:$PATH
|
||||||
|
|
||||||
|
# Install Python, FFmpeg, ImageMagick, and CLI tools for agent use.
|
||||||
|
# bubblewrap provides OS-level sandbox (whitelist-only FS + no network)
|
||||||
|
# for the bash_exec MCP tool.
|
||||||
|
# Using --no-install-recommends saves ~650MB by skipping unnecessary deps like llvm, mesa, etc.
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
python3.13 \
|
||||||
|
python3-pip \
|
||||||
|
ffmpeg \
|
||||||
|
imagemagick \
|
||||||
|
jq \
|
||||||
|
ripgrep \
|
||||||
|
tree \
|
||||||
|
bubblewrap \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
COPY --from=builder /usr/local/lib/python3* /usr/local/lib/python3*
|
||||||
|
COPY --from=builder /usr/local/bin/poetry /usr/local/bin/poetry
|
||||||
|
# Copy Node.js installation for Prisma
|
||||||
|
COPY --from=builder /usr/bin/node /usr/bin/node
|
||||||
|
COPY --from=builder /usr/lib/node_modules /usr/lib/node_modules
|
||||||
|
COPY --from=builder /usr/bin/npm /usr/bin/npm
|
||||||
|
COPY --from=builder /usr/bin/npx /usr/bin/npx
|
||||||
|
COPY --from=builder /root/.cache/prisma-python/binaries /root/.cache/prisma-python/binaries
|
||||||
|
|
||||||
|
WORKDIR /app/autogpt_platform/backend
|
||||||
|
|
||||||
|
# Copy only the .venv from builder (not the entire /app directory)
|
||||||
|
# The .venv includes the generated Prisma client
|
||||||
|
COPY --from=builder /app/autogpt_platform/backend/.venv ./.venv
|
||||||
|
ENV PATH="/app/autogpt_platform/backend/.venv/bin:$PATH"
|
||||||
|
|
||||||
|
# Copy dependency files + autogpt_libs (path dependency)
|
||||||
|
COPY autogpt_platform/autogpt_libs /app/autogpt_platform/autogpt_libs
|
||||||
|
COPY autogpt_platform/backend/poetry.lock autogpt_platform/backend/pyproject.toml ./
|
||||||
|
|
||||||
|
# Copy backend code + docs (for Copilot docs search)
|
||||||
|
COPY autogpt_platform/backend ./
|
||||||
|
COPY docs /app/docs
|
||||||
|
RUN poetry install --no-ansi --only-root
|
||||||
|
|
||||||
|
ENV PORT=8000
|
||||||
|
|
||||||
|
CMD ["poetry", "run", "rest"]
|
||||||
|
|
||||||
# =============================== DB MIGRATOR =============================== #
|
# =============================== DB MIGRATOR =============================== #
|
||||||
|
|
||||||
# Lightweight migrate stage - only needs Prisma CLI, not full Python environment
|
# Lightweight migrate stage - only needs Prisma CLI, not full Python environment
|
||||||
@@ -84,59 +141,3 @@ COPY autogpt_platform/backend/schema.prisma ./
|
|||||||
COPY autogpt_platform/backend/backend/data/partial_types.py ./backend/data/partial_types.py
|
COPY autogpt_platform/backend/backend/data/partial_types.py ./backend/data/partial_types.py
|
||||||
COPY autogpt_platform/backend/gen_prisma_types_stub.py ./
|
COPY autogpt_platform/backend/gen_prisma_types_stub.py ./
|
||||||
COPY autogpt_platform/backend/migrations ./migrations
|
COPY autogpt_platform/backend/migrations ./migrations
|
||||||
|
|
||||||
# ============================== BACKEND SERVER ============================== #
|
|
||||||
|
|
||||||
FROM debian:13-slim AS server
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
|
||||||
|
|
||||||
# Install Python, FFmpeg, ImageMagick, and CLI tools for agent use.
|
|
||||||
# bubblewrap provides OS-level sandbox (whitelist-only FS + no network)
|
|
||||||
# for the bash_exec MCP tool.
|
|
||||||
# Using --no-install-recommends saves ~650MB by skipping unnecessary deps like llvm, mesa, etc.
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
||||||
python3.13 \
|
|
||||||
python3-pip \
|
|
||||||
ffmpeg \
|
|
||||||
imagemagick \
|
|
||||||
jq \
|
|
||||||
ripgrep \
|
|
||||||
tree \
|
|
||||||
bubblewrap \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Copy poetry (build-time only, for `poetry install --only-root` to create entry points)
|
|
||||||
COPY --from=builder /usr/local/lib/python3* /usr/local/lib/python3*
|
|
||||||
COPY --from=builder /usr/local/bin/poetry /usr/local/bin/poetry
|
|
||||||
# Copy Node.js installation for Prisma
|
|
||||||
COPY --from=builder /usr/bin/node /usr/bin/node
|
|
||||||
COPY --from=builder /usr/lib/node_modules /usr/lib/node_modules
|
|
||||||
COPY --from=builder /usr/bin/npm /usr/bin/npm
|
|
||||||
COPY --from=builder /usr/bin/npx /usr/bin/npx
|
|
||||||
COPY --from=builder /root/.cache/prisma-python/binaries /root/.cache/prisma-python/binaries
|
|
||||||
|
|
||||||
WORKDIR /app/autogpt_platform/backend
|
|
||||||
|
|
||||||
# Copy only the .venv from builder (not the entire /app directory)
|
|
||||||
# The .venv includes the generated Prisma client
|
|
||||||
COPY --from=builder /app/autogpt_platform/backend/.venv ./.venv
|
|
||||||
ENV PATH="/app/autogpt_platform/backend/.venv/bin:$PATH"
|
|
||||||
|
|
||||||
# Copy dependency files + autogpt_libs (path dependency)
|
|
||||||
COPY autogpt_platform/autogpt_libs /app/autogpt_platform/autogpt_libs
|
|
||||||
COPY autogpt_platform/backend/poetry.lock autogpt_platform/backend/pyproject.toml ./
|
|
||||||
|
|
||||||
# Copy backend code + docs (for Copilot docs search)
|
|
||||||
COPY autogpt_platform/backend ./
|
|
||||||
COPY docs /app/docs
|
|
||||||
# Install the project package to create entry point scripts in .venv/bin/
|
|
||||||
# (e.g., rest, executor, ws, db, scheduler, notification - see [tool.poetry.scripts])
|
|
||||||
RUN POETRY_VIRTUALENVS_CREATE=true POETRY_VIRTUALENVS_IN_PROJECT=true \
|
|
||||||
poetry install --no-ansi --only-root
|
|
||||||
|
|
||||||
ENV PORT=8000
|
|
||||||
|
|
||||||
CMD ["rest"]
|
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ from .model import (
|
|||||||
ChatSession,
|
ChatSession,
|
||||||
append_and_save_message,
|
append_and_save_message,
|
||||||
create_chat_session,
|
create_chat_session,
|
||||||
delete_chat_session,
|
|
||||||
get_chat_session,
|
get_chat_session,
|
||||||
get_user_sessions,
|
get_user_sessions,
|
||||||
)
|
)
|
||||||
@@ -212,43 +211,6 @@ async def create_session(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@router.delete(
|
|
||||||
"/sessions/{session_id}",
|
|
||||||
dependencies=[Security(auth.requires_user)],
|
|
||||||
status_code=204,
|
|
||||||
responses={404: {"description": "Session not found or access denied"}},
|
|
||||||
)
|
|
||||||
async def delete_session(
|
|
||||||
session_id: str,
|
|
||||||
user_id: Annotated[str, Security(auth.get_user_id)],
|
|
||||||
) -> Response:
|
|
||||||
"""
|
|
||||||
Delete a chat session.
|
|
||||||
|
|
||||||
Permanently removes a chat session and all its messages.
|
|
||||||
Only the owner can delete their sessions.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
session_id: The session ID to delete.
|
|
||||||
user_id: The authenticated user's ID.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
204 No Content on success.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
HTTPException: 404 if session not found or not owned by user.
|
|
||||||
"""
|
|
||||||
deleted = await delete_chat_session(session_id, user_id)
|
|
||||||
|
|
||||||
if not deleted:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=404,
|
|
||||||
detail=f"Session {session_id} not found or access denied",
|
|
||||||
)
|
|
||||||
|
|
||||||
return Response(status_code=204)
|
|
||||||
|
|
||||||
|
|
||||||
@router.get(
|
@router.get(
|
||||||
"/sessions/{session_id}",
|
"/sessions/{session_id}",
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -187,11 +187,9 @@ class ClaudeCodeBlock(Block):
|
|||||||
)
|
)
|
||||||
files: list[SandboxFileOutput] = SchemaField(
|
files: list[SandboxFileOutput] = SchemaField(
|
||||||
description=(
|
description=(
|
||||||
"List of files created/modified by Claude Code during this execution. "
|
"List of text files created/modified by Claude Code during this execution. "
|
||||||
"Includes text files and binary files (images, PDFs, etc.). "
|
|
||||||
"Each file has 'path', 'relative_path', 'name', 'content', and 'workspace_ref' fields. "
|
"Each file has 'path', 'relative_path', 'name', 'content', and 'workspace_ref' fields. "
|
||||||
"workspace_ref contains a workspace:// URI for workspace storage. "
|
"workspace_ref contains a workspace:// URI if the file was stored to workspace."
|
||||||
"For binary files, content contains a placeholder; use workspace_ref to access the file."
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
conversation_history: str = SchemaField(
|
conversation_history: str = SchemaField(
|
||||||
@@ -455,14 +453,12 @@ class ClaudeCodeBlock(Block):
|
|||||||
new_conversation_history = turn_entry
|
new_conversation_history = turn_entry
|
||||||
|
|
||||||
# Extract files created/modified during this run and store to workspace
|
# Extract files created/modified during this run and store to workspace
|
||||||
# Include binary files (images, PDFs, etc.) - they'll be stored via
|
|
||||||
# store_media_file which handles virus scanning and workspace storage
|
|
||||||
sandbox_files = await extract_and_store_sandbox_files(
|
sandbox_files = await extract_and_store_sandbox_files(
|
||||||
sandbox=sandbox,
|
sandbox=sandbox,
|
||||||
working_directory=working_directory,
|
working_directory=working_directory,
|
||||||
execution_context=execution_context,
|
execution_context=execution_context,
|
||||||
since_timestamp=start_timestamp,
|
since_timestamp=start_timestamp,
|
||||||
text_only=False, # Extract both text and binary files
|
text_only=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -74,51 +74,8 @@ TEXT_EXTENSIONS = {
|
|||||||
".tex",
|
".tex",
|
||||||
".csv",
|
".csv",
|
||||||
".log",
|
".log",
|
||||||
".svg", # SVG is XML-based text
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Binary file extensions we explicitly support extracting
|
|
||||||
# These are common output formats that users expect to retrieve
|
|
||||||
BINARY_EXTENSIONS = {
|
|
||||||
# Images
|
|
||||||
".png",
|
|
||||||
".jpg",
|
|
||||||
".jpeg",
|
|
||||||
".gif",
|
|
||||||
".webp",
|
|
||||||
".ico",
|
|
||||||
".bmp",
|
|
||||||
".tiff",
|
|
||||||
".tif",
|
|
||||||
# Documents
|
|
||||||
".pdf",
|
|
||||||
# Archives
|
|
||||||
".zip",
|
|
||||||
".tar",
|
|
||||||
".gz",
|
|
||||||
".7z",
|
|
||||||
# Audio
|
|
||||||
".mp3",
|
|
||||||
".wav",
|
|
||||||
".ogg",
|
|
||||||
".flac",
|
|
||||||
# Video
|
|
||||||
".mp4",
|
|
||||||
".webm",
|
|
||||||
".mov",
|
|
||||||
".avi",
|
|
||||||
# Fonts
|
|
||||||
".woff",
|
|
||||||
".woff2",
|
|
||||||
".ttf",
|
|
||||||
".otf",
|
|
||||||
".eot",
|
|
||||||
}
|
|
||||||
|
|
||||||
# Maximum file size for binary extraction (50MB)
|
|
||||||
# Prevents OOM from accidentally extracting huge files
|
|
||||||
MAX_BINARY_FILE_SIZE = 50 * 1024 * 1024
|
|
||||||
|
|
||||||
|
|
||||||
class SandboxFileOutput(BaseModel):
|
class SandboxFileOutput(BaseModel):
|
||||||
"""A file extracted from a sandbox and optionally stored in workspace."""
|
"""A file extracted from a sandbox and optionally stored in workspace."""
|
||||||
@@ -163,8 +120,7 @@ async def extract_sandbox_files(
|
|||||||
sandbox: The E2B sandbox instance
|
sandbox: The E2B sandbox instance
|
||||||
working_directory: Directory to search for files
|
working_directory: Directory to search for files
|
||||||
since_timestamp: ISO timestamp - only return files modified after this time
|
since_timestamp: ISO timestamp - only return files modified after this time
|
||||||
text_only: If True, only extract text files. If False, also extract
|
text_only: If True, only extract text files (default). If False, extract all files.
|
||||||
supported binary files (images, PDFs, etc.).
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List of ExtractedFile objects with path, content, and metadata
|
List of ExtractedFile objects with path, content, and metadata
|
||||||
@@ -193,53 +149,14 @@ async def extract_sandbox_files(
|
|||||||
if not file_path:
|
if not file_path:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Check file type (case-insensitive for extensions)
|
# Check if it's a text file
|
||||||
file_path_lower = file_path.lower()
|
is_text = any(file_path.endswith(ext) for ext in TEXT_EXTENSIONS)
|
||||||
is_text = any(
|
|
||||||
file_path_lower.endswith(ext.lower()) for ext in TEXT_EXTENSIONS
|
|
||||||
)
|
|
||||||
is_binary = any(
|
|
||||||
file_path_lower.endswith(ext.lower()) for ext in BINARY_EXTENSIONS
|
|
||||||
)
|
|
||||||
|
|
||||||
# Determine if we should extract this file
|
# Skip non-text files if text_only mode
|
||||||
if text_only:
|
if text_only and not is_text:
|
||||||
# Only extract text files
|
|
||||||
if not is_text:
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
# Extract text files and supported binary files
|
|
||||||
if not is_text and not is_binary:
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# For binary files, check size before reading to prevent OOM
|
|
||||||
if is_binary:
|
|
||||||
stat_result = await sandbox.commands.run(
|
|
||||||
f"stat -c %s {shlex.quote(file_path)} 2>/dev/null"
|
|
||||||
)
|
|
||||||
if stat_result.exit_code != 0 or not stat_result.stdout:
|
|
||||||
logger.debug(
|
|
||||||
f"Skipping {file_path}: could not determine file size"
|
|
||||||
)
|
|
||||||
continue
|
|
||||||
|
|
||||||
try:
|
|
||||||
file_size = int(stat_result.stdout.strip())
|
|
||||||
except ValueError:
|
|
||||||
logger.debug(
|
|
||||||
f"Skipping {file_path}: unexpected stat output "
|
|
||||||
f"{stat_result.stdout.strip()!r}"
|
|
||||||
)
|
|
||||||
continue
|
|
||||||
|
|
||||||
if file_size > MAX_BINARY_FILE_SIZE:
|
|
||||||
logger.info(
|
|
||||||
f"Skipping {file_path}: size {file_size} bytes "
|
|
||||||
f"exceeds limit {MAX_BINARY_FILE_SIZE}"
|
|
||||||
)
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Read file content as bytes
|
# Read file content as bytes
|
||||||
content = await sandbox.files.read(file_path, format="bytes")
|
content = await sandbox.files.read(file_path, format="bytes")
|
||||||
if isinstance(content, str):
|
if isinstance(content, str):
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ services:
|
|||||||
|
|
||||||
rabbitmq:
|
rabbitmq:
|
||||||
<<: *agpt-services
|
<<: *agpt-services
|
||||||
image: rabbitmq:4.1.4
|
image: rabbitmq:management
|
||||||
container_name: rabbitmq
|
container_name: rabbitmq
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: rabbitmq-diagnostics -q ping
|
test: rabbitmq-diagnostics -q ping
|
||||||
@@ -66,6 +66,7 @@ services:
|
|||||||
- RABBITMQ_DEFAULT_PASS=k0VMxyIJF9S35f3x2uaw5IWAl6Y536O7
|
- RABBITMQ_DEFAULT_PASS=k0VMxyIJF9S35f3x2uaw5IWAl6Y536O7
|
||||||
ports:
|
ports:
|
||||||
- "5672:5672"
|
- "5672:5672"
|
||||||
|
- "15672:15672"
|
||||||
clamav:
|
clamav:
|
||||||
image: clamav/clamav-debian:latest
|
image: clamav/clamav-debian:latest
|
||||||
ports:
|
ports:
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ services:
|
|||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 5
|
retries: 5
|
||||||
rabbitmq:
|
rabbitmq:
|
||||||
image: rabbitmq:4.1.4
|
image: rabbitmq:management
|
||||||
container_name: rabbitmq
|
container_name: rabbitmq
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: rabbitmq-diagnostics -q ping
|
test: rabbitmq-diagnostics -q ping
|
||||||
@@ -88,13 +88,14 @@ services:
|
|||||||
<<: *backend-env
|
<<: *backend-env
|
||||||
ports:
|
ports:
|
||||||
- "5672:5672"
|
- "5672:5672"
|
||||||
|
- "15672:15672"
|
||||||
|
|
||||||
rest_server:
|
rest_server:
|
||||||
build:
|
build:
|
||||||
context: ../
|
context: ../
|
||||||
dockerfile: autogpt_platform/backend/Dockerfile
|
dockerfile: autogpt_platform/backend/Dockerfile
|
||||||
target: server
|
target: server
|
||||||
command: ["rest"] # points to entry in [tool.poetry.scripts] in pyproject.toml
|
command: ["python", "-m", "backend.rest"]
|
||||||
develop:
|
develop:
|
||||||
watch:
|
watch:
|
||||||
- path: ./
|
- path: ./
|
||||||
@@ -127,7 +128,7 @@ services:
|
|||||||
context: ../
|
context: ../
|
||||||
dockerfile: autogpt_platform/backend/Dockerfile
|
dockerfile: autogpt_platform/backend/Dockerfile
|
||||||
target: server
|
target: server
|
||||||
command: ["executor"] # points to entry in [tool.poetry.scripts] in pyproject.toml
|
command: ["python", "-m", "backend.exec"]
|
||||||
develop:
|
develop:
|
||||||
watch:
|
watch:
|
||||||
- path: ./
|
- path: ./
|
||||||
@@ -162,7 +163,7 @@ services:
|
|||||||
context: ../
|
context: ../
|
||||||
dockerfile: autogpt_platform/backend/Dockerfile
|
dockerfile: autogpt_platform/backend/Dockerfile
|
||||||
target: server
|
target: server
|
||||||
command: ["ws"] # points to entry in [tool.poetry.scripts] in pyproject.toml
|
command: ["python", "-m", "backend.ws"]
|
||||||
develop:
|
develop:
|
||||||
watch:
|
watch:
|
||||||
- path: ./
|
- path: ./
|
||||||
@@ -195,7 +196,7 @@ services:
|
|||||||
context: ../
|
context: ../
|
||||||
dockerfile: autogpt_platform/backend/Dockerfile
|
dockerfile: autogpt_platform/backend/Dockerfile
|
||||||
target: server
|
target: server
|
||||||
command: ["db"] # points to entry in [tool.poetry.scripts] in pyproject.toml
|
command: ["python", "-m", "backend.db"]
|
||||||
develop:
|
develop:
|
||||||
watch:
|
watch:
|
||||||
- path: ./
|
- path: ./
|
||||||
@@ -224,7 +225,7 @@ services:
|
|||||||
context: ../
|
context: ../
|
||||||
dockerfile: autogpt_platform/backend/Dockerfile
|
dockerfile: autogpt_platform/backend/Dockerfile
|
||||||
target: server
|
target: server
|
||||||
command: ["scheduler"] # points to entry in [tool.poetry.scripts] in pyproject.toml
|
command: ["python", "-m", "backend.scheduler"]
|
||||||
develop:
|
develop:
|
||||||
watch:
|
watch:
|
||||||
- path: ./
|
- path: ./
|
||||||
@@ -272,7 +273,7 @@ services:
|
|||||||
context: ../
|
context: ../
|
||||||
dockerfile: autogpt_platform/backend/Dockerfile
|
dockerfile: autogpt_platform/backend/Dockerfile
|
||||||
target: server
|
target: server
|
||||||
command: ["notification"] # points to entry in [tool.poetry.scripts] in pyproject.toml
|
command: ["python", "-m", "backend.notification"]
|
||||||
develop:
|
develop:
|
||||||
watch:
|
watch:
|
||||||
- path: ./
|
- path: ./
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { SidebarProvider } from "@/components/ui/sidebar";
|
import { SidebarProvider } from "@/components/ui/sidebar";
|
||||||
// TODO: Replace with modern Dialog component when available
|
|
||||||
import DeleteConfirmDialog from "@/components/__legacy__/delete-confirm-dialog";
|
|
||||||
import { ChatContainer } from "./components/ChatContainer/ChatContainer";
|
import { ChatContainer } from "./components/ChatContainer/ChatContainer";
|
||||||
import { ChatSidebar } from "./components/ChatSidebar/ChatSidebar";
|
import { ChatSidebar } from "./components/ChatSidebar/ChatSidebar";
|
||||||
import { MobileDrawer } from "./components/MobileDrawer/MobileDrawer";
|
import { MobileDrawer } from "./components/MobileDrawer/MobileDrawer";
|
||||||
@@ -33,12 +31,6 @@ export function CopilotPage() {
|
|||||||
handleDrawerOpenChange,
|
handleDrawerOpenChange,
|
||||||
handleSelectSession,
|
handleSelectSession,
|
||||||
handleNewChat,
|
handleNewChat,
|
||||||
// Delete functionality
|
|
||||||
sessionToDelete,
|
|
||||||
isDeleting,
|
|
||||||
handleDeleteClick,
|
|
||||||
handleConfirmDelete,
|
|
||||||
handleCancelDelete,
|
|
||||||
} = useCopilotPage();
|
} = useCopilotPage();
|
||||||
|
|
||||||
if (isUserLoading || !isLoggedIn) {
|
if (isUserLoading || !isLoggedIn) {
|
||||||
@@ -56,19 +48,7 @@ export function CopilotPage() {
|
|||||||
>
|
>
|
||||||
{!isMobile && <ChatSidebar />}
|
{!isMobile && <ChatSidebar />}
|
||||||
<div className="relative flex h-full w-full flex-col overflow-hidden bg-[#f8f8f9] px-0">
|
<div className="relative flex h-full w-full flex-col overflow-hidden bg-[#f8f8f9] px-0">
|
||||||
{isMobile && (
|
{isMobile && <MobileHeader onOpenDrawer={handleOpenDrawer} />}
|
||||||
<MobileHeader
|
|
||||||
onOpenDrawer={handleOpenDrawer}
|
|
||||||
showDelete={!!sessionId}
|
|
||||||
isDeleting={isDeleting}
|
|
||||||
onDelete={() => {
|
|
||||||
const session = sessions.find((s) => s.id === sessionId);
|
|
||||||
if (session) {
|
|
||||||
handleDeleteClick(session.id, session.title);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<div className="flex-1 overflow-hidden">
|
<div className="flex-1 overflow-hidden">
|
||||||
<ChatContainer
|
<ChatContainer
|
||||||
messages={messages}
|
messages={messages}
|
||||||
@@ -95,16 +75,6 @@ export function CopilotPage() {
|
|||||||
onOpenChange={handleDrawerOpenChange}
|
onOpenChange={handleDrawerOpenChange}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{/* Delete confirmation dialog - rendered at top level for proper z-index on mobile */}
|
|
||||||
{isMobile && (
|
|
||||||
<DeleteConfirmDialog
|
|
||||||
entityType="chat"
|
|
||||||
entityName={sessionToDelete?.title || "Untitled chat"}
|
|
||||||
open={!!sessionToDelete}
|
|
||||||
onOpenChange={(open) => !open && handleCancelDelete()}
|
|
||||||
onDoDelete={handleConfirmDelete}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</SidebarProvider>
|
</SidebarProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,8 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import {
|
import { useGetV2ListSessions } from "@/app/api/__generated__/endpoints/chat/chat";
|
||||||
getGetV2ListSessionsQueryKey,
|
|
||||||
useDeleteV2DeleteSession,
|
|
||||||
useGetV2ListSessions,
|
|
||||||
} from "@/app/api/__generated__/endpoints/chat/chat";
|
|
||||||
import { Button } from "@/components/atoms/Button/Button";
|
import { Button } from "@/components/atoms/Button/Button";
|
||||||
import { LoadingSpinner } from "@/components/atoms/LoadingSpinner/LoadingSpinner";
|
import { LoadingSpinner } from "@/components/atoms/LoadingSpinner/LoadingSpinner";
|
||||||
import { Text } from "@/components/atoms/Text/Text";
|
import { Text } from "@/components/atoms/Text/Text";
|
||||||
import { toast } from "@/components/molecules/Toast/use-toast";
|
|
||||||
// TODO: Replace with modern Dialog component when available
|
|
||||||
import DeleteConfirmDialog from "@/components/__legacy__/delete-confirm-dialog";
|
|
||||||
import {
|
import {
|
||||||
Sidebar,
|
Sidebar,
|
||||||
SidebarContent,
|
SidebarContent,
|
||||||
@@ -19,52 +12,18 @@ import {
|
|||||||
useSidebar,
|
useSidebar,
|
||||||
} from "@/components/ui/sidebar";
|
} from "@/components/ui/sidebar";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { PlusCircleIcon, PlusIcon, TrashIcon } from "@phosphor-icons/react";
|
import { PlusCircleIcon, PlusIcon } from "@phosphor-icons/react";
|
||||||
import { useQueryClient } from "@tanstack/react-query";
|
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import { useState } from "react";
|
|
||||||
import { parseAsString, useQueryState } from "nuqs";
|
import { parseAsString, useQueryState } from "nuqs";
|
||||||
|
|
||||||
export function ChatSidebar() {
|
export function ChatSidebar() {
|
||||||
const { state } = useSidebar();
|
const { state } = useSidebar();
|
||||||
const isCollapsed = state === "collapsed";
|
const isCollapsed = state === "collapsed";
|
||||||
const [sessionId, setSessionId] = useQueryState("sessionId", parseAsString);
|
const [sessionId, setSessionId] = useQueryState("sessionId", parseAsString);
|
||||||
const [sessionToDelete, setSessionToDelete] = useState<{
|
|
||||||
id: string;
|
|
||||||
title: string | null | undefined;
|
|
||||||
} | null>(null);
|
|
||||||
|
|
||||||
const queryClient = useQueryClient();
|
|
||||||
|
|
||||||
const { data: sessionsResponse, isLoading: isLoadingSessions } =
|
const { data: sessionsResponse, isLoading: isLoadingSessions } =
|
||||||
useGetV2ListSessions({ limit: 50 });
|
useGetV2ListSessions({ limit: 50 });
|
||||||
|
|
||||||
const { mutate: deleteSession, isPending: isDeleting } =
|
|
||||||
useDeleteV2DeleteSession({
|
|
||||||
mutation: {
|
|
||||||
onSuccess: () => {
|
|
||||||
// Invalidate sessions list to refetch
|
|
||||||
queryClient.invalidateQueries({
|
|
||||||
queryKey: getGetV2ListSessionsQueryKey(),
|
|
||||||
});
|
|
||||||
// If we deleted the current session, clear selection
|
|
||||||
if (sessionToDelete?.id === sessionId) {
|
|
||||||
setSessionId(null);
|
|
||||||
}
|
|
||||||
setSessionToDelete(null);
|
|
||||||
},
|
|
||||||
onError: (error) => {
|
|
||||||
toast({
|
|
||||||
title: "Failed to delete chat",
|
|
||||||
description:
|
|
||||||
error instanceof Error ? error.message : "An error occurred",
|
|
||||||
variant: "destructive",
|
|
||||||
});
|
|
||||||
setSessionToDelete(null);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const sessions =
|
const sessions =
|
||||||
sessionsResponse?.status === 200 ? sessionsResponse.data.sessions : [];
|
sessionsResponse?.status === 200 ? sessionsResponse.data.sessions : [];
|
||||||
|
|
||||||
@@ -76,22 +35,6 @@ export function ChatSidebar() {
|
|||||||
setSessionId(id);
|
setSessionId(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleDeleteClick(
|
|
||||||
e: React.MouseEvent,
|
|
||||||
id: string,
|
|
||||||
title: string | null | undefined,
|
|
||||||
) {
|
|
||||||
e.stopPropagation(); // Prevent session selection
|
|
||||||
if (isDeleting) return; // Prevent double-click during deletion
|
|
||||||
setSessionToDelete({ id, title });
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleConfirmDelete() {
|
|
||||||
if (sessionToDelete) {
|
|
||||||
deleteSession({ sessionId: sessionToDelete.id });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatDate(dateString: string) {
|
function formatDate(dateString: string) {
|
||||||
const date = new Date(dateString);
|
const date = new Date(dateString);
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
@@ -118,7 +61,6 @@ export function ChatSidebar() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
|
||||||
<Sidebar
|
<Sidebar
|
||||||
variant="inset"
|
variant="inset"
|
||||||
collapsible="icon"
|
collapsible="icon"
|
||||||
@@ -188,18 +130,15 @@ export function ChatSidebar() {
|
|||||||
</p>
|
</p>
|
||||||
) : (
|
) : (
|
||||||
sessions.map((session) => (
|
sessions.map((session) => (
|
||||||
<div
|
<button
|
||||||
key={session.id}
|
key={session.id}
|
||||||
|
onClick={() => handleSelectSession(session.id)}
|
||||||
className={cn(
|
className={cn(
|
||||||
"group relative w-full rounded-lg transition-colors",
|
"w-full rounded-lg px-3 py-2.5 text-left transition-colors",
|
||||||
session.id === sessionId
|
session.id === sessionId
|
||||||
? "bg-zinc-100"
|
? "bg-zinc-100"
|
||||||
: "hover:bg-zinc-50",
|
: "hover:bg-zinc-50",
|
||||||
)}
|
)}
|
||||||
>
|
|
||||||
<button
|
|
||||||
onClick={() => handleSelectSession(session.id)}
|
|
||||||
className="w-full px-3 py-2.5 pr-10 text-left"
|
|
||||||
>
|
>
|
||||||
<div className="flex min-w-0 max-w-full flex-col overflow-hidden">
|
<div className="flex min-w-0 max-w-full flex-col overflow-hidden">
|
||||||
<div className="min-w-0 max-w-full">
|
<div className="min-w-0 max-w-full">
|
||||||
@@ -220,17 +159,6 @@ export function ChatSidebar() {
|
|||||||
</Text>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
onClick={(e) =>
|
|
||||||
handleDeleteClick(e, session.id, session.title)
|
|
||||||
}
|
|
||||||
disabled={isDeleting}
|
|
||||||
className="absolute right-2 top-1/2 -translate-y-1/2 rounded p-1.5 text-zinc-400 opacity-0 transition-all group-hover:opacity-100 hover:bg-red-100 hover:text-red-600 focus-visible:opacity-100 disabled:cursor-not-allowed disabled:opacity-50"
|
|
||||||
aria-label="Delete chat"
|
|
||||||
>
|
|
||||||
<TrashIcon className="h-4 w-4" />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
</motion.div>
|
</motion.div>
|
||||||
@@ -256,14 +184,5 @@ export function ChatSidebar() {
|
|||||||
</SidebarFooter>
|
</SidebarFooter>
|
||||||
)}
|
)}
|
||||||
</Sidebar>
|
</Sidebar>
|
||||||
|
|
||||||
<DeleteConfirmDialog
|
|
||||||
entityType="chat"
|
|
||||||
entityName={sessionToDelete?.title || "Untitled chat"}
|
|
||||||
open={!!sessionToDelete}
|
|
||||||
onOpenChange={(open) => !open && setSessionToDelete(null)}
|
|
||||||
onDoDelete={handleConfirmDelete}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,46 +1,22 @@
|
|||||||
import { Button } from "@/components/atoms/Button/Button";
|
import { Button } from "@/components/atoms/Button/Button";
|
||||||
import { NAVBAR_HEIGHT_PX } from "@/lib/constants";
|
import { NAVBAR_HEIGHT_PX } from "@/lib/constants";
|
||||||
import { ListIcon, TrashIcon } from "@phosphor-icons/react";
|
import { ListIcon } from "@phosphor-icons/react";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
onOpenDrawer: () => void;
|
onOpenDrawer: () => void;
|
||||||
showDelete?: boolean;
|
|
||||||
isDeleting?: boolean;
|
|
||||||
onDelete?: () => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MobileHeader({
|
export function MobileHeader({ onOpenDrawer }: Props) {
|
||||||
onOpenDrawer,
|
|
||||||
showDelete,
|
|
||||||
isDeleting,
|
|
||||||
onDelete,
|
|
||||||
}: Props) {
|
|
||||||
return (
|
return (
|
||||||
<div
|
|
||||||
className="fixed z-50 flex gap-2"
|
|
||||||
style={{ left: "1rem", top: `${NAVBAR_HEIGHT_PX + 20}px` }}
|
|
||||||
>
|
|
||||||
<Button
|
<Button
|
||||||
variant="icon"
|
variant="icon"
|
||||||
size="icon"
|
size="icon"
|
||||||
aria-label="Open sessions"
|
aria-label="Open sessions"
|
||||||
onClick={onOpenDrawer}
|
onClick={onOpenDrawer}
|
||||||
className="bg-white shadow-md"
|
className="fixed z-50 bg-white shadow-md"
|
||||||
|
style={{ left: "1rem", top: `${NAVBAR_HEIGHT_PX + 20}px` }}
|
||||||
>
|
>
|
||||||
<ListIcon width="1.25rem" height="1.25rem" />
|
<ListIcon width="1.25rem" height="1.25rem" />
|
||||||
</Button>
|
</Button>
|
||||||
{showDelete && onDelete && (
|
|
||||||
<Button
|
|
||||||
variant="icon"
|
|
||||||
size="icon"
|
|
||||||
aria-label="Delete current chat"
|
|
||||||
onClick={onDelete}
|
|
||||||
disabled={isDeleting}
|
|
||||||
className="bg-white text-red-500 shadow-md hover:bg-red-50 hover:text-red-600 disabled:opacity-50"
|
|
||||||
>
|
|
||||||
<TrashIcon width="1.25rem" height="1.25rem" />
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,10 @@
|
|||||||
import {
|
import { useGetV2ListSessions } from "@/app/api/__generated__/endpoints/chat/chat";
|
||||||
getGetV2ListSessionsQueryKey,
|
|
||||||
useDeleteV2DeleteSession,
|
|
||||||
useGetV2ListSessions,
|
|
||||||
} from "@/app/api/__generated__/endpoints/chat/chat";
|
|
||||||
import { toast } from "@/components/molecules/Toast/use-toast";
|
import { toast } from "@/components/molecules/Toast/use-toast";
|
||||||
import { useBreakpoint } from "@/lib/hooks/useBreakpoint";
|
import { useBreakpoint } from "@/lib/hooks/useBreakpoint";
|
||||||
import { useSupabase } from "@/lib/supabase/hooks/useSupabase";
|
import { useSupabase } from "@/lib/supabase/hooks/useSupabase";
|
||||||
import { useChat } from "@ai-sdk/react";
|
import { useChat } from "@ai-sdk/react";
|
||||||
import { useQueryClient } from "@tanstack/react-query";
|
|
||||||
import { DefaultChatTransport } from "ai";
|
import { DefaultChatTransport } from "ai";
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
import { useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { useChatSession } from "./useChatSession";
|
import { useChatSession } from "./useChatSession";
|
||||||
import { useLongRunningToolPolling } from "./hooks/useLongRunningToolPolling";
|
import { useLongRunningToolPolling } from "./hooks/useLongRunningToolPolling";
|
||||||
|
|
||||||
@@ -19,11 +14,6 @@ export function useCopilotPage() {
|
|||||||
const { isUserLoading, isLoggedIn } = useSupabase();
|
const { isUserLoading, isLoggedIn } = useSupabase();
|
||||||
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
|
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
|
||||||
const [pendingMessage, setPendingMessage] = useState<string | null>(null);
|
const [pendingMessage, setPendingMessage] = useState<string | null>(null);
|
||||||
const [sessionToDelete, setSessionToDelete] = useState<{
|
|
||||||
id: string;
|
|
||||||
title: string | null | undefined;
|
|
||||||
} | null>(null);
|
|
||||||
const queryClient = useQueryClient();
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
sessionId,
|
sessionId,
|
||||||
@@ -34,30 +24,6 @@ export function useCopilotPage() {
|
|||||||
isCreatingSession,
|
isCreatingSession,
|
||||||
} = useChatSession();
|
} = useChatSession();
|
||||||
|
|
||||||
const { mutate: deleteSessionMutation, isPending: isDeleting } =
|
|
||||||
useDeleteV2DeleteSession({
|
|
||||||
mutation: {
|
|
||||||
onSuccess: () => {
|
|
||||||
queryClient.invalidateQueries({
|
|
||||||
queryKey: getGetV2ListSessionsQueryKey(),
|
|
||||||
});
|
|
||||||
if (sessionToDelete?.id === sessionId) {
|
|
||||||
setSessionId(null);
|
|
||||||
}
|
|
||||||
setSessionToDelete(null);
|
|
||||||
},
|
|
||||||
onError: (error) => {
|
|
||||||
toast({
|
|
||||||
title: "Failed to delete chat",
|
|
||||||
description:
|
|
||||||
error instanceof Error ? error.message : "An error occurred",
|
|
||||||
variant: "destructive",
|
|
||||||
});
|
|
||||||
setSessionToDelete(null);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const breakpoint = useBreakpoint();
|
const breakpoint = useBreakpoint();
|
||||||
const isMobile =
|
const isMobile =
|
||||||
breakpoint === "base" || breakpoint === "sm" || breakpoint === "md";
|
breakpoint === "base" || breakpoint === "sm" || breakpoint === "md";
|
||||||
@@ -177,24 +143,6 @@ export function useCopilotPage() {
|
|||||||
if (isMobile) setIsDrawerOpen(false);
|
if (isMobile) setIsDrawerOpen(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleDeleteClick = useCallback(
|
|
||||||
(id: string, title: string | null | undefined) => {
|
|
||||||
if (isDeleting) return;
|
|
||||||
setSessionToDelete({ id, title });
|
|
||||||
},
|
|
||||||
[isDeleting],
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleConfirmDelete = useCallback(() => {
|
|
||||||
if (sessionToDelete) {
|
|
||||||
deleteSessionMutation({ sessionId: sessionToDelete.id });
|
|
||||||
}
|
|
||||||
}, [sessionToDelete, deleteSessionMutation]);
|
|
||||||
|
|
||||||
const handleCancelDelete = useCallback(() => {
|
|
||||||
setSessionToDelete(null);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
sessionId,
|
sessionId,
|
||||||
messages,
|
messages,
|
||||||
@@ -217,11 +165,5 @@ export function useCopilotPage() {
|
|||||||
handleDrawerOpenChange,
|
handleDrawerOpenChange,
|
||||||
handleSelectSession,
|
handleSelectSession,
|
||||||
handleNewChat,
|
handleNewChat,
|
||||||
// Delete functionality
|
|
||||||
sessionToDelete,
|
|
||||||
isDeleting,
|
|
||||||
handleDeleteClick,
|
|
||||||
handleConfirmDelete,
|
|
||||||
handleCancelDelete,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1151,36 +1151,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/api/chat/sessions/{session_id}": {
|
"/api/chat/sessions/{session_id}": {
|
||||||
"delete": {
|
|
||||||
"tags": ["v2", "chat", "chat"],
|
|
||||||
"summary": "Delete Session",
|
|
||||||
"description": "Delete a chat session.\n\nPermanently removes a chat session and all its messages.\nOnly the owner can delete their sessions.\n\nArgs:\n session_id: The session ID to delete.\n user_id: The authenticated user's ID.\n\nReturns:\n 204 No Content on success.\n\nRaises:\n HTTPException: 404 if session not found or not owned by user.",
|
|
||||||
"operationId": "deleteV2DeleteSession",
|
|
||||||
"security": [{ "HTTPBearerJWT": [] }],
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "session_id",
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"schema": { "type": "string", "title": "Session Id" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"204": { "description": "Successful Response" },
|
|
||||||
"401": {
|
|
||||||
"$ref": "#/components/responses/HTTP401NotAuthenticatedError"
|
|
||||||
},
|
|
||||||
"404": { "description": "Session not found or access denied" },
|
|
||||||
"422": {
|
|
||||||
"description": "Validation Error",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": { "$ref": "#/components/schemas/HTTPValidationError" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"get": {
|
"get": {
|
||||||
"tags": ["v2", "chat", "chat"],
|
"tags": ["v2", "chat", "chat"],
|
||||||
"summary": "Get Session",
|
"summary": "Get Session",
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ const DialogFooter = ({
|
|||||||
}: React.HTMLAttributes<HTMLDivElement>) => (
|
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
|
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ When activated, the block:
|
|||||||
- Install dependencies (npm, pip, etc.)
|
- Install dependencies (npm, pip, etc.)
|
||||||
- Run terminal commands
|
- Run terminal commands
|
||||||
- Build and test applications
|
- Build and test applications
|
||||||
5. Extracts all files created/modified during execution (text files and binary files like images, PDFs, etc.)
|
5. Extracts all text files created/modified during execution
|
||||||
6. Returns the response and files, optionally keeping the sandbox alive for follow-up tasks
|
6. Returns the response and files, optionally keeping the sandbox alive for follow-up tasks
|
||||||
|
|
||||||
The block supports conversation continuation through three mechanisms:
|
The block supports conversation continuation through three mechanisms:
|
||||||
@@ -42,7 +42,7 @@ The block supports conversation continuation through three mechanisms:
|
|||||||
| Output | Description |
|
| Output | Description |
|
||||||
|--------|-------------|
|
|--------|-------------|
|
||||||
| Response | The output/response from Claude Code execution |
|
| Response | The output/response from Claude Code execution |
|
||||||
| Files | List of files (text and binary) created/modified during execution. Includes images, PDFs, and other supported formats. Each file has path, relative_path, name, content, and workspace_ref fields. Binary files are stored in workspace and accessible via workspace_ref |
|
| Files | List of text files created/modified during execution. Each file includes path, relative_path, name, and content fields |
|
||||||
| Conversation History | Full conversation history including this turn. Use to restore context on a fresh sandbox |
|
| Conversation History | Full conversation history including this turn. Use to restore context on a fresh sandbox |
|
||||||
| Session ID | Session ID for this conversation. Pass back with sandbox_id to continue the conversation |
|
| Session ID | Session ID for this conversation. Pass back with sandbox_id to continue the conversation |
|
||||||
| Sandbox ID | ID of the sandbox instance (null if disposed). Pass back with session_id to continue the conversation |
|
| Sandbox ID | ID of the sandbox instance (null if disposed). Pass back with session_id to continue the conversation |
|
||||||
|
|||||||
@@ -535,7 +535,7 @@ When activated, the block:
|
|||||||
2. Installs the latest version of Claude Code in the sandbox
|
2. Installs the latest version of Claude Code in the sandbox
|
||||||
3. Optionally runs setup commands to prepare the environment
|
3. Optionally runs setup commands to prepare the environment
|
||||||
4. Executes your prompt using Claude Code, which can create/edit files, install dependencies, run terminal commands, and build applications
|
4. Executes your prompt using Claude Code, which can create/edit files, install dependencies, run terminal commands, and build applications
|
||||||
5. Extracts all files created/modified during execution (text files and binary files like images, PDFs, etc.)
|
5. Extracts all text files created/modified during execution
|
||||||
6. Returns the response and files, optionally keeping the sandbox alive for follow-up tasks
|
6. Returns the response and files, optionally keeping the sandbox alive for follow-up tasks
|
||||||
|
|
||||||
The block supports conversation continuation through three mechanisms:
|
The block supports conversation continuation through three mechanisms:
|
||||||
@@ -563,7 +563,7 @@ The block supports conversation continuation through three mechanisms:
|
|||||||
|--------|-------------|------|
|
|--------|-------------|------|
|
||||||
| error | Error message if execution failed | str |
|
| error | Error message if execution failed | str |
|
||||||
| response | The output/response from Claude Code execution | str |
|
| response | The output/response from Claude Code execution | str |
|
||||||
| files | List of files created/modified by Claude Code during this execution. Includes text files and binary files (images, PDFs, etc.). Each file has 'path', 'relative_path', 'name', 'content', and 'workspace_ref' fields. workspace_ref contains a workspace:// URI for workspace storage. For binary files, content contains a placeholder; use workspace_ref to access the file. | List[SandboxFileOutput] |
|
| files | List of text files created/modified by Claude Code during this execution. Each file has 'path', 'relative_path', 'name', 'content', and 'workspace_ref' fields. workspace_ref contains a workspace:// URI if the file was stored to workspace. | List[SandboxFileOutput] |
|
||||||
| conversation_history | Full conversation history including this turn. Pass this to conversation_history input to continue on a fresh sandbox if the previous sandbox timed out. | str |
|
| conversation_history | Full conversation history including this turn. Pass this to conversation_history input to continue on a fresh sandbox if the previous sandbox timed out. | str |
|
||||||
| session_id | Session ID for this conversation. Pass this back along with sandbox_id to continue the conversation. | str |
|
| session_id | Session ID for this conversation. Pass this back along with sandbox_id to continue the conversation. | str |
|
||||||
| sandbox_id | ID of the sandbox instance. Pass this back along with session_id to continue the conversation. This is None if dispose_sandbox was True (sandbox was disposed). | str |
|
| sandbox_id | ID of the sandbox instance. Pass this back along with session_id to continue the conversation. This is None if dispose_sandbox was True (sandbox was disposed). | str |
|
||||||
|
|||||||
@@ -218,6 +218,17 @@ 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