@lark-apaas/client-capability 0.1.4 → 0.1.6

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 CHANGED
@@ -45,7 +45,6 @@ var ErrorCodes = {
45
45
  EXECUTION_ERROR: "k_ec_cap_005",
46
46
  RATE_LIMIT_EXCEEDED: "k_ec_cap_006"
47
47
  };
48
- var UPLOAD_API_PATH = "/af/api/v1/studio/plugins/tmp_files";
49
48
 
50
49
  // src/errors.ts
51
50
  var _CapabilityError = class _CapabilityError extends Error {
@@ -118,19 +117,20 @@ __name(_RateLimitError, "RateLimitError");
118
117
  var RateLimitError = _RateLimitError;
119
118
 
120
119
  // src/uploader.ts
120
+ var import_internal_slardar = require("@lark-apaas/internal-slardar");
121
121
  var _FileUploader = class _FileUploader {
122
- constructor(fetchOptions) {
123
- __publicField(this, "fetchOptions");
124
- this.fetchOptions = fetchOptions;
122
+ constructor(options) {
123
+ __publicField(this, "options");
124
+ this.options = options;
125
125
  }
126
126
  /**
127
127
  * 上传单个文件,返回下载 URL
128
128
  */
129
129
  async upload(file) {
130
130
  const fileName = file instanceof File ? file.name : `blob-${Date.now()}`;
131
- const { uploadURL, objectKey } = await this.acquireUploadUrl(fileName);
131
+ const { uploadURL, objectKey } = await this.fetchUploadUrl(fileName);
132
132
  await this.uploadToTos(uploadURL, file);
133
- const downloadUrl = await this.acquireDownloadUrl(objectKey);
133
+ const downloadUrl = await this.fetchDownloadUrl(objectKey);
134
134
  return downloadUrl;
135
135
  }
136
136
  /**
@@ -149,22 +149,27 @@ var _FileUploader = class _FileUploader {
149
149
  /**
150
150
  * 获取上传预签名 URL
151
151
  */
152
- async acquireUploadUrl(fileName) {
153
- const url = `${UPLOAD_API_PATH}/acquire_upload_url`;
152
+ async fetchUploadUrl(fileName) {
153
+ const { acquireUploadUrl, fetchOptions } = this.options;
154
154
  let response;
155
155
  try {
156
- response = await fetch(url, {
156
+ response = await fetch(acquireUploadUrl, {
157
157
  method: "POST",
158
- ...this.fetchOptions,
158
+ ...fetchOptions,
159
159
  headers: {
160
160
  "Content-Type": "application/json",
161
- ...this.fetchOptions?.headers
161
+ ...fetchOptions?.headers
162
162
  },
163
163
  body: JSON.stringify({
164
164
  fileName
165
165
  })
166
166
  });
167
167
  } catch (error) {
168
+ import_internal_slardar.slardar.captureException(error, {
169
+ source: "client-capability",
170
+ module: "file-upload",
171
+ step: "fetch-upload-url"
172
+ });
168
173
  throw new FileUploadError(`Failed to acquire upload URL: ${error instanceof Error ? error.message : String(error)}`);
169
174
  }
170
175
  if (!response.ok) {
@@ -187,6 +192,11 @@ var _FileUploader = class _FileUploader {
187
192
  body: file
188
193
  });
189
194
  } catch (error) {
195
+ import_internal_slardar.slardar.captureException(error, {
196
+ source: "client-capability",
197
+ module: "file-upload",
198
+ step: "upload-to-tos"
199
+ });
190
200
  throw new FileUploadError(`Failed to upload file to TOS: ${error instanceof Error ? error.message : String(error)}`);
191
201
  }
192
202
  if (!response.ok) {
@@ -196,22 +206,27 @@ var _FileUploader = class _FileUploader {
196
206
  /**
197
207
  * 获取临时下载 URL
198
208
  */
199
- async acquireDownloadUrl(objectKey) {
200
- const url = `${UPLOAD_API_PATH}/acquire_download_url`;
209
+ async fetchDownloadUrl(objectKey) {
210
+ const { acquireDownloadUrl, fetchOptions } = this.options;
201
211
  let response;
202
212
  try {
203
- response = await fetch(url, {
213
+ response = await fetch(acquireDownloadUrl, {
204
214
  method: "POST",
205
- ...this.fetchOptions,
215
+ ...fetchOptions,
206
216
  headers: {
207
217
  "Content-Type": "application/json",
208
- ...this.fetchOptions?.headers
218
+ ...fetchOptions?.headers
209
219
  },
210
220
  body: JSON.stringify({
211
221
  objectKey
212
222
  })
213
223
  });
214
224
  } catch (error) {
225
+ import_internal_slardar.slardar.captureException(error, {
226
+ source: "client-capability",
227
+ module: "file-upload",
228
+ step: "fetch-download-url"
229
+ });
215
230
  throw new FileUploadError(`Failed to acquire download URL: ${error instanceof Error ? error.message : String(error)}`);
216
231
  }
217
232
  if (!response.ok) {
@@ -298,6 +313,7 @@ function replaceFilesWithUrls(params, results) {
298
313
  __name(replaceFilesWithUrls, "replaceFilesWithUrls");
299
314
 
300
315
  // src/client.ts
316
+ var import_internal_slardar2 = require("@lark-apaas/internal-slardar");
301
317
  var LOG_PREFIX = "[CapabilityClient]";
302
318
  var defaultLogger = {
303
319
  debug: console.debug.bind(console),
@@ -311,7 +327,7 @@ var _CapabilityClient = class _CapabilityClient {
311
327
  __publicField(this, "baseURL");
312
328
  __publicField(this, "logger");
313
329
  __publicField(this, "onRateLimitError");
314
- this.options = options ?? {};
330
+ this.options = options;
315
331
  this.baseURL = (options?.baseURL ?? "").replace(/\/+$/, "");
316
332
  this.logger = options?.logger ?? defaultLogger;
317
333
  this.onRateLimitError = options?.onRateLimitError;
@@ -340,7 +356,7 @@ var _CapabilityClient = class _CapabilityClient {
340
356
  const extractedFiles = extractFiles(requestParams);
341
357
  if (extractedFiles.length > 0) {
342
358
  this.logger.info(LOG_PREFIX, `uploading ${extractedFiles.length} file(s)...`);
343
- const uploader = new FileUploader(this.options.fetchOptions);
359
+ const uploader = new FileUploader(this.options);
344
360
  const uploadResults = await uploader.uploadAll(extractedFiles);
345
361
  requestParams = replaceFilesWithUrls(requestParams, uploadResults);
346
362
  this.logger.info(LOG_PREFIX, `file upload completed`);
@@ -391,6 +407,12 @@ var _CapabilityClient = class _CapabilityClient {
391
407
  params: requestParams,
392
408
  error
393
409
  });
410
+ import_internal_slardar2.slardar.captureException(error, {
411
+ source: "client-capability",
412
+ module: "execute-call",
413
+ capabilityId,
414
+ action
415
+ });
394
416
  if (error instanceof CapabilityError) {
395
417
  throw error;
396
418
  }
@@ -403,7 +425,7 @@ var _CapabilityClient = class _CapabilityClient {
403
425
  const extractedFiles = extractFiles(requestParams);
404
426
  if (extractedFiles.length > 0) {
405
427
  this.logger.info(LOG_PREFIX, `uploading ${extractedFiles.length} file(s)...`);
406
- const uploader = new FileUploader(this.options.fetchOptions);
428
+ const uploader = new FileUploader(this.options);
407
429
  const uploadResults = await uploader.uploadAll(extractedFiles);
408
430
  requestParams = replaceFilesWithUrls(requestParams, uploadResults);
409
431
  this.logger.info(LOG_PREFIX, `file upload completed`);
@@ -430,6 +452,13 @@ var _CapabilityClient = class _CapabilityClient {
430
452
  params: requestParams,
431
453
  error
432
454
  });
455
+ import_internal_slardar2.slardar.captureException(error, {
456
+ source: "client-capability",
457
+ module: "execute-call-stream",
458
+ capabilityId,
459
+ action,
460
+ phase: "fetch"
461
+ });
433
462
  throw new NetworkError(error instanceof Error ? error.message : String(error));
434
463
  }
435
464
  if (!response.ok) {
@@ -529,6 +558,13 @@ var _CapabilityClient = class _CapabilityClient {
529
558
  error,
530
559
  chunkCount
531
560
  });
561
+ import_internal_slardar2.slardar.captureException(error, {
562
+ source: "client-capability",
563
+ module: "execute-call-stream",
564
+ capabilityId,
565
+ action,
566
+ phase: "read"
567
+ });
532
568
  if (error instanceof CapabilityError) {
533
569
  throw error;
534
570
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/errors.ts","../src/uploader.ts","../src/file-extractor.ts","../src/client.ts"],"sourcesContent":["// 客户端\nexport { createClient, CapabilityClient } from './client';\n\n// 类型\nexport type { CapabilityClientOptions, CapabilityExecutor, Logger, RateLimitErrorHook } from './types';\n\n// 错误类型\nexport {\n CapabilityError,\n CapabilityNotFoundError,\n ActionNotFoundError,\n NetworkError,\n ExecutionError,\n FileUploadError,\n RateLimitError,\n} from './errors';\n","import type { RateLimitError } from './errors';\n\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 * RateLimitError 钩子函数类型\n * 当检测到计费受限错误时,在抛出异常前调用此钩子\n */\nexport type RateLimitErrorHook = (error: RateLimitError) => void | Promise<void>;\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 * 当检测到 RateLimitError 时,在抛出异常前调用此钩子\n * 可用于上报埋点、展示 toast 等场景\n */\n onRateLimitError?: RateLimitErrorHook;\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 is_rate_limit_error?: boolean;\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 /** 错误码,计费受限时为业务错误码(如 k_st_ec_400002687) */\n code: string;\n message: string;\n /** 是否为计费受限错误 */\n isRateLimitError?: boolean;\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 RATE_LIMIT_EXCEEDED: 'k_ec_cap_006',\n} as const;\n\n// ========== 文件上传相关类型 ==========\n\n/**\n * 文件上传接口 BasePath\n */\nexport const UPLOAD_API_PATH = '/af/api/v1/studio/plugins/tmp_files';\n\n/**\n * 提取的文件信息\n */\nexport interface ExtractedFile {\n /** 在 params 中的路径,如 ['image_list', 0] */\n path: (string | number)[];\n /** 文件对象 */\n file: File | Blob;\n}\n\n/**\n * 上传结果\n */\nexport interface UploadResult {\n /** 在 params 中的路径 */\n path: (string | number)[];\n /** 临时下载 URL */\n downloadUrl: string;\n}\n\n/**\n * 获取上传 URL 响应\n */\nexport interface AcquireUploadUrlResponse {\n status_code: string;\n data: {\n uploadURL: string;\n objectKey: string;\n };\n}\n\n/**\n * 获取下载 URL 响应\n */\nexport interface AcquireDownloadUrlResponse {\n status_code: string;\n data: {\n downloadURL: string;\n };\n}\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\n/**\n * 文件上传错误\n */\nexport class FileUploadError extends CapabilityError {\n constructor(message: string, statusCode?: number) {\n super(message, 'FILE_UPLOAD_ERROR', statusCode);\n this.name = 'FileUploadError';\n }\n}\n\n/**\n * 计费受限错误\n */\nexport class RateLimitError extends CapabilityError {\n /** 业务错误码 */\n rateLimitCode: string;\n /** 业务错误消息 */\n rateLimitMessage: string;\n\n constructor(rateLimitCode: string, rateLimitMessage: string, statusCode?: number) {\n super(rateLimitMessage, 'RATE_LIMIT_EXCEEDED', statusCode);\n this.name = 'RateLimitError';\n this.rateLimitCode = rateLimitCode;\n this.rateLimitMessage = rateLimitMessage;\n }\n}\n","import type {\n ExtractedFile,\n UploadResult,\n AcquireUploadUrlResponse,\n AcquireDownloadUrlResponse,\n} from './types';\nimport { UPLOAD_API_PATH } from './types';\nimport { FileUploadError } from './errors';\n\n/**\n * 文件上传器\n */\nexport class FileUploader {\n private readonly fetchOptions?: RequestInit;\n\n constructor(fetchOptions?: RequestInit) {\n this.fetchOptions = fetchOptions;\n }\n\n /**\n * 上传单个文件,返回下载 URL\n */\n async upload(file: File | Blob): Promise<string> {\n const fileName = file instanceof File ? file.name : `blob-${Date.now()}`;\n\n // 1. 获取上传预签名 URL\n const { uploadURL, objectKey } = await this.acquireUploadUrl(fileName);\n\n // 2. 上传文件到 TOS\n await this.uploadToTos(uploadURL, file);\n\n // 3. 获取下载 URL\n const downloadUrl = await this.acquireDownloadUrl(objectKey);\n\n return downloadUrl;\n }\n\n /**\n * 并发上传多个文件\n */\n async uploadAll(files: ExtractedFile[]): Promise<UploadResult[]> {\n const results = await Promise.all(\n files.map(async ({ path, file }) => {\n const downloadUrl = await this.upload(file);\n return { path, downloadUrl };\n })\n );\n return results;\n }\n\n /**\n * 获取上传预签名 URL\n */\n private async acquireUploadUrl(fileName: string): Promise<{ uploadURL: string; objectKey: string }> {\n const url = `${UPLOAD_API_PATH}/acquire_upload_url`;\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: 'POST',\n ...this.fetchOptions,\n headers: {\n 'Content-Type': 'application/json',\n ...this.fetchOptions?.headers,\n },\n body: JSON.stringify({ fileName }),\n });\n } catch (error) {\n throw new FileUploadError(\n `Failed to acquire upload URL: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n\n if (!response.ok) {\n throw new FileUploadError(\n `Failed to acquire upload URL: HTTP ${response.status}`,\n response.status\n );\n }\n\n const data = (await response.json()) as AcquireUploadUrlResponse;\n\n if (data.status_code !== '0') {\n throw new FileUploadError(`Failed to acquire upload URL: ${data.status_code}`);\n }\n\n return data.data;\n }\n\n /**\n * 上传文件到 TOS(预签名 URL)\n */\n private async uploadToTos(uploadURL: string, file: File | Blob): Promise<void> {\n let response: Response;\n try {\n response = await fetch(uploadURL, {\n method: 'PUT',\n body: file,\n });\n } catch (error) {\n throw new FileUploadError(\n `Failed to upload file to TOS: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n\n if (!response.ok) {\n throw new FileUploadError(\n `Failed to upload file to TOS: HTTP ${response.status}`,\n response.status\n );\n }\n }\n\n /**\n * 获取临时下载 URL\n */\n private async acquireDownloadUrl(objectKey: string): Promise<string> {\n const url = `${UPLOAD_API_PATH}/acquire_download_url`;\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: 'POST',\n ...this.fetchOptions,\n headers: {\n 'Content-Type': 'application/json',\n ...this.fetchOptions?.headers,\n },\n body: JSON.stringify({ objectKey }),\n });\n } catch (error) {\n throw new FileUploadError(\n `Failed to acquire download URL: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n\n if (!response.ok) {\n throw new FileUploadError(\n `Failed to acquire download URL: HTTP ${response.status}`,\n response.status\n );\n }\n\n const data = (await response.json()) as AcquireDownloadUrlResponse;\n\n if (data.status_code !== '0') {\n throw new FileUploadError(`Failed to acquire download URL: ${data.status_code}`);\n }\n\n return data.data.downloadURL;\n }\n}\n","import type { ExtractedFile, UploadResult } from './types';\n\n/**\n * 检测是否为 File 或 Blob\n */\nexport function isFile(value: unknown): value is File | Blob {\n return value instanceof File || value instanceof Blob;\n}\n\n/**\n * 递归提取 params 中的所有文件\n *\n * @example\n * extractFiles({ image_list: [file1, file2] })\n * // => [\n * // { path: ['image_list', 0], file: file1 },\n * // { path: ['image_list', 1], file: file2 }\n * // ]\n */\nexport function extractFiles(params: Record<string, unknown>): ExtractedFile[] {\n const files: ExtractedFile[] = [];\n\n function traverse(obj: unknown, path: (string | number)[]): void {\n if (isFile(obj)) {\n files.push({ path: [...path], file: obj });\n } else if (Array.isArray(obj)) {\n obj.forEach((item, index) => traverse(item, [...path, index]));\n } else if (obj !== null && typeof obj === 'object') {\n Object.entries(obj).forEach(([key, value]) => {\n traverse(value, [...path, key]);\n });\n }\n }\n\n traverse(params, []);\n return files;\n}\n\n/**\n * 根据上传结果替换 params 中的文件为 URL\n *\n * @example\n * replaceFilesWithUrls(\n * { image_list: [file1, file2] },\n * [\n * { path: ['image_list', 0], downloadUrl: 'https://...' },\n * { path: ['image_list', 1], downloadUrl: 'https://...' }\n * ]\n * )\n * // => { image_list: ['https://...', 'https://...'] }\n */\nexport function replaceFilesWithUrls(\n params: Record<string, unknown>,\n results: UploadResult[]\n): Record<string, unknown> {\n // 创建 path -> url 的映射,用于快速查找\n const urlMap = new Map<string, string>();\n for (const { path, downloadUrl } of results) {\n urlMap.set(JSON.stringify(path), downloadUrl);\n }\n\n // 手动深拷贝,同时将 File/Blob 替换为对应的 URL\n // 注意:不能使用 structuredClone,因为它不支持 File/Blob 对象\n function cloneAndReplace(obj: unknown, currentPath: (string | number)[]): unknown {\n // 检查当前路径是否有对应的 URL\n const pathKey = JSON.stringify(currentPath);\n if (urlMap.has(pathKey)) {\n return urlMap.get(pathKey);\n }\n\n // 如果是 File/Blob 但没有对应的 URL(不应该发生),返回 null\n if (isFile(obj)) {\n return null;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item, index) => cloneAndReplace(item, [...currentPath, index]));\n }\n\n if (obj !== null && typeof obj === 'object') {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n result[key] = cloneAndReplace(value, [...currentPath, key]);\n }\n return result;\n }\n\n // 原始值直接返回\n return obj;\n }\n\n return cloneAndReplace(params, []) as Record<string, unknown>;\n}\n","import type {\n CapabilityClientOptions,\n CapabilityExecutor,\n ApiResponse,\n ExecuteResponseData,\n StreamResponse,\n Logger,\n RateLimitErrorHook,\n} from './types';\nimport { ErrorCodes } from './types';\nimport {\n CapabilityError,\n CapabilityNotFoundError,\n ActionNotFoundError,\n NetworkError,\n ExecutionError,\n RateLimitError,\n} from './errors';\nimport { FileUploader } from './uploader';\nimport { extractFiles, replaceFilesWithUrls } from './file-extractor';\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};\n\n/**\n * 能力客户端\n */\nexport class CapabilityClient {\n private options: CapabilityClientOptions;\n private baseURL: string;\n private logger: Logger;\n private onRateLimitError?: RateLimitErrorHook;\n\n constructor(options?: CapabilityClientOptions) {\n this.options = options ?? {};\n // 移除末尾的斜杠,确保拼接时格式正确\n this.baseURL = (options?.baseURL ?? '').replace(/\\/+$/, '');\n this.logger = options?.logger ?? defaultLogger;\n this.onRateLimitError = options?.onRateLimitError;\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 let requestParams = params ?? {};\n\n // 处理文件上传\n const extractedFiles = extractFiles(requestParams);\n if (extractedFiles.length > 0) {\n this.logger.info(LOG_PREFIX, `uploading ${extractedFiles.length} file(s)...`);\n const uploader = new FileUploader(this.options.fetchOptions);\n const uploadResults = await uploader.uploadAll(extractedFiles);\n requestParams = replaceFilesWithUrls(requestParams, uploadResults);\n this.logger.info(LOG_PREFIX, `file upload completed`);\n }\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 {\n status_code: string;\n error_msg: string;\n is_rate_limit_error?: boolean;\n };\n const errorCode = errorResponse.status_code;\n\n // 计费受限错误:通过 is_rate_limit_error 字段识别\n if (errorResponse.is_rate_limit_error) {\n const rateLimitError = new RateLimitError(\n errorCode, // status_code 就是业务错误码\n errorResponse.error_msg,\n response.status,\n );\n await this.onRateLimitError?.(rateLimitError);\n throw rateLimitError;\n }\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 let requestParams = params ?? {};\n\n // 处理文件上传\n const extractedFiles = extractFiles(requestParams);\n if (extractedFiles.length > 0) {\n this.logger.info(LOG_PREFIX, `uploading ${extractedFiles.length} file(s)...`);\n const uploader = new FileUploader(this.options.fetchOptions);\n const uploadResults = await uploader.uploadAll(extractedFiles);\n requestParams = replaceFilesWithUrls(requestParams, uploadResults);\n this.logger.info(LOG_PREFIX, `file upload completed`);\n }\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 const err = parsed.data.error;\n if (err.isRateLimitError) {\n const rateLimitError = new RateLimitError(\n err.code, // code 就是业务错误码\n err.message,\n );\n await this.onRateLimitError?.(rateLimitError);\n throw rateLimitError;\n }\n throw new ExecutionError(err.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"],"mappings":"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","names":["ErrorCodes","SUCCESS","CAPABILITY_NOT_FOUND","PLUGIN_NOT_FOUND","ACTION_NOT_FOUND","PARAMS_VALIDATION_ERROR","EXECUTION_ERROR","RATE_LIMIT_EXCEEDED","UPLOAD_API_PATH","CapabilityError","Error","message","code","statusCode","name","CapabilityNotFoundError","capabilityId","ActionNotFoundError","NetworkError","ExecutionError","FileUploadError","RateLimitError","rateLimitCode","rateLimitMessage","FileUploader","fetchOptions","upload","file","fileName","File","name","Date","now","uploadURL","objectKey","acquireUploadUrl","uploadToTos","downloadUrl","acquireDownloadUrl","uploadAll","files","results","Promise","all","map","path","url","UPLOAD_API_PATH","response","fetch","method","headers","body","JSON","stringify","error","FileUploadError","Error","message","String","ok","status","data","json","status_code","downloadURL","isFile","value","File","Blob","extractFiles","params","files","traverse","obj","path","push","file","Array","isArray","forEach","item","index","Object","entries","key","replaceFilesWithUrls","results","urlMap","Map","downloadUrl","set","JSON","stringify","cloneAndReplace","currentPath","pathKey","has","get","map","result","LOG_PREFIX","defaultLogger","debug","console","bind","info","warn","error","CapabilityClient","options","baseURL","logger","onRateLimitError","replace","load","capabilityId","createExecutor","call","action","params","executeCall","callStream","executeCallStream","url","requestParams","extractedFiles","extractFiles","length","uploader","FileUploader","fetchOptions","uploadResults","uploadAll","replaceFilesWithUrls","response","fetch","method","headers","body","JSON","stringify","data","json","ok","status_code","ErrorCodes","SUCCESS","errorResponse","errorCode","is_rate_limit_error","rateLimitError","RateLimitError","error_msg","status","CAPABILITY_NOT_FOUND","CapabilityNotFoundError","ACTION_NOT_FOUND","ActionNotFoundError","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","err","isRateLimitError","code","parseError","releaseLock","createClient"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/errors.ts","../src/uploader.ts","../src/file-extractor.ts","../src/client.ts"],"sourcesContent":["// 客户端\nexport { createClient, CapabilityClient } from './client';\n\n// 类型\nexport type { CapabilityClientOptions, CapabilityExecutor, Logger, RateLimitErrorHook } from './types';\n\n// 错误类型\nexport {\n CapabilityError,\n CapabilityNotFoundError,\n ActionNotFoundError,\n NetworkError,\n ExecutionError,\n FileUploadError,\n RateLimitError,\n} from './errors';\n","import type { RateLimitError } from './errors';\n\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 * RateLimitError 钩子函数类型\n * 当检测到计费受限错误时,在抛出异常前调用此钩子\n */\nexport type RateLimitErrorHook = (error: RateLimitError) => void | Promise<void>;\n\n/**\n * 客户端配置选项\n */\nexport interface CapabilityClientOptions {\n /** 全局路径前缀,默认 ''。例如线上环境可设置为 '/spark/a' */\n baseURL?: string;\n /** 获取文件上传预签名 URL 的接口地址,由上层注入 */\n acquireUploadUrl: string;\n /** 获取文件临时下载 URL 的接口地址,由上层注入 */\n acquireDownloadUrl: string;\n /** 自定义 fetch 配置 */\n fetchOptions?: RequestInit;\n /** 自定义 logger,默认使用 console */\n logger?: Logger;\n /**\n * 计费受限错误钩子\n * 当检测到 RateLimitError 时,在抛出异常前调用此钩子\n * 可用于上报埋点、展示 toast 等场景\n */\n onRateLimitError?: RateLimitErrorHook;\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 is_rate_limit_error?: boolean;\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 /** 错误码,计费受限时为业务错误码(如 k_st_ec_400002687) */\n code: string;\n message: string;\n /** 是否为计费受限错误 */\n isRateLimitError?: boolean;\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 RATE_LIMIT_EXCEEDED: 'k_ec_cap_006',\n} as const;\n\n// ========== 文件上传相关类型 ==========\n\n/**\n * 提取的文件信息\n */\nexport interface ExtractedFile {\n /** 在 params 中的路径,如 ['image_list', 0] */\n path: (string | number)[];\n /** 文件对象 */\n file: File | Blob;\n}\n\n/**\n * 上传结果\n */\nexport interface UploadResult {\n /** 在 params 中的路径 */\n path: (string | number)[];\n /** 临时下载 URL */\n downloadUrl: string;\n}\n\n/**\n * 获取上传 URL 响应\n */\nexport interface AcquireUploadUrlResponse {\n status_code: string;\n data: {\n uploadURL: string;\n objectKey: string;\n };\n}\n\n/**\n * 获取下载 URL 响应\n */\nexport interface AcquireDownloadUrlResponse {\n status_code: string;\n data: {\n downloadURL: string;\n };\n}\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\n/**\n * 文件上传错误\n */\nexport class FileUploadError extends CapabilityError {\n constructor(message: string, statusCode?: number) {\n super(message, 'FILE_UPLOAD_ERROR', statusCode);\n this.name = 'FileUploadError';\n }\n}\n\n/**\n * 计费受限错误\n */\nexport class RateLimitError extends CapabilityError {\n /** 业务错误码 */\n rateLimitCode: string;\n /** 业务错误消息 */\n rateLimitMessage: string;\n\n constructor(rateLimitCode: string, rateLimitMessage: string, statusCode?: number) {\n super(rateLimitMessage, 'RATE_LIMIT_EXCEEDED', statusCode);\n this.name = 'RateLimitError';\n this.rateLimitCode = rateLimitCode;\n this.rateLimitMessage = rateLimitMessage;\n }\n}\n","import type {\n CapabilityClientOptions,\n ExtractedFile,\n UploadResult,\n AcquireUploadUrlResponse,\n AcquireDownloadUrlResponse,\n} from './types';\nimport { FileUploadError } from './errors';\nimport { slardar } from '@lark-apaas/internal-slardar';\n\ntype FileUploaderOptions = Pick<CapabilityClientOptions, 'acquireUploadUrl' | 'acquireDownloadUrl' | 'fetchOptions'>;\n\n/**\n * 文件上传器\n */\nexport class FileUploader {\n private readonly options: FileUploaderOptions;\n\n constructor(options: FileUploaderOptions) {\n this.options = options;\n }\n\n /**\n * 上传单个文件,返回下载 URL\n */\n async upload(file: File | Blob): Promise<string> {\n const fileName = file instanceof File ? file.name : `blob-${Date.now()}`;\n\n // 1. 获取上传预签名 URL\n const { uploadURL, objectKey } = await this.fetchUploadUrl(fileName);\n\n // 2. 上传文件到 TOS\n await this.uploadToTos(uploadURL, file);\n\n // 3. 获取下载 URL\n const downloadUrl = await this.fetchDownloadUrl(objectKey);\n\n return downloadUrl;\n }\n\n /**\n * 并发上传多个文件\n */\n async uploadAll(files: ExtractedFile[]): Promise<UploadResult[]> {\n const results = await Promise.all(\n files.map(async ({ path, file }) => {\n const downloadUrl = await this.upload(file);\n return { path, downloadUrl };\n })\n );\n return results;\n }\n\n /**\n * 获取上传预签名 URL\n */\n private async fetchUploadUrl(fileName: string): Promise<{ uploadURL: string; objectKey: string }> {\n const { acquireUploadUrl, fetchOptions } = this.options;\n\n let response: Response;\n try {\n response = await fetch(acquireUploadUrl, {\n method: 'POST',\n ...fetchOptions,\n headers: {\n 'Content-Type': 'application/json',\n ...fetchOptions?.headers,\n },\n body: JSON.stringify({ fileName }),\n });\n } catch (error) {\n slardar.captureException(error, { source: 'client-capability', module: 'file-upload', step: 'fetch-upload-url' });\n throw new FileUploadError(\n `Failed to acquire upload URL: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n\n if (!response.ok) {\n throw new FileUploadError(\n `Failed to acquire upload URL: HTTP ${response.status}`,\n response.status\n );\n }\n\n const data = (await response.json()) as AcquireUploadUrlResponse;\n\n if (data.status_code !== '0') {\n throw new FileUploadError(`Failed to acquire upload URL: ${data.status_code}`);\n }\n\n return data.data;\n }\n\n /**\n * 上传文件到 TOS(预签名 URL)\n */\n private async uploadToTos(uploadURL: string, file: File | Blob): Promise<void> {\n let response: Response;\n try {\n response = await fetch(uploadURL, {\n method: 'PUT',\n body: file,\n });\n } catch (error) {\n slardar.captureException(error, { source: 'client-capability', module: 'file-upload', step: 'upload-to-tos' });\n throw new FileUploadError(\n `Failed to upload file to TOS: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n\n if (!response.ok) {\n throw new FileUploadError(\n `Failed to upload file to TOS: HTTP ${response.status}`,\n response.status\n );\n }\n }\n\n /**\n * 获取临时下载 URL\n */\n private async fetchDownloadUrl(objectKey: string): Promise<string> {\n const { acquireDownloadUrl, fetchOptions } = this.options;\n\n let response: Response;\n try {\n response = await fetch(acquireDownloadUrl, {\n method: 'POST',\n ...fetchOptions,\n headers: {\n 'Content-Type': 'application/json',\n ...fetchOptions?.headers,\n },\n body: JSON.stringify({ objectKey }),\n });\n } catch (error) {\n slardar.captureException(error, { source: 'client-capability', module: 'file-upload', step: 'fetch-download-url' });\n throw new FileUploadError(\n `Failed to acquire download URL: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n\n if (!response.ok) {\n throw new FileUploadError(\n `Failed to acquire download URL: HTTP ${response.status}`,\n response.status\n );\n }\n\n const data = (await response.json()) as AcquireDownloadUrlResponse;\n\n if (data.status_code !== '0') {\n throw new FileUploadError(`Failed to acquire download URL: ${data.status_code}`);\n }\n\n return data.data.downloadURL;\n }\n}\n","import type { ExtractedFile, UploadResult } from './types';\n\n/**\n * 检测是否为 File 或 Blob\n */\nexport function isFile(value: unknown): value is File | Blob {\n return value instanceof File || value instanceof Blob;\n}\n\n/**\n * 递归提取 params 中的所有文件\n *\n * @example\n * extractFiles({ image_list: [file1, file2] })\n * // => [\n * // { path: ['image_list', 0], file: file1 },\n * // { path: ['image_list', 1], file: file2 }\n * // ]\n */\nexport function extractFiles(params: Record<string, unknown>): ExtractedFile[] {\n const files: ExtractedFile[] = [];\n\n function traverse(obj: unknown, path: (string | number)[]): void {\n if (isFile(obj)) {\n files.push({ path: [...path], file: obj });\n } else if (Array.isArray(obj)) {\n obj.forEach((item, index) => traverse(item, [...path, index]));\n } else if (obj !== null && typeof obj === 'object') {\n Object.entries(obj).forEach(([key, value]) => {\n traverse(value, [...path, key]);\n });\n }\n }\n\n traverse(params, []);\n return files;\n}\n\n/**\n * 根据上传结果替换 params 中的文件为 URL\n *\n * @example\n * replaceFilesWithUrls(\n * { image_list: [file1, file2] },\n * [\n * { path: ['image_list', 0], downloadUrl: 'https://...' },\n * { path: ['image_list', 1], downloadUrl: 'https://...' }\n * ]\n * )\n * // => { image_list: ['https://...', 'https://...'] }\n */\nexport function replaceFilesWithUrls(\n params: Record<string, unknown>,\n results: UploadResult[]\n): Record<string, unknown> {\n // 创建 path -> url 的映射,用于快速查找\n const urlMap = new Map<string, string>();\n for (const { path, downloadUrl } of results) {\n urlMap.set(JSON.stringify(path), downloadUrl);\n }\n\n // 手动深拷贝,同时将 File/Blob 替换为对应的 URL\n // 注意:不能使用 structuredClone,因为它不支持 File/Blob 对象\n function cloneAndReplace(obj: unknown, currentPath: (string | number)[]): unknown {\n // 检查当前路径是否有对应的 URL\n const pathKey = JSON.stringify(currentPath);\n if (urlMap.has(pathKey)) {\n return urlMap.get(pathKey);\n }\n\n // 如果是 File/Blob 但没有对应的 URL(不应该发生),返回 null\n if (isFile(obj)) {\n return null;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item, index) => cloneAndReplace(item, [...currentPath, index]));\n }\n\n if (obj !== null && typeof obj === 'object') {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n result[key] = cloneAndReplace(value, [...currentPath, key]);\n }\n return result;\n }\n\n // 原始值直接返回\n return obj;\n }\n\n return cloneAndReplace(params, []) as Record<string, unknown>;\n}\n","import type {\n CapabilityClientOptions,\n CapabilityExecutor,\n ApiResponse,\n ExecuteResponseData,\n StreamResponse,\n Logger,\n RateLimitErrorHook,\n} from './types';\nimport { ErrorCodes } from './types';\nimport {\n CapabilityError,\n CapabilityNotFoundError,\n ActionNotFoundError,\n NetworkError,\n ExecutionError,\n RateLimitError,\n} from './errors';\nimport { FileUploader } from './uploader';\nimport { extractFiles, replaceFilesWithUrls } from './file-extractor';\nimport { slardar } from '@lark-apaas/internal-slardar';\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};\n\n/**\n * 能力客户端\n */\nexport class CapabilityClient {\n private options: CapabilityClientOptions;\n private baseURL: string;\n private logger: Logger;\n private onRateLimitError?: RateLimitErrorHook;\n\n constructor(options: CapabilityClientOptions) {\n this.options = options;\n // 移除末尾的斜杠,确保拼接时格式正确\n this.baseURL = (options?.baseURL ?? '').replace(/\\/+$/, '');\n this.logger = options?.logger ?? defaultLogger;\n this.onRateLimitError = options?.onRateLimitError;\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 let requestParams = params ?? {};\n\n // 处理文件上传\n const extractedFiles = extractFiles(requestParams);\n if (extractedFiles.length > 0) {\n this.logger.info(LOG_PREFIX, `uploading ${extractedFiles.length} file(s)...`);\n const uploader = new FileUploader(this.options);\n const uploadResults = await uploader.uploadAll(extractedFiles);\n requestParams = replaceFilesWithUrls(requestParams, uploadResults);\n this.logger.info(LOG_PREFIX, `file upload completed`);\n }\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 {\n status_code: string;\n error_msg: string;\n is_rate_limit_error?: boolean;\n };\n const errorCode = errorResponse.status_code;\n\n // 计费受限错误:通过 is_rate_limit_error 字段识别\n if (errorResponse.is_rate_limit_error) {\n const rateLimitError = new RateLimitError(\n errorCode, // status_code 就是业务错误码\n errorResponse.error_msg,\n response.status,\n );\n await this.onRateLimitError?.(rateLimitError);\n throw rateLimitError;\n }\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 slardar.captureException(error, { source: 'client-capability', module: 'execute-call', capabilityId, action });\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 let requestParams = params ?? {};\n\n // 处理文件上传\n const extractedFiles = extractFiles(requestParams);\n if (extractedFiles.length > 0) {\n this.logger.info(LOG_PREFIX, `uploading ${extractedFiles.length} file(s)...`);\n const uploader = new FileUploader(this.options);\n const uploadResults = await uploader.uploadAll(extractedFiles);\n requestParams = replaceFilesWithUrls(requestParams, uploadResults);\n this.logger.info(LOG_PREFIX, `file upload completed`);\n }\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 slardar.captureException(error, { source: 'client-capability', module: 'execute-call-stream', capabilityId, action, phase: 'fetch' });\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 const err = parsed.data.error;\n if (err.isRateLimitError) {\n const rateLimitError = new RateLimitError(\n err.code, // code 就是业务错误码\n err.message,\n );\n await this.onRateLimitError?.(rateLimitError);\n throw rateLimitError;\n }\n throw new ExecutionError(err.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 slardar.captureException(error, { source: 'client-capability', module: 'execute-call-stream', capabilityId, action, phase: 'read' });\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"],"mappings":"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","names":["ErrorCodes","SUCCESS","CAPABILITY_NOT_FOUND","PLUGIN_NOT_FOUND","ACTION_NOT_FOUND","PARAMS_VALIDATION_ERROR","EXECUTION_ERROR","RATE_LIMIT_EXCEEDED","CapabilityError","Error","message","code","statusCode","name","CapabilityNotFoundError","capabilityId","ActionNotFoundError","NetworkError","ExecutionError","FileUploadError","RateLimitError","rateLimitCode","rateLimitMessage","FileUploader","options","upload","file","fileName","File","name","Date","now","uploadURL","objectKey","fetchUploadUrl","uploadToTos","downloadUrl","fetchDownloadUrl","uploadAll","files","results","Promise","all","map","path","acquireUploadUrl","fetchOptions","response","fetch","method","headers","body","JSON","stringify","error","slardar","captureException","source","module","step","FileUploadError","Error","message","String","ok","status","data","json","status_code","acquireDownloadUrl","downloadURL","isFile","value","File","Blob","extractFiles","params","files","traverse","obj","path","push","file","Array","isArray","forEach","item","index","Object","entries","key","replaceFilesWithUrls","results","urlMap","Map","downloadUrl","set","JSON","stringify","cloneAndReplace","currentPath","pathKey","has","get","map","result","import_internal_slardar","LOG_PREFIX","defaultLogger","debug","console","bind","info","warn","error","CapabilityClient","options","baseURL","logger","onRateLimitError","replace","load","capabilityId","createExecutor","call","action","params","executeCall","callStream","executeCallStream","url","requestParams","extractedFiles","extractFiles","length","uploader","FileUploader","uploadResults","uploadAll","replaceFilesWithUrls","response","fetch","method","fetchOptions","headers","body","JSON","stringify","data","json","ok","status_code","ErrorCodes","SUCCESS","errorResponse","errorCode","is_rate_limit_error","rateLimitError","RateLimitError","error_msg","status","CAPABILITY_NOT_FOUND","CapabilityNotFoundError","ACTION_NOT_FOUND","ActionNotFoundError","PLUGIN_NOT_FOUND","EXECUTION_ERROR","ExecutionError","result","output","slardar","captureException","source","module","CapabilityError","NetworkError","Error","message","String","phase","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","err","isRateLimitError","code","parseError","releaseLock","createClient"]}
package/dist/index.d.cts CHANGED
@@ -69,6 +69,10 @@ type RateLimitErrorHook = (error: RateLimitError) => void | Promise<void>;
69
69
  interface CapabilityClientOptions {
70
70
  /** 全局路径前缀,默认 ''。例如线上环境可设置为 '/spark/a' */
71
71
  baseURL?: string;
72
+ /** 获取文件上传预签名 URL 的接口地址,由上层注入 */
73
+ acquireUploadUrl: string;
74
+ /** 获取文件临时下载 URL 的接口地址,由上层注入 */
75
+ acquireDownloadUrl: string;
72
76
  /** 自定义 fetch 配置 */
73
77
  fetchOptions?: RequestInit;
74
78
  /** 自定义 logger,默认使用 console */
@@ -108,7 +112,7 @@ declare class CapabilityClient {
108
112
  private baseURL;
109
113
  private logger;
110
114
  private onRateLimitError?;
111
- constructor(options?: CapabilityClientOptions);
115
+ constructor(options: CapabilityClientOptions);
112
116
  /**
113
117
  * 加载能力,返回执行器
114
118
  * @param capabilityId - 能力 ID
@@ -122,6 +126,6 @@ declare class CapabilityClient {
122
126
  /**
123
127
  * 创建客户端实例
124
128
  */
125
- declare function createClient(options?: CapabilityClientOptions): CapabilityClient;
129
+ declare function createClient(options: CapabilityClientOptions): CapabilityClient;
126
130
 
127
131
  export { ActionNotFoundError, CapabilityClient, type CapabilityClientOptions, CapabilityError, type CapabilityExecutor, CapabilityNotFoundError, ExecutionError, FileUploadError, type Logger, NetworkError, RateLimitError, type RateLimitErrorHook, createClient };
package/dist/index.d.ts CHANGED
@@ -69,6 +69,10 @@ type RateLimitErrorHook = (error: RateLimitError) => void | Promise<void>;
69
69
  interface CapabilityClientOptions {
70
70
  /** 全局路径前缀,默认 ''。例如线上环境可设置为 '/spark/a' */
71
71
  baseURL?: string;
72
+ /** 获取文件上传预签名 URL 的接口地址,由上层注入 */
73
+ acquireUploadUrl: string;
74
+ /** 获取文件临时下载 URL 的接口地址,由上层注入 */
75
+ acquireDownloadUrl: string;
72
76
  /** 自定义 fetch 配置 */
73
77
  fetchOptions?: RequestInit;
74
78
  /** 自定义 logger,默认使用 console */
@@ -108,7 +112,7 @@ declare class CapabilityClient {
108
112
  private baseURL;
109
113
  private logger;
110
114
  private onRateLimitError?;
111
- constructor(options?: CapabilityClientOptions);
115
+ constructor(options: CapabilityClientOptions);
112
116
  /**
113
117
  * 加载能力,返回执行器
114
118
  * @param capabilityId - 能力 ID
@@ -122,6 +126,6 @@ declare class CapabilityClient {
122
126
  /**
123
127
  * 创建客户端实例
124
128
  */
125
- declare function createClient(options?: CapabilityClientOptions): CapabilityClient;
129
+ declare function createClient(options: CapabilityClientOptions): CapabilityClient;
126
130
 
127
131
  export { ActionNotFoundError, CapabilityClient, type CapabilityClientOptions, CapabilityError, type CapabilityExecutor, CapabilityNotFoundError, ExecutionError, FileUploadError, type Logger, NetworkError, RateLimitError, type RateLimitErrorHook, createClient };
package/dist/index.js CHANGED
@@ -13,7 +13,6 @@ var ErrorCodes = {
13
13
  EXECUTION_ERROR: "k_ec_cap_005",
14
14
  RATE_LIMIT_EXCEEDED: "k_ec_cap_006"
15
15
  };
16
- var UPLOAD_API_PATH = "/af/api/v1/studio/plugins/tmp_files";
17
16
 
18
17
  // src/errors.ts
19
18
  var _CapabilityError = class _CapabilityError extends Error {
@@ -86,19 +85,20 @@ __name(_RateLimitError, "RateLimitError");
86
85
  var RateLimitError = _RateLimitError;
87
86
 
88
87
  // src/uploader.ts
88
+ import { slardar } from "@lark-apaas/internal-slardar";
89
89
  var _FileUploader = class _FileUploader {
90
- constructor(fetchOptions) {
91
- __publicField(this, "fetchOptions");
92
- this.fetchOptions = fetchOptions;
90
+ constructor(options) {
91
+ __publicField(this, "options");
92
+ this.options = options;
93
93
  }
94
94
  /**
95
95
  * 上传单个文件,返回下载 URL
96
96
  */
97
97
  async upload(file) {
98
98
  const fileName = file instanceof File ? file.name : `blob-${Date.now()}`;
99
- const { uploadURL, objectKey } = await this.acquireUploadUrl(fileName);
99
+ const { uploadURL, objectKey } = await this.fetchUploadUrl(fileName);
100
100
  await this.uploadToTos(uploadURL, file);
101
- const downloadUrl = await this.acquireDownloadUrl(objectKey);
101
+ const downloadUrl = await this.fetchDownloadUrl(objectKey);
102
102
  return downloadUrl;
103
103
  }
104
104
  /**
@@ -117,22 +117,27 @@ var _FileUploader = class _FileUploader {
117
117
  /**
118
118
  * 获取上传预签名 URL
119
119
  */
120
- async acquireUploadUrl(fileName) {
121
- const url = `${UPLOAD_API_PATH}/acquire_upload_url`;
120
+ async fetchUploadUrl(fileName) {
121
+ const { acquireUploadUrl, fetchOptions } = this.options;
122
122
  let response;
123
123
  try {
124
- response = await fetch(url, {
124
+ response = await fetch(acquireUploadUrl, {
125
125
  method: "POST",
126
- ...this.fetchOptions,
126
+ ...fetchOptions,
127
127
  headers: {
128
128
  "Content-Type": "application/json",
129
- ...this.fetchOptions?.headers
129
+ ...fetchOptions?.headers
130
130
  },
131
131
  body: JSON.stringify({
132
132
  fileName
133
133
  })
134
134
  });
135
135
  } catch (error) {
136
+ slardar.captureException(error, {
137
+ source: "client-capability",
138
+ module: "file-upload",
139
+ step: "fetch-upload-url"
140
+ });
136
141
  throw new FileUploadError(`Failed to acquire upload URL: ${error instanceof Error ? error.message : String(error)}`);
137
142
  }
138
143
  if (!response.ok) {
@@ -155,6 +160,11 @@ var _FileUploader = class _FileUploader {
155
160
  body: file
156
161
  });
157
162
  } catch (error) {
163
+ slardar.captureException(error, {
164
+ source: "client-capability",
165
+ module: "file-upload",
166
+ step: "upload-to-tos"
167
+ });
158
168
  throw new FileUploadError(`Failed to upload file to TOS: ${error instanceof Error ? error.message : String(error)}`);
159
169
  }
160
170
  if (!response.ok) {
@@ -164,22 +174,27 @@ var _FileUploader = class _FileUploader {
164
174
  /**
165
175
  * 获取临时下载 URL
166
176
  */
167
- async acquireDownloadUrl(objectKey) {
168
- const url = `${UPLOAD_API_PATH}/acquire_download_url`;
177
+ async fetchDownloadUrl(objectKey) {
178
+ const { acquireDownloadUrl, fetchOptions } = this.options;
169
179
  let response;
170
180
  try {
171
- response = await fetch(url, {
181
+ response = await fetch(acquireDownloadUrl, {
172
182
  method: "POST",
173
- ...this.fetchOptions,
183
+ ...fetchOptions,
174
184
  headers: {
175
185
  "Content-Type": "application/json",
176
- ...this.fetchOptions?.headers
186
+ ...fetchOptions?.headers
177
187
  },
178
188
  body: JSON.stringify({
179
189
  objectKey
180
190
  })
181
191
  });
182
192
  } catch (error) {
193
+ slardar.captureException(error, {
194
+ source: "client-capability",
195
+ module: "file-upload",
196
+ step: "fetch-download-url"
197
+ });
183
198
  throw new FileUploadError(`Failed to acquire download URL: ${error instanceof Error ? error.message : String(error)}`);
184
199
  }
185
200
  if (!response.ok) {
@@ -266,6 +281,7 @@ function replaceFilesWithUrls(params, results) {
266
281
  __name(replaceFilesWithUrls, "replaceFilesWithUrls");
267
282
 
268
283
  // src/client.ts
284
+ import { slardar as slardar2 } from "@lark-apaas/internal-slardar";
269
285
  var LOG_PREFIX = "[CapabilityClient]";
270
286
  var defaultLogger = {
271
287
  debug: console.debug.bind(console),
@@ -279,7 +295,7 @@ var _CapabilityClient = class _CapabilityClient {
279
295
  __publicField(this, "baseURL");
280
296
  __publicField(this, "logger");
281
297
  __publicField(this, "onRateLimitError");
282
- this.options = options ?? {};
298
+ this.options = options;
283
299
  this.baseURL = (options?.baseURL ?? "").replace(/\/+$/, "");
284
300
  this.logger = options?.logger ?? defaultLogger;
285
301
  this.onRateLimitError = options?.onRateLimitError;
@@ -308,7 +324,7 @@ var _CapabilityClient = class _CapabilityClient {
308
324
  const extractedFiles = extractFiles(requestParams);
309
325
  if (extractedFiles.length > 0) {
310
326
  this.logger.info(LOG_PREFIX, `uploading ${extractedFiles.length} file(s)...`);
311
- const uploader = new FileUploader(this.options.fetchOptions);
327
+ const uploader = new FileUploader(this.options);
312
328
  const uploadResults = await uploader.uploadAll(extractedFiles);
313
329
  requestParams = replaceFilesWithUrls(requestParams, uploadResults);
314
330
  this.logger.info(LOG_PREFIX, `file upload completed`);
@@ -359,6 +375,12 @@ var _CapabilityClient = class _CapabilityClient {
359
375
  params: requestParams,
360
376
  error
361
377
  });
378
+ slardar2.captureException(error, {
379
+ source: "client-capability",
380
+ module: "execute-call",
381
+ capabilityId,
382
+ action
383
+ });
362
384
  if (error instanceof CapabilityError) {
363
385
  throw error;
364
386
  }
@@ -371,7 +393,7 @@ var _CapabilityClient = class _CapabilityClient {
371
393
  const extractedFiles = extractFiles(requestParams);
372
394
  if (extractedFiles.length > 0) {
373
395
  this.logger.info(LOG_PREFIX, `uploading ${extractedFiles.length} file(s)...`);
374
- const uploader = new FileUploader(this.options.fetchOptions);
396
+ const uploader = new FileUploader(this.options);
375
397
  const uploadResults = await uploader.uploadAll(extractedFiles);
376
398
  requestParams = replaceFilesWithUrls(requestParams, uploadResults);
377
399
  this.logger.info(LOG_PREFIX, `file upload completed`);
@@ -398,6 +420,13 @@ var _CapabilityClient = class _CapabilityClient {
398
420
  params: requestParams,
399
421
  error
400
422
  });
423
+ slardar2.captureException(error, {
424
+ source: "client-capability",
425
+ module: "execute-call-stream",
426
+ capabilityId,
427
+ action,
428
+ phase: "fetch"
429
+ });
401
430
  throw new NetworkError(error instanceof Error ? error.message : String(error));
402
431
  }
403
432
  if (!response.ok) {
@@ -497,6 +526,13 @@ var _CapabilityClient = class _CapabilityClient {
497
526
  error,
498
527
  chunkCount
499
528
  });
529
+ slardar2.captureException(error, {
530
+ source: "client-capability",
531
+ module: "execute-call-stream",
532
+ capabilityId,
533
+ action,
534
+ phase: "read"
535
+ });
500
536
  if (error instanceof CapabilityError) {
501
537
  throw error;
502
538
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts","../src/errors.ts","../src/uploader.ts","../src/file-extractor.ts","../src/client.ts"],"sourcesContent":["import type { RateLimitError } from './errors';\n\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 * RateLimitError 钩子函数类型\n * 当检测到计费受限错误时,在抛出异常前调用此钩子\n */\nexport type RateLimitErrorHook = (error: RateLimitError) => void | Promise<void>;\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 * 当检测到 RateLimitError 时,在抛出异常前调用此钩子\n * 可用于上报埋点、展示 toast 等场景\n */\n onRateLimitError?: RateLimitErrorHook;\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 is_rate_limit_error?: boolean;\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 /** 错误码,计费受限时为业务错误码(如 k_st_ec_400002687) */\n code: string;\n message: string;\n /** 是否为计费受限错误 */\n isRateLimitError?: boolean;\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 RATE_LIMIT_EXCEEDED: 'k_ec_cap_006',\n} as const;\n\n// ========== 文件上传相关类型 ==========\n\n/**\n * 文件上传接口 BasePath\n */\nexport const UPLOAD_API_PATH = '/af/api/v1/studio/plugins/tmp_files';\n\n/**\n * 提取的文件信息\n */\nexport interface ExtractedFile {\n /** 在 params 中的路径,如 ['image_list', 0] */\n path: (string | number)[];\n /** 文件对象 */\n file: File | Blob;\n}\n\n/**\n * 上传结果\n */\nexport interface UploadResult {\n /** 在 params 中的路径 */\n path: (string | number)[];\n /** 临时下载 URL */\n downloadUrl: string;\n}\n\n/**\n * 获取上传 URL 响应\n */\nexport interface AcquireUploadUrlResponse {\n status_code: string;\n data: {\n uploadURL: string;\n objectKey: string;\n };\n}\n\n/**\n * 获取下载 URL 响应\n */\nexport interface AcquireDownloadUrlResponse {\n status_code: string;\n data: {\n downloadURL: string;\n };\n}\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\n/**\n * 文件上传错误\n */\nexport class FileUploadError extends CapabilityError {\n constructor(message: string, statusCode?: number) {\n super(message, 'FILE_UPLOAD_ERROR', statusCode);\n this.name = 'FileUploadError';\n }\n}\n\n/**\n * 计费受限错误\n */\nexport class RateLimitError extends CapabilityError {\n /** 业务错误码 */\n rateLimitCode: string;\n /** 业务错误消息 */\n rateLimitMessage: string;\n\n constructor(rateLimitCode: string, rateLimitMessage: string, statusCode?: number) {\n super(rateLimitMessage, 'RATE_LIMIT_EXCEEDED', statusCode);\n this.name = 'RateLimitError';\n this.rateLimitCode = rateLimitCode;\n this.rateLimitMessage = rateLimitMessage;\n }\n}\n","import type {\n ExtractedFile,\n UploadResult,\n AcquireUploadUrlResponse,\n AcquireDownloadUrlResponse,\n} from './types';\nimport { UPLOAD_API_PATH } from './types';\nimport { FileUploadError } from './errors';\n\n/**\n * 文件上传器\n */\nexport class FileUploader {\n private readonly fetchOptions?: RequestInit;\n\n constructor(fetchOptions?: RequestInit) {\n this.fetchOptions = fetchOptions;\n }\n\n /**\n * 上传单个文件,返回下载 URL\n */\n async upload(file: File | Blob): Promise<string> {\n const fileName = file instanceof File ? file.name : `blob-${Date.now()}`;\n\n // 1. 获取上传预签名 URL\n const { uploadURL, objectKey } = await this.acquireUploadUrl(fileName);\n\n // 2. 上传文件到 TOS\n await this.uploadToTos(uploadURL, file);\n\n // 3. 获取下载 URL\n const downloadUrl = await this.acquireDownloadUrl(objectKey);\n\n return downloadUrl;\n }\n\n /**\n * 并发上传多个文件\n */\n async uploadAll(files: ExtractedFile[]): Promise<UploadResult[]> {\n const results = await Promise.all(\n files.map(async ({ path, file }) => {\n const downloadUrl = await this.upload(file);\n return { path, downloadUrl };\n })\n );\n return results;\n }\n\n /**\n * 获取上传预签名 URL\n */\n private async acquireUploadUrl(fileName: string): Promise<{ uploadURL: string; objectKey: string }> {\n const url = `${UPLOAD_API_PATH}/acquire_upload_url`;\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: 'POST',\n ...this.fetchOptions,\n headers: {\n 'Content-Type': 'application/json',\n ...this.fetchOptions?.headers,\n },\n body: JSON.stringify({ fileName }),\n });\n } catch (error) {\n throw new FileUploadError(\n `Failed to acquire upload URL: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n\n if (!response.ok) {\n throw new FileUploadError(\n `Failed to acquire upload URL: HTTP ${response.status}`,\n response.status\n );\n }\n\n const data = (await response.json()) as AcquireUploadUrlResponse;\n\n if (data.status_code !== '0') {\n throw new FileUploadError(`Failed to acquire upload URL: ${data.status_code}`);\n }\n\n return data.data;\n }\n\n /**\n * 上传文件到 TOS(预签名 URL)\n */\n private async uploadToTos(uploadURL: string, file: File | Blob): Promise<void> {\n let response: Response;\n try {\n response = await fetch(uploadURL, {\n method: 'PUT',\n body: file,\n });\n } catch (error) {\n throw new FileUploadError(\n `Failed to upload file to TOS: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n\n if (!response.ok) {\n throw new FileUploadError(\n `Failed to upload file to TOS: HTTP ${response.status}`,\n response.status\n );\n }\n }\n\n /**\n * 获取临时下载 URL\n */\n private async acquireDownloadUrl(objectKey: string): Promise<string> {\n const url = `${UPLOAD_API_PATH}/acquire_download_url`;\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: 'POST',\n ...this.fetchOptions,\n headers: {\n 'Content-Type': 'application/json',\n ...this.fetchOptions?.headers,\n },\n body: JSON.stringify({ objectKey }),\n });\n } catch (error) {\n throw new FileUploadError(\n `Failed to acquire download URL: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n\n if (!response.ok) {\n throw new FileUploadError(\n `Failed to acquire download URL: HTTP ${response.status}`,\n response.status\n );\n }\n\n const data = (await response.json()) as AcquireDownloadUrlResponse;\n\n if (data.status_code !== '0') {\n throw new FileUploadError(`Failed to acquire download URL: ${data.status_code}`);\n }\n\n return data.data.downloadURL;\n }\n}\n","import type { ExtractedFile, UploadResult } from './types';\n\n/**\n * 检测是否为 File 或 Blob\n */\nexport function isFile(value: unknown): value is File | Blob {\n return value instanceof File || value instanceof Blob;\n}\n\n/**\n * 递归提取 params 中的所有文件\n *\n * @example\n * extractFiles({ image_list: [file1, file2] })\n * // => [\n * // { path: ['image_list', 0], file: file1 },\n * // { path: ['image_list', 1], file: file2 }\n * // ]\n */\nexport function extractFiles(params: Record<string, unknown>): ExtractedFile[] {\n const files: ExtractedFile[] = [];\n\n function traverse(obj: unknown, path: (string | number)[]): void {\n if (isFile(obj)) {\n files.push({ path: [...path], file: obj });\n } else if (Array.isArray(obj)) {\n obj.forEach((item, index) => traverse(item, [...path, index]));\n } else if (obj !== null && typeof obj === 'object') {\n Object.entries(obj).forEach(([key, value]) => {\n traverse(value, [...path, key]);\n });\n }\n }\n\n traverse(params, []);\n return files;\n}\n\n/**\n * 根据上传结果替换 params 中的文件为 URL\n *\n * @example\n * replaceFilesWithUrls(\n * { image_list: [file1, file2] },\n * [\n * { path: ['image_list', 0], downloadUrl: 'https://...' },\n * { path: ['image_list', 1], downloadUrl: 'https://...' }\n * ]\n * )\n * // => { image_list: ['https://...', 'https://...'] }\n */\nexport function replaceFilesWithUrls(\n params: Record<string, unknown>,\n results: UploadResult[]\n): Record<string, unknown> {\n // 创建 path -> url 的映射,用于快速查找\n const urlMap = new Map<string, string>();\n for (const { path, downloadUrl } of results) {\n urlMap.set(JSON.stringify(path), downloadUrl);\n }\n\n // 手动深拷贝,同时将 File/Blob 替换为对应的 URL\n // 注意:不能使用 structuredClone,因为它不支持 File/Blob 对象\n function cloneAndReplace(obj: unknown, currentPath: (string | number)[]): unknown {\n // 检查当前路径是否有对应的 URL\n const pathKey = JSON.stringify(currentPath);\n if (urlMap.has(pathKey)) {\n return urlMap.get(pathKey);\n }\n\n // 如果是 File/Blob 但没有对应的 URL(不应该发生),返回 null\n if (isFile(obj)) {\n return null;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item, index) => cloneAndReplace(item, [...currentPath, index]));\n }\n\n if (obj !== null && typeof obj === 'object') {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n result[key] = cloneAndReplace(value, [...currentPath, key]);\n }\n return result;\n }\n\n // 原始值直接返回\n return obj;\n }\n\n return cloneAndReplace(params, []) as Record<string, unknown>;\n}\n","import type {\n CapabilityClientOptions,\n CapabilityExecutor,\n ApiResponse,\n ExecuteResponseData,\n StreamResponse,\n Logger,\n RateLimitErrorHook,\n} from './types';\nimport { ErrorCodes } from './types';\nimport {\n CapabilityError,\n CapabilityNotFoundError,\n ActionNotFoundError,\n NetworkError,\n ExecutionError,\n RateLimitError,\n} from './errors';\nimport { FileUploader } from './uploader';\nimport { extractFiles, replaceFilesWithUrls } from './file-extractor';\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};\n\n/**\n * 能力客户端\n */\nexport class CapabilityClient {\n private options: CapabilityClientOptions;\n private baseURL: string;\n private logger: Logger;\n private onRateLimitError?: RateLimitErrorHook;\n\n constructor(options?: CapabilityClientOptions) {\n this.options = options ?? {};\n // 移除末尾的斜杠,确保拼接时格式正确\n this.baseURL = (options?.baseURL ?? '').replace(/\\/+$/, '');\n this.logger = options?.logger ?? defaultLogger;\n this.onRateLimitError = options?.onRateLimitError;\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 let requestParams = params ?? {};\n\n // 处理文件上传\n const extractedFiles = extractFiles(requestParams);\n if (extractedFiles.length > 0) {\n this.logger.info(LOG_PREFIX, `uploading ${extractedFiles.length} file(s)...`);\n const uploader = new FileUploader(this.options.fetchOptions);\n const uploadResults = await uploader.uploadAll(extractedFiles);\n requestParams = replaceFilesWithUrls(requestParams, uploadResults);\n this.logger.info(LOG_PREFIX, `file upload completed`);\n }\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 {\n status_code: string;\n error_msg: string;\n is_rate_limit_error?: boolean;\n };\n const errorCode = errorResponse.status_code;\n\n // 计费受限错误:通过 is_rate_limit_error 字段识别\n if (errorResponse.is_rate_limit_error) {\n const rateLimitError = new RateLimitError(\n errorCode, // status_code 就是业务错误码\n errorResponse.error_msg,\n response.status,\n );\n await this.onRateLimitError?.(rateLimitError);\n throw rateLimitError;\n }\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 let requestParams = params ?? {};\n\n // 处理文件上传\n const extractedFiles = extractFiles(requestParams);\n if (extractedFiles.length > 0) {\n this.logger.info(LOG_PREFIX, `uploading ${extractedFiles.length} file(s)...`);\n const uploader = new FileUploader(this.options.fetchOptions);\n const uploadResults = await uploader.uploadAll(extractedFiles);\n requestParams = replaceFilesWithUrls(requestParams, uploadResults);\n this.logger.info(LOG_PREFIX, `file upload completed`);\n }\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 const err = parsed.data.error;\n if (err.isRateLimitError) {\n const rateLimitError = new RateLimitError(\n err.code, // code 就是业务错误码\n err.message,\n );\n await this.onRateLimitError?.(rateLimitError);\n throw rateLimitError;\n }\n throw new ExecutionError(err.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"],"mappings":";;;;;;AA0IO,IAAMA,aAAa;EACxBC,SAAS;EACTC,sBAAsB;EACtBC,kBAAkB;EAClBC,kBAAkB;EAClBC,yBAAyB;EACzBC,iBAAiB;EACjBC,qBAAqB;AACvB;AAOO,IAAMC,kBAAkB;;;ACtJxB,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;AAUA,IAAMC,mBAAN,MAAMA,yBAAwBX,gBAAAA;EACnC,YAAYE,SAAiBE,YAAqB;AAChD,UAAMF,SAAS,qBAAqBE,UAAAA;AACpC,SAAKC,OAAO;EACd;AACF;AALqCL;AAA9B,IAAMW,kBAAN;AAUA,IAAMC,kBAAN,MAAMA,wBAAuBZ,gBAAAA;EAMlC,YAAYa,eAAuBC,kBAA0BV,YAAqB;AAChF,UAAMU,kBAAkB,uBAAuBV,UAAAA;AALjDS;;AAEAC;;AAIE,SAAKT,OAAO;AACZ,SAAKQ,gBAAgBA;AACrB,SAAKC,mBAAmBA;EAC1B;AACF;AAZoCd;AAA7B,IAAMY,iBAAN;;;AC1DA,IAAMG,gBAAN,MAAMA,cAAAA;EAGX,YAAYC,cAA4B;AAFvBA;AAGf,SAAKA,eAAeA;EACtB;;;;EAKA,MAAMC,OAAOC,MAAoC;AAC/C,UAAMC,WAAWD,gBAAgBE,OAAOF,KAAKG,OAAO,QAAQC,KAAKC,IAAG,CAAA;AAGpE,UAAM,EAAEC,WAAWC,UAAS,IAAK,MAAM,KAAKC,iBAAiBP,QAAAA;AAG7D,UAAM,KAAKQ,YAAYH,WAAWN,IAAAA;AAGlC,UAAMU,cAAc,MAAM,KAAKC,mBAAmBJ,SAAAA;AAElD,WAAOG;EACT;;;;EAKA,MAAME,UAAUC,OAAiD;AAC/D,UAAMC,UAAU,MAAMC,QAAQC,IAC5BH,MAAMI,IAAI,OAAO,EAAEC,MAAMlB,KAAI,MAAE;AAC7B,YAAMU,cAAc,MAAM,KAAKX,OAAOC,IAAAA;AACtC,aAAO;QAAEkB;QAAMR;MAAY;IAC7B,CAAA,CAAA;AAEF,WAAOI;EACT;;;;EAKA,MAAcN,iBAAiBP,UAAqE;AAClG,UAAMkB,MAAM,GAAGC,eAAAA;AAEf,QAAIC;AACJ,QAAI;AACFA,iBAAW,MAAMC,MAAMH,KAAK;QAC1BI,QAAQ;QACR,GAAG,KAAKzB;QACR0B,SAAS;UACP,gBAAgB;UAChB,GAAG,KAAK1B,cAAc0B;QACxB;QACAC,MAAMC,KAAKC,UAAU;UAAE1B;QAAS,CAAA;MAClC,CAAA;IACF,SAAS2B,OAAO;AACd,YAAM,IAAIC,gBACR,iCAAiCD,iBAAiBE,QAAQF,MAAMG,UAAUC,OAAOJ,KAAAA,CAAAA,EAAQ;IAE7F;AAEA,QAAI,CAACP,SAASY,IAAI;AAChB,YAAM,IAAIJ,gBACR,sCAAsCR,SAASa,MAAM,IACrDb,SAASa,MAAM;IAEnB;AAEA,UAAMC,OAAQ,MAAMd,SAASe,KAAI;AAEjC,QAAID,KAAKE,gBAAgB,KAAK;AAC5B,YAAM,IAAIR,gBAAgB,iCAAiCM,KAAKE,WAAW,EAAE;IAC/E;AAEA,WAAOF,KAAKA;EACd;;;;EAKA,MAAc1B,YAAYH,WAAmBN,MAAkC;AAC7E,QAAIqB;AACJ,QAAI;AACFA,iBAAW,MAAMC,MAAMhB,WAAW;QAChCiB,QAAQ;QACRE,MAAMzB;MACR,CAAA;IACF,SAAS4B,OAAO;AACd,YAAM,IAAIC,gBACR,iCAAiCD,iBAAiBE,QAAQF,MAAMG,UAAUC,OAAOJ,KAAAA,CAAAA,EAAQ;IAE7F;AAEA,QAAI,CAACP,SAASY,IAAI;AAChB,YAAM,IAAIJ,gBACR,sCAAsCR,SAASa,MAAM,IACrDb,SAASa,MAAM;IAEnB;EACF;;;;EAKA,MAAcvB,mBAAmBJ,WAAoC;AACnE,UAAMY,MAAM,GAAGC,eAAAA;AAEf,QAAIC;AACJ,QAAI;AACFA,iBAAW,MAAMC,MAAMH,KAAK;QAC1BI,QAAQ;QACR,GAAG,KAAKzB;QACR0B,SAAS;UACP,gBAAgB;UAChB,GAAG,KAAK1B,cAAc0B;QACxB;QACAC,MAAMC,KAAKC,UAAU;UAAEpB;QAAU,CAAA;MACnC,CAAA;IACF,SAASqB,OAAO;AACd,YAAM,IAAIC,gBACR,mCAAmCD,iBAAiBE,QAAQF,MAAMG,UAAUC,OAAOJ,KAAAA,CAAAA,EAAQ;IAE/F;AAEA,QAAI,CAACP,SAASY,IAAI;AAChB,YAAM,IAAIJ,gBACR,wCAAwCR,SAASa,MAAM,IACvDb,SAASa,MAAM;IAEnB;AAEA,UAAMC,OAAQ,MAAMd,SAASe,KAAI;AAEjC,QAAID,KAAKE,gBAAgB,KAAK;AAC5B,YAAM,IAAIR,gBAAgB,mCAAmCM,KAAKE,WAAW,EAAE;IACjF;AAEA,WAAOF,KAAKA,KAAKG;EACnB;AACF;AA3IazC;AAAN,IAAMA,eAAN;;;ACPA,SAAS0C,OAAOC,OAAc;AACnC,SAAOA,iBAAiBC,QAAQD,iBAAiBE;AACnD;AAFgBH;AAcT,SAASI,aAAaC,QAA+B;AAC1D,QAAMC,QAAyB,CAAA;AAE/B,WAASC,SAASC,KAAcC,MAAyB;AACvD,QAAIT,OAAOQ,GAAAA,GAAM;AACfF,YAAMI,KAAK;QAAED,MAAM;aAAIA;;QAAOE,MAAMH;MAAI,CAAA;IAC1C,WAAWI,MAAMC,QAAQL,GAAAA,GAAM;AAC7BA,UAAIM,QAAQ,CAACC,MAAMC,UAAUT,SAASQ,MAAM;WAAIN;QAAMO;OAAM,CAAA;IAC9D,WAAWR,QAAQ,QAAQ,OAAOA,QAAQ,UAAU;AAClDS,aAAOC,QAAQV,GAAAA,EAAKM,QAAQ,CAAC,CAACK,KAAKlB,KAAAA,MAAM;AACvCM,iBAASN,OAAO;aAAIQ;UAAMU;SAAI;MAChC,CAAA;IACF;EACF;AAVSZ;AAYTA,WAASF,QAAQ,CAAA,CAAE;AACnB,SAAOC;AACT;AAjBgBF;AAgCT,SAASgB,qBACdf,QACAgB,SAAuB;AAGvB,QAAMC,SAAS,oBAAIC,IAAAA;AACnB,aAAW,EAAEd,MAAMe,YAAW,KAAMH,SAAS;AAC3CC,WAAOG,IAAIC,KAAKC,UAAUlB,IAAAA,GAAOe,WAAAA;EACnC;AAIA,WAASI,gBAAgBpB,KAAcqB,aAAgC;AAErE,UAAMC,UAAUJ,KAAKC,UAAUE,WAAAA;AAC/B,QAAIP,OAAOS,IAAID,OAAAA,GAAU;AACvB,aAAOR,OAAOU,IAAIF,OAAAA;IACpB;AAGA,QAAI9B,OAAOQ,GAAAA,GAAM;AACf,aAAO;IACT;AAEA,QAAII,MAAMC,QAAQL,GAAAA,GAAM;AACtB,aAAOA,IAAIyB,IAAI,CAAClB,MAAMC,UAAUY,gBAAgBb,MAAM;WAAIc;QAAab;OAAM,CAAA;IAC/E;AAEA,QAAIR,QAAQ,QAAQ,OAAOA,QAAQ,UAAU;AAC3C,YAAM0B,SAAkC,CAAC;AACzC,iBAAW,CAACf,KAAKlB,KAAAA,KAAUgB,OAAOC,QAAQV,GAAAA,GAAM;AAC9C0B,eAAOf,GAAAA,IAAOS,gBAAgB3B,OAAO;aAAI4B;UAAaV;SAAI;MAC5D;AACA,aAAOe;IACT;AAGA,WAAO1B;EACT;AA1BSoB;AA4BT,SAAOA,gBAAgBvB,QAAQ,CAAA,CAAE;AACnC;AAzCgBe;;;AC9BhB,IAAMe,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;AAKO,IAAMK,oBAAN,MAAMA,kBAAAA;EAMX,YAAYC,SAAmC;AALvCA;AACAC;AACAC;AACAC;AAGN,SAAKH,UAAUA,WAAW,CAAC;AAE3B,SAAKC,WAAWD,SAASC,WAAW,IAAIG,QAAQ,QAAQ,EAAA;AACxD,SAAKF,SAASF,SAASE,UAAUV;AACjC,SAAKW,mBAAmBH,SAASG;EACnC;;;;;;EAOAE,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,KAAKb,OAAO,mBAAmBK,YAAAA;AAC9C,QAAIS,gBAAgBL,UAAU,CAAC;AAG/B,UAAMM,iBAAiBC,aAAaF,aAAAA;AACpC,QAAIC,eAAeE,SAAS,GAAG;AAC7B,WAAKhB,OAAON,KAAKL,YAAY,aAAayB,eAAeE,MAAM,aAAa;AAC5E,YAAMC,WAAW,IAAIC,aAAa,KAAKpB,QAAQqB,YAAY;AAC3D,YAAMC,gBAAgB,MAAMH,SAASI,UAAUP,cAAAA;AAC/CD,sBAAgBS,qBAAqBT,eAAeO,aAAAA;AACpD,WAAKpB,OAAON,KAAKL,YAAY,uBAAuB;IACtD;AAEA,SAAKW,OAAON,KAAKL,YAAY,4BAA4Be,YAAAA,YAAwBG,MAAAA,IAAU;MAAEC,QAAQK;IAAc,CAAA;AAEnH,QAAI;AACF,YAAMU,WAAW,MAAMC,MAAMZ,KAAK;QAChCa,QAAQ;QACR,GAAG,KAAK3B,QAAQqB;QAChBO,SAAS;UACP,gBAAgB;UAChB,GAAG,KAAK5B,QAAQqB,cAAcO;QAChC;QACAC,MAAMC,KAAKC,UAAU;UACnBtB;UACAC,QAAQK;QACV,CAAA;MACF,CAAA;AAEA,YAAMiB,OAAQ,MAAMP,SAASQ,KAAI;AAEjC,UAAI,CAACR,SAASS,MAAMF,KAAKG,gBAAgBC,WAAWC,SAAS;AAC3D,cAAMC,gBAAgBN;AAKtB,cAAMO,YAAYD,cAAcH;AAGhC,YAAIG,cAAcE,qBAAqB;AACrC,gBAAMC,iBAAiB,IAAIC,eACzBH,WACAD,cAAcK,WACdlB,SAASmB,MAAM;AAEjB,gBAAM,KAAKzC,mBAAmBsC,cAAAA;AAC9B,gBAAMA;QACR;AAEA,gBAAQF,WAAAA;UACN,KAAKH,WAAWS;AACd,kBAAM,IAAIC,wBAAwBxC,cAAcmB,SAASmB,MAAM;UACjE,KAAKR,WAAWW;AACd,kBAAM,IAAIC,oBAAoBV,cAAcK,WAAWlB,SAASmB,MAAM;UACxE,KAAKR,WAAWa;UAChB,KAAKb,WAAWc;UAChB;AACE,kBAAM,IAAIC,eAAeb,cAAcK,WAAWlB,SAASmB,MAAM;QACrE;MACF;AAEA,YAAMQ,SAAUpB,KAAuCA,KAAKqB;AAE5D,WAAKnD,OAAON,KAAKL,YAAY,8BAA8Be,YAAAA,YAAwBG,MAAAA,IAAU;QAAE2C;MAAO,CAAA;AAEtG,aAAOA;IACT,SAAStD,OAAO;AACd,WAAKI,OAAOJ,MAAMP,YAAY,6BAA6Be,YAAAA,YAAwBG,MAAAA,IAAU;QAAEC,QAAQK;QAAejB;MAAM,CAAA;AAC5H,UAAIA,iBAAiBwD,iBAAiB;AACpC,cAAMxD;MACR;AACA,YAAM,IAAIyD,aAAazD,iBAAiB0D,QAAQ1D,MAAM2D,UAAUC,OAAO5D,KAAAA,CAAAA;IACzE;EACF;EAEA,OAAee,kBACbP,cACAG,QACAC,QACkB;AAClB,UAAMI,MAAM,GAAG,KAAKb,OAAO,mBAAmBK,YAAAA;AAC9C,QAAIS,gBAAgBL,UAAU,CAAC;AAG/B,UAAMM,iBAAiBC,aAAaF,aAAAA;AACpC,QAAIC,eAAeE,SAAS,GAAG;AAC7B,WAAKhB,OAAON,KAAKL,YAAY,aAAayB,eAAeE,MAAM,aAAa;AAC5E,YAAMC,WAAW,IAAIC,aAAa,KAAKpB,QAAQqB,YAAY;AAC3D,YAAMC,gBAAgB,MAAMH,SAASI,UAAUP,cAAAA;AAC/CD,sBAAgBS,qBAAqBT,eAAeO,aAAAA;AACpD,WAAKpB,OAAON,KAAKL,YAAY,uBAAuB;IACtD;AAEA,SAAKW,OAAON,KAAKL,YAAY,kCAAkCe,YAAAA,YAAwBG,MAAAA,IAAU;MAAEC,QAAQK;IAAc,CAAA;AAEzH,QAAIU;AACJ,QAAI;AACFA,iBAAW,MAAMC,MAAMZ,KAAK;QAC1Ba,QAAQ;QACR,GAAG,KAAK3B,QAAQqB;QAChBO,SAAS;UACP,gBAAgB;UAChB,GAAG,KAAK5B,QAAQqB,cAAcO;QAChC;QACAC,MAAMC,KAAKC,UAAU;UACnBtB;UACAC,QAAQK;QACV,CAAA;MACF,CAAA;IACF,SAASjB,OAAO;AACd,WAAKI,OAAOJ,MAAMP,YAAY,mCAAmCe,YAAAA,YAAwBG,MAAAA,IAAU;QAAEC,QAAQK;QAAejB;MAAM,CAAA;AAClI,YAAM,IAAIyD,aAAazD,iBAAiB0D,QAAQ1D,MAAM2D,UAAUC,OAAO5D,KAAAA,CAAAA;IACzE;AAEA,QAAI,CAAC2B,SAASS,IAAI;AAChB,YAAMyB,SAAS,QAAQlC,SAASmB,MAAM,IAAInB,SAASmC,UAAU;AAC7D,WAAK1D,OAAOJ,MAAMP,YAAY,mCAAmCe,YAAAA,YAAwBG,MAAAA,IAAU;QAAEC,QAAQK;QAAejB,OAAO6D;MAAO,CAAA;AAC1I,YAAM,IAAIJ,aAAaI,MAAAA;IACzB;AAEA,QAAI,CAAClC,SAASI,MAAM;AAClB,YAAM8B,SAAS;AACf,WAAKzD,OAAOJ,MAAMP,YAAY,mCAAmCe,YAAAA,YAAwBG,MAAAA,IAAU;QAAEC,QAAQK;QAAejB,OAAO6D;MAAO,CAAA;AAC1I,YAAM,IAAIJ,aAAaI,MAAAA;IACzB;AAEA,UAAME,SAASpC,SAASI,KAAKiC,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,kBAAM9C,OAAO6C,KAAKE,MAAM,CAAA;AAExB,gBAAI;AACF,oBAAMC,SAASlD,KAAKmD,MAAMjD,IAAAA;AAE1B,kBAAIgD,OAAO7C,gBAAgBC,WAAWC,WAAW2C,OAAOhD,MAAM;AAC5D,oBAAIgD,OAAOhD,KAAKkD,SAAS,WAAW;AAClChB;AACA,wBAAMiB,QAAQH,OAAOhD,KAAKmD;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,OAAOhD,KAAKqD,UAAU;AACxB,0BAAMC,cAAalB,eACf;sBAAEF;sBAAYd,QAAQe;oBAAkB,IACxC;sBAAED;sBAAYqB,cAAcpB,kBAAkBjD,UAAUgD;oBAAW;AACvE,yBAAKhE,OAAON,KAAKL,YAAY,gCAAgCe,YAAAA,YAAwBG,MAAAA,IAAU6E,WAAAA;AAC/F;kBACF;gBACF,WAAWN,OAAOhD,KAAKkD,SAAS,SAAS;AACvC,wBAAMM,MAAMR,OAAOhD,KAAKlC;AACxB,sBAAI0F,IAAIC,kBAAkB;AACxB,0BAAMhD,iBAAiB,IAAIC,eACzB8C,IAAIE,MACJF,IAAI/B,OAAO;AAEb,0BAAM,KAAKtD,mBAAmBsC,cAAAA;AAC9B,0BAAMA;kBACR;AACA,wBAAM,IAAIU,eAAeqC,IAAI/B,OAAO;gBACtC;cACF;YACF,SAASkC,YAAY;AACnB,kBAAIA,sBAAsBrC,iBAAiB;AACzC,qBAAKpD,OAAOJ,MAAMP,YAAY,mCAAmCe,YAAAA,YAAwBG,MAAAA,IAAU;kBAAEC,QAAQK;kBAAejB,OAAO6F;kBAAYzB;gBAAW,CAAA;AAC1J,sBAAMyB;cACR;YAEF;UACF;QACF;MACF;AACA,YAAML,aAAalB,eACf;QAAEF;QAAYd,QAAQe;MAAkB,IACxC;QAAED;QAAYqB,cAAcpB,kBAAkBjD,UAAUgD;MAAW;AACvE,WAAKhE,OAAON,KAAKL,YAAY,gCAAgCe,YAAAA,YAAwBG,MAAAA,IAAU6E,UAAAA;IACjG,SAASxF,OAAO;AACd,WAAKI,OAAOJ,MAAMP,YAAY,mCAAmCe,YAAAA,YAAwBG,MAAAA,IAAU;QAAEC,QAAQK;QAAejB;QAAOoE;MAAW,CAAA;AAC9I,UAAIpE,iBAAiBwD,iBAAiB;AACpC,cAAMxD;MACR;AACA,YAAM,IAAIyD,aAAazD,iBAAiB0D,QAAQ1D,MAAM2D,UAAUC,OAAO5D,KAAAA,CAAAA;IACzE,UAAA;AACE+D,aAAO+B,YAAW;IACpB;EACF;AACF;AA1Pa7F;AAAN,IAAMA,mBAAN;AA+PA,SAAS8F,aAAa7F,SAAiC;AAC5D,SAAO,IAAID,iBAAiBC,OAAAA;AAC9B;AAFgB6F;","names":["ErrorCodes","SUCCESS","CAPABILITY_NOT_FOUND","PLUGIN_NOT_FOUND","ACTION_NOT_FOUND","PARAMS_VALIDATION_ERROR","EXECUTION_ERROR","RATE_LIMIT_EXCEEDED","UPLOAD_API_PATH","CapabilityError","Error","message","code","statusCode","name","CapabilityNotFoundError","capabilityId","ActionNotFoundError","NetworkError","ExecutionError","FileUploadError","RateLimitError","rateLimitCode","rateLimitMessage","FileUploader","fetchOptions","upload","file","fileName","File","name","Date","now","uploadURL","objectKey","acquireUploadUrl","uploadToTos","downloadUrl","acquireDownloadUrl","uploadAll","files","results","Promise","all","map","path","url","UPLOAD_API_PATH","response","fetch","method","headers","body","JSON","stringify","error","FileUploadError","Error","message","String","ok","status","data","json","status_code","downloadURL","isFile","value","File","Blob","extractFiles","params","files","traverse","obj","path","push","file","Array","isArray","forEach","item","index","Object","entries","key","replaceFilesWithUrls","results","urlMap","Map","downloadUrl","set","JSON","stringify","cloneAndReplace","currentPath","pathKey","has","get","map","result","LOG_PREFIX","defaultLogger","debug","console","bind","info","warn","error","CapabilityClient","options","baseURL","logger","onRateLimitError","replace","load","capabilityId","createExecutor","call","action","params","executeCall","callStream","executeCallStream","url","requestParams","extractedFiles","extractFiles","length","uploader","FileUploader","fetchOptions","uploadResults","uploadAll","replaceFilesWithUrls","response","fetch","method","headers","body","JSON","stringify","data","json","ok","status_code","ErrorCodes","SUCCESS","errorResponse","errorCode","is_rate_limit_error","rateLimitError","RateLimitError","error_msg","status","CAPABILITY_NOT_FOUND","CapabilityNotFoundError","ACTION_NOT_FOUND","ActionNotFoundError","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","err","isRateLimitError","code","parseError","releaseLock","createClient"]}
1
+ {"version":3,"sources":["../src/types.ts","../src/errors.ts","../src/uploader.ts","../src/file-extractor.ts","../src/client.ts"],"sourcesContent":["import type { RateLimitError } from './errors';\n\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 * RateLimitError 钩子函数类型\n * 当检测到计费受限错误时,在抛出异常前调用此钩子\n */\nexport type RateLimitErrorHook = (error: RateLimitError) => void | Promise<void>;\n\n/**\n * 客户端配置选项\n */\nexport interface CapabilityClientOptions {\n /** 全局路径前缀,默认 ''。例如线上环境可设置为 '/spark/a' */\n baseURL?: string;\n /** 获取文件上传预签名 URL 的接口地址,由上层注入 */\n acquireUploadUrl: string;\n /** 获取文件临时下载 URL 的接口地址,由上层注入 */\n acquireDownloadUrl: string;\n /** 自定义 fetch 配置 */\n fetchOptions?: RequestInit;\n /** 自定义 logger,默认使用 console */\n logger?: Logger;\n /**\n * 计费受限错误钩子\n * 当检测到 RateLimitError 时,在抛出异常前调用此钩子\n * 可用于上报埋点、展示 toast 等场景\n */\n onRateLimitError?: RateLimitErrorHook;\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 is_rate_limit_error?: boolean;\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 /** 错误码,计费受限时为业务错误码(如 k_st_ec_400002687) */\n code: string;\n message: string;\n /** 是否为计费受限错误 */\n isRateLimitError?: boolean;\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 RATE_LIMIT_EXCEEDED: 'k_ec_cap_006',\n} as const;\n\n// ========== 文件上传相关类型 ==========\n\n/**\n * 提取的文件信息\n */\nexport interface ExtractedFile {\n /** 在 params 中的路径,如 ['image_list', 0] */\n path: (string | number)[];\n /** 文件对象 */\n file: File | Blob;\n}\n\n/**\n * 上传结果\n */\nexport interface UploadResult {\n /** 在 params 中的路径 */\n path: (string | number)[];\n /** 临时下载 URL */\n downloadUrl: string;\n}\n\n/**\n * 获取上传 URL 响应\n */\nexport interface AcquireUploadUrlResponse {\n status_code: string;\n data: {\n uploadURL: string;\n objectKey: string;\n };\n}\n\n/**\n * 获取下载 URL 响应\n */\nexport interface AcquireDownloadUrlResponse {\n status_code: string;\n data: {\n downloadURL: string;\n };\n}\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\n/**\n * 文件上传错误\n */\nexport class FileUploadError extends CapabilityError {\n constructor(message: string, statusCode?: number) {\n super(message, 'FILE_UPLOAD_ERROR', statusCode);\n this.name = 'FileUploadError';\n }\n}\n\n/**\n * 计费受限错误\n */\nexport class RateLimitError extends CapabilityError {\n /** 业务错误码 */\n rateLimitCode: string;\n /** 业务错误消息 */\n rateLimitMessage: string;\n\n constructor(rateLimitCode: string, rateLimitMessage: string, statusCode?: number) {\n super(rateLimitMessage, 'RATE_LIMIT_EXCEEDED', statusCode);\n this.name = 'RateLimitError';\n this.rateLimitCode = rateLimitCode;\n this.rateLimitMessage = rateLimitMessage;\n }\n}\n","import type {\n CapabilityClientOptions,\n ExtractedFile,\n UploadResult,\n AcquireUploadUrlResponse,\n AcquireDownloadUrlResponse,\n} from './types';\nimport { FileUploadError } from './errors';\nimport { slardar } from '@lark-apaas/internal-slardar';\n\ntype FileUploaderOptions = Pick<CapabilityClientOptions, 'acquireUploadUrl' | 'acquireDownloadUrl' | 'fetchOptions'>;\n\n/**\n * 文件上传器\n */\nexport class FileUploader {\n private readonly options: FileUploaderOptions;\n\n constructor(options: FileUploaderOptions) {\n this.options = options;\n }\n\n /**\n * 上传单个文件,返回下载 URL\n */\n async upload(file: File | Blob): Promise<string> {\n const fileName = file instanceof File ? file.name : `blob-${Date.now()}`;\n\n // 1. 获取上传预签名 URL\n const { uploadURL, objectKey } = await this.fetchUploadUrl(fileName);\n\n // 2. 上传文件到 TOS\n await this.uploadToTos(uploadURL, file);\n\n // 3. 获取下载 URL\n const downloadUrl = await this.fetchDownloadUrl(objectKey);\n\n return downloadUrl;\n }\n\n /**\n * 并发上传多个文件\n */\n async uploadAll(files: ExtractedFile[]): Promise<UploadResult[]> {\n const results = await Promise.all(\n files.map(async ({ path, file }) => {\n const downloadUrl = await this.upload(file);\n return { path, downloadUrl };\n })\n );\n return results;\n }\n\n /**\n * 获取上传预签名 URL\n */\n private async fetchUploadUrl(fileName: string): Promise<{ uploadURL: string; objectKey: string }> {\n const { acquireUploadUrl, fetchOptions } = this.options;\n\n let response: Response;\n try {\n response = await fetch(acquireUploadUrl, {\n method: 'POST',\n ...fetchOptions,\n headers: {\n 'Content-Type': 'application/json',\n ...fetchOptions?.headers,\n },\n body: JSON.stringify({ fileName }),\n });\n } catch (error) {\n slardar.captureException(error, { source: 'client-capability', module: 'file-upload', step: 'fetch-upload-url' });\n throw new FileUploadError(\n `Failed to acquire upload URL: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n\n if (!response.ok) {\n throw new FileUploadError(\n `Failed to acquire upload URL: HTTP ${response.status}`,\n response.status\n );\n }\n\n const data = (await response.json()) as AcquireUploadUrlResponse;\n\n if (data.status_code !== '0') {\n throw new FileUploadError(`Failed to acquire upload URL: ${data.status_code}`);\n }\n\n return data.data;\n }\n\n /**\n * 上传文件到 TOS(预签名 URL)\n */\n private async uploadToTos(uploadURL: string, file: File | Blob): Promise<void> {\n let response: Response;\n try {\n response = await fetch(uploadURL, {\n method: 'PUT',\n body: file,\n });\n } catch (error) {\n slardar.captureException(error, { source: 'client-capability', module: 'file-upload', step: 'upload-to-tos' });\n throw new FileUploadError(\n `Failed to upload file to TOS: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n\n if (!response.ok) {\n throw new FileUploadError(\n `Failed to upload file to TOS: HTTP ${response.status}`,\n response.status\n );\n }\n }\n\n /**\n * 获取临时下载 URL\n */\n private async fetchDownloadUrl(objectKey: string): Promise<string> {\n const { acquireDownloadUrl, fetchOptions } = this.options;\n\n let response: Response;\n try {\n response = await fetch(acquireDownloadUrl, {\n method: 'POST',\n ...fetchOptions,\n headers: {\n 'Content-Type': 'application/json',\n ...fetchOptions?.headers,\n },\n body: JSON.stringify({ objectKey }),\n });\n } catch (error) {\n slardar.captureException(error, { source: 'client-capability', module: 'file-upload', step: 'fetch-download-url' });\n throw new FileUploadError(\n `Failed to acquire download URL: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n\n if (!response.ok) {\n throw new FileUploadError(\n `Failed to acquire download URL: HTTP ${response.status}`,\n response.status\n );\n }\n\n const data = (await response.json()) as AcquireDownloadUrlResponse;\n\n if (data.status_code !== '0') {\n throw new FileUploadError(`Failed to acquire download URL: ${data.status_code}`);\n }\n\n return data.data.downloadURL;\n }\n}\n","import type { ExtractedFile, UploadResult } from './types';\n\n/**\n * 检测是否为 File 或 Blob\n */\nexport function isFile(value: unknown): value is File | Blob {\n return value instanceof File || value instanceof Blob;\n}\n\n/**\n * 递归提取 params 中的所有文件\n *\n * @example\n * extractFiles({ image_list: [file1, file2] })\n * // => [\n * // { path: ['image_list', 0], file: file1 },\n * // { path: ['image_list', 1], file: file2 }\n * // ]\n */\nexport function extractFiles(params: Record<string, unknown>): ExtractedFile[] {\n const files: ExtractedFile[] = [];\n\n function traverse(obj: unknown, path: (string | number)[]): void {\n if (isFile(obj)) {\n files.push({ path: [...path], file: obj });\n } else if (Array.isArray(obj)) {\n obj.forEach((item, index) => traverse(item, [...path, index]));\n } else if (obj !== null && typeof obj === 'object') {\n Object.entries(obj).forEach(([key, value]) => {\n traverse(value, [...path, key]);\n });\n }\n }\n\n traverse(params, []);\n return files;\n}\n\n/**\n * 根据上传结果替换 params 中的文件为 URL\n *\n * @example\n * replaceFilesWithUrls(\n * { image_list: [file1, file2] },\n * [\n * { path: ['image_list', 0], downloadUrl: 'https://...' },\n * { path: ['image_list', 1], downloadUrl: 'https://...' }\n * ]\n * )\n * // => { image_list: ['https://...', 'https://...'] }\n */\nexport function replaceFilesWithUrls(\n params: Record<string, unknown>,\n results: UploadResult[]\n): Record<string, unknown> {\n // 创建 path -> url 的映射,用于快速查找\n const urlMap = new Map<string, string>();\n for (const { path, downloadUrl } of results) {\n urlMap.set(JSON.stringify(path), downloadUrl);\n }\n\n // 手动深拷贝,同时将 File/Blob 替换为对应的 URL\n // 注意:不能使用 structuredClone,因为它不支持 File/Blob 对象\n function cloneAndReplace(obj: unknown, currentPath: (string | number)[]): unknown {\n // 检查当前路径是否有对应的 URL\n const pathKey = JSON.stringify(currentPath);\n if (urlMap.has(pathKey)) {\n return urlMap.get(pathKey);\n }\n\n // 如果是 File/Blob 但没有对应的 URL(不应该发生),返回 null\n if (isFile(obj)) {\n return null;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item, index) => cloneAndReplace(item, [...currentPath, index]));\n }\n\n if (obj !== null && typeof obj === 'object') {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n result[key] = cloneAndReplace(value, [...currentPath, key]);\n }\n return result;\n }\n\n // 原始值直接返回\n return obj;\n }\n\n return cloneAndReplace(params, []) as Record<string, unknown>;\n}\n","import type {\n CapabilityClientOptions,\n CapabilityExecutor,\n ApiResponse,\n ExecuteResponseData,\n StreamResponse,\n Logger,\n RateLimitErrorHook,\n} from './types';\nimport { ErrorCodes } from './types';\nimport {\n CapabilityError,\n CapabilityNotFoundError,\n ActionNotFoundError,\n NetworkError,\n ExecutionError,\n RateLimitError,\n} from './errors';\nimport { FileUploader } from './uploader';\nimport { extractFiles, replaceFilesWithUrls } from './file-extractor';\nimport { slardar } from '@lark-apaas/internal-slardar';\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};\n\n/**\n * 能力客户端\n */\nexport class CapabilityClient {\n private options: CapabilityClientOptions;\n private baseURL: string;\n private logger: Logger;\n private onRateLimitError?: RateLimitErrorHook;\n\n constructor(options: CapabilityClientOptions) {\n this.options = options;\n // 移除末尾的斜杠,确保拼接时格式正确\n this.baseURL = (options?.baseURL ?? '').replace(/\\/+$/, '');\n this.logger = options?.logger ?? defaultLogger;\n this.onRateLimitError = options?.onRateLimitError;\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 let requestParams = params ?? {};\n\n // 处理文件上传\n const extractedFiles = extractFiles(requestParams);\n if (extractedFiles.length > 0) {\n this.logger.info(LOG_PREFIX, `uploading ${extractedFiles.length} file(s)...`);\n const uploader = new FileUploader(this.options);\n const uploadResults = await uploader.uploadAll(extractedFiles);\n requestParams = replaceFilesWithUrls(requestParams, uploadResults);\n this.logger.info(LOG_PREFIX, `file upload completed`);\n }\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 {\n status_code: string;\n error_msg: string;\n is_rate_limit_error?: boolean;\n };\n const errorCode = errorResponse.status_code;\n\n // 计费受限错误:通过 is_rate_limit_error 字段识别\n if (errorResponse.is_rate_limit_error) {\n const rateLimitError = new RateLimitError(\n errorCode, // status_code 就是业务错误码\n errorResponse.error_msg,\n response.status,\n );\n await this.onRateLimitError?.(rateLimitError);\n throw rateLimitError;\n }\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 slardar.captureException(error, { source: 'client-capability', module: 'execute-call', capabilityId, action });\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 let requestParams = params ?? {};\n\n // 处理文件上传\n const extractedFiles = extractFiles(requestParams);\n if (extractedFiles.length > 0) {\n this.logger.info(LOG_PREFIX, `uploading ${extractedFiles.length} file(s)...`);\n const uploader = new FileUploader(this.options);\n const uploadResults = await uploader.uploadAll(extractedFiles);\n requestParams = replaceFilesWithUrls(requestParams, uploadResults);\n this.logger.info(LOG_PREFIX, `file upload completed`);\n }\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 slardar.captureException(error, { source: 'client-capability', module: 'execute-call-stream', capabilityId, action, phase: 'fetch' });\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 const err = parsed.data.error;\n if (err.isRateLimitError) {\n const rateLimitError = new RateLimitError(\n err.code, // code 就是业务错误码\n err.message,\n );\n await this.onRateLimitError?.(rateLimitError);\n throw rateLimitError;\n }\n throw new ExecutionError(err.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 slardar.captureException(error, { source: 'client-capability', module: 'execute-call-stream', capabilityId, action, phase: 'read' });\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"],"mappings":"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","names":["ErrorCodes","SUCCESS","CAPABILITY_NOT_FOUND","PLUGIN_NOT_FOUND","ACTION_NOT_FOUND","PARAMS_VALIDATION_ERROR","EXECUTION_ERROR","RATE_LIMIT_EXCEEDED","CapabilityError","Error","message","code","statusCode","name","CapabilityNotFoundError","capabilityId","ActionNotFoundError","NetworkError","ExecutionError","FileUploadError","RateLimitError","rateLimitCode","rateLimitMessage","slardar","FileUploader","options","upload","file","fileName","File","name","Date","now","uploadURL","objectKey","fetchUploadUrl","uploadToTos","downloadUrl","fetchDownloadUrl","uploadAll","files","results","Promise","all","map","path","acquireUploadUrl","fetchOptions","response","fetch","method","headers","body","JSON","stringify","error","slardar","captureException","source","module","step","FileUploadError","Error","message","String","ok","status","data","json","status_code","acquireDownloadUrl","downloadURL","isFile","value","File","Blob","extractFiles","params","files","traverse","obj","path","push","file","Array","isArray","forEach","item","index","Object","entries","key","replaceFilesWithUrls","results","urlMap","Map","downloadUrl","set","JSON","stringify","cloneAndReplace","currentPath","pathKey","has","get","map","result","slardar","LOG_PREFIX","defaultLogger","debug","console","bind","info","warn","error","CapabilityClient","options","baseURL","logger","onRateLimitError","replace","load","capabilityId","createExecutor","call","action","params","executeCall","callStream","executeCallStream","url","requestParams","extractedFiles","extractFiles","length","uploader","FileUploader","uploadResults","uploadAll","replaceFilesWithUrls","response","fetch","method","fetchOptions","headers","body","JSON","stringify","data","json","ok","status_code","ErrorCodes","SUCCESS","errorResponse","errorCode","is_rate_limit_error","rateLimitError","RateLimitError","error_msg","status","CAPABILITY_NOT_FOUND","CapabilityNotFoundError","ACTION_NOT_FOUND","ActionNotFoundError","PLUGIN_NOT_FOUND","EXECUTION_ERROR","ExecutionError","result","output","slardar","captureException","source","module","CapabilityError","NetworkError","Error","message","String","phase","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","err","isRateLimitError","code","parseError","releaseLock","createClient"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/client-capability",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "Client SDK for calling capabilities",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -35,9 +35,12 @@
35
35
  "lint": "echo 'ESLint skipped'",
36
36
  "prepublishOnly": "npm run build"
37
37
  },
38
+ "dependencies": {
39
+ "@lark-apaas/internal-slardar": "^0.0.3"
40
+ },
38
41
  "devDependencies": {
39
42
  "tsup": "^8.0.0",
40
43
  "typescript": "^5.0.0",
41
- "vitest": "^1.6.0"
44
+ "vitest": "^3.2.4"
42
45
  }
43
46
  }