第十四章:API Gateway 与 SDK 本章目标 :帮助你理解 dsh 的 BFF(Backend-for-Frontend)架构、JSON-RPC 协议细节、TypeScript/Python SDK 的实现差异、以及连接管理与重连策略。阅读本章后,你应该能回答"前后端如何通信"以及"SDK 如何连接到 dsh 服务"。
14.1 BFF 架构 14.1.1 概念BFF(Backend-for-Frontend)是 dsh 的 API 网关模式,为前端提供专门的 API 接口。
14.1.2 api/ 包组织 14.2 JSON-RPC 协议 14.2.1 协议规范dsh 使用 JSON-RPC 2.0 作为前后端通信协议。
interface JsonRpcRequest {
jsonrpc: '2.0'
id: string | number
method: string
params? : unknown
}
interface JsonRpcSuccessResponse {
jsonrpc: '2.0'
id: string | number
result: unknown
}
interface JsonRpcErrorResponse {
jsonrpc: '2.0'
id: string | number
error: {
code: number
message: string
data? : unknown
}
}
14.2.2 方法注册
class HarnessSdkJsonRpcServer {
private registerMethods ( ) : void {
this . server. method ( 'session.create' , this . createSession . bind ( this ) )
this . server. method ( 'session.list' , this . listSessions . bind ( this ) )
this . server. method ( 'session.open' , this . openSession . bind ( this ) )
this . server. method ( 'session.send' , this . sendMessage . bind ( this ) )
this . server. method ( 'event.subscribe' , this . subscribeEvents . bind ( this ) )
this . server. method ( 'event.unsubscribe' , this . unsubscribeEvents . bind ( this ) )
this . server. method ( 'tool.execute' , this . executeTool . bind ( this ) )
this . server. method ( 'projection.get' , this . getProjection . bind ( this ) )
}
}
14.2.3 方法实现
async createSession ( params: CreateSessionParams) : Promise < SessionHeader> {
const session = await this . ctx. agents. create ( {
sessionId: generateSessionId ( ) ,
meta: params. meta
} )
return session. header ( )
}
async sendMessage ( params: SendParams) : Promise < MessageResult> {
const session = await this . ctx. sessions. open ( params. sessionId)
await session. log. append ( {
type: 'user/message' ,
data: { content: params. content }
} )
const agent = this . ctx. agents. get ( params. sessionId)
agent. inbox. insert ( {
role: 'user' ,
content: params. content
} )
return { success: true }
}
14.3 TypeScript SDK 14.3.1 客户端实现
class HarnessClient {
private connection: JsonRpcConnection
constructor ( private options: ClientOptions) {
this . connection = new JsonRpcConnection ( options. endpoint)
}
async createSession ( options? : CreateSessionOptions) : Promise < Session> {
const header = await this . connection. request ( 'session.create' , options)
return new Session ( this . connection, header)
}
async listSessions ( ) : Promise < SessionHeader[ ] > {
return this . connection. request ( 'session.list' )
}
async openSession ( sessionId: string ) : Promise < Session> {
const header = await this . connection. request ( 'session.open' , { sessionId } )
return new Session ( this . connection, header)
}
}
14.3.2 Session 对象
class Session {
constructor (
private connection: JsonRpcConnection,
public readonly header: SessionHeader
) { }
async send ( content: string ) : Promise < MessageResult> {
return this . connection. request ( 'session.send' , {
sessionId: this . header. id,
content
} )
}
subscribe ( callback : ( event: SessionEvent) => void ) : Disposable {
const subscription = this . connection. subscribe ( 'event' , {
sessionId: this . header. id
} )
subscription. on ( 'event' , callback)
return ( ) => subscription. unsubscribe ( )
}
async getProjection < K extends string > ( key: K ) : Promise < ProjectionState< K >> {
return this . connection. request ( 'projection.get' , {
sessionId: this . header. id,
key
} )
}
}
14.4 Python SDK 14.4.1 客户端实现
class HarnessClient :
def __init__ ( self, endpoint: str = 'ws://localhost:3000' ) :
self. connection = JsonRpcConnection( endpoint)
async def create_session ( self, ** options) - > Session:
"""创建会话"""
header = await self. connection. request( 'session.create' , options)
return Session( self. connection, header)
async def list_sessions ( self) - > list [ dict ] :
"""列出所有会话"""
return await self. connection. request( 'session.list' )
async def open_session ( self, session_id: str ) - > Session:
"""打开会话"""
header = await self. connection. request( 'session.open' , {
'sessionId' : session_id
} )
return Session( self. connection, header)
14.4.2 Session 对象
class Session :
def __init__ ( self, connection, header) :
self. connection = connection
self. header = header
async def send ( self, content: str ) - > dict :
"""发送消息"""
return await self. connection. request( 'session.send' , {
'sessionId' : self. header[ 'id' ] ,
'content' : content
} )
def subscribe ( self, callback) :
"""订阅事件"""
subscription = self. connection. subscribe( 'event' , {
'sessionId' : self. header[ 'id' ]
} )
subscription. on( 'event' , callback)
return subscription
async def get_projection ( self, key: str ) :
"""获取投影"""
return await self. connection. request( 'projection.get' , {
'sessionId' : self. header[ 'id' ] ,
'key' : key
} )
14.5 连接管理 14.5.1 连接池
class ConnectionPool {
private connections = new Map< string , JsonRpcConnection> ( )
async getConnection ( endpoint: string ) : Promise < JsonRpcConnection> {
let connection = this . connections. get ( endpoint)
if ( ! connection || connection. isClosed ( ) ) {
connection = new JsonRpcConnection ( endpoint)
this . connections. set ( endpoint, connection)
}
return connection
}
async closeAll ( ) : Promise < void > {
for ( const connection of this . connections. values ( ) ) {
await connection. close ( )
}
this . connections. clear ( )
}
}
14.5.2 重连策略
class ReconnectStrategy {
async reconnect ( connection: JsonRpcConnection) : Promise < void > {
let attempt = 0
const maxAttempts = 5
const baseDelay = 1000
while ( attempt < maxAttempts) {
try {
await connection. connect ( )
return
} catch ( error) {
attempt++
const delay = baseDelay * Math. pow ( 2 , attempt - 1 )
await sleep ( delay)
}
}
throw new Error ( 'Failed to reconnect after max attempts' )
}
}
14.6 流式响应 14.6.1 概念对于长时间运行的操作(如 LLM 流式输出),SDK 支持流式响应。
class StreamableSession {
async * sendStream ( content: string ) : AsyncIterable< StreamChunk> {
const subscription = this . connection. subscribe ( 'stream' , {
sessionId: this . header. id,
content
} )
try {
for await ( const chunk of subscription) {
yield chunk
}
} finally {
subscription. unsubscribe ( )
}
}
}
14.6.2 Python 流式
class StreamableSession :
async def send_stream ( self, content: str ) :
"""流式发送消息"""
subscription = self. connection. subscribe( 'stream' , {
'sessionId' : self. header[ 'id' ] ,
'content' : content
} )
try :
async for chunk in subscription:
yield chunk
finally :
subscription. unsubscribe( )
14.7 配置 14.7.1 SDK 服务器配置
- id : sdk- server
config :
port : 3000
cors :
origin : '*'
methods : [ 'GET' , 'POST' ]
auth :
type : 'none'
14.8 小结
概念 一句话解释 BFF Backend-for-Frontend 架构 JSON-RPC 前后端通信协议 TypeScript SDK TypeScript 客户端库 Python SDK Python 客户端库 连接管理 连接池和重连策略 流式响应 长时间运行操作的流式输出
下一步 :第十五章:凭证与授权 ——深入理解凭证接缝、API Key 管理和 OAuth 流程。