@tencent-ai/workbuddy-cloud-sdk 0.1.0-dev.dee063d.202608201621 → 0.1.1-dev.520de95.202609090209

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/README.md ADDED
@@ -0,0 +1,28 @@
1
+ # WorkBuddy Cloud SDK
2
+
3
+ 通过 WorkBuddy 云服务的 `publicConfig` 访问 Auth、Database、Storage 和 LLM。
4
+
5
+ ## 微信小程序
6
+
7
+ 在小程序项目的 `package.json` 所在目录安装依赖:
8
+
9
+ ```sh
10
+ npm install @tencent-ai/workbuddy-cloud-sdk@dev
11
+ ```
12
+
13
+ 然后在微信开发者工具中执行「工具 → 构建 npm」,确认生成
14
+ `miniprogram_npm/@tencent-ai/workbuddy-cloud-sdk/miniprogram.js`,再点击「编译」。
15
+ 仅写入 `package.json` 不会安装依赖;升级 SDK 后也需要重新构建 npm。
16
+
17
+ ```js
18
+ const { createMiniProgramWorkBuddyCloud } = require('@tencent-ai/workbuddy-cloud-sdk/miniprogram');
19
+
20
+ const cloud = createMiniProgramWorkBuddyCloud({
21
+ endpoint: publicConfig.endpoint,
22
+ publishableKey: publicConfig.publishableKey,
23
+ });
24
+ ```
25
+
26
+ SDK 通过 `package.json#miniprogram` 提供微信专用的 CommonJS `.js` 产物,
27
+ 其中已打包运行时依赖。现有 Web / Node 的根入口和 `/miniprogram` 子入口保持不变。
28
+ WorkBuddy H5 预览会注入 SDK,预览成功不能替代微信项目的安装、构建 npm 验证。
package/lib/index.cjs CHANGED
@@ -39,6 +39,8 @@ __export(index_exports, {
39
39
  anonymousTokenProvider: () => anonymousTokenProvider,
40
40
  createMemoryStorage: () => createMemoryStorage,
41
41
  createWorkBuddyCloud: () => createWorkBuddyCloud,
42
+ getModelCapability: () => getModelCapability,
43
+ getModelDisplayName: () => getModelDisplayName,
42
44
  shouldClearCredentials: () => shouldClearCredentials
43
45
  });
44
46
  module.exports = __toCommonJS(index_exports);
@@ -73,6 +75,17 @@ function normalizeHttpUrl(value, field) {
73
75
  return trimmed.replace(/\/+$/, "");
74
76
  }
75
77
  __name(normalizeHttpUrl, "normalizeHttpUrl");
78
+ function resolveEndpoint(value) {
79
+ if (value !== void 0 && value !== null && value !== "") {
80
+ return normalizeHttpUrl(value, "endpoint");
81
+ }
82
+ const origin = globalThis.location?.origin;
83
+ if (typeof origin !== "string" || origin === "") {
84
+ throw new WorkBuddyCloudConfigError("endpoint is required outside browsers (no location.origin to fall back to).");
85
+ }
86
+ return origin.replace(/\/+$/, "");
87
+ }
88
+ __name(resolveEndpoint, "resolveEndpoint");
76
89
  function normalizePublishableKey(publishableKey) {
77
90
  if (typeof publishableKey !== "string" || publishableKey.trim() === "") {
78
91
  throw new WorkBuddyCloudConfigError("publishableKey is required and must be a non-empty string.");
@@ -96,11 +109,11 @@ function resolveFetch(candidate) {
96
109
  __name(resolveFetch, "resolveFetch");
97
110
  function resolveRuntimeConfig(options) {
98
111
  if (!options || typeof options !== "object") {
99
- throw new WorkBuddyCloudConfigError("createWorkBuddyCloud requires endpoint, oauthRelayBaseUrl and publishableKey.");
112
+ throw new WorkBuddyCloudConfigError("createWorkBuddyCloud requires publishableKey.");
100
113
  }
101
114
  return Object.freeze({
102
- endpoint: normalizeHttpUrl(options.endpoint, "endpoint"),
103
- oauthRelayBaseUrl: normalizeHttpUrl(options.oauthRelayBaseUrl, "oauthRelayBaseUrl"),
115
+ endpoint: resolveEndpoint(options.endpoint),
116
+ oauthRelayBaseUrl: options.oauthRelayBaseUrl ? normalizeHttpUrl(options.oauthRelayBaseUrl, "oauthRelayBaseUrl") : "",
104
117
  publishableKey: normalizePublishableKey(options.publishableKey),
105
118
  fetch: resolveFetch(options.fetch)
106
119
  });
@@ -144,6 +157,8 @@ var AUTH_PATHS = {
144
157
  signInWithProvider: "/v1/signin/with/provider",
145
158
  /** 本地续期端点(服务端不转发上游)。 */
146
159
  token: "/v1/token",
160
+ /** 小程序微信登录:本地认人后仍需用 custom 票据换取 TCB session。 */
161
+ loginWechat: "/v1/login-wechat",
147
162
  signOut: "/v1/user/signout",
148
163
  userMe: "/v1/user/me",
149
164
  /** 发码。 */
@@ -569,15 +584,34 @@ var AuthModule = class {
569
584
  password: credentials.password
570
585
  });
571
586
  }
587
+ /**
588
+ * 小程序 wx.login 的 code 换 Genie session。
589
+ * 试用与正式是两套独立小程序,必须带当前账号的 appid
590
+ *(`wx.getAccountInfoSync().miniProgram.appId`)。
591
+ */
592
+ async signInWithWechat(code, appid) {
593
+ if (!code) {
594
+ return fail(badRequest("signInWithWechat requires code"));
595
+ }
596
+ if (!appid) {
597
+ return fail(badRequest("signInWithWechat requires appid"));
598
+ }
599
+ return this.postForSession(AUTH_PATHS.loginWechat, {
600
+ code,
601
+ appid
602
+ });
603
+ }
572
604
  /**
573
605
  * 注册。
574
606
  *
575
607
  * 上游要求先完成验证码验证,所以必须带一个 `verificationToken`(来自
576
608
  * `verifyOtp`)。只有用户名+密码的注册会被上游明确拒绝。
609
+ *
610
+ * 账号标识用 `email` 或 `phone`(二选一,与发码渠道一致)。
577
611
  */
578
612
  async signUp(credentials) {
579
- if (!credentials.email) {
580
- return fail(badRequest("signUp requires email"));
613
+ if (!credentials.email && !credentials.phone) {
614
+ return fail(badRequest("signUp requires email or phone"));
581
615
  }
582
616
  if (!credentials.verificationToken) {
583
617
  return fail(badRequest("signUp requires a verificationToken; run sendOtp + verifyOtp first (the provider rejects username+password-only signup)"));
@@ -585,28 +619,40 @@ var AuthModule = class {
585
619
  const body = {
586
620
  verification_token: credentials.verificationToken
587
621
  };
588
- body.email = credentials.email;
622
+ if (credentials.phone) body.phone_number = normalizePhone(credentials.phone);
623
+ if (credentials.email) body.email = credentials.email;
589
624
  if (credentials.password) body.password = credentials.password;
590
625
  return this.postForSession(AUTH_PATHS.signUp, body);
591
626
  }
592
627
  /**
593
- * 发邮箱验证码。
628
+ * 发验证码(邮箱或短信,由 `credentials` 传的字段决定)。
594
629
  *
595
630
  * 这一步**不产生会话**,只返回一个 `verificationId`。发码由上游完成,
596
631
  * 我方不实现发码逻辑。
597
632
  *
598
633
  * 返回的 `isExistingUser` 决定验码之后走登录还是注册 —— 该判断由上游给出,
599
634
  * SDK 不猜。
635
+ *
636
+ * 两条渠道的请求体差异是刻意的(runtime-auth-design §3.1):
637
+ * - 邮箱:`{ email, usage: 'EMAIL' }`
638
+ * - 手机:`{ phone_number, target: 'ANY' }` —— **不带 `usage`**(普通短信登录
639
+ * 发码时省略即可,上游没有对应的短信枚举值),`target: 'ANY'` 表示新老用户
640
+ * 都允许发码。
600
641
  */
601
642
  async sendOtp(credentials) {
602
- if (!credentials.email) {
603
- return fail(badRequest("sendOtp requires email"));
643
+ const body = {};
644
+ if (credentials.phone) {
645
+ body.phone_number = normalizePhone(credentials.phone);
646
+ body.target = "ANY";
647
+ } else if (credentials.email) {
648
+ body.email = credentials.email;
649
+ body.usage = "EMAIL";
650
+ if (credentials.emailRedirectTo) {
651
+ body.email_redirect_to = credentials.emailRedirectTo;
652
+ }
653
+ } else {
654
+ return fail(badRequest("sendOtp requires email or phone"));
604
655
  }
605
- const body = {
606
- email: credentials.email,
607
- usage: "EMAIL"
608
- };
609
- if (credentials.emailRedirectTo) body.email_redirect_to = credentials.emailRedirectTo;
610
656
  const res = await this.request(AUTH_PATHS.verification, {
611
657
  method: "POST",
612
658
  body
@@ -631,15 +677,18 @@ var AuthModule = class {
631
677
  return fail(sent.error);
632
678
  }
633
679
  const { verificationId, isExistingUser } = sent.data;
680
+ const phone = credentials.phone ? normalizePhone(credentials.phone) : void 0;
634
681
  return ok({
635
682
  verificationId,
636
683
  isExistingUser,
637
684
  isUser: isExistingUser,
638
- verify: /* @__PURE__ */ __name(({ token }) => this.verifyOtp({
685
+ verify: /* @__PURE__ */ __name(({ token, password }) => this.verifyOtp({
639
686
  verificationId,
640
687
  token,
641
688
  email: credentials.email,
642
- isExistingUser
689
+ phone,
690
+ isExistingUser,
691
+ password
643
692
  }), "verify")
644
693
  });
645
694
  }
@@ -652,10 +701,14 @@ var AuthModule = class {
652
701
  * 走登录还是注册由 `isExistingUser` 决定(`sendOtp` 的返回值)。刻意不做
653
702
  * 「先试登录失败再试注册」的兜底:那会把「密码错」这类真实错误掩盖成一次
654
703
  * 莫名的注册尝试。
704
+ *
705
+ * 登录侧邮箱与手机号共用 `username` 字段 —— 上游 `SignInRequest.username`
706
+ * 承载邮箱/手机/用户名三种形态(runtime-auth-design §3.2)。
655
707
  */
656
708
  async verifyOtp(params) {
657
- if (!params.verificationId || !params.token || !params.email) {
658
- return fail(badRequest("verifyOtp requires verificationId, token and email"));
709
+ const identifier = params.phone ? normalizePhone(params.phone) : params.email ?? "";
710
+ if (!params.verificationId || !params.token || !identifier) {
711
+ return fail(badRequest("verifyOtp requires verificationId, token and either email or phone"));
659
712
  }
660
713
  const verified = await this.request(AUTH_PATHS.verificationVerify, {
661
714
  method: "POST",
@@ -674,12 +727,13 @@ var AuthModule = class {
674
727
  }
675
728
  if (params.isExistingUser) {
676
729
  return this.postForSession(AUTH_PATHS.signIn, {
677
- username: params.email,
730
+ username: identifier,
678
731
  verification_token: verificationToken
679
732
  });
680
733
  }
681
734
  return this.signUp({
682
735
  email: params.email,
736
+ phone: params.phone,
683
737
  password: params.password ?? "",
684
738
  verificationToken
685
739
  });
@@ -696,8 +750,13 @@ var AuthModule = class {
696
750
  *
697
751
  * SDK 不自己跳转(不写 `location.href`):跳转时机应由应用决定 —— 有的要
698
752
  * 先存草稿,有的在 iframe 里要开弹窗。返回 url 交调用方处置。
753
+ *
754
+ * @deprecated Google 登录已下线,新应用不应再调用该方法。
699
755
  */
700
756
  async signInWithOAuth(options) {
757
+ if (!this.oauthRelayBaseUrl) {
758
+ return fail(badRequest("signInWithOAuth requires oauthRelayBaseUrl"));
759
+ }
701
760
  if (options.provider !== "google") {
702
761
  return fail(badRequest("signInWithOAuth currently supports only google"));
703
762
  }
@@ -712,6 +771,8 @@ var AuthModule = class {
712
771
  *
713
772
  * 在回调落地页调一次即可。`code` 缺失时返回 `null` 数据而**不是**错误 ——
714
773
  * 落地页可能被直接访问(用户收藏了它),那不是失败。
774
+ *
775
+ * @deprecated Google 登录已下线,新应用不应再调用该方法。
715
776
  */
716
777
  async handleOAuthCallback(search) {
717
778
  const callbackInput = search ?? currentPageSearch();
@@ -946,7 +1007,11 @@ var AuthModule = class {
946
1007
  // ------------------------------------------------------------------
947
1008
  // 内部
948
1009
  // ------------------------------------------------------------------
949
- /** 拼出平台 Relay 授权地址;state 由 Relay 自己签发、校验并一次性消费。 */
1010
+ /**
1011
+ * 拼出平台 Relay 授权地址;state 由 Relay 自己签发、校验并一次性消费。
1012
+ *
1013
+ * @deprecated Google 登录已下线,仅保留给存量应用的回调落地页。
1014
+ */
950
1015
  async startRelayOAuth(options, redirectTo) {
951
1016
  const callback = new URL(redirectTo);
952
1017
  const relay = new URL(`${this.oauthRelayBaseUrl}/authorize`);
@@ -1042,6 +1107,17 @@ function badRequest(message) {
1042
1107
  };
1043
1108
  }
1044
1109
  __name(badRequest, "badRequest");
1110
+ function normalizePhone(phone) {
1111
+ const digits = phone.replace(/\D/g, "");
1112
+ let local = digits;
1113
+ if (local.startsWith("0086")) {
1114
+ local = local.slice(4);
1115
+ } else if (local.startsWith("86") && local.length === 13) {
1116
+ local = local.slice(2);
1117
+ }
1118
+ return /^1\d{10}$/.test(local) ? `+86 ${local}` : phone;
1119
+ }
1120
+ __name(normalizePhone, "normalizePhone");
1045
1121
  function isCloudError(v) {
1046
1122
  return !!v && typeof v === "object" && typeof v.kind === "string";
1047
1123
  }
@@ -5140,9 +5216,42 @@ function pricingField(value) {
5140
5216
  return Object.keys(pricing).length ? pricing : void 0;
5141
5217
  }
5142
5218
  __name(pricingField, "pricingField");
5219
+ function reasoningField(value) {
5220
+ if (!value || typeof value !== "object") return void 0;
5221
+ const raw = value;
5222
+ const result = {};
5223
+ const effort = stringField(raw.effort);
5224
+ if (effort !== void 0) result.effort = effort;
5225
+ const defaultEffort = stringField(raw.defaultEffort);
5226
+ if (defaultEffort !== void 0) result.defaultEffort = defaultEffort;
5227
+ if (Array.isArray(raw.supportedEfforts)) {
5228
+ result.supportedEfforts = raw.supportedEfforts.filter((item) => typeof item === "string");
5229
+ }
5230
+ const rawSummary = stringField(raw.summary);
5231
+ if (rawSummary !== void 0 && (rawSummary === "auto" || rawSummary === "concise" || rawSummary === "detailed")) {
5232
+ result.summary = rawSummary;
5233
+ }
5234
+ const canDisable = booleanField(raw.canDisableThinking);
5235
+ if (canDisable !== void 0) result.canDisableThinking = canDisable;
5236
+ return Object.keys(result).length > 0 ? result : void 0;
5237
+ }
5238
+ __name(reasoningField, "reasoningField");
5143
5239
  function normalizeModel(raw) {
5144
5240
  const id = stringField(raw.id, raw.ID);
5145
5241
  if (!id) return null;
5242
+ const serverEnabled = booleanField(raw.enabled, raw.Enabled);
5243
+ const serverDisabled = booleanField(raw.disabled, raw.Disabled);
5244
+ let enabled;
5245
+ let disabled;
5246
+ if (serverEnabled !== void 0) {
5247
+ enabled = serverEnabled;
5248
+ if (serverDisabled !== void 0) disabled = serverDisabled;
5249
+ } else if (serverDisabled !== void 0) {
5250
+ disabled = serverDisabled;
5251
+ enabled = !serverDisabled;
5252
+ } else {
5253
+ enabled = true;
5254
+ }
5146
5255
  return {
5147
5256
  id,
5148
5257
  name: stringField(raw.name, raw.Name) ?? id,
@@ -5185,7 +5294,10 @@ function normalizeModel(raw) {
5185
5294
  ...capabilitiesField(raw.capabilities ?? raw.Capabilities) ? {
5186
5295
  capabilities: capabilitiesField(raw.capabilities ?? raw.Capabilities)
5187
5296
  } : {},
5188
- enabled: booleanField(raw.enabled, raw.Enabled) ?? true,
5297
+ enabled,
5298
+ ...disabled !== void 0 ? {
5299
+ disabled
5300
+ } : {},
5189
5301
  ...booleanField(raw.isDefault, raw.IsDefault) !== void 0 ? {
5190
5302
  isDefault: booleanField(raw.isDefault, raw.IsDefault)
5191
5303
  } : {},
@@ -5194,10 +5306,55 @@ function normalizeModel(raw) {
5194
5306
  } : {},
5195
5307
  ...pricingField(raw.pricing ?? raw.Pricing) ? {
5196
5308
  pricing: pricingField(raw.pricing ?? raw.Pricing)
5309
+ } : {},
5310
+ // User-specified sparse fields: preserve explicit false/0, omit only when absent.
5311
+ ...stringField(raw.credits, raw.Credits) ? {
5312
+ credits: stringField(raw.credits, raw.Credits)
5313
+ } : {},
5314
+ ...numberField(raw.maxAllowedSize, raw.MaxAllowedSize) !== void 0 ? {
5315
+ maxAllowedSize: numberField(raw.maxAllowedSize, raw.MaxAllowedSize)
5316
+ } : {},
5317
+ ...booleanField(raw.disabledMultimodal, raw.DisabledMultimodal) !== void 0 ? {
5318
+ disabledMultimodal: booleanField(raw.disabledMultimodal, raw.DisabledMultimodal)
5319
+ } : {},
5320
+ ...booleanField(raw.supportsImages, raw.SupportsImages) !== void 0 ? {
5321
+ supportsImages: booleanField(raw.supportsImages, raw.SupportsImages)
5322
+ } : {},
5323
+ ...booleanField(raw.supportsToolCall, raw.SupportsToolCall) !== void 0 ? {
5324
+ supportsToolCall: booleanField(raw.supportsToolCall, raw.SupportsToolCall)
5325
+ } : {},
5326
+ ...booleanField(raw.supportsReasoning, raw.SupportsReasoning) !== void 0 ? {
5327
+ supportsReasoning: booleanField(raw.supportsReasoning, raw.SupportsReasoning)
5328
+ } : {},
5329
+ ...booleanField(raw.onlyReasoning, raw.OnlyReasoning) !== void 0 ? {
5330
+ onlyReasoning: booleanField(raw.onlyReasoning, raw.OnlyReasoning)
5331
+ } : {},
5332
+ ...reasoningField(raw.reasoning ?? raw.Reasoning) ? {
5333
+ reasoning: reasoningField(raw.reasoning ?? raw.Reasoning)
5334
+ } : {},
5335
+ ...numberField(raw.temperature, raw.Temperature) !== void 0 ? {
5336
+ temperature: numberField(raw.temperature, raw.Temperature)
5337
+ } : {},
5338
+ ...numberField(raw.top_k, raw.Top_K) !== void 0 ? {
5339
+ top_k: numberField(raw.top_k, raw.Top_K)
5340
+ } : {},
5341
+ ...numberField(raw.top_p, raw.Top_P) !== void 0 ? {
5342
+ top_p: numberField(raw.top_p, raw.Top_P)
5343
+ } : {},
5344
+ ...numberField(raw.repetition_penalty, raw.Repetition_Penalty) !== void 0 ? {
5345
+ repetition_penalty: numberField(raw.repetition_penalty, raw.Repetition_Penalty)
5197
5346
  } : {}
5198
5347
  };
5199
5348
  }
5200
5349
  __name(normalizeModel, "normalizeModel");
5350
+ function getModelDisplayName(model) {
5351
+ return model.name || model.id;
5352
+ }
5353
+ __name(getModelDisplayName, "getModelDisplayName");
5354
+ function getModelCapability(model, capability) {
5355
+ return model.capabilities?.[capability];
5356
+ }
5357
+ __name(getModelCapability, "getModelCapability");
5201
5358
  var ModelsAPI = class {
5202
5359
  static {
5203
5360
  __name(this, "ModelsAPI");
@@ -5213,8 +5370,8 @@ var ModelsAPI = class {
5213
5370
  *
5214
5371
  * `id` is the value to pass as `model` to `chat.completions.create()`.
5215
5372
  * Optional metadata is included only when the server explicitly provides
5216
- * it; absence means unknown, not unsupported. The server remains the
5217
- * final allowlist authority for chat requests.
5373
+ * it; absence means unknown, not unsupported. The actual call result
5374
+ * is determined by the response, not by the directory entry.
5218
5375
  */
5219
5376
  async list(signal) {
5220
5377
  let response;
@@ -5487,7 +5644,10 @@ async function* iterSSEEvents(body, signal) {
5487
5644
  __name(iterSSEEvents, "iterSSEEvents");
5488
5645
 
5489
5646
  // src/modules/llm/chat.ts
5490
- function extractSSEError(data) {
5647
+ function extractSSEError(data, requestId) {
5648
+ const init = requestId ? {
5649
+ requestId
5650
+ } : {};
5491
5651
  try {
5492
5652
  const parsed = JSON.parse(data);
5493
5653
  if (parsed && typeof parsed === "object") {
@@ -5498,7 +5658,7 @@ function extractSSEError(data) {
5498
5658
  type: typeof errorObj.type === "string" ? errorObj.type : "server_error",
5499
5659
  param: errorObj.param === void 0 ? null : errorObj.param,
5500
5660
  code: errorObj.code === void 0 ? null : errorObj.code
5501
- });
5661
+ }, init);
5502
5662
  }
5503
5663
  }
5504
5664
  } catch {
@@ -5508,7 +5668,7 @@ function extractSSEError(data) {
5508
5668
  type: "server_error",
5509
5669
  param: null,
5510
5670
  code: null
5511
- });
5671
+ }, init);
5512
5672
  }
5513
5673
  __name(extractSSEError, "extractSSEError");
5514
5674
  var ChatCompletionsAPI = class {
@@ -5522,72 +5682,28 @@ var ChatCompletionsAPI = class {
5522
5682
  this.fetch = fetch2;
5523
5683
  }
5524
5684
  create(input) {
5525
- if (input.stream === true) {
5526
- return this.createStreaming(input);
5527
- }
5528
- return this.createNonStreaming(input);
5529
- }
5530
- /**
5531
- * Non-streaming chat completion.
5532
- */
5533
- async createNonStreaming(input) {
5534
- if (input.stream_options) {
5685
+ if (input.stream !== true) {
5535
5686
  throw new CloudOpenAIError({
5536
- message: "stream_options can only be used with stream=true",
5687
+ message: "stream must be true; non-streaming chat completions are not supported",
5537
5688
  type: "invalid_request_error",
5538
- param: "stream_options",
5539
- code: "request_invalid_parameter"
5540
- });
5541
- }
5542
- const { signal, ...body } = input;
5543
- if (body.stream === void 0) {
5544
- delete body.stream;
5545
- } else {
5546
- body.stream = false;
5547
- }
5548
- let response;
5549
- try {
5550
- response = await this.fetch(`${this.baseUrl}/chat/completions`, {
5551
- method: "POST",
5552
- headers: {
5553
- Accept: "application/json",
5554
- "Content-Type": "application/json"
5555
- },
5556
- body: JSON.stringify(body),
5557
- signal
5558
- });
5559
- } catch (err) {
5560
- if (err instanceof Error && err.name === "AbortError") {
5561
- throw err;
5562
- }
5563
- throw new CloudOpenAIError({
5564
- message: `Network error: ${err?.message ?? "unknown"}`,
5565
- type: "server_error",
5566
- param: null,
5567
- code: "gateway_network_error"
5568
- }, {
5569
- cause: err
5570
- });
5571
- }
5572
- if (!response.ok) {
5573
- throw await httpError(response);
5574
- }
5575
- const text = await response.text();
5576
- try {
5577
- return JSON.parse(text);
5578
- } catch {
5579
- throw new CloudOpenAIError({
5580
- message: "Failed to parse chat completion response: invalid JSON",
5581
- type: "server_error",
5582
- param: null,
5583
- code: "gateway_invalid_response"
5689
+ param: "stream",
5690
+ code: "request_stream_required"
5584
5691
  });
5585
5692
  }
5693
+ return this.createStreaming(input);
5586
5694
  }
5587
5695
  /**
5588
5696
  * Streaming chat completion — returns an async generator of chunks.
5589
5697
  *
5590
5698
  * Reads the SSE stream incrementally, yielding ChatCompletionChunk objects.
5699
+ * `stream_options` is passed through unchanged when present.
5700
+ *
5701
+ * The `X-Request-Id` response header is captured and attached (as
5702
+ * `requestId`) to every `CloudOpenAIError` thrown from within the stream:
5703
+ * `event: error`, chunk-embedded error, JSON parse failure, and missing
5704
+ * `[DONE]` interruption. Non-2xx HTTP errors continue to go through
5705
+ * `httpError`, which independently extracts `X-Request-Id`.
5706
+ *
5591
5707
  * Throws CloudOpenAIError on:
5592
5708
  * - `event: error` in the stream
5593
5709
  * - Stream ends without `[DONE]` (gateway_stream_interrupted)
@@ -5595,7 +5711,7 @@ var ChatCompletionsAPI = class {
5595
5711
  * - Caller abort (AbortSignal) — exits silently, no throw
5596
5712
  */
5597
5713
  async *createStreaming(input) {
5598
- const { signal, ...body } = input;
5714
+ const { signal, conversationId, ...body } = input;
5599
5715
  body.stream = true;
5600
5716
  let response;
5601
5717
  try {
@@ -5603,7 +5719,10 @@ var ChatCompletionsAPI = class {
5603
5719
  method: "POST",
5604
5720
  headers: {
5605
5721
  Accept: "text/event-stream",
5606
- "Content-Type": "application/json"
5722
+ "Content-Type": "application/json",
5723
+ ...conversationId !== void 0 ? {
5724
+ "X-Conversation-ID": conversationId
5725
+ } : {}
5607
5726
  },
5608
5727
  body: JSON.stringify(body),
5609
5728
  signal
@@ -5630,15 +5749,18 @@ var ChatCompletionsAPI = class {
5630
5749
  type: "server_error",
5631
5750
  param: null,
5632
5751
  code: "gateway_invalid_response"
5752
+ }, {
5753
+ requestId: response.headers.get("x-request-id") ?? void 0
5633
5754
  });
5634
5755
  }
5756
+ const requestId = response.headers.get("x-request-id") ?? void 0;
5635
5757
  let receivedDone = false;
5636
5758
  let threw = false;
5637
5759
  try {
5638
5760
  for await (const sseEvent of iterSSEEvents(response.body, signal)) {
5639
5761
  if (sseEvent.event === "error") {
5640
5762
  threw = true;
5641
- throw extractSSEError(sseEvent.data);
5763
+ throw extractSSEError(sseEvent.data, requestId);
5642
5764
  }
5643
5765
  if (sseEvent.event === null || sseEvent.event === "") {
5644
5766
  if (sseEvent.data === SSE_DONE) {
@@ -5658,6 +5780,8 @@ var ChatCompletionsAPI = class {
5658
5780
  type: "server_error",
5659
5781
  param: null,
5660
5782
  code: "gateway_invalid_response"
5783
+ }, {
5784
+ requestId
5661
5785
  });
5662
5786
  }
5663
5787
  if (chunk && typeof chunk === "object" && "error" in chunk) {
@@ -5668,6 +5792,8 @@ var ChatCompletionsAPI = class {
5668
5792
  type: typeof errObj?.type === "string" ? errObj.type : "server_error",
5669
5793
  param: errObj?.param === void 0 ? null : errObj.param,
5670
5794
  code: errObj?.code === void 0 ? null : errObj.code
5795
+ }, {
5796
+ requestId
5671
5797
  });
5672
5798
  }
5673
5799
  yield chunk;
@@ -5686,6 +5812,8 @@ var ChatCompletionsAPI = class {
5686
5812
  type: "server_error",
5687
5813
  param: null,
5688
5814
  code: "gateway_stream_interrupted"
5815
+ }, {
5816
+ requestId
5689
5817
  });
5690
5818
  }
5691
5819
  }
@@ -9266,6 +9394,8 @@ __name(shouldClearCredentials, "shouldClearCredentials");
9266
9394
  anonymousTokenProvider,
9267
9395
  createMemoryStorage,
9268
9396
  createWorkBuddyCloud,
9397
+ getModelCapability,
9398
+ getModelDisplayName,
9269
9399
  shouldClearCredentials
9270
9400
  });
9271
9401
  //# sourceMappingURL=index.cjs.map