@lark-apaas/client-capability 0.0.1-alpha.0 → 0.0.1-alpha.2
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 +69 -94
- package/dist/index.cjs +53 -151
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -58
- package/dist/index.d.ts +25 -58
- package/dist/index.js +53 -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,37 @@ 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
|
-
|
|
58
|
+
// 全局路径前缀(线上环境)
|
|
59
|
+
baseURL: '/spark/a', // 请求路径: /spark/a/api/capability/xxx
|
|
76
60
|
fetchOptions: {
|
|
77
61
|
credentials: 'include',
|
|
78
62
|
headers: {
|
|
79
63
|
'X-Custom-Header': 'value',
|
|
80
64
|
},
|
|
81
65
|
},
|
|
82
|
-
autoInit: false,
|
|
83
66
|
});
|
|
84
67
|
|
|
85
|
-
await client.
|
|
86
|
-
const result = await client.call('xxx', 'run', params);
|
|
68
|
+
const result = await client.load('xxx').call('run', params);
|
|
87
69
|
```
|
|
88
70
|
|
|
71
|
+
**baseURL 配置说明:**
|
|
72
|
+
|
|
73
|
+
| 环境 | baseURL | 实际请求路径 |
|
|
74
|
+
|-----|---------|-------------|
|
|
75
|
+
| 本地开发 | `''`(默认) | `/api/capability/xxx` |
|
|
76
|
+
| 线上环境 | `'/spark/a'` | `/spark/a/api/capability/xxx` |
|
|
77
|
+
|
|
89
78
|
### 错误处理
|
|
90
79
|
|
|
91
80
|
```typescript
|
|
92
81
|
import {
|
|
93
|
-
|
|
82
|
+
capabilityClient,
|
|
94
83
|
CapabilityNotFoundError,
|
|
95
84
|
ExecutionError
|
|
96
85
|
} from '@lark-apaas/client-capability';
|
|
97
86
|
|
|
98
87
|
try {
|
|
99
|
-
const result = await
|
|
88
|
+
const result = await capabilityClient.load('create_feishu_group').call('run', params);
|
|
100
89
|
} catch (error) {
|
|
101
90
|
if (error instanceof CapabilityNotFoundError) {
|
|
102
91
|
console.error('能力不存在:', error.message);
|
|
@@ -108,29 +97,13 @@ try {
|
|
|
108
97
|
}
|
|
109
98
|
```
|
|
110
99
|
|
|
111
|
-
###
|
|
112
|
-
|
|
113
|
-
用于 LLM 对话等流式输出场景:
|
|
100
|
+
### 流式调用错误处理
|
|
114
101
|
|
|
115
102
|
```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';
|
|
103
|
+
import { capabilityClient, NetworkError, ExecutionError } from '@lark-apaas/client-capability';
|
|
131
104
|
|
|
132
105
|
try {
|
|
133
|
-
const stream =
|
|
106
|
+
const stream = capabilityClient.load('ai_chat').callStream('chat', { message: 'hello' });
|
|
134
107
|
for await (const chunk of stream) {
|
|
135
108
|
process(chunk);
|
|
136
109
|
}
|
|
@@ -149,34 +122,40 @@ try {
|
|
|
149
122
|
|
|
150
123
|
```typescript
|
|
151
124
|
class CapabilityClient {
|
|
152
|
-
|
|
153
|
-
|
|
125
|
+
/**
|
|
126
|
+
* 加载能力,返回执行器
|
|
127
|
+
* @param capabilityId - 能力 ID
|
|
128
|
+
* @returns 能力执行器
|
|
129
|
+
*/
|
|
130
|
+
load(capabilityId: string): CapabilityExecutor;
|
|
131
|
+
}
|
|
132
|
+
```
|
|
154
133
|
|
|
155
|
-
|
|
156
|
-
init(): Promise<void>;
|
|
134
|
+
### CapabilityExecutor
|
|
157
135
|
|
|
158
|
-
|
|
136
|
+
```typescript
|
|
137
|
+
interface CapabilityExecutor {
|
|
138
|
+
/**
|
|
139
|
+
* 调用能力
|
|
140
|
+
* @param action - Action 名称
|
|
141
|
+
* @param params - 输入参数
|
|
142
|
+
* @returns Action 执行结果
|
|
143
|
+
*/
|
|
159
144
|
call<T = unknown>(
|
|
160
|
-
capabilityId: string,
|
|
161
145
|
action: string,
|
|
162
146
|
params?: Record<string, unknown>
|
|
163
147
|
): Promise<T>;
|
|
164
148
|
|
|
165
|
-
|
|
149
|
+
/**
|
|
150
|
+
* 流式调用能力
|
|
151
|
+
* @param action - Action 名称
|
|
152
|
+
* @param params - 输入参数
|
|
153
|
+
* @returns AsyncIterable,逐个 yield chunk
|
|
154
|
+
*/
|
|
166
155
|
callStream<T = unknown>(
|
|
167
|
-
capabilityId: string,
|
|
168
156
|
action: string,
|
|
169
157
|
params?: Record<string, unknown>
|
|
170
158
|
): 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
159
|
}
|
|
181
160
|
```
|
|
182
161
|
|
|
@@ -184,26 +163,10 @@ class CapabilityClient {
|
|
|
184
163
|
|
|
185
164
|
```typescript
|
|
186
165
|
interface CapabilityClientOptions {
|
|
187
|
-
|
|
166
|
+
/** 全局路径前缀,默认 ''。例如线上环境可设置为 '/spark/a' */
|
|
188
167
|
baseURL?: string;
|
|
189
|
-
|
|
190
|
-
// 自定义 fetch 配置
|
|
168
|
+
/** 自定义 fetch 配置 */
|
|
191
169
|
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
170
|
}
|
|
208
171
|
```
|
|
209
172
|
|
|
@@ -212,7 +175,6 @@ interface CapabilityInfo {
|
|
|
212
175
|
| 错误类型 | 错误码 | 描述 |
|
|
213
176
|
|---------|--------|------|
|
|
214
177
|
| `CapabilityError` | - | 错误基类 |
|
|
215
|
-
| `ClientNotInitializedError` | CLIENT_NOT_INITIALIZED | 客户端未初始化 |
|
|
216
178
|
| `CapabilityNotFoundError` | CAPABILITY_NOT_FOUND | 能力不存在 |
|
|
217
179
|
| `ActionNotFoundError` | ACTION_NOT_FOUND | Action 不存在 |
|
|
218
180
|
| `NetworkError` | NETWORK_ERROR | 网络错误 |
|
|
@@ -222,18 +184,17 @@ interface CapabilityInfo {
|
|
|
222
184
|
|
|
223
185
|
```typescript
|
|
224
186
|
// 默认客户端实例
|
|
225
|
-
export {
|
|
187
|
+
export { capabilityClient } from '@lark-apaas/client-capability';
|
|
226
188
|
|
|
227
189
|
// 创建自定义客户端
|
|
228
190
|
export { createClient, CapabilityClient } from '@lark-apaas/client-capability';
|
|
229
191
|
|
|
230
192
|
// 类型
|
|
231
|
-
export type { CapabilityClientOptions,
|
|
193
|
+
export type { CapabilityClientOptions, CapabilityExecutor } from '@lark-apaas/client-capability';
|
|
232
194
|
|
|
233
195
|
// 错误类型
|
|
234
196
|
export {
|
|
235
197
|
CapabilityError,
|
|
236
|
-
ClientNotInitializedError,
|
|
237
198
|
CapabilityNotFoundError,
|
|
238
199
|
ActionNotFoundError,
|
|
239
200
|
NetworkError,
|
|
@@ -241,6 +202,20 @@ export {
|
|
|
241
202
|
} from '@lark-apaas/client-capability';
|
|
242
203
|
```
|
|
243
204
|
|
|
205
|
+
## 与服务端 API 对比
|
|
206
|
+
|
|
207
|
+
客户端与服务端使用一致的链式调用风格:
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
// 客户端
|
|
211
|
+
import { capabilityClient } from '@lark-apaas/client-capability';
|
|
212
|
+
const result = await capabilityClient.load('xxx').call('run', params);
|
|
213
|
+
|
|
214
|
+
// 服务端
|
|
215
|
+
import { CapabilityService } from '@lark-apaas/nestjs-capability';
|
|
216
|
+
const result = await capabilityService.load('xxx').call('run', params);
|
|
217
|
+
```
|
|
218
|
+
|
|
244
219
|
## 许可证
|
|
245
220
|
|
|
246
221
|
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,40 @@ __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
|
-
__publicField(this, "
|
|
104
|
-
|
|
105
|
-
|
|
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
|
+
__publicField(this, "baseURL");
|
|
100
|
+
this.options = options ?? {};
|
|
101
|
+
this.baseURL = (options?.baseURL ?? "").replace(/\/+$/, "");
|
|
163
102
|
}
|
|
164
103
|
/**
|
|
165
|
-
*
|
|
166
|
-
*/
|
|
167
|
-
async ensureInitialized() {
|
|
168
|
-
if (!this._initialized && this.options.autoInit) {
|
|
169
|
-
await this.init();
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
/**
|
|
173
|
-
* 调用能力
|
|
104
|
+
* 加载能力,返回执行器
|
|
174
105
|
* @param capabilityId - 能力 ID
|
|
175
|
-
* @
|
|
176
|
-
* @param params - 输入参数
|
|
177
|
-
* @returns Action 执行结果
|
|
106
|
+
* @returns 能力执行器
|
|
178
107
|
*/
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
108
|
+
load(capabilityId) {
|
|
109
|
+
return this.createExecutor(capabilityId);
|
|
110
|
+
}
|
|
111
|
+
createExecutor(capabilityId) {
|
|
112
|
+
return {
|
|
113
|
+
call: /* @__PURE__ */ __name((action, params) => {
|
|
114
|
+
return this.executeCall(capabilityId, action, params);
|
|
115
|
+
}, "call"),
|
|
116
|
+
callStream: /* @__PURE__ */ __name((action, params) => {
|
|
117
|
+
return this.executeCallStream(capabilityId, action, params);
|
|
118
|
+
}, "callStream")
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
async executeCall(capabilityId, action, params) {
|
|
122
|
+
const url = `${this.baseURL}/api/capability/${capabilityId}`;
|
|
185
123
|
try {
|
|
186
124
|
const response = await fetch(url, {
|
|
187
125
|
method: "POST",
|
|
188
126
|
...this.options.fetchOptions,
|
|
189
127
|
headers: {
|
|
190
128
|
"Content-Type": "application/json",
|
|
191
|
-
...this.options.fetchOptions
|
|
129
|
+
...this.options.fetchOptions?.headers
|
|
192
130
|
},
|
|
193
131
|
body: JSON.stringify({
|
|
194
132
|
action,
|
|
@@ -196,21 +134,21 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
196
134
|
})
|
|
197
135
|
});
|
|
198
136
|
const data = await response.json();
|
|
199
|
-
if (!response.ok || data.
|
|
137
|
+
if (!response.ok || data.status_code !== ErrorCodes.SUCCESS) {
|
|
200
138
|
const errorResponse = data;
|
|
201
|
-
const errorCode = errorResponse.
|
|
139
|
+
const errorCode = errorResponse.status_code;
|
|
202
140
|
switch (errorCode) {
|
|
203
|
-
case
|
|
141
|
+
case ErrorCodes.CAPABILITY_NOT_FOUND:
|
|
204
142
|
throw new CapabilityNotFoundError(capabilityId, response.status);
|
|
205
|
-
case
|
|
206
|
-
throw new ActionNotFoundError(errorResponse.
|
|
207
|
-
case
|
|
208
|
-
case
|
|
143
|
+
case ErrorCodes.ACTION_NOT_FOUND:
|
|
144
|
+
throw new ActionNotFoundError(errorResponse.error_msg, response.status);
|
|
145
|
+
case ErrorCodes.PLUGIN_NOT_FOUND:
|
|
146
|
+
case ErrorCodes.EXECUTION_ERROR:
|
|
209
147
|
default:
|
|
210
|
-
throw new ExecutionError(errorResponse.
|
|
148
|
+
throw new ExecutionError(errorResponse.error_msg, response.status);
|
|
211
149
|
}
|
|
212
150
|
}
|
|
213
|
-
return data.data;
|
|
151
|
+
return data.data.output;
|
|
214
152
|
} catch (error) {
|
|
215
153
|
if (error instanceof CapabilityError) {
|
|
216
154
|
throw error;
|
|
@@ -218,39 +156,8 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
218
156
|
throw new NetworkError(error instanceof Error ? error.message : String(error));
|
|
219
157
|
}
|
|
220
158
|
}
|
|
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`;
|
|
159
|
+
async *executeCallStream(capabilityId, action, params) {
|
|
160
|
+
const url = `${this.baseURL}/api/capability/${capabilityId}/stream`;
|
|
254
161
|
let response;
|
|
255
162
|
try {
|
|
256
163
|
response = await fetch(url, {
|
|
@@ -258,7 +165,7 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
258
165
|
...this.options.fetchOptions,
|
|
259
166
|
headers: {
|
|
260
167
|
"Content-Type": "application/json",
|
|
261
|
-
...this.options.fetchOptions
|
|
168
|
+
...this.options.fetchOptions?.headers
|
|
262
169
|
},
|
|
263
170
|
body: JSON.stringify({
|
|
264
171
|
action,
|
|
@@ -289,23 +196,18 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
289
196
|
for (const line of lines) {
|
|
290
197
|
if (line.startsWith("data: ")) {
|
|
291
198
|
const data = line.slice(6);
|
|
292
|
-
if (data === "[DONE]") {
|
|
293
|
-
return;
|
|
294
|
-
}
|
|
295
199
|
try {
|
|
296
200
|
const parsed = JSON.parse(data);
|
|
297
|
-
if (parsed.
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
throw new ExecutionError(parsed.error);
|
|
201
|
+
if (parsed.status_code === ErrorCodes.SUCCESS && parsed.data) {
|
|
202
|
+
if (parsed.data.type === "content") {
|
|
203
|
+
yield parsed.data.delta.content;
|
|
204
|
+
if (parsed.data.finished) {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
} else if (parsed.data.type === "error") {
|
|
208
|
+
throw new ExecutionError(parsed.data.error.message);
|
|
306
209
|
}
|
|
307
210
|
}
|
|
308
|
-
yield parsed;
|
|
309
211
|
} catch (parseError) {
|
|
310
212
|
if (parseError instanceof CapabilityError) {
|
|
311
213
|
throw parseError;
|
|
@@ -330,5 +232,5 @@ function createClient(options) {
|
|
|
330
232
|
return new CapabilityClient(options);
|
|
331
233
|
}
|
|
332
234
|
__name(createClient, "createClient");
|
|
333
|
-
var
|
|
235
|
+
var capabilityClient = new CapabilityClient({});
|
|
334
236
|
//# 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":";;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;;;;;;;;;ACGO,IAAMA,mBAAN,MAAMA,yBAAwBC,MAAAA;EAMnC,YAAYC,SAAiBC,MAAcC,YAAqB;AAC9D,UAAMF,OAAAA;AALRC;;AAEAC;;AAIE,SAAKC,OAAO;AACZ,SAAKF,OAAOA;AACZ,SAAKC,aAAaA;EACpB;AACF;AAZqCH;AAA9B,IAAMD,kBAAN;AAiBA,IAAMM,6BAAN,MAAMA,mCAAkCN,gBAAAA;EAC7C,cAAc;AACZ,UAAM,iEAAiE,wBAAA;AACvE,SAAKK,OAAO;EACd;AACF;AAL+CL;AAAxC,IAAMM,4BAAN;AAUA,IAAMC,2BAAN,MAAMA,iCAAgCP,gBAAAA;EAC3C,YAAYQ,cAAsBJ,YAAqB;AACrD,UAAM,yBAAyBI,YAAAA,IAAgB,wBAAwBJ,UAAAA;AACvE,SAAKC,OAAO;EACd;AACF;AAL6CL;AAAtC,IAAMO,0BAAN;AAUA,IAAME,uBAAN,MAAMA,6BAA4BT,gBAAAA;EACvC,YAAYE,SAAiBE,YAAqB;AAChD,UAAMF,SAAS,oBAAoBE,UAAAA;AACnC,SAAKC,OAAO;EACd;AACF;AALyCL;AAAlC,IAAMS,sBAAN;AAUA,IAAMC,gBAAN,MAAMA,sBAAqBV,gBAAAA;EAChC,YAAYE,SAAiB;AAC3B,UAAMA,SAAS,eAAA;AACf,SAAKG,OAAO;EACd;AACF;AALkCL;AAA3B,IAAMU,eAAN;AAUA,IAAMC,kBAAN,MAAMA,wBAAuBX,gBAAAA;EAClC,YAAYE,SAAiBE,YAAqB;AAChD,UAAMF,SAAS,mBAAmBE,UAAAA;AAClC,SAAKC,OAAO;EACd;AACF;AALoCL;AAA7B,IAAMW,iBAAN;;;ACnDP,IAAMC,kBAAqD;EACzDC,SAAS;EACTC,cAAc,CAAC;EACfC,UAAU;AACZ;AAKO,IAAMC,oBAAN,MAAMA,kBAAAA;EAaX,YAAYC,SAAmC;AAZvCA;AACAC,wCAA4C,oBAAIC,IAAAA;AAChDC,wCAAe;AACfC,uCAAoC;AAU1C,SAAKJ,UAAU;MAAE,GAAGL;MAAiB,GAAGK;IAAQ;EAClD;;;;EANA,IAAIK,cAAuB;AACzB,WAAO,KAAKF;EACd;;;;EASA,MAAMG,OAAsB;AAC1B,QAAI,KAAKH,cAAc;AACrB;IACF;AAGA,QAAI,KAAKC,aAAa;AACpB,aAAO,KAAKA;IACd;AAEA,SAAKA,cAAc,KAAKG,OAAM;AAC9B,QAAI;AACF,YAAM,KAAKH;IACb,UAAA;AACE,WAAKA,cAAc;IACrB;EACF;EAEA,MAAcG,SAAwB;AACpC,UAAMC,MAAM,GAAG,KAAKR,QAAQJ,OAAO;AAEnC,QAAI;AACF,YAAMa,WAAW,MAAMC,MAAMF,KAAK;QAChCG,QAAQ;QACR,GAAG,KAAKX,QAAQH;QAChBe,SAAS;UACP,gBAAgB;UAChB,GAAG,KAAKZ,QAAQH,aAAae;QAC/B;MACF,CAAA;AAEA,UAAI,CAACH,SAASI,IAAI;AAChB,cAAM,IAAIC,aAAa,iCAAiCL,SAASM,MAAM,IAAIN,SAASO,UAAU,EAAE;MAClG;AAEA,YAAMC,OAAQ,MAAMR,SAASS,KAAI;AAEjC,UAAID,KAAKE,SAAS,GAAG;AACnB,cAAM,IAAIC,eAAgBH,KAA6BI,OAAO;MAChE;AAEA,WAAKpB,aAAaqB,MAAK;AACvB,iBAAWC,cAAeN,KAAoCA,MAAM;AAClE,aAAKhB,aAAauB,IAAID,WAAWE,IAAIF,UAAAA;MACvC;AAEA,WAAKpB,eAAe;IACtB,SAASuB,OAAO;AACd,UAAIA,iBAAiBC,iBAAiB;AACpC,cAAMD;MACR;AACA,YAAM,IAAIZ,aAAaY,iBAAiBE,QAAQF,MAAML,UAAUQ,OAAOH,KAAAA,CAAAA;IACzE;EACF;;;;EAKA,MAAcI,oBAAmC;AAC/C,QAAI,CAAC,KAAK3B,gBAAgB,KAAKH,QAAQF,UAAU;AAC/C,YAAM,KAAKQ,KAAI;IACjB;EACF;;;;;;;;EASA,MAAMyB,KACJC,cACAC,QACAC,QACY;AACZ,UAAM,KAAKJ,kBAAiB;AAG5B,QAAI,KAAK3B,gBAAgB,CAAC,KAAKF,aAAakC,IAAIH,YAAAA,GAAe;AAC7D,YAAM,IAAII,wBAAwBJ,YAAAA;IACpC;AAEA,UAAMxB,MAAM,GAAG,KAAKR,QAAQJ,OAAO,mBAAmBoC,YAAAA;AAEtD,QAAI;AACF,YAAMvB,WAAW,MAAMC,MAAMF,KAAK;QAChCG,QAAQ;QACR,GAAG,KAAKX,QAAQH;QAChBe,SAAS;UACP,gBAAgB;UAChB,GAAG,KAAKZ,QAAQH,aAAae;QAC/B;QACAyB,MAAMC,KAAKC,UAAU;UACnBN;UACAC,QAAQA,UAAU,CAAC;QACrB,CAAA;MACF,CAAA;AAEA,YAAMjB,OAAQ,MAAMR,SAASS,KAAI;AAEjC,UAAI,CAACT,SAASI,MAAMI,KAAKE,SAAS,GAAG;AACnC,cAAMqB,gBAAgBvB;AACtB,cAAMwB,YAAYD,cAAcd,SAAS;AAEzC,gBAAQe,WAAAA;UACN,KAAK;AACH,kBAAM,IAAIL,wBAAwBJ,cAAcvB,SAASM,MAAM;UACjE,KAAK;AACH,kBAAM,IAAI2B,oBAAoBF,cAAcnB,SAASZ,SAASM,MAAM;UACtE,KAAK;UACL,KAAK;UACL;AACE,kBAAM,IAAIK,eAAeoB,cAAcnB,SAASZ,SAASM,MAAM;QACnE;MACF;AAEA,aAAQE,KAAqBA;IAC/B,SAASS,OAAO;AACd,UAAIA,iBAAiBC,iBAAiB;AACpC,cAAMD;MACR;AACA,YAAM,IAAIZ,aAAaY,iBAAiBE,QAAQF,MAAML,UAAUQ,OAAOH,KAAAA,CAAAA;IACzE;EACF;;;;EAKAiB,cAAcX,cAA+B;AAC3C,WAAO,KAAK/B,aAAakC,IAAIH,YAAAA;EAC/B;;;;EAKA,MAAMY,mBAA8C;AAClD,UAAM,KAAKd,kBAAiB;AAC5B,WAAOe,MAAMC,KAAK,KAAK7C,aAAa8C,OAAM,CAAA;EAC5C;;;;EAKA,MAAMC,cAAchB,cAAsD;AACxE,UAAM,KAAKF,kBAAiB;AAC5B,WAAO,KAAK7B,aAAagD,IAAIjB,YAAAA,KAAiB;EAChD;;;;;;;;EASA,OAAOkB,WACLlB,cACAC,QACAC,QACkB;AAClB,UAAM,KAAKJ,kBAAiB;AAG5B,QAAI,KAAK3B,gBAAgB,CAAC,KAAKF,aAAakC,IAAIH,YAAAA,GAAe;AAC7D,YAAM,IAAII,wBAAwBJ,YAAAA;IACpC;AAEA,UAAMxB,MAAM,GAAG,KAAKR,QAAQJ,OAAO,mBAAmBoC,YAAAA;AAEtD,QAAIvB;AACJ,QAAI;AACFA,iBAAW,MAAMC,MAAMF,KAAK;QAC1BG,QAAQ;QACR,GAAG,KAAKX,QAAQH;QAChBe,SAAS;UACP,gBAAgB;UAChB,GAAG,KAAKZ,QAAQH,aAAae;QAC/B;QACAyB,MAAMC,KAAKC,UAAU;UACnBN;UACAC,QAAQA,UAAU,CAAC;QACrB,CAAA;MACF,CAAA;IACF,SAASR,OAAO;AACd,YAAM,IAAIZ,aAAaY,iBAAiBE,QAAQF,MAAML,UAAUQ,OAAOH,KAAAA,CAAAA;IACzE;AAEA,QAAI,CAACjB,SAASI,IAAI;AAChB,YAAM,IAAIC,aAAa,QAAQL,SAASM,MAAM,IAAIN,SAASO,UAAU,EAAE;IACzE;AAEA,QAAI,CAACP,SAAS4B,MAAM;AAClB,YAAM,IAAIvB,aAAa,uBAAA;IACzB;AAEA,UAAMqC,SAAS1C,SAAS4B,KAAKe,UAAS;AACtC,UAAMC,UAAU,IAAIC,YAAAA;AACpB,QAAIC,SAAS;AAEb,QAAI;AACF,aAAO,MAAM;AACX,cAAM,EAAEC,MAAMC,MAAK,IAAK,MAAMN,OAAOO,KAAI;AACzC,YAAIF,KAAM;AAEVD,kBAAUF,QAAQM,OAAOF,OAAO;UAAEG,QAAQ;QAAK,CAAA;AAC/C,cAAMC,QAAQN,OAAOO,MAAM,IAAA;AAC3BP,iBAASM,MAAME,IAAG,KAAM;AAExB,mBAAWC,QAAQH,OAAO;AACxB,cAAIG,KAAKC,WAAW,QAAA,GAAW;AAC7B,kBAAMhD,OAAO+C,KAAKE,MAAM,CAAA;AAGxB,gBAAIjD,SAAS,UAAU;AACrB;YACF;AAEA,gBAAI;AACF,oBAAMkD,SAAS7B,KAAK8B,MAAMnD,IAAAA;AAG1B,kBAAIkD,OAAOzC,OAAO;AAChB,sBAAMe,YAAY0B,OAAOhD,QAAQ;AACjC,wBAAQsB,WAAAA;kBACN,KAAK;AACH,0BAAM,IAAIL,wBAAwBJ,YAAAA;kBACpC,KAAK;AACH,0BAAM,IAAIU,oBAAoByB,OAAOzC,KAAK;kBAC5C;AACE,0BAAM,IAAIN,eAAe+C,OAAOzC,KAAK;gBACzC;cACF;AAEA,oBAAMyC;YACR,SAASE,YAAY;AAEnB,kBAAIA,sBAAsB1C,iBAAiB;AACzC,sBAAM0C;cACR;YAEF;UACF;QACF;MACF;IACF,SAAS3C,OAAO;AACd,UAAIA,iBAAiBC,iBAAiB;AACpC,cAAMD;MACR;AACA,YAAM,IAAIZ,aAAaY,iBAAiBE,QAAQF,MAAML,UAAUQ,OAAOH,KAAAA,CAAAA;IACzE,UAAA;AACEyB,aAAOmB,YAAW;IACpB;EACF;AACF;AAlRavE;AAAN,IAAMA,mBAAN;AAuRA,SAASwE,aAAavE,SAAiC;AAC5D,SAAO,IAAID,iBAAiBC,OAAAA;AAC9B;AAFgBuE;AAOT,IAAMC,SAAS,IAAIzE,iBAAAA;","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 /** 全局路径前缀,默认 ''。例如线上环境可设置为 '/spark/a' */\n baseURL?: string;\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 private baseURL: string;\n\n constructor(options?: CapabilityClientOptions) {\n this.options = options ?? {};\n // 移除末尾的斜杠,确保拼接时格式正确\n this.baseURL = (options?.baseURL ?? '').replace(/\\/+$/, '');\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 = `${this.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<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 = `${this.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 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\n});\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","baseURL","replace","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,47 @@
|
|
|
2
2
|
* 客户端配置选项
|
|
3
3
|
*/
|
|
4
4
|
interface CapabilityClientOptions {
|
|
5
|
-
/**
|
|
5
|
+
/** 全局路径前缀,默认 ''。例如线上环境可设置为 '/spark/a' */
|
|
6
6
|
baseURL?: string;
|
|
7
7
|
/** 自定义 fetch 配置 */
|
|
8
8
|
fetchOptions?: RequestInit;
|
|
9
|
-
/** 是否在创建时自动初始化,默认 true */
|
|
10
|
-
autoInit?: boolean;
|
|
11
9
|
}
|
|
12
10
|
/**
|
|
13
|
-
*
|
|
11
|
+
* 能力执行器接口
|
|
14
12
|
*/
|
|
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;
|
|
13
|
+
interface CapabilityExecutor {
|
|
45
14
|
/**
|
|
46
15
|
* 调用能力
|
|
47
|
-
* @param capabilityId - 能力 ID
|
|
48
16
|
* @param action - Action 名称
|
|
49
17
|
* @param params - 输入参数
|
|
50
18
|
* @returns Action 执行结果
|
|
51
19
|
*/
|
|
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>;
|
|
20
|
+
call<T = unknown>(action: string, params?: Record<string, unknown>): Promise<T>;
|
|
65
21
|
/**
|
|
66
22
|
* 流式调用能力
|
|
67
|
-
* @param capabilityId - 能力 ID
|
|
68
23
|
* @param action - Action 名称
|
|
69
24
|
* @param params - 输入参数
|
|
70
25
|
* @returns AsyncIterable,逐个 yield chunk
|
|
71
26
|
*/
|
|
72
|
-
callStream<T = unknown>(
|
|
27
|
+
callStream<T = unknown>(action: string, params?: Record<string, unknown>): AsyncIterable<T>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* 能力客户端
|
|
32
|
+
*/
|
|
33
|
+
declare class CapabilityClient {
|
|
34
|
+
private options;
|
|
35
|
+
private baseURL;
|
|
36
|
+
constructor(options?: CapabilityClientOptions);
|
|
37
|
+
/**
|
|
38
|
+
* 加载能力,返回执行器
|
|
39
|
+
* @param capabilityId - 能力 ID
|
|
40
|
+
* @returns 能力执行器
|
|
41
|
+
*/
|
|
42
|
+
load(capabilityId: string): CapabilityExecutor;
|
|
43
|
+
private createExecutor;
|
|
44
|
+
private executeCall;
|
|
45
|
+
private executeCallStream;
|
|
73
46
|
}
|
|
74
47
|
/**
|
|
75
48
|
* 创建自定义客户端
|
|
@@ -78,7 +51,7 @@ declare function createClient(options?: CapabilityClientOptions): CapabilityClie
|
|
|
78
51
|
/**
|
|
79
52
|
* 默认客户端实例
|
|
80
53
|
*/
|
|
81
|
-
declare const
|
|
54
|
+
declare const capabilityClient: CapabilityClient;
|
|
82
55
|
|
|
83
56
|
/**
|
|
84
57
|
* 能力调用错误基类
|
|
@@ -90,12 +63,6 @@ declare class CapabilityError extends Error {
|
|
|
90
63
|
statusCode?: number;
|
|
91
64
|
constructor(message: string, code: string, statusCode?: number);
|
|
92
65
|
}
|
|
93
|
-
/**
|
|
94
|
-
* 客户端未初始化错误
|
|
95
|
-
*/
|
|
96
|
-
declare class ClientNotInitializedError extends CapabilityError {
|
|
97
|
-
constructor();
|
|
98
|
-
}
|
|
99
66
|
/**
|
|
100
67
|
* 能力不存在错误
|
|
101
68
|
*/
|
|
@@ -121,4 +88,4 @@ declare class ExecutionError extends CapabilityError {
|
|
|
121
88
|
constructor(message: string, statusCode?: number);
|
|
122
89
|
}
|
|
123
90
|
|
|
124
|
-
export { ActionNotFoundError, CapabilityClient, type CapabilityClientOptions, CapabilityError, type
|
|
91
|
+
export { ActionNotFoundError, CapabilityClient, type CapabilityClientOptions, CapabilityError, type CapabilityExecutor, CapabilityNotFoundError, ExecutionError, NetworkError, capabilityClient, createClient };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,74 +2,47 @@
|
|
|
2
2
|
* 客户端配置选项
|
|
3
3
|
*/
|
|
4
4
|
interface CapabilityClientOptions {
|
|
5
|
-
/**
|
|
5
|
+
/** 全局路径前缀,默认 ''。例如线上环境可设置为 '/spark/a' */
|
|
6
6
|
baseURL?: string;
|
|
7
7
|
/** 自定义 fetch 配置 */
|
|
8
8
|
fetchOptions?: RequestInit;
|
|
9
|
-
/** 是否在创建时自动初始化,默认 true */
|
|
10
|
-
autoInit?: boolean;
|
|
11
9
|
}
|
|
12
10
|
/**
|
|
13
|
-
*
|
|
11
|
+
* 能力执行器接口
|
|
14
12
|
*/
|
|
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;
|
|
13
|
+
interface CapabilityExecutor {
|
|
45
14
|
/**
|
|
46
15
|
* 调用能力
|
|
47
|
-
* @param capabilityId - 能力 ID
|
|
48
16
|
* @param action - Action 名称
|
|
49
17
|
* @param params - 输入参数
|
|
50
18
|
* @returns Action 执行结果
|
|
51
19
|
*/
|
|
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>;
|
|
20
|
+
call<T = unknown>(action: string, params?: Record<string, unknown>): Promise<T>;
|
|
65
21
|
/**
|
|
66
22
|
* 流式调用能力
|
|
67
|
-
* @param capabilityId - 能力 ID
|
|
68
23
|
* @param action - Action 名称
|
|
69
24
|
* @param params - 输入参数
|
|
70
25
|
* @returns AsyncIterable,逐个 yield chunk
|
|
71
26
|
*/
|
|
72
|
-
callStream<T = unknown>(
|
|
27
|
+
callStream<T = unknown>(action: string, params?: Record<string, unknown>): AsyncIterable<T>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* 能力客户端
|
|
32
|
+
*/
|
|
33
|
+
declare class CapabilityClient {
|
|
34
|
+
private options;
|
|
35
|
+
private baseURL;
|
|
36
|
+
constructor(options?: CapabilityClientOptions);
|
|
37
|
+
/**
|
|
38
|
+
* 加载能力,返回执行器
|
|
39
|
+
* @param capabilityId - 能力 ID
|
|
40
|
+
* @returns 能力执行器
|
|
41
|
+
*/
|
|
42
|
+
load(capabilityId: string): CapabilityExecutor;
|
|
43
|
+
private createExecutor;
|
|
44
|
+
private executeCall;
|
|
45
|
+
private executeCallStream;
|
|
73
46
|
}
|
|
74
47
|
/**
|
|
75
48
|
* 创建自定义客户端
|
|
@@ -78,7 +51,7 @@ declare function createClient(options?: CapabilityClientOptions): CapabilityClie
|
|
|
78
51
|
/**
|
|
79
52
|
* 默认客户端实例
|
|
80
53
|
*/
|
|
81
|
-
declare const
|
|
54
|
+
declare const capabilityClient: CapabilityClient;
|
|
82
55
|
|
|
83
56
|
/**
|
|
84
57
|
* 能力调用错误基类
|
|
@@ -90,12 +63,6 @@ declare class CapabilityError extends Error {
|
|
|
90
63
|
statusCode?: number;
|
|
91
64
|
constructor(message: string, code: string, statusCode?: number);
|
|
92
65
|
}
|
|
93
|
-
/**
|
|
94
|
-
* 客户端未初始化错误
|
|
95
|
-
*/
|
|
96
|
-
declare class ClientNotInitializedError extends CapabilityError {
|
|
97
|
-
constructor();
|
|
98
|
-
}
|
|
99
66
|
/**
|
|
100
67
|
* 能力不存在错误
|
|
101
68
|
*/
|
|
@@ -121,4 +88,4 @@ declare class ExecutionError extends CapabilityError {
|
|
|
121
88
|
constructor(message: string, statusCode?: number);
|
|
122
89
|
}
|
|
123
90
|
|
|
124
|
-
export { ActionNotFoundError, CapabilityClient, type CapabilityClientOptions, CapabilityError, type
|
|
91
|
+
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,40 @@ __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
|
-
__publicField(this, "
|
|
72
|
-
|
|
73
|
-
|
|
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
|
+
__publicField(this, "baseURL");
|
|
69
|
+
this.options = options ?? {};
|
|
70
|
+
this.baseURL = (options?.baseURL ?? "").replace(/\/+$/, "");
|
|
131
71
|
}
|
|
132
72
|
/**
|
|
133
|
-
*
|
|
134
|
-
*/
|
|
135
|
-
async ensureInitialized() {
|
|
136
|
-
if (!this._initialized && this.options.autoInit) {
|
|
137
|
-
await this.init();
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* 调用能力
|
|
73
|
+
* 加载能力,返回执行器
|
|
142
74
|
* @param capabilityId - 能力 ID
|
|
143
|
-
* @
|
|
144
|
-
* @param params - 输入参数
|
|
145
|
-
* @returns Action 执行结果
|
|
75
|
+
* @returns 能力执行器
|
|
146
76
|
*/
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
77
|
+
load(capabilityId) {
|
|
78
|
+
return this.createExecutor(capabilityId);
|
|
79
|
+
}
|
|
80
|
+
createExecutor(capabilityId) {
|
|
81
|
+
return {
|
|
82
|
+
call: /* @__PURE__ */ __name((action, params) => {
|
|
83
|
+
return this.executeCall(capabilityId, action, params);
|
|
84
|
+
}, "call"),
|
|
85
|
+
callStream: /* @__PURE__ */ __name((action, params) => {
|
|
86
|
+
return this.executeCallStream(capabilityId, action, params);
|
|
87
|
+
}, "callStream")
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
async executeCall(capabilityId, action, params) {
|
|
91
|
+
const url = `${this.baseURL}/api/capability/${capabilityId}`;
|
|
153
92
|
try {
|
|
154
93
|
const response = await fetch(url, {
|
|
155
94
|
method: "POST",
|
|
156
95
|
...this.options.fetchOptions,
|
|
157
96
|
headers: {
|
|
158
97
|
"Content-Type": "application/json",
|
|
159
|
-
...this.options.fetchOptions
|
|
98
|
+
...this.options.fetchOptions?.headers
|
|
160
99
|
},
|
|
161
100
|
body: JSON.stringify({
|
|
162
101
|
action,
|
|
@@ -164,21 +103,21 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
164
103
|
})
|
|
165
104
|
});
|
|
166
105
|
const data = await response.json();
|
|
167
|
-
if (!response.ok || data.
|
|
106
|
+
if (!response.ok || data.status_code !== ErrorCodes.SUCCESS) {
|
|
168
107
|
const errorResponse = data;
|
|
169
|
-
const errorCode = errorResponse.
|
|
108
|
+
const errorCode = errorResponse.status_code;
|
|
170
109
|
switch (errorCode) {
|
|
171
|
-
case
|
|
110
|
+
case ErrorCodes.CAPABILITY_NOT_FOUND:
|
|
172
111
|
throw new CapabilityNotFoundError(capabilityId, response.status);
|
|
173
|
-
case
|
|
174
|
-
throw new ActionNotFoundError(errorResponse.
|
|
175
|
-
case
|
|
176
|
-
case
|
|
112
|
+
case ErrorCodes.ACTION_NOT_FOUND:
|
|
113
|
+
throw new ActionNotFoundError(errorResponse.error_msg, response.status);
|
|
114
|
+
case ErrorCodes.PLUGIN_NOT_FOUND:
|
|
115
|
+
case ErrorCodes.EXECUTION_ERROR:
|
|
177
116
|
default:
|
|
178
|
-
throw new ExecutionError(errorResponse.
|
|
117
|
+
throw new ExecutionError(errorResponse.error_msg, response.status);
|
|
179
118
|
}
|
|
180
119
|
}
|
|
181
|
-
return data.data;
|
|
120
|
+
return data.data.output;
|
|
182
121
|
} catch (error) {
|
|
183
122
|
if (error instanceof CapabilityError) {
|
|
184
123
|
throw error;
|
|
@@ -186,39 +125,8 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
186
125
|
throw new NetworkError(error instanceof Error ? error.message : String(error));
|
|
187
126
|
}
|
|
188
127
|
}
|
|
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`;
|
|
128
|
+
async *executeCallStream(capabilityId, action, params) {
|
|
129
|
+
const url = `${this.baseURL}/api/capability/${capabilityId}/stream`;
|
|
222
130
|
let response;
|
|
223
131
|
try {
|
|
224
132
|
response = await fetch(url, {
|
|
@@ -226,7 +134,7 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
226
134
|
...this.options.fetchOptions,
|
|
227
135
|
headers: {
|
|
228
136
|
"Content-Type": "application/json",
|
|
229
|
-
...this.options.fetchOptions
|
|
137
|
+
...this.options.fetchOptions?.headers
|
|
230
138
|
},
|
|
231
139
|
body: JSON.stringify({
|
|
232
140
|
action,
|
|
@@ -257,23 +165,18 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
257
165
|
for (const line of lines) {
|
|
258
166
|
if (line.startsWith("data: ")) {
|
|
259
167
|
const data = line.slice(6);
|
|
260
|
-
if (data === "[DONE]") {
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
168
|
try {
|
|
264
169
|
const parsed = JSON.parse(data);
|
|
265
|
-
if (parsed.
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
throw new ExecutionError(parsed.error);
|
|
170
|
+
if (parsed.status_code === ErrorCodes.SUCCESS && parsed.data) {
|
|
171
|
+
if (parsed.data.type === "content") {
|
|
172
|
+
yield parsed.data.delta.content;
|
|
173
|
+
if (parsed.data.finished) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
} else if (parsed.data.type === "error") {
|
|
177
|
+
throw new ExecutionError(parsed.data.error.message);
|
|
274
178
|
}
|
|
275
179
|
}
|
|
276
|
-
yield parsed;
|
|
277
180
|
} catch (parseError) {
|
|
278
181
|
if (parseError instanceof CapabilityError) {
|
|
279
182
|
throw parseError;
|
|
@@ -298,16 +201,15 @@ function createClient(options) {
|
|
|
298
201
|
return new CapabilityClient(options);
|
|
299
202
|
}
|
|
300
203
|
__name(createClient, "createClient");
|
|
301
|
-
var
|
|
204
|
+
var capabilityClient = new CapabilityClient({});
|
|
302
205
|
export {
|
|
303
206
|
ActionNotFoundError,
|
|
304
207
|
CapabilityClient,
|
|
305
208
|
CapabilityError,
|
|
306
209
|
CapabilityNotFoundError,
|
|
307
|
-
ClientNotInitializedError,
|
|
308
210
|
ExecutionError,
|
|
309
211
|
NetworkError,
|
|
310
|
-
|
|
212
|
+
capabilityClient,
|
|
311
213
|
createClient
|
|
312
214
|
};
|
|
313
215
|
//# 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 /** 全局路径前缀,默认 ''。例如线上环境可设置为 '/spark/a' */\n baseURL?: string;\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 private baseURL: string;\n\n constructor(options?: CapabilityClientOptions) {\n this.options = options ?? {};\n // 移除末尾的斜杠,确保拼接时格式正确\n this.baseURL = (options?.baseURL ?? '').replace(/\\/+$/, '');\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 = `${this.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<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 = `${this.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 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\n});\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","baseURL","replace","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"]}
|