沙箱内容可保存
This commit is contained in:
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}
|
||||
+1
-1
@@ -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()},
|
||||
)
|
||||
|
||||
|
||||
Reference in new issue
Block a user