沙箱内容可保存

This commit is contained in:
董宏凯 committed 2026-05-14 22:12:20 +08:00
1 parent 4e0787ec77
commit 044370f13c
4 files changed
+142 -18

No files matched your search

@@ -6,6 +6,7 @@ from urllib.parse import quote
from fastapi import APIRouter, HTTPException, Request
from fastapi.responses import FileResponse, PlainTextResponse, Response
from pydantic import BaseModel
from app.gateway.authz import require_permission
from app.gateway.path_utils import resolve_thread_virtual_path
@@ -181,3 +182,46 @@ async def get_artifact(thread_id: str, path: str, request: Request, download: bo
return PlainTextResponse(content=actual_path.read_text(encoding="utf-8"), media_type=mime_type)
return Response(content=actual_path.read_bytes(), media_type=mime_type, headers={"Content-Disposition": _build_content_disposition("inline", actual_path.name)})
class ArtifactUpdateRequest(BaseModel):
content: str
@router.put(
"/threads/{thread_id}/artifacts/{path:path}",
summary="Update Artifact File",
description="Update the content of an artifact file.",
)
@require_permission("threads", "write", owner_check=True)
async def update_artifact(thread_id: str, path: str, request: Request, body: ArtifactUpdateRequest) -> dict:
"""Update an artifact file's content.
Args:
thread_id: The thread ID.
path: The artifact path (e.g. mnt/user-data/outputs/index.html).
body: Request body containing the new file content.
Returns:
{"ok": true} on success.
Raises:
HTTPException:
- 400 if path is invalid, not a file, or is a .skill archive
- 403 if access denied
- 404 if file not found
"""
if ".skill/" in path or path.endswith(".skill"):
raise HTTPException(status_code=400, detail="Cannot edit .skill archives")
actual_path = resolve_thread_virtual_path(thread_id, path)
if not actual_path.exists():
raise HTTPException(status_code=404, detail=f"Artifact not found: {path}")
if not actual_path.is_file():
raise HTTPException(status_code=400, detail=f"Path is not a file: {path}")
actual_path.write_text(body.content, encoding="utf-8")
logger.info(f"Updated artifact: thread_id={thread_id}, path={path}")
return {"ok": True}
@@ -106,7 +106,7 @@ class ThreadDataMiddleware(AgentMiddleware[ThreadDataMiddlewareState]):
messages[-1] = HumanMessage(
content=last_message.content,
id=last_message.id,
name=last_message.name or "user-input",
name=last_message.name,
additional_kwargs={**last_message.additional_kwargs, "run_id": runtime.context.get("run_id"), "timestamp": datetime.now(UTC).isoformat()},
)