@qjp88995/provider-client 0.3.0 → 0.4.0

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.
Files changed (40) hide show
  1. package/dist/direct-resolver.d.ts.map +1 -1
  2. package/dist/direct-resolver.js +2 -0
  3. package/dist/direct-resolver.js.map +1 -1
  4. package/dist/image/http.d.ts +16 -0
  5. package/dist/image/http.d.ts.map +1 -0
  6. package/dist/image/http.js +62 -0
  7. package/dist/image/http.js.map +1 -0
  8. package/dist/image/index.d.ts +32 -0
  9. package/dist/image/index.d.ts.map +1 -0
  10. package/dist/image/index.js +39 -0
  11. package/dist/image/index.js.map +1 -0
  12. package/dist/image/types.d.ts +94 -0
  13. package/dist/image/types.d.ts.map +1 -0
  14. package/dist/image/types.js +44 -0
  15. package/dist/image/types.js.map +1 -0
  16. package/dist/image/volcengine.adapter.d.ts +8 -0
  17. package/dist/image/volcengine.adapter.d.ts.map +1 -0
  18. package/dist/image/volcengine.adapter.js +85 -0
  19. package/dist/image/volcengine.adapter.js.map +1 -0
  20. package/dist/index.d.ts +3 -2
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +2 -1
  23. package/dist/index.js.map +1 -1
  24. package/dist/provider-client.d.ts +13 -0
  25. package/dist/provider-client.d.ts.map +1 -1
  26. package/dist/provider-client.js +47 -0
  27. package/dist/provider-client.js.map +1 -1
  28. package/dist/types.d.ts +18 -0
  29. package/dist/types.d.ts.map +1 -1
  30. package/dist/types.js +2 -0
  31. package/dist/types.js.map +1 -1
  32. package/package.json +1 -1
  33. package/src/direct-resolver.ts +2 -0
  34. package/src/image/http.ts +68 -0
  35. package/src/image/index.ts +87 -0
  36. package/src/image/types.ts +134 -0
  37. package/src/image/volcengine.adapter.ts +133 -0
  38. package/src/index.ts +27 -0
  39. package/src/provider-client.ts +77 -2
  40. package/src/types.ts +21 -0
package/src/index.ts CHANGED
@@ -9,6 +9,28 @@ export {
9
9
  ProviderClientError,
10
10
  type ProviderClientErrorCode,
11
11
  } from './errors.js';
12
+ export {
13
+ createImageGenerator,
14
+ type CreateImageGeneratorInput,
15
+ fitImageSize,
16
+ type GeneratedImage,
17
+ type GenerateImageInput,
18
+ type GenerateImageOutcome,
19
+ IMAGE_ADAPTERS,
20
+ IMAGE_FORMATS,
21
+ IMAGE_KINDS,
22
+ type ImageAdapter,
23
+ type ImageConnection,
24
+ type ImageFormat,
25
+ type ImageGenerator,
26
+ type ImageKind,
27
+ type ImageSize,
28
+ type ImageTraits,
29
+ ImageUpstreamError,
30
+ type ImageUsage,
31
+ isImageKind,
32
+ type ReferenceImage,
33
+ } from './image/index.js';
12
34
  export {
13
35
  classifyCode,
14
36
  createJustOne,
@@ -88,6 +110,7 @@ export {
88
110
  } from './model-handle.js';
89
111
  export {
90
112
  type FetchForOptions,
113
+ type ImageModelOptions,
91
114
  type JustOneClientOptions,
92
115
  type MediaOptions,
93
116
  ProviderClient,
@@ -97,6 +120,7 @@ export {
97
120
  export { toProviderClientError } from './to-error.js';
98
121
  export {
99
122
  type CatalogEndpoint,
123
+ type CatalogImageModel,
100
124
  type CatalogModel,
101
125
  type CatalogResponse,
102
126
  type CatalogVendor,
@@ -104,6 +128,9 @@ export {
104
128
  type CenterErrorCode,
105
129
  ENDPOINT_PROTOCOLS,
106
130
  type EndpointProtocol,
131
+ IMAGE_CAPABILITIES,
132
+ type ImageCapability,
133
+ type ImagePricing,
107
134
  LLM_CAPABILITIES,
108
135
  LLM_PROTOCOLS,
109
136
  type LlmCapability,
@@ -1,5 +1,11 @@
1
1
  import { type CenterFetchOptions, createCenterFetch } from './center-fetch.js';
2
2
  import { errorFromResponse, ProviderClientError } from './errors.js';
3
+ import {
4
+ createImageGenerator,
5
+ IMAGE_ADAPTERS,
6
+ type ImageGenerator,
7
+ isImageKind,
8
+ } from './image/index.js';
3
9
  import {
4
10
  createJustOne,
5
11
  type JustOne,
@@ -51,8 +57,7 @@ export interface MediaOptions<
51
57
 
52
58
  /** `ProviderClient.justOne` 的选项。 */
53
59
  export interface JustOneClientOptions<C = unknown>
54
- extends FetchForOptions,
55
- Pick<JustOneOptions<C>, 'onAttempt'> {}
60
+ extends FetchForOptions, Pick<JustOneOptions<C>, 'onAttempt'> {}
56
61
 
57
62
  /** `ProviderClient.fetchFor` 的选项。 */
58
63
  export interface FetchForOptions {
@@ -64,6 +69,9 @@ export interface FetchForOptions {
64
69
  onCredential?: (ref: string) => void;
65
70
  }
66
71
 
72
+ /** `ProviderClient.imageModel` 的选项。 */
73
+ export type ImageModelOptions = FetchForOptions;
74
+
67
75
  export interface ProviderClientOptions {
68
76
  /** 中心的根地址,如 `https://provider.example.com`。 */
69
77
  centerUrl: string;
@@ -229,6 +237,71 @@ export class ProviderClient implements ModelResolver {
229
237
  });
230
238
  }
231
239
 
240
+ /**
241
+ * 一个生图模型(适配器在本包,请求经中心透传、中心注入 key)。地址取自这家的对话端点(生图模型没有自己的协议,
242
+ * 用哪个端点由这家的生图适配器定)。**一次 `generate` 出一张**;要几张就并发几次。
243
+ * - 目录里没有这家 → `unknown_vendor`;这家没有这个生图模型(或停用了)→ `unknown_model`;
244
+ * 这个版本的 client 没有这家的生图适配器 → `unsupported_vendor_kind`;这家没有启用的对应端点 → `protocol_unavailable`。
245
+ * - 生成时中心自己报的错是 `ProviderClientError`,厂商的失败是 `ImageUpstreamError`(`retryable`、`contentFiltered`)。
246
+ * - 用量(张数、参考图数)在结果里,单价在目录里(`catalog()` 的 `imageModels[].pricing`),钱由 APP 自己算。
247
+ * 目录只在创建时查一次。
248
+ */
249
+ async imageModel(
250
+ ref: ModelRef,
251
+ options: ImageModelOptions = {}
252
+ ): Promise<ImageGenerator> {
253
+ const vendor = (await this.catalog()).vendors.find(
254
+ v => v.slug === ref.vendor
255
+ );
256
+ if (!vendor) {
257
+ throw new ProviderClientError(
258
+ 'unknown_vendor',
259
+ `vendor "${ref.vendor}" is not in the catalog`,
260
+ null
261
+ );
262
+ }
263
+ const model = vendor.imageModels.find(m => m.modelId === ref.modelId);
264
+ if (!model) {
265
+ throw new ProviderClientError(
266
+ 'unknown_model',
267
+ `image model "${ref.modelId}" is not in the catalog of vendor "${ref.vendor}"`,
268
+ null
269
+ );
270
+ }
271
+ if (!isImageKind(vendor.kind)) {
272
+ throw new ProviderClientError(
273
+ 'unsupported_vendor_kind',
274
+ `vendor kind "${vendor.kind}" has no image generation adapter`,
275
+ null
276
+ );
277
+ }
278
+ const protocol = IMAGE_ADAPTERS[vendor.kind].endpointProtocol;
279
+ const endpoint = vendor.endpoints.find(e => e.protocol === protocol);
280
+ if (!endpoint) {
281
+ throw new ProviderClientError(
282
+ 'protocol_unavailable',
283
+ `vendor "${ref.vendor}" has no ${protocol} endpoint (image generation uses its base URL)`,
284
+ null
285
+ );
286
+ }
287
+ const fetch = createCenterFetch({
288
+ centerUrl: this.center,
289
+ apiKey: this.options.apiKey,
290
+ vendor: vendor.slug,
291
+ baseUrls: vendor.endpoints.map(e => e.baseUrl),
292
+ affinity: options.affinity,
293
+ pin: options.pin,
294
+ onCredential: options.onCredential,
295
+ fetch: this.send,
296
+ });
297
+ return createImageGenerator({
298
+ kind: vendor.kind,
299
+ modelId: model.modelId,
300
+ referenceImages: model.capabilities.includes('reference-image'),
301
+ connection: { baseUrl: endpoint.baseUrl, fetch },
302
+ });
303
+ }
304
+
232
305
  /**
233
306
  * 某家厂商的媒体解析(适配器在本包,请求经中心透传、中心注入 key):智谱的文件解析 / 语音转写(地址取自这家的
234
307
  * `media` 端点)、BibiGPT 的视频链接解析(它唯一的 `http` 端点)。
@@ -372,6 +445,8 @@ export class ProviderClient implements ModelResolver {
372
445
  }
373
446
  if (!res.ok) throw await errorFromResponse(res);
374
447
  const body = (await res.json()) as CatalogResponse;
448
+ // 中心 2026-11 之前没有 `imageModels`:补成空数组,后面不用到处判空。
449
+ for (const v of body.vendors) v.imageModels ??= [];
375
450
  this.cached = {
376
451
  etag: res.headers.get('etag'),
377
452
  body,
package/src/types.ts CHANGED
@@ -33,6 +33,10 @@ export type VendorCategory = (typeof VENDOR_CATEGORIES)[number];
33
33
  export const LLM_CAPABILITIES = ['vision', 'video', 'reasoning'] as const;
34
34
  export type LlmCapability = (typeof LLM_CAPABILITIES)[number];
35
35
 
36
+ /** 生图模型的能力。`reference-image` = 能带参考图(图生图 / 改图)。 */
37
+ export const IMAGE_CAPABILITIES = ['reference-image'] as const;
38
+ export type ImageCapability = (typeof IMAGE_CAPABILITIES)[number];
39
+
36
40
  /** 厂商类型。`llm` 类别的每一种对应一个适配器(`VENDOR_ADAPTERS`);bibigpt / justone 没有。 */
37
41
  export const VENDOR_KINDS = [
38
42
  'openai',
@@ -91,7 +95,10 @@ export interface CatalogVendor {
91
95
  /** 非 `llm` 的厂商没有模型,接入方只拿它的端点经中心透传。 */
92
96
  category: VendorCategory;
93
97
  endpoints: CatalogEndpoint[];
98
+ /** 对话模型。 */
94
99
  models: CatalogModel[];
100
+ /** 生图模型(中心 2026-11 起有;读目录时缺了按空数组补上)。 */
101
+ imageModels: CatalogImageModel[];
95
102
  }
96
103
 
97
104
  export interface CatalogEndpoint {
@@ -111,6 +118,20 @@ export interface CatalogModel {
111
118
  pricing: ModelPricing | null;
112
119
  }
113
120
 
121
+ /** 生图的单价(每张,十进制字符串)。 */
122
+ export interface ImagePricing {
123
+ currency: string;
124
+ perImage: string;
125
+ }
126
+
127
+ export interface CatalogImageModel {
128
+ /** 厂商侧的模型名(请求体里的 `model`)。 */
129
+ modelId: string;
130
+ displayName: string;
131
+ capabilities: ImageCapability[];
132
+ pricing: ImagePricing | null;
133
+ }
134
+
114
135
  /** 中心的错误码(响应体 `{ code, message }`)。 */
115
136
  export const CENTER_ERROR_CODES = [
116
137
  'unauthorized',