@@ -37,6 +37,9 @@ import type {
3737 FilePage ,
3838 SessionEventInput ,
3939 SessionEventSendResult ,
40+ SessionResourceListOptions ,
41+ SessionResourceMountInput ,
42+ SessionResourcePage ,
4043 SessionUpdateInput ,
4144 SkillDownloadInfo ,
4245 SkillListOptions ,
@@ -56,7 +59,13 @@ import type {
5659 UpdateMemoryInput ,
5760 UpdateMemoryStoreInput ,
5861} from "../../types/memory.ts" ;
59- import type { ProviderSessionInfo , SessionBindings , SessionFilter , SessionListResult } from "../../types/session.ts" ;
62+ import type {
63+ ProviderSessionInfo ,
64+ SessionBindings ,
65+ SessionFilter ,
66+ SessionListResult ,
67+ SessionResourceInfo ,
68+ } from "../../types/session.ts" ;
6069import type {
6170 EventListOptions ,
6271 EventStreamOptions ,
@@ -1211,6 +1220,35 @@ export class BailianAdapter implements ProviderAdapter {
12111220 await this . client . delete ( `/sessions/${ id } ` ) ;
12121221 }
12131222
1223+ async mountSessionResource ( sessionId : string , input : SessionResourceMountInput ) : Promise < SessionResourceInfo > {
1224+ const res = ( await this . client . post ( `/sessions/${ sessionId } /resources` , {
1225+ type : input . type ,
1226+ file_id : input . file_id ,
1227+ // The runtime endpoint takes the path under the sandbox session root
1228+ // ("/uploads/…"), while the SDK's neutral layer — and the create-session
1229+ // API — use the full sandbox path ("/mnt/session/uploads/…").
1230+ mount_path : toRuntimeResourceMountPath ( input . mount_path ) ,
1231+ } ) ) as Record < string , unknown > ;
1232+ return toSessionResourceInfo ( res ) ;
1233+ }
1234+
1235+ async listSessionResources ( sessionId : string , options ?: SessionResourceListOptions ) : Promise < SessionResourcePage > {
1236+ const res = ( await this . client . get ( withQuery ( `/sessions/${ sessionId } /resources` , cursorParams ( options ) ) ) ) as Record <
1237+ string ,
1238+ unknown
1239+ > ;
1240+ return cursorPage ( res , toSessionResourceInfo ) ;
1241+ }
1242+
1243+ async getSessionResource ( sessionId : string , resourceId : string ) : Promise < SessionResourceInfo > {
1244+ const res = ( await this . client . get ( `/sessions/${ sessionId } /resources/${ resourceId } ` ) ) as Record < string , unknown > ;
1245+ return toSessionResourceInfo ( res ) ;
1246+ }
1247+
1248+ async unmountSessionResource ( sessionId : string , resourceId : string ) : Promise < void > {
1249+ await this . client . delete ( `/sessions/${ sessionId } /resources/${ resourceId } ` ) ;
1250+ }
1251+
12141252 async sendSessionMessage ( sessionId : string , message : string ) : Promise < string | undefined > {
12151253 const body = mapSendMessage ( message ) ;
12161254 const res = ( await this . client . post ( `/sessions/${ sessionId } /events` , body ) ) as Record < string , unknown > ;
@@ -1363,6 +1401,38 @@ export function toSessionInfo(res: Record<string, unknown>): ProviderSessionInfo
13631401 return sessionInfo ;
13641402}
13651403
1404+ /** Sandbox session root on bailian; the runtime resources API takes paths relative to it. */
1405+ const BAILIAN_SESSION_SANDBOX_ROOT = "/mnt/session" ;
1406+
1407+ /**
1408+ * Runtime resource mount_path wire convention: absolute under `/uploads/`. Accept the
1409+ * full sandbox path used by the neutral layer and create-session API (`/mnt/session/uploads/…`),
1410+ * or an already wire-shaped `/uploads/…` path; anything else is rejected client-side.
1411+ */
1412+ function toRuntimeResourceMountPath ( mountPath : string ) : string {
1413+ const wirePath = mountPath . startsWith ( `${ BAILIAN_SESSION_SANDBOX_ROOT } /` )
1414+ ? mountPath . slice ( BAILIAN_SESSION_SANDBOX_ROOT . length )
1415+ : mountPath ;
1416+ if ( wirePath === "/uploads" || wirePath . startsWith ( "/uploads/" ) ) return wirePath ;
1417+ throw new UserError (
1418+ `bailian runtime mount_path must resolve to '/uploads/…' (sandbox '${ BAILIAN_SESSION_SANDBOX_ROOT } /uploads/…'); received '${ mountPath } '.` ,
1419+ ) ;
1420+ }
1421+
1422+ /** Raw bailian session-resource object → neutral SessionResourceInfo; the full payload rides in `attributes`. */
1423+ function toSessionResourceInfo ( res : Record < string , unknown > ) : SessionResourceInfo {
1424+ return {
1425+ ...( typeof res . id === "string" ? { id : res . id } : { } ) ,
1426+ type : ( res . type as string ) ?? "file" ,
1427+ ...( typeof res . mount_path === "string" ? { mount_path : res . mount_path } : { } ) ,
1428+ ...( typeof res . file_id === "string" ? { file_id : res . file_id } : { } ) ,
1429+ ...( typeof res . memory_store_id === "string" ? { memory_store_id : res . memory_store_id } : { } ) ,
1430+ ...( res . access === "read_write" || res . access === "read_only" ? { access : res . access } : { } ) ,
1431+ ...( typeof res . instructions === "string" ? { instructions : res . instructions } : { } ) ,
1432+ attributes : res ,
1433+ } ;
1434+ }
1435+
13661436// Raw Bailian `/skills` item → neutral ProviderSkillInfo. Kept provider-local (not the
13671437// shared toRestSkillInfo) because bailian's wire differs: name is `name` (not display_title),
13681438// the custom catalog reports `customer`, and skills carry a real security-scan status.
0 commit comments