@tencent-ai/workbuddy-cloud-sdk 0.1.0-dev.dee063d.202608201621 → 0.1.1-dev.2eb913e.202609082341
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 +28 -0
- package/lib/index.cjs +204 -86
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +280 -44
- package/lib/index.d.ts +280 -44
- package/lib/index.global.js +4 -4
- package/lib/index.global.js.map +1 -1
- package/lib/index.js +202 -86
- package/lib/index.js.map +1 -1
- package/lib/miniprogram.cjs +9752 -0
- package/lib/miniprogram.cjs.map +1 -0
- package/lib/miniprogram.d.cts +6794 -0
- package/lib/miniprogram.d.ts +6794 -0
- package/lib/miniprogram.js +9722 -0
- package/lib/miniprogram.js.map +1 -0
- package/miniprogram_dist/miniprogram.js +14737 -0
- package/package.json +33 -4
package/lib/index.js
CHANGED
|
@@ -31,6 +31,17 @@ function normalizeHttpUrl(value, field) {
|
|
|
31
31
|
return trimmed.replace(/\/+$/, "");
|
|
32
32
|
}
|
|
33
33
|
__name(normalizeHttpUrl, "normalizeHttpUrl");
|
|
34
|
+
function resolveEndpoint(value) {
|
|
35
|
+
if (value !== void 0 && value !== null && value !== "") {
|
|
36
|
+
return normalizeHttpUrl(value, "endpoint");
|
|
37
|
+
}
|
|
38
|
+
const origin = globalThis.location?.origin;
|
|
39
|
+
if (typeof origin !== "string" || origin === "") {
|
|
40
|
+
throw new WorkBuddyCloudConfigError("endpoint is required outside browsers (no location.origin to fall back to).");
|
|
41
|
+
}
|
|
42
|
+
return origin.replace(/\/+$/, "");
|
|
43
|
+
}
|
|
44
|
+
__name(resolveEndpoint, "resolveEndpoint");
|
|
34
45
|
function normalizePublishableKey(publishableKey) {
|
|
35
46
|
if (typeof publishableKey !== "string" || publishableKey.trim() === "") {
|
|
36
47
|
throw new WorkBuddyCloudConfigError("publishableKey is required and must be a non-empty string.");
|
|
@@ -54,11 +65,11 @@ function resolveFetch(candidate) {
|
|
|
54
65
|
__name(resolveFetch, "resolveFetch");
|
|
55
66
|
function resolveRuntimeConfig(options) {
|
|
56
67
|
if (!options || typeof options !== "object") {
|
|
57
|
-
throw new WorkBuddyCloudConfigError("createWorkBuddyCloud requires
|
|
68
|
+
throw new WorkBuddyCloudConfigError("createWorkBuddyCloud requires publishableKey.");
|
|
58
69
|
}
|
|
59
70
|
return Object.freeze({
|
|
60
|
-
endpoint:
|
|
61
|
-
oauthRelayBaseUrl: normalizeHttpUrl(options.oauthRelayBaseUrl, "oauthRelayBaseUrl"),
|
|
71
|
+
endpoint: resolveEndpoint(options.endpoint),
|
|
72
|
+
oauthRelayBaseUrl: options.oauthRelayBaseUrl ? normalizeHttpUrl(options.oauthRelayBaseUrl, "oauthRelayBaseUrl") : "",
|
|
62
73
|
publishableKey: normalizePublishableKey(options.publishableKey),
|
|
63
74
|
fetch: resolveFetch(options.fetch)
|
|
64
75
|
});
|
|
@@ -102,6 +113,8 @@ var AUTH_PATHS = {
|
|
|
102
113
|
signInWithProvider: "/v1/signin/with/provider",
|
|
103
114
|
/** 本地续期端点(服务端不转发上游)。 */
|
|
104
115
|
token: "/v1/token",
|
|
116
|
+
/** 小程序微信登录:本地认人后仍需用 custom 票据换取 TCB session。 */
|
|
117
|
+
loginWechat: "/v1/login-wechat",
|
|
105
118
|
signOut: "/v1/user/signout",
|
|
106
119
|
userMe: "/v1/user/me",
|
|
107
120
|
/** 发码。 */
|
|
@@ -527,15 +540,34 @@ var AuthModule = class {
|
|
|
527
540
|
password: credentials.password
|
|
528
541
|
});
|
|
529
542
|
}
|
|
543
|
+
/**
|
|
544
|
+
* 小程序 wx.login 的 code 换 Genie session。
|
|
545
|
+
* 试用与正式是两套独立小程序,必须带当前账号的 appid
|
|
546
|
+
*(`wx.getAccountInfoSync().miniProgram.appId`)。
|
|
547
|
+
*/
|
|
548
|
+
async signInWithWechat(code, appid) {
|
|
549
|
+
if (!code) {
|
|
550
|
+
return fail(badRequest("signInWithWechat requires code"));
|
|
551
|
+
}
|
|
552
|
+
if (!appid) {
|
|
553
|
+
return fail(badRequest("signInWithWechat requires appid"));
|
|
554
|
+
}
|
|
555
|
+
return this.postForSession(AUTH_PATHS.loginWechat, {
|
|
556
|
+
code,
|
|
557
|
+
appid
|
|
558
|
+
});
|
|
559
|
+
}
|
|
530
560
|
/**
|
|
531
561
|
* 注册。
|
|
532
562
|
*
|
|
533
563
|
* 上游要求先完成验证码验证,所以必须带一个 `verificationToken`(来自
|
|
534
564
|
* `verifyOtp`)。只有用户名+密码的注册会被上游明确拒绝。
|
|
565
|
+
*
|
|
566
|
+
* 账号标识用 `email` 或 `phone`(二选一,与发码渠道一致)。
|
|
535
567
|
*/
|
|
536
568
|
async signUp(credentials) {
|
|
537
|
-
if (!credentials.email) {
|
|
538
|
-
return fail(badRequest("signUp requires email"));
|
|
569
|
+
if (!credentials.email && !credentials.phone) {
|
|
570
|
+
return fail(badRequest("signUp requires email or phone"));
|
|
539
571
|
}
|
|
540
572
|
if (!credentials.verificationToken) {
|
|
541
573
|
return fail(badRequest("signUp requires a verificationToken; run sendOtp + verifyOtp first (the provider rejects username+password-only signup)"));
|
|
@@ -543,28 +575,40 @@ var AuthModule = class {
|
|
|
543
575
|
const body = {
|
|
544
576
|
verification_token: credentials.verificationToken
|
|
545
577
|
};
|
|
546
|
-
body.
|
|
578
|
+
if (credentials.phone) body.phone_number = credentials.phone;
|
|
579
|
+
if (credentials.email) body.email = credentials.email;
|
|
547
580
|
if (credentials.password) body.password = credentials.password;
|
|
548
581
|
return this.postForSession(AUTH_PATHS.signUp, body);
|
|
549
582
|
}
|
|
550
583
|
/**
|
|
551
|
-
*
|
|
584
|
+
* 发验证码(邮箱或短信,由 `credentials` 传的字段决定)。
|
|
552
585
|
*
|
|
553
586
|
* 这一步**不产生会话**,只返回一个 `verificationId`。发码由上游完成,
|
|
554
587
|
* 我方不实现发码逻辑。
|
|
555
588
|
*
|
|
556
589
|
* 返回的 `isExistingUser` 决定验码之后走登录还是注册 —— 该判断由上游给出,
|
|
557
590
|
* SDK 不猜。
|
|
591
|
+
*
|
|
592
|
+
* 两条渠道的请求体差异是刻意的(runtime-auth-design §3.1):
|
|
593
|
+
* - 邮箱:`{ email, usage: 'EMAIL' }`
|
|
594
|
+
* - 手机:`{ phone_number, target: 'ANY' }` —— **不带 `usage`**(普通短信登录
|
|
595
|
+
* 发码时省略即可,上游没有对应的短信枚举值),`target: 'ANY'` 表示新老用户
|
|
596
|
+
* 都允许发码。
|
|
558
597
|
*/
|
|
559
598
|
async sendOtp(credentials) {
|
|
560
|
-
|
|
561
|
-
|
|
599
|
+
const body = {};
|
|
600
|
+
if (credentials.phone) {
|
|
601
|
+
body.phone_number = credentials.phone;
|
|
602
|
+
body.target = "ANY";
|
|
603
|
+
} else if (credentials.email) {
|
|
604
|
+
body.email = credentials.email;
|
|
605
|
+
body.usage = "EMAIL";
|
|
606
|
+
if (credentials.emailRedirectTo) {
|
|
607
|
+
body.email_redirect_to = credentials.emailRedirectTo;
|
|
608
|
+
}
|
|
609
|
+
} else {
|
|
610
|
+
return fail(badRequest("sendOtp requires email or phone"));
|
|
562
611
|
}
|
|
563
|
-
const body = {
|
|
564
|
-
email: credentials.email,
|
|
565
|
-
usage: "EMAIL"
|
|
566
|
-
};
|
|
567
|
-
if (credentials.emailRedirectTo) body.email_redirect_to = credentials.emailRedirectTo;
|
|
568
612
|
const res = await this.request(AUTH_PATHS.verification, {
|
|
569
613
|
method: "POST",
|
|
570
614
|
body
|
|
@@ -593,11 +637,13 @@ var AuthModule = class {
|
|
|
593
637
|
verificationId,
|
|
594
638
|
isExistingUser,
|
|
595
639
|
isUser: isExistingUser,
|
|
596
|
-
verify: /* @__PURE__ */ __name(({ token }) => this.verifyOtp({
|
|
640
|
+
verify: /* @__PURE__ */ __name(({ token, password }) => this.verifyOtp({
|
|
597
641
|
verificationId,
|
|
598
642
|
token,
|
|
599
643
|
email: credentials.email,
|
|
600
|
-
|
|
644
|
+
phone: credentials.phone,
|
|
645
|
+
isExistingUser,
|
|
646
|
+
password
|
|
601
647
|
}), "verify")
|
|
602
648
|
});
|
|
603
649
|
}
|
|
@@ -610,10 +656,14 @@ var AuthModule = class {
|
|
|
610
656
|
* 走登录还是注册由 `isExistingUser` 决定(`sendOtp` 的返回值)。刻意不做
|
|
611
657
|
* 「先试登录失败再试注册」的兜底:那会把「密码错」这类真实错误掩盖成一次
|
|
612
658
|
* 莫名的注册尝试。
|
|
659
|
+
*
|
|
660
|
+
* 登录侧邮箱与手机号共用 `username` 字段 —— 上游 `SignInRequest.username`
|
|
661
|
+
* 承载邮箱/手机/用户名三种形态(runtime-auth-design §3.2)。
|
|
613
662
|
*/
|
|
614
663
|
async verifyOtp(params) {
|
|
615
|
-
|
|
616
|
-
|
|
664
|
+
const identifier = params.phone ?? params.email ?? "";
|
|
665
|
+
if (!params.verificationId || !params.token || !identifier) {
|
|
666
|
+
return fail(badRequest("verifyOtp requires verificationId, token and either email or phone"));
|
|
617
667
|
}
|
|
618
668
|
const verified = await this.request(AUTH_PATHS.verificationVerify, {
|
|
619
669
|
method: "POST",
|
|
@@ -632,12 +682,13 @@ var AuthModule = class {
|
|
|
632
682
|
}
|
|
633
683
|
if (params.isExistingUser) {
|
|
634
684
|
return this.postForSession(AUTH_PATHS.signIn, {
|
|
635
|
-
username:
|
|
685
|
+
username: identifier,
|
|
636
686
|
verification_token: verificationToken
|
|
637
687
|
});
|
|
638
688
|
}
|
|
639
689
|
return this.signUp({
|
|
640
690
|
email: params.email,
|
|
691
|
+
phone: params.phone,
|
|
641
692
|
password: params.password ?? "",
|
|
642
693
|
verificationToken
|
|
643
694
|
});
|
|
@@ -654,8 +705,13 @@ var AuthModule = class {
|
|
|
654
705
|
*
|
|
655
706
|
* SDK 不自己跳转(不写 `location.href`):跳转时机应由应用决定 —— 有的要
|
|
656
707
|
* 先存草稿,有的在 iframe 里要开弹窗。返回 url 交调用方处置。
|
|
708
|
+
*
|
|
709
|
+
* @deprecated Google 登录已下线,新应用不应再调用该方法。
|
|
657
710
|
*/
|
|
658
711
|
async signInWithOAuth(options) {
|
|
712
|
+
if (!this.oauthRelayBaseUrl) {
|
|
713
|
+
return fail(badRequest("signInWithOAuth requires oauthRelayBaseUrl"));
|
|
714
|
+
}
|
|
659
715
|
if (options.provider !== "google") {
|
|
660
716
|
return fail(badRequest("signInWithOAuth currently supports only google"));
|
|
661
717
|
}
|
|
@@ -670,6 +726,8 @@ var AuthModule = class {
|
|
|
670
726
|
*
|
|
671
727
|
* 在回调落地页调一次即可。`code` 缺失时返回 `null` 数据而**不是**错误 ——
|
|
672
728
|
* 落地页可能被直接访问(用户收藏了它),那不是失败。
|
|
729
|
+
*
|
|
730
|
+
* @deprecated Google 登录已下线,新应用不应再调用该方法。
|
|
673
731
|
*/
|
|
674
732
|
async handleOAuthCallback(search) {
|
|
675
733
|
const callbackInput = search ?? currentPageSearch();
|
|
@@ -904,7 +962,11 @@ var AuthModule = class {
|
|
|
904
962
|
// ------------------------------------------------------------------
|
|
905
963
|
// 内部
|
|
906
964
|
// ------------------------------------------------------------------
|
|
907
|
-
/**
|
|
965
|
+
/**
|
|
966
|
+
* 拼出平台 Relay 授权地址;state 由 Relay 自己签发、校验并一次性消费。
|
|
967
|
+
*
|
|
968
|
+
* @deprecated Google 登录已下线,仅保留给存量应用的回调落地页。
|
|
969
|
+
*/
|
|
908
970
|
async startRelayOAuth(options, redirectTo) {
|
|
909
971
|
const callback = new URL(redirectTo);
|
|
910
972
|
const relay = new URL(`${this.oauthRelayBaseUrl}/authorize`);
|
|
@@ -5098,9 +5160,42 @@ function pricingField(value) {
|
|
|
5098
5160
|
return Object.keys(pricing).length ? pricing : void 0;
|
|
5099
5161
|
}
|
|
5100
5162
|
__name(pricingField, "pricingField");
|
|
5163
|
+
function reasoningField(value) {
|
|
5164
|
+
if (!value || typeof value !== "object") return void 0;
|
|
5165
|
+
const raw = value;
|
|
5166
|
+
const result = {};
|
|
5167
|
+
const effort = stringField(raw.effort);
|
|
5168
|
+
if (effort !== void 0) result.effort = effort;
|
|
5169
|
+
const defaultEffort = stringField(raw.defaultEffort);
|
|
5170
|
+
if (defaultEffort !== void 0) result.defaultEffort = defaultEffort;
|
|
5171
|
+
if (Array.isArray(raw.supportedEfforts)) {
|
|
5172
|
+
result.supportedEfforts = raw.supportedEfforts.filter((item) => typeof item === "string");
|
|
5173
|
+
}
|
|
5174
|
+
const rawSummary = stringField(raw.summary);
|
|
5175
|
+
if (rawSummary !== void 0 && (rawSummary === "auto" || rawSummary === "concise" || rawSummary === "detailed")) {
|
|
5176
|
+
result.summary = rawSummary;
|
|
5177
|
+
}
|
|
5178
|
+
const canDisable = booleanField(raw.canDisableThinking);
|
|
5179
|
+
if (canDisable !== void 0) result.canDisableThinking = canDisable;
|
|
5180
|
+
return Object.keys(result).length > 0 ? result : void 0;
|
|
5181
|
+
}
|
|
5182
|
+
__name(reasoningField, "reasoningField");
|
|
5101
5183
|
function normalizeModel(raw) {
|
|
5102
5184
|
const id = stringField(raw.id, raw.ID);
|
|
5103
5185
|
if (!id) return null;
|
|
5186
|
+
const serverEnabled = booleanField(raw.enabled, raw.Enabled);
|
|
5187
|
+
const serverDisabled = booleanField(raw.disabled, raw.Disabled);
|
|
5188
|
+
let enabled;
|
|
5189
|
+
let disabled;
|
|
5190
|
+
if (serverEnabled !== void 0) {
|
|
5191
|
+
enabled = serverEnabled;
|
|
5192
|
+
if (serverDisabled !== void 0) disabled = serverDisabled;
|
|
5193
|
+
} else if (serverDisabled !== void 0) {
|
|
5194
|
+
disabled = serverDisabled;
|
|
5195
|
+
enabled = !serverDisabled;
|
|
5196
|
+
} else {
|
|
5197
|
+
enabled = true;
|
|
5198
|
+
}
|
|
5104
5199
|
return {
|
|
5105
5200
|
id,
|
|
5106
5201
|
name: stringField(raw.name, raw.Name) ?? id,
|
|
@@ -5143,7 +5238,10 @@ function normalizeModel(raw) {
|
|
|
5143
5238
|
...capabilitiesField(raw.capabilities ?? raw.Capabilities) ? {
|
|
5144
5239
|
capabilities: capabilitiesField(raw.capabilities ?? raw.Capabilities)
|
|
5145
5240
|
} : {},
|
|
5146
|
-
enabled
|
|
5241
|
+
enabled,
|
|
5242
|
+
...disabled !== void 0 ? {
|
|
5243
|
+
disabled
|
|
5244
|
+
} : {},
|
|
5147
5245
|
...booleanField(raw.isDefault, raw.IsDefault) !== void 0 ? {
|
|
5148
5246
|
isDefault: booleanField(raw.isDefault, raw.IsDefault)
|
|
5149
5247
|
} : {},
|
|
@@ -5152,10 +5250,55 @@ function normalizeModel(raw) {
|
|
|
5152
5250
|
} : {},
|
|
5153
5251
|
...pricingField(raw.pricing ?? raw.Pricing) ? {
|
|
5154
5252
|
pricing: pricingField(raw.pricing ?? raw.Pricing)
|
|
5253
|
+
} : {},
|
|
5254
|
+
// User-specified sparse fields: preserve explicit false/0, omit only when absent.
|
|
5255
|
+
...stringField(raw.credits, raw.Credits) ? {
|
|
5256
|
+
credits: stringField(raw.credits, raw.Credits)
|
|
5257
|
+
} : {},
|
|
5258
|
+
...numberField(raw.maxAllowedSize, raw.MaxAllowedSize) !== void 0 ? {
|
|
5259
|
+
maxAllowedSize: numberField(raw.maxAllowedSize, raw.MaxAllowedSize)
|
|
5260
|
+
} : {},
|
|
5261
|
+
...booleanField(raw.disabledMultimodal, raw.DisabledMultimodal) !== void 0 ? {
|
|
5262
|
+
disabledMultimodal: booleanField(raw.disabledMultimodal, raw.DisabledMultimodal)
|
|
5263
|
+
} : {},
|
|
5264
|
+
...booleanField(raw.supportsImages, raw.SupportsImages) !== void 0 ? {
|
|
5265
|
+
supportsImages: booleanField(raw.supportsImages, raw.SupportsImages)
|
|
5266
|
+
} : {},
|
|
5267
|
+
...booleanField(raw.supportsToolCall, raw.SupportsToolCall) !== void 0 ? {
|
|
5268
|
+
supportsToolCall: booleanField(raw.supportsToolCall, raw.SupportsToolCall)
|
|
5269
|
+
} : {},
|
|
5270
|
+
...booleanField(raw.supportsReasoning, raw.SupportsReasoning) !== void 0 ? {
|
|
5271
|
+
supportsReasoning: booleanField(raw.supportsReasoning, raw.SupportsReasoning)
|
|
5272
|
+
} : {},
|
|
5273
|
+
...booleanField(raw.onlyReasoning, raw.OnlyReasoning) !== void 0 ? {
|
|
5274
|
+
onlyReasoning: booleanField(raw.onlyReasoning, raw.OnlyReasoning)
|
|
5275
|
+
} : {},
|
|
5276
|
+
...reasoningField(raw.reasoning ?? raw.Reasoning) ? {
|
|
5277
|
+
reasoning: reasoningField(raw.reasoning ?? raw.Reasoning)
|
|
5278
|
+
} : {},
|
|
5279
|
+
...numberField(raw.temperature, raw.Temperature) !== void 0 ? {
|
|
5280
|
+
temperature: numberField(raw.temperature, raw.Temperature)
|
|
5281
|
+
} : {},
|
|
5282
|
+
...numberField(raw.top_k, raw.Top_K) !== void 0 ? {
|
|
5283
|
+
top_k: numberField(raw.top_k, raw.Top_K)
|
|
5284
|
+
} : {},
|
|
5285
|
+
...numberField(raw.top_p, raw.Top_P) !== void 0 ? {
|
|
5286
|
+
top_p: numberField(raw.top_p, raw.Top_P)
|
|
5287
|
+
} : {},
|
|
5288
|
+
...numberField(raw.repetition_penalty, raw.Repetition_Penalty) !== void 0 ? {
|
|
5289
|
+
repetition_penalty: numberField(raw.repetition_penalty, raw.Repetition_Penalty)
|
|
5155
5290
|
} : {}
|
|
5156
5291
|
};
|
|
5157
5292
|
}
|
|
5158
5293
|
__name(normalizeModel, "normalizeModel");
|
|
5294
|
+
function getModelDisplayName(model) {
|
|
5295
|
+
return model.name || model.id;
|
|
5296
|
+
}
|
|
5297
|
+
__name(getModelDisplayName, "getModelDisplayName");
|
|
5298
|
+
function getModelCapability(model, capability) {
|
|
5299
|
+
return model.capabilities?.[capability];
|
|
5300
|
+
}
|
|
5301
|
+
__name(getModelCapability, "getModelCapability");
|
|
5159
5302
|
var ModelsAPI = class {
|
|
5160
5303
|
static {
|
|
5161
5304
|
__name(this, "ModelsAPI");
|
|
@@ -5171,8 +5314,8 @@ var ModelsAPI = class {
|
|
|
5171
5314
|
*
|
|
5172
5315
|
* `id` is the value to pass as `model` to `chat.completions.create()`.
|
|
5173
5316
|
* Optional metadata is included only when the server explicitly provides
|
|
5174
|
-
* it; absence means unknown, not unsupported. The
|
|
5175
|
-
*
|
|
5317
|
+
* it; absence means unknown, not unsupported. The actual call result
|
|
5318
|
+
* is determined by the response, not by the directory entry.
|
|
5176
5319
|
*/
|
|
5177
5320
|
async list(signal) {
|
|
5178
5321
|
let response;
|
|
@@ -5445,7 +5588,10 @@ async function* iterSSEEvents(body, signal) {
|
|
|
5445
5588
|
__name(iterSSEEvents, "iterSSEEvents");
|
|
5446
5589
|
|
|
5447
5590
|
// src/modules/llm/chat.ts
|
|
5448
|
-
function extractSSEError(data) {
|
|
5591
|
+
function extractSSEError(data, requestId) {
|
|
5592
|
+
const init = requestId ? {
|
|
5593
|
+
requestId
|
|
5594
|
+
} : {};
|
|
5449
5595
|
try {
|
|
5450
5596
|
const parsed = JSON.parse(data);
|
|
5451
5597
|
if (parsed && typeof parsed === "object") {
|
|
@@ -5456,7 +5602,7 @@ function extractSSEError(data) {
|
|
|
5456
5602
|
type: typeof errorObj.type === "string" ? errorObj.type : "server_error",
|
|
5457
5603
|
param: errorObj.param === void 0 ? null : errorObj.param,
|
|
5458
5604
|
code: errorObj.code === void 0 ? null : errorObj.code
|
|
5459
|
-
});
|
|
5605
|
+
}, init);
|
|
5460
5606
|
}
|
|
5461
5607
|
}
|
|
5462
5608
|
} catch {
|
|
@@ -5466,7 +5612,7 @@ function extractSSEError(data) {
|
|
|
5466
5612
|
type: "server_error",
|
|
5467
5613
|
param: null,
|
|
5468
5614
|
code: null
|
|
5469
|
-
});
|
|
5615
|
+
}, init);
|
|
5470
5616
|
}
|
|
5471
5617
|
__name(extractSSEError, "extractSSEError");
|
|
5472
5618
|
var ChatCompletionsAPI = class {
|
|
@@ -5480,72 +5626,28 @@ var ChatCompletionsAPI = class {
|
|
|
5480
5626
|
this.fetch = fetch2;
|
|
5481
5627
|
}
|
|
5482
5628
|
create(input) {
|
|
5483
|
-
if (input.stream
|
|
5484
|
-
return this.createStreaming(input);
|
|
5485
|
-
}
|
|
5486
|
-
return this.createNonStreaming(input);
|
|
5487
|
-
}
|
|
5488
|
-
/**
|
|
5489
|
-
* Non-streaming chat completion.
|
|
5490
|
-
*/
|
|
5491
|
-
async createNonStreaming(input) {
|
|
5492
|
-
if (input.stream_options) {
|
|
5629
|
+
if (input.stream !== true) {
|
|
5493
5630
|
throw new CloudOpenAIError({
|
|
5494
|
-
message: "
|
|
5631
|
+
message: "stream must be true; non-streaming chat completions are not supported",
|
|
5495
5632
|
type: "invalid_request_error",
|
|
5496
|
-
param: "
|
|
5497
|
-
code: "
|
|
5498
|
-
});
|
|
5499
|
-
}
|
|
5500
|
-
const { signal, ...body } = input;
|
|
5501
|
-
if (body.stream === void 0) {
|
|
5502
|
-
delete body.stream;
|
|
5503
|
-
} else {
|
|
5504
|
-
body.stream = false;
|
|
5505
|
-
}
|
|
5506
|
-
let response;
|
|
5507
|
-
try {
|
|
5508
|
-
response = await this.fetch(`${this.baseUrl}/chat/completions`, {
|
|
5509
|
-
method: "POST",
|
|
5510
|
-
headers: {
|
|
5511
|
-
Accept: "application/json",
|
|
5512
|
-
"Content-Type": "application/json"
|
|
5513
|
-
},
|
|
5514
|
-
body: JSON.stringify(body),
|
|
5515
|
-
signal
|
|
5516
|
-
});
|
|
5517
|
-
} catch (err) {
|
|
5518
|
-
if (err instanceof Error && err.name === "AbortError") {
|
|
5519
|
-
throw err;
|
|
5520
|
-
}
|
|
5521
|
-
throw new CloudOpenAIError({
|
|
5522
|
-
message: `Network error: ${err?.message ?? "unknown"}`,
|
|
5523
|
-
type: "server_error",
|
|
5524
|
-
param: null,
|
|
5525
|
-
code: "gateway_network_error"
|
|
5526
|
-
}, {
|
|
5527
|
-
cause: err
|
|
5528
|
-
});
|
|
5529
|
-
}
|
|
5530
|
-
if (!response.ok) {
|
|
5531
|
-
throw await httpError(response);
|
|
5532
|
-
}
|
|
5533
|
-
const text = await response.text();
|
|
5534
|
-
try {
|
|
5535
|
-
return JSON.parse(text);
|
|
5536
|
-
} catch {
|
|
5537
|
-
throw new CloudOpenAIError({
|
|
5538
|
-
message: "Failed to parse chat completion response: invalid JSON",
|
|
5539
|
-
type: "server_error",
|
|
5540
|
-
param: null,
|
|
5541
|
-
code: "gateway_invalid_response"
|
|
5633
|
+
param: "stream",
|
|
5634
|
+
code: "request_stream_required"
|
|
5542
5635
|
});
|
|
5543
5636
|
}
|
|
5637
|
+
return this.createStreaming(input);
|
|
5544
5638
|
}
|
|
5545
5639
|
/**
|
|
5546
5640
|
* Streaming chat completion — returns an async generator of chunks.
|
|
5547
5641
|
*
|
|
5548
5642
|
* Reads the SSE stream incrementally, yielding ChatCompletionChunk objects.
|
|
5643
|
+
* `stream_options` is passed through unchanged when present.
|
|
5644
|
+
*
|
|
5645
|
+
* The `X-Request-Id` response header is captured and attached (as
|
|
5646
|
+
* `requestId`) to every `CloudOpenAIError` thrown from within the stream:
|
|
5647
|
+
* `event: error`, chunk-embedded error, JSON parse failure, and missing
|
|
5648
|
+
* `[DONE]` interruption. Non-2xx HTTP errors continue to go through
|
|
5649
|
+
* `httpError`, which independently extracts `X-Request-Id`.
|
|
5650
|
+
*
|
|
5549
5651
|
* Throws CloudOpenAIError on:
|
|
5550
5652
|
* - `event: error` in the stream
|
|
5551
5653
|
* - Stream ends without `[DONE]` (gateway_stream_interrupted)
|
|
@@ -5553,7 +5655,7 @@ var ChatCompletionsAPI = class {
|
|
|
5553
5655
|
* - Caller abort (AbortSignal) — exits silently, no throw
|
|
5554
5656
|
*/
|
|
5555
5657
|
async *createStreaming(input) {
|
|
5556
|
-
const { signal, ...body } = input;
|
|
5658
|
+
const { signal, conversationId, ...body } = input;
|
|
5557
5659
|
body.stream = true;
|
|
5558
5660
|
let response;
|
|
5559
5661
|
try {
|
|
@@ -5561,7 +5663,10 @@ var ChatCompletionsAPI = class {
|
|
|
5561
5663
|
method: "POST",
|
|
5562
5664
|
headers: {
|
|
5563
5665
|
Accept: "text/event-stream",
|
|
5564
|
-
"Content-Type": "application/json"
|
|
5666
|
+
"Content-Type": "application/json",
|
|
5667
|
+
...conversationId !== void 0 ? {
|
|
5668
|
+
"X-Conversation-ID": conversationId
|
|
5669
|
+
} : {}
|
|
5565
5670
|
},
|
|
5566
5671
|
body: JSON.stringify(body),
|
|
5567
5672
|
signal
|
|
@@ -5588,15 +5693,18 @@ var ChatCompletionsAPI = class {
|
|
|
5588
5693
|
type: "server_error",
|
|
5589
5694
|
param: null,
|
|
5590
5695
|
code: "gateway_invalid_response"
|
|
5696
|
+
}, {
|
|
5697
|
+
requestId: response.headers.get("x-request-id") ?? void 0
|
|
5591
5698
|
});
|
|
5592
5699
|
}
|
|
5700
|
+
const requestId = response.headers.get("x-request-id") ?? void 0;
|
|
5593
5701
|
let receivedDone = false;
|
|
5594
5702
|
let threw = false;
|
|
5595
5703
|
try {
|
|
5596
5704
|
for await (const sseEvent of iterSSEEvents(response.body, signal)) {
|
|
5597
5705
|
if (sseEvent.event === "error") {
|
|
5598
5706
|
threw = true;
|
|
5599
|
-
throw extractSSEError(sseEvent.data);
|
|
5707
|
+
throw extractSSEError(sseEvent.data, requestId);
|
|
5600
5708
|
}
|
|
5601
5709
|
if (sseEvent.event === null || sseEvent.event === "") {
|
|
5602
5710
|
if (sseEvent.data === SSE_DONE) {
|
|
@@ -5616,6 +5724,8 @@ var ChatCompletionsAPI = class {
|
|
|
5616
5724
|
type: "server_error",
|
|
5617
5725
|
param: null,
|
|
5618
5726
|
code: "gateway_invalid_response"
|
|
5727
|
+
}, {
|
|
5728
|
+
requestId
|
|
5619
5729
|
});
|
|
5620
5730
|
}
|
|
5621
5731
|
if (chunk && typeof chunk === "object" && "error" in chunk) {
|
|
@@ -5626,6 +5736,8 @@ var ChatCompletionsAPI = class {
|
|
|
5626
5736
|
type: typeof errObj?.type === "string" ? errObj.type : "server_error",
|
|
5627
5737
|
param: errObj?.param === void 0 ? null : errObj.param,
|
|
5628
5738
|
code: errObj?.code === void 0 ? null : errObj.code
|
|
5739
|
+
}, {
|
|
5740
|
+
requestId
|
|
5629
5741
|
});
|
|
5630
5742
|
}
|
|
5631
5743
|
yield chunk;
|
|
@@ -5644,6 +5756,8 @@ var ChatCompletionsAPI = class {
|
|
|
5644
5756
|
type: "server_error",
|
|
5645
5757
|
param: null,
|
|
5646
5758
|
code: "gateway_stream_interrupted"
|
|
5759
|
+
}, {
|
|
5760
|
+
requestId
|
|
5647
5761
|
});
|
|
5648
5762
|
}
|
|
5649
5763
|
}
|
|
@@ -9223,6 +9337,8 @@ export {
|
|
|
9223
9337
|
anonymousTokenProvider,
|
|
9224
9338
|
createMemoryStorage,
|
|
9225
9339
|
createWorkBuddyCloud,
|
|
9340
|
+
getModelCapability,
|
|
9341
|
+
getModelDisplayName,
|
|
9226
9342
|
shouldClearCredentials
|
|
9227
9343
|
};
|
|
9228
9344
|
//# sourceMappingURL=index.js.map
|