@lark-apaas/client-capability 0.0.1-alpha.0 → 0.0.1-alpha.1
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 +59 -95
- package/dist/index.cjs +51 -151
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -59
- package/dist/index.d.ts +23 -59
- package/dist/index.js +51 -151
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,18 +14,18 @@ npm install @lark-apaas/client-capability
|
|
|
14
14
|
|
|
15
15
|
- 封装 `/api/capability/:id` HTTP 调用
|
|
16
16
|
- 流式调用支持(SSE)
|
|
17
|
-
- 运行时能力发现和验证
|
|
18
17
|
- 统一的错误处理
|
|
18
|
+
- 与服务端 API 一致的链式调用风格
|
|
19
19
|
|
|
20
20
|
## 快速开始
|
|
21
21
|
|
|
22
22
|
### 基础使用
|
|
23
23
|
|
|
24
24
|
```typescript
|
|
25
|
-
import {
|
|
25
|
+
import { capabilityClient } from '@lark-apaas/client-capability';
|
|
26
26
|
|
|
27
|
-
//
|
|
28
|
-
const result = await
|
|
27
|
+
// 加载能力并调用
|
|
28
|
+
const result = await capabilityClient.load('create_feishu_group').call('run', {
|
|
29
29
|
group_name: '项目讨论群',
|
|
30
30
|
members: ['user_001', 'user_002'],
|
|
31
31
|
});
|
|
@@ -33,37 +33,20 @@ const result = await client.call('create_feishu_group', 'run', {
|
|
|
33
33
|
console.log(result);
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
###
|
|
37
|
-
|
|
38
|
-
```typescript
|
|
39
|
-
import { client } from '@lark-apaas/client-capability';
|
|
40
|
-
|
|
41
|
-
// 手动初始化
|
|
42
|
-
await client.init();
|
|
43
|
-
|
|
44
|
-
// 检查能力是否存在
|
|
45
|
-
if (client.hasCapability('create_feishu_group')) {
|
|
46
|
-
const result = await client.call('create_feishu_group', 'run', params);
|
|
47
|
-
}
|
|
48
|
-
```
|
|
36
|
+
### 流式调用
|
|
49
37
|
|
|
50
|
-
|
|
38
|
+
用于 LLM 对话等流式输出场景:
|
|
51
39
|
|
|
52
40
|
```typescript
|
|
53
|
-
import {
|
|
54
|
-
|
|
55
|
-
await client.init();
|
|
41
|
+
import { capabilityClient } from '@lark-apaas/client-capability';
|
|
56
42
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
// [
|
|
61
|
-
// { id: 'create_feishu_group', name: '创建飞书群', ... },
|
|
62
|
-
// { id: 'send_message', name: '发送消息', ... },
|
|
63
|
-
// ]
|
|
43
|
+
const stream = capabilityClient.load('ai_chat').callStream<{ content: string }>('chat', {
|
|
44
|
+
message: 'hello',
|
|
45
|
+
});
|
|
64
46
|
|
|
65
|
-
|
|
66
|
-
|
|
47
|
+
for await (const chunk of stream) {
|
|
48
|
+
console.log(chunk.content);
|
|
49
|
+
}
|
|
67
50
|
```
|
|
68
51
|
|
|
69
52
|
### 自定义配置
|
|
@@ -72,31 +55,28 @@ const info = await client.getCapability('create_feishu_group');
|
|
|
72
55
|
import { createClient } from '@lark-apaas/client-capability';
|
|
73
56
|
|
|
74
57
|
const client = createClient({
|
|
75
|
-
baseURL: 'https://api.example.com',
|
|
76
58
|
fetchOptions: {
|
|
77
59
|
credentials: 'include',
|
|
78
60
|
headers: {
|
|
79
61
|
'X-Custom-Header': 'value',
|
|
80
62
|
},
|
|
81
63
|
},
|
|
82
|
-
autoInit: false,
|
|
83
64
|
});
|
|
84
65
|
|
|
85
|
-
await client.
|
|
86
|
-
const result = await client.call('xxx', 'run', params);
|
|
66
|
+
const result = await client.load('xxx').call('run', params);
|
|
87
67
|
```
|
|
88
68
|
|
|
89
69
|
### 错误处理
|
|
90
70
|
|
|
91
71
|
```typescript
|
|
92
72
|
import {
|
|
93
|
-
|
|
73
|
+
capabilityClient,
|
|
94
74
|
CapabilityNotFoundError,
|
|
95
75
|
ExecutionError
|
|
96
76
|
} from '@lark-apaas/client-capability';
|
|
97
77
|
|
|
98
78
|
try {
|
|
99
|
-
const result = await
|
|
79
|
+
const result = await capabilityClient.load('create_feishu_group').call('run', params);
|
|
100
80
|
} catch (error) {
|
|
101
81
|
if (error instanceof CapabilityNotFoundError) {
|
|
102
82
|
console.error('能力不存在:', error.message);
|
|
@@ -108,29 +88,13 @@ try {
|
|
|
108
88
|
}
|
|
109
89
|
```
|
|
110
90
|
|
|
111
|
-
###
|
|
112
|
-
|
|
113
|
-
用于 LLM 对话等流式输出场景:
|
|
91
|
+
### 流式调用错误处理
|
|
114
92
|
|
|
115
93
|
```typescript
|
|
116
|
-
import {
|
|
117
|
-
|
|
118
|
-
const stream = client.callStream<{ content: string }>('ai_chat', 'chat', {
|
|
119
|
-
message: 'hello',
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
for await (const chunk of stream) {
|
|
123
|
-
console.log(chunk.content);
|
|
124
|
-
}
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
流式调用错误处理:
|
|
128
|
-
|
|
129
|
-
```typescript
|
|
130
|
-
import { client, NetworkError, ExecutionError } from '@lark-apaas/client-capability';
|
|
94
|
+
import { capabilityClient, NetworkError, ExecutionError } from '@lark-apaas/client-capability';
|
|
131
95
|
|
|
132
96
|
try {
|
|
133
|
-
const stream =
|
|
97
|
+
const stream = capabilityClient.load('ai_chat').callStream('chat', { message: 'hello' });
|
|
134
98
|
for await (const chunk of stream) {
|
|
135
99
|
process(chunk);
|
|
136
100
|
}
|
|
@@ -149,34 +113,40 @@ try {
|
|
|
149
113
|
|
|
150
114
|
```typescript
|
|
151
115
|
class CapabilityClient {
|
|
152
|
-
|
|
153
|
-
|
|
116
|
+
/**
|
|
117
|
+
* 加载能力,返回执行器
|
|
118
|
+
* @param capabilityId - 能力 ID
|
|
119
|
+
* @returns 能力执行器
|
|
120
|
+
*/
|
|
121
|
+
load(capabilityId: string): CapabilityExecutor;
|
|
122
|
+
}
|
|
123
|
+
```
|
|
154
124
|
|
|
155
|
-
|
|
156
|
-
init(): Promise<void>;
|
|
125
|
+
### CapabilityExecutor
|
|
157
126
|
|
|
158
|
-
|
|
127
|
+
```typescript
|
|
128
|
+
interface CapabilityExecutor {
|
|
129
|
+
/**
|
|
130
|
+
* 调用能力
|
|
131
|
+
* @param action - Action 名称
|
|
132
|
+
* @param params - 输入参数
|
|
133
|
+
* @returns Action 执行结果
|
|
134
|
+
*/
|
|
159
135
|
call<T = unknown>(
|
|
160
|
-
capabilityId: string,
|
|
161
136
|
action: string,
|
|
162
137
|
params?: Record<string, unknown>
|
|
163
138
|
): Promise<T>;
|
|
164
139
|
|
|
165
|
-
|
|
140
|
+
/**
|
|
141
|
+
* 流式调用能力
|
|
142
|
+
* @param action - Action 名称
|
|
143
|
+
* @param params - 输入参数
|
|
144
|
+
* @returns AsyncIterable,逐个 yield chunk
|
|
145
|
+
*/
|
|
166
146
|
callStream<T = unknown>(
|
|
167
|
-
capabilityId: string,
|
|
168
147
|
action: string,
|
|
169
148
|
params?: Record<string, unknown>
|
|
170
149
|
): AsyncIterable<T>;
|
|
171
|
-
|
|
172
|
-
// 检查能力是否存在
|
|
173
|
-
hasCapability(capabilityId: string): boolean;
|
|
174
|
-
|
|
175
|
-
// 获取所有可用能力
|
|
176
|
-
listCapabilities(): Promise<CapabilityInfo[]>;
|
|
177
|
-
|
|
178
|
-
// 获取单个能力信息
|
|
179
|
-
getCapability(capabilityId: string): Promise<CapabilityInfo | null>;
|
|
180
150
|
}
|
|
181
151
|
```
|
|
182
152
|
|
|
@@ -184,26 +154,8 @@ class CapabilityClient {
|
|
|
184
154
|
|
|
185
155
|
```typescript
|
|
186
156
|
interface CapabilityClientOptions {
|
|
187
|
-
|
|
188
|
-
baseURL?: string;
|
|
189
|
-
|
|
190
|
-
// 自定义 fetch 配置
|
|
157
|
+
/** 自定义 fetch 配置 */
|
|
191
158
|
fetchOptions?: RequestInit;
|
|
192
|
-
|
|
193
|
-
// 是否在创建时自动初始化,默认 true
|
|
194
|
-
autoInit?: boolean;
|
|
195
|
-
}
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
### CapabilityInfo
|
|
199
|
-
|
|
200
|
-
```typescript
|
|
201
|
-
interface CapabilityInfo {
|
|
202
|
-
id: string; // 能力 ID
|
|
203
|
-
name: string; // 能力名称
|
|
204
|
-
description: string; // 能力描述
|
|
205
|
-
pluginID: string; // 关联的插件 ID
|
|
206
|
-
pluginVersion: string; // 关联的插件版本
|
|
207
159
|
}
|
|
208
160
|
```
|
|
209
161
|
|
|
@@ -212,7 +164,6 @@ interface CapabilityInfo {
|
|
|
212
164
|
| 错误类型 | 错误码 | 描述 |
|
|
213
165
|
|---------|--------|------|
|
|
214
166
|
| `CapabilityError` | - | 错误基类 |
|
|
215
|
-
| `ClientNotInitializedError` | CLIENT_NOT_INITIALIZED | 客户端未初始化 |
|
|
216
167
|
| `CapabilityNotFoundError` | CAPABILITY_NOT_FOUND | 能力不存在 |
|
|
217
168
|
| `ActionNotFoundError` | ACTION_NOT_FOUND | Action 不存在 |
|
|
218
169
|
| `NetworkError` | NETWORK_ERROR | 网络错误 |
|
|
@@ -222,18 +173,17 @@ interface CapabilityInfo {
|
|
|
222
173
|
|
|
223
174
|
```typescript
|
|
224
175
|
// 默认客户端实例
|
|
225
|
-
export {
|
|
176
|
+
export { capabilityClient } from '@lark-apaas/client-capability';
|
|
226
177
|
|
|
227
178
|
// 创建自定义客户端
|
|
228
179
|
export { createClient, CapabilityClient } from '@lark-apaas/client-capability';
|
|
229
180
|
|
|
230
181
|
// 类型
|
|
231
|
-
export type { CapabilityClientOptions,
|
|
182
|
+
export type { CapabilityClientOptions, CapabilityExecutor } from '@lark-apaas/client-capability';
|
|
232
183
|
|
|
233
184
|
// 错误类型
|
|
234
185
|
export {
|
|
235
186
|
CapabilityError,
|
|
236
|
-
ClientNotInitializedError,
|
|
237
187
|
CapabilityNotFoundError,
|
|
238
188
|
ActionNotFoundError,
|
|
239
189
|
NetworkError,
|
|
@@ -241,6 +191,20 @@ export {
|
|
|
241
191
|
} from '@lark-apaas/client-capability';
|
|
242
192
|
```
|
|
243
193
|
|
|
194
|
+
## 与服务端 API 对比
|
|
195
|
+
|
|
196
|
+
客户端与服务端使用一致的链式调用风格:
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
// 客户端
|
|
200
|
+
import { capabilityClient } from '@lark-apaas/client-capability';
|
|
201
|
+
const result = await capabilityClient.load('xxx').call('run', params);
|
|
202
|
+
|
|
203
|
+
// 服务端
|
|
204
|
+
import { CapabilityService } from '@lark-apaas/nestjs-capability';
|
|
205
|
+
const result = await capabilityService.load('xxx').call('run', params);
|
|
206
|
+
```
|
|
207
|
+
|
|
244
208
|
## 许可证
|
|
245
209
|
|
|
246
210
|
MIT
|
package/dist/index.cjs
CHANGED
|
@@ -27,14 +27,23 @@ __export(index_exports, {
|
|
|
27
27
|
CapabilityClient: () => CapabilityClient,
|
|
28
28
|
CapabilityError: () => CapabilityError,
|
|
29
29
|
CapabilityNotFoundError: () => CapabilityNotFoundError,
|
|
30
|
-
ClientNotInitializedError: () => ClientNotInitializedError,
|
|
31
30
|
ExecutionError: () => ExecutionError,
|
|
32
31
|
NetworkError: () => NetworkError,
|
|
33
|
-
|
|
32
|
+
capabilityClient: () => capabilityClient,
|
|
34
33
|
createClient: () => createClient
|
|
35
34
|
});
|
|
36
35
|
module.exports = __toCommonJS(index_exports);
|
|
37
36
|
|
|
37
|
+
// src/types.ts
|
|
38
|
+
var ErrorCodes = {
|
|
39
|
+
SUCCESS: "0",
|
|
40
|
+
CAPABILITY_NOT_FOUND: "k_ec_cap_001",
|
|
41
|
+
PLUGIN_NOT_FOUND: "k_ec_cap_002",
|
|
42
|
+
ACTION_NOT_FOUND: "k_ec_cap_003",
|
|
43
|
+
PARAMS_VALIDATION_ERROR: "k_ec_cap_004",
|
|
44
|
+
EXECUTION_ERROR: "k_ec_cap_005"
|
|
45
|
+
};
|
|
46
|
+
|
|
38
47
|
// src/errors.ts
|
|
39
48
|
var _CapabilityError = class _CapabilityError extends Error {
|
|
40
49
|
constructor(message, code, statusCode) {
|
|
@@ -50,14 +59,6 @@ var _CapabilityError = class _CapabilityError extends Error {
|
|
|
50
59
|
};
|
|
51
60
|
__name(_CapabilityError, "CapabilityError");
|
|
52
61
|
var CapabilityError = _CapabilityError;
|
|
53
|
-
var _ClientNotInitializedError = class _ClientNotInitializedError extends CapabilityError {
|
|
54
|
-
constructor() {
|
|
55
|
-
super("Client not initialized. Call init() first or enable autoInit.", "CLIENT_NOT_INITIALIZED");
|
|
56
|
-
this.name = "ClientNotInitializedError";
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
__name(_ClientNotInitializedError, "ClientNotInitializedError");
|
|
60
|
-
var ClientNotInitializedError = _ClientNotInitializedError;
|
|
61
62
|
var _CapabilityNotFoundError = class _CapabilityNotFoundError extends CapabilityError {
|
|
62
63
|
constructor(capabilityId, statusCode) {
|
|
63
64
|
super(`Capability not found: ${capabilityId}`, "CAPABILITY_NOT_FOUND", statusCode);
|
|
@@ -92,103 +93,38 @@ __name(_ExecutionError, "ExecutionError");
|
|
|
92
93
|
var ExecutionError = _ExecutionError;
|
|
93
94
|
|
|
94
95
|
// src/client.ts
|
|
95
|
-
var DEFAULT_OPTIONS = {
|
|
96
|
-
baseURL: "",
|
|
97
|
-
fetchOptions: {},
|
|
98
|
-
autoInit: true
|
|
99
|
-
};
|
|
100
96
|
var _CapabilityClient = class _CapabilityClient {
|
|
101
97
|
constructor(options) {
|
|
102
98
|
__publicField(this, "options");
|
|
103
|
-
|
|
104
|
-
__publicField(this, "_initialized", false);
|
|
105
|
-
__publicField(this, "initPromise", null);
|
|
106
|
-
this.options = {
|
|
107
|
-
...DEFAULT_OPTIONS,
|
|
108
|
-
...options
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* 是否已初始化
|
|
113
|
-
*/
|
|
114
|
-
get initialized() {
|
|
115
|
-
return this._initialized;
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* 初始化客户端,获取能力列表
|
|
119
|
-
*/
|
|
120
|
-
async init() {
|
|
121
|
-
if (this._initialized) {
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
if (this.initPromise) {
|
|
125
|
-
return this.initPromise;
|
|
126
|
-
}
|
|
127
|
-
this.initPromise = this.doInit();
|
|
128
|
-
try {
|
|
129
|
-
await this.initPromise;
|
|
130
|
-
} finally {
|
|
131
|
-
this.initPromise = null;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
async doInit() {
|
|
135
|
-
const url = `${this.options.baseURL}/api/capability/list`;
|
|
136
|
-
try {
|
|
137
|
-
const response = await fetch(url, {
|
|
138
|
-
method: "GET",
|
|
139
|
-
...this.options.fetchOptions,
|
|
140
|
-
headers: {
|
|
141
|
-
"Content-Type": "application/json",
|
|
142
|
-
...this.options.fetchOptions.headers
|
|
143
|
-
}
|
|
144
|
-
});
|
|
145
|
-
if (!response.ok) {
|
|
146
|
-
throw new NetworkError(`Failed to fetch capabilities: ${response.status} ${response.statusText}`);
|
|
147
|
-
}
|
|
148
|
-
const data = await response.json();
|
|
149
|
-
if (data.code !== 0) {
|
|
150
|
-
throw new ExecutionError(data.message);
|
|
151
|
-
}
|
|
152
|
-
this.capabilities.clear();
|
|
153
|
-
for (const capability of data.data) {
|
|
154
|
-
this.capabilities.set(capability.id, capability);
|
|
155
|
-
}
|
|
156
|
-
this._initialized = true;
|
|
157
|
-
} catch (error) {
|
|
158
|
-
if (error instanceof CapabilityError) {
|
|
159
|
-
throw error;
|
|
160
|
-
}
|
|
161
|
-
throw new NetworkError(error instanceof Error ? error.message : String(error));
|
|
162
|
-
}
|
|
99
|
+
this.options = options ?? {};
|
|
163
100
|
}
|
|
164
101
|
/**
|
|
165
|
-
*
|
|
166
|
-
*/
|
|
167
|
-
async ensureInitialized() {
|
|
168
|
-
if (!this._initialized && this.options.autoInit) {
|
|
169
|
-
await this.init();
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
/**
|
|
173
|
-
* 调用能力
|
|
102
|
+
* 加载能力,返回执行器
|
|
174
103
|
* @param capabilityId - 能力 ID
|
|
175
|
-
* @
|
|
176
|
-
* @param params - 输入参数
|
|
177
|
-
* @returns Action 执行结果
|
|
104
|
+
* @returns 能力执行器
|
|
178
105
|
*/
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
106
|
+
load(capabilityId) {
|
|
107
|
+
return this.createExecutor(capabilityId);
|
|
108
|
+
}
|
|
109
|
+
createExecutor(capabilityId) {
|
|
110
|
+
return {
|
|
111
|
+
call: /* @__PURE__ */ __name((action, params) => {
|
|
112
|
+
return this.executeCall(capabilityId, action, params);
|
|
113
|
+
}, "call"),
|
|
114
|
+
callStream: /* @__PURE__ */ __name((action, params) => {
|
|
115
|
+
return this.executeCallStream(capabilityId, action, params);
|
|
116
|
+
}, "callStream")
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
async executeCall(capabilityId, action, params) {
|
|
120
|
+
const url = `/api/capability/${capabilityId}`;
|
|
185
121
|
try {
|
|
186
122
|
const response = await fetch(url, {
|
|
187
123
|
method: "POST",
|
|
188
124
|
...this.options.fetchOptions,
|
|
189
125
|
headers: {
|
|
190
126
|
"Content-Type": "application/json",
|
|
191
|
-
...this.options.fetchOptions
|
|
127
|
+
...this.options.fetchOptions?.headers
|
|
192
128
|
},
|
|
193
129
|
body: JSON.stringify({
|
|
194
130
|
action,
|
|
@@ -196,21 +132,21 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
196
132
|
})
|
|
197
133
|
});
|
|
198
134
|
const data = await response.json();
|
|
199
|
-
if (!response.ok || data.
|
|
135
|
+
if (!response.ok || data.status_code !== ErrorCodes.SUCCESS) {
|
|
200
136
|
const errorResponse = data;
|
|
201
|
-
const errorCode = errorResponse.
|
|
137
|
+
const errorCode = errorResponse.status_code;
|
|
202
138
|
switch (errorCode) {
|
|
203
|
-
case
|
|
139
|
+
case ErrorCodes.CAPABILITY_NOT_FOUND:
|
|
204
140
|
throw new CapabilityNotFoundError(capabilityId, response.status);
|
|
205
|
-
case
|
|
206
|
-
throw new ActionNotFoundError(errorResponse.
|
|
207
|
-
case
|
|
208
|
-
case
|
|
141
|
+
case ErrorCodes.ACTION_NOT_FOUND:
|
|
142
|
+
throw new ActionNotFoundError(errorResponse.error_msg, response.status);
|
|
143
|
+
case ErrorCodes.PLUGIN_NOT_FOUND:
|
|
144
|
+
case ErrorCodes.EXECUTION_ERROR:
|
|
209
145
|
default:
|
|
210
|
-
throw new ExecutionError(errorResponse.
|
|
146
|
+
throw new ExecutionError(errorResponse.error_msg, response.status);
|
|
211
147
|
}
|
|
212
148
|
}
|
|
213
|
-
return data.data;
|
|
149
|
+
return data.data.output;
|
|
214
150
|
} catch (error) {
|
|
215
151
|
if (error instanceof CapabilityError) {
|
|
216
152
|
throw error;
|
|
@@ -218,39 +154,8 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
218
154
|
throw new NetworkError(error instanceof Error ? error.message : String(error));
|
|
219
155
|
}
|
|
220
156
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
*/
|
|
224
|
-
hasCapability(capabilityId) {
|
|
225
|
-
return this.capabilities.has(capabilityId);
|
|
226
|
-
}
|
|
227
|
-
/**
|
|
228
|
-
* 获取所有可用能力
|
|
229
|
-
*/
|
|
230
|
-
async listCapabilities() {
|
|
231
|
-
await this.ensureInitialized();
|
|
232
|
-
return Array.from(this.capabilities.values());
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* 获取单个能力信息
|
|
236
|
-
*/
|
|
237
|
-
async getCapability(capabilityId) {
|
|
238
|
-
await this.ensureInitialized();
|
|
239
|
-
return this.capabilities.get(capabilityId) ?? null;
|
|
240
|
-
}
|
|
241
|
-
/**
|
|
242
|
-
* 流式调用能力
|
|
243
|
-
* @param capabilityId - 能力 ID
|
|
244
|
-
* @param action - Action 名称
|
|
245
|
-
* @param params - 输入参数
|
|
246
|
-
* @returns AsyncIterable,逐个 yield chunk
|
|
247
|
-
*/
|
|
248
|
-
async *callStream(capabilityId, action, params) {
|
|
249
|
-
await this.ensureInitialized();
|
|
250
|
-
if (this._initialized && !this.capabilities.has(capabilityId)) {
|
|
251
|
-
throw new CapabilityNotFoundError(capabilityId);
|
|
252
|
-
}
|
|
253
|
-
const url = `${this.options.baseURL}/api/capability/${capabilityId}/stream`;
|
|
157
|
+
async *executeCallStream(capabilityId, action, params) {
|
|
158
|
+
const url = `/api/capability/${capabilityId}/stream`;
|
|
254
159
|
let response;
|
|
255
160
|
try {
|
|
256
161
|
response = await fetch(url, {
|
|
@@ -258,7 +163,7 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
258
163
|
...this.options.fetchOptions,
|
|
259
164
|
headers: {
|
|
260
165
|
"Content-Type": "application/json",
|
|
261
|
-
...this.options.fetchOptions
|
|
166
|
+
...this.options.fetchOptions?.headers
|
|
262
167
|
},
|
|
263
168
|
body: JSON.stringify({
|
|
264
169
|
action,
|
|
@@ -289,23 +194,18 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
289
194
|
for (const line of lines) {
|
|
290
195
|
if (line.startsWith("data: ")) {
|
|
291
196
|
const data = line.slice(6);
|
|
292
|
-
if (data === "[DONE]") {
|
|
293
|
-
return;
|
|
294
|
-
}
|
|
295
197
|
try {
|
|
296
198
|
const parsed = JSON.parse(data);
|
|
297
|
-
if (parsed.
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
throw new ExecutionError(parsed.error);
|
|
199
|
+
if (parsed.status_code === ErrorCodes.SUCCESS && parsed.data) {
|
|
200
|
+
if (parsed.data.type === "content") {
|
|
201
|
+
yield parsed.data.delta.content;
|
|
202
|
+
if (parsed.data.finished) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
} else if (parsed.data.type === "error") {
|
|
206
|
+
throw new ExecutionError(parsed.data.error.message);
|
|
306
207
|
}
|
|
307
208
|
}
|
|
308
|
-
yield parsed;
|
|
309
209
|
} catch (parseError) {
|
|
310
210
|
if (parseError instanceof CapabilityError) {
|
|
311
211
|
throw parseError;
|
|
@@ -330,5 +230,5 @@ function createClient(options) {
|
|
|
330
230
|
return new CapabilityClient(options);
|
|
331
231
|
}
|
|
332
232
|
__name(createClient, "createClient");
|
|
333
|
-
var
|
|
233
|
+
var capabilityClient = new CapabilityClient();
|
|
334
234
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/client.ts"],"sourcesContent":["// 默认客户端实例\nexport { client, createClient, CapabilityClient } from './client';\n\n// 类型\nexport type { CapabilityClientOptions, CapabilityInfo } from './types';\n\n// 错误类型\nexport {\n CapabilityError,\n ClientNotInitializedError,\n CapabilityNotFoundError,\n ActionNotFoundError,\n NetworkError,\n ExecutionError,\n} from './errors';\n","/**\n * 能力调用错误基类\n */\nexport class CapabilityError extends Error {\n /** 错误码 */\n code: string;\n /** HTTP 状态码 */\n statusCode?: number;\n\n constructor(message: string, code: string, statusCode?: number) {\n super(message);\n this.name = 'CapabilityError';\n this.code = code;\n this.statusCode = statusCode;\n }\n}\n\n/**\n * 客户端未初始化错误\n */\nexport class ClientNotInitializedError extends CapabilityError {\n constructor() {\n super('Client not initialized. Call init() first or enable autoInit.', 'CLIENT_NOT_INITIALIZED');\n this.name = 'ClientNotInitializedError';\n }\n}\n\n/**\n * 能力不存在错误\n */\nexport class CapabilityNotFoundError extends CapabilityError {\n constructor(capabilityId: string, statusCode?: number) {\n super(`Capability not found: ${capabilityId}`, 'CAPABILITY_NOT_FOUND', statusCode);\n this.name = 'CapabilityNotFoundError';\n }\n}\n\n/**\n * Action 不存在错误\n */\nexport class ActionNotFoundError extends CapabilityError {\n constructor(message: string, statusCode?: number) {\n super(message, 'ACTION_NOT_FOUND', statusCode);\n this.name = 'ActionNotFoundError';\n }\n}\n\n/**\n * 网络错误\n */\nexport class NetworkError extends CapabilityError {\n constructor(message: string) {\n super(message, 'NETWORK_ERROR');\n this.name = 'NetworkError';\n }\n}\n\n/**\n * 执行错误\n */\nexport class ExecutionError extends CapabilityError {\n constructor(message: string, statusCode?: number) {\n super(message, 'EXECUTION_ERROR', statusCode);\n this.name = 'ExecutionError';\n }\n}\n","import type { CapabilityClientOptions, CapabilityInfo, ApiResponse } from './types';\nimport {\n CapabilityError,\n CapabilityNotFoundError,\n ActionNotFoundError,\n NetworkError,\n ExecutionError,\n} from './errors';\n\nconst DEFAULT_OPTIONS: Required<CapabilityClientOptions> = {\n baseURL: '',\n fetchOptions: {},\n autoInit: true,\n};\n\n/**\n * 能力客户端\n */\nexport class CapabilityClient {\n private options: Required<CapabilityClientOptions>;\n private capabilities: Map<string, CapabilityInfo> = new Map();\n private _initialized = false;\n private initPromise: Promise<void> | null = null;\n\n /**\n * 是否已初始化\n */\n get initialized(): boolean {\n return this._initialized;\n }\n\n constructor(options?: CapabilityClientOptions) {\n this.options = { ...DEFAULT_OPTIONS, ...options };\n }\n\n /**\n * 初始化客户端,获取能力列表\n */\n async init(): Promise<void> {\n if (this._initialized) {\n return;\n }\n\n // 防止并发初始化\n if (this.initPromise) {\n return this.initPromise;\n }\n\n this.initPromise = this.doInit();\n try {\n await this.initPromise;\n } finally {\n this.initPromise = null;\n }\n }\n\n private async doInit(): Promise<void> {\n const url = `${this.options.baseURL}/api/capability/list`;\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n ...this.options.fetchOptions,\n headers: {\n 'Content-Type': 'application/json',\n ...this.options.fetchOptions.headers,\n },\n });\n\n if (!response.ok) {\n throw new NetworkError(`Failed to fetch capabilities: ${response.status} ${response.statusText}`);\n }\n\n const data = (await response.json()) as ApiResponse<CapabilityInfo[]>;\n\n if (data.code !== 0) {\n throw new ExecutionError((data as { message: string }).message);\n }\n\n this.capabilities.clear();\n for (const capability of (data as { data: CapabilityInfo[] }).data) {\n this.capabilities.set(capability.id, capability);\n }\n\n this._initialized = true;\n } catch (error) {\n if (error instanceof CapabilityError) {\n throw error;\n }\n throw new NetworkError(error instanceof Error ? error.message : String(error));\n }\n }\n\n /**\n * 确保已初始化\n */\n private async ensureInitialized(): Promise<void> {\n if (!this._initialized && this.options.autoInit) {\n await this.init();\n }\n }\n\n /**\n * 调用能力\n * @param capabilityId - 能力 ID\n * @param action - Action 名称\n * @param params - 输入参数\n * @returns Action 执行结果\n */\n async call<T = unknown>(\n capabilityId: string,\n action: string,\n params?: Record<string, unknown>\n ): Promise<T> {\n await this.ensureInitialized();\n\n // 检查能力是否存在(如果已初始化)\n if (this._initialized && !this.capabilities.has(capabilityId)) {\n throw new CapabilityNotFoundError(capabilityId);\n }\n\n const url = `${this.options.baseURL}/api/capability/${capabilityId}`;\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n ...this.options.fetchOptions,\n headers: {\n 'Content-Type': 'application/json',\n ...this.options.fetchOptions.headers,\n },\n body: JSON.stringify({\n action,\n params: params ?? {},\n }),\n });\n\n const data = (await response.json()) as ApiResponse<T>;\n\n if (!response.ok || data.code !== 0) {\n const errorResponse = data as { code: number; message: string; error?: string };\n const errorCode = errorResponse.error ?? 'UNKNOWN_ERROR';\n\n switch (errorCode) {\n case 'CAPABILITY_NOT_FOUND':\n throw new CapabilityNotFoundError(capabilityId, response.status);\n case 'ACTION_NOT_FOUND':\n throw new ActionNotFoundError(errorResponse.message, response.status);\n case 'PLUGIN_NOT_FOUND':\n case 'EXECUTION_ERROR':\n default:\n throw new ExecutionError(errorResponse.message, response.status);\n }\n }\n\n return (data as { data: T }).data;\n } catch (error) {\n if (error instanceof CapabilityError) {\n throw error;\n }\n throw new NetworkError(error instanceof Error ? error.message : String(error));\n }\n }\n\n /**\n * 检查能力是否存在\n */\n hasCapability(capabilityId: string): boolean {\n return this.capabilities.has(capabilityId);\n }\n\n /**\n * 获取所有可用能力\n */\n async listCapabilities(): Promise<CapabilityInfo[]> {\n await this.ensureInitialized();\n return Array.from(this.capabilities.values());\n }\n\n /**\n * 获取单个能力信息\n */\n async getCapability(capabilityId: string): Promise<CapabilityInfo | null> {\n await this.ensureInitialized();\n return this.capabilities.get(capabilityId) ?? null;\n }\n\n /**\n * 流式调用能力\n * @param capabilityId - 能力 ID\n * @param action - Action 名称\n * @param params - 输入参数\n * @returns AsyncIterable,逐个 yield chunk\n */\n async *callStream<T = unknown>(\n capabilityId: string,\n action: string,\n params?: Record<string, unknown>\n ): AsyncIterable<T> {\n await this.ensureInitialized();\n\n // 检查能力是否存在(如果已初始化)\n if (this._initialized && !this.capabilities.has(capabilityId)) {\n throw new CapabilityNotFoundError(capabilityId);\n }\n\n const url = `${this.options.baseURL}/api/capability/${capabilityId}/stream`;\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: 'POST',\n ...this.options.fetchOptions,\n headers: {\n 'Content-Type': 'application/json',\n ...this.options.fetchOptions.headers,\n },\n body: JSON.stringify({\n action,\n params: params ?? {},\n }),\n });\n } catch (error) {\n throw new NetworkError(error instanceof Error ? error.message : String(error));\n }\n\n if (!response.ok) {\n throw new NetworkError(`HTTP ${response.status} ${response.statusText}`);\n }\n\n if (!response.body) {\n throw new NetworkError('Response body is null');\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n const data = line.slice(6);\n\n // 流结束标记\n if (data === '[DONE]') {\n return;\n }\n\n try {\n const parsed = JSON.parse(data) as { error?: string; code?: string } & T;\n\n // 服务端错误\n if (parsed.error) {\n const errorCode = parsed.code ?? 'EXECUTION_ERROR';\n switch (errorCode) {\n case 'CAPABILITY_NOT_FOUND':\n throw new CapabilityNotFoundError(capabilityId);\n case 'ACTION_NOT_FOUND':\n throw new ActionNotFoundError(parsed.error);\n default:\n throw new ExecutionError(parsed.error);\n }\n }\n\n yield parsed as T;\n } catch (parseError) {\n // JSON 解析错误,跳过此行\n if (parseError instanceof CapabilityError) {\n throw parseError;\n }\n // 忽略非 JSON 行\n }\n }\n }\n }\n } catch (error) {\n if (error instanceof CapabilityError) {\n throw error;\n }\n throw new NetworkError(error instanceof Error ? error.message : String(error));\n } finally {\n reader.releaseLock();\n }\n }\n}\n\n/**\n * 创建自定义客户端\n */\nexport function createClient(options?: CapabilityClientOptions): CapabilityClient {\n return new CapabilityClient(options);\n}\n\n/**\n * 默认客户端实例\n */\nexport const client = new CapabilityClient();\n"],"mappings":"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","names":["CapabilityError","Error","message","code","statusCode","name","ClientNotInitializedError","CapabilityNotFoundError","capabilityId","ActionNotFoundError","NetworkError","ExecutionError","DEFAULT_OPTIONS","baseURL","fetchOptions","autoInit","CapabilityClient","options","capabilities","Map","_initialized","initPromise","initialized","init","doInit","url","response","fetch","method","headers","ok","NetworkError","status","statusText","data","json","code","ExecutionError","message","clear","capability","set","id","error","CapabilityError","Error","String","ensureInitialized","call","capabilityId","action","params","has","CapabilityNotFoundError","body","JSON","stringify","errorResponse","errorCode","ActionNotFoundError","hasCapability","listCapabilities","Array","from","values","getCapability","get","callStream","reader","getReader","decoder","TextDecoder","buffer","done","value","read","decode","stream","lines","split","pop","line","startsWith","slice","parsed","parse","parseError","releaseLock","createClient","client"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/types.ts","../src/errors.ts","../src/client.ts"],"sourcesContent":["// 默认客户端实例\nexport { capabilityClient, createClient, CapabilityClient } from './client';\n\n// 类型\nexport type { CapabilityClientOptions, CapabilityExecutor } from './types';\n\n// 错误类型\nexport {\n CapabilityError,\n CapabilityNotFoundError,\n ActionNotFoundError,\n NetworkError,\n ExecutionError,\n} from './errors';\n","/**\n * 客户端配置选项\n */\nexport interface CapabilityClientOptions {\n /** 自定义 fetch 配置 */\n fetchOptions?: RequestInit;\n}\n\n/**\n * 能力执行器接口\n */\nexport interface CapabilityExecutor {\n /**\n * 调用能力\n * @param action - Action 名称\n * @param params - 输入参数\n * @returns Action 执行结果\n */\n call<T = unknown>(\n action: string,\n params?: Record<string, unknown>\n ): Promise<T>;\n\n /**\n * 流式调用能力\n * @param action - Action 名称\n * @param params - 输入参数\n * @returns AsyncIterable,逐个 yield chunk\n */\n callStream<T = unknown>(\n action: string,\n params?: Record<string, unknown>\n ): AsyncIterable<T>;\n}\n\n// ========== API 响应类型 ==========\n\n/**\n * 成功响应\n */\nexport interface SuccessResponse<T> {\n status_code: '0';\n data: T;\n}\n\n/**\n * 错误响应\n */\nexport interface ErrorResponse {\n status_code: string;\n error_msg: string;\n}\n\n/**\n * API 响应类型\n */\nexport type ApiResponse<T> = SuccessResponse<T> | ErrorResponse;\n\n// ========== 具体响应 data 结构 ==========\n\n/**\n * 执行接口响应 data 结构\n */\nexport interface ExecuteResponseData {\n output: unknown;\n}\n\n// ========== 流式响应结构 ==========\n\n/**\n * 流式内容响应\n */\nexport interface StreamContentResponse {\n status_code: '0';\n data: {\n type: 'content';\n delta: {\n content: unknown;\n };\n finished?: boolean;\n };\n}\n\n/**\n * 流式错误响应\n */\nexport interface StreamErrorResponse {\n status_code: '0';\n data: {\n type: 'error';\n error: {\n code: number;\n message: string;\n };\n };\n}\n\n/**\n * 流式响应类型\n */\nexport type StreamResponse = StreamContentResponse | StreamErrorResponse;\n\n// ========== 错误码 ==========\n\n/**\n * 后端错误码\n */\nexport const ErrorCodes = {\n SUCCESS: '0',\n CAPABILITY_NOT_FOUND: 'k_ec_cap_001',\n PLUGIN_NOT_FOUND: 'k_ec_cap_002',\n ACTION_NOT_FOUND: 'k_ec_cap_003',\n PARAMS_VALIDATION_ERROR: 'k_ec_cap_004',\n EXECUTION_ERROR: 'k_ec_cap_005',\n} as const;\n","/**\n * 能力调用错误基类\n */\nexport class CapabilityError extends Error {\n /** 错误码 */\n code: string;\n /** HTTP 状态码 */\n statusCode?: number;\n\n constructor(message: string, code: string, statusCode?: number) {\n super(message);\n this.name = 'CapabilityError';\n this.code = code;\n this.statusCode = statusCode;\n }\n}\n\n/**\n * 能力不存在错误\n */\nexport class CapabilityNotFoundError extends CapabilityError {\n constructor(capabilityId: string, statusCode?: number) {\n super(`Capability not found: ${capabilityId}`, 'CAPABILITY_NOT_FOUND', statusCode);\n this.name = 'CapabilityNotFoundError';\n }\n}\n\n/**\n * Action 不存在错误\n */\nexport class ActionNotFoundError extends CapabilityError {\n constructor(message: string, statusCode?: number) {\n super(message, 'ACTION_NOT_FOUND', statusCode);\n this.name = 'ActionNotFoundError';\n }\n}\n\n/**\n * 网络错误\n */\nexport class NetworkError extends CapabilityError {\n constructor(message: string) {\n super(message, 'NETWORK_ERROR');\n this.name = 'NetworkError';\n }\n}\n\n/**\n * 执行错误\n */\nexport class ExecutionError extends CapabilityError {\n constructor(message: string, statusCode?: number) {\n super(message, 'EXECUTION_ERROR', statusCode);\n this.name = 'ExecutionError';\n }\n}\n","import type {\n CapabilityClientOptions,\n CapabilityExecutor,\n ApiResponse,\n ExecuteResponseData,\n StreamResponse,\n} from './types';\nimport { ErrorCodes } from './types';\nimport {\n CapabilityError,\n CapabilityNotFoundError,\n ActionNotFoundError,\n NetworkError,\n ExecutionError,\n} from './errors';\n\n/**\n * 能力客户端\n */\nexport class CapabilityClient {\n private options: CapabilityClientOptions;\n\n constructor(options?: CapabilityClientOptions) {\n this.options = options ?? {};\n }\n\n /**\n * 加载能力,返回执行器\n * @param capabilityId - 能力 ID\n * @returns 能力执行器\n */\n load(capabilityId: string): CapabilityExecutor {\n return this.createExecutor(capabilityId);\n }\n\n private createExecutor(capabilityId: string): CapabilityExecutor {\n return {\n call: <T = unknown>(action: string, params?: Record<string, unknown>) => {\n return this.executeCall<T>(capabilityId, action, params);\n },\n callStream: <T = unknown>(action: string, params?: Record<string, unknown>) => {\n return this.executeCallStream<T>(capabilityId, action, params);\n },\n };\n }\n\n private async executeCall<T>(\n capabilityId: string,\n action: string,\n params?: Record<string, unknown>\n ): Promise<T> {\n const url = `/api/capability/${capabilityId}`;\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n ...this.options.fetchOptions,\n headers: {\n 'Content-Type': 'application/json',\n ...this.options.fetchOptions?.headers,\n },\n body: JSON.stringify({\n action,\n params: params ?? {},\n }),\n });\n\n const data = (await response.json()) as ApiResponse<ExecuteResponseData>;\n\n if (!response.ok || data.status_code !== ErrorCodes.SUCCESS) {\n const errorResponse = data as { status_code: string; error_msg: string };\n const errorCode = errorResponse.status_code;\n\n switch (errorCode) {\n case ErrorCodes.CAPABILITY_NOT_FOUND:\n throw new CapabilityNotFoundError(capabilityId, response.status);\n case ErrorCodes.ACTION_NOT_FOUND:\n throw new ActionNotFoundError(errorResponse.error_msg, response.status);\n case ErrorCodes.PLUGIN_NOT_FOUND:\n case ErrorCodes.EXECUTION_ERROR:\n default:\n throw new ExecutionError(errorResponse.error_msg, response.status);\n }\n }\n\n return (data as { data: ExecuteResponseData }).data.output as T;\n } catch (error) {\n if (error instanceof CapabilityError) {\n throw error;\n }\n throw new NetworkError(error instanceof Error ? error.message : String(error));\n }\n }\n\n private async *executeCallStream<T>(\n capabilityId: string,\n action: string,\n params?: Record<string, unknown>\n ): AsyncIterable<T> {\n const url = `/api/capability/${capabilityId}/stream`;\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: 'POST',\n ...this.options.fetchOptions,\n headers: {\n 'Content-Type': 'application/json',\n ...this.options.fetchOptions?.headers,\n },\n body: JSON.stringify({\n action,\n params: params ?? {},\n }),\n });\n } catch (error) {\n throw new NetworkError(error instanceof Error ? error.message : String(error));\n }\n\n if (!response.ok) {\n throw new NetworkError(`HTTP ${response.status} ${response.statusText}`);\n }\n\n if (!response.body) {\n throw new NetworkError('Response body is null');\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n const data = line.slice(6);\n\n try {\n const parsed = JSON.parse(data) as StreamResponse;\n\n if (parsed.status_code === ErrorCodes.SUCCESS && parsed.data) {\n if (parsed.data.type === 'content') {\n yield parsed.data.delta.content as T;\n\n if (parsed.data.finished) {\n return;\n }\n } else if (parsed.data.type === 'error') {\n throw new ExecutionError(parsed.data.error.message);\n }\n }\n } catch (parseError) {\n if (parseError instanceof CapabilityError) {\n throw parseError;\n }\n // 忽略非 JSON 行\n }\n }\n }\n }\n } catch (error) {\n if (error instanceof CapabilityError) {\n throw error;\n }\n throw new NetworkError(error instanceof Error ? error.message : String(error));\n } finally {\n reader.releaseLock();\n }\n }\n}\n\n/**\n * 创建自定义客户端\n */\nexport function createClient(options?: CapabilityClientOptions): CapabilityClient {\n return new CapabilityClient(options);\n}\n\n/**\n * 默认客户端实例\n */\nexport const capabilityClient = new CapabilityClient();\n"],"mappings":"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","names":["ErrorCodes","SUCCESS","CAPABILITY_NOT_FOUND","PLUGIN_NOT_FOUND","ACTION_NOT_FOUND","PARAMS_VALIDATION_ERROR","EXECUTION_ERROR","CapabilityError","Error","message","code","statusCode","name","CapabilityNotFoundError","capabilityId","ActionNotFoundError","NetworkError","ExecutionError","CapabilityClient","options","load","capabilityId","createExecutor","call","action","params","executeCall","callStream","executeCallStream","url","response","fetch","method","fetchOptions","headers","body","JSON","stringify","data","json","ok","status_code","ErrorCodes","SUCCESS","errorResponse","errorCode","CAPABILITY_NOT_FOUND","CapabilityNotFoundError","status","ACTION_NOT_FOUND","ActionNotFoundError","error_msg","PLUGIN_NOT_FOUND","EXECUTION_ERROR","ExecutionError","output","error","CapabilityError","NetworkError","Error","message","String","statusText","reader","getReader","decoder","TextDecoder","buffer","done","value","read","decode","stream","lines","split","pop","line","startsWith","slice","parsed","parse","type","delta","content","finished","parseError","releaseLock","createClient","capabilityClient"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -2,74 +2,44 @@
|
|
|
2
2
|
* 客户端配置选项
|
|
3
3
|
*/
|
|
4
4
|
interface CapabilityClientOptions {
|
|
5
|
-
/** API 基础路径,默认 '' (相对路径) */
|
|
6
|
-
baseURL?: string;
|
|
7
5
|
/** 自定义 fetch 配置 */
|
|
8
6
|
fetchOptions?: RequestInit;
|
|
9
|
-
/** 是否在创建时自动初始化,默认 true */
|
|
10
|
-
autoInit?: boolean;
|
|
11
7
|
}
|
|
12
8
|
/**
|
|
13
|
-
*
|
|
9
|
+
* 能力执行器接口
|
|
14
10
|
*/
|
|
15
|
-
interface
|
|
16
|
-
id: string;
|
|
17
|
-
name: string;
|
|
18
|
-
description: string;
|
|
19
|
-
pluginID: string;
|
|
20
|
-
pluginVersion: string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* 能力客户端
|
|
25
|
-
*/
|
|
26
|
-
declare class CapabilityClient {
|
|
27
|
-
private options;
|
|
28
|
-
private capabilities;
|
|
29
|
-
private _initialized;
|
|
30
|
-
private initPromise;
|
|
31
|
-
/**
|
|
32
|
-
* 是否已初始化
|
|
33
|
-
*/
|
|
34
|
-
get initialized(): boolean;
|
|
35
|
-
constructor(options?: CapabilityClientOptions);
|
|
36
|
-
/**
|
|
37
|
-
* 初始化客户端,获取能力列表
|
|
38
|
-
*/
|
|
39
|
-
init(): Promise<void>;
|
|
40
|
-
private doInit;
|
|
41
|
-
/**
|
|
42
|
-
* 确保已初始化
|
|
43
|
-
*/
|
|
44
|
-
private ensureInitialized;
|
|
11
|
+
interface CapabilityExecutor {
|
|
45
12
|
/**
|
|
46
13
|
* 调用能力
|
|
47
|
-
* @param capabilityId - 能力 ID
|
|
48
14
|
* @param action - Action 名称
|
|
49
15
|
* @param params - 输入参数
|
|
50
16
|
* @returns Action 执行结果
|
|
51
17
|
*/
|
|
52
|
-
call<T = unknown>(
|
|
53
|
-
/**
|
|
54
|
-
* 检查能力是否存在
|
|
55
|
-
*/
|
|
56
|
-
hasCapability(capabilityId: string): boolean;
|
|
57
|
-
/**
|
|
58
|
-
* 获取所有可用能力
|
|
59
|
-
*/
|
|
60
|
-
listCapabilities(): Promise<CapabilityInfo[]>;
|
|
61
|
-
/**
|
|
62
|
-
* 获取单个能力信息
|
|
63
|
-
*/
|
|
64
|
-
getCapability(capabilityId: string): Promise<CapabilityInfo | null>;
|
|
18
|
+
call<T = unknown>(action: string, params?: Record<string, unknown>): Promise<T>;
|
|
65
19
|
/**
|
|
66
20
|
* 流式调用能力
|
|
67
|
-
* @param capabilityId - 能力 ID
|
|
68
21
|
* @param action - Action 名称
|
|
69
22
|
* @param params - 输入参数
|
|
70
23
|
* @returns AsyncIterable,逐个 yield chunk
|
|
71
24
|
*/
|
|
72
|
-
callStream<T = unknown>(
|
|
25
|
+
callStream<T = unknown>(action: string, params?: Record<string, unknown>): AsyncIterable<T>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* 能力客户端
|
|
30
|
+
*/
|
|
31
|
+
declare class CapabilityClient {
|
|
32
|
+
private options;
|
|
33
|
+
constructor(options?: CapabilityClientOptions);
|
|
34
|
+
/**
|
|
35
|
+
* 加载能力,返回执行器
|
|
36
|
+
* @param capabilityId - 能力 ID
|
|
37
|
+
* @returns 能力执行器
|
|
38
|
+
*/
|
|
39
|
+
load(capabilityId: string): CapabilityExecutor;
|
|
40
|
+
private createExecutor;
|
|
41
|
+
private executeCall;
|
|
42
|
+
private executeCallStream;
|
|
73
43
|
}
|
|
74
44
|
/**
|
|
75
45
|
* 创建自定义客户端
|
|
@@ -78,7 +48,7 @@ declare function createClient(options?: CapabilityClientOptions): CapabilityClie
|
|
|
78
48
|
/**
|
|
79
49
|
* 默认客户端实例
|
|
80
50
|
*/
|
|
81
|
-
declare const
|
|
51
|
+
declare const capabilityClient: CapabilityClient;
|
|
82
52
|
|
|
83
53
|
/**
|
|
84
54
|
* 能力调用错误基类
|
|
@@ -90,12 +60,6 @@ declare class CapabilityError extends Error {
|
|
|
90
60
|
statusCode?: number;
|
|
91
61
|
constructor(message: string, code: string, statusCode?: number);
|
|
92
62
|
}
|
|
93
|
-
/**
|
|
94
|
-
* 客户端未初始化错误
|
|
95
|
-
*/
|
|
96
|
-
declare class ClientNotInitializedError extends CapabilityError {
|
|
97
|
-
constructor();
|
|
98
|
-
}
|
|
99
63
|
/**
|
|
100
64
|
* 能力不存在错误
|
|
101
65
|
*/
|
|
@@ -121,4 +85,4 @@ declare class ExecutionError extends CapabilityError {
|
|
|
121
85
|
constructor(message: string, statusCode?: number);
|
|
122
86
|
}
|
|
123
87
|
|
|
124
|
-
export { ActionNotFoundError, CapabilityClient, type CapabilityClientOptions, CapabilityError, type
|
|
88
|
+
export { ActionNotFoundError, CapabilityClient, type CapabilityClientOptions, CapabilityError, type CapabilityExecutor, CapabilityNotFoundError, ExecutionError, NetworkError, capabilityClient, createClient };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,74 +2,44 @@
|
|
|
2
2
|
* 客户端配置选项
|
|
3
3
|
*/
|
|
4
4
|
interface CapabilityClientOptions {
|
|
5
|
-
/** API 基础路径,默认 '' (相对路径) */
|
|
6
|
-
baseURL?: string;
|
|
7
5
|
/** 自定义 fetch 配置 */
|
|
8
6
|
fetchOptions?: RequestInit;
|
|
9
|
-
/** 是否在创建时自动初始化,默认 true */
|
|
10
|
-
autoInit?: boolean;
|
|
11
7
|
}
|
|
12
8
|
/**
|
|
13
|
-
*
|
|
9
|
+
* 能力执行器接口
|
|
14
10
|
*/
|
|
15
|
-
interface
|
|
16
|
-
id: string;
|
|
17
|
-
name: string;
|
|
18
|
-
description: string;
|
|
19
|
-
pluginID: string;
|
|
20
|
-
pluginVersion: string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* 能力客户端
|
|
25
|
-
*/
|
|
26
|
-
declare class CapabilityClient {
|
|
27
|
-
private options;
|
|
28
|
-
private capabilities;
|
|
29
|
-
private _initialized;
|
|
30
|
-
private initPromise;
|
|
31
|
-
/**
|
|
32
|
-
* 是否已初始化
|
|
33
|
-
*/
|
|
34
|
-
get initialized(): boolean;
|
|
35
|
-
constructor(options?: CapabilityClientOptions);
|
|
36
|
-
/**
|
|
37
|
-
* 初始化客户端,获取能力列表
|
|
38
|
-
*/
|
|
39
|
-
init(): Promise<void>;
|
|
40
|
-
private doInit;
|
|
41
|
-
/**
|
|
42
|
-
* 确保已初始化
|
|
43
|
-
*/
|
|
44
|
-
private ensureInitialized;
|
|
11
|
+
interface CapabilityExecutor {
|
|
45
12
|
/**
|
|
46
13
|
* 调用能力
|
|
47
|
-
* @param capabilityId - 能力 ID
|
|
48
14
|
* @param action - Action 名称
|
|
49
15
|
* @param params - 输入参数
|
|
50
16
|
* @returns Action 执行结果
|
|
51
17
|
*/
|
|
52
|
-
call<T = unknown>(
|
|
53
|
-
/**
|
|
54
|
-
* 检查能力是否存在
|
|
55
|
-
*/
|
|
56
|
-
hasCapability(capabilityId: string): boolean;
|
|
57
|
-
/**
|
|
58
|
-
* 获取所有可用能力
|
|
59
|
-
*/
|
|
60
|
-
listCapabilities(): Promise<CapabilityInfo[]>;
|
|
61
|
-
/**
|
|
62
|
-
* 获取单个能力信息
|
|
63
|
-
*/
|
|
64
|
-
getCapability(capabilityId: string): Promise<CapabilityInfo | null>;
|
|
18
|
+
call<T = unknown>(action: string, params?: Record<string, unknown>): Promise<T>;
|
|
65
19
|
/**
|
|
66
20
|
* 流式调用能力
|
|
67
|
-
* @param capabilityId - 能力 ID
|
|
68
21
|
* @param action - Action 名称
|
|
69
22
|
* @param params - 输入参数
|
|
70
23
|
* @returns AsyncIterable,逐个 yield chunk
|
|
71
24
|
*/
|
|
72
|
-
callStream<T = unknown>(
|
|
25
|
+
callStream<T = unknown>(action: string, params?: Record<string, unknown>): AsyncIterable<T>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* 能力客户端
|
|
30
|
+
*/
|
|
31
|
+
declare class CapabilityClient {
|
|
32
|
+
private options;
|
|
33
|
+
constructor(options?: CapabilityClientOptions);
|
|
34
|
+
/**
|
|
35
|
+
* 加载能力,返回执行器
|
|
36
|
+
* @param capabilityId - 能力 ID
|
|
37
|
+
* @returns 能力执行器
|
|
38
|
+
*/
|
|
39
|
+
load(capabilityId: string): CapabilityExecutor;
|
|
40
|
+
private createExecutor;
|
|
41
|
+
private executeCall;
|
|
42
|
+
private executeCallStream;
|
|
73
43
|
}
|
|
74
44
|
/**
|
|
75
45
|
* 创建自定义客户端
|
|
@@ -78,7 +48,7 @@ declare function createClient(options?: CapabilityClientOptions): CapabilityClie
|
|
|
78
48
|
/**
|
|
79
49
|
* 默认客户端实例
|
|
80
50
|
*/
|
|
81
|
-
declare const
|
|
51
|
+
declare const capabilityClient: CapabilityClient;
|
|
82
52
|
|
|
83
53
|
/**
|
|
84
54
|
* 能力调用错误基类
|
|
@@ -90,12 +60,6 @@ declare class CapabilityError extends Error {
|
|
|
90
60
|
statusCode?: number;
|
|
91
61
|
constructor(message: string, code: string, statusCode?: number);
|
|
92
62
|
}
|
|
93
|
-
/**
|
|
94
|
-
* 客户端未初始化错误
|
|
95
|
-
*/
|
|
96
|
-
declare class ClientNotInitializedError extends CapabilityError {
|
|
97
|
-
constructor();
|
|
98
|
-
}
|
|
99
63
|
/**
|
|
100
64
|
* 能力不存在错误
|
|
101
65
|
*/
|
|
@@ -121,4 +85,4 @@ declare class ExecutionError extends CapabilityError {
|
|
|
121
85
|
constructor(message: string, statusCode?: number);
|
|
122
86
|
}
|
|
123
87
|
|
|
124
|
-
export { ActionNotFoundError, CapabilityClient, type CapabilityClientOptions, CapabilityError, type
|
|
88
|
+
export { ActionNotFoundError, CapabilityClient, type CapabilityClientOptions, CapabilityError, type CapabilityExecutor, CapabilityNotFoundError, ExecutionError, NetworkError, capabilityClient, createClient };
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,16 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
|
|
|
3
3
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
4
4
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
5
|
|
|
6
|
+
// src/types.ts
|
|
7
|
+
var ErrorCodes = {
|
|
8
|
+
SUCCESS: "0",
|
|
9
|
+
CAPABILITY_NOT_FOUND: "k_ec_cap_001",
|
|
10
|
+
PLUGIN_NOT_FOUND: "k_ec_cap_002",
|
|
11
|
+
ACTION_NOT_FOUND: "k_ec_cap_003",
|
|
12
|
+
PARAMS_VALIDATION_ERROR: "k_ec_cap_004",
|
|
13
|
+
EXECUTION_ERROR: "k_ec_cap_005"
|
|
14
|
+
};
|
|
15
|
+
|
|
6
16
|
// src/errors.ts
|
|
7
17
|
var _CapabilityError = class _CapabilityError extends Error {
|
|
8
18
|
constructor(message, code, statusCode) {
|
|
@@ -18,14 +28,6 @@ var _CapabilityError = class _CapabilityError extends Error {
|
|
|
18
28
|
};
|
|
19
29
|
__name(_CapabilityError, "CapabilityError");
|
|
20
30
|
var CapabilityError = _CapabilityError;
|
|
21
|
-
var _ClientNotInitializedError = class _ClientNotInitializedError extends CapabilityError {
|
|
22
|
-
constructor() {
|
|
23
|
-
super("Client not initialized. Call init() first or enable autoInit.", "CLIENT_NOT_INITIALIZED");
|
|
24
|
-
this.name = "ClientNotInitializedError";
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
__name(_ClientNotInitializedError, "ClientNotInitializedError");
|
|
28
|
-
var ClientNotInitializedError = _ClientNotInitializedError;
|
|
29
31
|
var _CapabilityNotFoundError = class _CapabilityNotFoundError extends CapabilityError {
|
|
30
32
|
constructor(capabilityId, statusCode) {
|
|
31
33
|
super(`Capability not found: ${capabilityId}`, "CAPABILITY_NOT_FOUND", statusCode);
|
|
@@ -60,103 +62,38 @@ __name(_ExecutionError, "ExecutionError");
|
|
|
60
62
|
var ExecutionError = _ExecutionError;
|
|
61
63
|
|
|
62
64
|
// src/client.ts
|
|
63
|
-
var DEFAULT_OPTIONS = {
|
|
64
|
-
baseURL: "",
|
|
65
|
-
fetchOptions: {},
|
|
66
|
-
autoInit: true
|
|
67
|
-
};
|
|
68
65
|
var _CapabilityClient = class _CapabilityClient {
|
|
69
66
|
constructor(options) {
|
|
70
67
|
__publicField(this, "options");
|
|
71
|
-
|
|
72
|
-
__publicField(this, "_initialized", false);
|
|
73
|
-
__publicField(this, "initPromise", null);
|
|
74
|
-
this.options = {
|
|
75
|
-
...DEFAULT_OPTIONS,
|
|
76
|
-
...options
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* 是否已初始化
|
|
81
|
-
*/
|
|
82
|
-
get initialized() {
|
|
83
|
-
return this._initialized;
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* 初始化客户端,获取能力列表
|
|
87
|
-
*/
|
|
88
|
-
async init() {
|
|
89
|
-
if (this._initialized) {
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
if (this.initPromise) {
|
|
93
|
-
return this.initPromise;
|
|
94
|
-
}
|
|
95
|
-
this.initPromise = this.doInit();
|
|
96
|
-
try {
|
|
97
|
-
await this.initPromise;
|
|
98
|
-
} finally {
|
|
99
|
-
this.initPromise = null;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
async doInit() {
|
|
103
|
-
const url = `${this.options.baseURL}/api/capability/list`;
|
|
104
|
-
try {
|
|
105
|
-
const response = await fetch(url, {
|
|
106
|
-
method: "GET",
|
|
107
|
-
...this.options.fetchOptions,
|
|
108
|
-
headers: {
|
|
109
|
-
"Content-Type": "application/json",
|
|
110
|
-
...this.options.fetchOptions.headers
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
if (!response.ok) {
|
|
114
|
-
throw new NetworkError(`Failed to fetch capabilities: ${response.status} ${response.statusText}`);
|
|
115
|
-
}
|
|
116
|
-
const data = await response.json();
|
|
117
|
-
if (data.code !== 0) {
|
|
118
|
-
throw new ExecutionError(data.message);
|
|
119
|
-
}
|
|
120
|
-
this.capabilities.clear();
|
|
121
|
-
for (const capability of data.data) {
|
|
122
|
-
this.capabilities.set(capability.id, capability);
|
|
123
|
-
}
|
|
124
|
-
this._initialized = true;
|
|
125
|
-
} catch (error) {
|
|
126
|
-
if (error instanceof CapabilityError) {
|
|
127
|
-
throw error;
|
|
128
|
-
}
|
|
129
|
-
throw new NetworkError(error instanceof Error ? error.message : String(error));
|
|
130
|
-
}
|
|
68
|
+
this.options = options ?? {};
|
|
131
69
|
}
|
|
132
70
|
/**
|
|
133
|
-
*
|
|
134
|
-
*/
|
|
135
|
-
async ensureInitialized() {
|
|
136
|
-
if (!this._initialized && this.options.autoInit) {
|
|
137
|
-
await this.init();
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* 调用能力
|
|
71
|
+
* 加载能力,返回执行器
|
|
142
72
|
* @param capabilityId - 能力 ID
|
|
143
|
-
* @
|
|
144
|
-
* @param params - 输入参数
|
|
145
|
-
* @returns Action 执行结果
|
|
73
|
+
* @returns 能力执行器
|
|
146
74
|
*/
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
75
|
+
load(capabilityId) {
|
|
76
|
+
return this.createExecutor(capabilityId);
|
|
77
|
+
}
|
|
78
|
+
createExecutor(capabilityId) {
|
|
79
|
+
return {
|
|
80
|
+
call: /* @__PURE__ */ __name((action, params) => {
|
|
81
|
+
return this.executeCall(capabilityId, action, params);
|
|
82
|
+
}, "call"),
|
|
83
|
+
callStream: /* @__PURE__ */ __name((action, params) => {
|
|
84
|
+
return this.executeCallStream(capabilityId, action, params);
|
|
85
|
+
}, "callStream")
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
async executeCall(capabilityId, action, params) {
|
|
89
|
+
const url = `/api/capability/${capabilityId}`;
|
|
153
90
|
try {
|
|
154
91
|
const response = await fetch(url, {
|
|
155
92
|
method: "POST",
|
|
156
93
|
...this.options.fetchOptions,
|
|
157
94
|
headers: {
|
|
158
95
|
"Content-Type": "application/json",
|
|
159
|
-
...this.options.fetchOptions
|
|
96
|
+
...this.options.fetchOptions?.headers
|
|
160
97
|
},
|
|
161
98
|
body: JSON.stringify({
|
|
162
99
|
action,
|
|
@@ -164,21 +101,21 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
164
101
|
})
|
|
165
102
|
});
|
|
166
103
|
const data = await response.json();
|
|
167
|
-
if (!response.ok || data.
|
|
104
|
+
if (!response.ok || data.status_code !== ErrorCodes.SUCCESS) {
|
|
168
105
|
const errorResponse = data;
|
|
169
|
-
const errorCode = errorResponse.
|
|
106
|
+
const errorCode = errorResponse.status_code;
|
|
170
107
|
switch (errorCode) {
|
|
171
|
-
case
|
|
108
|
+
case ErrorCodes.CAPABILITY_NOT_FOUND:
|
|
172
109
|
throw new CapabilityNotFoundError(capabilityId, response.status);
|
|
173
|
-
case
|
|
174
|
-
throw new ActionNotFoundError(errorResponse.
|
|
175
|
-
case
|
|
176
|
-
case
|
|
110
|
+
case ErrorCodes.ACTION_NOT_FOUND:
|
|
111
|
+
throw new ActionNotFoundError(errorResponse.error_msg, response.status);
|
|
112
|
+
case ErrorCodes.PLUGIN_NOT_FOUND:
|
|
113
|
+
case ErrorCodes.EXECUTION_ERROR:
|
|
177
114
|
default:
|
|
178
|
-
throw new ExecutionError(errorResponse.
|
|
115
|
+
throw new ExecutionError(errorResponse.error_msg, response.status);
|
|
179
116
|
}
|
|
180
117
|
}
|
|
181
|
-
return data.data;
|
|
118
|
+
return data.data.output;
|
|
182
119
|
} catch (error) {
|
|
183
120
|
if (error instanceof CapabilityError) {
|
|
184
121
|
throw error;
|
|
@@ -186,39 +123,8 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
186
123
|
throw new NetworkError(error instanceof Error ? error.message : String(error));
|
|
187
124
|
}
|
|
188
125
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
*/
|
|
192
|
-
hasCapability(capabilityId) {
|
|
193
|
-
return this.capabilities.has(capabilityId);
|
|
194
|
-
}
|
|
195
|
-
/**
|
|
196
|
-
* 获取所有可用能力
|
|
197
|
-
*/
|
|
198
|
-
async listCapabilities() {
|
|
199
|
-
await this.ensureInitialized();
|
|
200
|
-
return Array.from(this.capabilities.values());
|
|
201
|
-
}
|
|
202
|
-
/**
|
|
203
|
-
* 获取单个能力信息
|
|
204
|
-
*/
|
|
205
|
-
async getCapability(capabilityId) {
|
|
206
|
-
await this.ensureInitialized();
|
|
207
|
-
return this.capabilities.get(capabilityId) ?? null;
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* 流式调用能力
|
|
211
|
-
* @param capabilityId - 能力 ID
|
|
212
|
-
* @param action - Action 名称
|
|
213
|
-
* @param params - 输入参数
|
|
214
|
-
* @returns AsyncIterable,逐个 yield chunk
|
|
215
|
-
*/
|
|
216
|
-
async *callStream(capabilityId, action, params) {
|
|
217
|
-
await this.ensureInitialized();
|
|
218
|
-
if (this._initialized && !this.capabilities.has(capabilityId)) {
|
|
219
|
-
throw new CapabilityNotFoundError(capabilityId);
|
|
220
|
-
}
|
|
221
|
-
const url = `${this.options.baseURL}/api/capability/${capabilityId}/stream`;
|
|
126
|
+
async *executeCallStream(capabilityId, action, params) {
|
|
127
|
+
const url = `/api/capability/${capabilityId}/stream`;
|
|
222
128
|
let response;
|
|
223
129
|
try {
|
|
224
130
|
response = await fetch(url, {
|
|
@@ -226,7 +132,7 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
226
132
|
...this.options.fetchOptions,
|
|
227
133
|
headers: {
|
|
228
134
|
"Content-Type": "application/json",
|
|
229
|
-
...this.options.fetchOptions
|
|
135
|
+
...this.options.fetchOptions?.headers
|
|
230
136
|
},
|
|
231
137
|
body: JSON.stringify({
|
|
232
138
|
action,
|
|
@@ -257,23 +163,18 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
257
163
|
for (const line of lines) {
|
|
258
164
|
if (line.startsWith("data: ")) {
|
|
259
165
|
const data = line.slice(6);
|
|
260
|
-
if (data === "[DONE]") {
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
166
|
try {
|
|
264
167
|
const parsed = JSON.parse(data);
|
|
265
|
-
if (parsed.
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
throw new ExecutionError(parsed.error);
|
|
168
|
+
if (parsed.status_code === ErrorCodes.SUCCESS && parsed.data) {
|
|
169
|
+
if (parsed.data.type === "content") {
|
|
170
|
+
yield parsed.data.delta.content;
|
|
171
|
+
if (parsed.data.finished) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
} else if (parsed.data.type === "error") {
|
|
175
|
+
throw new ExecutionError(parsed.data.error.message);
|
|
274
176
|
}
|
|
275
177
|
}
|
|
276
|
-
yield parsed;
|
|
277
178
|
} catch (parseError) {
|
|
278
179
|
if (parseError instanceof CapabilityError) {
|
|
279
180
|
throw parseError;
|
|
@@ -298,16 +199,15 @@ function createClient(options) {
|
|
|
298
199
|
return new CapabilityClient(options);
|
|
299
200
|
}
|
|
300
201
|
__name(createClient, "createClient");
|
|
301
|
-
var
|
|
202
|
+
var capabilityClient = new CapabilityClient();
|
|
302
203
|
export {
|
|
303
204
|
ActionNotFoundError,
|
|
304
205
|
CapabilityClient,
|
|
305
206
|
CapabilityError,
|
|
306
207
|
CapabilityNotFoundError,
|
|
307
|
-
ClientNotInitializedError,
|
|
308
208
|
ExecutionError,
|
|
309
209
|
NetworkError,
|
|
310
|
-
|
|
210
|
+
capabilityClient,
|
|
311
211
|
createClient
|
|
312
212
|
};
|
|
313
213
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/client.ts"],"sourcesContent":["/**\n * 能力调用错误基类\n */\nexport class CapabilityError extends Error {\n /** 错误码 */\n code: string;\n /** HTTP 状态码 */\n statusCode?: number;\n\n constructor(message: string, code: string, statusCode?: number) {\n super(message);\n this.name = 'CapabilityError';\n this.code = code;\n this.statusCode = statusCode;\n }\n}\n\n/**\n * 客户端未初始化错误\n */\nexport class ClientNotInitializedError extends CapabilityError {\n constructor() {\n super('Client not initialized. Call init() first or enable autoInit.', 'CLIENT_NOT_INITIALIZED');\n this.name = 'ClientNotInitializedError';\n }\n}\n\n/**\n * 能力不存在错误\n */\nexport class CapabilityNotFoundError extends CapabilityError {\n constructor(capabilityId: string, statusCode?: number) {\n super(`Capability not found: ${capabilityId}`, 'CAPABILITY_NOT_FOUND', statusCode);\n this.name = 'CapabilityNotFoundError';\n }\n}\n\n/**\n * Action 不存在错误\n */\nexport class ActionNotFoundError extends CapabilityError {\n constructor(message: string, statusCode?: number) {\n super(message, 'ACTION_NOT_FOUND', statusCode);\n this.name = 'ActionNotFoundError';\n }\n}\n\n/**\n * 网络错误\n */\nexport class NetworkError extends CapabilityError {\n constructor(message: string) {\n super(message, 'NETWORK_ERROR');\n this.name = 'NetworkError';\n }\n}\n\n/**\n * 执行错误\n */\nexport class ExecutionError extends CapabilityError {\n constructor(message: string, statusCode?: number) {\n super(message, 'EXECUTION_ERROR', statusCode);\n this.name = 'ExecutionError';\n }\n}\n","import type { CapabilityClientOptions, CapabilityInfo, ApiResponse } from './types';\nimport {\n CapabilityError,\n CapabilityNotFoundError,\n ActionNotFoundError,\n NetworkError,\n ExecutionError,\n} from './errors';\n\nconst DEFAULT_OPTIONS: Required<CapabilityClientOptions> = {\n baseURL: '',\n fetchOptions: {},\n autoInit: true,\n};\n\n/**\n * 能力客户端\n */\nexport class CapabilityClient {\n private options: Required<CapabilityClientOptions>;\n private capabilities: Map<string, CapabilityInfo> = new Map();\n private _initialized = false;\n private initPromise: Promise<void> | null = null;\n\n /**\n * 是否已初始化\n */\n get initialized(): boolean {\n return this._initialized;\n }\n\n constructor(options?: CapabilityClientOptions) {\n this.options = { ...DEFAULT_OPTIONS, ...options };\n }\n\n /**\n * 初始化客户端,获取能力列表\n */\n async init(): Promise<void> {\n if (this._initialized) {\n return;\n }\n\n // 防止并发初始化\n if (this.initPromise) {\n return this.initPromise;\n }\n\n this.initPromise = this.doInit();\n try {\n await this.initPromise;\n } finally {\n this.initPromise = null;\n }\n }\n\n private async doInit(): Promise<void> {\n const url = `${this.options.baseURL}/api/capability/list`;\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n ...this.options.fetchOptions,\n headers: {\n 'Content-Type': 'application/json',\n ...this.options.fetchOptions.headers,\n },\n });\n\n if (!response.ok) {\n throw new NetworkError(`Failed to fetch capabilities: ${response.status} ${response.statusText}`);\n }\n\n const data = (await response.json()) as ApiResponse<CapabilityInfo[]>;\n\n if (data.code !== 0) {\n throw new ExecutionError((data as { message: string }).message);\n }\n\n this.capabilities.clear();\n for (const capability of (data as { data: CapabilityInfo[] }).data) {\n this.capabilities.set(capability.id, capability);\n }\n\n this._initialized = true;\n } catch (error) {\n if (error instanceof CapabilityError) {\n throw error;\n }\n throw new NetworkError(error instanceof Error ? error.message : String(error));\n }\n }\n\n /**\n * 确保已初始化\n */\n private async ensureInitialized(): Promise<void> {\n if (!this._initialized && this.options.autoInit) {\n await this.init();\n }\n }\n\n /**\n * 调用能力\n * @param capabilityId - 能力 ID\n * @param action - Action 名称\n * @param params - 输入参数\n * @returns Action 执行结果\n */\n async call<T = unknown>(\n capabilityId: string,\n action: string,\n params?: Record<string, unknown>\n ): Promise<T> {\n await this.ensureInitialized();\n\n // 检查能力是否存在(如果已初始化)\n if (this._initialized && !this.capabilities.has(capabilityId)) {\n throw new CapabilityNotFoundError(capabilityId);\n }\n\n const url = `${this.options.baseURL}/api/capability/${capabilityId}`;\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n ...this.options.fetchOptions,\n headers: {\n 'Content-Type': 'application/json',\n ...this.options.fetchOptions.headers,\n },\n body: JSON.stringify({\n action,\n params: params ?? {},\n }),\n });\n\n const data = (await response.json()) as ApiResponse<T>;\n\n if (!response.ok || data.code !== 0) {\n const errorResponse = data as { code: number; message: string; error?: string };\n const errorCode = errorResponse.error ?? 'UNKNOWN_ERROR';\n\n switch (errorCode) {\n case 'CAPABILITY_NOT_FOUND':\n throw new CapabilityNotFoundError(capabilityId, response.status);\n case 'ACTION_NOT_FOUND':\n throw new ActionNotFoundError(errorResponse.message, response.status);\n case 'PLUGIN_NOT_FOUND':\n case 'EXECUTION_ERROR':\n default:\n throw new ExecutionError(errorResponse.message, response.status);\n }\n }\n\n return (data as { data: T }).data;\n } catch (error) {\n if (error instanceof CapabilityError) {\n throw error;\n }\n throw new NetworkError(error instanceof Error ? error.message : String(error));\n }\n }\n\n /**\n * 检查能力是否存在\n */\n hasCapability(capabilityId: string): boolean {\n return this.capabilities.has(capabilityId);\n }\n\n /**\n * 获取所有可用能力\n */\n async listCapabilities(): Promise<CapabilityInfo[]> {\n await this.ensureInitialized();\n return Array.from(this.capabilities.values());\n }\n\n /**\n * 获取单个能力信息\n */\n async getCapability(capabilityId: string): Promise<CapabilityInfo | null> {\n await this.ensureInitialized();\n return this.capabilities.get(capabilityId) ?? null;\n }\n\n /**\n * 流式调用能力\n * @param capabilityId - 能力 ID\n * @param action - Action 名称\n * @param params - 输入参数\n * @returns AsyncIterable,逐个 yield chunk\n */\n async *callStream<T = unknown>(\n capabilityId: string,\n action: string,\n params?: Record<string, unknown>\n ): AsyncIterable<T> {\n await this.ensureInitialized();\n\n // 检查能力是否存在(如果已初始化)\n if (this._initialized && !this.capabilities.has(capabilityId)) {\n throw new CapabilityNotFoundError(capabilityId);\n }\n\n const url = `${this.options.baseURL}/api/capability/${capabilityId}/stream`;\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: 'POST',\n ...this.options.fetchOptions,\n headers: {\n 'Content-Type': 'application/json',\n ...this.options.fetchOptions.headers,\n },\n body: JSON.stringify({\n action,\n params: params ?? {},\n }),\n });\n } catch (error) {\n throw new NetworkError(error instanceof Error ? error.message : String(error));\n }\n\n if (!response.ok) {\n throw new NetworkError(`HTTP ${response.status} ${response.statusText}`);\n }\n\n if (!response.body) {\n throw new NetworkError('Response body is null');\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n const data = line.slice(6);\n\n // 流结束标记\n if (data === '[DONE]') {\n return;\n }\n\n try {\n const parsed = JSON.parse(data) as { error?: string; code?: string } & T;\n\n // 服务端错误\n if (parsed.error) {\n const errorCode = parsed.code ?? 'EXECUTION_ERROR';\n switch (errorCode) {\n case 'CAPABILITY_NOT_FOUND':\n throw new CapabilityNotFoundError(capabilityId);\n case 'ACTION_NOT_FOUND':\n throw new ActionNotFoundError(parsed.error);\n default:\n throw new ExecutionError(parsed.error);\n }\n }\n\n yield parsed as T;\n } catch (parseError) {\n // JSON 解析错误,跳过此行\n if (parseError instanceof CapabilityError) {\n throw parseError;\n }\n // 忽略非 JSON 行\n }\n }\n }\n }\n } catch (error) {\n if (error instanceof CapabilityError) {\n throw error;\n }\n throw new NetworkError(error instanceof Error ? error.message : String(error));\n } finally {\n reader.releaseLock();\n }\n }\n}\n\n/**\n * 创建自定义客户端\n */\nexport function createClient(options?: CapabilityClientOptions): CapabilityClient {\n return new CapabilityClient(options);\n}\n\n/**\n * 默认客户端实例\n */\nexport const client = new CapabilityClient();\n"],"mappings":"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","names":["CapabilityError","Error","message","code","statusCode","name","ClientNotInitializedError","CapabilityNotFoundError","capabilityId","ActionNotFoundError","NetworkError","ExecutionError","DEFAULT_OPTIONS","baseURL","fetchOptions","autoInit","CapabilityClient","options","capabilities","Map","_initialized","initPromise","initialized","init","doInit","url","response","fetch","method","headers","ok","NetworkError","status","statusText","data","json","code","ExecutionError","message","clear","capability","set","id","error","CapabilityError","Error","String","ensureInitialized","call","capabilityId","action","params","has","CapabilityNotFoundError","body","JSON","stringify","errorResponse","errorCode","ActionNotFoundError","hasCapability","listCapabilities","Array","from","values","getCapability","get","callStream","reader","getReader","decoder","TextDecoder","buffer","done","value","read","decode","stream","lines","split","pop","line","startsWith","slice","parsed","parse","parseError","releaseLock","createClient","client"]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/errors.ts","../src/client.ts"],"sourcesContent":["/**\n * 客户端配置选项\n */\nexport interface CapabilityClientOptions {\n /** 自定义 fetch 配置 */\n fetchOptions?: RequestInit;\n}\n\n/**\n * 能力执行器接口\n */\nexport interface CapabilityExecutor {\n /**\n * 调用能力\n * @param action - Action 名称\n * @param params - 输入参数\n * @returns Action 执行结果\n */\n call<T = unknown>(\n action: string,\n params?: Record<string, unknown>\n ): Promise<T>;\n\n /**\n * 流式调用能力\n * @param action - Action 名称\n * @param params - 输入参数\n * @returns AsyncIterable,逐个 yield chunk\n */\n callStream<T = unknown>(\n action: string,\n params?: Record<string, unknown>\n ): AsyncIterable<T>;\n}\n\n// ========== API 响应类型 ==========\n\n/**\n * 成功响应\n */\nexport interface SuccessResponse<T> {\n status_code: '0';\n data: T;\n}\n\n/**\n * 错误响应\n */\nexport interface ErrorResponse {\n status_code: string;\n error_msg: string;\n}\n\n/**\n * API 响应类型\n */\nexport type ApiResponse<T> = SuccessResponse<T> | ErrorResponse;\n\n// ========== 具体响应 data 结构 ==========\n\n/**\n * 执行接口响应 data 结构\n */\nexport interface ExecuteResponseData {\n output: unknown;\n}\n\n// ========== 流式响应结构 ==========\n\n/**\n * 流式内容响应\n */\nexport interface StreamContentResponse {\n status_code: '0';\n data: {\n type: 'content';\n delta: {\n content: unknown;\n };\n finished?: boolean;\n };\n}\n\n/**\n * 流式错误响应\n */\nexport interface StreamErrorResponse {\n status_code: '0';\n data: {\n type: 'error';\n error: {\n code: number;\n message: string;\n };\n };\n}\n\n/**\n * 流式响应类型\n */\nexport type StreamResponse = StreamContentResponse | StreamErrorResponse;\n\n// ========== 错误码 ==========\n\n/**\n * 后端错误码\n */\nexport const ErrorCodes = {\n SUCCESS: '0',\n CAPABILITY_NOT_FOUND: 'k_ec_cap_001',\n PLUGIN_NOT_FOUND: 'k_ec_cap_002',\n ACTION_NOT_FOUND: 'k_ec_cap_003',\n PARAMS_VALIDATION_ERROR: 'k_ec_cap_004',\n EXECUTION_ERROR: 'k_ec_cap_005',\n} as const;\n","/**\n * 能力调用错误基类\n */\nexport class CapabilityError extends Error {\n /** 错误码 */\n code: string;\n /** HTTP 状态码 */\n statusCode?: number;\n\n constructor(message: string, code: string, statusCode?: number) {\n super(message);\n this.name = 'CapabilityError';\n this.code = code;\n this.statusCode = statusCode;\n }\n}\n\n/**\n * 能力不存在错误\n */\nexport class CapabilityNotFoundError extends CapabilityError {\n constructor(capabilityId: string, statusCode?: number) {\n super(`Capability not found: ${capabilityId}`, 'CAPABILITY_NOT_FOUND', statusCode);\n this.name = 'CapabilityNotFoundError';\n }\n}\n\n/**\n * Action 不存在错误\n */\nexport class ActionNotFoundError extends CapabilityError {\n constructor(message: string, statusCode?: number) {\n super(message, 'ACTION_NOT_FOUND', statusCode);\n this.name = 'ActionNotFoundError';\n }\n}\n\n/**\n * 网络错误\n */\nexport class NetworkError extends CapabilityError {\n constructor(message: string) {\n super(message, 'NETWORK_ERROR');\n this.name = 'NetworkError';\n }\n}\n\n/**\n * 执行错误\n */\nexport class ExecutionError extends CapabilityError {\n constructor(message: string, statusCode?: number) {\n super(message, 'EXECUTION_ERROR', statusCode);\n this.name = 'ExecutionError';\n }\n}\n","import type {\n CapabilityClientOptions,\n CapabilityExecutor,\n ApiResponse,\n ExecuteResponseData,\n StreamResponse,\n} from './types';\nimport { ErrorCodes } from './types';\nimport {\n CapabilityError,\n CapabilityNotFoundError,\n ActionNotFoundError,\n NetworkError,\n ExecutionError,\n} from './errors';\n\n/**\n * 能力客户端\n */\nexport class CapabilityClient {\n private options: CapabilityClientOptions;\n\n constructor(options?: CapabilityClientOptions) {\n this.options = options ?? {};\n }\n\n /**\n * 加载能力,返回执行器\n * @param capabilityId - 能力 ID\n * @returns 能力执行器\n */\n load(capabilityId: string): CapabilityExecutor {\n return this.createExecutor(capabilityId);\n }\n\n private createExecutor(capabilityId: string): CapabilityExecutor {\n return {\n call: <T = unknown>(action: string, params?: Record<string, unknown>) => {\n return this.executeCall<T>(capabilityId, action, params);\n },\n callStream: <T = unknown>(action: string, params?: Record<string, unknown>) => {\n return this.executeCallStream<T>(capabilityId, action, params);\n },\n };\n }\n\n private async executeCall<T>(\n capabilityId: string,\n action: string,\n params?: Record<string, unknown>\n ): Promise<T> {\n const url = `/api/capability/${capabilityId}`;\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n ...this.options.fetchOptions,\n headers: {\n 'Content-Type': 'application/json',\n ...this.options.fetchOptions?.headers,\n },\n body: JSON.stringify({\n action,\n params: params ?? {},\n }),\n });\n\n const data = (await response.json()) as ApiResponse<ExecuteResponseData>;\n\n if (!response.ok || data.status_code !== ErrorCodes.SUCCESS) {\n const errorResponse = data as { status_code: string; error_msg: string };\n const errorCode = errorResponse.status_code;\n\n switch (errorCode) {\n case ErrorCodes.CAPABILITY_NOT_FOUND:\n throw new CapabilityNotFoundError(capabilityId, response.status);\n case ErrorCodes.ACTION_NOT_FOUND:\n throw new ActionNotFoundError(errorResponse.error_msg, response.status);\n case ErrorCodes.PLUGIN_NOT_FOUND:\n case ErrorCodes.EXECUTION_ERROR:\n default:\n throw new ExecutionError(errorResponse.error_msg, response.status);\n }\n }\n\n return (data as { data: ExecuteResponseData }).data.output as T;\n } catch (error) {\n if (error instanceof CapabilityError) {\n throw error;\n }\n throw new NetworkError(error instanceof Error ? error.message : String(error));\n }\n }\n\n private async *executeCallStream<T>(\n capabilityId: string,\n action: string,\n params?: Record<string, unknown>\n ): AsyncIterable<T> {\n const url = `/api/capability/${capabilityId}/stream`;\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: 'POST',\n ...this.options.fetchOptions,\n headers: {\n 'Content-Type': 'application/json',\n ...this.options.fetchOptions?.headers,\n },\n body: JSON.stringify({\n action,\n params: params ?? {},\n }),\n });\n } catch (error) {\n throw new NetworkError(error instanceof Error ? error.message : String(error));\n }\n\n if (!response.ok) {\n throw new NetworkError(`HTTP ${response.status} ${response.statusText}`);\n }\n\n if (!response.body) {\n throw new NetworkError('Response body is null');\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n const data = line.slice(6);\n\n try {\n const parsed = JSON.parse(data) as StreamResponse;\n\n if (parsed.status_code === ErrorCodes.SUCCESS && parsed.data) {\n if (parsed.data.type === 'content') {\n yield parsed.data.delta.content as T;\n\n if (parsed.data.finished) {\n return;\n }\n } else if (parsed.data.type === 'error') {\n throw new ExecutionError(parsed.data.error.message);\n }\n }\n } catch (parseError) {\n if (parseError instanceof CapabilityError) {\n throw parseError;\n }\n // 忽略非 JSON 行\n }\n }\n }\n }\n } catch (error) {\n if (error instanceof CapabilityError) {\n throw error;\n }\n throw new NetworkError(error instanceof Error ? error.message : String(error));\n } finally {\n reader.releaseLock();\n }\n }\n}\n\n/**\n * 创建自定义客户端\n */\nexport function createClient(options?: CapabilityClientOptions): CapabilityClient {\n return new CapabilityClient(options);\n}\n\n/**\n * 默认客户端实例\n */\nexport const capabilityClient = new CapabilityClient();\n"],"mappings":"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","names":["ErrorCodes","SUCCESS","CAPABILITY_NOT_FOUND","PLUGIN_NOT_FOUND","ACTION_NOT_FOUND","PARAMS_VALIDATION_ERROR","EXECUTION_ERROR","CapabilityError","Error","message","code","statusCode","name","CapabilityNotFoundError","capabilityId","ActionNotFoundError","NetworkError","ExecutionError","CapabilityClient","options","load","capabilityId","createExecutor","call","action","params","executeCall","callStream","executeCallStream","url","response","fetch","method","fetchOptions","headers","body","JSON","stringify","data","json","ok","status_code","ErrorCodes","SUCCESS","errorResponse","errorCode","CAPABILITY_NOT_FOUND","CapabilityNotFoundError","status","ACTION_NOT_FOUND","ActionNotFoundError","error_msg","PLUGIN_NOT_FOUND","EXECUTION_ERROR","ExecutionError","output","error","CapabilityError","NetworkError","Error","message","String","statusText","reader","getReader","decoder","TextDecoder","buffer","done","value","read","decode","stream","lines","split","pop","line","startsWith","slice","parsed","parse","type","delta","content","finished","parseError","releaseLock","createClient","capabilityClient"]}
|