@agentdock/sdk 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +101 -0
- package/dist/client.d.ts +61 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +145 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/rpc.d.ts +36 -0
- package/dist/rpc.d.ts.map +1 -0
- package/dist/rpc.js +72 -0
- package/dist/rpc.js.map +1 -0
- package/package.json +42 -0
package/README.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# @agentbox/sdk
|
|
2
|
+
|
|
3
|
+
> 客户端 SDK — Socket.IO 连接管理 + 类型安全 RPC + 离线队列。
|
|
4
|
+
|
|
5
|
+
## 概述
|
|
6
|
+
|
|
7
|
+
sdk 包为 Web 前端和其他客户端提供与 AgentBox server 的连接能力:
|
|
8
|
+
|
|
9
|
+
- **自动重连**:断线后指数退避重连,连接状态实时可观测
|
|
10
|
+
- **RPC 封装**:类型安全的远程调用,Promise 风格
|
|
11
|
+
- **离线队列**:断线期间的 RPC 调用自动入队,重连后按序 flush
|
|
12
|
+
- **事件流**:订阅 CoreUpdate 实时推送
|
|
13
|
+
|
|
14
|
+
## 在架构中的位置
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
wire → crypto → sdk → web
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
依赖 wire(协议定义)和 crypto(加密),被 web 包使用。
|
|
21
|
+
|
|
22
|
+
## 模块结构
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
src/
|
|
26
|
+
├── client.ts # AgentboxClient — 连接管理 + 事件订阅 + 状态监听
|
|
27
|
+
├── rpc.ts # RpcClient — 类型安全 RPC + 离线队列 + flush
|
|
28
|
+
└── index.ts # Barrel exports
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## API 参考
|
|
32
|
+
|
|
33
|
+
### createClient (client.ts)
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { createClient } from '@agentbox/sdk';
|
|
37
|
+
import type { AgentboxClient, ClientConfig } from '@agentbox/sdk';
|
|
38
|
+
|
|
39
|
+
const client: AgentboxClient = createClient({
|
|
40
|
+
serverUrl: 'https://api.agentbox.dev',
|
|
41
|
+
token: 'user-auth-token',
|
|
42
|
+
clientType: 'web', // 'web' | 'daemon' | 'cli'
|
|
43
|
+
autoConnect: true, // 默认 true
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// 连接状态监听
|
|
47
|
+
const unsub = client.onStatus((status: ConnectionStatus) => {
|
|
48
|
+
// 'connected' | 'connecting' | 'disconnected' | 'error'
|
|
49
|
+
console.log('Connection:', status);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// 订阅实时更新
|
|
53
|
+
const unsub2 = client.onUpdate((update: CoreUpdate) => {
|
|
54
|
+
// 处理增量更新(会话事件、消息等)
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// 手动连接/断开
|
|
58
|
+
client.connect();
|
|
59
|
+
client.disconnect(); // 清理所有事件监听器(L16 教训)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### createRpcClient (rpc.ts)
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { createRpcClient } from '@agentbox/sdk';
|
|
66
|
+
import type { RpcClient, RpcTransport } from '@agentbox/sdk';
|
|
67
|
+
|
|
68
|
+
const rpc: RpcClient = createRpcClient(transport);
|
|
69
|
+
|
|
70
|
+
// 调用 RPC 方法(在线时立即发送,离线时入队)
|
|
71
|
+
const result: RpcResult = await rpc.call('method-name', params);
|
|
72
|
+
|
|
73
|
+
// 离线队列在重连时自动 flush(带互斥锁防竞态,L19 教训)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 类型定义
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
type ConnectionStatus = 'connected' | 'connecting' | 'disconnected' | 'error';
|
|
80
|
+
type ClientType = 'web' | 'daemon' | 'cli';
|
|
81
|
+
type Unsubscribe = () => void;
|
|
82
|
+
type StatusListener = (status: ConnectionStatus) => void;
|
|
83
|
+
type UpdateListener = (update: CoreUpdate) => void;
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## 开发
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# 运行测试(42 tests)
|
|
90
|
+
pnpm --filter @agentbox/sdk test
|
|
91
|
+
|
|
92
|
+
# 覆盖率(目标 90%+)
|
|
93
|
+
pnpm --filter @agentbox/sdk test:coverage
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## 设计决策
|
|
97
|
+
|
|
98
|
+
- **Socket.IO 而非原生 WebSocket**:自动重连、命名空间、房间、二进制支持
|
|
99
|
+
- **RPC + 离线队列**:离线期间操作不丢失,重连后补发
|
|
100
|
+
- **flush 互斥锁**:防止两次 reconnect 触发竞态(L19 教训)
|
|
101
|
+
- **disconnect 清理**:所有 `on()` 注册都有对应 `off()` 清理(L16 教训)
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentBox SDK client — Socket.IO connection management.
|
|
3
|
+
*
|
|
4
|
+
* Provides a uniform interface for connecting to the AgentBox server
|
|
5
|
+
* with auto-reconnection, status tracking, and event handling.
|
|
6
|
+
*/
|
|
7
|
+
import { type Socket } from 'socket.io-client';
|
|
8
|
+
/** Connection status for the client. */
|
|
9
|
+
export type ConnectionStatus = 'disconnected' | 'connecting' | 'connected' | 'error';
|
|
10
|
+
/** Client scope type for auth. */
|
|
11
|
+
export type ClientType = 'user-scoped' | 'session-scoped' | 'machine-scoped';
|
|
12
|
+
/** Status change listener. */
|
|
13
|
+
export type StatusListener = (status: ConnectionStatus) => void;
|
|
14
|
+
/** Update data listener. */
|
|
15
|
+
export type UpdateListener = (data: unknown) => void;
|
|
16
|
+
/** Unsubscribe function returned by event registration. */
|
|
17
|
+
export type Unsubscribe = () => void;
|
|
18
|
+
/** Socket factory — returns a Socket-like object. Used for DI in tests. */
|
|
19
|
+
export type SocketFactory = (endpoint: string, opts: Record<string, unknown>) => Socket;
|
|
20
|
+
/** Client configuration. */
|
|
21
|
+
export interface ClientConfig {
|
|
22
|
+
/** Server endpoint URL. */
|
|
23
|
+
readonly endpoint: string;
|
|
24
|
+
/** Authentication token. */
|
|
25
|
+
readonly token: string;
|
|
26
|
+
/** Socket.IO path (default: '/v1/updates'). */
|
|
27
|
+
readonly path?: string;
|
|
28
|
+
/** Client scope type (default: 'user-scoped'). */
|
|
29
|
+
readonly clientType?: ClientType;
|
|
30
|
+
/** Session ID (required for session-scoped). */
|
|
31
|
+
readonly sessionId?: string;
|
|
32
|
+
/** Machine ID (required for machine-scoped). */
|
|
33
|
+
readonly machineId?: string;
|
|
34
|
+
/** Reconnection delay in ms (default: 1000). */
|
|
35
|
+
readonly reconnectionDelay?: number;
|
|
36
|
+
/** Max reconnection delay in ms (default: 5000). */
|
|
37
|
+
readonly reconnectionDelayMax?: number;
|
|
38
|
+
/** Internal: socket factory for testing. */
|
|
39
|
+
readonly _socketFactory?: SocketFactory;
|
|
40
|
+
}
|
|
41
|
+
/** AgentBox client interface. */
|
|
42
|
+
export interface AgentboxClient {
|
|
43
|
+
/** Connect to the server. */
|
|
44
|
+
connect(): void;
|
|
45
|
+
/** Disconnect from the server. */
|
|
46
|
+
disconnect(): void;
|
|
47
|
+
/** Get the current connection status. */
|
|
48
|
+
getStatus(): ConnectionStatus;
|
|
49
|
+
/** Listen for status changes. Returns unsubscribe function. */
|
|
50
|
+
onStatusChange(listener: StatusListener): Unsubscribe;
|
|
51
|
+
/** Listen for server update events. Returns unsubscribe function. */
|
|
52
|
+
onUpdate(listener: UpdateListener): Unsubscribe;
|
|
53
|
+
/** Emit an event with acknowledgement (RPC-style). */
|
|
54
|
+
emitWithAck<T>(event: string, data: unknown): Promise<T>;
|
|
55
|
+
/** Subscribe to a raw socket event. Returns unsubscribe function. */
|
|
56
|
+
on(event: string, handler: (...args: unknown[]) => void): Unsubscribe;
|
|
57
|
+
/** Emit a raw socket event (fire-and-forget). */
|
|
58
|
+
emit(event: string, ...args: unknown[]): void;
|
|
59
|
+
}
|
|
60
|
+
export declare function createClient(config: ClientConfig): AgentboxClient;
|
|
61
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAM,KAAK,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAKnD,wCAAwC;AACxC,MAAM,MAAM,gBAAgB,GAAG,cAAc,GAAG,YAAY,GAAG,WAAW,GAAG,OAAO,CAAC;AAErF,kCAAkC;AAClC,MAAM,MAAM,UAAU,GAAG,aAAa,GAAG,gBAAgB,GAAG,gBAAgB,CAAC;AAE7E,8BAA8B;AAC9B,MAAM,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;AAEhE,4BAA4B;AAC5B,MAAM,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;AAErD,2DAA2D;AAC3D,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC;AAErC,2EAA2E;AAC3E,MAAM,MAAM,aAAa,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC;AAExF,4BAA4B;AAC5B,MAAM,WAAW,YAAY;IAC3B,2BAA2B;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,4BAA4B;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,+CAA+C;IAC/C,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,kDAAkD;IAClD,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;IACjC,gDAAgD;IAChD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,gDAAgD;IAChD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,gDAAgD;IAChD,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,oDAAoD;IACpD,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IACvC,4CAA4C;IAC5C,QAAQ,CAAC,cAAc,CAAC,EAAE,aAAa,CAAC;CACzC;AAED,iCAAiC;AACjC,MAAM,WAAW,cAAc;IAC7B,6BAA6B;IAC7B,OAAO,IAAI,IAAI,CAAC;IAChB,kCAAkC;IAClC,UAAU,IAAI,IAAI,CAAC;IACnB,yCAAyC;IACzC,SAAS,IAAI,gBAAgB,CAAC;IAC9B,+DAA+D;IAC/D,cAAc,CAAC,QAAQ,EAAE,cAAc,GAAG,WAAW,CAAC;IACtD,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,EAAE,cAAc,GAAG,WAAW,CAAC;IAChD,sDAAsD;IACtD,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACzD,qEAAqE;IACrE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,WAAW,CAAC;IACtE,iDAAiD;IACjD,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CAC/C;AAYD,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,cAAc,CAiJjE"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentBox SDK client — Socket.IO connection management.
|
|
3
|
+
*
|
|
4
|
+
* Provides a uniform interface for connecting to the AgentBox server
|
|
5
|
+
* with auto-reconnection, status tracking, and event handling.
|
|
6
|
+
*/
|
|
7
|
+
import { io } from 'socket.io-client';
|
|
8
|
+
import createDebug from 'debug';
|
|
9
|
+
// ── Factory ─────────────────────────────────────────────────────────
|
|
10
|
+
/**
|
|
11
|
+
* Create an AgentBox client instance.
|
|
12
|
+
*
|
|
13
|
+
* @param config - Client configuration.
|
|
14
|
+
* @returns An AgentboxClient ready to be connected.
|
|
15
|
+
*/
|
|
16
|
+
const log = createDebug('agentbox:sdk:client');
|
|
17
|
+
export function createClient(config) {
|
|
18
|
+
let status = 'disconnected';
|
|
19
|
+
let socket = null;
|
|
20
|
+
const statusListeners = new Set();
|
|
21
|
+
const updateListeners = new Set();
|
|
22
|
+
const createSocket = config._socketFactory ?? io;
|
|
23
|
+
// Buffer for event listeners registered before connect()
|
|
24
|
+
const pendingListeners = [];
|
|
25
|
+
function setStatus(newStatus) {
|
|
26
|
+
status = newStatus;
|
|
27
|
+
for (const listener of statusListeners) {
|
|
28
|
+
listener(newStatus);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function emitUpdate(data) {
|
|
32
|
+
for (const listener of updateListeners) {
|
|
33
|
+
listener(data);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function buildAuth() {
|
|
37
|
+
const auth = {
|
|
38
|
+
token: config.token,
|
|
39
|
+
clientType: config.clientType ?? 'user-scoped',
|
|
40
|
+
};
|
|
41
|
+
if (config.sessionId) {
|
|
42
|
+
auth['sessionId'] = config.sessionId;
|
|
43
|
+
}
|
|
44
|
+
if (config.machineId) {
|
|
45
|
+
auth['machineId'] = config.machineId;
|
|
46
|
+
}
|
|
47
|
+
return auth;
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
connect() {
|
|
51
|
+
if (socket)
|
|
52
|
+
return;
|
|
53
|
+
setStatus('connecting');
|
|
54
|
+
socket = createSocket(config.endpoint, {
|
|
55
|
+
path: config.path ?? '/v1/updates',
|
|
56
|
+
auth: buildAuth(),
|
|
57
|
+
transports: ['websocket', 'polling'],
|
|
58
|
+
reconnection: true,
|
|
59
|
+
reconnectionDelay: config.reconnectionDelay ?? 1000,
|
|
60
|
+
reconnectionDelayMax: config.reconnectionDelayMax ?? 5000,
|
|
61
|
+
reconnectionAttempts: Infinity,
|
|
62
|
+
autoConnect: false,
|
|
63
|
+
});
|
|
64
|
+
socket.on('connect', () => {
|
|
65
|
+
log('connected to %s', config.endpoint);
|
|
66
|
+
setStatus('connected');
|
|
67
|
+
});
|
|
68
|
+
socket.on('disconnect', (reason) => {
|
|
69
|
+
log('disconnected: %s', reason);
|
|
70
|
+
setStatus('disconnected');
|
|
71
|
+
});
|
|
72
|
+
socket.on('connect_error', (err) => {
|
|
73
|
+
log('connect_error: %s', err instanceof Error ? err.message : err);
|
|
74
|
+
setStatus('error');
|
|
75
|
+
});
|
|
76
|
+
socket.on('update', (data) => {
|
|
77
|
+
emitUpdate(data);
|
|
78
|
+
});
|
|
79
|
+
socket.on('ephemeral', (data) => {
|
|
80
|
+
emitUpdate(data);
|
|
81
|
+
});
|
|
82
|
+
// Replay any event listeners registered before connect()
|
|
83
|
+
for (const { event, handler } of pendingListeners) {
|
|
84
|
+
socket.on(event, handler);
|
|
85
|
+
}
|
|
86
|
+
pendingListeners.length = 0;
|
|
87
|
+
// Connect after all listeners are registered (avoids race with autoConnect)
|
|
88
|
+
socket.connect();
|
|
89
|
+
},
|
|
90
|
+
disconnect() {
|
|
91
|
+
if (socket) {
|
|
92
|
+
// Clean up all event listeners before disconnecting (L16)
|
|
93
|
+
socket.removeAllListeners();
|
|
94
|
+
socket.disconnect();
|
|
95
|
+
socket = null;
|
|
96
|
+
setStatus('disconnected');
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
getStatus() {
|
|
100
|
+
return status;
|
|
101
|
+
},
|
|
102
|
+
onStatusChange(listener) {
|
|
103
|
+
statusListeners.add(listener);
|
|
104
|
+
return () => {
|
|
105
|
+
statusListeners.delete(listener);
|
|
106
|
+
};
|
|
107
|
+
},
|
|
108
|
+
onUpdate(listener) {
|
|
109
|
+
updateListeners.add(listener);
|
|
110
|
+
return () => {
|
|
111
|
+
updateListeners.delete(listener);
|
|
112
|
+
};
|
|
113
|
+
},
|
|
114
|
+
async emitWithAck(event, data) {
|
|
115
|
+
if (!socket || !socket.connected) {
|
|
116
|
+
throw new Error('Not connected');
|
|
117
|
+
}
|
|
118
|
+
return socket.emitWithAck(event, data);
|
|
119
|
+
},
|
|
120
|
+
on(event, handler) {
|
|
121
|
+
if (socket) {
|
|
122
|
+
socket.on(event, handler);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
pendingListeners.push({ event, handler });
|
|
126
|
+
}
|
|
127
|
+
return () => {
|
|
128
|
+
if (socket) {
|
|
129
|
+
socket.off(event, handler);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
const idx = pendingListeners.findIndex((p) => p.event === event && p.handler === handler);
|
|
133
|
+
if (idx !== -1)
|
|
134
|
+
pendingListeners.splice(idx, 1);
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
},
|
|
138
|
+
emit(event, ...args) {
|
|
139
|
+
if (socket?.connected) {
|
|
140
|
+
socket.emit(event, ...args);
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createClient } from './client.js';
|
|
2
|
+
export type { AgentboxClient, ClientConfig, ClientType, ConnectionStatus, StatusListener, UpdateListener, Unsubscribe, } from './client.js';
|
|
3
|
+
export { createRpcClient } from './rpc.js';
|
|
4
|
+
export type { RpcClient, RpcTransport, RpcResult } from './rpc.js';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,YAAY,EACV,cAAc,EACd,YAAY,EACZ,UAAU,EACV,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,WAAW,GACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAE3C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAU3C,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/rpc.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RPC client — typed method calls over Socket.IO with offline queue.
|
|
3
|
+
*
|
|
4
|
+
* When disconnected, calls are queued and automatically flushed
|
|
5
|
+
* when the transport reconnects.
|
|
6
|
+
*/
|
|
7
|
+
/** RPC call result. */
|
|
8
|
+
export interface RpcResult<T = unknown> {
|
|
9
|
+
readonly ok: boolean;
|
|
10
|
+
readonly result?: T;
|
|
11
|
+
readonly error?: string;
|
|
12
|
+
}
|
|
13
|
+
/** Transport abstraction for RPC calls. */
|
|
14
|
+
export interface RpcTransport {
|
|
15
|
+
/** Emit an event and wait for acknowledgement. */
|
|
16
|
+
emitWithAck<T>(event: string, data: unknown): Promise<T>;
|
|
17
|
+
/** Whether the transport is currently connected. */
|
|
18
|
+
isConnected(): boolean;
|
|
19
|
+
}
|
|
20
|
+
/** RPC client interface. */
|
|
21
|
+
export interface RpcClient {
|
|
22
|
+
/** Call an RPC method. Queues if disconnected. */
|
|
23
|
+
call<T = unknown>(method: string, params: unknown): Promise<RpcResult<T>>;
|
|
24
|
+
/** Get the number of queued (offline) calls. */
|
|
25
|
+
getQueueSize(): number;
|
|
26
|
+
/** Flush queued calls (call after reconnection). */
|
|
27
|
+
flush(): Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Create an RPC client.
|
|
31
|
+
*
|
|
32
|
+
* @param transport - Transport layer for sending RPC calls.
|
|
33
|
+
* @returns An RpcClient instance.
|
|
34
|
+
*/
|
|
35
|
+
export declare function createRpcClient(transport: RpcTransport): RpcClient;
|
|
36
|
+
//# sourceMappingURL=rpc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rpc.d.ts","sourceRoot":"","sources":["../src/rpc.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,uBAAuB;AACvB,MAAM,WAAW,SAAS,CAAC,CAAC,GAAG,OAAO;IACpC,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACpB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,2CAA2C;AAC3C,MAAM,WAAW,YAAY;IAC3B,kDAAkD;IAClD,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACzD,oDAAoD;IACpD,WAAW,IAAI,OAAO,CAAC;CACxB;AAUD,4BAA4B;AAC5B,MAAM,WAAW,SAAS;IACxB,kDAAkD;IAClD,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1E,gDAAgD;IAChD,YAAY,IAAI,MAAM,CAAC;IACvB,oDAAoD;IACpD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAID;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,YAAY,GAAG,SAAS,CAyDlE"}
|
package/dist/rpc.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RPC client — typed method calls over Socket.IO with offline queue.
|
|
3
|
+
*
|
|
4
|
+
* When disconnected, calls are queued and automatically flushed
|
|
5
|
+
* when the transport reconnects.
|
|
6
|
+
*/
|
|
7
|
+
import createDebug from 'debug';
|
|
8
|
+
const log = createDebug('agentbox:sdk:rpc');
|
|
9
|
+
// ── Factory ─────────────────────────────────────────────────────────
|
|
10
|
+
/**
|
|
11
|
+
* Create an RPC client.
|
|
12
|
+
*
|
|
13
|
+
* @param transport - Transport layer for sending RPC calls.
|
|
14
|
+
* @returns An RpcClient instance.
|
|
15
|
+
*/
|
|
16
|
+
export function createRpcClient(transport) {
|
|
17
|
+
const queue = [];
|
|
18
|
+
let isFlushing = false;
|
|
19
|
+
async function executeCall(method, params) {
|
|
20
|
+
return transport.emitWithAck('rpc-call', {
|
|
21
|
+
method,
|
|
22
|
+
params,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
call(method, params) {
|
|
27
|
+
if (transport.isConnected()) {
|
|
28
|
+
log('call %s', method);
|
|
29
|
+
return executeCall(method, params);
|
|
30
|
+
}
|
|
31
|
+
log('queued %s (offline, queue=%d)', method, queue.length + 1);
|
|
32
|
+
return new Promise((resolve, reject) => {
|
|
33
|
+
queue.push({
|
|
34
|
+
method,
|
|
35
|
+
params,
|
|
36
|
+
resolve: resolve,
|
|
37
|
+
reject,
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
},
|
|
41
|
+
getQueueSize() {
|
|
42
|
+
return queue.length;
|
|
43
|
+
},
|
|
44
|
+
async flush() {
|
|
45
|
+
if (!transport.isConnected())
|
|
46
|
+
return;
|
|
47
|
+
if (isFlushing)
|
|
48
|
+
return;
|
|
49
|
+
isFlushing = true;
|
|
50
|
+
log('flushing %d queued calls', queue.length);
|
|
51
|
+
try {
|
|
52
|
+
while (queue.length > 0) {
|
|
53
|
+
const item = queue.shift();
|
|
54
|
+
if (!item)
|
|
55
|
+
break;
|
|
56
|
+
try {
|
|
57
|
+
const result = await executeCall(item.method, item.params);
|
|
58
|
+
item.resolve(result);
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
log('flush failed for %s: %s', item.method, err);
|
|
62
|
+
item.reject(err instanceof Error ? err : new Error(String(err)));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
finally {
|
|
67
|
+
isFlushing = false;
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=rpc.js.map
|
package/dist/rpc.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rpc.js","sourceRoot":"","sources":["../src/rpc.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,WAAW,MAAM,OAAO,CAAC;AAEhC,MAAM,GAAG,GAAG,WAAW,CAAC,kBAAkB,CAAC,CAAC;AAmC5C,uEAAuE;AAEvE;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,SAAuB;IACrD,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,IAAI,UAAU,GAAG,KAAK,CAAC;IAEvB,KAAK,UAAU,WAAW,CAAI,MAAc,EAAE,MAAe;QAC3D,OAAO,SAAS,CAAC,WAAW,CAAe,UAAU,EAAE;YACrD,MAAM;YACN,MAAM;SACP,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,IAAI,CAAc,MAAc,EAAE,MAAe;YAC/C,IAAI,SAAS,CAAC,WAAW,EAAE,EAAE,CAAC;gBAC5B,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;gBACvB,OAAO,WAAW,CAAI,MAAM,EAAE,MAAM,CAAC,CAAC;YACxC,CAAC;YAED,GAAG,CAAC,+BAA+B,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC/D,OAAO,IAAI,OAAO,CAAe,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBACnD,KAAK,CAAC,IAAI,CAAC;oBACT,MAAM;oBACN,MAAM;oBACN,OAAO,EAAE,OAAmC;oBAC5C,MAAM;iBACP,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC;QAED,YAAY;YACV,OAAO,KAAK,CAAC,MAAM,CAAC;QACtB,CAAC;QAED,KAAK,CAAC,KAAK;YACT,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE;gBAAE,OAAO;YACrC,IAAI,UAAU;gBAAE,OAAO;YACvB,UAAU,GAAG,IAAI,CAAC;YAClB,GAAG,CAAC,0BAA0B,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;YAE9C,IAAI,CAAC;gBACH,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACxB,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC;oBAC3B,IAAI,CAAC,IAAI;wBAAE,MAAM;oBAEjB,IAAI,CAAC;wBACH,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;wBAC3D,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;oBACvB,CAAC;oBAAC,OAAO,GAAG,EAAE,CAAC;wBACb,GAAG,CAAC,yBAAyB,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;wBACjD,IAAI,CAAC,MAAM,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;oBACnE,CAAC;gBACH,CAAC;YACH,CAAC;oBAAS,CAAC;gBACT,UAAU,GAAG,KAAK,CAAC;YACrB,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agentdock/sdk",
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "Client SDK for AgentDock — Socket.IO, RPC, offline queue",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"author": "kevin8536945",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "dist/index.js",
|
|
9
|
+
"types": "dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"access": "public",
|
|
21
|
+
"registry": "https://registry.npmjs.org"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"debug": "^4.4.3",
|
|
25
|
+
"socket.io-client": "^4.8.3",
|
|
26
|
+
"@agentdock/wire": "0.4.0",
|
|
27
|
+
"@agentdock/crypto": "0.4.0"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/debug": "^4.1.12",
|
|
31
|
+
"@vitest/coverage-v8": "^3.0.0",
|
|
32
|
+
"typescript": "^5.7.0",
|
|
33
|
+
"vitest": "^3.0.0"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "tsc",
|
|
37
|
+
"test": "vitest run",
|
|
38
|
+
"test:coverage": "vitest run --coverage",
|
|
39
|
+
"lint": "eslint src/ && tsc --noEmit",
|
|
40
|
+
"typecheck": "tsc --noEmit"
|
|
41
|
+
}
|
|
42
|
+
}
|