@howone/sdk 0.3.10 → 0.3.12

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.js CHANGED
@@ -289,12 +289,14 @@ __export(index_exports, {
289
289
  ThemeToggle: () => ThemeToggle,
290
290
  aiWorkflow: () => aiWorkflow,
291
291
  canAccessArtifact: () => canAccessArtifact,
292
+ createAIClient: () => createAIClient,
292
293
  createAIWorkflowClient: () => createAIWorkflowClient,
293
294
  createAIWorkflowClientAxios: () => createAIWorkflowClientAxios,
294
295
  createArtifactsClient: () => createArtifactsClient,
295
296
  createClient: () => createClient,
296
297
  createSSEClient: () => createSSEClient,
297
298
  createSSERequest: () => createSSERequest,
299
+ createUploadClient: () => createUploadClient,
298
300
  elementSelector: () => elementSelector,
299
301
  executeSSEWorkflow: () => executeSSEWorkflow,
300
302
  getCodeStatus: () => getCodeStatus,
@@ -2029,18 +2031,30 @@ var ToastContent = ({ type, title, message, component, closeToast }) => {
2029
2031
  }
2030
2032
  }
2031
2033
  ),
2032
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex-shrink-0 mt-0.5 relative z-10", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: `w-7 h-7 backdrop-blur-sm rounded-full flex items-center justify-center ${theme === "dark" || theme === "system" && window.matchMedia("(prefers-color-scheme: dark)").matches ? "bg-white/10" : "bg-black/5"}`, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2033
- import_react12.Icon,
2034
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex-shrink-0 flex-grow-0 mt-0.5 relative z-10", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2035
+ "div",
2034
2036
  {
2035
- icon: iconConfig.icon,
2036
- width: 16,
2037
- height: 16,
2038
- className: iconConfig.color,
2037
+ className: "backdrop-blur-sm rounded-full flex items-center justify-center overflow-hidden flex-shrink-0 flex-grow-0",
2039
2038
  style: {
2040
- color: themeConfig.gradientColor
2041
- }
2039
+ backgroundColor: theme === "dark" || theme === "system" && window.matchMedia("(prefers-color-scheme: dark)").matches ? "rgba(255, 255, 255, 0.1)" : "rgba(0, 0, 0, 0.05)",
2040
+ width: "28px",
2041
+ height: "28px"
2042
+ },
2043
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "rounded-full flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2044
+ import_react12.Icon,
2045
+ {
2046
+ icon: iconConfig.icon,
2047
+ width: 16,
2048
+ height: 16,
2049
+ className: `flex-shrink-0`,
2050
+ style: {
2051
+ color: themeConfig.gradientColor,
2052
+ display: "block"
2053
+ }
2054
+ }
2055
+ ) })
2042
2056
  }
2043
- ) }) }),
2057
+ ) }),
2044
2058
  /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex flex-col gap-1 flex-1 relative z-10", children: [
2045
2059
  title && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2046
2060
  "div",
@@ -2489,6 +2503,150 @@ function createArtifactsClient(req) {
2489
2503
  };
2490
2504
  }
2491
2505
 
2506
+ // src/services/upload-client.ts
2507
+ function createUploadClient(req, projectId) {
2508
+ const uploadUrl = projectId ? `/entities/apps/${projectId}/files` : "/files";
2509
+ return {
2510
+ /**
2511
+ * 上传单个文件
2512
+ *
2513
+ * @example
2514
+ * ```typescript
2515
+ * const { url } = await client.upload.file(imageFile)
2516
+ * console.log('文件地址:', url)
2517
+ * ```
2518
+ */
2519
+ async file(file, options) {
2520
+ const formData = new FormData();
2521
+ if (typeof file === "string") {
2522
+ if (file.startsWith("data:")) {
2523
+ const response2 = await fetch(file);
2524
+ const blob = await response2.blob();
2525
+ formData.append("file", blob, "upload.bin");
2526
+ } else {
2527
+ formData.append("fileUrl", file);
2528
+ }
2529
+ } else if (file instanceof File) {
2530
+ formData.append("file", file, file.name);
2531
+ } else {
2532
+ formData.append("file", file, "upload.bin");
2533
+ }
2534
+ if (options?.metadata) {
2535
+ formData.append("metadata", JSON.stringify(options.metadata));
2536
+ }
2537
+ const response = await req.post({
2538
+ url: uploadUrl,
2539
+ data: formData,
2540
+ signal: options?.signal
2541
+ });
2542
+ return {
2543
+ url: response.data.publicUrl
2544
+ };
2545
+ },
2546
+ /**
2547
+ * 上传图片(快捷方法,专为 AI 设计)
2548
+ *
2549
+ * @example
2550
+ * ```typescript
2551
+ * const { url } = await client.upload.image(imageFile)
2552
+ * ```
2553
+ */
2554
+ async image(file) {
2555
+ const result = await this.file(file);
2556
+ return { url: result.url };
2557
+ },
2558
+ /**
2559
+ * 批量上传文件
2560
+ *
2561
+ * @example
2562
+ * ```typescript
2563
+ * const result = await client.upload.batch({
2564
+ * files: [file1, file2, file3],
2565
+ * concurrent: 3,
2566
+ * onProgress: (completed, total) => {
2567
+ * console.log(`${completed}/${total}`)
2568
+ * }
2569
+ * })
2570
+ * ```
2571
+ */
2572
+ async batch(options) {
2573
+ const { files, concurrent = 3, onProgress, onFileComplete, signal } = options;
2574
+ const success = [];
2575
+ const failed = [];
2576
+ let completed = 0;
2577
+ for (let i = 0; i < files.length; i += concurrent) {
2578
+ if (signal?.aborted) break;
2579
+ const batch = files.slice(i, Math.min(i + concurrent, files.length));
2580
+ const promises = batch.map(async (file, batchIndex) => {
2581
+ const globalIndex = i + batchIndex;
2582
+ try {
2583
+ const result = await this.file(file, { signal });
2584
+ success.push(result);
2585
+ if (onFileComplete) {
2586
+ onFileComplete(result, globalIndex);
2587
+ }
2588
+ } catch (error) {
2589
+ const errorMsg = error instanceof Error ? error.message : String(error);
2590
+ failed.push({ index: globalIndex, error: errorMsg });
2591
+ if (onFileComplete) {
2592
+ onFileComplete(
2593
+ error instanceof Error ? error : new Error(errorMsg),
2594
+ globalIndex
2595
+ );
2596
+ }
2597
+ } finally {
2598
+ completed++;
2599
+ if (onProgress) {
2600
+ onProgress(completed, files.length);
2601
+ }
2602
+ }
2603
+ });
2604
+ await Promise.all(promises);
2605
+ }
2606
+ return {
2607
+ success,
2608
+ failed,
2609
+ total: files.length
2610
+ };
2611
+ }
2612
+ };
2613
+ }
2614
+
2615
+ // src/services/ai-client.ts
2616
+ function createAIClient(req, projectId) {
2617
+ const generateImageUrl = projectId ? `/entities/apps/${projectId}/generate-image` : "/generate-image";
2618
+ return {
2619
+ /**
2620
+ * 生成/修改图片
2621
+ *
2622
+ * @example
2623
+ * ```typescript
2624
+ * const result = await client.ai.generateImage({
2625
+ * imageUrl: 'https://example.com/image.jpg',
2626
+ * description: '把天空改成蓝色'
2627
+ * })
2628
+ * console.log('新图片:', result.imageUrl)
2629
+ * ```
2630
+ */
2631
+ async generateImage(options) {
2632
+ const { imageUrl, description, signal } = options;
2633
+ const response = await req.post({
2634
+ url: generateImageUrl,
2635
+ data: {
2636
+ imageUrl,
2637
+ description
2638
+ },
2639
+ signal
2640
+ });
2641
+ return {
2642
+ imageUrl: response.imageUrl || response.url,
2643
+ taskId: response.taskId || response.id,
2644
+ metadata: response.metadata
2645
+ };
2646
+ }
2647
+ };
2648
+ }
2649
+
2492
2650
  // src/services/sse-executor.ts
2493
2651
  init_config();
2494
2652
  async function executeSSEWorkflow(request, options = {}) {
@@ -3562,6 +3720,41 @@ function createClient(opts) {
3562
3720
  workflowExecutor: workflowExecutorFactory,
3563
3721
  // artifact helpers using artifacts-client
3564
3722
  artifacts: createArtifactsClient(biz),
3723
+ /**
3724
+ * 文件上传模块(独立,不依赖 artifact)
3725
+ *
3726
+ * @example
3727
+ * ```typescript
3728
+ * // 最简单的用法
3729
+ * const { url } = await client.upload.file(imageFile)
3730
+ * console.log('文件地址:', url)
3731
+ *
3732
+ * // AI 友好版本(只返回 url)
3733
+ * const { url } = await client.upload.image(imageFile)
3734
+ *
3735
+ * // 批量上传
3736
+ * const result = await client.upload.batch({
3737
+ * files: [file1, file2, file3],
3738
+ * concurrent: 3,
3739
+ * onProgress: (completed, total) => console.log(`${completed}/${total}`)
3740
+ * })
3741
+ * ```
3742
+ */
3743
+ upload: createUploadClient(bizWrapped, opts?.projectId),
3744
+ /**
3745
+ * AI 功能模块
3746
+ *
3747
+ * @example
3748
+ * ```typescript
3749
+ * // 图片生成/修改
3750
+ * const result = await client.ai.generateImage({
3751
+ * imageUrl: 'https://example.com/image.jpg',
3752
+ * description: '把天空改成蓝色'
3753
+ * })
3754
+ * console.log('新图片:', result.imageUrl)
3755
+ * ```
3756
+ */
3757
+ ai: createAIClient(bizWrapped, opts?.projectId),
3565
3758
  me: async () => {
3566
3759
  try {
3567
3760
  let availableToken = getCachedOrGlobalToken();
@@ -4066,12 +4259,14 @@ var elementSelector = {
4066
4259
  ThemeToggle,
4067
4260
  aiWorkflow,
4068
4261
  canAccessArtifact,
4262
+ createAIClient,
4069
4263
  createAIWorkflowClient,
4070
4264
  createAIWorkflowClientAxios,
4071
4265
  createArtifactsClient,
4072
4266
  createClient,
4073
4267
  createSSEClient,
4074
4268
  createSSERequest,
4269
+ createUploadClient,
4075
4270
  elementSelector,
4076
4271
  executeSSEWorkflow,
4077
4272
  getCodeStatus,