@lark-apaas/client-capability 0.1.1 → 0.1.2-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/dist/index.cjs +84 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -1
- package/dist/index.d.ts +13 -1
- package/dist/index.js +84 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -93,12 +93,21 @@ __name(_ExecutionError, "ExecutionError");
|
|
|
93
93
|
var ExecutionError = _ExecutionError;
|
|
94
94
|
|
|
95
95
|
// src/client.ts
|
|
96
|
+
var LOG_PREFIX = "[CapabilityClient]";
|
|
97
|
+
var defaultLogger = {
|
|
98
|
+
debug: console.debug.bind(console),
|
|
99
|
+
info: console.info.bind(console),
|
|
100
|
+
warn: console.warn.bind(console),
|
|
101
|
+
error: console.error.bind(console)
|
|
102
|
+
};
|
|
96
103
|
var _CapabilityClient = class _CapabilityClient {
|
|
97
104
|
constructor(options) {
|
|
98
105
|
__publicField(this, "options");
|
|
99
106
|
__publicField(this, "baseURL");
|
|
107
|
+
__publicField(this, "logger");
|
|
100
108
|
this.options = options ?? {};
|
|
101
109
|
this.baseURL = (options?.baseURL ?? "").replace(/\/+$/, "");
|
|
110
|
+
this.logger = options?.logger ?? defaultLogger;
|
|
102
111
|
}
|
|
103
112
|
/**
|
|
104
113
|
* 加载能力,返回执行器
|
|
@@ -120,6 +129,10 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
120
129
|
}
|
|
121
130
|
async executeCall(capabilityId, action, params) {
|
|
122
131
|
const url = `${this.baseURL}/api/capability/${capabilityId}`;
|
|
132
|
+
const requestParams = params ?? {};
|
|
133
|
+
this.logger.info(LOG_PREFIX, `call start: capabilityId=${capabilityId}, action=${action}`, {
|
|
134
|
+
params: requestParams
|
|
135
|
+
});
|
|
123
136
|
try {
|
|
124
137
|
const response = await fetch(url, {
|
|
125
138
|
method: "POST",
|
|
@@ -130,7 +143,7 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
130
143
|
},
|
|
131
144
|
body: JSON.stringify({
|
|
132
145
|
action,
|
|
133
|
-
params:
|
|
146
|
+
params: requestParams
|
|
134
147
|
})
|
|
135
148
|
});
|
|
136
149
|
const data = await response.json();
|
|
@@ -148,8 +161,16 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
148
161
|
throw new ExecutionError(errorResponse.error_msg, response.status);
|
|
149
162
|
}
|
|
150
163
|
}
|
|
151
|
-
|
|
164
|
+
const result = data.data.output;
|
|
165
|
+
this.logger.info(LOG_PREFIX, `call success: capabilityId=${capabilityId}, action=${action}`, {
|
|
166
|
+
result
|
|
167
|
+
});
|
|
168
|
+
return result;
|
|
152
169
|
} catch (error) {
|
|
170
|
+
this.logger.error(LOG_PREFIX, `call failed: capabilityId=${capabilityId}, action=${action}`, {
|
|
171
|
+
params: requestParams,
|
|
172
|
+
error
|
|
173
|
+
});
|
|
153
174
|
if (error instanceof CapabilityError) {
|
|
154
175
|
throw error;
|
|
155
176
|
}
|
|
@@ -158,6 +179,10 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
158
179
|
}
|
|
159
180
|
async *executeCallStream(capabilityId, action, params) {
|
|
160
181
|
const url = `${this.baseURL}/api/capability/${capabilityId}/stream`;
|
|
182
|
+
const requestParams = params ?? {};
|
|
183
|
+
this.logger.info(LOG_PREFIX, `callStream start: capabilityId=${capabilityId}, action=${action}`, {
|
|
184
|
+
params: requestParams
|
|
185
|
+
});
|
|
161
186
|
let response;
|
|
162
187
|
try {
|
|
163
188
|
response = await fetch(url, {
|
|
@@ -169,21 +194,38 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
169
194
|
},
|
|
170
195
|
body: JSON.stringify({
|
|
171
196
|
action,
|
|
172
|
-
params:
|
|
197
|
+
params: requestParams
|
|
173
198
|
})
|
|
174
199
|
});
|
|
175
200
|
} catch (error) {
|
|
201
|
+
this.logger.error(LOG_PREFIX, `callStream failed: capabilityId=${capabilityId}, action=${action}`, {
|
|
202
|
+
params: requestParams,
|
|
203
|
+
error
|
|
204
|
+
});
|
|
176
205
|
throw new NetworkError(error instanceof Error ? error.message : String(error));
|
|
177
206
|
}
|
|
178
207
|
if (!response.ok) {
|
|
179
|
-
|
|
208
|
+
const errMsg = `HTTP ${response.status} ${response.statusText}`;
|
|
209
|
+
this.logger.error(LOG_PREFIX, `callStream failed: capabilityId=${capabilityId}, action=${action}`, {
|
|
210
|
+
params: requestParams,
|
|
211
|
+
error: errMsg
|
|
212
|
+
});
|
|
213
|
+
throw new NetworkError(errMsg);
|
|
180
214
|
}
|
|
181
215
|
if (!response.body) {
|
|
182
|
-
|
|
216
|
+
const errMsg = "Response body is null";
|
|
217
|
+
this.logger.error(LOG_PREFIX, `callStream failed: capabilityId=${capabilityId}, action=${action}`, {
|
|
218
|
+
params: requestParams,
|
|
219
|
+
error: errMsg
|
|
220
|
+
});
|
|
221
|
+
throw new NetworkError(errMsg);
|
|
183
222
|
}
|
|
184
223
|
const reader = response.body.getReader();
|
|
185
224
|
const decoder = new TextDecoder();
|
|
186
225
|
let buffer = "";
|
|
226
|
+
let chunkCount = 0;
|
|
227
|
+
let aggregatedContent = "";
|
|
228
|
+
let canAggregate = true;
|
|
187
229
|
try {
|
|
188
230
|
while (true) {
|
|
189
231
|
const { done, value } = await reader.read();
|
|
@@ -200,8 +242,26 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
200
242
|
const parsed = JSON.parse(data);
|
|
201
243
|
if (parsed.status_code === ErrorCodes.SUCCESS && parsed.data) {
|
|
202
244
|
if (parsed.data.type === "content") {
|
|
203
|
-
|
|
245
|
+
chunkCount++;
|
|
246
|
+
const delta = parsed.data.delta;
|
|
247
|
+
if (canAggregate) {
|
|
248
|
+
const content = delta?.content;
|
|
249
|
+
if (typeof content === "string") {
|
|
250
|
+
aggregatedContent += content;
|
|
251
|
+
} else {
|
|
252
|
+
canAggregate = false;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
yield delta;
|
|
204
256
|
if (parsed.data.finished) {
|
|
257
|
+
const resultInfo2 = canAggregate ? {
|
|
258
|
+
chunkCount,
|
|
259
|
+
result: aggregatedContent
|
|
260
|
+
} : {
|
|
261
|
+
chunkCount,
|
|
262
|
+
resultLength: aggregatedContent.length || chunkCount
|
|
263
|
+
};
|
|
264
|
+
this.logger.info(LOG_PREFIX, `callStream end: capabilityId=${capabilityId}, action=${action}`, resultInfo2);
|
|
205
265
|
return;
|
|
206
266
|
}
|
|
207
267
|
} else if (parsed.data.type === "error") {
|
|
@@ -210,13 +270,31 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
210
270
|
}
|
|
211
271
|
} catch (parseError) {
|
|
212
272
|
if (parseError instanceof CapabilityError) {
|
|
273
|
+
this.logger.error(LOG_PREFIX, `callStream failed: capabilityId=${capabilityId}, action=${action}`, {
|
|
274
|
+
params: requestParams,
|
|
275
|
+
error: parseError,
|
|
276
|
+
chunkCount
|
|
277
|
+
});
|
|
213
278
|
throw parseError;
|
|
214
279
|
}
|
|
215
280
|
}
|
|
216
281
|
}
|
|
217
282
|
}
|
|
218
283
|
}
|
|
284
|
+
const resultInfo = canAggregate ? {
|
|
285
|
+
chunkCount,
|
|
286
|
+
result: aggregatedContent
|
|
287
|
+
} : {
|
|
288
|
+
chunkCount,
|
|
289
|
+
resultLength: aggregatedContent.length || chunkCount
|
|
290
|
+
};
|
|
291
|
+
this.logger.info(LOG_PREFIX, `callStream end: capabilityId=${capabilityId}, action=${action}`, resultInfo);
|
|
219
292
|
} catch (error) {
|
|
293
|
+
this.logger.error(LOG_PREFIX, `callStream failed: capabilityId=${capabilityId}, action=${action}`, {
|
|
294
|
+
params: requestParams,
|
|
295
|
+
error,
|
|
296
|
+
chunkCount
|
|
297
|
+
});
|
|
220
298
|
if (error instanceof CapabilityError) {
|
|
221
299
|
throw error;
|
|
222
300
|
}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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: unknown;\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 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","finished","parseError","releaseLock","createClient","capabilityClient"]}
|
|
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, Logger } from './types';\n\n// 错误类型\nexport {\n CapabilityError,\n CapabilityNotFoundError,\n ActionNotFoundError,\n NetworkError,\n ExecutionError,\n} from './errors';\n","/**\n * Logger 接口,兼容 console 和 @lark-apaas/toolkit 的 logger\n */\nexport interface Logger {\n debug(message: unknown, ...args: unknown[]): void;\n info(message: unknown, ...args: unknown[]): void;\n warn(message: unknown, ...args: unknown[]): void;\n error(message: unknown, ...args: unknown[]): void;\n}\n\n/**\n * 客户端配置选项\n */\nexport interface CapabilityClientOptions {\n /** 全局路径前缀,默认 ''。例如线上环境可设置为 '/spark/a' */\n baseURL?: string;\n /** 自定义 fetch 配置 */\n fetchOptions?: RequestInit;\n /** 自定义 logger,默认使用 console */\n logger?: Logger;\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: unknown;\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 Logger,\n} from './types';\nimport { ErrorCodes } from './types';\n\nconst LOG_PREFIX = '[CapabilityClient]';\n\nconst defaultLogger: Logger = {\n debug: console.debug.bind(console),\n info: console.info.bind(console),\n warn: console.warn.bind(console),\n error: console.error.bind(console),\n};\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 private logger: Logger;\n\n constructor(options?: CapabilityClientOptions) {\n this.options = options ?? {};\n // 移除末尾的斜杠,确保拼接时格式正确\n this.baseURL = (options?.baseURL ?? '').replace(/\\/+$/, '');\n this.logger = options?.logger ?? defaultLogger;\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 const requestParams = params ?? {};\n\n this.logger.info(LOG_PREFIX, `call start: capabilityId=${capabilityId}, action=${action}`, { params: requestParams });\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: requestParams,\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 const result = (data as { data: ExecuteResponseData }).data.output as T;\n\n this.logger.info(LOG_PREFIX, `call success: capabilityId=${capabilityId}, action=${action}`, { result });\n\n return result;\n } catch (error) {\n this.logger.error(LOG_PREFIX, `call failed: capabilityId=${capabilityId}, action=${action}`, { params: requestParams, 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 const requestParams = params ?? {};\n\n this.logger.info(LOG_PREFIX, `callStream start: capabilityId=${capabilityId}, action=${action}`, { params: requestParams });\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: requestParams,\n }),\n });\n } catch (error) {\n this.logger.error(LOG_PREFIX, `callStream failed: capabilityId=${capabilityId}, action=${action}`, { params: requestParams, error });\n throw new NetworkError(error instanceof Error ? error.message : String(error));\n }\n\n if (!response.ok) {\n const errMsg = `HTTP ${response.status} ${response.statusText}`;\n this.logger.error(LOG_PREFIX, `callStream failed: capabilityId=${capabilityId}, action=${action}`, { params: requestParams, error: errMsg });\n throw new NetworkError(errMsg);\n }\n\n if (!response.body) {\n const errMsg = 'Response body is null';\n this.logger.error(LOG_PREFIX, `callStream failed: capabilityId=${capabilityId}, action=${action}`, { params: requestParams, error: errMsg });\n throw new NetworkError(errMsg);\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n let chunkCount = 0;\n let aggregatedContent = '';\n let canAggregate = true;\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 chunkCount++;\n const delta = parsed.data.delta as T;\n\n // 尝试聚合 content 字段\n if (canAggregate) {\n const content = (delta as Record<string, unknown>)?.content;\n if (typeof content === 'string') {\n aggregatedContent += content;\n } else {\n canAggregate = false;\n }\n }\n\n yield delta;\n\n if (parsed.data.finished) {\n const resultInfo = canAggregate\n ? { chunkCount, result: aggregatedContent }\n : { chunkCount, resultLength: aggregatedContent.length || chunkCount };\n this.logger.info(LOG_PREFIX, `callStream end: capabilityId=${capabilityId}, action=${action}`, resultInfo);\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 this.logger.error(LOG_PREFIX, `callStream failed: capabilityId=${capabilityId}, action=${action}`, { params: requestParams, error: parseError, chunkCount });\n throw parseError;\n }\n // 忽略非 JSON 行\n }\n }\n }\n }\n const resultInfo = canAggregate\n ? { chunkCount, result: aggregatedContent }\n : { chunkCount, resultLength: aggregatedContent.length || chunkCount };\n this.logger.info(LOG_PREFIX, `callStream end: capabilityId=${capabilityId}, action=${action}`, resultInfo);\n } catch (error) {\n this.logger.error(LOG_PREFIX, `callStream failed: capabilityId=${capabilityId}, action=${action}`, { params: requestParams, error, chunkCount });\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","LOG_PREFIX","defaultLogger","debug","console","bind","info","warn","error","CapabilityClient","options","baseURL","logger","replace","load","capabilityId","createExecutor","call","action","params","executeCall","callStream","executeCallStream","url","requestParams","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","result","output","CapabilityError","NetworkError","Error","message","String","errMsg","statusText","reader","getReader","decoder","TextDecoder","buffer","chunkCount","aggregatedContent","canAggregate","done","value","read","decode","stream","lines","split","pop","line","startsWith","slice","parsed","parse","type","delta","content","finished","resultInfo","resultLength","length","parseError","releaseLock","createClient","capabilityClient"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger 接口,兼容 console 和 @lark-apaas/toolkit 的 logger
|
|
3
|
+
*/
|
|
4
|
+
interface Logger {
|
|
5
|
+
debug(message: unknown, ...args: unknown[]): void;
|
|
6
|
+
info(message: unknown, ...args: unknown[]): void;
|
|
7
|
+
warn(message: unknown, ...args: unknown[]): void;
|
|
8
|
+
error(message: unknown, ...args: unknown[]): void;
|
|
9
|
+
}
|
|
1
10
|
/**
|
|
2
11
|
* 客户端配置选项
|
|
3
12
|
*/
|
|
@@ -6,6 +15,8 @@ interface CapabilityClientOptions {
|
|
|
6
15
|
baseURL?: string;
|
|
7
16
|
/** 自定义 fetch 配置 */
|
|
8
17
|
fetchOptions?: RequestInit;
|
|
18
|
+
/** 自定义 logger,默认使用 console */
|
|
19
|
+
logger?: Logger;
|
|
9
20
|
}
|
|
10
21
|
/**
|
|
11
22
|
* 能力执行器接口
|
|
@@ -33,6 +44,7 @@ interface CapabilityExecutor {
|
|
|
33
44
|
declare class CapabilityClient {
|
|
34
45
|
private options;
|
|
35
46
|
private baseURL;
|
|
47
|
+
private logger;
|
|
36
48
|
constructor(options?: CapabilityClientOptions);
|
|
37
49
|
/**
|
|
38
50
|
* 加载能力,返回执行器
|
|
@@ -88,4 +100,4 @@ declare class ExecutionError extends CapabilityError {
|
|
|
88
100
|
constructor(message: string, statusCode?: number);
|
|
89
101
|
}
|
|
90
102
|
|
|
91
|
-
export { ActionNotFoundError, CapabilityClient, type CapabilityClientOptions, CapabilityError, type CapabilityExecutor, CapabilityNotFoundError, ExecutionError, NetworkError, capabilityClient, createClient };
|
|
103
|
+
export { ActionNotFoundError, CapabilityClient, type CapabilityClientOptions, CapabilityError, type CapabilityExecutor, CapabilityNotFoundError, ExecutionError, type Logger, NetworkError, capabilityClient, createClient };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger 接口,兼容 console 和 @lark-apaas/toolkit 的 logger
|
|
3
|
+
*/
|
|
4
|
+
interface Logger {
|
|
5
|
+
debug(message: unknown, ...args: unknown[]): void;
|
|
6
|
+
info(message: unknown, ...args: unknown[]): void;
|
|
7
|
+
warn(message: unknown, ...args: unknown[]): void;
|
|
8
|
+
error(message: unknown, ...args: unknown[]): void;
|
|
9
|
+
}
|
|
1
10
|
/**
|
|
2
11
|
* 客户端配置选项
|
|
3
12
|
*/
|
|
@@ -6,6 +15,8 @@ interface CapabilityClientOptions {
|
|
|
6
15
|
baseURL?: string;
|
|
7
16
|
/** 自定义 fetch 配置 */
|
|
8
17
|
fetchOptions?: RequestInit;
|
|
18
|
+
/** 自定义 logger,默认使用 console */
|
|
19
|
+
logger?: Logger;
|
|
9
20
|
}
|
|
10
21
|
/**
|
|
11
22
|
* 能力执行器接口
|
|
@@ -33,6 +44,7 @@ interface CapabilityExecutor {
|
|
|
33
44
|
declare class CapabilityClient {
|
|
34
45
|
private options;
|
|
35
46
|
private baseURL;
|
|
47
|
+
private logger;
|
|
36
48
|
constructor(options?: CapabilityClientOptions);
|
|
37
49
|
/**
|
|
38
50
|
* 加载能力,返回执行器
|
|
@@ -88,4 +100,4 @@ declare class ExecutionError extends CapabilityError {
|
|
|
88
100
|
constructor(message: string, statusCode?: number);
|
|
89
101
|
}
|
|
90
102
|
|
|
91
|
-
export { ActionNotFoundError, CapabilityClient, type CapabilityClientOptions, CapabilityError, type CapabilityExecutor, CapabilityNotFoundError, ExecutionError, NetworkError, capabilityClient, createClient };
|
|
103
|
+
export { ActionNotFoundError, CapabilityClient, type CapabilityClientOptions, CapabilityError, type CapabilityExecutor, CapabilityNotFoundError, ExecutionError, type Logger, NetworkError, capabilityClient, createClient };
|
package/dist/index.js
CHANGED
|
@@ -62,12 +62,21 @@ __name(_ExecutionError, "ExecutionError");
|
|
|
62
62
|
var ExecutionError = _ExecutionError;
|
|
63
63
|
|
|
64
64
|
// src/client.ts
|
|
65
|
+
var LOG_PREFIX = "[CapabilityClient]";
|
|
66
|
+
var defaultLogger = {
|
|
67
|
+
debug: console.debug.bind(console),
|
|
68
|
+
info: console.info.bind(console),
|
|
69
|
+
warn: console.warn.bind(console),
|
|
70
|
+
error: console.error.bind(console)
|
|
71
|
+
};
|
|
65
72
|
var _CapabilityClient = class _CapabilityClient {
|
|
66
73
|
constructor(options) {
|
|
67
74
|
__publicField(this, "options");
|
|
68
75
|
__publicField(this, "baseURL");
|
|
76
|
+
__publicField(this, "logger");
|
|
69
77
|
this.options = options ?? {};
|
|
70
78
|
this.baseURL = (options?.baseURL ?? "").replace(/\/+$/, "");
|
|
79
|
+
this.logger = options?.logger ?? defaultLogger;
|
|
71
80
|
}
|
|
72
81
|
/**
|
|
73
82
|
* 加载能力,返回执行器
|
|
@@ -89,6 +98,10 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
89
98
|
}
|
|
90
99
|
async executeCall(capabilityId, action, params) {
|
|
91
100
|
const url = `${this.baseURL}/api/capability/${capabilityId}`;
|
|
101
|
+
const requestParams = params ?? {};
|
|
102
|
+
this.logger.info(LOG_PREFIX, `call start: capabilityId=${capabilityId}, action=${action}`, {
|
|
103
|
+
params: requestParams
|
|
104
|
+
});
|
|
92
105
|
try {
|
|
93
106
|
const response = await fetch(url, {
|
|
94
107
|
method: "POST",
|
|
@@ -99,7 +112,7 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
99
112
|
},
|
|
100
113
|
body: JSON.stringify({
|
|
101
114
|
action,
|
|
102
|
-
params:
|
|
115
|
+
params: requestParams
|
|
103
116
|
})
|
|
104
117
|
});
|
|
105
118
|
const data = await response.json();
|
|
@@ -117,8 +130,16 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
117
130
|
throw new ExecutionError(errorResponse.error_msg, response.status);
|
|
118
131
|
}
|
|
119
132
|
}
|
|
120
|
-
|
|
133
|
+
const result = data.data.output;
|
|
134
|
+
this.logger.info(LOG_PREFIX, `call success: capabilityId=${capabilityId}, action=${action}`, {
|
|
135
|
+
result
|
|
136
|
+
});
|
|
137
|
+
return result;
|
|
121
138
|
} catch (error) {
|
|
139
|
+
this.logger.error(LOG_PREFIX, `call failed: capabilityId=${capabilityId}, action=${action}`, {
|
|
140
|
+
params: requestParams,
|
|
141
|
+
error
|
|
142
|
+
});
|
|
122
143
|
if (error instanceof CapabilityError) {
|
|
123
144
|
throw error;
|
|
124
145
|
}
|
|
@@ -127,6 +148,10 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
127
148
|
}
|
|
128
149
|
async *executeCallStream(capabilityId, action, params) {
|
|
129
150
|
const url = `${this.baseURL}/api/capability/${capabilityId}/stream`;
|
|
151
|
+
const requestParams = params ?? {};
|
|
152
|
+
this.logger.info(LOG_PREFIX, `callStream start: capabilityId=${capabilityId}, action=${action}`, {
|
|
153
|
+
params: requestParams
|
|
154
|
+
});
|
|
130
155
|
let response;
|
|
131
156
|
try {
|
|
132
157
|
response = await fetch(url, {
|
|
@@ -138,21 +163,38 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
138
163
|
},
|
|
139
164
|
body: JSON.stringify({
|
|
140
165
|
action,
|
|
141
|
-
params:
|
|
166
|
+
params: requestParams
|
|
142
167
|
})
|
|
143
168
|
});
|
|
144
169
|
} catch (error) {
|
|
170
|
+
this.logger.error(LOG_PREFIX, `callStream failed: capabilityId=${capabilityId}, action=${action}`, {
|
|
171
|
+
params: requestParams,
|
|
172
|
+
error
|
|
173
|
+
});
|
|
145
174
|
throw new NetworkError(error instanceof Error ? error.message : String(error));
|
|
146
175
|
}
|
|
147
176
|
if (!response.ok) {
|
|
148
|
-
|
|
177
|
+
const errMsg = `HTTP ${response.status} ${response.statusText}`;
|
|
178
|
+
this.logger.error(LOG_PREFIX, `callStream failed: capabilityId=${capabilityId}, action=${action}`, {
|
|
179
|
+
params: requestParams,
|
|
180
|
+
error: errMsg
|
|
181
|
+
});
|
|
182
|
+
throw new NetworkError(errMsg);
|
|
149
183
|
}
|
|
150
184
|
if (!response.body) {
|
|
151
|
-
|
|
185
|
+
const errMsg = "Response body is null";
|
|
186
|
+
this.logger.error(LOG_PREFIX, `callStream failed: capabilityId=${capabilityId}, action=${action}`, {
|
|
187
|
+
params: requestParams,
|
|
188
|
+
error: errMsg
|
|
189
|
+
});
|
|
190
|
+
throw new NetworkError(errMsg);
|
|
152
191
|
}
|
|
153
192
|
const reader = response.body.getReader();
|
|
154
193
|
const decoder = new TextDecoder();
|
|
155
194
|
let buffer = "";
|
|
195
|
+
let chunkCount = 0;
|
|
196
|
+
let aggregatedContent = "";
|
|
197
|
+
let canAggregate = true;
|
|
156
198
|
try {
|
|
157
199
|
while (true) {
|
|
158
200
|
const { done, value } = await reader.read();
|
|
@@ -169,8 +211,26 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
169
211
|
const parsed = JSON.parse(data);
|
|
170
212
|
if (parsed.status_code === ErrorCodes.SUCCESS && parsed.data) {
|
|
171
213
|
if (parsed.data.type === "content") {
|
|
172
|
-
|
|
214
|
+
chunkCount++;
|
|
215
|
+
const delta = parsed.data.delta;
|
|
216
|
+
if (canAggregate) {
|
|
217
|
+
const content = delta?.content;
|
|
218
|
+
if (typeof content === "string") {
|
|
219
|
+
aggregatedContent += content;
|
|
220
|
+
} else {
|
|
221
|
+
canAggregate = false;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
yield delta;
|
|
173
225
|
if (parsed.data.finished) {
|
|
226
|
+
const resultInfo2 = canAggregate ? {
|
|
227
|
+
chunkCount,
|
|
228
|
+
result: aggregatedContent
|
|
229
|
+
} : {
|
|
230
|
+
chunkCount,
|
|
231
|
+
resultLength: aggregatedContent.length || chunkCount
|
|
232
|
+
};
|
|
233
|
+
this.logger.info(LOG_PREFIX, `callStream end: capabilityId=${capabilityId}, action=${action}`, resultInfo2);
|
|
174
234
|
return;
|
|
175
235
|
}
|
|
176
236
|
} else if (parsed.data.type === "error") {
|
|
@@ -179,13 +239,31 @@ var _CapabilityClient = class _CapabilityClient {
|
|
|
179
239
|
}
|
|
180
240
|
} catch (parseError) {
|
|
181
241
|
if (parseError instanceof CapabilityError) {
|
|
242
|
+
this.logger.error(LOG_PREFIX, `callStream failed: capabilityId=${capabilityId}, action=${action}`, {
|
|
243
|
+
params: requestParams,
|
|
244
|
+
error: parseError,
|
|
245
|
+
chunkCount
|
|
246
|
+
});
|
|
182
247
|
throw parseError;
|
|
183
248
|
}
|
|
184
249
|
}
|
|
185
250
|
}
|
|
186
251
|
}
|
|
187
252
|
}
|
|
253
|
+
const resultInfo = canAggregate ? {
|
|
254
|
+
chunkCount,
|
|
255
|
+
result: aggregatedContent
|
|
256
|
+
} : {
|
|
257
|
+
chunkCount,
|
|
258
|
+
resultLength: aggregatedContent.length || chunkCount
|
|
259
|
+
};
|
|
260
|
+
this.logger.info(LOG_PREFIX, `callStream end: capabilityId=${capabilityId}, action=${action}`, resultInfo);
|
|
188
261
|
} catch (error) {
|
|
262
|
+
this.logger.error(LOG_PREFIX, `callStream failed: capabilityId=${capabilityId}, action=${action}`, {
|
|
263
|
+
params: requestParams,
|
|
264
|
+
error,
|
|
265
|
+
chunkCount
|
|
266
|
+
});
|
|
189
267
|
if (error instanceof CapabilityError) {
|
|
190
268
|
throw error;
|
|
191
269
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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: unknown;\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 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","finished","parseError","releaseLock","createClient","capabilityClient"]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/errors.ts","../src/client.ts"],"sourcesContent":["/**\n * Logger 接口,兼容 console 和 @lark-apaas/toolkit 的 logger\n */\nexport interface Logger {\n debug(message: unknown, ...args: unknown[]): void;\n info(message: unknown, ...args: unknown[]): void;\n warn(message: unknown, ...args: unknown[]): void;\n error(message: unknown, ...args: unknown[]): void;\n}\n\n/**\n * 客户端配置选项\n */\nexport interface CapabilityClientOptions {\n /** 全局路径前缀,默认 ''。例如线上环境可设置为 '/spark/a' */\n baseURL?: string;\n /** 自定义 fetch 配置 */\n fetchOptions?: RequestInit;\n /** 自定义 logger,默认使用 console */\n logger?: Logger;\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: unknown;\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 Logger,\n} from './types';\nimport { ErrorCodes } from './types';\n\nconst LOG_PREFIX = '[CapabilityClient]';\n\nconst defaultLogger: Logger = {\n debug: console.debug.bind(console),\n info: console.info.bind(console),\n warn: console.warn.bind(console),\n error: console.error.bind(console),\n};\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 private logger: Logger;\n\n constructor(options?: CapabilityClientOptions) {\n this.options = options ?? {};\n // 移除末尾的斜杠,确保拼接时格式正确\n this.baseURL = (options?.baseURL ?? '').replace(/\\/+$/, '');\n this.logger = options?.logger ?? defaultLogger;\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 const requestParams = params ?? {};\n\n this.logger.info(LOG_PREFIX, `call start: capabilityId=${capabilityId}, action=${action}`, { params: requestParams });\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: requestParams,\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 const result = (data as { data: ExecuteResponseData }).data.output as T;\n\n this.logger.info(LOG_PREFIX, `call success: capabilityId=${capabilityId}, action=${action}`, { result });\n\n return result;\n } catch (error) {\n this.logger.error(LOG_PREFIX, `call failed: capabilityId=${capabilityId}, action=${action}`, { params: requestParams, 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 const requestParams = params ?? {};\n\n this.logger.info(LOG_PREFIX, `callStream start: capabilityId=${capabilityId}, action=${action}`, { params: requestParams });\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: requestParams,\n }),\n });\n } catch (error) {\n this.logger.error(LOG_PREFIX, `callStream failed: capabilityId=${capabilityId}, action=${action}`, { params: requestParams, error });\n throw new NetworkError(error instanceof Error ? error.message : String(error));\n }\n\n if (!response.ok) {\n const errMsg = `HTTP ${response.status} ${response.statusText}`;\n this.logger.error(LOG_PREFIX, `callStream failed: capabilityId=${capabilityId}, action=${action}`, { params: requestParams, error: errMsg });\n throw new NetworkError(errMsg);\n }\n\n if (!response.body) {\n const errMsg = 'Response body is null';\n this.logger.error(LOG_PREFIX, `callStream failed: capabilityId=${capabilityId}, action=${action}`, { params: requestParams, error: errMsg });\n throw new NetworkError(errMsg);\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n let chunkCount = 0;\n let aggregatedContent = '';\n let canAggregate = true;\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 chunkCount++;\n const delta = parsed.data.delta as T;\n\n // 尝试聚合 content 字段\n if (canAggregate) {\n const content = (delta as Record<string, unknown>)?.content;\n if (typeof content === 'string') {\n aggregatedContent += content;\n } else {\n canAggregate = false;\n }\n }\n\n yield delta;\n\n if (parsed.data.finished) {\n const resultInfo = canAggregate\n ? { chunkCount, result: aggregatedContent }\n : { chunkCount, resultLength: aggregatedContent.length || chunkCount };\n this.logger.info(LOG_PREFIX, `callStream end: capabilityId=${capabilityId}, action=${action}`, resultInfo);\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 this.logger.error(LOG_PREFIX, `callStream failed: capabilityId=${capabilityId}, action=${action}`, { params: requestParams, error: parseError, chunkCount });\n throw parseError;\n }\n // 忽略非 JSON 行\n }\n }\n }\n }\n const resultInfo = canAggregate\n ? { chunkCount, result: aggregatedContent }\n : { chunkCount, resultLength: aggregatedContent.length || chunkCount };\n this.logger.info(LOG_PREFIX, `callStream end: capabilityId=${capabilityId}, action=${action}`, resultInfo);\n } catch (error) {\n this.logger.error(LOG_PREFIX, `callStream failed: capabilityId=${capabilityId}, action=${action}`, { params: requestParams, error, chunkCount });\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":";;;;;;AAuHO,IAAMA,aAAa;EACxBC,SAAS;EACTC,sBAAsB;EACtBC,kBAAkB;EAClBC,kBAAkB;EAClBC,yBAAyB;EACzBC,iBAAiB;AACnB;;;AC3HO,IAAMC,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,2BAAN,MAAMA,iCAAgCN,gBAAAA;EAC3C,YAAYO,cAAsBH,YAAqB;AACrD,UAAM,yBAAyBG,YAAAA,IAAgB,wBAAwBH,UAAAA;AACvE,SAAKC,OAAO;EACd;AACF;AAL6CL;AAAtC,IAAMM,0BAAN;AAUA,IAAME,uBAAN,MAAMA,6BAA4BR,gBAAAA;EACvC,YAAYE,SAAiBE,YAAqB;AAChD,UAAMF,SAAS,oBAAoBE,UAAAA;AACnC,SAAKC,OAAO;EACd;AACF;AALyCL;AAAlC,IAAMQ,sBAAN;AAUA,IAAMC,gBAAN,MAAMA,sBAAqBT,gBAAAA;EAChC,YAAYE,SAAiB;AAC3B,UAAMA,SAAS,eAAA;AACf,SAAKG,OAAO;EACd;AACF;AALkCL;AAA3B,IAAMS,eAAN;AAUA,IAAMC,kBAAN,MAAMA,wBAAuBV,gBAAAA;EAClC,YAAYE,SAAiBE,YAAqB;AAChD,UAAMF,SAAS,mBAAmBE,UAAAA;AAClC,SAAKC,OAAO;EACd;AACF;AALoCL;AAA7B,IAAMU,iBAAN;;;ACxCP,IAAMC,aAAa;AAEnB,IAAMC,gBAAwB;EAC5BC,OAAOC,QAAQD,MAAME,KAAKD,OAAAA;EAC1BE,MAAMF,QAAQE,KAAKD,KAAKD,OAAAA;EACxBG,MAAMH,QAAQG,KAAKF,KAAKD,OAAAA;EACxBI,OAAOJ,QAAQI,MAAMH,KAAKD,OAAAA;AAC5B;AAYO,IAAMK,oBAAN,MAAMA,kBAAAA;EAKX,YAAYC,SAAmC;AAJvCA;AACAC;AACAC;AAGN,SAAKF,UAAUA,WAAW,CAAC;AAE3B,SAAKC,WAAWD,SAASC,WAAW,IAAIE,QAAQ,QAAQ,EAAA;AACxD,SAAKD,SAASF,SAASE,UAAUV;EACnC;;;;;;EAOAY,KAAKC,cAA0C;AAC7C,WAAO,KAAKC,eAAeD,YAAAA;EAC7B;EAEQC,eAAeD,cAA0C;AAC/D,WAAO;MACLE,MAAM,wBAAcC,QAAgBC,WAAAA;AAClC,eAAO,KAAKC,YAAeL,cAAcG,QAAQC,MAAAA;MACnD,GAFM;MAGNE,YAAY,wBAAcH,QAAgBC,WAAAA;AACxC,eAAO,KAAKG,kBAAqBP,cAAcG,QAAQC,MAAAA;MACzD,GAFY;IAGd;EACF;EAEA,MAAcC,YACZL,cACAG,QACAC,QACY;AACZ,UAAMI,MAAM,GAAG,KAAKZ,OAAO,mBAAmBI,YAAAA;AAC9C,UAAMS,gBAAgBL,UAAU,CAAC;AAEjC,SAAKP,OAAON,KAAKL,YAAY,4BAA4Bc,YAAAA,YAAwBG,MAAAA,IAAU;MAAEC,QAAQK;IAAc,CAAA;AAEnH,QAAI;AACF,YAAMC,WAAW,MAAMC,MAAMH,KAAK;QAChCI,QAAQ;QACR,GAAG,KAAKjB,QAAQkB;QAChBC,SAAS;UACP,gBAAgB;UAChB,GAAG,KAAKnB,QAAQkB,cAAcC;QAChC;QACAC,MAAMC,KAAKC,UAAU;UACnBd;UACAC,QAAQK;QACV,CAAA;MACF,CAAA;AAEA,YAAMS,OAAQ,MAAMR,SAASS,KAAI;AAEjC,UAAI,CAACT,SAASU,MAAMF,KAAKG,gBAAgBC,WAAWC,SAAS;AAC3D,cAAMC,gBAAgBN;AACtB,cAAMO,YAAYD,cAAcH;AAEhC,gBAAQI,WAAAA;UACN,KAAKH,WAAWI;AACd,kBAAM,IAAIC,wBAAwB3B,cAAcU,SAASkB,MAAM;UACjE,KAAKN,WAAWO;AACd,kBAAM,IAAIC,oBAAoBN,cAAcO,WAAWrB,SAASkB,MAAM;UACxE,KAAKN,WAAWU;UAChB,KAAKV,WAAWW;UAChB;AACE,kBAAM,IAAIC,eAAeV,cAAcO,WAAWrB,SAASkB,MAAM;QACrE;MACF;AAEA,YAAMO,SAAUjB,KAAuCA,KAAKkB;AAE5D,WAAKvC,OAAON,KAAKL,YAAY,8BAA8Bc,YAAAA,YAAwBG,MAAAA,IAAU;QAAEgC;MAAO,CAAA;AAEtG,aAAOA;IACT,SAAS1C,OAAO;AACd,WAAKI,OAAOJ,MAAMP,YAAY,6BAA6Bc,YAAAA,YAAwBG,MAAAA,IAAU;QAAEC,QAAQK;QAAehB;MAAM,CAAA;AAC5H,UAAIA,iBAAiB4C,iBAAiB;AACpC,cAAM5C;MACR;AACA,YAAM,IAAI6C,aAAa7C,iBAAiB8C,QAAQ9C,MAAM+C,UAAUC,OAAOhD,KAAAA,CAAAA;IACzE;EACF;EAEA,OAAec,kBACbP,cACAG,QACAC,QACkB;AAClB,UAAMI,MAAM,GAAG,KAAKZ,OAAO,mBAAmBI,YAAAA;AAC9C,UAAMS,gBAAgBL,UAAU,CAAC;AAEjC,SAAKP,OAAON,KAAKL,YAAY,kCAAkCc,YAAAA,YAAwBG,MAAAA,IAAU;MAAEC,QAAQK;IAAc,CAAA;AAEzH,QAAIC;AACJ,QAAI;AACFA,iBAAW,MAAMC,MAAMH,KAAK;QAC1BI,QAAQ;QACR,GAAG,KAAKjB,QAAQkB;QAChBC,SAAS;UACP,gBAAgB;UAChB,GAAG,KAAKnB,QAAQkB,cAAcC;QAChC;QACAC,MAAMC,KAAKC,UAAU;UACnBd;UACAC,QAAQK;QACV,CAAA;MACF,CAAA;IACF,SAAShB,OAAO;AACd,WAAKI,OAAOJ,MAAMP,YAAY,mCAAmCc,YAAAA,YAAwBG,MAAAA,IAAU;QAAEC,QAAQK;QAAehB;MAAM,CAAA;AAClI,YAAM,IAAI6C,aAAa7C,iBAAiB8C,QAAQ9C,MAAM+C,UAAUC,OAAOhD,KAAAA,CAAAA;IACzE;AAEA,QAAI,CAACiB,SAASU,IAAI;AAChB,YAAMsB,SAAS,QAAQhC,SAASkB,MAAM,IAAIlB,SAASiC,UAAU;AAC7D,WAAK9C,OAAOJ,MAAMP,YAAY,mCAAmCc,YAAAA,YAAwBG,MAAAA,IAAU;QAAEC,QAAQK;QAAehB,OAAOiD;MAAO,CAAA;AAC1I,YAAM,IAAIJ,aAAaI,MAAAA;IACzB;AAEA,QAAI,CAAChC,SAASK,MAAM;AAClB,YAAM2B,SAAS;AACf,WAAK7C,OAAOJ,MAAMP,YAAY,mCAAmCc,YAAAA,YAAwBG,MAAAA,IAAU;QAAEC,QAAQK;QAAehB,OAAOiD;MAAO,CAAA;AAC1I,YAAM,IAAIJ,aAAaI,MAAAA;IACzB;AAEA,UAAME,SAASlC,SAASK,KAAK8B,UAAS;AACtC,UAAMC,UAAU,IAAIC,YAAAA;AACpB,QAAIC,SAAS;AACb,QAAIC,aAAa;AACjB,QAAIC,oBAAoB;AACxB,QAAIC,eAAe;AAEnB,QAAI;AACF,aAAO,MAAM;AACX,cAAM,EAAEC,MAAMC,MAAK,IAAK,MAAMT,OAAOU,KAAI;AACzC,YAAIF,KAAM;AAEVJ,kBAAUF,QAAQS,OAAOF,OAAO;UAAEG,QAAQ;QAAK,CAAA;AAC/C,cAAMC,QAAQT,OAAOU,MAAM,IAAA;AAC3BV,iBAASS,MAAME,IAAG,KAAM;AAExB,mBAAWC,QAAQH,OAAO;AACxB,cAAIG,KAAKC,WAAW,QAAA,GAAW;AAC7B,kBAAM3C,OAAO0C,KAAKE,MAAM,CAAA;AAExB,gBAAI;AACF,oBAAMC,SAAS/C,KAAKgD,MAAM9C,IAAAA;AAE1B,kBAAI6C,OAAO1C,gBAAgBC,WAAWC,WAAWwC,OAAO7C,MAAM;AAC5D,oBAAI6C,OAAO7C,KAAK+C,SAAS,WAAW;AAClChB;AACA,wBAAMiB,QAAQH,OAAO7C,KAAKgD;AAG1B,sBAAIf,cAAc;AAChB,0BAAMgB,UAAWD,OAAmCC;AACpD,wBAAI,OAAOA,YAAY,UAAU;AAC/BjB,2CAAqBiB;oBACvB,OAAO;AACLhB,qCAAe;oBACjB;kBACF;AAEA,wBAAMe;AAEN,sBAAIH,OAAO7C,KAAKkD,UAAU;AACxB,0BAAMC,cAAalB,eACf;sBAAEF;sBAAYd,QAAQe;oBAAkB,IACxC;sBAAED;sBAAYqB,cAAcpB,kBAAkBqB,UAAUtB;oBAAW;AACvE,yBAAKpD,OAAON,KAAKL,YAAY,gCAAgCc,YAAAA,YAAwBG,MAAAA,IAAUkE,WAAAA;AAC/F;kBACF;gBACF,WAAWN,OAAO7C,KAAK+C,SAAS,SAAS;AACvC,wBAAM,IAAI/B,eAAe6B,OAAO7C,KAAKzB,MAAM+C,OAAO;gBACpD;cACF;YACF,SAASgC,YAAY;AACnB,kBAAIA,sBAAsBnC,iBAAiB;AACzC,qBAAKxC,OAAOJ,MAAMP,YAAY,mCAAmCc,YAAAA,YAAwBG,MAAAA,IAAU;kBAAEC,QAAQK;kBAAehB,OAAO+E;kBAAYvB;gBAAW,CAAA;AAC1J,sBAAMuB;cACR;YAEF;UACF;QACF;MACF;AACA,YAAMH,aAAalB,eACf;QAAEF;QAAYd,QAAQe;MAAkB,IACxC;QAAED;QAAYqB,cAAcpB,kBAAkBqB,UAAUtB;MAAW;AACvE,WAAKpD,OAAON,KAAKL,YAAY,gCAAgCc,YAAAA,YAAwBG,MAAAA,IAAUkE,UAAAA;IACjG,SAAS5E,OAAO;AACd,WAAKI,OAAOJ,MAAMP,YAAY,mCAAmCc,YAAAA,YAAwBG,MAAAA,IAAU;QAAEC,QAAQK;QAAehB;QAAOwD;MAAW,CAAA;AAC9I,UAAIxD,iBAAiB4C,iBAAiB;AACpC,cAAM5C;MACR;AACA,YAAM,IAAI6C,aAAa7C,iBAAiB8C,QAAQ9C,MAAM+C,UAAUC,OAAOhD,KAAAA,CAAAA;IACzE,UAAA;AACEmD,aAAO6B,YAAW;IACpB;EACF;AACF;AA5Ma/E;AAAN,IAAMA,mBAAN;AAiNA,SAASgF,aAAa/E,SAAiC;AAC5D,SAAO,IAAID,iBAAiBC,OAAAA;AAC9B;AAFgB+E;AAOT,IAAMC,mBAAmB,IAAIjF,iBAAiB,CAErD,CAAA;","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","LOG_PREFIX","defaultLogger","debug","console","bind","info","warn","error","CapabilityClient","options","baseURL","logger","replace","load","capabilityId","createExecutor","call","action","params","executeCall","callStream","executeCallStream","url","requestParams","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","result","output","CapabilityError","NetworkError","Error","message","String","errMsg","statusText","reader","getReader","decoder","TextDecoder","buffer","chunkCount","aggregatedContent","canAggregate","done","value","read","decode","stream","lines","split","pop","line","startsWith","slice","parsed","parse","type","delta","content","finished","resultInfo","resultLength","length","parseError","releaseLock","createClient","capabilityClient"]}
|