@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/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
|
|
112
|
+
throw new WorkBuddyCloudConfigError("createWorkBuddyCloud requires publishableKey.");
|
|
100
113
|
}
|
|
101
114
|
return Object.freeze({
|
|
102
|
-
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.
|
|
622
|
+
if (credentials.phone) body.phone_number = 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
|
-
|
|
603
|
-
|
|
643
|
+
const body = {};
|
|
644
|
+
if (credentials.phone) {
|
|
645
|
+
body.phone_number = 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
|
|
@@ -635,11 +681,13 @@ var AuthModule = class {
|
|
|
635
681
|
verificationId,
|
|
636
682
|
isExistingUser,
|
|
637
683
|
isUser: isExistingUser,
|
|
638
|
-
verify: /* @__PURE__ */ __name(({ token }) => this.verifyOtp({
|
|
684
|
+
verify: /* @__PURE__ */ __name(({ token, password }) => this.verifyOtp({
|
|
639
685
|
verificationId,
|
|
640
686
|
token,
|
|
641
687
|
email: credentials.email,
|
|
642
|
-
|
|
688
|
+
phone: credentials.phone,
|
|
689
|
+
isExistingUser,
|
|
690
|
+
password
|
|
643
691
|
}), "verify")
|
|
644
692
|
});
|
|
645
693
|
}
|
|
@@ -652,10 +700,14 @@ var AuthModule = class {
|
|
|
652
700
|
* 走登录还是注册由 `isExistingUser` 决定(`sendOtp` 的返回值)。刻意不做
|
|
653
701
|
* 「先试登录失败再试注册」的兜底:那会把「密码错」这类真实错误掩盖成一次
|
|
654
702
|
* 莫名的注册尝试。
|
|
703
|
+
*
|
|
704
|
+
* 登录侧邮箱与手机号共用 `username` 字段 —— 上游 `SignInRequest.username`
|
|
705
|
+
* 承载邮箱/手机/用户名三种形态(runtime-auth-design §3.2)。
|
|
655
706
|
*/
|
|
656
707
|
async verifyOtp(params) {
|
|
657
|
-
|
|
658
|
-
|
|
708
|
+
const identifier = params.phone ?? params.email ?? "";
|
|
709
|
+
if (!params.verificationId || !params.token || !identifier) {
|
|
710
|
+
return fail(badRequest("verifyOtp requires verificationId, token and either email or phone"));
|
|
659
711
|
}
|
|
660
712
|
const verified = await this.request(AUTH_PATHS.verificationVerify, {
|
|
661
713
|
method: "POST",
|
|
@@ -674,12 +726,13 @@ var AuthModule = class {
|
|
|
674
726
|
}
|
|
675
727
|
if (params.isExistingUser) {
|
|
676
728
|
return this.postForSession(AUTH_PATHS.signIn, {
|
|
677
|
-
username:
|
|
729
|
+
username: identifier,
|
|
678
730
|
verification_token: verificationToken
|
|
679
731
|
});
|
|
680
732
|
}
|
|
681
733
|
return this.signUp({
|
|
682
734
|
email: params.email,
|
|
735
|
+
phone: params.phone,
|
|
683
736
|
password: params.password ?? "",
|
|
684
737
|
verificationToken
|
|
685
738
|
});
|
|
@@ -696,8 +749,13 @@ var AuthModule = class {
|
|
|
696
749
|
*
|
|
697
750
|
* SDK 不自己跳转(不写 `location.href`):跳转时机应由应用决定 —— 有的要
|
|
698
751
|
* 先存草稿,有的在 iframe 里要开弹窗。返回 url 交调用方处置。
|
|
752
|
+
*
|
|
753
|
+
* @deprecated Google 登录已下线,新应用不应再调用该方法。
|
|
699
754
|
*/
|
|
700
755
|
async signInWithOAuth(options) {
|
|
756
|
+
if (!this.oauthRelayBaseUrl) {
|
|
757
|
+
return fail(badRequest("signInWithOAuth requires oauthRelayBaseUrl"));
|
|
758
|
+
}
|
|
701
759
|
if (options.provider !== "google") {
|
|
702
760
|
return fail(badRequest("signInWithOAuth currently supports only google"));
|
|
703
761
|
}
|
|
@@ -712,6 +770,8 @@ var AuthModule = class {
|
|
|
712
770
|
*
|
|
713
771
|
* 在回调落地页调一次即可。`code` 缺失时返回 `null` 数据而**不是**错误 ——
|
|
714
772
|
* 落地页可能被直接访问(用户收藏了它),那不是失败。
|
|
773
|
+
*
|
|
774
|
+
* @deprecated Google 登录已下线,新应用不应再调用该方法。
|
|
715
775
|
*/
|
|
716
776
|
async handleOAuthCallback(search) {
|
|
717
777
|
const callbackInput = search ?? currentPageSearch();
|
|
@@ -946,7 +1006,11 @@ var AuthModule = class {
|
|
|
946
1006
|
// ------------------------------------------------------------------
|
|
947
1007
|
// 内部
|
|
948
1008
|
// ------------------------------------------------------------------
|
|
949
|
-
/**
|
|
1009
|
+
/**
|
|
1010
|
+
* 拼出平台 Relay 授权地址;state 由 Relay 自己签发、校验并一次性消费。
|
|
1011
|
+
*
|
|
1012
|
+
* @deprecated Google 登录已下线,仅保留给存量应用的回调落地页。
|
|
1013
|
+
*/
|
|
950
1014
|
async startRelayOAuth(options, redirectTo) {
|
|
951
1015
|
const callback = new URL(redirectTo);
|
|
952
1016
|
const relay = new URL(`${this.oauthRelayBaseUrl}/authorize`);
|
|
@@ -5140,9 +5204,42 @@ function pricingField(value) {
|
|
|
5140
5204
|
return Object.keys(pricing).length ? pricing : void 0;
|
|
5141
5205
|
}
|
|
5142
5206
|
__name(pricingField, "pricingField");
|
|
5207
|
+
function reasoningField(value) {
|
|
5208
|
+
if (!value || typeof value !== "object") return void 0;
|
|
5209
|
+
const raw = value;
|
|
5210
|
+
const result = {};
|
|
5211
|
+
const effort = stringField(raw.effort);
|
|
5212
|
+
if (effort !== void 0) result.effort = effort;
|
|
5213
|
+
const defaultEffort = stringField(raw.defaultEffort);
|
|
5214
|
+
if (defaultEffort !== void 0) result.defaultEffort = defaultEffort;
|
|
5215
|
+
if (Array.isArray(raw.supportedEfforts)) {
|
|
5216
|
+
result.supportedEfforts = raw.supportedEfforts.filter((item) => typeof item === "string");
|
|
5217
|
+
}
|
|
5218
|
+
const rawSummary = stringField(raw.summary);
|
|
5219
|
+
if (rawSummary !== void 0 && (rawSummary === "auto" || rawSummary === "concise" || rawSummary === "detailed")) {
|
|
5220
|
+
result.summary = rawSummary;
|
|
5221
|
+
}
|
|
5222
|
+
const canDisable = booleanField(raw.canDisableThinking);
|
|
5223
|
+
if (canDisable !== void 0) result.canDisableThinking = canDisable;
|
|
5224
|
+
return Object.keys(result).length > 0 ? result : void 0;
|
|
5225
|
+
}
|
|
5226
|
+
__name(reasoningField, "reasoningField");
|
|
5143
5227
|
function normalizeModel(raw) {
|
|
5144
5228
|
const id = stringField(raw.id, raw.ID);
|
|
5145
5229
|
if (!id) return null;
|
|
5230
|
+
const serverEnabled = booleanField(raw.enabled, raw.Enabled);
|
|
5231
|
+
const serverDisabled = booleanField(raw.disabled, raw.Disabled);
|
|
5232
|
+
let enabled;
|
|
5233
|
+
let disabled;
|
|
5234
|
+
if (serverEnabled !== void 0) {
|
|
5235
|
+
enabled = serverEnabled;
|
|
5236
|
+
if (serverDisabled !== void 0) disabled = serverDisabled;
|
|
5237
|
+
} else if (serverDisabled !== void 0) {
|
|
5238
|
+
disabled = serverDisabled;
|
|
5239
|
+
enabled = !serverDisabled;
|
|
5240
|
+
} else {
|
|
5241
|
+
enabled = true;
|
|
5242
|
+
}
|
|
5146
5243
|
return {
|
|
5147
5244
|
id,
|
|
5148
5245
|
name: stringField(raw.name, raw.Name) ?? id,
|
|
@@ -5185,7 +5282,10 @@ function normalizeModel(raw) {
|
|
|
5185
5282
|
...capabilitiesField(raw.capabilities ?? raw.Capabilities) ? {
|
|
5186
5283
|
capabilities: capabilitiesField(raw.capabilities ?? raw.Capabilities)
|
|
5187
5284
|
} : {},
|
|
5188
|
-
enabled
|
|
5285
|
+
enabled,
|
|
5286
|
+
...disabled !== void 0 ? {
|
|
5287
|
+
disabled
|
|
5288
|
+
} : {},
|
|
5189
5289
|
...booleanField(raw.isDefault, raw.IsDefault) !== void 0 ? {
|
|
5190
5290
|
isDefault: booleanField(raw.isDefault, raw.IsDefault)
|
|
5191
5291
|
} : {},
|
|
@@ -5194,10 +5294,55 @@ function normalizeModel(raw) {
|
|
|
5194
5294
|
} : {},
|
|
5195
5295
|
...pricingField(raw.pricing ?? raw.Pricing) ? {
|
|
5196
5296
|
pricing: pricingField(raw.pricing ?? raw.Pricing)
|
|
5297
|
+
} : {},
|
|
5298
|
+
// User-specified sparse fields: preserve explicit false/0, omit only when absent.
|
|
5299
|
+
...stringField(raw.credits, raw.Credits) ? {
|
|
5300
|
+
credits: stringField(raw.credits, raw.Credits)
|
|
5301
|
+
} : {},
|
|
5302
|
+
...numberField(raw.maxAllowedSize, raw.MaxAllowedSize) !== void 0 ? {
|
|
5303
|
+
maxAllowedSize: numberField(raw.maxAllowedSize, raw.MaxAllowedSize)
|
|
5304
|
+
} : {},
|
|
5305
|
+
...booleanField(raw.disabledMultimodal, raw.DisabledMultimodal) !== void 0 ? {
|
|
5306
|
+
disabledMultimodal: booleanField(raw.disabledMultimodal, raw.DisabledMultimodal)
|
|
5307
|
+
} : {},
|
|
5308
|
+
...booleanField(raw.supportsImages, raw.SupportsImages) !== void 0 ? {
|
|
5309
|
+
supportsImages: booleanField(raw.supportsImages, raw.SupportsImages)
|
|
5310
|
+
} : {},
|
|
5311
|
+
...booleanField(raw.supportsToolCall, raw.SupportsToolCall) !== void 0 ? {
|
|
5312
|
+
supportsToolCall: booleanField(raw.supportsToolCall, raw.SupportsToolCall)
|
|
5313
|
+
} : {},
|
|
5314
|
+
...booleanField(raw.supportsReasoning, raw.SupportsReasoning) !== void 0 ? {
|
|
5315
|
+
supportsReasoning: booleanField(raw.supportsReasoning, raw.SupportsReasoning)
|
|
5316
|
+
} : {},
|
|
5317
|
+
...booleanField(raw.onlyReasoning, raw.OnlyReasoning) !== void 0 ? {
|
|
5318
|
+
onlyReasoning: booleanField(raw.onlyReasoning, raw.OnlyReasoning)
|
|
5319
|
+
} : {},
|
|
5320
|
+
...reasoningField(raw.reasoning ?? raw.Reasoning) ? {
|
|
5321
|
+
reasoning: reasoningField(raw.reasoning ?? raw.Reasoning)
|
|
5322
|
+
} : {},
|
|
5323
|
+
...numberField(raw.temperature, raw.Temperature) !== void 0 ? {
|
|
5324
|
+
temperature: numberField(raw.temperature, raw.Temperature)
|
|
5325
|
+
} : {},
|
|
5326
|
+
...numberField(raw.top_k, raw.Top_K) !== void 0 ? {
|
|
5327
|
+
top_k: numberField(raw.top_k, raw.Top_K)
|
|
5328
|
+
} : {},
|
|
5329
|
+
...numberField(raw.top_p, raw.Top_P) !== void 0 ? {
|
|
5330
|
+
top_p: numberField(raw.top_p, raw.Top_P)
|
|
5331
|
+
} : {},
|
|
5332
|
+
...numberField(raw.repetition_penalty, raw.Repetition_Penalty) !== void 0 ? {
|
|
5333
|
+
repetition_penalty: numberField(raw.repetition_penalty, raw.Repetition_Penalty)
|
|
5197
5334
|
} : {}
|
|
5198
5335
|
};
|
|
5199
5336
|
}
|
|
5200
5337
|
__name(normalizeModel, "normalizeModel");
|
|
5338
|
+
function getModelDisplayName(model) {
|
|
5339
|
+
return model.name || model.id;
|
|
5340
|
+
}
|
|
5341
|
+
__name(getModelDisplayName, "getModelDisplayName");
|
|
5342
|
+
function getModelCapability(model, capability) {
|
|
5343
|
+
return model.capabilities?.[capability];
|
|
5344
|
+
}
|
|
5345
|
+
__name(getModelCapability, "getModelCapability");
|
|
5201
5346
|
var ModelsAPI = class {
|
|
5202
5347
|
static {
|
|
5203
5348
|
__name(this, "ModelsAPI");
|
|
@@ -5213,8 +5358,8 @@ var ModelsAPI = class {
|
|
|
5213
5358
|
*
|
|
5214
5359
|
* `id` is the value to pass as `model` to `chat.completions.create()`.
|
|
5215
5360
|
* Optional metadata is included only when the server explicitly provides
|
|
5216
|
-
* it; absence means unknown, not unsupported. The
|
|
5217
|
-
*
|
|
5361
|
+
* it; absence means unknown, not unsupported. The actual call result
|
|
5362
|
+
* is determined by the response, not by the directory entry.
|
|
5218
5363
|
*/
|
|
5219
5364
|
async list(signal) {
|
|
5220
5365
|
let response;
|
|
@@ -5487,7 +5632,10 @@ async function* iterSSEEvents(body, signal) {
|
|
|
5487
5632
|
__name(iterSSEEvents, "iterSSEEvents");
|
|
5488
5633
|
|
|
5489
5634
|
// src/modules/llm/chat.ts
|
|
5490
|
-
function extractSSEError(data) {
|
|
5635
|
+
function extractSSEError(data, requestId) {
|
|
5636
|
+
const init = requestId ? {
|
|
5637
|
+
requestId
|
|
5638
|
+
} : {};
|
|
5491
5639
|
try {
|
|
5492
5640
|
const parsed = JSON.parse(data);
|
|
5493
5641
|
if (parsed && typeof parsed === "object") {
|
|
@@ -5498,7 +5646,7 @@ function extractSSEError(data) {
|
|
|
5498
5646
|
type: typeof errorObj.type === "string" ? errorObj.type : "server_error",
|
|
5499
5647
|
param: errorObj.param === void 0 ? null : errorObj.param,
|
|
5500
5648
|
code: errorObj.code === void 0 ? null : errorObj.code
|
|
5501
|
-
});
|
|
5649
|
+
}, init);
|
|
5502
5650
|
}
|
|
5503
5651
|
}
|
|
5504
5652
|
} catch {
|
|
@@ -5508,7 +5656,7 @@ function extractSSEError(data) {
|
|
|
5508
5656
|
type: "server_error",
|
|
5509
5657
|
param: null,
|
|
5510
5658
|
code: null
|
|
5511
|
-
});
|
|
5659
|
+
}, init);
|
|
5512
5660
|
}
|
|
5513
5661
|
__name(extractSSEError, "extractSSEError");
|
|
5514
5662
|
var ChatCompletionsAPI = class {
|
|
@@ -5522,72 +5670,28 @@ var ChatCompletionsAPI = class {
|
|
|
5522
5670
|
this.fetch = fetch2;
|
|
5523
5671
|
}
|
|
5524
5672
|
create(input) {
|
|
5525
|
-
if (input.stream
|
|
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) {
|
|
5673
|
+
if (input.stream !== true) {
|
|
5535
5674
|
throw new CloudOpenAIError({
|
|
5536
|
-
message: "
|
|
5675
|
+
message: "stream must be true; non-streaming chat completions are not supported",
|
|
5537
5676
|
type: "invalid_request_error",
|
|
5538
|
-
param: "
|
|
5539
|
-
code: "
|
|
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"
|
|
5677
|
+
param: "stream",
|
|
5678
|
+
code: "request_stream_required"
|
|
5584
5679
|
});
|
|
5585
5680
|
}
|
|
5681
|
+
return this.createStreaming(input);
|
|
5586
5682
|
}
|
|
5587
5683
|
/**
|
|
5588
5684
|
* Streaming chat completion — returns an async generator of chunks.
|
|
5589
5685
|
*
|
|
5590
5686
|
* Reads the SSE stream incrementally, yielding ChatCompletionChunk objects.
|
|
5687
|
+
* `stream_options` is passed through unchanged when present.
|
|
5688
|
+
*
|
|
5689
|
+
* The `X-Request-Id` response header is captured and attached (as
|
|
5690
|
+
* `requestId`) to every `CloudOpenAIError` thrown from within the stream:
|
|
5691
|
+
* `event: error`, chunk-embedded error, JSON parse failure, and missing
|
|
5692
|
+
* `[DONE]` interruption. Non-2xx HTTP errors continue to go through
|
|
5693
|
+
* `httpError`, which independently extracts `X-Request-Id`.
|
|
5694
|
+
*
|
|
5591
5695
|
* Throws CloudOpenAIError on:
|
|
5592
5696
|
* - `event: error` in the stream
|
|
5593
5697
|
* - Stream ends without `[DONE]` (gateway_stream_interrupted)
|
|
@@ -5595,7 +5699,7 @@ var ChatCompletionsAPI = class {
|
|
|
5595
5699
|
* - Caller abort (AbortSignal) — exits silently, no throw
|
|
5596
5700
|
*/
|
|
5597
5701
|
async *createStreaming(input) {
|
|
5598
|
-
const { signal, ...body } = input;
|
|
5702
|
+
const { signal, conversationId, ...body } = input;
|
|
5599
5703
|
body.stream = true;
|
|
5600
5704
|
let response;
|
|
5601
5705
|
try {
|
|
@@ -5603,7 +5707,10 @@ var ChatCompletionsAPI = class {
|
|
|
5603
5707
|
method: "POST",
|
|
5604
5708
|
headers: {
|
|
5605
5709
|
Accept: "text/event-stream",
|
|
5606
|
-
"Content-Type": "application/json"
|
|
5710
|
+
"Content-Type": "application/json",
|
|
5711
|
+
...conversationId !== void 0 ? {
|
|
5712
|
+
"X-Conversation-ID": conversationId
|
|
5713
|
+
} : {}
|
|
5607
5714
|
},
|
|
5608
5715
|
body: JSON.stringify(body),
|
|
5609
5716
|
signal
|
|
@@ -5630,15 +5737,18 @@ var ChatCompletionsAPI = class {
|
|
|
5630
5737
|
type: "server_error",
|
|
5631
5738
|
param: null,
|
|
5632
5739
|
code: "gateway_invalid_response"
|
|
5740
|
+
}, {
|
|
5741
|
+
requestId: response.headers.get("x-request-id") ?? void 0
|
|
5633
5742
|
});
|
|
5634
5743
|
}
|
|
5744
|
+
const requestId = response.headers.get("x-request-id") ?? void 0;
|
|
5635
5745
|
let receivedDone = false;
|
|
5636
5746
|
let threw = false;
|
|
5637
5747
|
try {
|
|
5638
5748
|
for await (const sseEvent of iterSSEEvents(response.body, signal)) {
|
|
5639
5749
|
if (sseEvent.event === "error") {
|
|
5640
5750
|
threw = true;
|
|
5641
|
-
throw extractSSEError(sseEvent.data);
|
|
5751
|
+
throw extractSSEError(sseEvent.data, requestId);
|
|
5642
5752
|
}
|
|
5643
5753
|
if (sseEvent.event === null || sseEvent.event === "") {
|
|
5644
5754
|
if (sseEvent.data === SSE_DONE) {
|
|
@@ -5658,6 +5768,8 @@ var ChatCompletionsAPI = class {
|
|
|
5658
5768
|
type: "server_error",
|
|
5659
5769
|
param: null,
|
|
5660
5770
|
code: "gateway_invalid_response"
|
|
5771
|
+
}, {
|
|
5772
|
+
requestId
|
|
5661
5773
|
});
|
|
5662
5774
|
}
|
|
5663
5775
|
if (chunk && typeof chunk === "object" && "error" in chunk) {
|
|
@@ -5668,6 +5780,8 @@ var ChatCompletionsAPI = class {
|
|
|
5668
5780
|
type: typeof errObj?.type === "string" ? errObj.type : "server_error",
|
|
5669
5781
|
param: errObj?.param === void 0 ? null : errObj.param,
|
|
5670
5782
|
code: errObj?.code === void 0 ? null : errObj.code
|
|
5783
|
+
}, {
|
|
5784
|
+
requestId
|
|
5671
5785
|
});
|
|
5672
5786
|
}
|
|
5673
5787
|
yield chunk;
|
|
@@ -5686,6 +5800,8 @@ var ChatCompletionsAPI = class {
|
|
|
5686
5800
|
type: "server_error",
|
|
5687
5801
|
param: null,
|
|
5688
5802
|
code: "gateway_stream_interrupted"
|
|
5803
|
+
}, {
|
|
5804
|
+
requestId
|
|
5689
5805
|
});
|
|
5690
5806
|
}
|
|
5691
5807
|
}
|
|
@@ -9266,6 +9382,8 @@ __name(shouldClearCredentials, "shouldClearCredentials");
|
|
|
9266
9382
|
anonymousTokenProvider,
|
|
9267
9383
|
createMemoryStorage,
|
|
9268
9384
|
createWorkBuddyCloud,
|
|
9385
|
+
getModelCapability,
|
|
9386
|
+
getModelDisplayName,
|
|
9269
9387
|
shouldClearCredentials
|
|
9270
9388
|
});
|
|
9271
9389
|
//# sourceMappingURL=index.cjs.map
|