""" 对象存储:只存字节;元数据登记走主账 attachment。 禁止:在本包维护工单状态。 骨架:S3 兼容客户端工厂与 put/get 占位(未配 endpoint 时不连网)。 """ from __future__ import annotations import logging from dataclasses import dataclass from typing import Optional from agent.config import Settings, get_settings logger = logging.getLogger(__name__) @dataclass class ObjectStorageClient: """ 对象存储骨架。 正式用 boto3/minio SDK;本版仅记录配置是否齐全,put_bytes 在未配置时返回 False。 """ endpoint_url: str bucket: str access_key: str = "" secret_key: str = "" path_style: bool = True @classmethod def from_settings(cls, settings: Optional[Settings] = None) -> "ObjectStorageClient": cfg = settings or get_settings() return cls( endpoint_url=getattr(cfg, "object_storage_endpoint_url", "") or "", bucket=getattr(cfg, "object_storage_bucket", "") or "", access_key=getattr(cfg, "object_storage_access_key", "") or "", secret_key=getattr(cfg, "object_storage_secret_key", "") or "", path_style=bool(getattr(cfg, "object_storage_path_style", True)), ) def configured(self) -> bool: """endpoint + bucket 是否已配(不含密钥是否正确)。""" return bool(self.endpoint_url and self.bucket) def put_bytes_stub(self, *, key: str, data: bytes, content_type: str = "") -> bool: """ 上传占位:未配置则 False;已配置也仅打日志不真正上传(骨架防误写桶)。 正式实现再打开真实 PUT。 """ if not self.configured(): logger.warning("object_storage 未配置,跳过 put key=%s", key) return False logger.info( "object_storage.put_bytes_stub bucket=%s key=%s bytes=%s(骨架不上传)", self.bucket, key, len(data), ) return True # SDK 壳:见 s3_client(默认 dry_run) from agent.storage.s3_client import S3ObjectStorage # noqa: E402 __all__ = ["ObjectStorageClient", "S3ObjectStorage"]