feat: Expose per-mount subpath/alias/permission on SessionV2 GraphQL node#11966
feat: Expose per-mount subpath/alias/permission on SessionV2 GraphQL node#11966rapsealk wants to merge 4 commits into
Conversation
…node Surface vfolder mount metadata (subpath, alias/mount destination, and effective permission) on the Strawberry SessionV2 node via a new SessionMount DTO and SessionMountGQL type. Data already flows to the v2 adapter; it is now mapped into the SessionNode DTO and exposed. Resolves #11963 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR exposes per-mount virtual folder metadata on the Strawberry SessionV2 GraphQL node by introducing a dedicated mount DTO/type and wiring already-available SessionData.vfolder_mounts through the v2 session adapter into the GraphQL schema (replacing the previous TODO/placeholder).
Changes:
- Added
SessionMountDTO and includedmounts: list[SessionMount]onSessionNode. - Mapped
SessionData.vfolder_mounts→SessionNode.mountsinSessionAdapter._session_data_to_node(), including"."→nullsubpath normalization. - Added
SessionMountGraphQL output type and exposedmountsonSessionV2, plus updated generated schemas and adapter unit tests.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
src/ai/backend/common/dto/manager/v2/session/response.py |
Introduces SessionMount DTO and adds mounts to SessionNode for downstream GraphQL exposure. |
src/ai/backend/manager/api/adapters/session/adapter.py |
Maps SessionData.vfolder_mounts into the new SessionNode.mounts structure (incl. subpath normalization). |
src/ai/backend/manager/api/gql/session/types.py |
Adds SessionMount GraphQL type and exposes mounts field on SessionV2. |
tests/unit/manager/api/adapters/test_session_adapter.py |
Adds unit coverage for mount mapping (subpath normalization, destination, permission, usage mode). |
docs/manager/graphql-reference/v2-schema.graphql |
Regenerated v2 schema to include SessionMount and SessionV2.mounts. |
docs/manager/graphql-reference/supergraph.graphql |
Regenerated supergraph schema to include the new type/field. |
changes/11966.feature.md |
Adds changelog entry for the new SessionV2.mounts exposure. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…fo-v2 # Conflicts: # src/ai/backend/common/dto/manager/v2/session/response.py # src/ai/backend/manager/api/adapters/session/adapter.py # src/ai/backend/manager/api/gql/session/types.py
| class SessionMountGQL: | ||
| vfolder_id: UUID = gql_field(description="UUID of the mounted virtual folder.") | ||
| name: str = gql_field(description="Name of the mounted virtual folder.") | ||
| subpath: str | None = gql_field( | ||
| description="Subpath within the vfolder that is mounted. Null when the vfolder root is mounted." | ||
| ) | ||
| mount_destination: str = gql_field( | ||
| description="Mount destination (alias) path inside the session container." | ||
| ) | ||
| permission: str = gql_field(description="Effective mount permission (e.g., 'ro', 'rw').") | ||
| usage_mode: str = gql_field(description="Usage mode of the mounted virtual folder.") |
There was a problem hiding this comment.
It would be better to add a vfolder node field so that mount-specific information (e.g., subpath, permission, etc.) and VFolder information can be queried separately in a structured manner.
There was a problem hiding this comment.
There used to be a convention that Node types were only attached to root types, but that convention does not seem applicable in this case.
Since the same vfolder can be mounted multiple times under different subpaths, it makes more sense for the mount itself to be associated with a vfolder node. This more accurately reflects the relationship between mounts and vfolders.
There was a problem hiding this comment.
Good call — restructured accordingly. Each mount now exposes a vfolder: VFolder node (the v2 Strawberry VFolderGQL, resolved through the existing vfolder_loader), so folder-level information can be queried separately in a structured manner. As you noted, the same vfolder can be mounted multiple times under different subpaths, so the relationship lives on the mount itself.
The SessionMount type now carries only mount-specific fields — vfolderId, subpath, mountDestination, permission — while name/usageMode moved to vfolder.metadata:
type SessionMount {
vfolderId: UUID!
subpath: String
mountDestination: String!
permission: VFolderMountPermission!
vfolder: VFolder
}| mount_destination: str = gql_field( | ||
| description="Mount destination (alias) path inside the session container." | ||
| ) | ||
| permission: str = gql_field(description="Effective mount permission (e.g., 'ro', 'rw').") |
There was a problem hiding this comment.
Since the VFolderMountPermissionGQL, VFolderUsageModeGQL type already exists, it would be better to use them
There was a problem hiding this comment.
Done — permission now uses the existing VFolderMountPermission GQL enum (and VFolderPermissionField on the DTO side) instead of a bare string. usage_mode was dropped from the mount type itself (see the vfolder-node thread); it is now reachable via vfolder.metadata.usageMode.
| added_version=NEXT_RELEASE_VERSION, | ||
| description="A single virtual folder mount on a session.", | ||
| ), | ||
| model=SessionMount, |
There was a problem hiding this comment.
Renamed SessionMount → SessionMountDTO.
Address review feedback on per-mount metadata exposure: - Rename DTO `SessionMount` -> `SessionMountDTO`. - Type `permission` with the existing `VFolderMountPermission` GQL enum (`VFolderPermissionField` DTO) instead of a bare string. - Attach each mount to the v2 `VFolder` node via a `vfolder` resolver (using the existing `vfolder_loader`), so folder attributes can be queried separately in a structured manner. The same vfolder may be mounted multiple times under different subpaths, so the relationship belongs on the mount. - Keep only mount-specific fields on the mount type (subpath, mount destination, permission, vfolder id); drop `name`/`usage_mode` which are now reachable through `vfolder.metadata`. - Regenerate v2 and supergraph schemas; update adapter unit tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary
Exposes per-mount subpath, alias (mount destination), and permission (plus name, vfolder id, and usage mode) on the new Strawberry
SessionV2GraphQL node, replacing the# TODO: Add vfolder_mounts dynamic fieldplaceholder.The mount data already flows to the v2 adapter via
SessionData.vfolder_mounts: list[VFolderMountData] | None, so no DB/loader/query change was needed. A newSessionMountDTO andSessionMountGQLoutput type were added, and the adapter now maps eachVFolderMountDatainto theSessionNodeDTO.Field mapping
vfolderIdvfid.folder_idnamenamesubpathvfsubpath("."→null)mountDestinationkernel_pathpermissionmount_permusageModeusage_modeSupergraph composition succeeded with the schema name
SessionMount(no collision with a legacy Graphene type), so noV2suffix was required.Test plan
pants fmtpassespants fixpassespants lintpassespants check(mypy) passespants testpassesv2-schema.graphql,supergraph.graphql)"."→nullnormalization)Part of #11962
Resolves #11963
🤖 Generated with Claude Code
📚 Documentation preview 📚: https://sorna--11966.org.readthedocs.build/en/11966/
📚 Documentation preview 📚: https://sorna-ko--11966.org.readthedocs.build/ko/11966/