@howone/sdk 0.3.10 → 0.3.11

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,154 @@ 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.url || response.storageUrl,
2544
+ thumbnailUrl: response.thumbnailUrl,
2545
+ id: response.id,
2546
+ size: response.size,
2547
+ mimeType: response.mimeType || response.contentType
2548
+ };
2549
+ },
2550
+ /**
2551
+ * 上传图片(快捷方法,专为 AI 设计)
2552
+ *
2553
+ * @example
2554
+ * ```typescript
2555
+ * const { url } = await client.upload.image(imageFile)
2556
+ * ```
2557
+ */
2558
+ async image(file) {
2559
+ const result = await this.file(file);
2560
+ return { url: result.url };
2561
+ },
2562
+ /**
2563
+ * 批量上传文件
2564
+ *
2565
+ * @example
2566
+ * ```typescript
2567
+ * const result = await client.upload.batch({
2568
+ * files: [file1, file2, file3],
2569
+ * concurrent: 3,
2570
+ * onProgress: (completed, total) => {
2571
+ * console.log(`${completed}/${total}`)
2572
+ * }
2573
+ * })
2574
+ * ```
2575
+ */
2576
+ async batch(options) {
2577
+ const { files, concurrent = 3, onProgress, onFileComplete, signal } = options;
2578
+ const success = [];
2579
+ const failed = [];
2580
+ let completed = 0;
2581
+ for (let i = 0; i < files.length; i += concurrent) {
2582
+ if (signal?.aborted) break;
2583
+ const batch = files.slice(i, Math.min(i + concurrent, files.length));
2584
+ const promises = batch.map(async (file, batchIndex) => {
2585
+ const globalIndex = i + batchIndex;
2586
+ try {
2587
+ const result = await this.file(file, { signal });
2588
+ success.push(result);
2589
+ if (onFileComplete) {
2590
+ onFileComplete(result, globalIndex);
2591
+ }
2592
+ } catch (error) {
2593
+ const errorMsg = error instanceof Error ? error.message : String(error);
2594
+ failed.push({ index: globalIndex, error: errorMsg });
2595
+ if (onFileComplete) {
2596
+ onFileComplete(
2597
+ error instanceof Error ? error : new Error(errorMsg),
2598
+ globalIndex
2599
+ );
2600
+ }
2601
+ } finally {
2602
+ completed++;
2603
+ if (onProgress) {
2604
+ onProgress(completed, files.length);
2605
+ }
2606
+ }
2607
+ });
2608
+ await Promise.all(promises);
2609
+ }
2610
+ return {
2611
+ success,
2612
+ failed,
2613
+ total: files.length
2614
+ };
2615
+ }
2616
+ };
2617
+ }
2618
+
2619
+ // src/services/ai-client.ts
2620
+ function createAIClient(req, projectId) {
2621
+ const generateImageUrl = projectId ? `/entities/apps/${projectId}/generate-image` : "/generate-image";
2622
+ return {
2623
+ /**
2624
+ * 生成/修改图片
2625
+ *
2626
+ * @example
2627
+ * ```typescript
2628
+ * const result = await client.ai.generateImage({
2629
+ * imageUrl: 'https://example.com/image.jpg',
2630
+ * description: '把天空改成蓝色'
2631
+ * })
2632
+ * console.log('新图片:', result.imageUrl)
2633
+ * ```
2634
+ */
2635
+ async generateImage(options) {
2636
+ const { imageUrl, description, signal } = options;
2637
+ const response = await req.post({
2638
+ url: generateImageUrl,
2639
+ data: {
2640
+ imageUrl,
2641
+ description
2642
+ },
2643
+ signal
2644
+ });
2645
+ return {
2646
+ imageUrl: response.imageUrl || response.url,
2647
+ taskId: response.taskId || response.id,
2648
+ metadata: response.metadata
2649
+ };
2650
+ }
2651
+ };
2652
+ }
2653
+
2492
2654
  // src/services/sse-executor.ts
2493
2655
  init_config();
2494
2656
  async function executeSSEWorkflow(request, options = {}) {
@@ -3562,6 +3724,41 @@ function createClient(opts) {
3562
3724
  workflowExecutor: workflowExecutorFactory,
3563
3725
  // artifact helpers using artifacts-client
3564
3726
  artifacts: createArtifactsClient(biz),
3727
+ /**
3728
+ * 文件上传模块(独立,不依赖 artifact)
3729
+ *
3730
+ * @example
3731
+ * ```typescript
3732
+ * // 最简单的用法
3733
+ * const { url } = await client.upload.file(imageFile)
3734
+ * console.log('文件地址:', url)
3735
+ *
3736
+ * // AI 友好版本(只返回 url)
3737
+ * const { url } = await client.upload.image(imageFile)
3738
+ *
3739
+ * // 批量上传
3740
+ * const result = await client.upload.batch({
3741
+ * files: [file1, file2, file3],
3742
+ * concurrent: 3,
3743
+ * onProgress: (completed, total) => console.log(`${completed}/${total}`)
3744
+ * })
3745
+ * ```
3746
+ */
3747
+ upload: createUploadClient(bizWrapped, opts?.projectId),
3748
+ /**
3749
+ * AI 功能模块
3750
+ *
3751
+ * @example
3752
+ * ```typescript
3753
+ * // 图片生成/修改
3754
+ * const result = await client.ai.generateImage({
3755
+ * imageUrl: 'https://example.com/image.jpg',
3756
+ * description: '把天空改成蓝色'
3757
+ * })
3758
+ * console.log('新图片:', result.imageUrl)
3759
+ * ```
3760
+ */
3761
+ ai: createAIClient(bizWrapped, opts?.projectId),
3565
3762
  me: async () => {
3566
3763
  try {
3567
3764
  let availableToken = getCachedOrGlobalToken();
@@ -4066,12 +4263,14 @@ var elementSelector = {
4066
4263
  ThemeToggle,
4067
4264
  aiWorkflow,
4068
4265
  canAccessArtifact,
4266
+ createAIClient,
4069
4267
  createAIWorkflowClient,
4070
4268
  createAIWorkflowClientAxios,
4071
4269
  createArtifactsClient,
4072
4270
  createClient,
4073
4271
  createSSEClient,
4074
4272
  createSSERequest,
4273
+ createUploadClient,
4075
4274
  elementSelector,
4076
4275
  executeSSEWorkflow,
4077
4276
  getCodeStatus,