diff --git a/dashscope/applications/agentstudio/resources/sessions.py b/dashscope/applications/agentstudio/resources/sessions.py index b03b3a64..d591a9bd 100644 --- a/dashscope/applications/agentstudio/resources/sessions.py +++ b/dashscope/applications/agentstudio/resources/sessions.py @@ -26,7 +26,11 @@ SessionThreads, AsyncSessionThreads, ) -from dashscope.applications.agentstudio.types import DeleteResponse, Session +from dashscope.applications.agentstudio.types import ( + DeleteResponse, + ResourceInput, + Session, +) from dashscope.applications.agentstudio.types.params import ( SessionCreateParams, SessionListParams, @@ -52,12 +56,31 @@ def create( agent: Any, environment_id: Optional[str] = None, title: Optional[str] = None, - resources: Optional[Sequence[Mapping[str, Any]]] = None, + resources: Optional[Sequence[ResourceInput]] = None, vault_ids: Optional[Sequence[str]] = None, environment_variables: Optional[Mapping[str, str]] = None, mcp_configs: Optional[Sequence[Mapping[str, Any]]] = None, metadata: Optional[Mapping[str, Any]] = None, ) -> Session: + """Create a session (``POST /sessions``). + + ``agent`` is the Agent id string or an + ``{"type": "agent_with_overrides", ...}`` mapping. ``resources`` + entries are wire-format mappings (or + :class:`~dashscope.agentstudio.types.Mount` objects, which + serialize to the same mappings):: + + client.sessions.create( + agent=agent_id, + resources=[ + {"type": "memory_store", "memory_store_id": store_id, + "access": "read_write"}, + {"type": "oss", "region": "cn-beijing", "bucket": "bkt", + "oss_path": "datasets/", "mount_path": "/data", + "access": "read_only"}, + ], + ) + """ body = SessionCreateParams( agent=agent, environment_id=environment_id, @@ -191,12 +214,31 @@ async def create( agent: Any, environment_id: Optional[str] = None, title: Optional[str] = None, - resources: Optional[Sequence[Mapping[str, Any]]] = None, + resources: Optional[Sequence[ResourceInput]] = None, vault_ids: Optional[Sequence[str]] = None, environment_variables: Optional[Mapping[str, str]] = None, mcp_configs: Optional[Sequence[Mapping[str, Any]]] = None, metadata: Optional[Mapping[str, Any]] = None, ) -> Session: + """Create a session (``POST /sessions``). + + ``agent`` is the Agent id string or an + ``{"type": "agent_with_overrides", ...}`` mapping. ``resources`` + entries are wire-format mappings (or + :class:`~dashscope.agentstudio.types.Mount` objects, which + serialize to the same mappings):: + + client.sessions.create( + agent=agent_id, + resources=[ + {"type": "memory_store", "memory_store_id": store_id, + "access": "read_write"}, + {"type": "oss", "region": "cn-beijing", "bucket": "bkt", + "oss_path": "datasets/", "mount_path": "/data", + "access": "read_only"}, + ], + ) + """ body = SessionCreateParams( agent=agent, environment_id=environment_id, diff --git a/dashscope/applications/agentstudio/types/__init__.py b/dashscope/applications/agentstudio/types/__init__.py index 0f922387..bb76c00b 100644 --- a/dashscope/applications/agentstudio/types/__init__.py +++ b/dashscope/applications/agentstudio/types/__init__.py @@ -11,6 +11,7 @@ Scope, Mount, Networking, + ResourceInput, Packages, EnvironmentConfig, StopReason, diff --git a/dashscope/applications/agentstudio/types/models.py b/dashscope/applications/agentstudio/types/models.py index 18fccf46..6c03a534 100644 --- a/dashscope/applications/agentstudio/types/models.py +++ b/dashscope/applications/agentstudio/types/models.py @@ -131,24 +131,49 @@ class Scope(BaseModel): class Mount(BaseModel): """Session resource mount descriptor (create-time input on POST /sessions).""" - _fields = ("type", "file_id", "skill_id", "mount_path") + _fields = ( + "type", + "file_id", + "skill_id", + "mount_path", + "memory_store_id", + "provider", + "entity_id", + "project_ids", + "profile_schema", + "description", + "access", + "instructions", + "region", + "bucket", + "oss_path", + ) + + +# One resources[] entry on POST /sessions: a raw wire-format mapping +# (dict) or a typed Mount object. +ResourceInput = Union[Mapping[str, Any], Mount] class SessionResource(BaseModel): - """A resource mounted into a session at runtime. - - The response ``file_id`` is the session-scoped copy id — **not** the - source file id passed at mount time. ``mount_path`` is the absolute - sandbox path (the server prepends a prefix; the user-supplied path is - preserved losslessly and must be under ``/uploads/``). - - For ``type="memory_store"`` resources the memory-specific fields - apply: ``memory_store_id`` (the attached store), ``access`` - (``read_write`` default / ``read_only``), ``instructions`` - (per-session guidance, <= 4096 chars) and the server-snapshotted - ``name``/``description`` of the store at attach time. Memory - stores can only be attached at session creation time — - ``sessions.resources.add`` accepts files only. + """A resource mounted into a session (file / memory_store / oss). + + ``file``: ``file_id`` is the session-scoped copy id (not the source + file id); ``mount_path`` resolves under ``/uploads/``. Memory and + OSS mounts are create-only — ``sessions.resources.add`` accepts + files only. + + ``memory_store``: ``access`` (``read_write`` default) and + ``instructions``; ``name``/``description`` are server-snapshotted + for built-in (``provider="default"``) mounts, which also carry the + server-generated ``mount_path`` (``/mnt/memory/``); + ``agentstudio_memory`` (Bailian) mounts echo ``entity_id`` and the + configured ``project_ids``/``profile_schema``/``description``, with + no ``mount_path``. + + ``oss``: echoes ``region``/``bucket``/``oss_path`` and the + user-supplied logical ``mount_path`` (the sandbox resolves it under + ``/mnt/oss/``). """ _fields = ( @@ -156,11 +181,18 @@ class SessionResource(BaseModel): "type", "file_id", "memory_store_id", + "provider", + "entity_id", + "project_ids", + "profile_schema", "access", "instructions", "name", "description", "mount_path", + "region", + "bucket", + "oss_path", "created_at", "updated_at", "request_id", diff --git a/dashscope/applications/agentstudio/types/params.py b/dashscope/applications/agentstudio/types/params.py index 7b76d08e..a87e764c 100644 --- a/dashscope/applications/agentstudio/types/params.py +++ b/dashscope/applications/agentstudio/types/params.py @@ -21,6 +21,7 @@ from dashscope.applications.agentstudio.types.models import ( BaseModel, ModelConfig, + ResourceInput, ) _NOT_GIVEN = object() @@ -288,7 +289,10 @@ class SessionCreateParams(BaseModel): ``environment_variables`` and ``mcp_configs`` are Session-level settings independent of the agent. ``resources`` is create-only — it - cannot be modified via ``updateSession``. + cannot be modified via ``updateSession``; each item is a mapping or + a :class:`~dashscope.applications.agentstudio.types.models.Mount` + (``file`` / ``memory_store`` — built-in or Bailian + ``provider="agentstudio_memory"`` — / ``oss``). """ _fields = ( @@ -308,7 +312,7 @@ def __init__( # pylint: disable=useless-parent-delegation agent: Any, environment_id: Optional[str] = None, title: Optional[str] = None, - resources: Optional[Sequence[Mapping[str, Any]]] = None, + resources: Optional[Sequence[ResourceInput]] = None, vault_ids: Optional[Sequence[str]] = None, environment_variables: Optional[Mapping[str, str]] = None, mcp_configs: Optional[Sequence[Mapping[str, Any]]] = None, @@ -319,7 +323,9 @@ def __init__( # pylint: disable=useless-parent-delegation environment_id=environment_id, title=title, resources=( - [dict(r) for r in resources] if resources is not None else None + [_to_mapping(r) for r in resources] + if resources is not None + else None ), vault_ids=(list(vault_ids) if vault_ids is not None else None), environment_variables=( diff --git a/tests/test_agentstudio_models.py b/tests/test_agentstudio_models.py index 3fecdd86..3938573a 100644 --- a/tests/test_agentstudio_models.py +++ b/tests/test_agentstudio_models.py @@ -10,6 +10,8 @@ from dashscope.agentstudio.types import ( Agent, Credential, + Mount, + SessionResource, CredentialAuth, DeleteResponse, Environment, @@ -323,3 +325,102 @@ def test_file_model_fields(): assert f.size_bytes == 1024 assert f.status == "checking" assert f.downloadable is None # not set + + +# --------------------------------------------------------------------------- +# Session mounts (Mount input / SessionResource echo) +# --------------------------------------------------------------------------- + + +def test_mount_fields_roundtrip(): + mount = Mount( + type="memory_store", + provider="agentstudio_memory", + memory_store_id="d7e534ca0e7d4fa8a4f4b079d314df3e", + entity_id="customer_001", + project_ids=["fact_rule_1", "skill_rule_1"], + profile_schema="7dfdc775eee5422dad37957e5ccf0081", + description="客户记忆", + access="read_only", + ) + d = mount.to_dict() + assert d["type"] == "memory_store" + assert d["provider"] == "agentstudio_memory" + assert d["entity_id"] == "customer_001" + assert d["project_ids"] == ["fact_rule_1", "skill_rule_1"] + assert d["profile_schema"] == "7dfdc775eee5422dad37957e5ccf0081" + assert d["description"] == "客户记忆" + assert d["access"] == "read_only" + + oss = Mount( + type="oss", + region="cn-beijing", + bucket="agentstudio-ma-oss-mnt", + oss_path="datasets/", + mount_path="/data", + ).to_dict() + assert oss == { + "type": "oss", + "region": "cn-beijing", + "bucket": "agentstudio-ma-oss-mnt", + "oss_path": "datasets/", + "mount_path": "/data", + } + + +def test_session_resource_mount_fields(): + r = SessionResource.from_dict( + { + "id": "sesrsc_1", + "type": "memory_store", + "provider": "agentstudio_memory", + "memory_store_id": "d7e534ca0e7d4fa8a4f4b079d314df3e", + "entity_id": "customer_001", + "project_ids": ["fact_rule_1"], + "profile_schema": "schema_demo", + }, + ) + assert r.provider == "agentstudio_memory" + assert r.entity_id == "customer_001" + assert r.project_ids == ["fact_rule_1"] + assert r.profile_schema == "schema_demo" + assert r.mount_path is None + + o = SessionResource.from_dict( + { + "id": "sesrsc_2", + "type": "oss", + "region": "cn-beijing", + "bucket": "agentstudio-ma-oss-mnt", + "oss_path": "datasets/", + "mount_path": "/data", + }, + ) + assert o.region == "cn-beijing" + assert o.bucket == "agentstudio-ma-oss-mnt" + assert o.oss_path == "datasets/" + assert o.mount_path == "/data" + + +def test_session_create_resources_accept_mount_or_dict(): + from dashscope.agentstudio.types.params import SessionCreateParams + + mount = Mount( + type="oss", + region="cn-beijing", + bucket="bkt", + mount_path="/data", + ) + body = SessionCreateParams( + agent={"type": "agent", "id": "agent_1"}, + resources=[mount, {"type": "file", "file_id": "file_1"}], + ).to_dict() + assert body["resources"] == [ + { + "type": "oss", + "region": "cn-beijing", + "bucket": "bkt", + "mount_path": "/data", + }, + {"type": "file", "file_id": "file_1"}, + ]