playkit-sdk 1.4.0-beta.3 → 1.6.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.
- package/README.md +9 -1
- package/dist/playkit-sdk.cjs.js +242 -1022
- package/dist/playkit-sdk.cjs.js.map +1 -1
- package/dist/playkit-sdk.d.ts +304 -309
- package/dist/playkit-sdk.esm.js +243 -1022
- package/dist/playkit-sdk.esm.js.map +1 -1
- package/dist/playkit-sdk.umd.js +242 -1022
- package/dist/playkit-sdk.umd.js.map +1 -1
- package/package.json +4 -4
package/dist/playkit-sdk.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* playkit-sdk v1.
|
|
2
|
+
* playkit-sdk v1.6.0
|
|
3
3
|
* PlayKit SDK for JavaScript
|
|
4
4
|
* @license SEE LICENSE IN LICENSE
|
|
5
5
|
*/
|
|
@@ -43,6 +43,48 @@ function createMultimodalMessage(role, text, images, audios) {
|
|
|
43
43
|
}
|
|
44
44
|
return { role, content };
|
|
45
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Convert an OpenAI-compatible tool call returned by the API into the canonical
|
|
48
|
+
* PlayKit message content part used for future requests.
|
|
49
|
+
*/
|
|
50
|
+
function createToolCallContentPart(toolCall) {
|
|
51
|
+
var _a;
|
|
52
|
+
let input = {};
|
|
53
|
+
const args = (_a = toolCall.function) === null || _a === void 0 ? void 0 : _a.arguments;
|
|
54
|
+
if (typeof args === 'string' && args.trim()) {
|
|
55
|
+
try {
|
|
56
|
+
input = JSON.parse(args);
|
|
57
|
+
}
|
|
58
|
+
catch (_b) {
|
|
59
|
+
input = args;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
type: 'tool-call',
|
|
64
|
+
toolCallId: toolCall.id,
|
|
65
|
+
toolName: toolCall.function.name,
|
|
66
|
+
input,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Create a canonical PlayKit tool-result content part.
|
|
71
|
+
*/
|
|
72
|
+
function createToolResultContentPart(toolCallId, toolName, result) {
|
|
73
|
+
if (typeof result === 'string') {
|
|
74
|
+
return {
|
|
75
|
+
type: 'tool-result',
|
|
76
|
+
toolCallId,
|
|
77
|
+
toolName,
|
|
78
|
+
output: { type: 'text', value: result },
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
type: 'tool-result',
|
|
83
|
+
toolCallId,
|
|
84
|
+
toolName,
|
|
85
|
+
output: { type: 'json', value: result },
|
|
86
|
+
};
|
|
87
|
+
}
|
|
46
88
|
/**
|
|
47
89
|
* Error types that can be thrown by the SDK
|
|
48
90
|
*/
|
|
@@ -826,7 +868,7 @@ class TokenStorage {
|
|
|
826
868
|
}
|
|
827
869
|
|
|
828
870
|
const SDK_TYPE = 'Javascript';
|
|
829
|
-
const SDK_VERSION = '"1.
|
|
871
|
+
const SDK_VERSION = '"1.6.0"';
|
|
830
872
|
function getSDKHeaders() {
|
|
831
873
|
return {
|
|
832
874
|
'X-SDK-Type': SDK_TYPE,
|
|
@@ -834,867 +876,6 @@ function getSDKHeaders() {
|
|
|
834
876
|
};
|
|
835
877
|
}
|
|
836
878
|
|
|
837
|
-
/**
|
|
838
|
-
* Authentication Flow Manager
|
|
839
|
-
* Manages the headless authentication flow with automatic UI
|
|
840
|
-
*
|
|
841
|
-
* @deprecated This class is deprecated. Use DeviceAuthFlowManager instead.
|
|
842
|
-
* Will be removed in v2.0
|
|
843
|
-
*/
|
|
844
|
-
// i18n translations
|
|
845
|
-
const translations$2 = {
|
|
846
|
-
en: {
|
|
847
|
-
signIn: 'Sign In / Register',
|
|
848
|
-
signInSubtitle: 'This game uses PlayKit for cost management.\nIf you don\'t have an account, we\'ll automatically register you. Sign up and get free AI game credits!',
|
|
849
|
-
email: 'Email',
|
|
850
|
-
phone: 'Phone',
|
|
851
|
-
emailPlaceholder: 'Enter your email address',
|
|
852
|
-
phonePlaceholder: 'Enter your phone number (+86 Only)',
|
|
853
|
-
sendCode: 'Send Code',
|
|
854
|
-
enterCode: 'Enter Code',
|
|
855
|
-
enterCodeSubtitle: "We've sent a 6-digit code to your",
|
|
856
|
-
verify: 'Verify',
|
|
857
|
-
pleaseEnterEmail: 'Please enter your email address',
|
|
858
|
-
pleaseEnterPhone: 'Please enter your phone number',
|
|
859
|
-
enterAllDigits: 'Please enter all 6 digits',
|
|
860
|
-
verificationFailed: 'Verification failed',
|
|
861
|
-
failedToSendCode: 'Failed to send code',
|
|
862
|
-
invalidCode: 'Invalid verification code',
|
|
863
|
-
},
|
|
864
|
-
zh: {
|
|
865
|
-
signIn: '登录/注册',
|
|
866
|
-
signInSubtitle: '本游戏使用PlayKit进行成本管理。\n如果您没有帐户,我们会为您自动注册。注册即送AI游戏积分!',
|
|
867
|
-
email: '邮箱',
|
|
868
|
-
phone: '手机',
|
|
869
|
-
emailPlaceholder: '请输入邮箱地址',
|
|
870
|
-
phonePlaceholder: '请输入手机号(仅限 +86)',
|
|
871
|
-
sendCode: '发送验证码',
|
|
872
|
-
enterCode: '输入验证码',
|
|
873
|
-
enterCodeSubtitle: '我们已向您发送了 6 位验证码:',
|
|
874
|
-
verify: '验证',
|
|
875
|
-
pleaseEnterEmail: '请输入邮箱地址',
|
|
876
|
-
pleaseEnterPhone: '请输入手机号',
|
|
877
|
-
enterAllDigits: '请输入完整的 6 位验证码',
|
|
878
|
-
verificationFailed: '验证失败',
|
|
879
|
-
failedToSendCode: '发送验证码失败',
|
|
880
|
-
invalidCode: '验证码无效',
|
|
881
|
-
},
|
|
882
|
-
'zh-TW': {
|
|
883
|
-
signIn: '登入/註冊',
|
|
884
|
-
signInSubtitle: '本遊戲使用PlayKit進行成本管理。\n如果您沒有帳戶,我們會為您自動註冊。註冊即送AI遊戲積分!',
|
|
885
|
-
email: '電子郵件',
|
|
886
|
-
phone: '手機',
|
|
887
|
-
emailPlaceholder: '請輸入電子郵件地址',
|
|
888
|
-
phonePlaceholder: '請輸入手機號碼(僅限 +86)',
|
|
889
|
-
sendCode: '發送驗證碼',
|
|
890
|
-
enterCode: '輸入驗證碼',
|
|
891
|
-
enterCodeSubtitle: '我們已向您發送了 6 位驗證碼:',
|
|
892
|
-
verify: '驗證',
|
|
893
|
-
pleaseEnterEmail: '請輸入電子郵件地址',
|
|
894
|
-
pleaseEnterPhone: '請輸入手機號碼',
|
|
895
|
-
enterAllDigits: '請輸入完整的 6 位驗證碼',
|
|
896
|
-
verificationFailed: '驗證失敗',
|
|
897
|
-
failedToSendCode: '發送驗證碼失敗',
|
|
898
|
-
invalidCode: '驗證碼無效',
|
|
899
|
-
},
|
|
900
|
-
ja: {
|
|
901
|
-
signIn: 'サインイン/登録',
|
|
902
|
-
signInSubtitle: 'このゲームはPlayKitでコスト管理を行っています。\nアカウントをお持ちでない場合は、自動的に登録します。登録するとAIゲームクレジットがもらえます!',
|
|
903
|
-
email: 'メール',
|
|
904
|
-
phone: '電話',
|
|
905
|
-
emailPlaceholder: 'メールアドレスを入力してください',
|
|
906
|
-
phonePlaceholder: '電話番号を入力してください(+86のみ)',
|
|
907
|
-
sendCode: '認証コードを送信',
|
|
908
|
-
enterCode: '認証コードを入力',
|
|
909
|
-
enterCodeSubtitle: '6桁の認証コードを送信しました:',
|
|
910
|
-
verify: '検証',
|
|
911
|
-
pleaseEnterEmail: 'メールアドレスを入力してください',
|
|
912
|
-
pleaseEnterPhone: '電話番号を入力してください',
|
|
913
|
-
enterAllDigits: '6桁すべて入力してください',
|
|
914
|
-
verificationFailed: '検証に失敗しました',
|
|
915
|
-
failedToSendCode: '認証コードの送信に失敗しました',
|
|
916
|
-
invalidCode: '認証コードが無効です',
|
|
917
|
-
},
|
|
918
|
-
ko: {
|
|
919
|
-
signIn: '로그인/가입',
|
|
920
|
-
signInSubtitle: '이 게임은 PlayKit으로 비용 관리를 합니다.\n계정이 없으시면 자동으로 등록해 드립니다. 가입하면 AI 게임 크레딧을 받으세요!',
|
|
921
|
-
email: '이메일',
|
|
922
|
-
phone: '전화',
|
|
923
|
-
emailPlaceholder: '이메일 주소를 입력하세요',
|
|
924
|
-
phonePlaceholder: '전화번호를 입력하세요(+86만 지원)',
|
|
925
|
-
sendCode: '인증 코드 전송',
|
|
926
|
-
enterCode: '인증 코드 입력',
|
|
927
|
-
enterCodeSubtitle: '6자리 인증 코드를 보냈습니다:',
|
|
928
|
-
verify: '확인',
|
|
929
|
-
pleaseEnterEmail: '이메일 주소를 입력하세요',
|
|
930
|
-
pleaseEnterPhone: '전화번호를 입력하세요',
|
|
931
|
-
enterAllDigits: '6자리를 모두 입력하세요',
|
|
932
|
-
verificationFailed: '인증 실패',
|
|
933
|
-
failedToSendCode: '인증 코드 전송 실패',
|
|
934
|
-
invalidCode: '인증 코드가 잘못되었습니다',
|
|
935
|
-
},
|
|
936
|
-
};
|
|
937
|
-
class AuthFlowManager extends EventEmitter {
|
|
938
|
-
constructor(baseURL) {
|
|
939
|
-
super();
|
|
940
|
-
this.currentSessionId = null;
|
|
941
|
-
this._uiContainer = null;
|
|
942
|
-
this._isSuccess = false;
|
|
943
|
-
this.currentLanguage = 'en';
|
|
944
|
-
// UI Elements
|
|
945
|
-
this.modal = null;
|
|
946
|
-
this.identifierPanel = null;
|
|
947
|
-
this.verificationPanel = null;
|
|
948
|
-
this.loadingOverlay = null;
|
|
949
|
-
this.otpInstance = null;
|
|
950
|
-
// @ts-ignore - replaced at build time
|
|
951
|
-
this.baseURL = baseURL || "https://api.playkit.ai";
|
|
952
|
-
this.currentLanguage = this.detectLanguage();
|
|
953
|
-
}
|
|
954
|
-
/**
|
|
955
|
-
* Detect browser language (safe for Node.js environment)
|
|
956
|
-
*/
|
|
957
|
-
detectLanguage() {
|
|
958
|
-
// Check if running in browser environment
|
|
959
|
-
if (typeof window === 'undefined' || typeof navigator === 'undefined') {
|
|
960
|
-
return 'en'; // Default to English in Node.js environment
|
|
961
|
-
}
|
|
962
|
-
try {
|
|
963
|
-
const browserLang = navigator.language.toLowerCase();
|
|
964
|
-
// Match language codes
|
|
965
|
-
if (browserLang.startsWith('zh-tw') || browserLang.startsWith('zh-hk')) {
|
|
966
|
-
return 'zh-TW'; // Traditional Chinese
|
|
967
|
-
}
|
|
968
|
-
else if (browserLang.startsWith('zh')) {
|
|
969
|
-
return 'zh'; // Simplified Chinese
|
|
970
|
-
}
|
|
971
|
-
else if (browserLang.startsWith('ja')) {
|
|
972
|
-
return 'ja'; // Japanese
|
|
973
|
-
}
|
|
974
|
-
else if (browserLang.startsWith('ko')) {
|
|
975
|
-
return 'ko'; // Korean
|
|
976
|
-
}
|
|
977
|
-
else {
|
|
978
|
-
return 'en'; // Default to English
|
|
979
|
-
}
|
|
980
|
-
}
|
|
981
|
-
catch (error) {
|
|
982
|
-
// Fallback to English if detection fails
|
|
983
|
-
return 'en';
|
|
984
|
-
}
|
|
985
|
-
}
|
|
986
|
-
/**
|
|
987
|
-
* Get translated text
|
|
988
|
-
*/
|
|
989
|
-
t(key) {
|
|
990
|
-
return translations$2[this.currentLanguage][key];
|
|
991
|
-
}
|
|
992
|
-
/**
|
|
993
|
-
* Start the authentication flow
|
|
994
|
-
* Returns a promise that resolves with the JWT token
|
|
995
|
-
*/
|
|
996
|
-
async startFlow() {
|
|
997
|
-
return new Promise((resolve, reject) => {
|
|
998
|
-
// Create and show UI
|
|
999
|
-
this.createUI();
|
|
1000
|
-
this.showModal();
|
|
1001
|
-
// Listen for success/failure
|
|
1002
|
-
this.once('success', (token) => {
|
|
1003
|
-
this.hideModal();
|
|
1004
|
-
resolve(token);
|
|
1005
|
-
});
|
|
1006
|
-
this.once('error', (error) => {
|
|
1007
|
-
this.hideModal();
|
|
1008
|
-
reject(error);
|
|
1009
|
-
});
|
|
1010
|
-
// Set default auth type based on region
|
|
1011
|
-
this.setDefaultAuthTypeByRegion().catch((err) => {
|
|
1012
|
-
console.error('[PlayKit Auth] Failed to detect region:', err);
|
|
1013
|
-
});
|
|
1014
|
-
});
|
|
1015
|
-
}
|
|
1016
|
-
/**
|
|
1017
|
-
* Create the authentication UI
|
|
1018
|
-
*/
|
|
1019
|
-
createUI() {
|
|
1020
|
-
// Create modal container
|
|
1021
|
-
this.modal = document.createElement('div');
|
|
1022
|
-
this.modal.className = 'playkit-auth-modal';
|
|
1023
|
-
this.modal.innerHTML = `
|
|
1024
|
-
<div class="playkit-auth-overlay"></div>
|
|
1025
|
-
<div class="playkit-auth-container">
|
|
1026
|
-
<!-- Identifier Panel -->
|
|
1027
|
-
<div class="playkit-auth-panel" id="playkit-identifier-panel">
|
|
1028
|
-
<div class="playkit-auth-header">
|
|
1029
|
-
<h2>${this.t('signIn')}</h2>
|
|
1030
|
-
<p>${this.t('signInSubtitle')}</p>
|
|
1031
|
-
</div>
|
|
1032
|
-
|
|
1033
|
-
<div class="playkit-auth-toggle">
|
|
1034
|
-
<label class="playkit-toggle-option">
|
|
1035
|
-
<input type="radio" name="auth-type" value="email" checked>
|
|
1036
|
-
<span>${this.t('email')}</span>
|
|
1037
|
-
</label>
|
|
1038
|
-
<label class="playkit-toggle-option">
|
|
1039
|
-
<input type="radio" name="auth-type" value="phone">
|
|
1040
|
-
<span>${this.t('phone')}</span>
|
|
1041
|
-
</label>
|
|
1042
|
-
</div>
|
|
1043
|
-
|
|
1044
|
-
<div class="playkit-auth-input-group">
|
|
1045
|
-
<div class="playkit-input-wrapper">
|
|
1046
|
-
<svg class="playkit-input-icon" id="playkit-identifier-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
1047
|
-
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path>
|
|
1048
|
-
<polyline points="22,6 12,13 2,6"></polyline>
|
|
1049
|
-
</svg>
|
|
1050
|
-
<input
|
|
1051
|
-
type="text"
|
|
1052
|
-
id="playkit-identifier-input"
|
|
1053
|
-
placeholder="${this.t('emailPlaceholder')}"
|
|
1054
|
-
autocomplete="off"
|
|
1055
|
-
>
|
|
1056
|
-
</div>
|
|
1057
|
-
</div>
|
|
1058
|
-
|
|
1059
|
-
<button class="playkit-auth-button" id="playkit-send-code-btn">
|
|
1060
|
-
${this.t('sendCode')}
|
|
1061
|
-
</button>
|
|
1062
|
-
|
|
1063
|
-
<div class="playkit-auth-error" id="playkit-error-text"></div>
|
|
1064
|
-
</div>
|
|
1065
|
-
|
|
1066
|
-
<!-- Verification Panel -->
|
|
1067
|
-
<div class="playkit-auth-panel" id="playkit-verification-panel" style="display: none;">
|
|
1068
|
-
<div class="playkit-auth-header">
|
|
1069
|
-
<button class="playkit-back-button" id="playkit-back-btn">
|
|
1070
|
-
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
1071
|
-
<path d="M19 12H5M12 19l-7-7 7-7"/>
|
|
1072
|
-
</svg>
|
|
1073
|
-
</button>
|
|
1074
|
-
<h2>${this.t('enterCode')}</h2>
|
|
1075
|
-
<p>${this.t('enterCodeSubtitle')} <span id="playkit-identifier-display"></span></p>
|
|
1076
|
-
</div>
|
|
1077
|
-
|
|
1078
|
-
<div class="playkit-auth-input-group">
|
|
1079
|
-
<div class="playkit-code-inputs">
|
|
1080
|
-
<input type="number" maxlength="1" class="playkit-code-input" data-index="0">
|
|
1081
|
-
<input type="number" maxlength="1" class="playkit-code-input" data-index="1">
|
|
1082
|
-
<input type="number" maxlength="1" class="playkit-code-input" data-index="2">
|
|
1083
|
-
<input type="number" maxlength="1" class="playkit-code-input" data-index="3">
|
|
1084
|
-
<input type="number" maxlength="1" class="playkit-code-input" data-index="4">
|
|
1085
|
-
<input type="number" maxlength="1" class="playkit-code-input" data-index="5">
|
|
1086
|
-
</div>
|
|
1087
|
-
</div>
|
|
1088
|
-
|
|
1089
|
-
<button class="playkit-auth-button" id="playkit-verify-btn">
|
|
1090
|
-
${this.t('verify')}
|
|
1091
|
-
</button>
|
|
1092
|
-
|
|
1093
|
-
<div class="playkit-auth-error" id="playkit-verify-error-text"></div>
|
|
1094
|
-
</div>
|
|
1095
|
-
|
|
1096
|
-
<!-- Loading Overlay -->
|
|
1097
|
-
<div class="playkit-loading-overlay" id="playkit-loading-overlay" style="display: none;">
|
|
1098
|
-
<div class="playkit-spinner"></div>
|
|
1099
|
-
</div>
|
|
1100
|
-
</div>
|
|
1101
|
-
`;
|
|
1102
|
-
// Add styles and load VanillaOTP
|
|
1103
|
-
this.addStyles();
|
|
1104
|
-
this.loadVanillaOTP();
|
|
1105
|
-
// Append to body
|
|
1106
|
-
document.body.appendChild(this.modal);
|
|
1107
|
-
// Get references
|
|
1108
|
-
this.identifierPanel = document.getElementById('playkit-identifier-panel');
|
|
1109
|
-
this.verificationPanel = document.getElementById('playkit-verification-panel');
|
|
1110
|
-
this.loadingOverlay = document.getElementById('playkit-loading-overlay');
|
|
1111
|
-
// Setup event listeners
|
|
1112
|
-
this.setupEventListeners();
|
|
1113
|
-
}
|
|
1114
|
-
/**
|
|
1115
|
-
* Load VanillaOTP library
|
|
1116
|
-
*/
|
|
1117
|
-
loadVanillaOTP() {
|
|
1118
|
-
// Check if VanillaOTP is already loaded
|
|
1119
|
-
if (window.VanillaOTP)
|
|
1120
|
-
return;
|
|
1121
|
-
// Inject VanillaOTP script
|
|
1122
|
-
const script = document.createElement('script');
|
|
1123
|
-
script.textContent = `"use strict";var VanillaOTP=function(t,e=null){if(this.emptyChar=" ","string"==typeof t)this.container=document.querySelector(t);else{if(!(t instanceof Element))return;this.container=t}e&&("string"==typeof e?this.updateTo=document.querySelector(e)||null:e instanceof Element?this.updateTo=e:this.updateTo=null),this.inputs=Array.from(this.container.querySelectorAll("input[type=text], input[type=number], input[type=password]"));let n=this,u=n.inputs.length;for(let i=0;i<u;i++){let l=n.inputs[i];l.addEventListener("input",function(){if(isNaN(l.value))return l.value=l.dataset.otpInputRestore||"",n._updateValue();if(0==l.value.length)return n._saveInputValue(i);if(1==l.value.length){n._saveInputValue(i),n._updateValue(),i+1<u&&n.inputs[i+1].focus();return}if(i==u-1)return n._setInputValue(i,l.value);let t=l.value.split("");for(let e=0;e<t.length&&!(e+i>=u);e++)n._setInputValue(e+i,t[e]);let a=Math.min(u-1,i+t.length);n.inputs[a].focus()}),l.addEventListener("keydown",function(t){if(8==t.keyCode&&""==l.value&&0!=i){n._setInputValue(i-1,""),n.inputs[i-1].focus();return}if(46==t.keyCode&&i!=u-1){let e=l.selectionStart||0;for(let a=i+e;a<u-1;a++)n._setInputValue(a,n.inputs[a+1].value);n._setInputValue(u-1,""),l.selectionStart&&(l.selectionStart=e),t.preventDefault();return}if(37==t.keyCode&&(null==l.selectionStart||0==l.selectionStart)){i>0&&(t.preventDefault(),n.inputs[i-1].focus(),n.inputs[i-1].select());return}if(39==t.keyCode&&(null==l.selectionStart||l.selectionEnd==l.value.length)){i+1<u&&(t.preventDefault(),n.inputs[i+1].focus(),n.inputs[i+1].select());return}})}};VanillaOTP.prototype.setEmptyChar=function(t){this.emptyChar=t},VanillaOTP.prototype.getValue=function(){let t="",e=this;return this.inputs.forEach(function(n){t+=""==n.value?e.emptyChar:n.value}),t},VanillaOTP.prototype.setValue=function(t){if(isNaN(t)){console.error("Please enter an integer value.");return}let e=(t=""+t).split("");for(let n=0;n<this.inputs.length;n++)this._setInputValue(n,e[n]||"")},VanillaOTP.prototype._setInputValue=function(t,e){return isNaN(e)?console.error("Please enter an integer value."):this.inputs[t]?void(this.inputs[t].value=String(e).substring(0,1),this._saveInputValue(t),this._updateValue()):console.error("Index not found.")},VanillaOTP.prototype._saveInputValue=function(t,e){if(!this.inputs[t])return console.error("Index not found.");this.inputs[t].dataset.otpInputRestore=e||this.inputs[t].value},VanillaOTP.prototype._updateValue=function(){this.updateTo&&(this.updateTo.value=this.getValue())};`;
|
|
1124
|
-
document.head.appendChild(script);
|
|
1125
|
-
}
|
|
1126
|
-
/**
|
|
1127
|
-
* Add CSS styles to the page
|
|
1128
|
-
*/
|
|
1129
|
-
addStyles() {
|
|
1130
|
-
const styleId = 'playkit-auth-styles';
|
|
1131
|
-
if (document.getElementById(styleId))
|
|
1132
|
-
return;
|
|
1133
|
-
const style = document.createElement('style');
|
|
1134
|
-
style.id = styleId;
|
|
1135
|
-
style.textContent = `
|
|
1136
|
-
.playkit-auth-modal {
|
|
1137
|
-
position: fixed;
|
|
1138
|
-
top: 0;
|
|
1139
|
-
left: 0;
|
|
1140
|
-
right: 0;
|
|
1141
|
-
bottom: 0;
|
|
1142
|
-
z-index: 999999;
|
|
1143
|
-
display: flex;
|
|
1144
|
-
justify-content: center;
|
|
1145
|
-
align-items: center;
|
|
1146
|
-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
1147
|
-
}
|
|
1148
|
-
|
|
1149
|
-
.playkit-auth-overlay {
|
|
1150
|
-
position: absolute;
|
|
1151
|
-
top: 0;
|
|
1152
|
-
left: 0;
|
|
1153
|
-
right: 0;
|
|
1154
|
-
bottom: 0;
|
|
1155
|
-
background: rgba(0, 0, 0, 0.8);
|
|
1156
|
-
}
|
|
1157
|
-
|
|
1158
|
-
.playkit-auth-container {
|
|
1159
|
-
position: relative;
|
|
1160
|
-
background: #fff;
|
|
1161
|
-
border: 1px solid rgba(0, 0, 0, 0.1);
|
|
1162
|
-
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.05);
|
|
1163
|
-
width: 90%;
|
|
1164
|
-
max-width: 320px;
|
|
1165
|
-
overflow: hidden;
|
|
1166
|
-
}
|
|
1167
|
-
|
|
1168
|
-
.playkit-auth-panel {
|
|
1169
|
-
padding: 24px;
|
|
1170
|
-
}
|
|
1171
|
-
|
|
1172
|
-
.playkit-auth-header {
|
|
1173
|
-
text-align: center;
|
|
1174
|
-
margin-bottom: 20px;
|
|
1175
|
-
position: relative;
|
|
1176
|
-
}
|
|
1177
|
-
|
|
1178
|
-
.playkit-auth-header h2 {
|
|
1179
|
-
margin: 0 0 8px 0;
|
|
1180
|
-
font-size: 14px;
|
|
1181
|
-
font-weight: 600;
|
|
1182
|
-
color: #171717;
|
|
1183
|
-
}
|
|
1184
|
-
|
|
1185
|
-
.playkit-auth-header p {
|
|
1186
|
-
margin: 0;
|
|
1187
|
-
font-size: 14px;
|
|
1188
|
-
color: #666;
|
|
1189
|
-
line-height: 1.5;
|
|
1190
|
-
}
|
|
1191
|
-
|
|
1192
|
-
.playkit-back-button {
|
|
1193
|
-
position: absolute;
|
|
1194
|
-
left: 0;
|
|
1195
|
-
top: 0;
|
|
1196
|
-
background: transparent;
|
|
1197
|
-
border: none;
|
|
1198
|
-
cursor: pointer;
|
|
1199
|
-
padding: 4px;
|
|
1200
|
-
color: #666;
|
|
1201
|
-
transition: background-color 0.2s ease, color 0.2s ease;
|
|
1202
|
-
}
|
|
1203
|
-
|
|
1204
|
-
.playkit-back-button:hover {
|
|
1205
|
-
background: #f5f5f5;
|
|
1206
|
-
color: #171717;
|
|
1207
|
-
}
|
|
1208
|
-
|
|
1209
|
-
.playkit-auth-toggle {
|
|
1210
|
-
display: flex;
|
|
1211
|
-
background: #f5f5f5;
|
|
1212
|
-
padding: 2px;
|
|
1213
|
-
margin-bottom: 20px;
|
|
1214
|
-
gap: 2px;
|
|
1215
|
-
}
|
|
1216
|
-
|
|
1217
|
-
.playkit-toggle-option {
|
|
1218
|
-
flex: 1;
|
|
1219
|
-
display: flex;
|
|
1220
|
-
justify-content: center;
|
|
1221
|
-
align-items: center;
|
|
1222
|
-
padding: 10px 16px;
|
|
1223
|
-
cursor: pointer;
|
|
1224
|
-
transition: background-color 0.2s ease;
|
|
1225
|
-
}
|
|
1226
|
-
|
|
1227
|
-
.playkit-toggle-option input {
|
|
1228
|
-
display: none;
|
|
1229
|
-
}
|
|
1230
|
-
|
|
1231
|
-
.playkit-toggle-option span {
|
|
1232
|
-
font-size: 14px;
|
|
1233
|
-
font-weight: 500;
|
|
1234
|
-
color: #666;
|
|
1235
|
-
transition: color 0.2s ease;
|
|
1236
|
-
}
|
|
1237
|
-
|
|
1238
|
-
.playkit-toggle-option input:checked + span {
|
|
1239
|
-
color: #fff;
|
|
1240
|
-
}
|
|
1241
|
-
|
|
1242
|
-
.playkit-toggle-option:has(input:checked) {
|
|
1243
|
-
background: #171717;
|
|
1244
|
-
}
|
|
1245
|
-
|
|
1246
|
-
.playkit-auth-input-group {
|
|
1247
|
-
margin-bottom: 20px;
|
|
1248
|
-
}
|
|
1249
|
-
|
|
1250
|
-
.playkit-input-wrapper {
|
|
1251
|
-
position: relative;
|
|
1252
|
-
display: flex;
|
|
1253
|
-
align-items: center;
|
|
1254
|
-
}
|
|
1255
|
-
|
|
1256
|
-
.playkit-input-icon {
|
|
1257
|
-
position: absolute;
|
|
1258
|
-
left: 12px;
|
|
1259
|
-
color: #999;
|
|
1260
|
-
pointer-events: none;
|
|
1261
|
-
}
|
|
1262
|
-
|
|
1263
|
-
.playkit-input-wrapper input {
|
|
1264
|
-
width: 100%;
|
|
1265
|
-
padding: 10px 12px 10px 44px;
|
|
1266
|
-
border: 1px solid #e5e7eb;
|
|
1267
|
-
font-size: 14px;
|
|
1268
|
-
transition: border-color 0.2s ease;
|
|
1269
|
-
box-sizing: border-box;
|
|
1270
|
-
background: #fff;
|
|
1271
|
-
}
|
|
1272
|
-
|
|
1273
|
-
.playkit-input-wrapper input:hover {
|
|
1274
|
-
border-color: #d4d4d4;
|
|
1275
|
-
}
|
|
1276
|
-
|
|
1277
|
-
.playkit-input-wrapper input:focus {
|
|
1278
|
-
outline: none;
|
|
1279
|
-
border-color: #171717;
|
|
1280
|
-
}
|
|
1281
|
-
|
|
1282
|
-
.playkit-code-inputs {
|
|
1283
|
-
display: flex;
|
|
1284
|
-
gap: 8px;
|
|
1285
|
-
justify-content: center;
|
|
1286
|
-
}
|
|
1287
|
-
|
|
1288
|
-
.playkit-code-input {
|
|
1289
|
-
width: 40px !important;
|
|
1290
|
-
height: 48px;
|
|
1291
|
-
text-align: center;
|
|
1292
|
-
font-size: 20px;
|
|
1293
|
-
font-weight: 600;
|
|
1294
|
-
border: 1px solid #e5e7eb !important;
|
|
1295
|
-
padding: 0 !important;
|
|
1296
|
-
transition: border-color 0.2s ease;
|
|
1297
|
-
background: #fff;
|
|
1298
|
-
-moz-appearance: textfield;
|
|
1299
|
-
}
|
|
1300
|
-
|
|
1301
|
-
.playkit-code-input::-webkit-outer-spin-button,
|
|
1302
|
-
.playkit-code-input::-webkit-inner-spin-button {
|
|
1303
|
-
-webkit-appearance: none;
|
|
1304
|
-
margin: 0;
|
|
1305
|
-
}
|
|
1306
|
-
|
|
1307
|
-
.playkit-code-input:hover {
|
|
1308
|
-
border-color: #d4d4d4 !important;
|
|
1309
|
-
}
|
|
1310
|
-
|
|
1311
|
-
.playkit-code-input:focus {
|
|
1312
|
-
outline: none;
|
|
1313
|
-
border-color: #171717 !important;
|
|
1314
|
-
}
|
|
1315
|
-
|
|
1316
|
-
.playkit-auth-button {
|
|
1317
|
-
width: 100%;
|
|
1318
|
-
padding: 10px 16px;
|
|
1319
|
-
background: #171717;
|
|
1320
|
-
color: white;
|
|
1321
|
-
border: none;
|
|
1322
|
-
font-size: 14px;
|
|
1323
|
-
font-weight: 500;
|
|
1324
|
-
cursor: pointer;
|
|
1325
|
-
transition: background 0.2s ease;
|
|
1326
|
-
}
|
|
1327
|
-
|
|
1328
|
-
.playkit-auth-button:hover:not(:disabled) {
|
|
1329
|
-
background: #404040;
|
|
1330
|
-
}
|
|
1331
|
-
|
|
1332
|
-
.playkit-auth-button:active:not(:disabled) {
|
|
1333
|
-
background: #0a0a0a;
|
|
1334
|
-
}
|
|
1335
|
-
|
|
1336
|
-
.playkit-auth-button:disabled {
|
|
1337
|
-
background: #e5e7eb;
|
|
1338
|
-
color: #999;
|
|
1339
|
-
cursor: not-allowed;
|
|
1340
|
-
}
|
|
1341
|
-
|
|
1342
|
-
.playkit-auth-error {
|
|
1343
|
-
margin-top: 16px;
|
|
1344
|
-
padding: 12px 16px;
|
|
1345
|
-
background: #fef2f2;
|
|
1346
|
-
border: 1px solid #fecaca;
|
|
1347
|
-
color: #dc2626;
|
|
1348
|
-
font-size: 13px;
|
|
1349
|
-
text-align: left;
|
|
1350
|
-
display: none;
|
|
1351
|
-
}
|
|
1352
|
-
|
|
1353
|
-
.playkit-auth-error.show {
|
|
1354
|
-
display: block;
|
|
1355
|
-
}
|
|
1356
|
-
|
|
1357
|
-
.playkit-loading-overlay {
|
|
1358
|
-
position: absolute;
|
|
1359
|
-
top: 0;
|
|
1360
|
-
left: 0;
|
|
1361
|
-
right: 0;
|
|
1362
|
-
bottom: 0;
|
|
1363
|
-
background: rgba(255, 255, 255, 0.96);
|
|
1364
|
-
display: flex;
|
|
1365
|
-
justify-content: center;
|
|
1366
|
-
align-items: center;
|
|
1367
|
-
}
|
|
1368
|
-
|
|
1369
|
-
.playkit-spinner {
|
|
1370
|
-
width: 24px;
|
|
1371
|
-
height: 24px;
|
|
1372
|
-
border: 2px solid #e5e7eb;
|
|
1373
|
-
border-top: 2px solid #171717;
|
|
1374
|
-
border-radius: 50%;
|
|
1375
|
-
animation: playkit-spin 1s linear infinite;
|
|
1376
|
-
}
|
|
1377
|
-
|
|
1378
|
-
@keyframes playkit-spin {
|
|
1379
|
-
0% { transform: rotate(0deg); }
|
|
1380
|
-
100% { transform: rotate(360deg); }
|
|
1381
|
-
}
|
|
1382
|
-
|
|
1383
|
-
@media (max-width: 480px) {
|
|
1384
|
-
.playkit-auth-container {
|
|
1385
|
-
width: 95%;
|
|
1386
|
-
max-width: none;
|
|
1387
|
-
}
|
|
1388
|
-
|
|
1389
|
-
.playkit-auth-panel {
|
|
1390
|
-
padding: 20px;
|
|
1391
|
-
}
|
|
1392
|
-
|
|
1393
|
-
.playkit-code-input {
|
|
1394
|
-
width: 36px !important;
|
|
1395
|
-
height: 44px;
|
|
1396
|
-
font-size: 18px;
|
|
1397
|
-
}
|
|
1398
|
-
|
|
1399
|
-
.playkit-code-inputs {
|
|
1400
|
-
gap: 6px;
|
|
1401
|
-
}
|
|
1402
|
-
}
|
|
1403
|
-
`;
|
|
1404
|
-
document.head.appendChild(style);
|
|
1405
|
-
}
|
|
1406
|
-
/**
|
|
1407
|
-
* Setup event listeners
|
|
1408
|
-
*/
|
|
1409
|
-
setupEventListeners() {
|
|
1410
|
-
var _a, _b, _c, _d;
|
|
1411
|
-
// Auth type toggle
|
|
1412
|
-
const emailRadio = (_a = this.modal) === null || _a === void 0 ? void 0 : _a.querySelector('input[value="email"]');
|
|
1413
|
-
const phoneRadio = (_b = this.modal) === null || _b === void 0 ? void 0 : _b.querySelector('input[value="phone"]');
|
|
1414
|
-
const identifierInput = document.getElementById('playkit-identifier-input');
|
|
1415
|
-
const identifierIcon = document.getElementById('playkit-identifier-icon');
|
|
1416
|
-
const updateIcon = () => {
|
|
1417
|
-
const isEmail = emailRadio === null || emailRadio === void 0 ? void 0 : emailRadio.checked;
|
|
1418
|
-
identifierInput.placeholder = isEmail
|
|
1419
|
-
? this.t('emailPlaceholder')
|
|
1420
|
-
: this.t('phonePlaceholder');
|
|
1421
|
-
// Update icon
|
|
1422
|
-
if (isEmail) {
|
|
1423
|
-
identifierIcon.innerHTML = `
|
|
1424
|
-
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path>
|
|
1425
|
-
<polyline points="22,6 12,13 2,6"></polyline>
|
|
1426
|
-
`;
|
|
1427
|
-
}
|
|
1428
|
-
else {
|
|
1429
|
-
identifierIcon.innerHTML = `
|
|
1430
|
-
<path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"></path>
|
|
1431
|
-
`;
|
|
1432
|
-
}
|
|
1433
|
-
};
|
|
1434
|
-
emailRadio === null || emailRadio === void 0 ? void 0 : emailRadio.addEventListener('change', updateIcon);
|
|
1435
|
-
phoneRadio === null || phoneRadio === void 0 ? void 0 : phoneRadio.addEventListener('change', updateIcon);
|
|
1436
|
-
// Send code button
|
|
1437
|
-
const sendCodeBtn = document.getElementById('playkit-send-code-btn');
|
|
1438
|
-
sendCodeBtn === null || sendCodeBtn === void 0 ? void 0 : sendCodeBtn.addEventListener('click', () => this.onSendCodeClicked());
|
|
1439
|
-
// Enter key in identifier input
|
|
1440
|
-
identifierInput === null || identifierInput === void 0 ? void 0 : identifierInput.addEventListener('keypress', (e) => {
|
|
1441
|
-
if (e.key === 'Enter') {
|
|
1442
|
-
this.onSendCodeClicked();
|
|
1443
|
-
}
|
|
1444
|
-
});
|
|
1445
|
-
// Initialize VanillaOTP for code inputs
|
|
1446
|
-
const codeInputsContainer = (_c = this.modal) === null || _c === void 0 ? void 0 : _c.querySelector('.playkit-code-inputs');
|
|
1447
|
-
if (codeInputsContainer && window.VanillaOTP) {
|
|
1448
|
-
this.otpInstance = new window.VanillaOTP(codeInputsContainer);
|
|
1449
|
-
// Auto-submit when all 6 digits entered
|
|
1450
|
-
const codeInputs = (_d = this.modal) === null || _d === void 0 ? void 0 : _d.querySelectorAll('.playkit-code-input');
|
|
1451
|
-
codeInputs === null || codeInputs === void 0 ? void 0 : codeInputs.forEach((input, _index) => {
|
|
1452
|
-
input.addEventListener('input', () => {
|
|
1453
|
-
// Check if all inputs are filled
|
|
1454
|
-
const allFilled = Array.from(codeInputs).every(inp => inp.value.length === 1);
|
|
1455
|
-
if (allFilled) {
|
|
1456
|
-
// Small delay to ensure the last input is processed
|
|
1457
|
-
setTimeout(() => this.onVerifyClicked(), 100);
|
|
1458
|
-
}
|
|
1459
|
-
});
|
|
1460
|
-
});
|
|
1461
|
-
}
|
|
1462
|
-
// Verify button
|
|
1463
|
-
const verifyBtn = document.getElementById('playkit-verify-btn');
|
|
1464
|
-
verifyBtn === null || verifyBtn === void 0 ? void 0 : verifyBtn.addEventListener('click', () => this.onVerifyClicked());
|
|
1465
|
-
// Back button
|
|
1466
|
-
const backBtn = document.getElementById('playkit-back-btn');
|
|
1467
|
-
backBtn === null || backBtn === void 0 ? void 0 : backBtn.addEventListener('click', () => {
|
|
1468
|
-
this.showIdentifierPanel();
|
|
1469
|
-
});
|
|
1470
|
-
}
|
|
1471
|
-
/**
|
|
1472
|
-
* Handle send code button click
|
|
1473
|
-
*/
|
|
1474
|
-
async onSendCodeClicked() {
|
|
1475
|
-
var _a;
|
|
1476
|
-
this.clearError();
|
|
1477
|
-
const identifierInput = document.getElementById('playkit-identifier-input');
|
|
1478
|
-
const identifier = identifierInput.value.trim();
|
|
1479
|
-
const emailRadio = (_a = this.modal) === null || _a === void 0 ? void 0 : _a.querySelector('input[value="email"]');
|
|
1480
|
-
const type = emailRadio.checked ? 'email' : 'phone';
|
|
1481
|
-
if (!identifier) {
|
|
1482
|
-
this.showError(type === 'email' ? this.t('pleaseEnterEmail') : this.t('pleaseEnterPhone'));
|
|
1483
|
-
return;
|
|
1484
|
-
}
|
|
1485
|
-
const sendCodeBtn = document.getElementById('playkit-send-code-btn');
|
|
1486
|
-
sendCodeBtn.disabled = true;
|
|
1487
|
-
this.showLoading();
|
|
1488
|
-
try {
|
|
1489
|
-
const success = await this.sendVerificationCode(identifier, type);
|
|
1490
|
-
if (success) {
|
|
1491
|
-
// Store identifier for display
|
|
1492
|
-
const displaySpan = document.getElementById('playkit-identifier-display');
|
|
1493
|
-
if (displaySpan) {
|
|
1494
|
-
displaySpan.textContent = type === 'email' ? identifier : identifier;
|
|
1495
|
-
}
|
|
1496
|
-
// Switch to verification panel
|
|
1497
|
-
this.showVerificationPanel();
|
|
1498
|
-
}
|
|
1499
|
-
}
|
|
1500
|
-
catch (error) {
|
|
1501
|
-
this.showError(error instanceof Error ? error.message : this.t('failedToSendCode'));
|
|
1502
|
-
}
|
|
1503
|
-
finally {
|
|
1504
|
-
this.hideLoading();
|
|
1505
|
-
sendCodeBtn.disabled = false;
|
|
1506
|
-
}
|
|
1507
|
-
}
|
|
1508
|
-
/**
|
|
1509
|
-
* Handle verify button click
|
|
1510
|
-
*/
|
|
1511
|
-
async onVerifyClicked() {
|
|
1512
|
-
var _a;
|
|
1513
|
-
this.clearError('verify');
|
|
1514
|
-
// Get code from VanillaOTP instance or fallback to manual collection
|
|
1515
|
-
let code = '';
|
|
1516
|
-
if (this.otpInstance) {
|
|
1517
|
-
code = this.otpInstance.getValue().replace(/\s/g, ''); // Remove spaces
|
|
1518
|
-
}
|
|
1519
|
-
else {
|
|
1520
|
-
const codeInputs = (_a = this.modal) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.playkit-code-input');
|
|
1521
|
-
code = Array.from(codeInputs).map((input) => input.value).join('');
|
|
1522
|
-
}
|
|
1523
|
-
if (code.length !== 6 || !/^\d{6}$/.test(code)) {
|
|
1524
|
-
this.showError(this.t('enterAllDigits'), 'verify');
|
|
1525
|
-
return;
|
|
1526
|
-
}
|
|
1527
|
-
this.showLoading();
|
|
1528
|
-
try {
|
|
1529
|
-
const globalToken = await this.verifyCode(code);
|
|
1530
|
-
this.emit('success', globalToken);
|
|
1531
|
-
}
|
|
1532
|
-
catch (error) {
|
|
1533
|
-
this.showError(error instanceof Error ? error.message : this.t('verificationFailed'), 'verify');
|
|
1534
|
-
this.hideLoading();
|
|
1535
|
-
}
|
|
1536
|
-
}
|
|
1537
|
-
/**
|
|
1538
|
-
* Send verification code to backend
|
|
1539
|
-
*/
|
|
1540
|
-
async sendVerificationCode(identifier, type) {
|
|
1541
|
-
const response = await fetch(`${this.baseURL}/api/auth/send-code`, {
|
|
1542
|
-
method: 'POST',
|
|
1543
|
-
headers: Object.assign({ 'Content-Type': 'application/json' }, getSDKHeaders()),
|
|
1544
|
-
body: JSON.stringify({ identifier, type }),
|
|
1545
|
-
});
|
|
1546
|
-
if (!response.ok) {
|
|
1547
|
-
throw new PlayKitError(this.t('failedToSendCode'), 'SEND_CODE_ERROR', response.status);
|
|
1548
|
-
}
|
|
1549
|
-
const data = await response.json();
|
|
1550
|
-
if (!data.success || !data.sessionId) {
|
|
1551
|
-
throw new PlayKitError(this.t('failedToSendCode'), 'INVALID_RESPONSE');
|
|
1552
|
-
}
|
|
1553
|
-
this.currentSessionId = data.sessionId;
|
|
1554
|
-
return true;
|
|
1555
|
-
}
|
|
1556
|
-
/**
|
|
1557
|
-
* Verify the code and get global token
|
|
1558
|
-
*/
|
|
1559
|
-
async verifyCode(code) {
|
|
1560
|
-
if (!this.currentSessionId) {
|
|
1561
|
-
throw new PlayKitError('No session ID available', 'NO_SESSION');
|
|
1562
|
-
}
|
|
1563
|
-
const response = await fetch(`${this.baseURL}/api/auth/verify-code`, {
|
|
1564
|
-
method: 'POST',
|
|
1565
|
-
headers: Object.assign({ 'Content-Type': 'application/json' }, getSDKHeaders()),
|
|
1566
|
-
body: JSON.stringify({
|
|
1567
|
-
sessionId: this.currentSessionId,
|
|
1568
|
-
code,
|
|
1569
|
-
}),
|
|
1570
|
-
});
|
|
1571
|
-
if (!response.ok) {
|
|
1572
|
-
throw new PlayKitError(this.t('invalidCode'), 'INVALID_CODE', response.status);
|
|
1573
|
-
}
|
|
1574
|
-
const data = await response.json();
|
|
1575
|
-
if (!data.success || !data.globalToken) {
|
|
1576
|
-
throw new PlayKitError(this.t('verificationFailed'), 'VERIFICATION_FAILED');
|
|
1577
|
-
}
|
|
1578
|
-
return data.globalToken;
|
|
1579
|
-
}
|
|
1580
|
-
/**
|
|
1581
|
-
* Set default auth type based on user region
|
|
1582
|
-
*/
|
|
1583
|
-
async setDefaultAuthTypeByRegion() {
|
|
1584
|
-
var _a;
|
|
1585
|
-
try {
|
|
1586
|
-
const response = await fetch(`${this.baseURL}/api/reachability`, {
|
|
1587
|
-
headers: Object.assign({}, getSDKHeaders()),
|
|
1588
|
-
});
|
|
1589
|
-
if (response.ok) {
|
|
1590
|
-
const data = await response.json();
|
|
1591
|
-
if (data.region === 'CN') {
|
|
1592
|
-
const phoneRadio = (_a = this.modal) === null || _a === void 0 ? void 0 : _a.querySelector('input[value="phone"]');
|
|
1593
|
-
if (phoneRadio) {
|
|
1594
|
-
phoneRadio.checked = true;
|
|
1595
|
-
phoneRadio.dispatchEvent(new Event('change'));
|
|
1596
|
-
}
|
|
1597
|
-
}
|
|
1598
|
-
}
|
|
1599
|
-
}
|
|
1600
|
-
catch (error) {
|
|
1601
|
-
console.error('[PlayKit Auth] Failed to detect region:', error);
|
|
1602
|
-
}
|
|
1603
|
-
}
|
|
1604
|
-
/**
|
|
1605
|
-
* Show/hide panels
|
|
1606
|
-
*/
|
|
1607
|
-
showIdentifierPanel() {
|
|
1608
|
-
var _a;
|
|
1609
|
-
if (this.identifierPanel)
|
|
1610
|
-
this.identifierPanel.style.display = 'block';
|
|
1611
|
-
if (this.verificationPanel)
|
|
1612
|
-
this.verificationPanel.style.display = 'none';
|
|
1613
|
-
// Clear code inputs
|
|
1614
|
-
if (this.otpInstance) {
|
|
1615
|
-
this.otpInstance.setValue(''); // Clear all inputs using VanillaOTP
|
|
1616
|
-
}
|
|
1617
|
-
else {
|
|
1618
|
-
const codeInputs = (_a = this.modal) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.playkit-code-input');
|
|
1619
|
-
codeInputs === null || codeInputs === void 0 ? void 0 : codeInputs.forEach((input) => (input.value = ''));
|
|
1620
|
-
}
|
|
1621
|
-
}
|
|
1622
|
-
showVerificationPanel() {
|
|
1623
|
-
var _a;
|
|
1624
|
-
if (this.identifierPanel)
|
|
1625
|
-
this.identifierPanel.style.display = 'none';
|
|
1626
|
-
if (this.verificationPanel)
|
|
1627
|
-
this.verificationPanel.style.display = 'block';
|
|
1628
|
-
// Focus first code input
|
|
1629
|
-
const firstInput = (_a = this.modal) === null || _a === void 0 ? void 0 : _a.querySelector('.playkit-code-input');
|
|
1630
|
-
firstInput === null || firstInput === void 0 ? void 0 : firstInput.focus();
|
|
1631
|
-
}
|
|
1632
|
-
/**
|
|
1633
|
-
* Show/hide loading
|
|
1634
|
-
*/
|
|
1635
|
-
showLoading() {
|
|
1636
|
-
if (this.loadingOverlay)
|
|
1637
|
-
this.loadingOverlay.style.display = 'flex';
|
|
1638
|
-
}
|
|
1639
|
-
hideLoading() {
|
|
1640
|
-
if (this.loadingOverlay)
|
|
1641
|
-
this.loadingOverlay.style.display = 'none';
|
|
1642
|
-
}
|
|
1643
|
-
/**
|
|
1644
|
-
* Show/hide error messages
|
|
1645
|
-
*/
|
|
1646
|
-
showError(message, panel = 'identifier') {
|
|
1647
|
-
const errorEl = panel === 'identifier'
|
|
1648
|
-
? document.getElementById('playkit-error-text')
|
|
1649
|
-
: document.getElementById('playkit-verify-error-text');
|
|
1650
|
-
if (errorEl) {
|
|
1651
|
-
errorEl.textContent = message;
|
|
1652
|
-
errorEl.classList.add('show');
|
|
1653
|
-
}
|
|
1654
|
-
}
|
|
1655
|
-
clearError(panel = 'both') {
|
|
1656
|
-
if (panel === 'identifier' || panel === 'both') {
|
|
1657
|
-
const errorEl = document.getElementById('playkit-error-text');
|
|
1658
|
-
if (errorEl) {
|
|
1659
|
-
errorEl.textContent = '';
|
|
1660
|
-
errorEl.classList.remove('show');
|
|
1661
|
-
}
|
|
1662
|
-
}
|
|
1663
|
-
if (panel === 'verify' || panel === 'both') {
|
|
1664
|
-
const errorEl = document.getElementById('playkit-verify-error-text');
|
|
1665
|
-
if (errorEl) {
|
|
1666
|
-
errorEl.textContent = '';
|
|
1667
|
-
errorEl.classList.remove('show');
|
|
1668
|
-
}
|
|
1669
|
-
}
|
|
1670
|
-
}
|
|
1671
|
-
/**
|
|
1672
|
-
* Show/hide modal
|
|
1673
|
-
*/
|
|
1674
|
-
showModal() {
|
|
1675
|
-
if (this.modal)
|
|
1676
|
-
this.modal.style.display = 'flex';
|
|
1677
|
-
}
|
|
1678
|
-
hideModal() {
|
|
1679
|
-
if (this.modal) {
|
|
1680
|
-
this.modal.style.display = 'none';
|
|
1681
|
-
// Remove from DOM after animation
|
|
1682
|
-
setTimeout(() => {
|
|
1683
|
-
var _a;
|
|
1684
|
-
(_a = this.modal) === null || _a === void 0 ? void 0 : _a.remove();
|
|
1685
|
-
}, 300);
|
|
1686
|
-
}
|
|
1687
|
-
}
|
|
1688
|
-
/**
|
|
1689
|
-
* Clean up
|
|
1690
|
-
*/
|
|
1691
|
-
destroy() {
|
|
1692
|
-
var _a;
|
|
1693
|
-
(_a = this.modal) === null || _a === void 0 ? void 0 : _a.remove();
|
|
1694
|
-
this.removeAllListeners();
|
|
1695
|
-
}
|
|
1696
|
-
}
|
|
1697
|
-
|
|
1698
879
|
/**
|
|
1699
880
|
* Device Authorization Flow Manager
|
|
1700
881
|
* Manages Device Auth polling flow for desktop/CLI/Unity applications
|
|
@@ -2068,14 +1249,12 @@ class DeviceAuthFlowManager extends EventEmitter {
|
|
|
2068
1249
|
// Store the flow promise so subsequent calls can await the same result
|
|
2069
1250
|
const flowPromise = this.executeFlow(options);
|
|
2070
1251
|
DeviceAuthFlowManager.currentFlowPromise = flowPromise;
|
|
2071
|
-
DeviceAuthFlowManager.activeInstance = this;
|
|
2072
1252
|
try {
|
|
2073
1253
|
return await flowPromise;
|
|
2074
1254
|
}
|
|
2075
1255
|
finally {
|
|
2076
1256
|
// Clean up static state when flow completes (success or failure)
|
|
2077
1257
|
DeviceAuthFlowManager.currentFlowPromise = null;
|
|
2078
|
-
DeviceAuthFlowManager.activeInstance = null;
|
|
2079
1258
|
}
|
|
2080
1259
|
}
|
|
2081
1260
|
/**
|
|
@@ -2414,8 +1593,6 @@ class DeviceAuthFlowManager extends EventEmitter {
|
|
|
2414
1593
|
}
|
|
2415
1594
|
/** Shared promise for the current flow - allows multiple callers to await the same result */
|
|
2416
1595
|
DeviceAuthFlowManager.currentFlowPromise = null;
|
|
2417
|
-
/** Reference to the currently active instance */
|
|
2418
|
-
DeviceAuthFlowManager.activeInstance = null;
|
|
2419
1596
|
|
|
2420
1597
|
/**
|
|
2421
1598
|
* Authentication manager
|
|
@@ -2423,12 +1600,10 @@ DeviceAuthFlowManager.activeInstance = null;
|
|
|
2423
1600
|
*/
|
|
2424
1601
|
// @ts-ignore - replaced at build time
|
|
2425
1602
|
const DEFAULT_BASE_URL$6 = "https://api.playkit.ai";
|
|
2426
|
-
const JWT_EXCHANGE_ENDPOINT = '/api/external/exchange-jwt';
|
|
2427
1603
|
const TOKEN_REFRESH_ENDPOINT = '/api/auth/refresh';
|
|
2428
1604
|
class AuthManager extends EventEmitter {
|
|
2429
1605
|
constructor(config) {
|
|
2430
1606
|
super();
|
|
2431
|
-
this.authFlowManager = null;
|
|
2432
1607
|
this.deviceAuthFlowManager = null;
|
|
2433
1608
|
this.logger = Logger.getLogger('AuthManager');
|
|
2434
1609
|
/** Shared promise for current device auth flow - allows multiple callers to await the same result */
|
|
@@ -2496,11 +1671,6 @@ class AuthManager extends EventEmitter {
|
|
|
2496
1671
|
}
|
|
2497
1672
|
}
|
|
2498
1673
|
}
|
|
2499
|
-
// Check if player JWT was provided
|
|
2500
|
-
if (this.config.playerJWT) {
|
|
2501
|
-
await this.exchangeJWT(this.config.playerJWT);
|
|
2502
|
-
return;
|
|
2503
|
-
}
|
|
2504
1674
|
// Check for platform-injected token (same-domain scenario)
|
|
2505
1675
|
// This allows seamless auth when SDK runs in a context where the platform
|
|
2506
1676
|
// (e.g., Agentland-Space) has already stored a token in localStorage
|
|
@@ -2521,35 +1691,30 @@ class AuthManager extends EventEmitter {
|
|
|
2521
1691
|
this.emit('unauthenticated');
|
|
2522
1692
|
// In server mode, don't try to show UI - just throw error
|
|
2523
1693
|
if (this.config.mode === 'server') {
|
|
2524
|
-
throw new PlayKitError('No authentication token provided. In server mode, please provide developerToken
|
|
1694
|
+
throw new PlayKitError('No authentication token provided. In server mode, please provide developerToken or playerToken.', 'NOT_AUTHENTICATED');
|
|
2525
1695
|
}
|
|
2526
1696
|
// Auto-start login flow in browser environment
|
|
2527
1697
|
if (typeof window !== 'undefined') {
|
|
2528
|
-
|
|
2529
|
-
const authMethod = this.config.authMethod || 'device';
|
|
2530
|
-
await this.startAuthFlow(authMethod);
|
|
1698
|
+
await this.startAuthFlow();
|
|
2531
1699
|
// If we reach here, authentication was successful
|
|
2532
1700
|
// If it failed, startAuthFlow() will have thrown an error
|
|
2533
1701
|
}
|
|
2534
1702
|
else {
|
|
2535
1703
|
// Node.js environment - cannot show UI, must provide token manually
|
|
2536
|
-
throw new PlayKitError('No authentication token provided. Please provide developerToken
|
|
1704
|
+
throw new PlayKitError('No authentication token provided. Please provide developerToken or playerToken.', 'NOT_AUTHENTICATED');
|
|
2537
1705
|
}
|
|
2538
1706
|
}
|
|
2539
1707
|
/**
|
|
2540
|
-
* Start the authentication flow
|
|
2541
|
-
*
|
|
2542
|
-
* @param authMethod - Authentication method to use ('device' or 'headless')
|
|
2543
|
-
* @deprecated 'headless' authentication is deprecated and will be removed in v2.0. Use 'device' instead.
|
|
1708
|
+
* Start the authentication flow (Device Authorization + PKCE).
|
|
2544
1709
|
*/
|
|
2545
|
-
async startAuthFlow(
|
|
1710
|
+
async startAuthFlow() {
|
|
2546
1711
|
// If a flow is already in progress, return the shared promise so all callers await the same result
|
|
2547
1712
|
if (this.currentAuthFlowPromise) {
|
|
2548
1713
|
this.logger.debug('Auth flow already in progress, waiting for existing flow');
|
|
2549
1714
|
return this.currentAuthFlowPromise;
|
|
2550
1715
|
}
|
|
2551
1716
|
// Store the flow promise so subsequent calls can await the same result
|
|
2552
|
-
const flowPromise = this.executeAuthFlow(
|
|
1717
|
+
const flowPromise = this.executeAuthFlow();
|
|
2553
1718
|
this.currentAuthFlowPromise = flowPromise;
|
|
2554
1719
|
try {
|
|
2555
1720
|
return await flowPromise;
|
|
@@ -2559,96 +1724,38 @@ class AuthManager extends EventEmitter {
|
|
|
2559
1724
|
}
|
|
2560
1725
|
}
|
|
2561
1726
|
/**
|
|
2562
|
-
* Internal method that executes the
|
|
1727
|
+
* Internal method that executes the Device Authorization flow.
|
|
2563
1728
|
* @private
|
|
2564
1729
|
*/
|
|
2565
|
-
async executeAuthFlow(
|
|
2566
|
-
var _a
|
|
2567
|
-
// Deprecation warning for headless auth
|
|
2568
|
-
if (authMethod === 'headless') {
|
|
2569
|
-
this.logger.warn('"headless" authentication is deprecated and will be removed in v2.0. ' +
|
|
2570
|
-
'Please migrate to "device" authentication.');
|
|
2571
|
-
}
|
|
2572
|
-
try {
|
|
2573
|
-
if (authMethod === 'device') {
|
|
2574
|
-
// Use Device Authorization flow (recommended)
|
|
2575
|
-
this.deviceAuthFlowManager = new DeviceAuthFlowManager(this.baseURL, this.config.gameId);
|
|
2576
|
-
const result = await this.deviceAuthFlowManager.startFlow({
|
|
2577
|
-
scope: 'player:play',
|
|
2578
|
-
});
|
|
2579
|
-
// Update auth state with the player token and refresh token
|
|
2580
|
-
this.authState = {
|
|
2581
|
-
isAuthenticated: true,
|
|
2582
|
-
token: result.access_token,
|
|
2583
|
-
tokenType: 'player',
|
|
2584
|
-
expiresAt: Date.now() + result.expires_in * 1000,
|
|
2585
|
-
refreshToken: result.refresh_token,
|
|
2586
|
-
refreshExpiresAt: Date.now() + result.refresh_expires_in * 1000,
|
|
2587
|
-
};
|
|
2588
|
-
// Save to storage
|
|
2589
|
-
await this.storage.saveAuthState(this.config.gameId, this.authState);
|
|
2590
|
-
this.emit('authenticated', this.authState);
|
|
2591
|
-
// Clean up
|
|
2592
|
-
this.deviceAuthFlowManager.destroy();
|
|
2593
|
-
this.deviceAuthFlowManager = null;
|
|
2594
|
-
}
|
|
2595
|
-
else {
|
|
2596
|
-
// Use headless verification code flow
|
|
2597
|
-
this.authFlowManager = new AuthFlowManager(this.baseURL);
|
|
2598
|
-
// Get global token from auth flow
|
|
2599
|
-
const globalToken = await this.authFlowManager.startFlow();
|
|
2600
|
-
// Exchange for player token
|
|
2601
|
-
await this.exchangeJWT(globalToken);
|
|
2602
|
-
// Clean up
|
|
2603
|
-
this.authFlowManager.destroy();
|
|
2604
|
-
this.authFlowManager = null;
|
|
2605
|
-
}
|
|
2606
|
-
}
|
|
2607
|
-
catch (error) {
|
|
2608
|
-
// User canceled or error occurred
|
|
2609
|
-
(_a = this.authFlowManager) === null || _a === void 0 ? void 0 : _a.destroy();
|
|
2610
|
-
this.authFlowManager = null;
|
|
2611
|
-
(_b = this.deviceAuthFlowManager) === null || _b === void 0 ? void 0 : _b.destroy();
|
|
2612
|
-
this.deviceAuthFlowManager = null;
|
|
2613
|
-
// Re-emit error
|
|
2614
|
-
this.emit('error', error);
|
|
2615
|
-
throw error;
|
|
2616
|
-
}
|
|
2617
|
-
}
|
|
2618
|
-
/**
|
|
2619
|
-
* Exchange JWT for player token
|
|
2620
|
-
*/
|
|
2621
|
-
async exchangeJWT(jwt) {
|
|
1730
|
+
async executeAuthFlow() {
|
|
1731
|
+
var _a;
|
|
2622
1732
|
try {
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
1733
|
+
// Device Authorization flow with PKCE — the only login flow.
|
|
1734
|
+
this.deviceAuthFlowManager = new DeviceAuthFlowManager(this.baseURL, this.config.gameId);
|
|
1735
|
+
const result = await this.deviceAuthFlowManager.startFlow({
|
|
1736
|
+
scope: 'player:play',
|
|
2627
1737
|
});
|
|
2628
|
-
|
|
2629
|
-
const error = await response.json().catch(() => ({ message: 'JWT exchange failed' }));
|
|
2630
|
-
throw new PlayKitError(error.message || 'JWT exchange failed', error.code, response.status);
|
|
2631
|
-
}
|
|
2632
|
-
const data = await response.json();
|
|
2633
|
-
const playerToken = data.playerToken || data.token;
|
|
2634
|
-
if (!playerToken) {
|
|
2635
|
-
throw new PlayKitError('No player token received from server');
|
|
2636
|
-
}
|
|
2637
|
-
// Calculate expiration (assume 24 hours if not provided)
|
|
2638
|
-
const expiresIn = data.expiresIn || 86400;
|
|
2639
|
-
const expiresAt = Date.now() + expiresIn * 1000;
|
|
1738
|
+
// Update auth state with the player token and refresh token
|
|
2640
1739
|
this.authState = {
|
|
2641
1740
|
isAuthenticated: true,
|
|
2642
|
-
token:
|
|
1741
|
+
token: result.access_token,
|
|
2643
1742
|
tokenType: 'player',
|
|
2644
|
-
expiresAt,
|
|
1743
|
+
expiresAt: Date.now() + result.expires_in * 1000,
|
|
1744
|
+
refreshToken: result.refresh_token,
|
|
1745
|
+
refreshExpiresAt: Date.now() + result.refresh_expires_in * 1000,
|
|
2645
1746
|
};
|
|
2646
1747
|
// Save to storage
|
|
2647
1748
|
await this.storage.saveAuthState(this.config.gameId, this.authState);
|
|
2648
1749
|
this.emit('authenticated', this.authState);
|
|
2649
|
-
|
|
1750
|
+
// Clean up
|
|
1751
|
+
this.deviceAuthFlowManager.destroy();
|
|
1752
|
+
this.deviceAuthFlowManager = null;
|
|
2650
1753
|
}
|
|
2651
1754
|
catch (error) {
|
|
1755
|
+
// User canceled or error occurred
|
|
1756
|
+
(_a = this.deviceAuthFlowManager) === null || _a === void 0 ? void 0 : _a.destroy();
|
|
1757
|
+
this.deviceAuthFlowManager = null;
|
|
1758
|
+
// Re-emit error
|
|
2652
1759
|
this.emit('error', error);
|
|
2653
1760
|
throw error;
|
|
2654
1761
|
}
|
|
@@ -2898,7 +2005,7 @@ class AuthManager extends EventEmitter {
|
|
|
2898
2005
|
* Check if an authentication flow is currently in progress
|
|
2899
2006
|
*/
|
|
2900
2007
|
isAuthFlowInProgress() {
|
|
2901
|
-
return !!
|
|
2008
|
+
return !!this.deviceAuthFlowManager;
|
|
2902
2009
|
}
|
|
2903
2010
|
/**
|
|
2904
2011
|
* Poll for authorization token after initiateDeviceAuth().
|
|
@@ -3819,6 +2926,11 @@ const VALID_PART_TYPES = new Set([
|
|
|
3819
2926
|
'file',
|
|
3820
2927
|
'audio',
|
|
3821
2928
|
'input_audio',
|
|
2929
|
+
'reasoning',
|
|
2930
|
+
'tool-call',
|
|
2931
|
+
'tool-result',
|
|
2932
|
+
'tool-approval-request',
|
|
2933
|
+
'tool-approval-response',
|
|
3822
2934
|
]);
|
|
3823
2935
|
function describePart(part) {
|
|
3824
2936
|
if (part === null)
|
|
@@ -3861,13 +2973,13 @@ function assertValidMessages(messages) {
|
|
|
3861
2973
|
if (!hasType) {
|
|
3862
2974
|
if ('role' in part && 'content' in part) {
|
|
3863
2975
|
throw new PlayKitError(`messages[${i}].content[${j}] is shaped like a Message (has role/content) ` +
|
|
3864
|
-
`but content parts must
|
|
2976
|
+
`but content parts must include a recognized 'type' field. ` +
|
|
3865
2977
|
`Did you mean to pass that array as messages directly? ` +
|
|
3866
2978
|
`e.g. \`messages: theArray\` instead of \`messages: [{role:'user', content: theArray}]\`. ` +
|
|
3867
2979
|
`Got part ${describePart(part)}`, 'INVALID_MESSAGES');
|
|
3868
2980
|
}
|
|
3869
2981
|
throw new PlayKitError(`messages[${i}].content[${j}] is missing a recognized 'type' field ` +
|
|
3870
|
-
`(expected one of
|
|
2982
|
+
`(expected one of ${Array.from(VALID_PART_TYPES).join('|')}). Got part ${describePart(part)}`, 'INVALID_MESSAGES');
|
|
3871
2983
|
}
|
|
3872
2984
|
}
|
|
3873
2985
|
}
|
|
@@ -3902,6 +3014,38 @@ class ChatProvider {
|
|
|
3902
3014
|
setPlayerClient(playerClient) {
|
|
3903
3015
|
this.playerClient = playerClient;
|
|
3904
3016
|
}
|
|
3017
|
+
/**
|
|
3018
|
+
* Resolve the `thinking` payload to send on the wire.
|
|
3019
|
+
*
|
|
3020
|
+
* Resolution order for effort: per-request `thinking.effort` > SDK-level
|
|
3021
|
+
* `defaultThinkingEffort` > omit (the server then defaults to off). This
|
|
3022
|
+
* mirrors how the chat model resolves (`chatConfig.model || defaultChatModel`).
|
|
3023
|
+
*
|
|
3024
|
+
* The deprecated `enabled` flag is preserved as an alias: when no effort can be
|
|
3025
|
+
* resolved, `enabled: false` maps to `{ effort: 'off' }` and `enabled: true`
|
|
3026
|
+
* maps to `{ effort: 'minimal' }`.
|
|
3027
|
+
*
|
|
3028
|
+
* @returns The `{ effort }` (and/or `enabled`) object to assign to
|
|
3029
|
+
* `requestBody.thinking`, or `undefined` to send nothing.
|
|
3030
|
+
*/
|
|
3031
|
+
resolveThinking(chatConfig) {
|
|
3032
|
+
const thinking = chatConfig.thinking;
|
|
3033
|
+
// Precedence: per-request `effort` > per-request `enabled` alias > SDK-level
|
|
3034
|
+
// `defaultThinkingEffort` > omit (server then defaults to off). The `enabled`
|
|
3035
|
+
// alias MUST be checked BEFORE the SDK default, so an explicit per-request
|
|
3036
|
+
// `enabled: false` is never overridden by a configured default effort.
|
|
3037
|
+
if (thinking === null || thinking === void 0 ? void 0 : thinking.effort) {
|
|
3038
|
+
return { effort: thinking.effort };
|
|
3039
|
+
}
|
|
3040
|
+
if ((thinking === null || thinking === void 0 ? void 0 : thinking.enabled) !== undefined) {
|
|
3041
|
+
return { effort: thinking.enabled ? 'minimal' : 'off' };
|
|
3042
|
+
}
|
|
3043
|
+
if (this.config.defaultThinkingEffort) {
|
|
3044
|
+
return { effort: this.config.defaultThinkingEffort };
|
|
3045
|
+
}
|
|
3046
|
+
// Nothing to send — server defaults to off.
|
|
3047
|
+
return undefined;
|
|
3048
|
+
}
|
|
3905
3049
|
/**
|
|
3906
3050
|
* Make a chat completion request (non-streaming)
|
|
3907
3051
|
*/
|
|
@@ -3926,8 +3070,9 @@ class ChatProvider {
|
|
|
3926
3070
|
stop: chatConfig.stop || null,
|
|
3927
3071
|
top_p: chatConfig.topP || null,
|
|
3928
3072
|
};
|
|
3929
|
-
|
|
3930
|
-
|
|
3073
|
+
const thinking = this.resolveThinking(chatConfig);
|
|
3074
|
+
if (thinking) {
|
|
3075
|
+
requestBody.thinking = thinking;
|
|
3931
3076
|
}
|
|
3932
3077
|
try {
|
|
3933
3078
|
const response = await fetch(`${this.baseURL}${endpoint}`, {
|
|
@@ -3986,8 +3131,9 @@ class ChatProvider {
|
|
|
3986
3131
|
stop: chatConfig.stop || null,
|
|
3987
3132
|
top_p: chatConfig.topP || null,
|
|
3988
3133
|
};
|
|
3989
|
-
|
|
3990
|
-
|
|
3134
|
+
const thinking = this.resolveThinking(chatConfig);
|
|
3135
|
+
if (thinking) {
|
|
3136
|
+
requestBody.thinking = thinking;
|
|
3991
3137
|
}
|
|
3992
3138
|
try {
|
|
3993
3139
|
const response = await fetch(`${this.baseURL}${endpoint}`, {
|
|
@@ -4053,8 +3199,9 @@ class ChatProvider {
|
|
|
4053
3199
|
if (chatConfig.tool_choice) {
|
|
4054
3200
|
requestBody.tool_choice = chatConfig.tool_choice;
|
|
4055
3201
|
}
|
|
4056
|
-
|
|
4057
|
-
|
|
3202
|
+
const thinking = this.resolveThinking(chatConfig);
|
|
3203
|
+
if (thinking) {
|
|
3204
|
+
requestBody.thinking = thinking;
|
|
4058
3205
|
}
|
|
4059
3206
|
try {
|
|
4060
3207
|
const response = await fetch(`${this.baseURL}${endpoint}`, {
|
|
@@ -4114,8 +3261,9 @@ class ChatProvider {
|
|
|
4114
3261
|
if (chatConfig.tool_choice) {
|
|
4115
3262
|
requestBody.tool_choice = chatConfig.tool_choice;
|
|
4116
3263
|
}
|
|
4117
|
-
|
|
4118
|
-
|
|
3264
|
+
const thinking = this.resolveThinking(chatConfig);
|
|
3265
|
+
if (thinking) {
|
|
3266
|
+
requestBody.thinking = thinking;
|
|
4119
3267
|
}
|
|
4120
3268
|
try {
|
|
4121
3269
|
const response = await fetch(`${this.baseURL}${endpoint}`, {
|
|
@@ -4500,6 +3648,25 @@ class TTSProvider {
|
|
|
4500
3648
|
}
|
|
4501
3649
|
return response;
|
|
4502
3650
|
}
|
|
3651
|
+
/** GET a TTS endpoint; throws a PlayKitError on a non-ok response. */
|
|
3652
|
+
async get(endpoint) {
|
|
3653
|
+
await this.authManager.ensureValidToken();
|
|
3654
|
+
const token = this.authManager.getToken();
|
|
3655
|
+
if (!token) {
|
|
3656
|
+
throw new PlayKitError('Not authenticated', 'NOT_AUTHENTICATED');
|
|
3657
|
+
}
|
|
3658
|
+
const response = await fetch(`${this.baseURL}${endpoint}`, {
|
|
3659
|
+
method: 'GET',
|
|
3660
|
+
headers: Object.assign({ Authorization: `Bearer ${token}` }, getSDKHeaders()),
|
|
3661
|
+
});
|
|
3662
|
+
if (!response.ok) {
|
|
3663
|
+
const error = await response
|
|
3664
|
+
.json()
|
|
3665
|
+
.catch(() => ({ message: 'Request failed' }));
|
|
3666
|
+
throw new PlayKitError(error.message || 'Request failed', error.code, response.status);
|
|
3667
|
+
}
|
|
3668
|
+
return response;
|
|
3669
|
+
}
|
|
4503
3670
|
checkBalanceAfter() {
|
|
4504
3671
|
if (this.playerClient) {
|
|
4505
3672
|
this.playerClient.checkBalanceAfterApiCall().catch(() => {
|
|
@@ -4584,6 +3751,39 @@ class TTSProvider {
|
|
|
4584
3751
|
throw new PlayKitError(error instanceof Error ? error.message : 'Unknown error', 'TTS_ERROR');
|
|
4585
3752
|
}
|
|
4586
3753
|
}
|
|
3754
|
+
/**
|
|
3755
|
+
* List the voices available for speech synthesis.
|
|
3756
|
+
*/
|
|
3757
|
+
async listVoices() {
|
|
3758
|
+
var _a;
|
|
3759
|
+
const endpoint = `/ai/${this.config.gameId}/v2/audio/voices`;
|
|
3760
|
+
try {
|
|
3761
|
+
const response = await this.get(endpoint);
|
|
3762
|
+
const json = (await response.json());
|
|
3763
|
+
const voices = ((_a = json.voices) !== null && _a !== void 0 ? _a : []).map((v) => {
|
|
3764
|
+
const voice = {
|
|
3765
|
+
voiceId: v.voice_id,
|
|
3766
|
+
kind: v.kind === 'custom' ? 'custom' : 'system',
|
|
3767
|
+
};
|
|
3768
|
+
if (v.name !== undefined)
|
|
3769
|
+
voice.name = v.name;
|
|
3770
|
+
if (v.description !== undefined)
|
|
3771
|
+
voice.description = v.description;
|
|
3772
|
+
if (v.language !== undefined)
|
|
3773
|
+
voice.language = v.language;
|
|
3774
|
+
return voice;
|
|
3775
|
+
});
|
|
3776
|
+
return {
|
|
3777
|
+
voices,
|
|
3778
|
+
total: Number(json.total) || voices.length,
|
|
3779
|
+
};
|
|
3780
|
+
}
|
|
3781
|
+
catch (error) {
|
|
3782
|
+
if (error instanceof PlayKitError)
|
|
3783
|
+
throw error;
|
|
3784
|
+
throw new PlayKitError(error instanceof Error ? error.message : 'Unknown error', 'TTS_ERROR');
|
|
3785
|
+
}
|
|
3786
|
+
}
|
|
4587
3787
|
}
|
|
4588
3788
|
|
|
4589
3789
|
/******************************************************************************
|
|
@@ -5141,14 +4341,14 @@ class ImageClient {
|
|
|
5141
4341
|
* Generate a single image
|
|
5142
4342
|
*/
|
|
5143
4343
|
async generateImage(config) {
|
|
5144
|
-
var _a;
|
|
4344
|
+
var _a, _b;
|
|
5145
4345
|
const imageConfig = Object.assign(Object.assign({}, config), { model: config.model || this.model, n: 1 });
|
|
5146
4346
|
const response = await this.provider.generateImages(imageConfig);
|
|
5147
4347
|
const imageData = response.data[0];
|
|
5148
4348
|
if (!imageData || !imageData.b64_json) {
|
|
5149
4349
|
throw new Error('No image data in response');
|
|
5150
4350
|
}
|
|
5151
|
-
return new GeneratedImageImpl(imageData.b64_json, config.prompt, (
|
|
4351
|
+
return new GeneratedImageImpl(imageData.b64_json, (_a = config.prompt) !== null && _a !== void 0 ? _a : '', (_b = imageData.revised_prompt) !== null && _b !== void 0 ? _b : config.prompt, config.size, imageData.b64_json_original, imageData.transparent_success);
|
|
5152
4352
|
}
|
|
5153
4353
|
/**
|
|
5154
4354
|
* Generate multiple images
|
|
@@ -5157,11 +4357,11 @@ class ImageClient {
|
|
|
5157
4357
|
const imageConfig = Object.assign(Object.assign({}, config), { model: config.model || this.model, n: config.n || 1 });
|
|
5158
4358
|
const response = await this.provider.generateImages(imageConfig);
|
|
5159
4359
|
return response.data.map((imageData) => {
|
|
5160
|
-
var _a;
|
|
4360
|
+
var _a, _b;
|
|
5161
4361
|
if (!imageData.b64_json) {
|
|
5162
4362
|
throw new Error('No image data in response');
|
|
5163
4363
|
}
|
|
5164
|
-
return new GeneratedImageImpl(imageData.b64_json, config.prompt, (
|
|
4364
|
+
return new GeneratedImageImpl(imageData.b64_json, (_a = config.prompt) !== null && _a !== void 0 ? _a : '', (_b = imageData.revised_prompt) !== null && _b !== void 0 ? _b : config.prompt, config.size, imageData.b64_json_original, imageData.transparent_success);
|
|
5165
4365
|
});
|
|
5166
4366
|
}
|
|
5167
4367
|
/**
|
|
@@ -5336,6 +4536,13 @@ class TTSClient {
|
|
|
5336
4536
|
async synthesizeWithTimestamps(config) {
|
|
5337
4537
|
return this.provider.synthesizeWithTimestamps(Object.assign(Object.assign({}, config), { model: config.model || this.model }));
|
|
5338
4538
|
}
|
|
4539
|
+
/**
|
|
4540
|
+
* List the voices available for speech synthesis
|
|
4541
|
+
* @returns The available voices and a total count
|
|
4542
|
+
*/
|
|
4543
|
+
async listVoices() {
|
|
4544
|
+
return this.provider.listVoices();
|
|
4545
|
+
}
|
|
5339
4546
|
/**
|
|
5340
4547
|
* Synthesize text into speech and return it as a Blob (browser-friendly)
|
|
5341
4548
|
* @param config - Full TTS configuration
|
|
@@ -6209,12 +5416,8 @@ Output ONLY a JSON array of ${predictionNum} strings, nothing else:
|
|
|
6209
5416
|
}));
|
|
6210
5417
|
response.hasActions = response.actionCalls.length > 0;
|
|
6211
5418
|
}
|
|
6212
|
-
// Add assistant response to history
|
|
6213
|
-
const assistantMessage =
|
|
6214
|
-
role: 'assistant',
|
|
6215
|
-
content: response.text,
|
|
6216
|
-
tool_calls: result.tool_calls,
|
|
6217
|
-
};
|
|
5419
|
+
// Add assistant response to history in canonical PlayKit format.
|
|
5420
|
+
const assistantMessage = this.createAssistantHistoryMessage(response.text, result.tool_calls);
|
|
6218
5421
|
this.history.push(assistantMessage);
|
|
6219
5422
|
this.trimHistory();
|
|
6220
5423
|
this.emit('response', response.text);
|
|
@@ -6272,12 +5475,8 @@ Output ONLY a JSON array of ${predictionNum} strings, nothing else:
|
|
|
6272
5475
|
}));
|
|
6273
5476
|
response.hasActions = response.actionCalls.length > 0;
|
|
6274
5477
|
}
|
|
6275
|
-
// Add assistant response to history
|
|
6276
|
-
const assistantMessage =
|
|
6277
|
-
role: 'assistant',
|
|
6278
|
-
content: response.text,
|
|
6279
|
-
tool_calls: result.tool_calls,
|
|
6280
|
-
};
|
|
5478
|
+
// Add assistant response to history in canonical PlayKit format.
|
|
5479
|
+
const assistantMessage = this.createAssistantHistoryMessage(response.text, result.tool_calls);
|
|
6281
5480
|
this.history.push(assistantMessage);
|
|
6282
5481
|
this.trimHistory();
|
|
6283
5482
|
this.emit('response', response.text);
|
|
@@ -6304,22 +5503,64 @@ Output ONLY a JSON array of ${predictionNum} strings, nothing else:
|
|
|
6304
5503
|
*/
|
|
6305
5504
|
reportActionResults(results) {
|
|
6306
5505
|
for (const [callId, result] of Object.entries(results)) {
|
|
6307
|
-
this.history.push(
|
|
6308
|
-
role: 'tool',
|
|
6309
|
-
tool_call_id: callId,
|
|
6310
|
-
content: result,
|
|
6311
|
-
});
|
|
5506
|
+
this.history.push(this.createToolResultHistoryMessage(callId, result));
|
|
6312
5507
|
}
|
|
6313
5508
|
}
|
|
6314
5509
|
/**
|
|
6315
5510
|
* Report a single action result
|
|
6316
5511
|
*/
|
|
6317
5512
|
reportActionResult(callId, result) {
|
|
6318
|
-
this.history.push(
|
|
5513
|
+
this.history.push(this.createToolResultHistoryMessage(callId, result));
|
|
5514
|
+
}
|
|
5515
|
+
createAssistantHistoryMessage(text, toolCalls) {
|
|
5516
|
+
if (!toolCalls || toolCalls.length === 0) {
|
|
5517
|
+
return { role: 'assistant', content: text };
|
|
5518
|
+
}
|
|
5519
|
+
const content = [];
|
|
5520
|
+
if (text) {
|
|
5521
|
+
content.push({ type: 'text', text });
|
|
5522
|
+
}
|
|
5523
|
+
content.push(...toolCalls.map(createToolCallContentPart));
|
|
5524
|
+
return {
|
|
5525
|
+
role: 'assistant',
|
|
5526
|
+
content,
|
|
5527
|
+
};
|
|
5528
|
+
}
|
|
5529
|
+
createToolResultHistoryMessage(callId, result) {
|
|
5530
|
+
const toolName = this.findToolNameForCall(callId);
|
|
5531
|
+
if (!toolName) {
|
|
5532
|
+
// Saved histories from older SDKs may not include enough context to infer
|
|
5533
|
+
// the tool name. Keep the legacy shape; the server normalizer can still
|
|
5534
|
+
// infer it when the matching assistant call is present.
|
|
5535
|
+
return {
|
|
5536
|
+
role: 'tool',
|
|
5537
|
+
tool_call_id: callId,
|
|
5538
|
+
content: result,
|
|
5539
|
+
};
|
|
5540
|
+
}
|
|
5541
|
+
return {
|
|
6319
5542
|
role: 'tool',
|
|
6320
5543
|
tool_call_id: callId,
|
|
6321
|
-
content: result,
|
|
6322
|
-
}
|
|
5544
|
+
content: [createToolResultContentPart(callId, toolName, result)],
|
|
5545
|
+
};
|
|
5546
|
+
}
|
|
5547
|
+
findToolNameForCall(callId) {
|
|
5548
|
+
var _a;
|
|
5549
|
+
for (let i = this.history.length - 1; i >= 0; i--) {
|
|
5550
|
+
const message = this.history[i];
|
|
5551
|
+
if (Array.isArray(message.content)) {
|
|
5552
|
+
for (const part of message.content) {
|
|
5553
|
+
if (part.type === 'tool-call' && part.toolCallId === callId) {
|
|
5554
|
+
return part.toolName;
|
|
5555
|
+
}
|
|
5556
|
+
}
|
|
5557
|
+
}
|
|
5558
|
+
const legacyCall = (_a = message.tool_calls) === null || _a === void 0 ? void 0 : _a.find(tc => tc.id === callId);
|
|
5559
|
+
if (legacyCall) {
|
|
5560
|
+
return legacyCall.function.name;
|
|
5561
|
+
}
|
|
5562
|
+
}
|
|
5563
|
+
return undefined;
|
|
6323
5564
|
}
|
|
6324
5565
|
/**
|
|
6325
5566
|
* Parse tool arguments from JSON string
|
|
@@ -6759,8 +6000,7 @@ class PlayKitSDK extends EventEmitter {
|
|
|
6759
6000
|
// Auto-restart login flow in browser environment
|
|
6760
6001
|
if (typeof window !== 'undefined') {
|
|
6761
6002
|
this.logger.debug('Restarting authentication flow...');
|
|
6762
|
-
|
|
6763
|
-
await this.authManager.startAuthFlow(authMethod);
|
|
6003
|
+
await this.authManager.startAuthFlow();
|
|
6764
6004
|
// Retry getting player info after re-authentication
|
|
6765
6005
|
await this.playerClient.getPlayerInfo();
|
|
6766
6006
|
this.logger.debug('Re-authentication successful, token validated');
|
|
@@ -6803,12 +6043,11 @@ class PlayKitSDK extends EventEmitter {
|
|
|
6803
6043
|
throw new PlayKitError('DeveloperToken validation failed: ' + (error instanceof Error ? error.message : String(error)), 'DEVELOPER_TOKEN_INVALID');
|
|
6804
6044
|
}
|
|
6805
6045
|
// Emit fallback started event
|
|
6806
|
-
|
|
6807
|
-
this.
|
|
6808
|
-
this.logger.debug('Starting fallback to player login', { fallbackMethod });
|
|
6046
|
+
this.emit('developer_token_fallback_started', { fallbackMethod: 'device' });
|
|
6047
|
+
this.logger.debug('Starting fallback to player login');
|
|
6809
6048
|
try {
|
|
6810
6049
|
// Start player login flow
|
|
6811
|
-
await this.authManager.startAuthFlow(
|
|
6050
|
+
await this.authManager.startAuthFlow();
|
|
6812
6051
|
// Verify the new token
|
|
6813
6052
|
await this.playerClient.getPlayerInfo();
|
|
6814
6053
|
// Emit fallback completed event
|
|
@@ -6871,24 +6110,6 @@ class PlayKitSDK extends EventEmitter {
|
|
|
6871
6110
|
isAuthenticated() {
|
|
6872
6111
|
return this.authManager.isAuthenticated();
|
|
6873
6112
|
}
|
|
6874
|
-
/**
|
|
6875
|
-
* Exchange JWT for player token
|
|
6876
|
-
*/
|
|
6877
|
-
async login(jwt) {
|
|
6878
|
-
const token = await this.authManager.exchangeJWT(jwt);
|
|
6879
|
-
// Verify token validity and fetch user info
|
|
6880
|
-
try {
|
|
6881
|
-
await this.playerClient.getPlayerInfo();
|
|
6882
|
-
this.logger.debug('Login successful, token validated and user info fetched');
|
|
6883
|
-
}
|
|
6884
|
-
catch (error) {
|
|
6885
|
-
// If token is invalid, logout and re-throw error
|
|
6886
|
-
this.logger.error('Token validation failed after login:', error);
|
|
6887
|
-
await this.authManager.logout();
|
|
6888
|
-
throw new Error('Token validation failed: ' + (error instanceof Error ? error.message : String(error)));
|
|
6889
|
-
}
|
|
6890
|
-
return token;
|
|
6891
|
-
}
|
|
6892
6113
|
/**
|
|
6893
6114
|
* Logout
|
|
6894
6115
|
*/
|
|
@@ -7336,5 +6557,5 @@ class TokenValidator {
|
|
|
7336
6557
|
*/
|
|
7337
6558
|
const defaultTokenValidator = new TokenValidator();
|
|
7338
6559
|
|
|
7339
|
-
export { AIContextManager,
|
|
6560
|
+
export { AIContextManager, AuthManager, BrowserStorage, BufferLogHandler, CallbackLogHandler, ChatClient, DeviceAuthFlowManager, ImageClient, LogLevel, Logger, MemoryStorage, NPCClient, PlayKitSDK, PlayerClient, RechargeManager, SchemaLibrary, StreamParser, TTSClient, TokenStorage, TokenValidator, TranscriptionClient, createMultimodalMessage, createStorage, createTextMessage, PlayKitSDK as default, defaultContextManager, defaultSchemaLibrary, defaultTokenValidator, isLocalStorageAvailable };
|
|
7340
6561
|
//# sourceMappingURL=playkit-sdk.esm.js.map
|