@mindstudio-ai/interface 0.1.1 → 0.1.3
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 +74 -14
- package/dist/index.d.ts +55 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,33 +13,36 @@ npm install @mindstudio-ai/interface
|
|
|
13
13
|
## Usage
|
|
14
14
|
|
|
15
15
|
```tsx
|
|
16
|
-
import { createClient, platform, auth } from '@mindstudio-ai/interface';
|
|
16
|
+
import { createClient, platform, auth, type AppUser } from '@mindstudio-ai/interface';
|
|
17
17
|
|
|
18
18
|
const api = createClient();
|
|
19
19
|
|
|
20
|
+
// Reactive auth state — re-renders on login/logout
|
|
21
|
+
function useAuth() {
|
|
22
|
+
const [user, setUser] = useState<AppUser | null>(null);
|
|
23
|
+
useEffect(() => auth.onAuthStateChanged(setUser), []);
|
|
24
|
+
return user;
|
|
25
|
+
}
|
|
26
|
+
|
|
20
27
|
function App() {
|
|
21
|
-
const user =
|
|
28
|
+
const user = useAuth();
|
|
22
29
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
30
|
+
if (!user) return <LoginPage />;
|
|
31
|
+
|
|
32
|
+
return <Dashboard user={user} />;
|
|
33
|
+
}
|
|
27
34
|
|
|
28
|
-
|
|
35
|
+
function Dashboard({ user }: { user: AppUser }) {
|
|
36
|
+
const [data, setData] = useState(null);
|
|
29
37
|
|
|
30
38
|
useEffect(() => {
|
|
31
|
-
api.getDashboard().then(
|
|
39
|
+
api.getDashboard().then(setData);
|
|
32
40
|
}, []);
|
|
33
41
|
|
|
34
|
-
const handleUpload = async (file: File) => {
|
|
35
|
-
const url = await platform.uploadFile(file);
|
|
36
|
-
// use the CDN url...
|
|
37
|
-
};
|
|
38
|
-
|
|
39
42
|
return (
|
|
40
43
|
<div>
|
|
41
44
|
<p>Welcome, {user.email}</p>
|
|
42
|
-
<
|
|
45
|
+
<button onClick={() => auth.logout()}>Log out</button>
|
|
43
46
|
</div>
|
|
44
47
|
);
|
|
45
48
|
}
|
|
@@ -128,6 +131,63 @@ await auth.requestEmailChange('new@example.com');
|
|
|
128
131
|
await auth.confirmEmailChange('new@example.com', code);
|
|
129
132
|
```
|
|
130
133
|
|
|
134
|
+
#### API keys
|
|
135
|
+
|
|
136
|
+
Apps with `api-key` in their auth methods can let users generate keys for programmatic access:
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
const { key } = await auth.createApiKey(); // full key (sk_...), shown once
|
|
140
|
+
console.log(auth.currentUser?.apiKey); // masked: "sk_...a1b2"
|
|
141
|
+
|
|
142
|
+
await auth.revokeApiKey(); // apiKey becomes null
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Both methods trigger `onAuthStateChanged` since the user's `apiKey` field changes.
|
|
146
|
+
|
|
147
|
+
#### Reactive auth state
|
|
148
|
+
|
|
149
|
+
`onAuthStateChanged` fires immediately with the current user, then again on every auth transition. Use it to build reactive UIs:
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
// React hook
|
|
153
|
+
function useAuth() {
|
|
154
|
+
const [user, setUser] = useState<AppUser | null>(null);
|
|
155
|
+
useEffect(() => auth.onAuthStateChanged(setUser), []);
|
|
156
|
+
return user;
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
You can also read the current user synchronously via `auth.currentUser`.
|
|
161
|
+
|
|
162
|
+
#### Auth error codes
|
|
163
|
+
|
|
164
|
+
Auth methods throw `MindStudioInterfaceError`. Handle specific cases via `err.code`:
|
|
165
|
+
|
|
166
|
+
| Code | Status | Meaning |
|
|
167
|
+
|------|--------|---------|
|
|
168
|
+
| `rate_limited` | 429 | Too many code requests (max 5 per 15 min) |
|
|
169
|
+
| `invalid_code` | 400 | Wrong verification code |
|
|
170
|
+
| `verification_expired` | 400 | Code expired (10 min TTL) |
|
|
171
|
+
| `max_attempts_exceeded` | 400 | Too many incorrect attempts (max 3) |
|
|
172
|
+
| `not_authenticated` | 401 | No auth session (change/logout/api-key endpoints) |
|
|
173
|
+
| `invalid_session` | 401 | Session expired or invalid |
|
|
174
|
+
| `not_supported` | 400 | Feature not enabled (e.g. api-key auth not in app methods) |
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
try {
|
|
178
|
+
await auth.verifyEmailCode(verificationId, code);
|
|
179
|
+
} catch (err) {
|
|
180
|
+
if (err instanceof MindStudioInterfaceError) {
|
|
181
|
+
if (err.code === 'invalid_code') {
|
|
182
|
+
showError('Wrong code, try again');
|
|
183
|
+
} else if (err.code === 'verification_expired') {
|
|
184
|
+
showError('Code expired — sending a new one');
|
|
185
|
+
await auth.sendEmailCode(email);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
131
191
|
#### Session management
|
|
132
192
|
|
|
133
193
|
Verify, confirm, and logout methods update the SDK's internal session in-place. All downstream calls (method invocation, agent chat, uploads) immediately use the new authenticated (or unauthenticated) session. No page refresh needed.
|
package/dist/index.d.ts
CHANGED
|
@@ -570,6 +570,8 @@ interface AppUser {
|
|
|
570
570
|
phone: string | null;
|
|
571
571
|
/** Role IDs assigned to this user. */
|
|
572
572
|
roles: string[];
|
|
573
|
+
/** Masked API key (e.g. "sk_...a1b2"), or null if no key exists. */
|
|
574
|
+
apiKey: string | null;
|
|
573
575
|
/** ISO 8601 timestamp of when the user was created. */
|
|
574
576
|
createdAt: string;
|
|
575
577
|
}
|
|
@@ -677,8 +679,24 @@ interface Country {
|
|
|
677
679
|
* ```
|
|
678
680
|
*/
|
|
679
681
|
|
|
680
|
-
/**
|
|
682
|
+
/**
|
|
683
|
+
* The auth namespace — authentication flows, state, and helpers.
|
|
684
|
+
*
|
|
685
|
+
* Auth methods throw {@link MindStudioInterfaceError} on failure.
|
|
686
|
+
* Common error codes:
|
|
687
|
+
*
|
|
688
|
+
* | Code | Status | Meaning |
|
|
689
|
+
* |------|--------|---------|
|
|
690
|
+
* | `rate_limited` | 429 | Too many code requests (max 5 per 15 min per identifier) |
|
|
691
|
+
* | `invalid_code` | 400 | Wrong verification code |
|
|
692
|
+
* | `verification_expired` | 400 | Code expired (10 min TTL) — request a new one |
|
|
693
|
+
* | `max_attempts_exceeded` | 400 | Too many incorrect attempts (max 3) — request a new code |
|
|
694
|
+
* | `not_authenticated` | 401 | Auth cookie missing (change/logout endpoints) |
|
|
695
|
+
* | `invalid_session` | 401 | Auth cookie expired or invalid |
|
|
696
|
+
*/
|
|
681
697
|
interface Auth {
|
|
698
|
+
/** The current authenticated user, or `null` if not authenticated. */
|
|
699
|
+
readonly currentUser: AppUser | null;
|
|
682
700
|
/** Get the current authenticated user, or `null` if not authenticated. */
|
|
683
701
|
getCurrentUser(): AppUser | null;
|
|
684
702
|
/** Whether the current session is authenticated. */
|
|
@@ -711,6 +729,42 @@ interface Auth {
|
|
|
711
729
|
confirmPhoneChange(newPhone: string, code: string): Promise<AppUser>;
|
|
712
730
|
/** Log out. Clears the cookie and updates the session to unauthenticated. */
|
|
713
731
|
logout(): Promise<void>;
|
|
732
|
+
/**
|
|
733
|
+
* Generate an API key for the current user. Returns the full key
|
|
734
|
+
* (shown once). The user's `apiKey` field updates to the masked
|
|
735
|
+
* value and `onAuthStateChanged` fires.
|
|
736
|
+
*
|
|
737
|
+
* @throws `not_authenticated` (401) if no session
|
|
738
|
+
* @throws `not_supported` (400) if api-key auth is not enabled
|
|
739
|
+
*/
|
|
740
|
+
createApiKey(): Promise<{
|
|
741
|
+
key: string;
|
|
742
|
+
}>;
|
|
743
|
+
/**
|
|
744
|
+
* Revoke the current user's API key. The user's `apiKey` field
|
|
745
|
+
* becomes `null` and `onAuthStateChanged` fires.
|
|
746
|
+
*
|
|
747
|
+
* @throws `not_authenticated` (401) if no session
|
|
748
|
+
*/
|
|
749
|
+
revokeApiKey(): Promise<void>;
|
|
750
|
+
/**
|
|
751
|
+
* Subscribe to auth state changes. Fires immediately with the
|
|
752
|
+
* current state, then again whenever verify, confirm, or logout
|
|
753
|
+
* updates the session.
|
|
754
|
+
*
|
|
755
|
+
* @returns An unsubscribe function.
|
|
756
|
+
*
|
|
757
|
+
* @example
|
|
758
|
+
* ```ts
|
|
759
|
+
* // React hook
|
|
760
|
+
* function useAuth() {
|
|
761
|
+
* const [user, setUser] = useState<AppUser | null>(null);
|
|
762
|
+
* useEffect(() => auth.onAuthStateChanged(setUser), []);
|
|
763
|
+
* return user;
|
|
764
|
+
* }
|
|
765
|
+
* ```
|
|
766
|
+
*/
|
|
767
|
+
onAuthStateChanged(callback: (user: AppUser | null) => void): () => void;
|
|
714
768
|
/** Phone number utilities — countries, formatting, validation. */
|
|
715
769
|
phone: {
|
|
716
770
|
/** All countries with dial codes, sorted alphabetically. */
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var d=class extends Error{code;status;constructor(a,o,i){super(a),this.name="MindStudioInterfaceError",this.code=o,this.status=i}};var
|
|
2
|
-
`);
|
|
3
|
-
`);u=p.pop()??"";for(let f of p){if(!f.startsWith("data: "))continue;let L=f.slice(6);try{let M=JSON.parse(L);M.type==="done"&&(A={stopReason:M.stopReason,usage:M.usage}),G(M,n)}catch{}}}if(!A)throw new d("Stream ended without a done event","stream_incomplete");return A})();return l.abort=()=>t.abort(),l}}}var D={async uploadFile(e,a){let o=m(),{onProgress:i,signal:t}=a??{};t?.throwIfAborted();let r=await fetch("/_/generate-upload-request",{method:"POST",headers:{Authorization:`Bearer ${o.token}`,"Content-Type":"application/json"},body:JSON.stringify({filename:e.name,contentType:e.type||"application/octet-stream"}),signal:t});if(!r.ok)throw new d(`Upload presign failed: ${r.status} ${r.statusText}`,"upload_error",r.status);let{uploadUrl:l,uploadFields:s,publicUrl:E}=await r.json(),c=new FormData;for(let[S,u]of Object.entries(s))c.append(S,u);if(c.append("file",e),i)return await H(l,c,i,t),E;let C=await fetch(l,{method:"POST",body:c,signal:t});if(!C.ok)throw new d(`File upload failed: ${C.status} ${C.statusText}`,"upload_error",C.status);return E}};function H(e,a,o,i){return new Promise((t,n)=>{let r=new XMLHttpRequest;if(r.upload.addEventListener("progress",l=>{l.lengthComputable&&o(l.loaded/l.total)}),r.addEventListener("load",()=>{r.status>=200&&r.status<300?(o(1),t()):n(new d(`File upload failed: ${r.status} ${r.statusText}`,"upload_error",r.status))}),r.addEventListener("error",()=>{n(new d("File upload failed: network error","upload_error"))}),r.addEventListener("abort",()=>{n(new DOMException("Upload aborted","AbortError"))}),i){if(i.aborted){n(new DOMException("Upload aborted","AbortError"));return}i.addEventListener("abort",()=>r.abort(),{once:!0})}r.open("POST",e),r.send(a)})}var P=[{code:"AF",dialCode:"+93",name:"Afghanistan",flag:"\u{1F1E6}\u{1F1EB}"},{code:"AL",dialCode:"+355",name:"Albania",flag:"\u{1F1E6}\u{1F1F1}"},{code:"DZ",dialCode:"+213",name:"Algeria",flag:"\u{1F1E9}\u{1F1FF}"},{code:"AD",dialCode:"+376",name:"Andorra",flag:"\u{1F1E6}\u{1F1E9}"},{code:"AO",dialCode:"+244",name:"Angola",flag:"\u{1F1E6}\u{1F1F4}"},{code:"AG",dialCode:"+1",name:"Antigua and Barbuda",flag:"\u{1F1E6}\u{1F1EC}"},{code:"AR",dialCode:"+54",name:"Argentina",flag:"\u{1F1E6}\u{1F1F7}"},{code:"AM",dialCode:"+374",name:"Armenia",flag:"\u{1F1E6}\u{1F1F2}"},{code:"AU",dialCode:"+61",name:"Australia",flag:"\u{1F1E6}\u{1F1FA}"},{code:"AT",dialCode:"+43",name:"Austria",flag:"\u{1F1E6}\u{1F1F9}"},{code:"AZ",dialCode:"+994",name:"Azerbaijan",flag:"\u{1F1E6}\u{1F1FF}"},{code:"BS",dialCode:"+1",name:"Bahamas",flag:"\u{1F1E7}\u{1F1F8}"},{code:"BH",dialCode:"+973",name:"Bahrain",flag:"\u{1F1E7}\u{1F1ED}"},{code:"BD",dialCode:"+880",name:"Bangladesh",flag:"\u{1F1E7}\u{1F1E9}"},{code:"BB",dialCode:"+1",name:"Barbados",flag:"\u{1F1E7}\u{1F1E7}"},{code:"BY",dialCode:"+375",name:"Belarus",flag:"\u{1F1E7}\u{1F1FE}"},{code:"BE",dialCode:"+32",name:"Belgium",flag:"\u{1F1E7}\u{1F1EA}"},{code:"BZ",dialCode:"+501",name:"Belize",flag:"\u{1F1E7}\u{1F1FF}"},{code:"BJ",dialCode:"+229",name:"Benin",flag:"\u{1F1E7}\u{1F1EF}"},{code:"BT",dialCode:"+975",name:"Bhutan",flag:"\u{1F1E7}\u{1F1F9}"},{code:"BO",dialCode:"+591",name:"Bolivia",flag:"\u{1F1E7}\u{1F1F4}"},{code:"BA",dialCode:"+387",name:"Bosnia and Herzegovina",flag:"\u{1F1E7}\u{1F1E6}"},{code:"BW",dialCode:"+267",name:"Botswana",flag:"\u{1F1E7}\u{1F1FC}"},{code:"BR",dialCode:"+55",name:"Brazil",flag:"\u{1F1E7}\u{1F1F7}"},{code:"BN",dialCode:"+673",name:"Brunei",flag:"\u{1F1E7}\u{1F1F3}"},{code:"BG",dialCode:"+359",name:"Bulgaria",flag:"\u{1F1E7}\u{1F1EC}"},{code:"BF",dialCode:"+226",name:"Burkina Faso",flag:"\u{1F1E7}\u{1F1EB}"},{code:"BI",dialCode:"+257",name:"Burundi",flag:"\u{1F1E7}\u{1F1EE}"},{code:"CV",dialCode:"+238",name:"Cabo Verde",flag:"\u{1F1E8}\u{1F1FB}"},{code:"KH",dialCode:"+855",name:"Cambodia",flag:"\u{1F1F0}\u{1F1ED}"},{code:"CM",dialCode:"+237",name:"Cameroon",flag:"\u{1F1E8}\u{1F1F2}"},{code:"CA",dialCode:"+1",name:"Canada",flag:"\u{1F1E8}\u{1F1E6}"},{code:"CF",dialCode:"+236",name:"Central African Republic",flag:"\u{1F1E8}\u{1F1EB}"},{code:"TD",dialCode:"+235",name:"Chad",flag:"\u{1F1F9}\u{1F1E9}"},{code:"CL",dialCode:"+56",name:"Chile",flag:"\u{1F1E8}\u{1F1F1}"},{code:"CN",dialCode:"+86",name:"China",flag:"\u{1F1E8}\u{1F1F3}"},{code:"CO",dialCode:"+57",name:"Colombia",flag:"\u{1F1E8}\u{1F1F4}"},{code:"KM",dialCode:"+269",name:"Comoros",flag:"\u{1F1F0}\u{1F1F2}"},{code:"CG",dialCode:"+242",name:"Congo",flag:"\u{1F1E8}\u{1F1EC}"},{code:"CD",dialCode:"+243",name:"Congo (DRC)",flag:"\u{1F1E8}\u{1F1E9}"},{code:"CR",dialCode:"+506",name:"Costa Rica",flag:"\u{1F1E8}\u{1F1F7}"},{code:"HR",dialCode:"+385",name:"Croatia",flag:"\u{1F1ED}\u{1F1F7}"},{code:"CU",dialCode:"+53",name:"Cuba",flag:"\u{1F1E8}\u{1F1FA}"},{code:"CY",dialCode:"+357",name:"Cyprus",flag:"\u{1F1E8}\u{1F1FE}"},{code:"CZ",dialCode:"+420",name:"Czechia",flag:"\u{1F1E8}\u{1F1FF}"},{code:"CI",dialCode:"+225",name:"Cote d'Ivoire",flag:"\u{1F1E8}\u{1F1EE}"},{code:"DK",dialCode:"+45",name:"Denmark",flag:"\u{1F1E9}\u{1F1F0}"},{code:"DJ",dialCode:"+253",name:"Djibouti",flag:"\u{1F1E9}\u{1F1EF}"},{code:"DM",dialCode:"+1",name:"Dominica",flag:"\u{1F1E9}\u{1F1F2}"},{code:"DO",dialCode:"+1",name:"Dominican Republic",flag:"\u{1F1E9}\u{1F1F4}"},{code:"EC",dialCode:"+593",name:"Ecuador",flag:"\u{1F1EA}\u{1F1E8}"},{code:"EG",dialCode:"+20",name:"Egypt",flag:"\u{1F1EA}\u{1F1EC}"},{code:"SV",dialCode:"+503",name:"El Salvador",flag:"\u{1F1F8}\u{1F1FB}"},{code:"GQ",dialCode:"+240",name:"Equatorial Guinea",flag:"\u{1F1EC}\u{1F1F6}"},{code:"ER",dialCode:"+291",name:"Eritrea",flag:"\u{1F1EA}\u{1F1F7}"},{code:"EE",dialCode:"+372",name:"Estonia",flag:"\u{1F1EA}\u{1F1EA}"},{code:"SZ",dialCode:"+268",name:"Eswatini",flag:"\u{1F1F8}\u{1F1FF}"},{code:"ET",dialCode:"+251",name:"Ethiopia",flag:"\u{1F1EA}\u{1F1F9}"},{code:"FJ",dialCode:"+679",name:"Fiji",flag:"\u{1F1EB}\u{1F1EF}"},{code:"FI",dialCode:"+358",name:"Finland",flag:"\u{1F1EB}\u{1F1EE}"},{code:"FR",dialCode:"+33",name:"France",flag:"\u{1F1EB}\u{1F1F7}"},{code:"GA",dialCode:"+241",name:"Gabon",flag:"\u{1F1EC}\u{1F1E6}"},{code:"GM",dialCode:"+220",name:"Gambia",flag:"\u{1F1EC}\u{1F1F2}"},{code:"GE",dialCode:"+995",name:"Georgia",flag:"\u{1F1EC}\u{1F1EA}"},{code:"DE",dialCode:"+49",name:"Germany",flag:"\u{1F1E9}\u{1F1EA}"},{code:"GH",dialCode:"+233",name:"Ghana",flag:"\u{1F1EC}\u{1F1ED}"},{code:"GR",dialCode:"+30",name:"Greece",flag:"\u{1F1EC}\u{1F1F7}"},{code:"GD",dialCode:"+1",name:"Grenada",flag:"\u{1F1EC}\u{1F1E9}"},{code:"GT",dialCode:"+502",name:"Guatemala",flag:"\u{1F1EC}\u{1F1F9}"},{code:"GN",dialCode:"+224",name:"Guinea",flag:"\u{1F1EC}\u{1F1F3}"},{code:"GW",dialCode:"+245",name:"Guinea-Bissau",flag:"\u{1F1EC}\u{1F1FC}"},{code:"GY",dialCode:"+592",name:"Guyana",flag:"\u{1F1EC}\u{1F1FE}"},{code:"HT",dialCode:"+509",name:"Haiti",flag:"\u{1F1ED}\u{1F1F9}"},{code:"HN",dialCode:"+504",name:"Honduras",flag:"\u{1F1ED}\u{1F1F3}"},{code:"HK",dialCode:"+852",name:"Hong Kong",flag:"\u{1F1ED}\u{1F1F0}"},{code:"HU",dialCode:"+36",name:"Hungary",flag:"\u{1F1ED}\u{1F1FA}"},{code:"IS",dialCode:"+354",name:"Iceland",flag:"\u{1F1EE}\u{1F1F8}"},{code:"IN",dialCode:"+91",name:"India",flag:"\u{1F1EE}\u{1F1F3}"},{code:"ID",dialCode:"+62",name:"Indonesia",flag:"\u{1F1EE}\u{1F1E9}"},{code:"IR",dialCode:"+98",name:"Iran",flag:"\u{1F1EE}\u{1F1F7}"},{code:"IQ",dialCode:"+964",name:"Iraq",flag:"\u{1F1EE}\u{1F1F6}"},{code:"IE",dialCode:"+353",name:"Ireland",flag:"\u{1F1EE}\u{1F1EA}"},{code:"IL",dialCode:"+972",name:"Israel",flag:"\u{1F1EE}\u{1F1F1}"},{code:"IT",dialCode:"+39",name:"Italy",flag:"\u{1F1EE}\u{1F1F9}"},{code:"JM",dialCode:"+1",name:"Jamaica",flag:"\u{1F1EF}\u{1F1F2}"},{code:"JP",dialCode:"+81",name:"Japan",flag:"\u{1F1EF}\u{1F1F5}"},{code:"JO",dialCode:"+962",name:"Jordan",flag:"\u{1F1EF}\u{1F1F4}"},{code:"KZ",dialCode:"+7",name:"Kazakhstan",flag:"\u{1F1F0}\u{1F1FF}"},{code:"KE",dialCode:"+254",name:"Kenya",flag:"\u{1F1F0}\u{1F1EA}"},{code:"KI",dialCode:"+686",name:"Kiribati",flag:"\u{1F1F0}\u{1F1EE}"},{code:"KW",dialCode:"+965",name:"Kuwait",flag:"\u{1F1F0}\u{1F1FC}"},{code:"KG",dialCode:"+996",name:"Kyrgyzstan",flag:"\u{1F1F0}\u{1F1EC}"},{code:"LA",dialCode:"+856",name:"Laos",flag:"\u{1F1F1}\u{1F1E6}"},{code:"LV",dialCode:"+371",name:"Latvia",flag:"\u{1F1F1}\u{1F1FB}"},{code:"LB",dialCode:"+961",name:"Lebanon",flag:"\u{1F1F1}\u{1F1E7}"},{code:"LS",dialCode:"+266",name:"Lesotho",flag:"\u{1F1F1}\u{1F1F8}"},{code:"LR",dialCode:"+231",name:"Liberia",flag:"\u{1F1F1}\u{1F1F7}"},{code:"LY",dialCode:"+218",name:"Libya",flag:"\u{1F1F1}\u{1F1FE}"},{code:"LI",dialCode:"+423",name:"Liechtenstein",flag:"\u{1F1F1}\u{1F1EE}"},{code:"LT",dialCode:"+370",name:"Lithuania",flag:"\u{1F1F1}\u{1F1F9}"},{code:"LU",dialCode:"+352",name:"Luxembourg",flag:"\u{1F1F1}\u{1F1FA}"},{code:"MO",dialCode:"+853",name:"Macao",flag:"\u{1F1F2}\u{1F1F4}"},{code:"MG",dialCode:"+261",name:"Madagascar",flag:"\u{1F1F2}\u{1F1EC}"},{code:"MW",dialCode:"+265",name:"Malawi",flag:"\u{1F1F2}\u{1F1FC}"},{code:"MY",dialCode:"+60",name:"Malaysia",flag:"\u{1F1F2}\u{1F1FE}"},{code:"MV",dialCode:"+960",name:"Maldives",flag:"\u{1F1F2}\u{1F1FB}"},{code:"ML",dialCode:"+223",name:"Mali",flag:"\u{1F1F2}\u{1F1F1}"},{code:"MT",dialCode:"+356",name:"Malta",flag:"\u{1F1F2}\u{1F1F9}"},{code:"MH",dialCode:"+692",name:"Marshall Islands",flag:"\u{1F1F2}\u{1F1ED}"},{code:"MR",dialCode:"+222",name:"Mauritania",flag:"\u{1F1F2}\u{1F1F7}"},{code:"MU",dialCode:"+230",name:"Mauritius",flag:"\u{1F1F2}\u{1F1FA}"},{code:"MX",dialCode:"+52",name:"Mexico",flag:"\u{1F1F2}\u{1F1FD}"},{code:"FM",dialCode:"+691",name:"Micronesia",flag:"\u{1F1EB}\u{1F1F2}"},{code:"MD",dialCode:"+373",name:"Moldova",flag:"\u{1F1F2}\u{1F1E9}"},{code:"MC",dialCode:"+377",name:"Monaco",flag:"\u{1F1F2}\u{1F1E8}"},{code:"MN",dialCode:"+976",name:"Mongolia",flag:"\u{1F1F2}\u{1F1F3}"},{code:"ME",dialCode:"+382",name:"Montenegro",flag:"\u{1F1F2}\u{1F1EA}"},{code:"MA",dialCode:"+212",name:"Morocco",flag:"\u{1F1F2}\u{1F1E6}"},{code:"MZ",dialCode:"+258",name:"Mozambique",flag:"\u{1F1F2}\u{1F1FF}"},{code:"MM",dialCode:"+95",name:"Myanmar",flag:"\u{1F1F2}\u{1F1F2}"},{code:"NA",dialCode:"+264",name:"Namibia",flag:"\u{1F1F3}\u{1F1E6}"},{code:"NR",dialCode:"+674",name:"Nauru",flag:"\u{1F1F3}\u{1F1F7}"},{code:"NP",dialCode:"+977",name:"Nepal",flag:"\u{1F1F3}\u{1F1F5}"},{code:"NL",dialCode:"+31",name:"Netherlands",flag:"\u{1F1F3}\u{1F1F1}"},{code:"NZ",dialCode:"+64",name:"New Zealand",flag:"\u{1F1F3}\u{1F1FF}"},{code:"NI",dialCode:"+505",name:"Nicaragua",flag:"\u{1F1F3}\u{1F1EE}"},{code:"NE",dialCode:"+227",name:"Niger",flag:"\u{1F1F3}\u{1F1EA}"},{code:"NG",dialCode:"+234",name:"Nigeria",flag:"\u{1F1F3}\u{1F1EC}"},{code:"KP",dialCode:"+850",name:"North Korea",flag:"\u{1F1F0}\u{1F1F5}"},{code:"MK",dialCode:"+389",name:"North Macedonia",flag:"\u{1F1F2}\u{1F1F0}"},{code:"NO",dialCode:"+47",name:"Norway",flag:"\u{1F1F3}\u{1F1F4}"},{code:"OM",dialCode:"+968",name:"Oman",flag:"\u{1F1F4}\u{1F1F2}"},{code:"PK",dialCode:"+92",name:"Pakistan",flag:"\u{1F1F5}\u{1F1F0}"},{code:"PW",dialCode:"+680",name:"Palau",flag:"\u{1F1F5}\u{1F1FC}"},{code:"PS",dialCode:"+970",name:"Palestine",flag:"\u{1F1F5}\u{1F1F8}"},{code:"PA",dialCode:"+507",name:"Panama",flag:"\u{1F1F5}\u{1F1E6}"},{code:"PG",dialCode:"+675",name:"Papua New Guinea",flag:"\u{1F1F5}\u{1F1EC}"},{code:"PY",dialCode:"+595",name:"Paraguay",flag:"\u{1F1F5}\u{1F1FE}"},{code:"PE",dialCode:"+51",name:"Peru",flag:"\u{1F1F5}\u{1F1EA}"},{code:"PH",dialCode:"+63",name:"Philippines",flag:"\u{1F1F5}\u{1F1ED}"},{code:"PL",dialCode:"+48",name:"Poland",flag:"\u{1F1F5}\u{1F1F1}"},{code:"PT",dialCode:"+351",name:"Portugal",flag:"\u{1F1F5}\u{1F1F9}"},{code:"PR",dialCode:"+1",name:"Puerto Rico",flag:"\u{1F1F5}\u{1F1F7}"},{code:"QA",dialCode:"+974",name:"Qatar",flag:"\u{1F1F6}\u{1F1E6}"},{code:"RO",dialCode:"+40",name:"Romania",flag:"\u{1F1F7}\u{1F1F4}"},{code:"RU",dialCode:"+7",name:"Russia",flag:"\u{1F1F7}\u{1F1FA}"},{code:"RW",dialCode:"+250",name:"Rwanda",flag:"\u{1F1F7}\u{1F1FC}"},{code:"KN",dialCode:"+1",name:"Saint Kitts and Nevis",flag:"\u{1F1F0}\u{1F1F3}"},{code:"LC",dialCode:"+1",name:"Saint Lucia",flag:"\u{1F1F1}\u{1F1E8}"},{code:"VC",dialCode:"+1",name:"Saint Vincent and the Grenadines",flag:"\u{1F1FB}\u{1F1E8}"},{code:"WS",dialCode:"+685",name:"Samoa",flag:"\u{1F1FC}\u{1F1F8}"},{code:"SM",dialCode:"+378",name:"San Marino",flag:"\u{1F1F8}\u{1F1F2}"},{code:"ST",dialCode:"+239",name:"Sao Tome and Principe",flag:"\u{1F1F8}\u{1F1F9}"},{code:"SA",dialCode:"+966",name:"Saudi Arabia",flag:"\u{1F1F8}\u{1F1E6}"},{code:"SN",dialCode:"+221",name:"Senegal",flag:"\u{1F1F8}\u{1F1F3}"},{code:"RS",dialCode:"+381",name:"Serbia",flag:"\u{1F1F7}\u{1F1F8}"},{code:"SC",dialCode:"+248",name:"Seychelles",flag:"\u{1F1F8}\u{1F1E8}"},{code:"SL",dialCode:"+232",name:"Sierra Leone",flag:"\u{1F1F8}\u{1F1F1}"},{code:"SG",dialCode:"+65",name:"Singapore",flag:"\u{1F1F8}\u{1F1EC}"},{code:"SK",dialCode:"+421",name:"Slovakia",flag:"\u{1F1F8}\u{1F1F0}"},{code:"SI",dialCode:"+386",name:"Slovenia",flag:"\u{1F1F8}\u{1F1EE}"},{code:"SB",dialCode:"+677",name:"Solomon Islands",flag:"\u{1F1F8}\u{1F1E7}"},{code:"SO",dialCode:"+252",name:"Somalia",flag:"\u{1F1F8}\u{1F1F4}"},{code:"ZA",dialCode:"+27",name:"South Africa",flag:"\u{1F1FF}\u{1F1E6}"},{code:"KR",dialCode:"+82",name:"South Korea",flag:"\u{1F1F0}\u{1F1F7}"},{code:"SS",dialCode:"+211",name:"South Sudan",flag:"\u{1F1F8}\u{1F1F8}"},{code:"ES",dialCode:"+34",name:"Spain",flag:"\u{1F1EA}\u{1F1F8}"},{code:"LK",dialCode:"+94",name:"Sri Lanka",flag:"\u{1F1F1}\u{1F1F0}"},{code:"SD",dialCode:"+249",name:"Sudan",flag:"\u{1F1F8}\u{1F1E9}"},{code:"SR",dialCode:"+597",name:"Suriname",flag:"\u{1F1F8}\u{1F1F7}"},{code:"SE",dialCode:"+46",name:"Sweden",flag:"\u{1F1F8}\u{1F1EA}"},{code:"CH",dialCode:"+41",name:"Switzerland",flag:"\u{1F1E8}\u{1F1ED}"},{code:"SY",dialCode:"+963",name:"Syria",flag:"\u{1F1F8}\u{1F1FE}"},{code:"TW",dialCode:"+886",name:"Taiwan",flag:"\u{1F1F9}\u{1F1FC}"},{code:"TJ",dialCode:"+992",name:"Tajikistan",flag:"\u{1F1F9}\u{1F1EF}"},{code:"TZ",dialCode:"+255",name:"Tanzania",flag:"\u{1F1F9}\u{1F1FF}"},{code:"TH",dialCode:"+66",name:"Thailand",flag:"\u{1F1F9}\u{1F1ED}"},{code:"TL",dialCode:"+670",name:"Timor-Leste",flag:"\u{1F1F9}\u{1F1F1}"},{code:"TG",dialCode:"+228",name:"Togo",flag:"\u{1F1F9}\u{1F1EC}"},{code:"TO",dialCode:"+676",name:"Tonga",flag:"\u{1F1F9}\u{1F1F4}"},{code:"TT",dialCode:"+1",name:"Trinidad and Tobago",flag:"\u{1F1F9}\u{1F1F9}"},{code:"TN",dialCode:"+216",name:"Tunisia",flag:"\u{1F1F9}\u{1F1F3}"},{code:"TR",dialCode:"+90",name:"Turkey",flag:"\u{1F1F9}\u{1F1F7}"},{code:"TM",dialCode:"+993",name:"Turkmenistan",flag:"\u{1F1F9}\u{1F1F2}"},{code:"TV",dialCode:"+688",name:"Tuvalu",flag:"\u{1F1F9}\u{1F1FB}"},{code:"UG",dialCode:"+256",name:"Uganda",flag:"\u{1F1FA}\u{1F1EC}"},{code:"UA",dialCode:"+380",name:"Ukraine",flag:"\u{1F1FA}\u{1F1E6}"},{code:"AE",dialCode:"+971",name:"United Arab Emirates",flag:"\u{1F1E6}\u{1F1EA}"},{code:"GB",dialCode:"+44",name:"United Kingdom",flag:"\u{1F1EC}\u{1F1E7}"},{code:"US",dialCode:"+1",name:"United States",flag:"\u{1F1FA}\u{1F1F8}"},{code:"UY",dialCode:"+598",name:"Uruguay",flag:"\u{1F1FA}\u{1F1FE}"},{code:"UZ",dialCode:"+998",name:"Uzbekistan",flag:"\u{1F1FA}\u{1F1FF}"},{code:"VU",dialCode:"+678",name:"Vanuatu",flag:"\u{1F1FB}\u{1F1FA}"},{code:"VA",dialCode:"+39",name:"Vatican City",flag:"\u{1F1FB}\u{1F1E6}"},{code:"VE",dialCode:"+58",name:"Venezuela",flag:"\u{1F1FB}\u{1F1EA}"},{code:"VN",dialCode:"+84",name:"Vietnam",flag:"\u{1F1FB}\u{1F1F3}"},{code:"YE",dialCode:"+967",name:"Yemen",flag:"\u{1F1FE}\u{1F1EA}"},{code:"ZM",dialCode:"+260",name:"Zambia",flag:"\u{1F1FF}\u{1F1F2}"},{code:"ZW",dialCode:"+263",name:"Zimbabwe",flag:"\u{1F1FF}\u{1F1FC}"}],K=new Map(P.map(e=>[e.code,e])),$={"America/New_York":"US","America/Chicago":"US","America/Denver":"US","America/Los_Angeles":"US","America/Anchorage":"US","Pacific/Honolulu":"US","America/Phoenix":"US","America/Indiana/Indianapolis":"US","America/Toronto":"CA","America/Vancouver":"CA","America/Edmonton":"CA","America/Winnipeg":"CA","America/Halifax":"CA","America/St_Johns":"CA","Europe/London":"GB","Europe/Dublin":"IE","Europe/Paris":"FR","Europe/Berlin":"DE","Europe/Madrid":"ES","Europe/Rome":"IT","Europe/Amsterdam":"NL","Europe/Brussels":"BE","Europe/Zurich":"CH","Europe/Vienna":"AT","Europe/Stockholm":"SE","Europe/Oslo":"NO","Europe/Copenhagen":"DK","Europe/Helsinki":"FI","Europe/Warsaw":"PL","Europe/Prague":"CZ","Europe/Bucharest":"RO","Europe/Budapest":"HU","Europe/Athens":"GR","Europe/Istanbul":"TR","Europe/Moscow":"RU","Europe/Kiev":"UA","Europe/Lisbon":"PT","Europe/Belgrade":"RS","Europe/Zagreb":"HR","Europe/Bratislava":"SK","Europe/Ljubljana":"SI","Europe/Tallinn":"EE","Europe/Riga":"LV","Europe/Vilnius":"LT","Asia/Tokyo":"JP","Asia/Seoul":"KR","Asia/Shanghai":"CN","Asia/Hong_Kong":"HK","Asia/Taipei":"TW","Asia/Singapore":"SG","Asia/Kolkata":"IN","Asia/Karachi":"PK","Asia/Dhaka":"BD","Asia/Bangkok":"TH","Asia/Jakarta":"ID","Asia/Manila":"PH","Asia/Kuala_Lumpur":"MY","Asia/Ho_Chi_Minh":"VN","Asia/Riyadh":"SA","Asia/Dubai":"AE","Asia/Tehran":"IR","Asia/Baghdad":"IQ","Asia/Beirut":"LB","Asia/Jerusalem":"IL","Asia/Amman":"JO","Asia/Almaty":"KZ","Asia/Tashkent":"UZ","Asia/Colombo":"LK","Asia/Kathmandu":"NP","Asia/Yangon":"MM","Australia/Sydney":"AU","Australia/Melbourne":"AU","Australia/Brisbane":"AU","Australia/Perth":"AU","Australia/Adelaide":"AU","Pacific/Auckland":"NZ","Pacific/Fiji":"FJ","Africa/Cairo":"EG","Africa/Lagos":"NG","Africa/Nairobi":"KE","Africa/Johannesburg":"ZA","Africa/Casablanca":"MA","Africa/Accra":"GH","Africa/Addis_Ababa":"ET","Africa/Dar_es_Salaam":"TZ","Africa/Kampala":"UG","America/Mexico_City":"MX","America/Bogota":"CO","America/Lima":"PE","America/Santiago":"CL","America/Buenos_Aires":"AR","America/Sao_Paulo":"BR","America/Caracas":"VE","America/Guatemala":"GT","America/Havana":"CU","America/Panama":"PA","America/Jamaica":"JM"};function B(){try{let e=Intl.DateTimeFormat().resolvedOptions().timeZone;return $[e]??"US"}catch{return"US"}}function R(e){if(!e.startsWith("+"))return e;let a=e.slice(1);if(a.startsWith("1")&&a.length===11){let o=a.slice(1,4),i=a.slice(4,7),t=a.slice(7);return`+1 (${o}) ${i}-${t}`}for(let o=4;o>=1;o--){let i="+"+a.slice(0,o),t=P.find(n=>n.dialCode===i);if(t){let n=a.slice(o);return`${t.dialCode} ${n}`}}return e}function U(e,a){let o=e.replace(/\D/g,""),i=K.get(a);if(!i)return"+"+o;let t=i.dialCode.slice(1);return o.startsWith(t)?"+"+o:i.dialCode+o}function I(e){return/^\+[1-9]\d{6,14}$/.test(e)}function _(e){return/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e)}async function h(e,a,o){let t={Authorization:`Bearer ${m().token}`};o!==void 0&&(t["Content-Type"]="application/json");let n=await fetch(e,{method:a,headers:t,...o!==void 0&&{body:JSON.stringify(o)}});if(!n.ok){let r=`Auth request failed: ${n.status} ${n.statusText}`,l="auth_error";try{let s=await n.json();s.error&&(r=s.error),s.code&&(l=s.code)}catch{}throw new d(r,l,n.status)}return await n.json()}function b(e){v({token:e.token,user:e.user,methods:e.methods})}function k(e){if(!e.user)throw new d("Verification succeeded but no user was returned","auth_error");return e.user}var j={getCurrentUser(){return m().user},isAuthenticated(){return m().user!==null},sendEmailCode(e){return h("/_/auth/email/send","POST",{email:e})},async verifyEmailCode(e,a){let o=await h("/_/auth/email/verify","POST",{verificationId:e,code:a});return b(o),k(o)},sendSmsCode(e){return h("/_/auth/sms/send","POST",{phone:e})},async verifySmsCode(e,a){let o=await h("/_/auth/sms/verify","POST",{verificationId:e,code:a});return b(o),k(o)},async requestEmailChange(e){await h("/_/auth/email/change","POST",{newEmail:e})},async confirmEmailChange(e,a){let o=await h("/_/auth/email/change/confirm","POST",{newEmail:e,code:a});return b(o),k(o)},async requestPhoneChange(e){await h("/_/auth/phone/change","POST",{newPhone:e})},async confirmPhoneChange(e,a){let o=await h("/_/auth/phone/change/confirm","POST",{newPhone:e,code:a});return b(o),k(o)},async logout(){let e=await h("/_/auth/logout","POST",{});b(e)},phone:{countries:P,detectCountry:B,format:R,toE164:U,isValid:I},email:{isValid:_}};export{d as MindStudioInterfaceError,j as auth,N as createAgentChatClient,O as createClient,D as platform};
|
|
1
|
+
var d=class extends Error{code;status;constructor(a,o,i){super(a),this.name="MindStudioInterfaceError",this.code=o,this.status=i}};var M;function c(){if(M)return M;let e=globalThis.__MINDSTUDIO__;if(!e)throw new d("@mindstudio-ai/interface requires the MindStudio platform context. This page must be loaded inside MindStudio (window.__MINDSTUDIO__ is missing).","not_initialized");if(!e.token||!e.releaseId||!e.methods){let a=["token","releaseId","methods"].filter(o=>!e[o]).join(", ");throw new d(`MindStudio platform context is incomplete. Missing: ${a}`,"invalid_config")}return M=e,M}function x(e){let a=c();e.token!==void 0&&(a.token=e.token),e.user!==void 0&&(a.user=e.user),e.methods!==void 0&&(a.methods=e.methods)}function G(){return new Proxy({},{get(e,a){return async(o,i)=>{let t=c(),n=t.methods[a];if(!n)throw new d(`Method "${a}" not found. Available methods: ${Object.keys(t.methods).join(", ")||"(none)"}`,"method_not_found");let r=`/_/methods/${n}/invoke`,l=i?.stream===!0,s=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.token}`},body:JSON.stringify({input:o??{},...l&&{stream:!0}})});if(!s.ok){let m=`Method "${a}" failed: ${s.status} ${s.statusText}`,A="method_error";try{let u=await s.json();u.error&&(m=u.error),u.code&&(A=u.code)}catch{}throw new d(m,A,s.status)}if(!l)return(await s.json()).output;let y=s.body.getReader(),g=new TextDecoder,p="",S;for(;;){let{done:m,value:A}=await y.read();if(m)break;p+=g.decode(A,{stream:!0});let u=p.split(`
|
|
2
|
+
`);p=u.pop()??"";for(let T of u){if(!T.startsWith("data: "))continue;let h=T.slice(6);try{let f=JSON.parse(h);f.type==="token"&&i?.onToken&&f.text?i.onToken(f.text):f.type==="error"&&f.error?i?.onStreamError&&i.onStreamError(f.error):f.type==="done"&&(S=f.output)}catch{}}}if(S===void 0)throw new d("Stream ended without a done event","stream_incomplete");return S}}})}var U="/_/agent";async function E(e,a,o){let t={Authorization:`Bearer ${c().token}`};o!==void 0&&(t["Content-Type"]="application/json");let n=await fetch(`${U}${e}`,{method:a,headers:t,...o!==void 0&&{body:JSON.stringify(o)}});if(!n.ok){let r=`Agent chat request failed: ${n.status} ${n.statusText}`,l="agent_chat_error";try{let s=await n.json();s.error&&(r=s.error),s.code&&(l=s.code)}catch{}throw new d(r,l,n.status)}return await n.json()}function D(e,a){switch(a.onEvent?.(e),e.type){case"text":a.onText?.(e.text);break;case"thinking":a.onThinking?.(e.text);break;case"thinking_complete":a.onThinkingComplete?.(e.thinking,e.signature);break;case"tool_call_start":a.onToolCallStart?.(e.id,e.name);break;case"tool_call_result":a.onToolCallResult?.(e.id,e.output);break;case"error":a.onError?.(e.error);break}}function K(){return{createThread(){return E("/threads","POST")},listThreads(e){let a=e?`?cursor=${encodeURIComponent(e)}`:"";return E(`/threads${a}`,"GET")},getThread(e){return E(`/threads/${e}`,"GET")},async updateThread(e,a){await E(`/threads/${e}`,"PATCH",{title:a})},async deleteThread(e){await E(`/threads/${e}`,"DELETE")},sendMessage(e,a,o,i){let t=new AbortController,n=o??{};n.signal&&(n.signal.aborted?t.abort():n.signal.addEventListener("abort",()=>t.abort(),{once:!0}));let l=(async()=>{let s=c(),y=`${U}/threads/${e}/messages`,g=await fetch(y,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${s.token}`},body:JSON.stringify({content:a,...i?.attachments?.length&&{attachments:i.attachments}}),signal:t.signal});if(!g.ok){let u=`Send message failed: ${g.status} ${g.statusText}`,T="agent_chat_error";try{let h=await g.json();h.error&&(u=h.error),h.code&&(T=h.code)}catch{}throw new d(u,T,g.status)}let p=g.body.getReader(),S=new TextDecoder,m="",A;for(;;){let{done:u,value:T}=await p.read();if(u)break;m+=S.decode(T,{stream:!0});let h=m.split(`
|
|
3
|
+
`);m=h.pop()??"";for(let f of h){if(!f.startsWith("data: "))continue;let N=f.slice(6);try{let w=JSON.parse(N);w.type==="done"&&(A={stopReason:w.stopReason,usage:w.usage}),D(w,n)}catch{}}}if(!A)throw new d("Stream ended without a done event","stream_incomplete");return A})();return l.abort=()=>t.abort(),l}}}var H={async uploadFile(e,a){let o=c(),{onProgress:i,signal:t}=a??{};t?.throwIfAborted();let r=await fetch("/_/generate-upload-request",{method:"POST",headers:{Authorization:`Bearer ${o.token}`,"Content-Type":"application/json"},body:JSON.stringify({filename:e.name,contentType:e.type||"application/octet-stream"}),signal:t});if(!r.ok)throw new d(`Upload presign failed: ${r.status} ${r.statusText}`,"upload_error",r.status);let{uploadUrl:l,uploadFields:s,publicUrl:y}=await r.json(),g=new FormData;for(let[S,m]of Object.entries(s))g.append(S,m);if(g.append("file",e),i)return await $(l,g,i,t),y;let p=await fetch(l,{method:"POST",body:g,signal:t});if(!p.ok)throw new d(`File upload failed: ${p.status} ${p.statusText}`,"upload_error",p.status);return y}};function $(e,a,o,i){return new Promise((t,n)=>{let r=new XMLHttpRequest;if(r.upload.addEventListener("progress",l=>{l.lengthComputable&&o(l.loaded/l.total)}),r.addEventListener("load",()=>{r.status>=200&&r.status<300?(o(1),t()):n(new d(`File upload failed: ${r.status} ${r.statusText}`,"upload_error",r.status))}),r.addEventListener("error",()=>{n(new d("File upload failed: network error","upload_error"))}),r.addEventListener("abort",()=>{n(new DOMException("Upload aborted","AbortError"))}),i){if(i.aborted){n(new DOMException("Upload aborted","AbortError"));return}i.addEventListener("abort",()=>r.abort(),{once:!0})}r.open("POST",e),r.send(a)})}var P=[{code:"AF",dialCode:"+93",name:"Afghanistan",flag:"\u{1F1E6}\u{1F1EB}"},{code:"AL",dialCode:"+355",name:"Albania",flag:"\u{1F1E6}\u{1F1F1}"},{code:"DZ",dialCode:"+213",name:"Algeria",flag:"\u{1F1E9}\u{1F1FF}"},{code:"AD",dialCode:"+376",name:"Andorra",flag:"\u{1F1E6}\u{1F1E9}"},{code:"AO",dialCode:"+244",name:"Angola",flag:"\u{1F1E6}\u{1F1F4}"},{code:"AG",dialCode:"+1",name:"Antigua and Barbuda",flag:"\u{1F1E6}\u{1F1EC}"},{code:"AR",dialCode:"+54",name:"Argentina",flag:"\u{1F1E6}\u{1F1F7}"},{code:"AM",dialCode:"+374",name:"Armenia",flag:"\u{1F1E6}\u{1F1F2}"},{code:"AU",dialCode:"+61",name:"Australia",flag:"\u{1F1E6}\u{1F1FA}"},{code:"AT",dialCode:"+43",name:"Austria",flag:"\u{1F1E6}\u{1F1F9}"},{code:"AZ",dialCode:"+994",name:"Azerbaijan",flag:"\u{1F1E6}\u{1F1FF}"},{code:"BS",dialCode:"+1",name:"Bahamas",flag:"\u{1F1E7}\u{1F1F8}"},{code:"BH",dialCode:"+973",name:"Bahrain",flag:"\u{1F1E7}\u{1F1ED}"},{code:"BD",dialCode:"+880",name:"Bangladesh",flag:"\u{1F1E7}\u{1F1E9}"},{code:"BB",dialCode:"+1",name:"Barbados",flag:"\u{1F1E7}\u{1F1E7}"},{code:"BY",dialCode:"+375",name:"Belarus",flag:"\u{1F1E7}\u{1F1FE}"},{code:"BE",dialCode:"+32",name:"Belgium",flag:"\u{1F1E7}\u{1F1EA}"},{code:"BZ",dialCode:"+501",name:"Belize",flag:"\u{1F1E7}\u{1F1FF}"},{code:"BJ",dialCode:"+229",name:"Benin",flag:"\u{1F1E7}\u{1F1EF}"},{code:"BT",dialCode:"+975",name:"Bhutan",flag:"\u{1F1E7}\u{1F1F9}"},{code:"BO",dialCode:"+591",name:"Bolivia",flag:"\u{1F1E7}\u{1F1F4}"},{code:"BA",dialCode:"+387",name:"Bosnia and Herzegovina",flag:"\u{1F1E7}\u{1F1E6}"},{code:"BW",dialCode:"+267",name:"Botswana",flag:"\u{1F1E7}\u{1F1FC}"},{code:"BR",dialCode:"+55",name:"Brazil",flag:"\u{1F1E7}\u{1F1F7}"},{code:"BN",dialCode:"+673",name:"Brunei",flag:"\u{1F1E7}\u{1F1F3}"},{code:"BG",dialCode:"+359",name:"Bulgaria",flag:"\u{1F1E7}\u{1F1EC}"},{code:"BF",dialCode:"+226",name:"Burkina Faso",flag:"\u{1F1E7}\u{1F1EB}"},{code:"BI",dialCode:"+257",name:"Burundi",flag:"\u{1F1E7}\u{1F1EE}"},{code:"CV",dialCode:"+238",name:"Cabo Verde",flag:"\u{1F1E8}\u{1F1FB}"},{code:"KH",dialCode:"+855",name:"Cambodia",flag:"\u{1F1F0}\u{1F1ED}"},{code:"CM",dialCode:"+237",name:"Cameroon",flag:"\u{1F1E8}\u{1F1F2}"},{code:"CA",dialCode:"+1",name:"Canada",flag:"\u{1F1E8}\u{1F1E6}"},{code:"CF",dialCode:"+236",name:"Central African Republic",flag:"\u{1F1E8}\u{1F1EB}"},{code:"TD",dialCode:"+235",name:"Chad",flag:"\u{1F1F9}\u{1F1E9}"},{code:"CL",dialCode:"+56",name:"Chile",flag:"\u{1F1E8}\u{1F1F1}"},{code:"CN",dialCode:"+86",name:"China",flag:"\u{1F1E8}\u{1F1F3}"},{code:"CO",dialCode:"+57",name:"Colombia",flag:"\u{1F1E8}\u{1F1F4}"},{code:"KM",dialCode:"+269",name:"Comoros",flag:"\u{1F1F0}\u{1F1F2}"},{code:"CG",dialCode:"+242",name:"Congo",flag:"\u{1F1E8}\u{1F1EC}"},{code:"CD",dialCode:"+243",name:"Congo (DRC)",flag:"\u{1F1E8}\u{1F1E9}"},{code:"CR",dialCode:"+506",name:"Costa Rica",flag:"\u{1F1E8}\u{1F1F7}"},{code:"HR",dialCode:"+385",name:"Croatia",flag:"\u{1F1ED}\u{1F1F7}"},{code:"CU",dialCode:"+53",name:"Cuba",flag:"\u{1F1E8}\u{1F1FA}"},{code:"CY",dialCode:"+357",name:"Cyprus",flag:"\u{1F1E8}\u{1F1FE}"},{code:"CZ",dialCode:"+420",name:"Czechia",flag:"\u{1F1E8}\u{1F1FF}"},{code:"CI",dialCode:"+225",name:"Cote d'Ivoire",flag:"\u{1F1E8}\u{1F1EE}"},{code:"DK",dialCode:"+45",name:"Denmark",flag:"\u{1F1E9}\u{1F1F0}"},{code:"DJ",dialCode:"+253",name:"Djibouti",flag:"\u{1F1E9}\u{1F1EF}"},{code:"DM",dialCode:"+1",name:"Dominica",flag:"\u{1F1E9}\u{1F1F2}"},{code:"DO",dialCode:"+1",name:"Dominican Republic",flag:"\u{1F1E9}\u{1F1F4}"},{code:"EC",dialCode:"+593",name:"Ecuador",flag:"\u{1F1EA}\u{1F1E8}"},{code:"EG",dialCode:"+20",name:"Egypt",flag:"\u{1F1EA}\u{1F1EC}"},{code:"SV",dialCode:"+503",name:"El Salvador",flag:"\u{1F1F8}\u{1F1FB}"},{code:"GQ",dialCode:"+240",name:"Equatorial Guinea",flag:"\u{1F1EC}\u{1F1F6}"},{code:"ER",dialCode:"+291",name:"Eritrea",flag:"\u{1F1EA}\u{1F1F7}"},{code:"EE",dialCode:"+372",name:"Estonia",flag:"\u{1F1EA}\u{1F1EA}"},{code:"SZ",dialCode:"+268",name:"Eswatini",flag:"\u{1F1F8}\u{1F1FF}"},{code:"ET",dialCode:"+251",name:"Ethiopia",flag:"\u{1F1EA}\u{1F1F9}"},{code:"FJ",dialCode:"+679",name:"Fiji",flag:"\u{1F1EB}\u{1F1EF}"},{code:"FI",dialCode:"+358",name:"Finland",flag:"\u{1F1EB}\u{1F1EE}"},{code:"FR",dialCode:"+33",name:"France",flag:"\u{1F1EB}\u{1F1F7}"},{code:"GA",dialCode:"+241",name:"Gabon",flag:"\u{1F1EC}\u{1F1E6}"},{code:"GM",dialCode:"+220",name:"Gambia",flag:"\u{1F1EC}\u{1F1F2}"},{code:"GE",dialCode:"+995",name:"Georgia",flag:"\u{1F1EC}\u{1F1EA}"},{code:"DE",dialCode:"+49",name:"Germany",flag:"\u{1F1E9}\u{1F1EA}"},{code:"GH",dialCode:"+233",name:"Ghana",flag:"\u{1F1EC}\u{1F1ED}"},{code:"GR",dialCode:"+30",name:"Greece",flag:"\u{1F1EC}\u{1F1F7}"},{code:"GD",dialCode:"+1",name:"Grenada",flag:"\u{1F1EC}\u{1F1E9}"},{code:"GT",dialCode:"+502",name:"Guatemala",flag:"\u{1F1EC}\u{1F1F9}"},{code:"GN",dialCode:"+224",name:"Guinea",flag:"\u{1F1EC}\u{1F1F3}"},{code:"GW",dialCode:"+245",name:"Guinea-Bissau",flag:"\u{1F1EC}\u{1F1FC}"},{code:"GY",dialCode:"+592",name:"Guyana",flag:"\u{1F1EC}\u{1F1FE}"},{code:"HT",dialCode:"+509",name:"Haiti",flag:"\u{1F1ED}\u{1F1F9}"},{code:"HN",dialCode:"+504",name:"Honduras",flag:"\u{1F1ED}\u{1F1F3}"},{code:"HK",dialCode:"+852",name:"Hong Kong",flag:"\u{1F1ED}\u{1F1F0}"},{code:"HU",dialCode:"+36",name:"Hungary",flag:"\u{1F1ED}\u{1F1FA}"},{code:"IS",dialCode:"+354",name:"Iceland",flag:"\u{1F1EE}\u{1F1F8}"},{code:"IN",dialCode:"+91",name:"India",flag:"\u{1F1EE}\u{1F1F3}"},{code:"ID",dialCode:"+62",name:"Indonesia",flag:"\u{1F1EE}\u{1F1E9}"},{code:"IR",dialCode:"+98",name:"Iran",flag:"\u{1F1EE}\u{1F1F7}"},{code:"IQ",dialCode:"+964",name:"Iraq",flag:"\u{1F1EE}\u{1F1F6}"},{code:"IE",dialCode:"+353",name:"Ireland",flag:"\u{1F1EE}\u{1F1EA}"},{code:"IL",dialCode:"+972",name:"Israel",flag:"\u{1F1EE}\u{1F1F1}"},{code:"IT",dialCode:"+39",name:"Italy",flag:"\u{1F1EE}\u{1F1F9}"},{code:"JM",dialCode:"+1",name:"Jamaica",flag:"\u{1F1EF}\u{1F1F2}"},{code:"JP",dialCode:"+81",name:"Japan",flag:"\u{1F1EF}\u{1F1F5}"},{code:"JO",dialCode:"+962",name:"Jordan",flag:"\u{1F1EF}\u{1F1F4}"},{code:"KZ",dialCode:"+7",name:"Kazakhstan",flag:"\u{1F1F0}\u{1F1FF}"},{code:"KE",dialCode:"+254",name:"Kenya",flag:"\u{1F1F0}\u{1F1EA}"},{code:"KI",dialCode:"+686",name:"Kiribati",flag:"\u{1F1F0}\u{1F1EE}"},{code:"KW",dialCode:"+965",name:"Kuwait",flag:"\u{1F1F0}\u{1F1FC}"},{code:"KG",dialCode:"+996",name:"Kyrgyzstan",flag:"\u{1F1F0}\u{1F1EC}"},{code:"LA",dialCode:"+856",name:"Laos",flag:"\u{1F1F1}\u{1F1E6}"},{code:"LV",dialCode:"+371",name:"Latvia",flag:"\u{1F1F1}\u{1F1FB}"},{code:"LB",dialCode:"+961",name:"Lebanon",flag:"\u{1F1F1}\u{1F1E7}"},{code:"LS",dialCode:"+266",name:"Lesotho",flag:"\u{1F1F1}\u{1F1F8}"},{code:"LR",dialCode:"+231",name:"Liberia",flag:"\u{1F1F1}\u{1F1F7}"},{code:"LY",dialCode:"+218",name:"Libya",flag:"\u{1F1F1}\u{1F1FE}"},{code:"LI",dialCode:"+423",name:"Liechtenstein",flag:"\u{1F1F1}\u{1F1EE}"},{code:"LT",dialCode:"+370",name:"Lithuania",flag:"\u{1F1F1}\u{1F1F9}"},{code:"LU",dialCode:"+352",name:"Luxembourg",flag:"\u{1F1F1}\u{1F1FA}"},{code:"MO",dialCode:"+853",name:"Macao",flag:"\u{1F1F2}\u{1F1F4}"},{code:"MG",dialCode:"+261",name:"Madagascar",flag:"\u{1F1F2}\u{1F1EC}"},{code:"MW",dialCode:"+265",name:"Malawi",flag:"\u{1F1F2}\u{1F1FC}"},{code:"MY",dialCode:"+60",name:"Malaysia",flag:"\u{1F1F2}\u{1F1FE}"},{code:"MV",dialCode:"+960",name:"Maldives",flag:"\u{1F1F2}\u{1F1FB}"},{code:"ML",dialCode:"+223",name:"Mali",flag:"\u{1F1F2}\u{1F1F1}"},{code:"MT",dialCode:"+356",name:"Malta",flag:"\u{1F1F2}\u{1F1F9}"},{code:"MH",dialCode:"+692",name:"Marshall Islands",flag:"\u{1F1F2}\u{1F1ED}"},{code:"MR",dialCode:"+222",name:"Mauritania",flag:"\u{1F1F2}\u{1F1F7}"},{code:"MU",dialCode:"+230",name:"Mauritius",flag:"\u{1F1F2}\u{1F1FA}"},{code:"MX",dialCode:"+52",name:"Mexico",flag:"\u{1F1F2}\u{1F1FD}"},{code:"FM",dialCode:"+691",name:"Micronesia",flag:"\u{1F1EB}\u{1F1F2}"},{code:"MD",dialCode:"+373",name:"Moldova",flag:"\u{1F1F2}\u{1F1E9}"},{code:"MC",dialCode:"+377",name:"Monaco",flag:"\u{1F1F2}\u{1F1E8}"},{code:"MN",dialCode:"+976",name:"Mongolia",flag:"\u{1F1F2}\u{1F1F3}"},{code:"ME",dialCode:"+382",name:"Montenegro",flag:"\u{1F1F2}\u{1F1EA}"},{code:"MA",dialCode:"+212",name:"Morocco",flag:"\u{1F1F2}\u{1F1E6}"},{code:"MZ",dialCode:"+258",name:"Mozambique",flag:"\u{1F1F2}\u{1F1FF}"},{code:"MM",dialCode:"+95",name:"Myanmar",flag:"\u{1F1F2}\u{1F1F2}"},{code:"NA",dialCode:"+264",name:"Namibia",flag:"\u{1F1F3}\u{1F1E6}"},{code:"NR",dialCode:"+674",name:"Nauru",flag:"\u{1F1F3}\u{1F1F7}"},{code:"NP",dialCode:"+977",name:"Nepal",flag:"\u{1F1F3}\u{1F1F5}"},{code:"NL",dialCode:"+31",name:"Netherlands",flag:"\u{1F1F3}\u{1F1F1}"},{code:"NZ",dialCode:"+64",name:"New Zealand",flag:"\u{1F1F3}\u{1F1FF}"},{code:"NI",dialCode:"+505",name:"Nicaragua",flag:"\u{1F1F3}\u{1F1EE}"},{code:"NE",dialCode:"+227",name:"Niger",flag:"\u{1F1F3}\u{1F1EA}"},{code:"NG",dialCode:"+234",name:"Nigeria",flag:"\u{1F1F3}\u{1F1EC}"},{code:"KP",dialCode:"+850",name:"North Korea",flag:"\u{1F1F0}\u{1F1F5}"},{code:"MK",dialCode:"+389",name:"North Macedonia",flag:"\u{1F1F2}\u{1F1F0}"},{code:"NO",dialCode:"+47",name:"Norway",flag:"\u{1F1F3}\u{1F1F4}"},{code:"OM",dialCode:"+968",name:"Oman",flag:"\u{1F1F4}\u{1F1F2}"},{code:"PK",dialCode:"+92",name:"Pakistan",flag:"\u{1F1F5}\u{1F1F0}"},{code:"PW",dialCode:"+680",name:"Palau",flag:"\u{1F1F5}\u{1F1FC}"},{code:"PS",dialCode:"+970",name:"Palestine",flag:"\u{1F1F5}\u{1F1F8}"},{code:"PA",dialCode:"+507",name:"Panama",flag:"\u{1F1F5}\u{1F1E6}"},{code:"PG",dialCode:"+675",name:"Papua New Guinea",flag:"\u{1F1F5}\u{1F1EC}"},{code:"PY",dialCode:"+595",name:"Paraguay",flag:"\u{1F1F5}\u{1F1FE}"},{code:"PE",dialCode:"+51",name:"Peru",flag:"\u{1F1F5}\u{1F1EA}"},{code:"PH",dialCode:"+63",name:"Philippines",flag:"\u{1F1F5}\u{1F1ED}"},{code:"PL",dialCode:"+48",name:"Poland",flag:"\u{1F1F5}\u{1F1F1}"},{code:"PT",dialCode:"+351",name:"Portugal",flag:"\u{1F1F5}\u{1F1F9}"},{code:"PR",dialCode:"+1",name:"Puerto Rico",flag:"\u{1F1F5}\u{1F1F7}"},{code:"QA",dialCode:"+974",name:"Qatar",flag:"\u{1F1F6}\u{1F1E6}"},{code:"RO",dialCode:"+40",name:"Romania",flag:"\u{1F1F7}\u{1F1F4}"},{code:"RU",dialCode:"+7",name:"Russia",flag:"\u{1F1F7}\u{1F1FA}"},{code:"RW",dialCode:"+250",name:"Rwanda",flag:"\u{1F1F7}\u{1F1FC}"},{code:"KN",dialCode:"+1",name:"Saint Kitts and Nevis",flag:"\u{1F1F0}\u{1F1F3}"},{code:"LC",dialCode:"+1",name:"Saint Lucia",flag:"\u{1F1F1}\u{1F1E8}"},{code:"VC",dialCode:"+1",name:"Saint Vincent and the Grenadines",flag:"\u{1F1FB}\u{1F1E8}"},{code:"WS",dialCode:"+685",name:"Samoa",flag:"\u{1F1FC}\u{1F1F8}"},{code:"SM",dialCode:"+378",name:"San Marino",flag:"\u{1F1F8}\u{1F1F2}"},{code:"ST",dialCode:"+239",name:"Sao Tome and Principe",flag:"\u{1F1F8}\u{1F1F9}"},{code:"SA",dialCode:"+966",name:"Saudi Arabia",flag:"\u{1F1F8}\u{1F1E6}"},{code:"SN",dialCode:"+221",name:"Senegal",flag:"\u{1F1F8}\u{1F1F3}"},{code:"RS",dialCode:"+381",name:"Serbia",flag:"\u{1F1F7}\u{1F1F8}"},{code:"SC",dialCode:"+248",name:"Seychelles",flag:"\u{1F1F8}\u{1F1E8}"},{code:"SL",dialCode:"+232",name:"Sierra Leone",flag:"\u{1F1F8}\u{1F1F1}"},{code:"SG",dialCode:"+65",name:"Singapore",flag:"\u{1F1F8}\u{1F1EC}"},{code:"SK",dialCode:"+421",name:"Slovakia",flag:"\u{1F1F8}\u{1F1F0}"},{code:"SI",dialCode:"+386",name:"Slovenia",flag:"\u{1F1F8}\u{1F1EE}"},{code:"SB",dialCode:"+677",name:"Solomon Islands",flag:"\u{1F1F8}\u{1F1E7}"},{code:"SO",dialCode:"+252",name:"Somalia",flag:"\u{1F1F8}\u{1F1F4}"},{code:"ZA",dialCode:"+27",name:"South Africa",flag:"\u{1F1FF}\u{1F1E6}"},{code:"KR",dialCode:"+82",name:"South Korea",flag:"\u{1F1F0}\u{1F1F7}"},{code:"SS",dialCode:"+211",name:"South Sudan",flag:"\u{1F1F8}\u{1F1F8}"},{code:"ES",dialCode:"+34",name:"Spain",flag:"\u{1F1EA}\u{1F1F8}"},{code:"LK",dialCode:"+94",name:"Sri Lanka",flag:"\u{1F1F1}\u{1F1F0}"},{code:"SD",dialCode:"+249",name:"Sudan",flag:"\u{1F1F8}\u{1F1E9}"},{code:"SR",dialCode:"+597",name:"Suriname",flag:"\u{1F1F8}\u{1F1F7}"},{code:"SE",dialCode:"+46",name:"Sweden",flag:"\u{1F1F8}\u{1F1EA}"},{code:"CH",dialCode:"+41",name:"Switzerland",flag:"\u{1F1E8}\u{1F1ED}"},{code:"SY",dialCode:"+963",name:"Syria",flag:"\u{1F1F8}\u{1F1FE}"},{code:"TW",dialCode:"+886",name:"Taiwan",flag:"\u{1F1F9}\u{1F1FC}"},{code:"TJ",dialCode:"+992",name:"Tajikistan",flag:"\u{1F1F9}\u{1F1EF}"},{code:"TZ",dialCode:"+255",name:"Tanzania",flag:"\u{1F1F9}\u{1F1FF}"},{code:"TH",dialCode:"+66",name:"Thailand",flag:"\u{1F1F9}\u{1F1ED}"},{code:"TL",dialCode:"+670",name:"Timor-Leste",flag:"\u{1F1F9}\u{1F1F1}"},{code:"TG",dialCode:"+228",name:"Togo",flag:"\u{1F1F9}\u{1F1EC}"},{code:"TO",dialCode:"+676",name:"Tonga",flag:"\u{1F1F9}\u{1F1F4}"},{code:"TT",dialCode:"+1",name:"Trinidad and Tobago",flag:"\u{1F1F9}\u{1F1F9}"},{code:"TN",dialCode:"+216",name:"Tunisia",flag:"\u{1F1F9}\u{1F1F3}"},{code:"TR",dialCode:"+90",name:"Turkey",flag:"\u{1F1F9}\u{1F1F7}"},{code:"TM",dialCode:"+993",name:"Turkmenistan",flag:"\u{1F1F9}\u{1F1F2}"},{code:"TV",dialCode:"+688",name:"Tuvalu",flag:"\u{1F1F9}\u{1F1FB}"},{code:"UG",dialCode:"+256",name:"Uganda",flag:"\u{1F1FA}\u{1F1EC}"},{code:"UA",dialCode:"+380",name:"Ukraine",flag:"\u{1F1FA}\u{1F1E6}"},{code:"AE",dialCode:"+971",name:"United Arab Emirates",flag:"\u{1F1E6}\u{1F1EA}"},{code:"GB",dialCode:"+44",name:"United Kingdom",flag:"\u{1F1EC}\u{1F1E7}"},{code:"US",dialCode:"+1",name:"United States",flag:"\u{1F1FA}\u{1F1F8}"},{code:"UY",dialCode:"+598",name:"Uruguay",flag:"\u{1F1FA}\u{1F1FE}"},{code:"UZ",dialCode:"+998",name:"Uzbekistan",flag:"\u{1F1FA}\u{1F1FF}"},{code:"VU",dialCode:"+678",name:"Vanuatu",flag:"\u{1F1FB}\u{1F1FA}"},{code:"VA",dialCode:"+39",name:"Vatican City",flag:"\u{1F1FB}\u{1F1E6}"},{code:"VE",dialCode:"+58",name:"Venezuela",flag:"\u{1F1FB}\u{1F1EA}"},{code:"VN",dialCode:"+84",name:"Vietnam",flag:"\u{1F1FB}\u{1F1F3}"},{code:"YE",dialCode:"+967",name:"Yemen",flag:"\u{1F1FE}\u{1F1EA}"},{code:"ZM",dialCode:"+260",name:"Zambia",flag:"\u{1F1FF}\u{1F1F2}"},{code:"ZW",dialCode:"+263",name:"Zimbabwe",flag:"\u{1F1FF}\u{1F1FC}"}],V=new Map(P.map(e=>[e.code,e])),j={"America/New_York":"US","America/Chicago":"US","America/Denver":"US","America/Los_Angeles":"US","America/Anchorage":"US","Pacific/Honolulu":"US","America/Phoenix":"US","America/Indiana/Indianapolis":"US","America/Toronto":"CA","America/Vancouver":"CA","America/Edmonton":"CA","America/Winnipeg":"CA","America/Halifax":"CA","America/St_Johns":"CA","Europe/London":"GB","Europe/Dublin":"IE","Europe/Paris":"FR","Europe/Berlin":"DE","Europe/Madrid":"ES","Europe/Rome":"IT","Europe/Amsterdam":"NL","Europe/Brussels":"BE","Europe/Zurich":"CH","Europe/Vienna":"AT","Europe/Stockholm":"SE","Europe/Oslo":"NO","Europe/Copenhagen":"DK","Europe/Helsinki":"FI","Europe/Warsaw":"PL","Europe/Prague":"CZ","Europe/Bucharest":"RO","Europe/Budapest":"HU","Europe/Athens":"GR","Europe/Istanbul":"TR","Europe/Moscow":"RU","Europe/Kiev":"UA","Europe/Lisbon":"PT","Europe/Belgrade":"RS","Europe/Zagreb":"HR","Europe/Bratislava":"SK","Europe/Ljubljana":"SI","Europe/Tallinn":"EE","Europe/Riga":"LV","Europe/Vilnius":"LT","Asia/Tokyo":"JP","Asia/Seoul":"KR","Asia/Shanghai":"CN","Asia/Hong_Kong":"HK","Asia/Taipei":"TW","Asia/Singapore":"SG","Asia/Kolkata":"IN","Asia/Karachi":"PK","Asia/Dhaka":"BD","Asia/Bangkok":"TH","Asia/Jakarta":"ID","Asia/Manila":"PH","Asia/Kuala_Lumpur":"MY","Asia/Ho_Chi_Minh":"VN","Asia/Riyadh":"SA","Asia/Dubai":"AE","Asia/Tehran":"IR","Asia/Baghdad":"IQ","Asia/Beirut":"LB","Asia/Jerusalem":"IL","Asia/Amman":"JO","Asia/Almaty":"KZ","Asia/Tashkent":"UZ","Asia/Colombo":"LK","Asia/Kathmandu":"NP","Asia/Yangon":"MM","Australia/Sydney":"AU","Australia/Melbourne":"AU","Australia/Brisbane":"AU","Australia/Perth":"AU","Australia/Adelaide":"AU","Pacific/Auckland":"NZ","Pacific/Fiji":"FJ","Africa/Cairo":"EG","Africa/Lagos":"NG","Africa/Nairobi":"KE","Africa/Johannesburg":"ZA","Africa/Casablanca":"MA","Africa/Accra":"GH","Africa/Addis_Ababa":"ET","Africa/Dar_es_Salaam":"TZ","Africa/Kampala":"UG","America/Mexico_City":"MX","America/Bogota":"CO","America/Lima":"PE","America/Santiago":"CL","America/Buenos_Aires":"AR","America/Sao_Paulo":"BR","America/Caracas":"VE","America/Guatemala":"GT","America/Havana":"CU","America/Panama":"PA","America/Jamaica":"JM"};function B(){try{let e=Intl.DateTimeFormat().resolvedOptions().timeZone;return j[e]??"US"}catch{return"US"}}function R(e){if(!e.startsWith("+"))return e;let a=e.slice(1);if(a.startsWith("1")&&a.length===11){let o=a.slice(1,4),i=a.slice(4,7),t=a.slice(7);return`+1 (${o}) ${i}-${t}`}for(let o=4;o>=1;o--){let i="+"+a.slice(0,o),t=P.find(n=>n.dialCode===i);if(t){let n=a.slice(o);return`${t.dialCode} ${n}`}}return e}function I(e,a){let o=e.replace(/\D/g,""),i=V.get(a);if(!i)return"+"+o;let t=i.dialCode.slice(1);return o.startsWith(t)?"+"+o:i.dialCode+o}function _(e){return/^\+[1-9]\d{6,14}$/.test(e)}function O(e){return/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e)}async function C(e,a,o){let t={Authorization:`Bearer ${c().token}`};o!==void 0&&(t["Content-Type"]="application/json");let n=await fetch(e,{method:a,headers:t,...o!==void 0&&{body:JSON.stringify(o)}});if(!n.ok){let r=`Auth request failed: ${n.status} ${n.statusText}`,l="auth_error";try{let s=await n.json();s.error&&(r=s.error),s.code&&(l=s.code)}catch{}throw new d(r,l,n.status)}return await n.json()}var v=new Set;function b(e){x({token:e.token,user:e.user,methods:e.methods}),v.forEach(a=>a(e.user))}function k(e){if(!e.user)throw new d("Verification succeeded but no user was returned","auth_error");return e.user}function L(e){let a=c();a.user&&(Object.assign(a.user,e),v.forEach(o=>o(a.user)))}var Z={get currentUser(){return c().user},getCurrentUser(){return c().user},isAuthenticated(){return c().user!==null},sendEmailCode(e){return C("/_/auth/email/send","POST",{email:e})},async verifyEmailCode(e,a){let o=await C("/_/auth/email/verify","POST",{verificationId:e,code:a});return b(o),k(o)},sendSmsCode(e){return C("/_/auth/sms/send","POST",{phone:e})},async verifySmsCode(e,a){let o=await C("/_/auth/sms/verify","POST",{verificationId:e,code:a});return b(o),k(o)},async requestEmailChange(e){await C("/_/auth/email/change","POST",{newEmail:e})},async confirmEmailChange(e,a){let o=await C("/_/auth/email/change/confirm","POST",{newEmail:e,code:a});return b(o),k(o)},async requestPhoneChange(e){await C("/_/auth/phone/change","POST",{newPhone:e})},async confirmPhoneChange(e,a){let o=await C("/_/auth/phone/change/confirm","POST",{newPhone:e,code:a});return b(o),k(o)},async logout(){let e=await C("/_/auth/logout","POST",{});b(e)},async createApiKey(){let e=await C("/_/auth/api-key/create","POST",{});return L({apiKey:e.apiKey}),{key:e.key}},async revokeApiKey(){await C("/_/auth/api-key/revoke","POST",{}),L({apiKey:null})},onAuthStateChanged(e){return v.add(e),e(c().user),()=>{v.delete(e)}},phone:{countries:P,detectCountry:B,format:R,toE164:I,isValid:_},email:{isValid:O}};export{d as MindStudioInterfaceError,Z as auth,K as createAgentChatClient,G as createClient,H as platform};
|
|
4
4
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/config.ts","../src/client.ts","../src/agent-chat.ts","../src/platform.ts","../src/auth-phone.ts","../src/auth-email.ts","../src/auth.ts"],"sourcesContent":["/**\n * Error class for the @mindstudio-ai/interface SDK.\n *\n * Thrown by `createClient()` method calls on HTTP errors, by `platform`\n * actions on failures, and by the config reader when bootstrap globals\n * are missing.\n */\nexport class MindStudioInterfaceError extends Error {\n /** Machine-readable error code (e.g. 'method_not_found', 'not_initialized'). */\n readonly code: string;\n\n /** HTTP status code, when the error originated from an API response. */\n readonly status?: number;\n\n constructor(message: string, code: string, status?: number) {\n super(message);\n this.name = 'MindStudioInterfaceError';\n this.code = code;\n this.status = status;\n }\n}\n","/**\n * Bootstrap configuration reader.\n *\n * Reads and validates `window.__MINDSTUDIO__` — the globals injected by\n * the platform before the app's JavaScript runs. The result is cached\n * after first read.\n *\n * All other modules in the SDK call `getConfig()` internally. App code\n * should never need to call this directly — use `createClient()`, `auth`,\n * and `platform` instead.\n */\n\nimport { MindStudioInterfaceError } from './errors.js';\nimport type { AppUser, BootstrapConfig } from './types.js';\n\nlet _config: BootstrapConfig | undefined;\n\n/**\n * Read and validate the bootstrap configuration from `window.__MINDSTUDIO__`.\n *\n * Caches the result after first successful read. Throws if the globals\n * are missing or incomplete — this means the page isn't running inside\n * the MindStudio platform.\n *\n * @returns The validated bootstrap config\n * @throws {MindStudioInterfaceError} if `window.__MINDSTUDIO__` is missing or invalid\n */\nexport function getConfig(): BootstrapConfig {\n if (_config) {\n return _config;\n }\n\n const raw = (globalThis as Record<string, unknown>).__MINDSTUDIO__ as\n | Partial<BootstrapConfig>\n | undefined;\n\n if (!raw) {\n throw new MindStudioInterfaceError(\n '@mindstudio-ai/interface requires the MindStudio platform context. ' +\n 'This page must be loaded inside MindStudio (window.__MINDSTUDIO__ is missing).',\n 'not_initialized',\n );\n }\n\n // Validate required fields (user can be null for unauthenticated sessions)\n if (!raw.token || !raw.releaseId || !raw.methods) {\n const missing = ['token', 'releaseId', 'methods']\n .filter((k) => !raw[k as keyof BootstrapConfig])\n .join(', ');\n\n throw new MindStudioInterfaceError(\n `MindStudio platform context is incomplete. Missing: ${missing}`,\n 'invalid_config',\n );\n }\n\n _config = raw as BootstrapConfig;\n return _config;\n}\n\n/**\n * Update the cached config in-place after an auth state transition.\n *\n * The cached config is a mutable reference — all SDK modules read it\n * on-demand via `getConfig()`, so mutations propagate immediately to\n * method invocation, agent chat, uploads, etc.\n *\n * @internal Not exported from the package — used by the auth module only.\n */\nexport function updateConfig(updates: {\n token?: string;\n user?: AppUser | null;\n methods?: Record<string, string>;\n}): void {\n const config = getConfig();\n if (updates.token !== undefined) {\n config.token = updates.token;\n }\n if (updates.user !== undefined) {\n config.user = updates.user;\n }\n if (updates.methods !== undefined) {\n config.methods = updates.methods;\n }\n}\n","/**\n * Method RPC client — typed function calls to backend methods.\n *\n * `createClient()` returns a Proxy where every property access creates\n * an async function that invokes the corresponding backend method via HTTP.\n * The method name matches the method's `export` field in `app.json`.\n *\n * ## How it works\n *\n * ```\n * api.submitVendorRequest({ name: 'Acme' })\n * │\n * ├─ Look up method ID: config.methods[\"submitVendorRequest\"]\n * │ → \"submit-vendor-request\"\n * │\n * ├─ POST /_/methods/submit-vendor-request/invoke\n * │ Authorization: Bearer {session token}\n * │ Body: { input: { name: \"Acme\" } }\n * │\n * └─ Returns response.output (or throws on error)\n * ```\n *\n * The method registry (export name → method ID mapping) is embedded in\n * `window.__MINDSTUDIO__.methods` at page load time — no extra HTTP call\n * needed to discover methods.\n *\n * ## Streaming\n *\n * Methods can optionally stream LLM token output via SSE. Pass\n * `{ stream: true }` as the second argument along with an `onToken`\n * callback to receive incremental updates:\n *\n * ```ts\n * const result = await api.submitVendorRequest({ name: 'Acme' }, {\n * stream: true,\n * onToken: (text) => setResponseText(text),\n * });\n * ```\n *\n * **Important:** The `text` value passed to `onToken` is the accumulated\n * response so far (not a delta). Replace your display content each time —\n * do not append. See {@link InvokeOptions.onToken} for details.\n *\n * ## Type safety\n *\n * Since the frontend and backend live in the same project, you can import\n * types directly:\n *\n * ```ts\n * import type { SubmitVendorInput, SubmitVendorOutput }\n * from '../../backend/src/submitVendorRequest';\n *\n * interface AppMethods {\n * submitVendorRequest(input: SubmitVendorInput): Promise<SubmitVendorOutput>;\n * getDashboard(): Promise<GetDashboardOutput>;\n * }\n *\n * const api = createClient<AppMethods>();\n * const result = await api.submitVendorRequest({ name: 'Acme' }); // fully typed\n * ```\n *\n * If no type parameter is provided, methods accept `any` input and return `any`.\n */\n\nimport { getConfig } from './config.js';\nimport { MindStudioInterfaceError } from './errors.js';\n\n/**\n * Options for method invocation. Pass as the optional second argument to\n * any method on the client returned by {@link createClient}.\n *\n * When `stream` is `true`, the SDK sends `{ stream: true }` in the request\n * body and parses the response as an SSE (Server-Sent Events) stream.\n * Three event types are handled:\n *\n * | SSE `type` | Payload field | SDK action |\n * |------------|---------------|------------|\n * | `token` | `text` | Calls {@link onToken} with accumulated text |\n * | `error` | `error` | Calls {@link onStreamError} with the message |\n * | `done` | `output` | Captures as the method's return value |\n *\n * The method's `Promise` resolves with the final `output` from the `done`\n * event — the same shape you'd get without streaming.\n */\nexport interface InvokeOptions {\n /**\n * Enable SSE streaming for LLM token output.\n *\n * When `true`, the request body includes `{ stream: true }` and the\n * response is parsed as an SSE stream instead of a single JSON payload.\n * The method still returns a `Promise` that resolves with the final\n * output once the stream completes.\n *\n * @default false\n */\n stream?: boolean;\n\n /**\n * Called with the accumulated response text each time a new token arrives.\n *\n * **Important:** `text` is the full response so far, not a delta/chunk.\n * Your frontend should **replace** (not append to) its display content\n * with this value each time the callback fires.\n *\n * This design avoids edge cases where the platform sanitizes or\n * reformats JSON mid-stream, causing earlier portions of the text to\n * change between tokens.\n *\n * @example\n * ```ts\n * const result = await api.generate({ prompt: 'Hello' }, {\n * stream: true,\n * onToken: (text) => {\n * // Replace — do NOT append\n * responseElement.textContent = text;\n * },\n * });\n * ```\n */\n onToken?: (text: string) => void;\n\n /**\n * Called if a stream-level error occurs.\n *\n * Stream errors are non-fatal at the protocol level — the method may\n * still complete and resolve with a final output. Use this callback for\n * logging or showing a transient warning, not for control flow.\n *\n * If the stream ends without a `done` event, the method rejects with a\n * `MindStudioInterfaceError` (code `stream_incomplete`) regardless of\n * whether `onStreamError` was provided.\n */\n onStreamError?: (error: string) => void;\n}\n\n/**\n * Default client type when no generic parameter is provided.\n * Every property returns an async function accepting optional input\n * and optional {@link InvokeOptions} for streaming.\n */\ntype DefaultMethodClient = Record<\n string,\n (input?: Record<string, unknown>, options?: InvokeOptions) => Promise<unknown>\n>;\n\n/**\n * Create a typed RPC client for calling backend methods.\n *\n * @typeParam T - Optional interface mapping method names to their signatures.\n * If omitted, all methods accept `any` and return `Promise<any>`.\n *\n * @returns A Proxy object where each property is an async function that\n * invokes the corresponding backend method.\n *\n * @example\n * ```ts\n * import { createClient } from '@mindstudio-ai/interface';\n *\n * const api = createClient();\n *\n * // Each method maps to a backend method export\n * const result = await api.submitVendorRequest({ name: 'Acme' });\n * const dashboard = await api.getDashboard();\n *\n * // Stream LLM output — onToken receives accumulated text (replace, don't append)\n * const streamed = await api.submitVendorRequest({ name: 'Acme' }, {\n * stream: true,\n * onToken: (text) => setResponseText(text),\n * });\n * // `streamed` is the same final output you'd get without streaming\n * ```\n */\nexport function createClient<T = DefaultMethodClient>(): T {\n return new Proxy({} as Record<string, unknown> as T & object, {\n get(_, methodName: string) {\n return async (input?: unknown, options?: InvokeOptions) => {\n const config = getConfig();\n\n const methodId = config.methods[methodName];\n if (!methodId) {\n throw new MindStudioInterfaceError(\n `Method \"${methodName}\" not found. Available methods: ${Object.keys(config.methods).join(', ') || '(none)'}`,\n 'method_not_found',\n );\n }\n\n const url = `/_/methods/${methodId}/invoke`;\n const wantsStream = options?.stream === true;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${config.token}`,\n },\n body: JSON.stringify({\n input: input ?? {},\n ...(wantsStream && { stream: true }),\n }),\n });\n\n if (!res.ok) {\n let errorMessage = `Method \"${methodName}\" failed: ${res.status} ${res.statusText}`;\n let errorCode = 'method_error';\n try {\n const body = (await res.json()) as {\n error?: string;\n code?: string;\n };\n if (body.error) {\n errorMessage = body.error;\n }\n if (body.code) {\n errorCode = body.code;\n }\n } catch {\n // Response wasn't JSON — use the default message\n }\n throw new MindStudioInterfaceError(\n errorMessage,\n errorCode,\n res.status,\n );\n }\n\n // Non-streaming: unchanged behavior\n if (!wantsStream) {\n const body = (await res.json()) as { output?: unknown };\n return body.output;\n }\n\n // Streaming: parse SSE events from response body\n const reader = res.body!.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n let finalOutput: unknown;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n\n for (const line of lines) {\n if (!line.startsWith('data: ')) {\n continue;\n }\n const json = line.slice(6);\n try {\n const event = JSON.parse(json) as {\n type: string;\n text?: string;\n error?: string;\n output?: unknown;\n };\n\n if (event.type === 'token' && options?.onToken && event.text) {\n options.onToken(event.text);\n } else if (event.type === 'error' && event.error) {\n if (options?.onStreamError) {\n options.onStreamError(event.error);\n }\n } else if (event.type === 'done') {\n finalOutput = event.output;\n }\n } catch {\n // Skip malformed SSE lines\n }\n }\n }\n\n if (finalOutput === undefined) {\n throw new MindStudioInterfaceError(\n 'Stream ended without a done event',\n 'stream_incomplete',\n );\n }\n\n return finalOutput;\n };\n },\n });\n}\n","/**\n * Agent chat client — thread-based conversations with AI agents.\n *\n * `createAgentChatClient()` returns an object with methods for thread\n * lifecycle (create, list, get, rename, delete) and message streaming.\n * The agent runs server-side with access to the app's methods as tools.\n *\n * ## How it works\n *\n * ```\n * chat.sendMessage(threadId, 'Help me prep for my review', {\n * onText: (delta) => setAssistantMessage((prev) => prev + delta),\n * })\n * │\n * ├─ POST /_/agent/threads/{threadId}/messages\n * │ Authorization: Bearer {session token}\n * │ Body: { content: \"Help me prep for my review\" }\n * │\n * ├─ Response: SSE stream\n * │ data: {\"type\":\"text\",\"text\":\"I'll create...\",\"ts\":1711...}\n * │ data: {\"type\":\"tool_call_start\",\"id\":\"call_abc\",\"name\":\"create-todo\",\"ts\":1711...}\n * │ data: {\"type\":\"tool_call_result\",\"id\":\"call_abc\",\"output\":{...},\"ts\":1711...}\n * │ data: {\"type\":\"text\",\"text\":\"Done — added it.\",\"ts\":1711...}\n * │ data: {\"type\":\"done\",\"stopReason\":\"end_turn\",\"usage\":{...},\"ts\":1711...}\n * │\n * └─ Promise resolves with { stopReason, usage }\n * ```\n *\n * ## Stateless design\n *\n * This client is a thin wrapper over HTTP endpoints. It does not manage\n * local state — your React/framework layer owns the thread list, message\n * array, and UI state. Each method is an independent request.\n *\n * ## Streaming callbacks\n *\n * `sendMessage` accepts named callbacks for common events (onText,\n * onThinking, onToolCallStart, etc.) plus a catch-all `onEvent` that\n * receives every SSE event as a discriminated union. Both fire for the\n * same event — use named callbacks for convenience, `onEvent` for\n * logging or handling low-level events like `tool_use` and\n * `tool_input_delta`.\n *\n * @example\n * ```ts\n * import { createAgentChatClient } from '@mindstudio-ai/interface';\n *\n * const chat = createAgentChatClient();\n *\n * // Thread lifecycle\n * const thread = await chat.createThread();\n * const { threads } = await chat.listThreads();\n * const full = await chat.getThread(thread.id);\n *\n * // Send a message with streaming\n * const response = chat.sendMessage(thread.id, 'Hello!', {\n * onText: (delta) => setMessage((prev) => prev + delta),\n * onToolCallStart: (id, name) => showToolSpinner(name),\n * onToolCallResult: (id, output) => showToolResult(output),\n * });\n *\n * const { stopReason, usage } = await response;\n *\n * // Abort mid-stream\n * response.abort();\n * ```\n */\n\nimport { getConfig } from './config.js';\nimport { MindStudioInterfaceError } from './errors.js';\n\n// ---------------------------------------------------------------------------\n// Thread types\n// ---------------------------------------------------------------------------\n\n/** Thread summary returned from create and list endpoints. */\nexport interface ThreadSummary {\n /** Thread ID (UUID). */\n id: string;\n /** User-editable title, auto-generated on first message. */\n title: string | null;\n /** ISO 8601 creation timestamp. */\n dateCreated: string;\n /** ISO 8601 last-updated timestamp. */\n dateUpdated: string;\n}\n\n/** Full thread with message history, returned from get endpoint. */\nexport interface Thread {\n /** Thread ID (UUID). */\n id: string;\n /** User-editable title. */\n title: string | null;\n /** Full conversation history. */\n messages: Message[];\n /** ISO 8601 creation timestamp. */\n dateCreated: string;\n /** ISO 8601 last-updated timestamp. */\n dateUpdated: string;\n}\n\n/** A tool call requested by the assistant. */\nexport interface ToolCall {\n /** Tool call ID, used to match results. */\n id: string;\n /** Method name. */\n name: string;\n /** Input arguments. */\n input: Record<string, unknown>;\n}\n\n/** A single message in a thread's conversation history. */\nexport interface Message {\n /** `\"user\"` for human messages, `\"assistant\"` for agent responses. */\n role: 'user' | 'assistant';\n /** Message text content. For tool results, this is JSON-stringified output. */\n content: string;\n /**\n * MindStudio CDN URLs attached to this message (user messages only).\n *\n * Images (`i.mscdn.ai`) are sent to the model as vision input.\n * Documents (`f.mscdn.ai`, `files.mindstudio-cdn.com`) have their text\n * extracted server-side and included in the model context. The original\n * URLs are preserved in thread history for the frontend to render.\n */\n attachments?: string[];\n /** Tool calls the assistant requested (assistant messages only). */\n toolCalls?: ToolCall[];\n /** ID of the tool call this message is a result for (tool result messages only). */\n toolCallId?: string;\n /** Whether this tool result represents an error. */\n isToolError?: boolean;\n}\n\n/** Paginated thread list response. */\nexport interface ThreadListPage {\n /** Threads for this page. */\n threads: ThreadSummary[];\n /** Cursor for the next page, or `null` if this is the last page. */\n nextCursor: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// SSE event types\n// ---------------------------------------------------------------------------\n\n/** Assistant text delta — append to your display string, do not replace. */\nexport interface AgentTextEvent {\n type: 'text';\n text: string;\n ts: number;\n}\n\n/** Model thinking text (extended thinking). */\nexport interface AgentThinkingEvent {\n type: 'thinking';\n text: string;\n ts: number;\n}\n\n/** Thinking complete with full text and signature. */\nexport interface AgentThinkingCompleteEvent {\n type: 'thinking_complete';\n thinking: string;\n signature: string;\n ts: number;\n}\n\n/** Model requested a tool call (includes parsed input). */\nexport interface AgentToolUseEvent {\n type: 'tool_use';\n id: string;\n name: string;\n input: Record<string, unknown>;\n ts: number;\n}\n\n/** Streaming delta for tool call input JSON. */\nexport interface AgentToolInputDeltaEvent {\n type: 'tool_input_delta';\n id: string;\n name: string;\n delta: string;\n ts: number;\n}\n\n/** Agent began executing a tool call. */\nexport interface AgentToolCallStartEvent {\n type: 'tool_call_start';\n id: string;\n name: string;\n ts: number;\n}\n\n/** Tool call returned a result. */\nexport interface AgentToolCallResultEvent {\n type: 'tool_call_result';\n id: string;\n output: unknown;\n ts: number;\n}\n\n/** Stream complete. */\nexport interface AgentDoneEvent {\n type: 'done';\n stopReason: string;\n usage: { inputTokens: number; outputTokens: number };\n ts: number;\n}\n\n/** Stream-level error. */\nexport interface AgentErrorEvent {\n type: 'error';\n error: string;\n ts: number;\n}\n\n/** Discriminated union of all SSE events from the agent chat stream. */\nexport type AgentChatEvent =\n | AgentTextEvent\n | AgentThinkingEvent\n | AgentThinkingCompleteEvent\n | AgentToolUseEvent\n | AgentToolInputDeltaEvent\n | AgentToolCallStartEvent\n | AgentToolCallResultEvent\n | AgentDoneEvent\n | AgentErrorEvent;\n\n// ---------------------------------------------------------------------------\n// Callbacks and result types\n// ---------------------------------------------------------------------------\n\n/**\n * Callbacks for `sendMessage` streaming.\n *\n * Named callbacks fire for common events. The catch-all `onEvent` fires\n * for every event including those with named callbacks — use it for\n * logging or handling low-level events like `tool_use` and\n * `tool_input_delta`.\n */\nexport interface SendMessageCallbacks {\n /**\n * Called with each text delta as the assistant responds.\n *\n * **Important:** `text` is a delta (new chunk), not the accumulated\n * response. Append it to your display string — do not replace.\n *\n * @example\n * ```ts\n * onText: (delta) => setMessage((prev) => prev + delta)\n * ```\n */\n onText?: (text: string) => void;\n\n /** Called with model thinking text (extended thinking). */\n onThinking?: (text: string) => void;\n\n /** Called when thinking is complete. */\n onThinkingComplete?: (thinking: string, signature: string) => void;\n\n /** Called when a tool call begins executing. */\n onToolCallStart?: (id: string, name: string) => void;\n\n /** Called when a tool call produces a result. */\n onToolCallResult?: (id: string, output: unknown) => void;\n\n /** Called on a stream-level error event. */\n onError?: (error: string) => void;\n\n /** Called for every SSE event (including ones with named callbacks). */\n onEvent?: (event: AgentChatEvent) => void;\n\n /** AbortSignal to cancel the stream. */\n signal?: AbortSignal;\n}\n\n/** Options for `sendMessage`. */\nexport interface SendMessageOptions {\n /**\n * MindStudio CDN URLs to attach to the message.\n *\n * Images (`i.mscdn.ai`) are sent to the model as vision input (one per message).\n * Documents (`f.mscdn.ai`, `files.mindstudio-cdn.com`) have their text\n * extracted server-side and included in context.\n *\n * Upload files first via `platform.uploadFile()`.\n *\n * @example\n * ```ts\n * const url = await platform.uploadFile(file);\n * chat.sendMessage(threadId, 'What is this?', callbacks, {\n * attachments: [url],\n * });\n * ```\n */\n attachments?: string[];\n}\n\n/** Resolved value of `sendMessage` — extracted from the `done` event. */\nexport interface SendMessageResult {\n /** Why the agent stopped (`\"end_turn\"`, `\"max_tokens\"`, etc.). */\n stopReason: string;\n /** Token usage for the full agent loop. */\n usage: { inputTokens: number; outputTokens: number };\n}\n\n/** A Promise with an `abort()` method for cancelling the stream. */\nexport type AbortablePromise<T> = Promise<T> & {\n /** Cancel the in-flight stream. The promise rejects with `AbortError`. */\n abort: () => void;\n};\n\n// ---------------------------------------------------------------------------\n// Client interface\n// ---------------------------------------------------------------------------\n\n/** Agent chat client returned by {@link createAgentChatClient}. */\nexport interface AgentChatClient {\n /** Create a new conversation thread. */\n createThread(): Promise<ThreadSummary>;\n\n /** List threads with cursor-based pagination (50 per page). */\n listThreads(cursor?: string): Promise<ThreadListPage>;\n\n /** Get a thread with its full message history. */\n getThread(threadId: string): Promise<Thread>;\n\n /** Update a thread's title. */\n updateThread(threadId: string, title: string): Promise<void>;\n\n /** Delete a thread (soft delete). */\n deleteThread(threadId: string): Promise<void>;\n\n /**\n * Send a message and stream the agent's response.\n *\n * Returns an {@link AbortablePromise} that resolves with\n * `{ stopReason, usage }` when the stream completes. Call `.abort()`\n * on the returned promise to cancel mid-stream.\n *\n * @param options.attachments - MindStudio CDN URLs to attach.\n * Images (`i.mscdn.ai`) are sent as vision input.\n * Documents (`f.mscdn.ai`) have text extracted into context.\n * Upload files first via `platform.uploadFile()`.\n */\n sendMessage(\n threadId: string,\n content: string,\n callbacks?: SendMessageCallbacks,\n options?: SendMessageOptions,\n ): AbortablePromise<SendMessageResult>;\n}\n\n// ---------------------------------------------------------------------------\n// Private helpers\n// ---------------------------------------------------------------------------\n\nconst AGENT_BASE = '/_/agent';\n\nasync function request<T>(\n path: string,\n method: string,\n body?: unknown,\n): Promise<T> {\n const config = getConfig();\n const headers: Record<string, string> = {\n Authorization: `Bearer ${config.token}`,\n };\n\n if (body !== undefined) {\n headers['Content-Type'] = 'application/json';\n }\n\n const res = await fetch(`${AGENT_BASE}${path}`, {\n method,\n headers,\n ...(body !== undefined && { body: JSON.stringify(body) }),\n });\n\n if (!res.ok) {\n let errorMessage = `Agent chat request failed: ${res.status} ${res.statusText}`;\n let errorCode = 'agent_chat_error';\n try {\n const err = (await res.json()) as { error?: string; code?: string };\n if (err.error) {\n errorMessage = err.error;\n }\n if (err.code) {\n errorCode = err.code;\n }\n } catch {\n // Response wasn't JSON — use the default message\n }\n throw new MindStudioInterfaceError(errorMessage, errorCode, res.status);\n }\n\n return (await res.json()) as T;\n}\n\nfunction dispatchEvent(\n event: AgentChatEvent,\n callbacks: SendMessageCallbacks,\n): void {\n // Catch-all fires for every event\n callbacks.onEvent?.(event);\n\n // Named callbacks\n switch (event.type) {\n case 'text':\n callbacks.onText?.(event.text);\n break;\n case 'thinking':\n callbacks.onThinking?.(event.text);\n break;\n case 'thinking_complete':\n callbacks.onThinkingComplete?.(event.thinking, event.signature);\n break;\n case 'tool_call_start':\n callbacks.onToolCallStart?.(event.id, event.name);\n break;\n case 'tool_call_result':\n callbacks.onToolCallResult?.(event.id, event.output);\n break;\n case 'error':\n callbacks.onError?.(event.error);\n break;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Create an agent chat client for thread-based conversations.\n *\n * The client is stateless — each method is an independent HTTP request.\n * Your application layer owns thread state, message arrays, and UI updates.\n *\n * @returns An {@link AgentChatClient} with methods for thread CRUD and\n * message streaming.\n *\n * @example\n * ```ts\n * import { createAgentChatClient } from '@mindstudio-ai/interface';\n *\n * const chat = createAgentChatClient();\n *\n * const thread = await chat.createThread();\n *\n * const response = chat.sendMessage(thread.id, 'Hello!', {\n * onText: (delta) => setAssistantMessage((prev) => prev + delta),\n * onToolCallStart: (id, name) => showToolSpinner(name),\n * onToolCallResult: (id, output) => showToolResult(output),\n * });\n *\n * const { stopReason, usage } = await response;\n * ```\n */\nexport function createAgentChatClient(): AgentChatClient {\n return {\n createThread() {\n return request<ThreadSummary>('/threads', 'POST');\n },\n\n listThreads(cursor?: string) {\n const query = cursor ? `?cursor=${encodeURIComponent(cursor)}` : '';\n return request<ThreadListPage>(`/threads${query}`, 'GET');\n },\n\n getThread(threadId: string) {\n return request<Thread>(`/threads/${threadId}`, 'GET');\n },\n\n async updateThread(threadId: string, title: string) {\n await request(`/threads/${threadId}`, 'PATCH', { title });\n },\n\n async deleteThread(threadId: string) {\n await request(`/threads/${threadId}`, 'DELETE');\n },\n\n sendMessage(\n threadId: string,\n content: string,\n callbacks?: SendMessageCallbacks,\n options?: SendMessageOptions,\n ): AbortablePromise<SendMessageResult> {\n const controller = new AbortController();\n const cb = callbacks ?? {};\n\n // Wire caller's signal to our internal controller\n if (cb.signal) {\n if (cb.signal.aborted) {\n controller.abort();\n } else {\n cb.signal.addEventListener('abort', () => controller.abort(), {\n once: true,\n });\n }\n }\n\n const promise = (async (): Promise<SendMessageResult> => {\n const config = getConfig();\n const url = `${AGENT_BASE}/threads/${threadId}/messages`;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${config.token}`,\n },\n body: JSON.stringify({\n content,\n ...(options?.attachments?.length && {\n attachments: options.attachments,\n }),\n }),\n signal: controller.signal,\n });\n\n if (!res.ok) {\n let errorMessage = `Send message failed: ${res.status} ${res.statusText}`;\n let errorCode = 'agent_chat_error';\n try {\n const err = (await res.json()) as {\n error?: string;\n code?: string;\n };\n if (err.error) {\n errorMessage = err.error;\n }\n if (err.code) {\n errorCode = err.code;\n }\n } catch {\n // Response wasn't JSON — use the default message\n }\n throw new MindStudioInterfaceError(\n errorMessage,\n errorCode,\n res.status,\n );\n }\n\n const reader = res.body!.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n let result: SendMessageResult | undefined;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n\n for (const line of lines) {\n if (!line.startsWith('data: ')) {\n continue;\n }\n const json = line.slice(6);\n try {\n const event = JSON.parse(json) as AgentChatEvent;\n\n if (event.type === 'done') {\n result = {\n stopReason: event.stopReason,\n usage: event.usage,\n };\n }\n\n dispatchEvent(event, cb);\n } catch {\n // Skip malformed SSE lines\n }\n }\n }\n\n if (!result) {\n throw new MindStudioInterfaceError(\n 'Stream ended without a done event',\n 'stream_incomplete',\n );\n }\n\n return result;\n })();\n\n const abortable = promise as AbortablePromise<SendMessageResult>;\n abortable.abort = () => controller.abort();\n return abortable;\n },\n };\n}\n","/**\n * Platform actions — file uploads via presigned S3 POST.\n *\n * Uses the session token from `window.__MINDSTUDIO__` to request a\n * presigned upload URL from the platform, then uploads directly to S3.\n * Returns the public CDN URL.\n *\n * @example\n * ```ts\n * import { platform } from '@mindstudio-ai/interface';\n *\n * const file = document.querySelector('input[type=file]').files[0];\n * const url = await platform.uploadFile(file);\n *\n * // With progress and abort\n * const controller = new AbortController();\n * const url = await platform.uploadFile(file, {\n * onProgress: (fraction) => console.log(`${Math.round(fraction * 100)}%`),\n * signal: controller.signal,\n * });\n * ```\n */\n\nimport { getConfig } from './config.js';\nimport { MindStudioInterfaceError } from './errors.js';\n\n/**\n * Options for `platform.uploadFile()`.\n */\nexport interface UploadFileOptions {\n /** Called with upload progress as a fraction from 0 to 1. */\n onProgress?: (fraction: number) => void;\n\n /** AbortSignal to cancel the upload. */\n signal?: AbortSignal;\n}\n\n/**\n * The platform namespace — file upload actions.\n */\nexport const platform = {\n /**\n * Upload a file to the MindStudio CDN.\n *\n * Requests a presigned upload URL from the platform, then uploads\n * the file directly to S3. Returns the public CDN URL.\n *\n * @param file - The File to upload\n * @param options - Optional progress callback and abort signal\n * @returns CDN URL of the uploaded file\n *\n * @example\n * ```ts\n * const url = await platform.uploadFile(file);\n *\n * // With progress\n * const url = await platform.uploadFile(file, {\n * onProgress: (f) => setProgress(f),\n * });\n *\n * // With abort\n * const controller = new AbortController();\n * const url = await platform.uploadFile(file, {\n * signal: controller.signal,\n * });\n * // controller.abort() to cancel\n * ```\n */\n async uploadFile(file: File, options?: UploadFileOptions): Promise<string> {\n const config = getConfig();\n const { onProgress, signal } = options ?? {};\n\n // Check if already aborted\n signal?.throwIfAborted();\n\n // Step 1: Get presigned upload URL\n const presignUrl = '/_/generate-upload-request';\n const presignRes = await fetch(presignUrl, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${config.token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n filename: file.name,\n contentType: file.type || 'application/octet-stream',\n }),\n signal,\n });\n\n if (!presignRes.ok) {\n throw new MindStudioInterfaceError(\n `Upload presign failed: ${presignRes.status} ${presignRes.statusText}`,\n 'upload_error',\n presignRes.status,\n );\n }\n\n const { uploadUrl, uploadFields, publicUrl } =\n (await presignRes.json()) as {\n uploadUrl: string;\n uploadFields: Record<string, string>;\n publicUrl: string;\n };\n\n // Step 2: Upload directly to S3\n const formData = new FormData();\n for (const [key, value] of Object.entries(uploadFields)) {\n formData.append(key, value);\n }\n formData.append('file', file); // must be last\n\n // Use XHR for upload progress (fetch doesn't support it)\n if (onProgress) {\n await xhrUpload(uploadUrl, formData, onProgress, signal);\n return publicUrl;\n }\n\n const uploadRes = await fetch(uploadUrl, {\n method: 'POST',\n body: formData,\n signal,\n });\n\n if (!uploadRes.ok) {\n throw new MindStudioInterfaceError(\n `File upload failed: ${uploadRes.status} ${uploadRes.statusText}`,\n 'upload_error',\n uploadRes.status,\n );\n }\n\n return publicUrl;\n },\n};\n\n/**\n * Upload via XMLHttpRequest to get progress events.\n * Falls back from fetch because fetch upload streams don't support progress.\n */\nfunction xhrUpload(\n url: string,\n formData: FormData,\n onProgress: (fraction: number) => void,\n signal?: AbortSignal,\n): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n\n xhr.upload.addEventListener('progress', (e) => {\n if (e.lengthComputable) {\n onProgress(e.loaded / e.total);\n }\n });\n\n xhr.addEventListener('load', () => {\n if (xhr.status >= 200 && xhr.status < 300) {\n onProgress(1);\n resolve();\n } else {\n reject(\n new MindStudioInterfaceError(\n `File upload failed: ${xhr.status} ${xhr.statusText}`,\n 'upload_error',\n xhr.status,\n ),\n );\n }\n });\n\n xhr.addEventListener('error', () => {\n reject(\n new MindStudioInterfaceError(\n 'File upload failed: network error',\n 'upload_error',\n ),\n );\n });\n\n xhr.addEventListener('abort', () => {\n reject(new DOMException('Upload aborted', 'AbortError'));\n });\n\n // Wire up abort signal\n if (signal) {\n if (signal.aborted) {\n reject(new DOMException('Upload aborted', 'AbortError'));\n return;\n }\n signal.addEventListener('abort', () => xhr.abort(), { once: true });\n }\n\n xhr.open('POST', url);\n xhr.send(formData);\n });\n}\n","/**\n * Phone number utilities for auth flows.\n *\n * Provides country data, E.164 conversion, formatting, and validation.\n * No external dependencies — designed for login/signup UIs that need\n * a country code picker and phone number formatting.\n */\n\n// ---------------------------------------------------------------------------\n// Country data\n// ---------------------------------------------------------------------------\n\n/** A country with its dial code and flag emoji. */\nexport interface Country {\n /** ISO 3166-1 alpha-2 code (e.g. \"US\"). */\n code: string;\n /** International dial code with + prefix (e.g. \"+1\"). */\n dialCode: string;\n /** Country name in English. */\n name: string;\n /** Flag emoji. */\n flag: string;\n}\n\n/** All countries with dial codes, sorted alphabetically by name. */\nexport const countries: readonly Country[] = [\n { code: 'AF', dialCode: '+93', name: 'Afghanistan', flag: '🇦🇫' },\n { code: 'AL', dialCode: '+355', name: 'Albania', flag: '🇦🇱' },\n { code: 'DZ', dialCode: '+213', name: 'Algeria', flag: '🇩🇿' },\n { code: 'AD', dialCode: '+376', name: 'Andorra', flag: '🇦🇩' },\n { code: 'AO', dialCode: '+244', name: 'Angola', flag: '🇦🇴' },\n { code: 'AG', dialCode: '+1', name: 'Antigua and Barbuda', flag: '🇦🇬' },\n { code: 'AR', dialCode: '+54', name: 'Argentina', flag: '🇦🇷' },\n { code: 'AM', dialCode: '+374', name: 'Armenia', flag: '🇦🇲' },\n { code: 'AU', dialCode: '+61', name: 'Australia', flag: '🇦🇺' },\n { code: 'AT', dialCode: '+43', name: 'Austria', flag: '🇦🇹' },\n { code: 'AZ', dialCode: '+994', name: 'Azerbaijan', flag: '🇦🇿' },\n { code: 'BS', dialCode: '+1', name: 'Bahamas', flag: '🇧🇸' },\n { code: 'BH', dialCode: '+973', name: 'Bahrain', flag: '🇧🇭' },\n { code: 'BD', dialCode: '+880', name: 'Bangladesh', flag: '🇧🇩' },\n { code: 'BB', dialCode: '+1', name: 'Barbados', flag: '🇧🇧' },\n { code: 'BY', dialCode: '+375', name: 'Belarus', flag: '🇧🇾' },\n { code: 'BE', dialCode: '+32', name: 'Belgium', flag: '🇧🇪' },\n { code: 'BZ', dialCode: '+501', name: 'Belize', flag: '🇧🇿' },\n { code: 'BJ', dialCode: '+229', name: 'Benin', flag: '🇧🇯' },\n { code: 'BT', dialCode: '+975', name: 'Bhutan', flag: '🇧🇹' },\n { code: 'BO', dialCode: '+591', name: 'Bolivia', flag: '🇧🇴' },\n { code: 'BA', dialCode: '+387', name: 'Bosnia and Herzegovina', flag: '🇧🇦' },\n { code: 'BW', dialCode: '+267', name: 'Botswana', flag: '🇧🇼' },\n { code: 'BR', dialCode: '+55', name: 'Brazil', flag: '🇧🇷' },\n { code: 'BN', dialCode: '+673', name: 'Brunei', flag: '🇧🇳' },\n { code: 'BG', dialCode: '+359', name: 'Bulgaria', flag: '🇧🇬' },\n { code: 'BF', dialCode: '+226', name: 'Burkina Faso', flag: '🇧🇫' },\n { code: 'BI', dialCode: '+257', name: 'Burundi', flag: '🇧🇮' },\n { code: 'CV', dialCode: '+238', name: 'Cabo Verde', flag: '🇨🇻' },\n { code: 'KH', dialCode: '+855', name: 'Cambodia', flag: '🇰🇭' },\n { code: 'CM', dialCode: '+237', name: 'Cameroon', flag: '🇨🇲' },\n { code: 'CA', dialCode: '+1', name: 'Canada', flag: '🇨🇦' },\n {\n code: 'CF',\n dialCode: '+236',\n name: 'Central African Republic',\n flag: '🇨🇫',\n },\n { code: 'TD', dialCode: '+235', name: 'Chad', flag: '🇹🇩' },\n { code: 'CL', dialCode: '+56', name: 'Chile', flag: '🇨🇱' },\n { code: 'CN', dialCode: '+86', name: 'China', flag: '🇨🇳' },\n { code: 'CO', dialCode: '+57', name: 'Colombia', flag: '🇨🇴' },\n { code: 'KM', dialCode: '+269', name: 'Comoros', flag: '🇰🇲' },\n { code: 'CG', dialCode: '+242', name: 'Congo', flag: '🇨🇬' },\n { code: 'CD', dialCode: '+243', name: 'Congo (DRC)', flag: '🇨🇩' },\n { code: 'CR', dialCode: '+506', name: 'Costa Rica', flag: '🇨🇷' },\n { code: 'HR', dialCode: '+385', name: 'Croatia', flag: '🇭🇷' },\n { code: 'CU', dialCode: '+53', name: 'Cuba', flag: '🇨🇺' },\n { code: 'CY', dialCode: '+357', name: 'Cyprus', flag: '🇨🇾' },\n { code: 'CZ', dialCode: '+420', name: 'Czechia', flag: '🇨🇿' },\n { code: 'CI', dialCode: '+225', name: \"Cote d'Ivoire\", flag: '🇨🇮' },\n { code: 'DK', dialCode: '+45', name: 'Denmark', flag: '🇩🇰' },\n { code: 'DJ', dialCode: '+253', name: 'Djibouti', flag: '🇩🇯' },\n { code: 'DM', dialCode: '+1', name: 'Dominica', flag: '🇩🇲' },\n { code: 'DO', dialCode: '+1', name: 'Dominican Republic', flag: '🇩🇴' },\n { code: 'EC', dialCode: '+593', name: 'Ecuador', flag: '🇪🇨' },\n { code: 'EG', dialCode: '+20', name: 'Egypt', flag: '🇪🇬' },\n { code: 'SV', dialCode: '+503', name: 'El Salvador', flag: '🇸🇻' },\n { code: 'GQ', dialCode: '+240', name: 'Equatorial Guinea', flag: '🇬🇶' },\n { code: 'ER', dialCode: '+291', name: 'Eritrea', flag: '🇪🇷' },\n { code: 'EE', dialCode: '+372', name: 'Estonia', flag: '🇪🇪' },\n { code: 'SZ', dialCode: '+268', name: 'Eswatini', flag: '🇸🇿' },\n { code: 'ET', dialCode: '+251', name: 'Ethiopia', flag: '🇪🇹' },\n { code: 'FJ', dialCode: '+679', name: 'Fiji', flag: '🇫🇯' },\n { code: 'FI', dialCode: '+358', name: 'Finland', flag: '🇫🇮' },\n { code: 'FR', dialCode: '+33', name: 'France', flag: '🇫🇷' },\n { code: 'GA', dialCode: '+241', name: 'Gabon', flag: '🇬🇦' },\n { code: 'GM', dialCode: '+220', name: 'Gambia', flag: '🇬🇲' },\n { code: 'GE', dialCode: '+995', name: 'Georgia', flag: '🇬🇪' },\n { code: 'DE', dialCode: '+49', name: 'Germany', flag: '🇩🇪' },\n { code: 'GH', dialCode: '+233', name: 'Ghana', flag: '🇬🇭' },\n { code: 'GR', dialCode: '+30', name: 'Greece', flag: '🇬🇷' },\n { code: 'GD', dialCode: '+1', name: 'Grenada', flag: '🇬🇩' },\n { code: 'GT', dialCode: '+502', name: 'Guatemala', flag: '🇬🇹' },\n { code: 'GN', dialCode: '+224', name: 'Guinea', flag: '🇬🇳' },\n { code: 'GW', dialCode: '+245', name: 'Guinea-Bissau', flag: '🇬🇼' },\n { code: 'GY', dialCode: '+592', name: 'Guyana', flag: '🇬🇾' },\n { code: 'HT', dialCode: '+509', name: 'Haiti', flag: '🇭🇹' },\n { code: 'HN', dialCode: '+504', name: 'Honduras', flag: '🇭🇳' },\n { code: 'HK', dialCode: '+852', name: 'Hong Kong', flag: '🇭🇰' },\n { code: 'HU', dialCode: '+36', name: 'Hungary', flag: '🇭🇺' },\n { code: 'IS', dialCode: '+354', name: 'Iceland', flag: '🇮🇸' },\n { code: 'IN', dialCode: '+91', name: 'India', flag: '🇮🇳' },\n { code: 'ID', dialCode: '+62', name: 'Indonesia', flag: '🇮🇩' },\n { code: 'IR', dialCode: '+98', name: 'Iran', flag: '🇮🇷' },\n { code: 'IQ', dialCode: '+964', name: 'Iraq', flag: '🇮🇶' },\n { code: 'IE', dialCode: '+353', name: 'Ireland', flag: '🇮🇪' },\n { code: 'IL', dialCode: '+972', name: 'Israel', flag: '🇮🇱' },\n { code: 'IT', dialCode: '+39', name: 'Italy', flag: '🇮🇹' },\n { code: 'JM', dialCode: '+1', name: 'Jamaica', flag: '🇯🇲' },\n { code: 'JP', dialCode: '+81', name: 'Japan', flag: '🇯🇵' },\n { code: 'JO', dialCode: '+962', name: 'Jordan', flag: '🇯🇴' },\n { code: 'KZ', dialCode: '+7', name: 'Kazakhstan', flag: '🇰🇿' },\n { code: 'KE', dialCode: '+254', name: 'Kenya', flag: '🇰🇪' },\n { code: 'KI', dialCode: '+686', name: 'Kiribati', flag: '🇰🇮' },\n { code: 'KW', dialCode: '+965', name: 'Kuwait', flag: '🇰🇼' },\n { code: 'KG', dialCode: '+996', name: 'Kyrgyzstan', flag: '🇰🇬' },\n { code: 'LA', dialCode: '+856', name: 'Laos', flag: '🇱🇦' },\n { code: 'LV', dialCode: '+371', name: 'Latvia', flag: '🇱🇻' },\n { code: 'LB', dialCode: '+961', name: 'Lebanon', flag: '🇱🇧' },\n { code: 'LS', dialCode: '+266', name: 'Lesotho', flag: '🇱🇸' },\n { code: 'LR', dialCode: '+231', name: 'Liberia', flag: '🇱🇷' },\n { code: 'LY', dialCode: '+218', name: 'Libya', flag: '🇱🇾' },\n { code: 'LI', dialCode: '+423', name: 'Liechtenstein', flag: '🇱🇮' },\n { code: 'LT', dialCode: '+370', name: 'Lithuania', flag: '🇱🇹' },\n { code: 'LU', dialCode: '+352', name: 'Luxembourg', flag: '🇱🇺' },\n { code: 'MO', dialCode: '+853', name: 'Macao', flag: '🇲🇴' },\n { code: 'MG', dialCode: '+261', name: 'Madagascar', flag: '🇲🇬' },\n { code: 'MW', dialCode: '+265', name: 'Malawi', flag: '🇲🇼' },\n { code: 'MY', dialCode: '+60', name: 'Malaysia', flag: '🇲🇾' },\n { code: 'MV', dialCode: '+960', name: 'Maldives', flag: '🇲🇻' },\n { code: 'ML', dialCode: '+223', name: 'Mali', flag: '🇲🇱' },\n { code: 'MT', dialCode: '+356', name: 'Malta', flag: '🇲🇹' },\n { code: 'MH', dialCode: '+692', name: 'Marshall Islands', flag: '🇲🇭' },\n { code: 'MR', dialCode: '+222', name: 'Mauritania', flag: '🇲🇷' },\n { code: 'MU', dialCode: '+230', name: 'Mauritius', flag: '🇲🇺' },\n { code: 'MX', dialCode: '+52', name: 'Mexico', flag: '🇲🇽' },\n { code: 'FM', dialCode: '+691', name: 'Micronesia', flag: '🇫🇲' },\n { code: 'MD', dialCode: '+373', name: 'Moldova', flag: '🇲🇩' },\n { code: 'MC', dialCode: '+377', name: 'Monaco', flag: '🇲🇨' },\n { code: 'MN', dialCode: '+976', name: 'Mongolia', flag: '🇲🇳' },\n { code: 'ME', dialCode: '+382', name: 'Montenegro', flag: '🇲🇪' },\n { code: 'MA', dialCode: '+212', name: 'Morocco', flag: '🇲🇦' },\n { code: 'MZ', dialCode: '+258', name: 'Mozambique', flag: '🇲🇿' },\n { code: 'MM', dialCode: '+95', name: 'Myanmar', flag: '🇲🇲' },\n { code: 'NA', dialCode: '+264', name: 'Namibia', flag: '🇳🇦' },\n { code: 'NR', dialCode: '+674', name: 'Nauru', flag: '🇳🇷' },\n { code: 'NP', dialCode: '+977', name: 'Nepal', flag: '🇳🇵' },\n { code: 'NL', dialCode: '+31', name: 'Netherlands', flag: '🇳🇱' },\n { code: 'NZ', dialCode: '+64', name: 'New Zealand', flag: '🇳🇿' },\n { code: 'NI', dialCode: '+505', name: 'Nicaragua', flag: '🇳🇮' },\n { code: 'NE', dialCode: '+227', name: 'Niger', flag: '🇳🇪' },\n { code: 'NG', dialCode: '+234', name: 'Nigeria', flag: '🇳🇬' },\n { code: 'KP', dialCode: '+850', name: 'North Korea', flag: '🇰🇵' },\n { code: 'MK', dialCode: '+389', name: 'North Macedonia', flag: '🇲🇰' },\n { code: 'NO', dialCode: '+47', name: 'Norway', flag: '🇳🇴' },\n { code: 'OM', dialCode: '+968', name: 'Oman', flag: '🇴🇲' },\n { code: 'PK', dialCode: '+92', name: 'Pakistan', flag: '🇵🇰' },\n { code: 'PW', dialCode: '+680', name: 'Palau', flag: '🇵🇼' },\n { code: 'PS', dialCode: '+970', name: 'Palestine', flag: '🇵🇸' },\n { code: 'PA', dialCode: '+507', name: 'Panama', flag: '🇵🇦' },\n { code: 'PG', dialCode: '+675', name: 'Papua New Guinea', flag: '🇵🇬' },\n { code: 'PY', dialCode: '+595', name: 'Paraguay', flag: '🇵🇾' },\n { code: 'PE', dialCode: '+51', name: 'Peru', flag: '🇵🇪' },\n { code: 'PH', dialCode: '+63', name: 'Philippines', flag: '🇵🇭' },\n { code: 'PL', dialCode: '+48', name: 'Poland', flag: '🇵🇱' },\n { code: 'PT', dialCode: '+351', name: 'Portugal', flag: '🇵🇹' },\n { code: 'PR', dialCode: '+1', name: 'Puerto Rico', flag: '🇵🇷' },\n { code: 'QA', dialCode: '+974', name: 'Qatar', flag: '🇶🇦' },\n { code: 'RO', dialCode: '+40', name: 'Romania', flag: '🇷🇴' },\n { code: 'RU', dialCode: '+7', name: 'Russia', flag: '🇷🇺' },\n { code: 'RW', dialCode: '+250', name: 'Rwanda', flag: '🇷🇼' },\n { code: 'KN', dialCode: '+1', name: 'Saint Kitts and Nevis', flag: '🇰🇳' },\n { code: 'LC', dialCode: '+1', name: 'Saint Lucia', flag: '🇱🇨' },\n {\n code: 'VC',\n dialCode: '+1',\n name: 'Saint Vincent and the Grenadines',\n flag: '🇻🇨',\n },\n { code: 'WS', dialCode: '+685', name: 'Samoa', flag: '🇼🇸' },\n { code: 'SM', dialCode: '+378', name: 'San Marino', flag: '🇸🇲' },\n { code: 'ST', dialCode: '+239', name: 'Sao Tome and Principe', flag: '🇸🇹' },\n { code: 'SA', dialCode: '+966', name: 'Saudi Arabia', flag: '🇸🇦' },\n { code: 'SN', dialCode: '+221', name: 'Senegal', flag: '🇸🇳' },\n { code: 'RS', dialCode: '+381', name: 'Serbia', flag: '🇷🇸' },\n { code: 'SC', dialCode: '+248', name: 'Seychelles', flag: '🇸🇨' },\n { code: 'SL', dialCode: '+232', name: 'Sierra Leone', flag: '🇸🇱' },\n { code: 'SG', dialCode: '+65', name: 'Singapore', flag: '🇸🇬' },\n { code: 'SK', dialCode: '+421', name: 'Slovakia', flag: '🇸🇰' },\n { code: 'SI', dialCode: '+386', name: 'Slovenia', flag: '🇸🇮' },\n { code: 'SB', dialCode: '+677', name: 'Solomon Islands', flag: '🇸🇧' },\n { code: 'SO', dialCode: '+252', name: 'Somalia', flag: '🇸🇴' },\n { code: 'ZA', dialCode: '+27', name: 'South Africa', flag: '🇿🇦' },\n { code: 'KR', dialCode: '+82', name: 'South Korea', flag: '🇰🇷' },\n { code: 'SS', dialCode: '+211', name: 'South Sudan', flag: '🇸🇸' },\n { code: 'ES', dialCode: '+34', name: 'Spain', flag: '🇪🇸' },\n { code: 'LK', dialCode: '+94', name: 'Sri Lanka', flag: '🇱🇰' },\n { code: 'SD', dialCode: '+249', name: 'Sudan', flag: '🇸🇩' },\n { code: 'SR', dialCode: '+597', name: 'Suriname', flag: '🇸🇷' },\n { code: 'SE', dialCode: '+46', name: 'Sweden', flag: '🇸🇪' },\n { code: 'CH', dialCode: '+41', name: 'Switzerland', flag: '🇨🇭' },\n { code: 'SY', dialCode: '+963', name: 'Syria', flag: '🇸🇾' },\n { code: 'TW', dialCode: '+886', name: 'Taiwan', flag: '🇹🇼' },\n { code: 'TJ', dialCode: '+992', name: 'Tajikistan', flag: '🇹🇯' },\n { code: 'TZ', dialCode: '+255', name: 'Tanzania', flag: '🇹🇿' },\n { code: 'TH', dialCode: '+66', name: 'Thailand', flag: '🇹🇭' },\n { code: 'TL', dialCode: '+670', name: 'Timor-Leste', flag: '🇹🇱' },\n { code: 'TG', dialCode: '+228', name: 'Togo', flag: '🇹🇬' },\n { code: 'TO', dialCode: '+676', name: 'Tonga', flag: '🇹🇴' },\n { code: 'TT', dialCode: '+1', name: 'Trinidad and Tobago', flag: '🇹🇹' },\n { code: 'TN', dialCode: '+216', name: 'Tunisia', flag: '🇹🇳' },\n { code: 'TR', dialCode: '+90', name: 'Turkey', flag: '🇹🇷' },\n { code: 'TM', dialCode: '+993', name: 'Turkmenistan', flag: '🇹🇲' },\n { code: 'TV', dialCode: '+688', name: 'Tuvalu', flag: '🇹🇻' },\n { code: 'UG', dialCode: '+256', name: 'Uganda', flag: '🇺🇬' },\n { code: 'UA', dialCode: '+380', name: 'Ukraine', flag: '🇺🇦' },\n { code: 'AE', dialCode: '+971', name: 'United Arab Emirates', flag: '🇦🇪' },\n { code: 'GB', dialCode: '+44', name: 'United Kingdom', flag: '🇬🇧' },\n { code: 'US', dialCode: '+1', name: 'United States', flag: '🇺🇸' },\n { code: 'UY', dialCode: '+598', name: 'Uruguay', flag: '🇺🇾' },\n { code: 'UZ', dialCode: '+998', name: 'Uzbekistan', flag: '🇺🇿' },\n { code: 'VU', dialCode: '+678', name: 'Vanuatu', flag: '🇻🇺' },\n { code: 'VA', dialCode: '+39', name: 'Vatican City', flag: '🇻🇦' },\n { code: 'VE', dialCode: '+58', name: 'Venezuela', flag: '🇻🇪' },\n { code: 'VN', dialCode: '+84', name: 'Vietnam', flag: '🇻🇳' },\n { code: 'YE', dialCode: '+967', name: 'Yemen', flag: '🇾🇪' },\n { code: 'ZM', dialCode: '+260', name: 'Zambia', flag: '🇿🇲' },\n { code: 'ZW', dialCode: '+263', name: 'Zimbabwe', flag: '🇿🇼' },\n];\n\n// ---------------------------------------------------------------------------\n// Country lookup helpers\n// ---------------------------------------------------------------------------\n\nconst byCode = new Map(countries.map((c) => [c.code, c]));\n\n/** Common IANA timezone → country code mapping. */\nconst timezoneToCountry: Record<string, string> = {\n 'America/New_York': 'US',\n 'America/Chicago': 'US',\n 'America/Denver': 'US',\n 'America/Los_Angeles': 'US',\n 'America/Anchorage': 'US',\n 'Pacific/Honolulu': 'US',\n 'America/Phoenix': 'US',\n 'America/Indiana/Indianapolis': 'US',\n 'America/Toronto': 'CA',\n 'America/Vancouver': 'CA',\n 'America/Edmonton': 'CA',\n 'America/Winnipeg': 'CA',\n 'America/Halifax': 'CA',\n 'America/St_Johns': 'CA',\n 'Europe/London': 'GB',\n 'Europe/Dublin': 'IE',\n 'Europe/Paris': 'FR',\n 'Europe/Berlin': 'DE',\n 'Europe/Madrid': 'ES',\n 'Europe/Rome': 'IT',\n 'Europe/Amsterdam': 'NL',\n 'Europe/Brussels': 'BE',\n 'Europe/Zurich': 'CH',\n 'Europe/Vienna': 'AT',\n 'Europe/Stockholm': 'SE',\n 'Europe/Oslo': 'NO',\n 'Europe/Copenhagen': 'DK',\n 'Europe/Helsinki': 'FI',\n 'Europe/Warsaw': 'PL',\n 'Europe/Prague': 'CZ',\n 'Europe/Bucharest': 'RO',\n 'Europe/Budapest': 'HU',\n 'Europe/Athens': 'GR',\n 'Europe/Istanbul': 'TR',\n 'Europe/Moscow': 'RU',\n 'Europe/Kiev': 'UA',\n 'Europe/Lisbon': 'PT',\n 'Europe/Belgrade': 'RS',\n 'Europe/Zagreb': 'HR',\n 'Europe/Bratislava': 'SK',\n 'Europe/Ljubljana': 'SI',\n 'Europe/Tallinn': 'EE',\n 'Europe/Riga': 'LV',\n 'Europe/Vilnius': 'LT',\n 'Asia/Tokyo': 'JP',\n 'Asia/Seoul': 'KR',\n 'Asia/Shanghai': 'CN',\n 'Asia/Hong_Kong': 'HK',\n 'Asia/Taipei': 'TW',\n 'Asia/Singapore': 'SG',\n 'Asia/Kolkata': 'IN',\n 'Asia/Karachi': 'PK',\n 'Asia/Dhaka': 'BD',\n 'Asia/Bangkok': 'TH',\n 'Asia/Jakarta': 'ID',\n 'Asia/Manila': 'PH',\n 'Asia/Kuala_Lumpur': 'MY',\n 'Asia/Ho_Chi_Minh': 'VN',\n 'Asia/Riyadh': 'SA',\n 'Asia/Dubai': 'AE',\n 'Asia/Tehran': 'IR',\n 'Asia/Baghdad': 'IQ',\n 'Asia/Beirut': 'LB',\n 'Asia/Jerusalem': 'IL',\n 'Asia/Amman': 'JO',\n 'Asia/Almaty': 'KZ',\n 'Asia/Tashkent': 'UZ',\n 'Asia/Colombo': 'LK',\n 'Asia/Kathmandu': 'NP',\n 'Asia/Yangon': 'MM',\n 'Australia/Sydney': 'AU',\n 'Australia/Melbourne': 'AU',\n 'Australia/Brisbane': 'AU',\n 'Australia/Perth': 'AU',\n 'Australia/Adelaide': 'AU',\n 'Pacific/Auckland': 'NZ',\n 'Pacific/Fiji': 'FJ',\n 'Africa/Cairo': 'EG',\n 'Africa/Lagos': 'NG',\n 'Africa/Nairobi': 'KE',\n 'Africa/Johannesburg': 'ZA',\n 'Africa/Casablanca': 'MA',\n 'Africa/Accra': 'GH',\n 'Africa/Addis_Ababa': 'ET',\n 'Africa/Dar_es_Salaam': 'TZ',\n 'Africa/Kampala': 'UG',\n 'America/Mexico_City': 'MX',\n 'America/Bogota': 'CO',\n 'America/Lima': 'PE',\n 'America/Santiago': 'CL',\n 'America/Buenos_Aires': 'AR',\n 'America/Sao_Paulo': 'BR',\n 'America/Caracas': 'VE',\n 'America/Guatemala': 'GT',\n 'America/Havana': 'CU',\n 'America/Panama': 'PA',\n 'America/Jamaica': 'JM',\n};\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Detect the user's country from their timezone.\n * Falls back to `'US'` if the timezone can't be mapped.\n */\nexport function detectCountry(): string {\n try {\n const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;\n return timezoneToCountry[tz] ?? 'US';\n } catch {\n return 'US';\n }\n}\n\n/**\n * Format an E.164 phone number for display.\n *\n * US/CA numbers: `+1 (555) 123-4567`\n * Others: `+{dialCode} {rest}`\n */\nexport function format(e164: string): string {\n if (!e164.startsWith('+')) {\n return e164;\n }\n\n const digits = e164.slice(1);\n\n // US/CA: +1 followed by 10 digits\n if (digits.startsWith('1') && digits.length === 11) {\n const area = digits.slice(1, 4);\n const prefix = digits.slice(4, 7);\n const line = digits.slice(7);\n return `+1 (${area}) ${prefix}-${line}`;\n }\n\n // Find matching dial code (try longest match first)\n for (let len = 4; len >= 1; len--) {\n const candidate = '+' + digits.slice(0, len);\n const match = countries.find((c) => c.dialCode === candidate);\n if (match) {\n const rest = digits.slice(len);\n return `${match.dialCode} ${rest}`;\n }\n }\n\n return e164;\n}\n\n/**\n * Convert a national phone number to E.164 format.\n *\n * @param national - Phone number with or without formatting (e.g. \"(555) 123-4567\")\n * @param countryCode - ISO 3166-1 alpha-2 code (e.g. \"US\")\n * @returns E.164 formatted number (e.g. \"+15551234567\")\n */\nexport function toE164(national: string, countryCode: string): string {\n const digits = national.replace(/\\D/g, '');\n const country = byCode.get(countryCode);\n if (!country) {\n return '+' + digits;\n }\n const dialDigits = country.dialCode.slice(1); // remove +\n // If the number already starts with the dial code, don't double-add\n if (digits.startsWith(dialDigits)) {\n return '+' + digits;\n }\n return country.dialCode + digits;\n}\n\n/**\n * Check if a string is a valid E.164 phone number.\n * Must start with + followed by 7-15 digits.\n */\nexport function isValid(phone: string): boolean {\n return /^\\+[1-9]\\d{6,14}$/.test(phone);\n}\n","/**\n * Email validation helper for auth flows.\n */\n\n/** Basic email format check. Not RFC 5322 exhaustive. */\nexport function isValid(email: string): boolean {\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email);\n}\n","/**\n * Auth — app-managed authentication for MindStudio v2 apps.\n *\n * Provides verification code flows (email + SMS), session state\n * management, and phone/email validation helpers. The platform\n * handles code delivery, cookie management, and user storage —\n * developers build their own login UI using these methods.\n *\n * ## How it works\n *\n * ```\n * // 1. Send a verification code\n * const { verificationId } = await auth.sendEmailCode('user@example.com');\n *\n * // 2. User enters the code in your UI\n * const user = await auth.verifyEmailCode(verificationId, '123456');\n *\n * // 3. Session is now active — all SDK calls use the authenticated token\n * const result = await api.getDashboard(); // uses authenticated session\n * auth.getCurrentUser(); // { id, email, phone, roles, createdAt }\n * ```\n *\n * Verify, confirm, and logout methods update `window.__MINDSTUDIO__`\n * in-place so all downstream calls (method invocation, agent chat,\n * uploads) immediately use the new session. No page refresh needed.\n *\n * @example\n * ```tsx\n * import { auth } from '@mindstudio-ai/interface';\n *\n * function LoginPage() {\n * const [email, setEmail] = useState('');\n * const [verificationId, setVerificationId] = useState('');\n * const [code, setCode] = useState('');\n *\n * const handleSend = async () => {\n * const { verificationId } = await auth.sendEmailCode(email);\n * setVerificationId(verificationId);\n * };\n *\n * const handleVerify = async () => {\n * await auth.verifyEmailCode(verificationId, code);\n * // Session updated in-place — navigate to your app\n * window.location.href = '/dashboard';\n * };\n * }\n * ```\n */\n\nimport { getConfig, updateConfig } from './config.js';\nimport { MindStudioInterfaceError } from './errors.js';\nimport type { AppUser, AuthSessionBundle } from './types.js';\nimport * as phoneHelpers from './auth-phone.js';\nimport * as emailHelpers from './auth-email.js';\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nasync function authFetch<T>(\n path: string,\n method: 'GET' | 'POST',\n body?: Record<string, unknown>,\n): Promise<T> {\n const config = getConfig();\n const headers: Record<string, string> = {\n Authorization: `Bearer ${config.token}`,\n };\n\n if (body !== undefined) {\n headers['Content-Type'] = 'application/json';\n }\n\n const res = await fetch(path, {\n method,\n headers,\n ...(body !== undefined && { body: JSON.stringify(body) }),\n });\n\n if (!res.ok) {\n let message = `Auth request failed: ${res.status} ${res.statusText}`;\n let code = 'auth_error';\n try {\n const err = (await res.json()) as { error?: string; code?: string };\n if (err.error) {\n message = err.error;\n }\n if (err.code) {\n code = err.code;\n }\n } catch {\n // Response wasn't JSON\n }\n throw new MindStudioInterfaceError(message, code, res.status);\n }\n\n return (await res.json()) as T;\n}\n\nfunction applySession(bundle: AuthSessionBundle): void {\n updateConfig({\n token: bundle.token,\n user: bundle.user,\n methods: bundle.methods,\n });\n}\n\nfunction requireUser(bundle: AuthSessionBundle): AppUser {\n if (!bundle.user) {\n throw new MindStudioInterfaceError(\n 'Verification succeeded but no user was returned',\n 'auth_error',\n );\n }\n return bundle.user;\n}\n\n// ---------------------------------------------------------------------------\n// Auth interface\n// ---------------------------------------------------------------------------\n\n/** The auth namespace — authentication flows, state, and helpers. */\nexport interface Auth {\n // -- State --\n\n /** Get the current authenticated user, or `null` if not authenticated. */\n getCurrentUser(): AppUser | null;\n\n /** Whether the current session is authenticated. */\n isAuthenticated(): boolean;\n\n // -- Email code flow --\n\n /** Send a 6-digit verification code to an email address. */\n sendEmailCode(email: string): Promise<{ verificationId: string }>;\n\n /**\n * Verify an email code. On success, updates the session in-place\n * and returns the authenticated user.\n */\n verifyEmailCode(verificationId: string, code: string): Promise<AppUser>;\n\n // -- SMS code flow --\n\n /** Send a 6-digit verification code via SMS. Phone must be E.164. */\n sendSmsCode(phone: string): Promise<{ verificationId: string }>;\n\n /**\n * Verify an SMS code. On success, updates the session in-place\n * and returns the authenticated user.\n */\n verifySmsCode(verificationId: string, code: string): Promise<AppUser>;\n\n // -- Email/phone change (requires authentication) --\n\n /** Request an email change. Sends a code to the new email. */\n requestEmailChange(newEmail: string): Promise<void>;\n\n /** Confirm an email change with the verification code. */\n confirmEmailChange(newEmail: string, code: string): Promise<AppUser>;\n\n /** Request a phone change. Sends a code to the new phone (E.164). */\n requestPhoneChange(newPhone: string): Promise<void>;\n\n /** Confirm a phone change with the verification code. */\n confirmPhoneChange(newPhone: string, code: string): Promise<AppUser>;\n\n // -- Session --\n\n /** Log out. Clears the cookie and updates the session to unauthenticated. */\n logout(): Promise<void>;\n\n // -- Helpers --\n\n /** Phone number utilities — countries, formatting, validation. */\n phone: {\n /** All countries with dial codes, sorted alphabetically. */\n countries: readonly phoneHelpers.Country[];\n /** Detect the user's country from their timezone. Falls back to `'US'`. */\n detectCountry(): string;\n /** Format an E.164 number for display (e.g. `+1 (555) 123-4567`). */\n format(e164: string): string;\n /** Convert a national number to E.164 (e.g. `('5551234567', 'US') → '+15551234567'`). */\n toE164(national: string, countryCode: string): string;\n /** Check if a string is a valid E.164 phone number. */\n isValid(phone: string): boolean;\n };\n\n /** Email validation. */\n email: {\n /** Basic email format check. */\n isValid(email: string): boolean;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Implementation\n// ---------------------------------------------------------------------------\n\nexport const auth: Auth = {\n // -- State --\n\n getCurrentUser() {\n return getConfig().user;\n },\n\n isAuthenticated() {\n return getConfig().user !== null;\n },\n\n // -- Email code flow --\n\n sendEmailCode(email: string) {\n return authFetch<{ verificationId: string }>('/_/auth/email/send', 'POST', {\n email,\n });\n },\n\n async verifyEmailCode(verificationId: string, code: string) {\n const bundle = await authFetch<AuthSessionBundle>(\n '/_/auth/email/verify',\n 'POST',\n { verificationId, code },\n );\n applySession(bundle);\n return requireUser(bundle);\n },\n\n // -- SMS code flow --\n\n sendSmsCode(phone: string) {\n return authFetch<{ verificationId: string }>('/_/auth/sms/send', 'POST', {\n phone,\n });\n },\n\n async verifySmsCode(verificationId: string, code: string) {\n const bundle = await authFetch<AuthSessionBundle>(\n '/_/auth/sms/verify',\n 'POST',\n { verificationId, code },\n );\n applySession(bundle);\n return requireUser(bundle);\n },\n\n // -- Email/phone change --\n\n async requestEmailChange(newEmail: string) {\n await authFetch('/_/auth/email/change', 'POST', { newEmail });\n },\n\n async confirmEmailChange(newEmail: string, code: string) {\n const bundle = await authFetch<AuthSessionBundle>(\n '/_/auth/email/change/confirm',\n 'POST',\n { newEmail, code },\n );\n applySession(bundle);\n return requireUser(bundle);\n },\n\n async requestPhoneChange(newPhone: string) {\n await authFetch('/_/auth/phone/change', 'POST', { newPhone });\n },\n\n async confirmPhoneChange(newPhone: string, code: string) {\n const bundle = await authFetch<AuthSessionBundle>(\n '/_/auth/phone/change/confirm',\n 'POST',\n { newPhone, code },\n );\n applySession(bundle);\n return requireUser(bundle);\n },\n\n // -- Session --\n\n async logout() {\n const bundle = await authFetch<AuthSessionBundle>(\n '/_/auth/logout',\n 'POST',\n {},\n );\n applySession(bundle);\n },\n\n // -- Helpers --\n\n phone: {\n countries: phoneHelpers.countries,\n detectCountry: phoneHelpers.detectCountry,\n format: phoneHelpers.format,\n toE164: phoneHelpers.toE164,\n isValid: phoneHelpers.isValid,\n },\n\n email: {\n isValid: emailHelpers.isValid,\n },\n};\n"],"mappings":"AAOO,IAAMA,EAAN,cAAuC,KAAM,CAEzC,KAGA,OAET,YAAYC,EAAiBC,EAAcC,EAAiB,CAC1D,MAAMF,CAAO,EACb,KAAK,KAAO,2BACZ,KAAK,KAAOC,EACZ,KAAK,OAASC,CAChB,CACF,ECLA,IAAIC,EAYG,SAASC,GAA6B,CAC3C,GAAID,EACF,OAAOA,EAGT,IAAME,EAAO,WAAuC,eAIpD,GAAI,CAACA,EACH,MAAM,IAAIC,EACR,oJAEA,iBACF,EAIF,GAAI,CAACD,EAAI,OAAS,CAACA,EAAI,WAAa,CAACA,EAAI,QAAS,CAChD,IAAME,EAAU,CAAC,QAAS,YAAa,SAAS,EAC7C,OAAQC,GAAM,CAACH,EAAIG,CAA0B,CAAC,EAC9C,KAAK,IAAI,EAEZ,MAAM,IAAIF,EACR,uDAAuDC,CAAO,GAC9D,gBACF,CACF,CAEA,OAAAJ,EAAUE,EACHF,CACT,CAWO,SAASM,EAAaC,EAIpB,CACP,IAAMC,EAASP,EAAU,EACrBM,EAAQ,QAAU,SACpBC,EAAO,MAAQD,EAAQ,OAErBA,EAAQ,OAAS,SACnBC,EAAO,KAAOD,EAAQ,MAEpBA,EAAQ,UAAY,SACtBC,EAAO,QAAUD,EAAQ,QAE7B,CCwFO,SAASE,GAA2C,CACzD,OAAO,IAAI,MAAM,CAAC,EAA4C,CAC5D,IAAIC,EAAGC,EAAoB,CACzB,MAAO,OAAOC,EAAiBC,IAA4B,CACzD,IAAMC,EAASC,EAAU,EAEnBC,EAAWF,EAAO,QAAQH,CAAU,EAC1C,GAAI,CAACK,EACH,MAAM,IAAIC,EACR,WAAWN,CAAU,mCAAmC,OAAO,KAAKG,EAAO,OAAO,EAAE,KAAK,IAAI,GAAK,QAAQ,GAC1G,kBACF,EAGF,IAAMI,EAAM,cAAcF,CAAQ,UAC5BG,EAAcN,GAAS,SAAW,GAElCO,EAAM,MAAM,MAAMF,EAAK,CAC3B,OAAQ,OACR,QAAS,CACP,eAAgB,mBAChB,cAAe,UAAUJ,EAAO,KAAK,EACvC,EACA,KAAM,KAAK,UAAU,CACnB,MAAOF,GAAS,CAAC,EACjB,GAAIO,GAAe,CAAE,OAAQ,EAAK,CACpC,CAAC,CACH,CAAC,EAED,GAAI,CAACC,EAAI,GAAI,CACX,IAAIC,EAAe,WAAWV,CAAU,aAAaS,EAAI,MAAM,IAAIA,EAAI,UAAU,GAC7EE,EAAY,eAChB,GAAI,CACF,IAAMC,EAAQ,MAAMH,EAAI,KAAK,EAIzBG,EAAK,QACPF,EAAeE,EAAK,OAElBA,EAAK,OACPD,EAAYC,EAAK,KAErB,MAAQ,CAER,CACA,MAAM,IAAIN,EACRI,EACAC,EACAF,EAAI,MACN,CACF,CAGA,GAAI,CAACD,EAEH,OADc,MAAMC,EAAI,KAAK,GACjB,OAId,IAAMI,EAASJ,EAAI,KAAM,UAAU,EAC7BK,EAAU,IAAI,YAChBC,EAAS,GACTC,EAEJ,OAAa,CACX,GAAM,CAAE,KAAAC,EAAM,MAAAC,CAAM,EAAI,MAAML,EAAO,KAAK,EAC1C,GAAII,EACF,MAGFF,GAAUD,EAAQ,OAAOI,EAAO,CAAE,OAAQ,EAAK,CAAC,EAChD,IAAMC,EAAQJ,EAAO,MAAM;AAAA,CAAI,EAC/BA,EAASI,EAAM,IAAI,GAAK,GAExB,QAAWC,KAAQD,EAAO,CACxB,GAAI,CAACC,EAAK,WAAW,QAAQ,EAC3B,SAEF,IAAMC,EAAOD,EAAK,MAAM,CAAC,EACzB,GAAI,CACF,IAAME,EAAQ,KAAK,MAAMD,CAAI,EAOzBC,EAAM,OAAS,SAAWpB,GAAS,SAAWoB,EAAM,KACtDpB,EAAQ,QAAQoB,EAAM,IAAI,EACjBA,EAAM,OAAS,SAAWA,EAAM,MACrCpB,GAAS,eACXA,EAAQ,cAAcoB,EAAM,KAAK,EAE1BA,EAAM,OAAS,SACxBN,EAAcM,EAAM,OAExB,MAAQ,CAER,CACF,CACF,CAEA,GAAIN,IAAgB,OAClB,MAAM,IAAIV,EACR,oCACA,mBACF,EAGF,OAAOU,CACT,CACF,CACF,CAAC,CACH,CCwEA,IAAMO,EAAa,WAEnB,eAAeC,EACbC,EACAC,EACAC,EACY,CAEZ,IAAMC,EAAkC,CACtC,cAAe,UAFFC,EAAU,EAES,KAAK,EACvC,EAEIF,IAAS,SACXC,EAAQ,cAAc,EAAI,oBAG5B,IAAME,EAAM,MAAM,MAAM,GAAGP,CAAU,GAAGE,CAAI,GAAI,CAC9C,OAAAC,EACA,QAAAE,EACA,GAAID,IAAS,QAAa,CAAE,KAAM,KAAK,UAAUA,CAAI,CAAE,CACzD,CAAC,EAED,GAAI,CAACG,EAAI,GAAI,CACX,IAAIC,EAAe,8BAA8BD,EAAI,MAAM,IAAIA,EAAI,UAAU,GACzEE,EAAY,mBAChB,GAAI,CACF,IAAMC,EAAO,MAAMH,EAAI,KAAK,EACxBG,EAAI,QACNF,EAAeE,EAAI,OAEjBA,EAAI,OACND,EAAYC,EAAI,KAEpB,MAAQ,CAER,CACA,MAAM,IAAIC,EAAyBH,EAAcC,EAAWF,EAAI,MAAM,CACxE,CAEA,OAAQ,MAAMA,EAAI,KAAK,CACzB,CAEA,SAASK,EACPC,EACAC,EACM,CAKN,OAHAA,EAAU,UAAUD,CAAK,EAGjBA,EAAM,KAAM,CAClB,IAAK,OACHC,EAAU,SAASD,EAAM,IAAI,EAC7B,MACF,IAAK,WACHC,EAAU,aAAaD,EAAM,IAAI,EACjC,MACF,IAAK,oBACHC,EAAU,qBAAqBD,EAAM,SAAUA,EAAM,SAAS,EAC9D,MACF,IAAK,kBACHC,EAAU,kBAAkBD,EAAM,GAAIA,EAAM,IAAI,EAChD,MACF,IAAK,mBACHC,EAAU,mBAAmBD,EAAM,GAAIA,EAAM,MAAM,EACnD,MACF,IAAK,QACHC,EAAU,UAAUD,EAAM,KAAK,EAC/B,KACJ,CACF,CAgCO,SAASE,GAAyC,CACvD,MAAO,CACL,cAAe,CACb,OAAOd,EAAuB,WAAY,MAAM,CAClD,EAEA,YAAYe,EAAiB,CAC3B,IAAMC,EAAQD,EAAS,WAAW,mBAAmBA,CAAM,CAAC,GAAK,GACjE,OAAOf,EAAwB,WAAWgB,CAAK,GAAI,KAAK,CAC1D,EAEA,UAAUC,EAAkB,CAC1B,OAAOjB,EAAgB,YAAYiB,CAAQ,GAAI,KAAK,CACtD,EAEA,MAAM,aAAaA,EAAkBC,EAAe,CAClD,MAAMlB,EAAQ,YAAYiB,CAAQ,GAAI,QAAS,CAAE,MAAAC,CAAM,CAAC,CAC1D,EAEA,MAAM,aAAaD,EAAkB,CACnC,MAAMjB,EAAQ,YAAYiB,CAAQ,GAAI,QAAQ,CAChD,EAEA,YACEA,EACAE,EACAN,EACAO,EACqC,CACrC,IAAMC,EAAa,IAAI,gBACjBC,EAAKT,GAAa,CAAC,EAGrBS,EAAG,SACDA,EAAG,OAAO,QACZD,EAAW,MAAM,EAEjBC,EAAG,OAAO,iBAAiB,QAAS,IAAMD,EAAW,MAAM,EAAG,CAC5D,KAAM,EACR,CAAC,GA8FL,IAAME,GA1FW,SAAwC,CACvD,IAAMC,EAASnB,EAAU,EACnBoB,EAAM,GAAG1B,CAAU,YAAYkB,CAAQ,YAEvCX,EAAM,MAAM,MAAMmB,EAAK,CAC3B,OAAQ,OACR,QAAS,CACP,eAAgB,mBAChB,cAAe,UAAUD,EAAO,KAAK,EACvC,EACA,KAAM,KAAK,UAAU,CACnB,QAAAL,EACA,GAAIC,GAAS,aAAa,QAAU,CAClC,YAAaA,EAAQ,WACvB,CACF,CAAC,EACD,OAAQC,EAAW,MACrB,CAAC,EAED,GAAI,CAACf,EAAI,GAAI,CACX,IAAIC,EAAe,wBAAwBD,EAAI,MAAM,IAAIA,EAAI,UAAU,GACnEE,EAAY,mBAChB,GAAI,CACF,IAAMC,EAAO,MAAMH,EAAI,KAAK,EAIxBG,EAAI,QACNF,EAAeE,EAAI,OAEjBA,EAAI,OACND,EAAYC,EAAI,KAEpB,MAAQ,CAER,CACA,MAAM,IAAIC,EACRH,EACAC,EACAF,EAAI,MACN,CACF,CAEA,IAAMoB,EAASpB,EAAI,KAAM,UAAU,EAC7BqB,EAAU,IAAI,YAChBC,EAAS,GACTC,EAEJ,OAAa,CACX,GAAM,CAAE,KAAAC,EAAM,MAAAC,CAAM,EAAI,MAAML,EAAO,KAAK,EAC1C,GAAII,EACF,MAGFF,GAAUD,EAAQ,OAAOI,EAAO,CAAE,OAAQ,EAAK,CAAC,EAChD,IAAMC,EAAQJ,EAAO,MAAM;AAAA,CAAI,EAC/BA,EAASI,EAAM,IAAI,GAAK,GAExB,QAAWC,KAAQD,EAAO,CACxB,GAAI,CAACC,EAAK,WAAW,QAAQ,EAC3B,SAEF,IAAMC,EAAOD,EAAK,MAAM,CAAC,EACzB,GAAI,CACF,IAAMrB,EAAQ,KAAK,MAAMsB,CAAI,EAEzBtB,EAAM,OAAS,SACjBiB,EAAS,CACP,WAAYjB,EAAM,WAClB,MAAOA,EAAM,KACf,GAGFD,EAAcC,EAAOU,CAAE,CACzB,MAAQ,CAER,CACF,CACF,CAEA,GAAI,CAACO,EACH,MAAM,IAAInB,EACR,oCACA,mBACF,EAGF,OAAOmB,CACT,GAAG,EAGH,OAAAN,EAAU,MAAQ,IAAMF,EAAW,MAAM,EAClCE,CACT,CACF,CACF,CC9iBO,IAAMY,EAAW,CA4BtB,MAAM,WAAWC,EAAYC,EAA8C,CACzE,IAAMC,EAASC,EAAU,EACnB,CAAE,WAAAC,EAAY,OAAAC,CAAO,EAAIJ,GAAW,CAAC,EAG3CI,GAAQ,eAAe,EAIvB,IAAMC,EAAa,MAAM,MADN,6BACwB,CACzC,OAAQ,OACR,QAAS,CACP,cAAe,UAAUJ,EAAO,KAAK,GACrC,eAAgB,kBAClB,EACA,KAAM,KAAK,UAAU,CACnB,SAAUF,EAAK,KACf,YAAaA,EAAK,MAAQ,0BAC5B,CAAC,EACD,OAAAK,CACF,CAAC,EAED,GAAI,CAACC,EAAW,GACd,MAAM,IAAIC,EACR,0BAA0BD,EAAW,MAAM,IAAIA,EAAW,UAAU,GACpE,eACAA,EAAW,MACb,EAGF,GAAM,CAAE,UAAAE,EAAW,aAAAC,EAAc,UAAAC,CAAU,EACxC,MAAMJ,EAAW,KAAK,EAOnBK,EAAW,IAAI,SACrB,OAAW,CAACC,EAAKC,CAAK,IAAK,OAAO,QAAQJ,CAAY,EACpDE,EAAS,OAAOC,EAAKC,CAAK,EAK5B,GAHAF,EAAS,OAAO,OAAQX,CAAI,EAGxBI,EACF,aAAMU,EAAUN,EAAWG,EAAUP,EAAYC,CAAM,EAChDK,EAGT,IAAMK,EAAY,MAAM,MAAMP,EAAW,CACvC,OAAQ,OACR,KAAMG,EACN,OAAAN,CACF,CAAC,EAED,GAAI,CAACU,EAAU,GACb,MAAM,IAAIR,EACR,uBAAuBQ,EAAU,MAAM,IAAIA,EAAU,UAAU,GAC/D,eACAA,EAAU,MACZ,EAGF,OAAOL,CACT,CACF,EAMA,SAASI,EACPE,EACAL,EACAP,EACAC,EACe,CACf,OAAO,IAAI,QAAc,CAACY,EAASC,IAAW,CAC5C,IAAMC,EAAM,IAAI,eAqChB,GAnCAA,EAAI,OAAO,iBAAiB,WAAaC,GAAM,CACzCA,EAAE,kBACJhB,EAAWgB,EAAE,OAASA,EAAE,KAAK,CAEjC,CAAC,EAEDD,EAAI,iBAAiB,OAAQ,IAAM,CAC7BA,EAAI,QAAU,KAAOA,EAAI,OAAS,KACpCf,EAAW,CAAC,EACZa,EAAQ,GAERC,EACE,IAAIX,EACF,uBAAuBY,EAAI,MAAM,IAAIA,EAAI,UAAU,GACnD,eACAA,EAAI,MACN,CACF,CAEJ,CAAC,EAEDA,EAAI,iBAAiB,QAAS,IAAM,CAClCD,EACE,IAAIX,EACF,oCACA,cACF,CACF,CACF,CAAC,EAEDY,EAAI,iBAAiB,QAAS,IAAM,CAClCD,EAAO,IAAI,aAAa,iBAAkB,YAAY,CAAC,CACzD,CAAC,EAGGb,EAAQ,CACV,GAAIA,EAAO,QAAS,CAClBa,EAAO,IAAI,aAAa,iBAAkB,YAAY,CAAC,EACvD,MACF,CACAb,EAAO,iBAAiB,QAAS,IAAMc,EAAI,MAAM,EAAG,CAAE,KAAM,EAAK,CAAC,CACpE,CAEAA,EAAI,KAAK,OAAQH,CAAG,EACpBG,EAAI,KAAKR,CAAQ,CACnB,CAAC,CACH,CC1KO,IAAMU,EAAgC,CAC3C,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,cAAe,KAAM,oBAAO,EACjE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,SAAU,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,KAAM,KAAM,sBAAuB,KAAM,oBAAO,EACxE,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,YAAa,KAAM,oBAAO,EAC/D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,YAAa,KAAM,oBAAO,EAC/D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,UAAW,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,aAAc,KAAM,oBAAO,EACjE,CAAE,KAAM,KAAM,SAAU,KAAM,KAAM,UAAW,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,aAAc,KAAM,oBAAO,EACjE,CAAE,KAAM,KAAM,SAAU,KAAM,KAAM,WAAY,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,UAAW,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,SAAU,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,QAAS,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,SAAU,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,yBAA0B,KAAM,oBAAO,EAC7E,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,WAAY,KAAM,oBAAO,EAC/D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,SAAU,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,SAAU,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,WAAY,KAAM,oBAAO,EAC/D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,eAAgB,KAAM,oBAAO,EACnE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,aAAc,KAAM,oBAAO,EACjE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,WAAY,KAAM,oBAAO,EAC/D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,WAAY,KAAM,oBAAO,EAC/D,CAAE,KAAM,KAAM,SAAU,KAAM,KAAM,SAAU,KAAM,oBAAO,EAC3D,CACE,KAAM,KACN,SAAU,OACV,KAAM,2BACN,KAAM,oBACR,EACA,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,OAAQ,KAAM,oBAAO,EAC3D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,QAAS,KAAM,oBAAO,EAC3D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,QAAS,KAAM,oBAAO,EAC3D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,WAAY,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,QAAS,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,cAAe,KAAM,oBAAO,EAClE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,aAAc,KAAM,oBAAO,EACjE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,OAAQ,KAAM,oBAAO,EAC1D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,SAAU,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,gBAAiB,KAAM,oBAAO,EACpE,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,UAAW,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,WAAY,KAAM,oBAAO,EAC/D,CAAE,KAAM,KAAM,SAAU,KAAM,KAAM,WAAY,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,KAAM,KAAM,qBAAsB,KAAM,oBAAO,EACvE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,QAAS,KAAM,oBAAO,EAC3D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,cAAe,KAAM,oBAAO,EAClE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,oBAAqB,KAAM,oBAAO,EACxE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,WAAY,KAAM,oBAAO,EAC/D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,WAAY,KAAM,oBAAO,EAC/D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,OAAQ,KAAM,oBAAO,EAC3D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,SAAU,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,QAAS,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,SAAU,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,UAAW,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,QAAS,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,SAAU,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,KAAM,KAAM,UAAW,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,YAAa,KAAM,oBAAO,EAChE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,SAAU,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,gBAAiB,KAAM,oBAAO,EACpE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,SAAU,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,QAAS,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,WAAY,KAAM,oBAAO,EAC/D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,YAAa,KAAM,oBAAO,EAChE,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,UAAW,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,QAAS,KAAM,oBAAO,EAC3D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,YAAa,KAAM,oBAAO,EAC/D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,OAAQ,KAAM,oBAAO,EAC1D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,OAAQ,KAAM,oBAAO,EAC3D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,SAAU,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,QAAS,KAAM,oBAAO,EAC3D,CAAE,KAAM,KAAM,SAAU,KAAM,KAAM,UAAW,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,QAAS,KAAM,oBAAO,EAC3D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,SAAU,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,KAAM,KAAM,aAAc,KAAM,oBAAO,EAC/D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,QAAS,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,WAAY,KAAM,oBAAO,EAC/D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,SAAU,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,aAAc,KAAM,oBAAO,EACjE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,OAAQ,KAAM,oBAAO,EAC3D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,SAAU,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,QAAS,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,gBAAiB,KAAM,oBAAO,EACpE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,YAAa,KAAM,oBAAO,EAChE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,aAAc,KAAM,oBAAO,EACjE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,QAAS,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,aAAc,KAAM,oBAAO,EACjE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,SAAU,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,WAAY,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,WAAY,KAAM,oBAAO,EAC/D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,OAAQ,KAAM,oBAAO,EAC3D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,QAAS,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,mBAAoB,KAAM,oBAAO,EACvE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,aAAc,KAAM,oBAAO,EACjE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,YAAa,KAAM,oBAAO,EAChE,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,SAAU,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,aAAc,KAAM,oBAAO,EACjE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,SAAU,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,WAAY,KAAM,oBAAO,EAC/D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,aAAc,KAAM,oBAAO,EACjE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,aAAc,KAAM,oBAAO,EACjE,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,UAAW,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,QAAS,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,QAAS,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,cAAe,KAAM,oBAAO,EACjE,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,cAAe,KAAM,oBAAO,EACjE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,YAAa,KAAM,oBAAO,EAChE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,QAAS,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,cAAe,KAAM,oBAAO,EAClE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,kBAAmB,KAAM,oBAAO,EACtE,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,SAAU,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,OAAQ,KAAM,oBAAO,EAC3D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,WAAY,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,QAAS,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,YAAa,KAAM,oBAAO,EAChE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,SAAU,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,mBAAoB,KAAM,oBAAO,EACvE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,WAAY,KAAM,oBAAO,EAC/D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,OAAQ,KAAM,oBAAO,EAC1D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,cAAe,KAAM,oBAAO,EACjE,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,SAAU,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,WAAY,KAAM,oBAAO,EAC/D,CAAE,KAAM,KAAM,SAAU,KAAM,KAAM,cAAe,KAAM,oBAAO,EAChE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,QAAS,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,UAAW,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,KAAM,KAAM,SAAU,KAAM,oBAAO,EAC3D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,SAAU,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,KAAM,KAAM,wBAAyB,KAAM,oBAAO,EAC1E,CAAE,KAAM,KAAM,SAAU,KAAM,KAAM,cAAe,KAAM,oBAAO,EAChE,CACE,KAAM,KACN,SAAU,KACV,KAAM,mCACN,KAAM,oBACR,EACA,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,QAAS,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,aAAc,KAAM,oBAAO,EACjE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,wBAAyB,KAAM,oBAAO,EAC5E,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,eAAgB,KAAM,oBAAO,EACnE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,SAAU,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,aAAc,KAAM,oBAAO,EACjE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,eAAgB,KAAM,oBAAO,EACnE,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,YAAa,KAAM,oBAAO,EAC/D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,WAAY,KAAM,oBAAO,EAC/D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,WAAY,KAAM,oBAAO,EAC/D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,kBAAmB,KAAM,oBAAO,EACtE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,eAAgB,KAAM,oBAAO,EAClE,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,cAAe,KAAM,oBAAO,EACjE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,cAAe,KAAM,oBAAO,EAClE,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,QAAS,KAAM,oBAAO,EAC3D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,YAAa,KAAM,oBAAO,EAC/D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,QAAS,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,WAAY,KAAM,oBAAO,EAC/D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,SAAU,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,cAAe,KAAM,oBAAO,EACjE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,QAAS,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,SAAU,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,aAAc,KAAM,oBAAO,EACjE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,WAAY,KAAM,oBAAO,EAC/D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,WAAY,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,cAAe,KAAM,oBAAO,EAClE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,OAAQ,KAAM,oBAAO,EAC3D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,QAAS,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,KAAM,KAAM,sBAAuB,KAAM,oBAAO,EACxE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,SAAU,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,eAAgB,KAAM,oBAAO,EACnE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,SAAU,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,SAAU,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,uBAAwB,KAAM,oBAAO,EAC3E,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,iBAAkB,KAAM,oBAAO,EACpE,CAAE,KAAM,KAAM,SAAU,KAAM,KAAM,gBAAiB,KAAM,oBAAO,EAClE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,aAAc,KAAM,oBAAO,EACjE,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,UAAW,KAAM,oBAAO,EAC9D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,eAAgB,KAAM,oBAAO,EAClE,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,YAAa,KAAM,oBAAO,EAC/D,CAAE,KAAM,KAAM,SAAU,MAAO,KAAM,UAAW,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,QAAS,KAAM,oBAAO,EAC5D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,SAAU,KAAM,oBAAO,EAC7D,CAAE,KAAM,KAAM,SAAU,OAAQ,KAAM,WAAY,KAAM,oBAAO,CACjE,EAMMC,EAAS,IAAI,IAAID,EAAU,IAAKE,GAAM,CAACA,EAAE,KAAMA,CAAC,CAAC,CAAC,EAGlDC,EAA4C,CAChD,mBAAoB,KACpB,kBAAmB,KACnB,iBAAkB,KAClB,sBAAuB,KACvB,oBAAqB,KACrB,mBAAoB,KACpB,kBAAmB,KACnB,+BAAgC,KAChC,kBAAmB,KACnB,oBAAqB,KACrB,mBAAoB,KACpB,mBAAoB,KACpB,kBAAmB,KACnB,mBAAoB,KACpB,gBAAiB,KACjB,gBAAiB,KACjB,eAAgB,KAChB,gBAAiB,KACjB,gBAAiB,KACjB,cAAe,KACf,mBAAoB,KACpB,kBAAmB,KACnB,gBAAiB,KACjB,gBAAiB,KACjB,mBAAoB,KACpB,cAAe,KACf,oBAAqB,KACrB,kBAAmB,KACnB,gBAAiB,KACjB,gBAAiB,KACjB,mBAAoB,KACpB,kBAAmB,KACnB,gBAAiB,KACjB,kBAAmB,KACnB,gBAAiB,KACjB,cAAe,KACf,gBAAiB,KACjB,kBAAmB,KACnB,gBAAiB,KACjB,oBAAqB,KACrB,mBAAoB,KACpB,iBAAkB,KAClB,cAAe,KACf,iBAAkB,KAClB,aAAc,KACd,aAAc,KACd,gBAAiB,KACjB,iBAAkB,KAClB,cAAe,KACf,iBAAkB,KAClB,eAAgB,KAChB,eAAgB,KAChB,aAAc,KACd,eAAgB,KAChB,eAAgB,KAChB,cAAe,KACf,oBAAqB,KACrB,mBAAoB,KACpB,cAAe,KACf,aAAc,KACd,cAAe,KACf,eAAgB,KAChB,cAAe,KACf,iBAAkB,KAClB,aAAc,KACd,cAAe,KACf,gBAAiB,KACjB,eAAgB,KAChB,iBAAkB,KAClB,cAAe,KACf,mBAAoB,KACpB,sBAAuB,KACvB,qBAAsB,KACtB,kBAAmB,KACnB,qBAAsB,KACtB,mBAAoB,KACpB,eAAgB,KAChB,eAAgB,KAChB,eAAgB,KAChB,iBAAkB,KAClB,sBAAuB,KACvB,oBAAqB,KACrB,eAAgB,KAChB,qBAAsB,KACtB,uBAAwB,KACxB,iBAAkB,KAClB,sBAAuB,KACvB,iBAAkB,KAClB,eAAgB,KAChB,mBAAoB,KACpB,uBAAwB,KACxB,oBAAqB,KACrB,kBAAmB,KACnB,oBAAqB,KACrB,iBAAkB,KAClB,iBAAkB,KAClB,kBAAmB,IACrB,EAUO,SAASC,GAAwB,CACtC,GAAI,CACF,IAAMC,EAAK,KAAK,eAAe,EAAE,gBAAgB,EAAE,SACnD,OAAOF,EAAkBE,CAAE,GAAK,IAClC,MAAQ,CACN,MAAO,IACT,CACF,CAQO,SAASC,EAAOC,EAAsB,CAC3C,GAAI,CAACA,EAAK,WAAW,GAAG,EACtB,OAAOA,EAGT,IAAMC,EAASD,EAAK,MAAM,CAAC,EAG3B,GAAIC,EAAO,WAAW,GAAG,GAAKA,EAAO,SAAW,GAAI,CAClD,IAAMC,EAAOD,EAAO,MAAM,EAAG,CAAC,EACxBE,EAASF,EAAO,MAAM,EAAG,CAAC,EAC1BG,EAAOH,EAAO,MAAM,CAAC,EAC3B,MAAO,OAAOC,CAAI,KAAKC,CAAM,IAAIC,CAAI,EACvC,CAGA,QAASC,EAAM,EAAGA,GAAO,EAAGA,IAAO,CACjC,IAAMC,EAAY,IAAML,EAAO,MAAM,EAAGI,CAAG,EACrCE,EAAQd,EAAU,KAAME,GAAMA,EAAE,WAAaW,CAAS,EAC5D,GAAIC,EAAO,CACT,IAAMC,EAAOP,EAAO,MAAMI,CAAG,EAC7B,MAAO,GAAGE,EAAM,QAAQ,IAAIC,CAAI,EAClC,CACF,CAEA,OAAOR,CACT,CASO,SAASS,EAAOC,EAAkBC,EAA6B,CACpE,IAAMV,EAASS,EAAS,QAAQ,MAAO,EAAE,EACnCE,EAAUlB,EAAO,IAAIiB,CAAW,EACtC,GAAI,CAACC,EACH,MAAO,IAAMX,EAEf,IAAMY,EAAaD,EAAQ,SAAS,MAAM,CAAC,EAE3C,OAAIX,EAAO,WAAWY,CAAU,EACvB,IAAMZ,EAERW,EAAQ,SAAWX,CAC5B,CAMO,SAASa,EAAQC,EAAwB,CAC9C,MAAO,oBAAoB,KAAKA,CAAK,CACvC,CCjaO,SAASC,EAAQC,EAAwB,CAC9C,MAAO,6BAA6B,KAAKA,CAAK,CAChD,CCoDA,eAAeC,EACbC,EACAC,EACAC,EACY,CAEZ,IAAMC,EAAkC,CACtC,cAAe,UAFFC,EAAU,EAES,KAAK,EACvC,EAEIF,IAAS,SACXC,EAAQ,cAAc,EAAI,oBAG5B,IAAME,EAAM,MAAM,MAAML,EAAM,CAC5B,OAAAC,EACA,QAAAE,EACA,GAAID,IAAS,QAAa,CAAE,KAAM,KAAK,UAAUA,CAAI,CAAE,CACzD,CAAC,EAED,GAAI,CAACG,EAAI,GAAI,CACX,IAAIC,EAAU,wBAAwBD,EAAI,MAAM,IAAIA,EAAI,UAAU,GAC9DE,EAAO,aACX,GAAI,CACF,IAAMC,EAAO,MAAMH,EAAI,KAAK,EACxBG,EAAI,QACNF,EAAUE,EAAI,OAEZA,EAAI,OACND,EAAOC,EAAI,KAEf,MAAQ,CAER,CACA,MAAM,IAAIC,EAAyBH,EAASC,EAAMF,EAAI,MAAM,CAC9D,CAEA,OAAQ,MAAMA,EAAI,KAAK,CACzB,CAEA,SAASK,EAAaC,EAAiC,CACrDC,EAAa,CACX,MAAOD,EAAO,MACd,KAAMA,EAAO,KACb,QAASA,EAAO,OAClB,CAAC,CACH,CAEA,SAASE,EAAYF,EAAoC,CACvD,GAAI,CAACA,EAAO,KACV,MAAM,IAAIF,EACR,kDACA,YACF,EAEF,OAAOE,EAAO,IAChB,CAoFO,IAAMG,EAAa,CAGxB,gBAAiB,CACf,OAAOV,EAAU,EAAE,IACrB,EAEA,iBAAkB,CAChB,OAAOA,EAAU,EAAE,OAAS,IAC9B,EAIA,cAAcW,EAAe,CAC3B,OAAOhB,EAAsC,qBAAsB,OAAQ,CACzE,MAAAgB,CACF,CAAC,CACH,EAEA,MAAM,gBAAgBC,EAAwBT,EAAc,CAC1D,IAAMI,EAAS,MAAMZ,EACnB,uBACA,OACA,CAAE,eAAAiB,EAAgB,KAAAT,CAAK,CACzB,EACA,OAAAG,EAAaC,CAAM,EACZE,EAAYF,CAAM,CAC3B,EAIA,YAAYM,EAAe,CACzB,OAAOlB,EAAsC,mBAAoB,OAAQ,CACvE,MAAAkB,CACF,CAAC,CACH,EAEA,MAAM,cAAcD,EAAwBT,EAAc,CACxD,IAAMI,EAAS,MAAMZ,EACnB,qBACA,OACA,CAAE,eAAAiB,EAAgB,KAAAT,CAAK,CACzB,EACA,OAAAG,EAAaC,CAAM,EACZE,EAAYF,CAAM,CAC3B,EAIA,MAAM,mBAAmBO,EAAkB,CACzC,MAAMnB,EAAU,uBAAwB,OAAQ,CAAE,SAAAmB,CAAS,CAAC,CAC9D,EAEA,MAAM,mBAAmBA,EAAkBX,EAAc,CACvD,IAAMI,EAAS,MAAMZ,EACnB,+BACA,OACA,CAAE,SAAAmB,EAAU,KAAAX,CAAK,CACnB,EACA,OAAAG,EAAaC,CAAM,EACZE,EAAYF,CAAM,CAC3B,EAEA,MAAM,mBAAmBQ,EAAkB,CACzC,MAAMpB,EAAU,uBAAwB,OAAQ,CAAE,SAAAoB,CAAS,CAAC,CAC9D,EAEA,MAAM,mBAAmBA,EAAkBZ,EAAc,CACvD,IAAMI,EAAS,MAAMZ,EACnB,+BACA,OACA,CAAE,SAAAoB,EAAU,KAAAZ,CAAK,CACnB,EACA,OAAAG,EAAaC,CAAM,EACZE,EAAYF,CAAM,CAC3B,EAIA,MAAM,QAAS,CACb,IAAMA,EAAS,MAAMZ,EACnB,iBACA,OACA,CAAC,CACH,EACAW,EAAaC,CAAM,CACrB,EAIA,MAAO,CACL,UAAwBS,EACxB,cAA4BC,EAC5B,OAAqBC,EACrB,OAAqBC,EACrB,QAAsBC,CACxB,EAEA,MAAO,CACL,QAAsBA,CACxB,CACF","names":["MindStudioInterfaceError","message","code","status","_config","getConfig","raw","MindStudioInterfaceError","missing","k","updateConfig","updates","config","createClient","_","methodName","input","options","config","getConfig","methodId","MindStudioInterfaceError","url","wantsStream","res","errorMessage","errorCode","body","reader","decoder","buffer","finalOutput","done","value","lines","line","json","event","AGENT_BASE","request","path","method","body","headers","getConfig","res","errorMessage","errorCode","err","MindStudioInterfaceError","dispatchEvent","event","callbacks","createAgentChatClient","cursor","query","threadId","title","content","options","controller","cb","abortable","config","url","reader","decoder","buffer","result","done","value","lines","line","json","platform","file","options","config","getConfig","onProgress","signal","presignRes","MindStudioInterfaceError","uploadUrl","uploadFields","publicUrl","formData","key","value","xhrUpload","uploadRes","url","resolve","reject","xhr","e","countries","byCode","c","timezoneToCountry","detectCountry","tz","format","e164","digits","area","prefix","line","len","candidate","match","rest","toE164","national","countryCode","country","dialDigits","isValid","phone","isValid","email","authFetch","path","method","body","headers","getConfig","res","message","code","err","MindStudioInterfaceError","applySession","bundle","updateConfig","requireUser","auth","email","verificationId","phone","newEmail","newPhone","countries","detectCountry","format","toE164","isValid"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/config.ts","../src/client.ts","../src/agent-chat.ts","../src/platform.ts","../src/auth-phone.ts","../src/auth-email.ts","../src/auth.ts"],"sourcesContent":["/**\n * Error class for the @mindstudio-ai/interface SDK.\n *\n * Thrown by `createClient()` method calls on HTTP errors, by `platform`\n * actions on failures, and by the config reader when bootstrap globals\n * are missing.\n */\nexport class MindStudioInterfaceError extends Error {\n /** Machine-readable error code (e.g. 'method_not_found', 'not_initialized'). */\n readonly code: string;\n\n /** HTTP status code, when the error originated from an API response. */\n readonly status?: number;\n\n constructor(message: string, code: string, status?: number) {\n super(message);\n this.name = 'MindStudioInterfaceError';\n this.code = code;\n this.status = status;\n }\n}\n","/**\n * Bootstrap configuration reader.\n *\n * Reads and validates `window.__MINDSTUDIO__` — the globals injected by\n * the platform before the app's JavaScript runs. The result is cached\n * after first read.\n *\n * All other modules in the SDK call `getConfig()` internally. App code\n * should never need to call this directly — use `createClient()`, `auth`,\n * and `platform` instead.\n */\n\nimport { MindStudioInterfaceError } from './errors.js';\nimport type { AppUser, BootstrapConfig } from './types.js';\n\nlet _config: BootstrapConfig | undefined;\n\n/**\n * Read and validate the bootstrap configuration from `window.__MINDSTUDIO__`.\n *\n * Caches the result after first successful read. Throws if the globals\n * are missing or incomplete — this means the page isn't running inside\n * the MindStudio platform.\n *\n * @returns The validated bootstrap config\n * @throws {MindStudioInterfaceError} if `window.__MINDSTUDIO__` is missing or invalid\n */\nexport function getConfig(): BootstrapConfig {\n if (_config) {\n return _config;\n }\n\n const raw = (globalThis as Record<string, unknown>).__MINDSTUDIO__ as\n | Partial<BootstrapConfig>\n | undefined;\n\n if (!raw) {\n throw new MindStudioInterfaceError(\n '@mindstudio-ai/interface requires the MindStudio platform context. ' +\n 'This page must be loaded inside MindStudio (window.__MINDSTUDIO__ is missing).',\n 'not_initialized',\n );\n }\n\n // Validate required fields (user can be null for unauthenticated sessions)\n if (!raw.token || !raw.releaseId || !raw.methods) {\n const missing = ['token', 'releaseId', 'methods']\n .filter((k) => !raw[k as keyof BootstrapConfig])\n .join(', ');\n\n throw new MindStudioInterfaceError(\n `MindStudio platform context is incomplete. Missing: ${missing}`,\n 'invalid_config',\n );\n }\n\n _config = raw as BootstrapConfig;\n return _config;\n}\n\n/**\n * Update the cached config in-place after an auth state transition.\n *\n * The cached config is a mutable reference — all SDK modules read it\n * on-demand via `getConfig()`, so mutations propagate immediately to\n * method invocation, agent chat, uploads, etc.\n *\n * @internal Not exported from the package — used by the auth module only.\n */\nexport function updateConfig(updates: {\n token?: string;\n user?: AppUser | null;\n methods?: Record<string, string>;\n}): void {\n const config = getConfig();\n if (updates.token !== undefined) {\n config.token = updates.token;\n }\n if (updates.user !== undefined) {\n config.user = updates.user;\n }\n if (updates.methods !== undefined) {\n config.methods = updates.methods;\n }\n}\n","/**\n * Method RPC client — typed function calls to backend methods.\n *\n * `createClient()` returns a Proxy where every property access creates\n * an async function that invokes the corresponding backend method via HTTP.\n * The method name matches the method's `export` field in `app.json`.\n *\n * ## How it works\n *\n * ```\n * api.submitVendorRequest({ name: 'Acme' })\n * │\n * ├─ Look up method ID: config.methods[\"submitVendorRequest\"]\n * │ → \"submit-vendor-request\"\n * │\n * ├─ POST /_/methods/submit-vendor-request/invoke\n * │ Authorization: Bearer {session token}\n * │ Body: { input: { name: \"Acme\" } }\n * │\n * └─ Returns response.output (or throws on error)\n * ```\n *\n * The method registry (export name → method ID mapping) is embedded in\n * `window.__MINDSTUDIO__.methods` at page load time — no extra HTTP call\n * needed to discover methods.\n *\n * ## Streaming\n *\n * Methods can optionally stream LLM token output via SSE. Pass\n * `{ stream: true }` as the second argument along with an `onToken`\n * callback to receive incremental updates:\n *\n * ```ts\n * const result = await api.submitVendorRequest({ name: 'Acme' }, {\n * stream: true,\n * onToken: (text) => setResponseText(text),\n * });\n * ```\n *\n * **Important:** The `text` value passed to `onToken` is the accumulated\n * response so far (not a delta). Replace your display content each time —\n * do not append. See {@link InvokeOptions.onToken} for details.\n *\n * ## Type safety\n *\n * Since the frontend and backend live in the same project, you can import\n * types directly:\n *\n * ```ts\n * import type { SubmitVendorInput, SubmitVendorOutput }\n * from '../../backend/src/submitVendorRequest';\n *\n * interface AppMethods {\n * submitVendorRequest(input: SubmitVendorInput): Promise<SubmitVendorOutput>;\n * getDashboard(): Promise<GetDashboardOutput>;\n * }\n *\n * const api = createClient<AppMethods>();\n * const result = await api.submitVendorRequest({ name: 'Acme' }); // fully typed\n * ```\n *\n * If no type parameter is provided, methods accept `any` input and return `any`.\n */\n\nimport { getConfig } from './config.js';\nimport { MindStudioInterfaceError } from './errors.js';\n\n/**\n * Options for method invocation. Pass as the optional second argument to\n * any method on the client returned by {@link createClient}.\n *\n * When `stream` is `true`, the SDK sends `{ stream: true }` in the request\n * body and parses the response as an SSE (Server-Sent Events) stream.\n * Three event types are handled:\n *\n * | SSE `type` | Payload field | SDK action |\n * |------------|---------------|------------|\n * | `token` | `text` | Calls {@link onToken} with accumulated text |\n * | `error` | `error` | Calls {@link onStreamError} with the message |\n * | `done` | `output` | Captures as the method's return value |\n *\n * The method's `Promise` resolves with the final `output` from the `done`\n * event — the same shape you'd get without streaming.\n */\nexport interface InvokeOptions {\n /**\n * Enable SSE streaming for LLM token output.\n *\n * When `true`, the request body includes `{ stream: true }` and the\n * response is parsed as an SSE stream instead of a single JSON payload.\n * The method still returns a `Promise` that resolves with the final\n * output once the stream completes.\n *\n * @default false\n */\n stream?: boolean;\n\n /**\n * Called with the accumulated response text each time a new token arrives.\n *\n * **Important:** `text` is the full response so far, not a delta/chunk.\n * Your frontend should **replace** (not append to) its display content\n * with this value each time the callback fires.\n *\n * This design avoids edge cases where the platform sanitizes or\n * reformats JSON mid-stream, causing earlier portions of the text to\n * change between tokens.\n *\n * @example\n * ```ts\n * const result = await api.generate({ prompt: 'Hello' }, {\n * stream: true,\n * onToken: (text) => {\n * // Replace — do NOT append\n * responseElement.textContent = text;\n * },\n * });\n * ```\n */\n onToken?: (text: string) => void;\n\n /**\n * Called if a stream-level error occurs.\n *\n * Stream errors are non-fatal at the protocol level — the method may\n * still complete and resolve with a final output. Use this callback for\n * logging or showing a transient warning, not for control flow.\n *\n * If the stream ends without a `done` event, the method rejects with a\n * `MindStudioInterfaceError` (code `stream_incomplete`) regardless of\n * whether `onStreamError` was provided.\n */\n onStreamError?: (error: string) => void;\n}\n\n/**\n * Default client type when no generic parameter is provided.\n * Every property returns an async function accepting optional input\n * and optional {@link InvokeOptions} for streaming.\n */\ntype DefaultMethodClient = Record<\n string,\n (input?: Record<string, unknown>, options?: InvokeOptions) => Promise<unknown>\n>;\n\n/**\n * Create a typed RPC client for calling backend methods.\n *\n * @typeParam T - Optional interface mapping method names to their signatures.\n * If omitted, all methods accept `any` and return `Promise<any>`.\n *\n * @returns A Proxy object where each property is an async function that\n * invokes the corresponding backend method.\n *\n * @example\n * ```ts\n * import { createClient } from '@mindstudio-ai/interface';\n *\n * const api = createClient();\n *\n * // Each method maps to a backend method export\n * const result = await api.submitVendorRequest({ name: 'Acme' });\n * const dashboard = await api.getDashboard();\n *\n * // Stream LLM output — onToken receives accumulated text (replace, don't append)\n * const streamed = await api.submitVendorRequest({ name: 'Acme' }, {\n * stream: true,\n * onToken: (text) => setResponseText(text),\n * });\n * // `streamed` is the same final output you'd get without streaming\n * ```\n */\nexport function createClient<T = DefaultMethodClient>(): T {\n return new Proxy({} as Record<string, unknown> as T & object, {\n get(_, methodName: string) {\n return async (input?: unknown, options?: InvokeOptions) => {\n const config = getConfig();\n\n const methodId = config.methods[methodName];\n if (!methodId) {\n throw new MindStudioInterfaceError(\n `Method \"${methodName}\" not found. Available methods: ${Object.keys(config.methods).join(', ') || '(none)'}`,\n 'method_not_found',\n );\n }\n\n const url = `/_/methods/${methodId}/invoke`;\n const wantsStream = options?.stream === true;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${config.token}`,\n },\n body: JSON.stringify({\n input: input ?? {},\n ...(wantsStream && { stream: true }),\n }),\n });\n\n if (!res.ok) {\n let errorMessage = `Method \"${methodName}\" failed: ${res.status} ${res.statusText}`;\n let errorCode = 'method_error';\n try {\n const body = (await res.json()) as {\n error?: string;\n code?: string;\n };\n if (body.error) {\n errorMessage = body.error;\n }\n if (body.code) {\n errorCode = body.code;\n }\n } catch {\n // Response wasn't JSON — use the default message\n }\n throw new MindStudioInterfaceError(\n errorMessage,\n errorCode,\n res.status,\n );\n }\n\n // Non-streaming: unchanged behavior\n if (!wantsStream) {\n const body = (await res.json()) as { output?: unknown };\n return body.output;\n }\n\n // Streaming: parse SSE events from response body\n const reader = res.body!.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n let finalOutput: unknown;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n\n for (const line of lines) {\n if (!line.startsWith('data: ')) {\n continue;\n }\n const json = line.slice(6);\n try {\n const event = JSON.parse(json) as {\n type: string;\n text?: string;\n error?: string;\n output?: unknown;\n };\n\n if (event.type === 'token' && options?.onToken && event.text) {\n options.onToken(event.text);\n } else if (event.type === 'error' && event.error) {\n if (options?.onStreamError) {\n options.onStreamError(event.error);\n }\n } else if (event.type === 'done') {\n finalOutput = event.output;\n }\n } catch {\n // Skip malformed SSE lines\n }\n }\n }\n\n if (finalOutput === undefined) {\n throw new MindStudioInterfaceError(\n 'Stream ended without a done event',\n 'stream_incomplete',\n );\n }\n\n return finalOutput;\n };\n },\n });\n}\n","/**\n * Agent chat client — thread-based conversations with AI agents.\n *\n * `createAgentChatClient()` returns an object with methods for thread\n * lifecycle (create, list, get, rename, delete) and message streaming.\n * The agent runs server-side with access to the app's methods as tools.\n *\n * ## How it works\n *\n * ```\n * chat.sendMessage(threadId, 'Help me prep for my review', {\n * onText: (delta) => setAssistantMessage((prev) => prev + delta),\n * })\n * │\n * ├─ POST /_/agent/threads/{threadId}/messages\n * │ Authorization: Bearer {session token}\n * │ Body: { content: \"Help me prep for my review\" }\n * │\n * ├─ Response: SSE stream\n * │ data: {\"type\":\"text\",\"text\":\"I'll create...\",\"ts\":1711...}\n * │ data: {\"type\":\"tool_call_start\",\"id\":\"call_abc\",\"name\":\"create-todo\",\"ts\":1711...}\n * │ data: {\"type\":\"tool_call_result\",\"id\":\"call_abc\",\"output\":{...},\"ts\":1711...}\n * │ data: {\"type\":\"text\",\"text\":\"Done — added it.\",\"ts\":1711...}\n * │ data: {\"type\":\"done\",\"stopReason\":\"end_turn\",\"usage\":{...},\"ts\":1711...}\n * │\n * └─ Promise resolves with { stopReason, usage }\n * ```\n *\n * ## Stateless design\n *\n * This client is a thin wrapper over HTTP endpoints. It does not manage\n * local state — your React/framework layer owns the thread list, message\n * array, and UI state. Each method is an independent request.\n *\n * ## Streaming callbacks\n *\n * `sendMessage` accepts named callbacks for common events (onText,\n * onThinking, onToolCallStart, etc.) plus a catch-all `onEvent` that\n * receives every SSE event as a discriminated union. Both fire for the\n * same event — use named callbacks for convenience, `onEvent` for\n * logging or handling low-level events like `tool_use` and\n * `tool_input_delta`.\n *\n * @example\n * ```ts\n * import { createAgentChatClient } from '@mindstudio-ai/interface';\n *\n * const chat = createAgentChatClient();\n *\n * // Thread lifecycle\n * const thread = await chat.createThread();\n * const { threads } = await chat.listThreads();\n * const full = await chat.getThread(thread.id);\n *\n * // Send a message with streaming\n * const response = chat.sendMessage(thread.id, 'Hello!', {\n * onText: (delta) => setMessage((prev) => prev + delta),\n * onToolCallStart: (id, name) => showToolSpinner(name),\n * onToolCallResult: (id, output) => showToolResult(output),\n * });\n *\n * const { stopReason, usage } = await response;\n *\n * // Abort mid-stream\n * response.abort();\n * ```\n */\n\nimport { getConfig } from './config.js';\nimport { MindStudioInterfaceError } from './errors.js';\n\n// ---------------------------------------------------------------------------\n// Thread types\n// ---------------------------------------------------------------------------\n\n/** Thread summary returned from create and list endpoints. */\nexport interface ThreadSummary {\n /** Thread ID (UUID). */\n id: string;\n /** User-editable title, auto-generated on first message. */\n title: string | null;\n /** ISO 8601 creation timestamp. */\n dateCreated: string;\n /** ISO 8601 last-updated timestamp. */\n dateUpdated: string;\n}\n\n/** Full thread with message history, returned from get endpoint. */\nexport interface Thread {\n /** Thread ID (UUID). */\n id: string;\n /** User-editable title. */\n title: string | null;\n /** Full conversation history. */\n messages: Message[];\n /** ISO 8601 creation timestamp. */\n dateCreated: string;\n /** ISO 8601 last-updated timestamp. */\n dateUpdated: string;\n}\n\n/** A tool call requested by the assistant. */\nexport interface ToolCall {\n /** Tool call ID, used to match results. */\n id: string;\n /** Method name. */\n name: string;\n /** Input arguments. */\n input: Record<string, unknown>;\n}\n\n/** A single message in a thread's conversation history. */\nexport interface Message {\n /** `\"user\"` for human messages, `\"assistant\"` for agent responses. */\n role: 'user' | 'assistant';\n /** Message text content. For tool results, this is JSON-stringified output. */\n content: string;\n /**\n * MindStudio CDN URLs attached to this message (user messages only).\n *\n * Images (`i.mscdn.ai`) are sent to the model as vision input.\n * Documents (`f.mscdn.ai`, `files.mindstudio-cdn.com`) have their text\n * extracted server-side and included in the model context. The original\n * URLs are preserved in thread history for the frontend to render.\n */\n attachments?: string[];\n /** Tool calls the assistant requested (assistant messages only). */\n toolCalls?: ToolCall[];\n /** ID of the tool call this message is a result for (tool result messages only). */\n toolCallId?: string;\n /** Whether this tool result represents an error. */\n isToolError?: boolean;\n}\n\n/** Paginated thread list response. */\nexport interface ThreadListPage {\n /** Threads for this page. */\n threads: ThreadSummary[];\n /** Cursor for the next page, or `null` if this is the last page. */\n nextCursor: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// SSE event types\n// ---------------------------------------------------------------------------\n\n/** Assistant text delta — append to your display string, do not replace. */\nexport interface AgentTextEvent {\n type: 'text';\n text: string;\n ts: number;\n}\n\n/** Model thinking text (extended thinking). */\nexport interface AgentThinkingEvent {\n type: 'thinking';\n text: string;\n ts: number;\n}\n\n/** Thinking complete with full text and signature. */\nexport interface AgentThinkingCompleteEvent {\n type: 'thinking_complete';\n thinking: string;\n signature: string;\n ts: number;\n}\n\n/** Model requested a tool call (includes parsed input). */\nexport interface AgentToolUseEvent {\n type: 'tool_use';\n id: string;\n name: string;\n input: Record<string, unknown>;\n ts: number;\n}\n\n/** Streaming delta for tool call input JSON. */\nexport interface AgentToolInputDeltaEvent {\n type: 'tool_input_delta';\n id: string;\n name: string;\n delta: string;\n ts: number;\n}\n\n/** Agent began executing a tool call. */\nexport interface AgentToolCallStartEvent {\n type: 'tool_call_start';\n id: string;\n name: string;\n ts: number;\n}\n\n/** Tool call returned a result. */\nexport interface AgentToolCallResultEvent {\n type: 'tool_call_result';\n id: string;\n output: unknown;\n ts: number;\n}\n\n/** Stream complete. */\nexport interface AgentDoneEvent {\n type: 'done';\n stopReason: string;\n usage: { inputTokens: number; outputTokens: number };\n ts: number;\n}\n\n/** Stream-level error. */\nexport interface AgentErrorEvent {\n type: 'error';\n error: string;\n ts: number;\n}\n\n/** Discriminated union of all SSE events from the agent chat stream. */\nexport type AgentChatEvent =\n | AgentTextEvent\n | AgentThinkingEvent\n | AgentThinkingCompleteEvent\n | AgentToolUseEvent\n | AgentToolInputDeltaEvent\n | AgentToolCallStartEvent\n | AgentToolCallResultEvent\n | AgentDoneEvent\n | AgentErrorEvent;\n\n// ---------------------------------------------------------------------------\n// Callbacks and result types\n// ---------------------------------------------------------------------------\n\n/**\n * Callbacks for `sendMessage` streaming.\n *\n * Named callbacks fire for common events. The catch-all `onEvent` fires\n * for every event including those with named callbacks — use it for\n * logging or handling low-level events like `tool_use` and\n * `tool_input_delta`.\n */\nexport interface SendMessageCallbacks {\n /**\n * Called with each text delta as the assistant responds.\n *\n * **Important:** `text` is a delta (new chunk), not the accumulated\n * response. Append it to your display string — do not replace.\n *\n * @example\n * ```ts\n * onText: (delta) => setMessage((prev) => prev + delta)\n * ```\n */\n onText?: (text: string) => void;\n\n /** Called with model thinking text (extended thinking). */\n onThinking?: (text: string) => void;\n\n /** Called when thinking is complete. */\n onThinkingComplete?: (thinking: string, signature: string) => void;\n\n /** Called when a tool call begins executing. */\n onToolCallStart?: (id: string, name: string) => void;\n\n /** Called when a tool call produces a result. */\n onToolCallResult?: (id: string, output: unknown) => void;\n\n /** Called on a stream-level error event. */\n onError?: (error: string) => void;\n\n /** Called for every SSE event (including ones with named callbacks). */\n onEvent?: (event: AgentChatEvent) => void;\n\n /** AbortSignal to cancel the stream. */\n signal?: AbortSignal;\n}\n\n/** Options for `sendMessage`. */\nexport interface SendMessageOptions {\n /**\n * MindStudio CDN URLs to attach to the message.\n *\n * Images (`i.mscdn.ai`) are sent to the model as vision input (one per message).\n * Documents (`f.mscdn.ai`, `files.mindstudio-cdn.com`) have their text\n * extracted server-side and included in context.\n *\n * Upload files first via `platform.uploadFile()`.\n *\n * @example\n * ```ts\n * const url = await platform.uploadFile(file);\n * chat.sendMessage(threadId, 'What is this?', callbacks, {\n * attachments: [url],\n * });\n * ```\n */\n attachments?: string[];\n}\n\n/** Resolved value of `sendMessage` — extracted from the `done` event. */\nexport interface SendMessageResult {\n /** Why the agent stopped (`\"end_turn\"`, `\"max_tokens\"`, etc.). */\n stopReason: string;\n /** Token usage for the full agent loop. */\n usage: { inputTokens: number; outputTokens: number };\n}\n\n/** A Promise with an `abort()` method for cancelling the stream. */\nexport type AbortablePromise<T> = Promise<T> & {\n /** Cancel the in-flight stream. The promise rejects with `AbortError`. */\n abort: () => void;\n};\n\n// ---------------------------------------------------------------------------\n// Client interface\n// ---------------------------------------------------------------------------\n\n/** Agent chat client returned by {@link createAgentChatClient}. */\nexport interface AgentChatClient {\n /** Create a new conversation thread. */\n createThread(): Promise<ThreadSummary>;\n\n /** List threads with cursor-based pagination (50 per page). */\n listThreads(cursor?: string): Promise<ThreadListPage>;\n\n /** Get a thread with its full message history. */\n getThread(threadId: string): Promise<Thread>;\n\n /** Update a thread's title. */\n updateThread(threadId: string, title: string): Promise<void>;\n\n /** Delete a thread (soft delete). */\n deleteThread(threadId: string): Promise<void>;\n\n /**\n * Send a message and stream the agent's response.\n *\n * Returns an {@link AbortablePromise} that resolves with\n * `{ stopReason, usage }` when the stream completes. Call `.abort()`\n * on the returned promise to cancel mid-stream.\n *\n * @param options.attachments - MindStudio CDN URLs to attach.\n * Images (`i.mscdn.ai`) are sent as vision input.\n * Documents (`f.mscdn.ai`) have text extracted into context.\n * Upload files first via `platform.uploadFile()`.\n */\n sendMessage(\n threadId: string,\n content: string,\n callbacks?: SendMessageCallbacks,\n options?: SendMessageOptions,\n ): AbortablePromise<SendMessageResult>;\n}\n\n// ---------------------------------------------------------------------------\n// Private helpers\n// ---------------------------------------------------------------------------\n\nconst AGENT_BASE = '/_/agent';\n\nasync function request<T>(\n path: string,\n method: string,\n body?: unknown,\n): Promise<T> {\n const config = getConfig();\n const headers: Record<string, string> = {\n Authorization: `Bearer ${config.token}`,\n };\n\n if (body !== undefined) {\n headers['Content-Type'] = 'application/json';\n }\n\n const res = await fetch(`${AGENT_BASE}${path}`, {\n method,\n headers,\n ...(body !== undefined && { body: JSON.stringify(body) }),\n });\n\n if (!res.ok) {\n let errorMessage = `Agent chat request failed: ${res.status} ${res.statusText}`;\n let errorCode = 'agent_chat_error';\n try {\n const err = (await res.json()) as { error?: string; code?: string };\n if (err.error) {\n errorMessage = err.error;\n }\n if (err.code) {\n errorCode = err.code;\n }\n } catch {\n // Response wasn't JSON — use the default message\n }\n throw new MindStudioInterfaceError(errorMessage, errorCode, res.status);\n }\n\n return (await res.json()) as T;\n}\n\nfunction dispatchEvent(\n event: AgentChatEvent,\n callbacks: SendMessageCallbacks,\n): void {\n // Catch-all fires for every event\n callbacks.onEvent?.(event);\n\n // Named callbacks\n switch (event.type) {\n case 'text':\n callbacks.onText?.(event.text);\n break;\n case 'thinking':\n callbacks.onThinking?.(event.text);\n break;\n case 'thinking_complete':\n callbacks.onThinkingComplete?.(event.thinking, event.signature);\n break;\n case 'tool_call_start':\n callbacks.onToolCallStart?.(event.id, event.name);\n break;\n case 'tool_call_result':\n callbacks.onToolCallResult?.(event.id, event.output);\n break;\n case 'error':\n callbacks.onError?.(event.error);\n break;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Create an agent chat client for thread-based conversations.\n *\n * The client is stateless — each method is an independent HTTP request.\n * Your application layer owns thread state, message arrays, and UI updates.\n *\n * @returns An {@link AgentChatClient} with methods for thread CRUD and\n * message streaming.\n *\n * @example\n * ```ts\n * import { createAgentChatClient } from '@mindstudio-ai/interface';\n *\n * const chat = createAgentChatClient();\n *\n * const thread = await chat.createThread();\n *\n * const response = chat.sendMessage(thread.id, 'Hello!', {\n * onText: (delta) => setAssistantMessage((prev) => prev + delta),\n * onToolCallStart: (id, name) => showToolSpinner(name),\n * onToolCallResult: (id, output) => showToolResult(output),\n * });\n *\n * const { stopReason, usage } = await response;\n * ```\n */\nexport function createAgentChatClient(): AgentChatClient {\n return {\n createThread() {\n return request<ThreadSummary>('/threads', 'POST');\n },\n\n listThreads(cursor?: string) {\n const query = cursor ? `?cursor=${encodeURIComponent(cursor)}` : '';\n return request<ThreadListPage>(`/threads${query}`, 'GET');\n },\n\n getThread(threadId: string) {\n return request<Thread>(`/threads/${threadId}`, 'GET');\n },\n\n async updateThread(threadId: string, title: string) {\n await request(`/threads/${threadId}`, 'PATCH', { title });\n },\n\n async deleteThread(threadId: string) {\n await request(`/threads/${threadId}`, 'DELETE');\n },\n\n sendMessage(\n threadId: string,\n content: string,\n callbacks?: SendMessageCallbacks,\n options?: SendMessageOptions,\n ): AbortablePromise<SendMessageResult> {\n const controller = new AbortController();\n const cb = callbacks ?? {};\n\n // Wire caller's signal to our internal controller\n if (cb.signal) {\n if (cb.signal.aborted) {\n controller.abort();\n } else {\n cb.signal.addEventListener('abort', () => controller.abort(), {\n once: true,\n });\n }\n }\n\n const promise = (async (): Promise<SendMessageResult> => {\n const config = getConfig();\n const url = `${AGENT_BASE}/threads/${threadId}/messages`;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${config.token}`,\n },\n body: JSON.stringify({\n content,\n ...(options?.attachments?.length && {\n attachments: options.attachments,\n }),\n }),\n signal: controller.signal,\n });\n\n if (!res.ok) {\n let errorMessage = `Send message failed: ${res.status} ${res.statusText}`;\n let errorCode = 'agent_chat_error';\n try {\n const err = (await res.json()) as {\n error?: string;\n code?: string;\n };\n if (err.error) {\n errorMessage = err.error;\n }\n if (err.code) {\n errorCode = err.code;\n }\n } catch {\n // Response wasn't JSON — use the default message\n }\n throw new MindStudioInterfaceError(\n errorMessage,\n errorCode,\n res.status,\n );\n }\n\n const reader = res.body!.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n let result: SendMessageResult | undefined;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n\n for (const line of lines) {\n if (!line.startsWith('data: ')) {\n continue;\n }\n const json = line.slice(6);\n try {\n const event = JSON.parse(json) as AgentChatEvent;\n\n if (event.type === 'done') {\n result = {\n stopReason: event.stopReason,\n usage: event.usage,\n };\n }\n\n dispatchEvent(event, cb);\n } catch {\n // Skip malformed SSE lines\n }\n }\n }\n\n if (!result) {\n throw new MindStudioInterfaceError(\n 'Stream ended without a done event',\n 'stream_incomplete',\n );\n }\n\n return result;\n })();\n\n const abortable = promise as AbortablePromise<SendMessageResult>;\n abortable.abort = () => controller.abort();\n return abortable;\n },\n };\n}\n","/**\n * Platform actions — file uploads via presigned S3 POST.\n *\n * Uses the session token from `window.__MINDSTUDIO__` to request a\n * presigned upload URL from the platform, then uploads directly to S3.\n * Returns the public CDN URL.\n *\n * @example\n * ```ts\n * import { platform } from '@mindstudio-ai/interface';\n *\n * const file = document.querySelector('input[type=file]').files[0];\n * const url = await platform.uploadFile(file);\n *\n * // With progress and abort\n * const controller = new AbortController();\n * const url = await platform.uploadFile(file, {\n * onProgress: (fraction) => console.log(`${Math.round(fraction * 100)}%`),\n * signal: controller.signal,\n * });\n * ```\n */\n\nimport { getConfig } from './config.js';\nimport { MindStudioInterfaceError } from './errors.js';\n\n/**\n * Options for `platform.uploadFile()`.\n */\nexport interface UploadFileOptions {\n /** Called with upload progress as a fraction from 0 to 1. */\n onProgress?: (fraction: number) => void;\n\n /** AbortSignal to cancel the upload. */\n signal?: AbortSignal;\n}\n\n/**\n * The platform namespace — file upload actions.\n */\nexport const platform = {\n /**\n * Upload a file to the MindStudio CDN.\n *\n * Requests a presigned upload URL from the platform, then uploads\n * the file directly to S3. Returns the public CDN URL.\n *\n * @param file - The File to upload\n * @param options - Optional progress callback and abort signal\n * @returns CDN URL of the uploaded file\n *\n * @example\n * ```ts\n * const url = await platform.uploadFile(file);\n *\n * // With progress\n * const url = await platform.uploadFile(file, {\n * onProgress: (f) => setProgress(f),\n * });\n *\n * // With abort\n * const controller = new AbortController();\n * const url = await platform.uploadFile(file, {\n * signal: controller.signal,\n * });\n * // controller.abort() to cancel\n * ```\n */\n async uploadFile(file: File, options?: UploadFileOptions): Promise<string> {\n const config = getConfig();\n const { onProgress, signal } = options ?? {};\n\n // Check if already aborted\n signal?.throwIfAborted();\n\n // Step 1: Get presigned upload URL\n const presignUrl = '/_/generate-upload-request';\n const presignRes = await fetch(presignUrl, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${config.token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n filename: file.name,\n contentType: file.type || 'application/octet-stream',\n }),\n signal,\n });\n\n if (!presignRes.ok) {\n throw new MindStudioInterfaceError(\n `Upload presign failed: ${presignRes.status} ${presignRes.statusText}`,\n 'upload_error',\n presignRes.status,\n );\n }\n\n const { uploadUrl, uploadFields, publicUrl } =\n (await presignRes.json()) as {\n uploadUrl: string;\n uploadFields: Record<string, string>;\n publicUrl: string;\n };\n\n // Step 2: Upload directly to S3\n const formData = new FormData();\n for (const [key, value] of Object.entries(uploadFields)) {\n formData.append(key, value);\n }\n formData.append('file', file); // must be last\n\n // Use XHR for upload progress (fetch doesn't support it)\n if (onProgress) {\n await xhrUpload(uploadUrl, formData, onProgress, signal);\n return publicUrl;\n }\n\n const uploadRes = await fetch(uploadUrl, {\n method: 'POST',\n body: formData,\n signal,\n });\n\n if (!uploadRes.ok) {\n throw new MindStudioInterfaceError(\n `File upload failed: ${uploadRes.status} ${uploadRes.statusText}`,\n 'upload_error',\n uploadRes.status,\n );\n }\n\n return publicUrl;\n },\n};\n\n/**\n * Upload via XMLHttpRequest to get progress events.\n * Falls back from fetch because fetch upload streams don't support progress.\n */\nfunction xhrUpload(\n url: string,\n formData: FormData,\n onProgress: (fraction: number) => void,\n signal?: AbortSignal,\n): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n\n xhr.upload.addEventListener('progress', (e) => {\n if (e.lengthComputable) {\n onProgress(e.loaded / e.total);\n }\n });\n\n xhr.addEventListener('load', () => {\n if (xhr.status >= 200 && xhr.status < 300) {\n onProgress(1);\n resolve();\n } else {\n reject(\n new MindStudioInterfaceError(\n `File upload failed: ${xhr.status} ${xhr.statusText}`,\n 'upload_error',\n xhr.status,\n ),\n );\n }\n });\n\n xhr.addEventListener('error', () => {\n reject(\n new MindStudioInterfaceError(\n 'File upload failed: network error',\n 'upload_error',\n ),\n );\n });\n\n xhr.addEventListener('abort', () => {\n reject(new DOMException('Upload aborted', 'AbortError'));\n });\n\n // Wire up abort signal\n if (signal) {\n if (signal.aborted) {\n reject(new DOMException('Upload aborted', 'AbortError'));\n return;\n }\n signal.addEventListener('abort', () => xhr.abort(), { once: true });\n }\n\n xhr.open('POST', url);\n xhr.send(formData);\n });\n}\n","/**\n * Phone number utilities for auth flows.\n *\n * Provides country data, E.164 conversion, formatting, and validation.\n * No external dependencies — designed for login/signup UIs that need\n * a country code picker and phone number formatting.\n */\n\n// ---------------------------------------------------------------------------\n// Country data\n// ---------------------------------------------------------------------------\n\n/** A country with its dial code and flag emoji. */\nexport interface Country {\n /** ISO 3166-1 alpha-2 code (e.g. \"US\"). */\n code: string;\n /** International dial code with + prefix (e.g. \"+1\"). */\n dialCode: string;\n /** Country name in English. */\n name: string;\n /** Flag emoji. */\n flag: string;\n}\n\n/** All countries with dial codes, sorted alphabetically by name. */\nexport const countries: readonly Country[] = [\n { code: 'AF', dialCode: '+93', name: 'Afghanistan', flag: '🇦🇫' },\n { code: 'AL', dialCode: '+355', name: 'Albania', flag: '🇦🇱' },\n { code: 'DZ', dialCode: '+213', name: 'Algeria', flag: '🇩🇿' },\n { code: 'AD', dialCode: '+376', name: 'Andorra', flag: '🇦🇩' },\n { code: 'AO', dialCode: '+244', name: 'Angola', flag: '🇦🇴' },\n { code: 'AG', dialCode: '+1', name: 'Antigua and Barbuda', flag: '🇦🇬' },\n { code: 'AR', dialCode: '+54', name: 'Argentina', flag: '🇦🇷' },\n { code: 'AM', dialCode: '+374', name: 'Armenia', flag: '🇦🇲' },\n { code: 'AU', dialCode: '+61', name: 'Australia', flag: '🇦🇺' },\n { code: 'AT', dialCode: '+43', name: 'Austria', flag: '🇦🇹' },\n { code: 'AZ', dialCode: '+994', name: 'Azerbaijan', flag: '🇦🇿' },\n { code: 'BS', dialCode: '+1', name: 'Bahamas', flag: '🇧🇸' },\n { code: 'BH', dialCode: '+973', name: 'Bahrain', flag: '🇧🇭' },\n { code: 'BD', dialCode: '+880', name: 'Bangladesh', flag: '🇧🇩' },\n { code: 'BB', dialCode: '+1', name: 'Barbados', flag: '🇧🇧' },\n { code: 'BY', dialCode: '+375', name: 'Belarus', flag: '🇧🇾' },\n { code: 'BE', dialCode: '+32', name: 'Belgium', flag: '🇧🇪' },\n { code: 'BZ', dialCode: '+501', name: 'Belize', flag: '🇧🇿' },\n { code: 'BJ', dialCode: '+229', name: 'Benin', flag: '🇧🇯' },\n { code: 'BT', dialCode: '+975', name: 'Bhutan', flag: '🇧🇹' },\n { code: 'BO', dialCode: '+591', name: 'Bolivia', flag: '🇧🇴' },\n { code: 'BA', dialCode: '+387', name: 'Bosnia and Herzegovina', flag: '🇧🇦' },\n { code: 'BW', dialCode: '+267', name: 'Botswana', flag: '🇧🇼' },\n { code: 'BR', dialCode: '+55', name: 'Brazil', flag: '🇧🇷' },\n { code: 'BN', dialCode: '+673', name: 'Brunei', flag: '🇧🇳' },\n { code: 'BG', dialCode: '+359', name: 'Bulgaria', flag: '🇧🇬' },\n { code: 'BF', dialCode: '+226', name: 'Burkina Faso', flag: '🇧🇫' },\n { code: 'BI', dialCode: '+257', name: 'Burundi', flag: '🇧🇮' },\n { code: 'CV', dialCode: '+238', name: 'Cabo Verde', flag: '🇨🇻' },\n { code: 'KH', dialCode: '+855', name: 'Cambodia', flag: '🇰🇭' },\n { code: 'CM', dialCode: '+237', name: 'Cameroon', flag: '🇨🇲' },\n { code: 'CA', dialCode: '+1', name: 'Canada', flag: '🇨🇦' },\n {\n code: 'CF',\n dialCode: '+236',\n name: 'Central African Republic',\n flag: '🇨🇫',\n },\n { code: 'TD', dialCode: '+235', name: 'Chad', flag: '🇹🇩' },\n { code: 'CL', dialCode: '+56', name: 'Chile', flag: '🇨🇱' },\n { code: 'CN', dialCode: '+86', name: 'China', flag: '🇨🇳' },\n { code: 'CO', dialCode: '+57', name: 'Colombia', flag: '🇨🇴' },\n { code: 'KM', dialCode: '+269', name: 'Comoros', flag: '🇰🇲' },\n { code: 'CG', dialCode: '+242', name: 'Congo', flag: '🇨🇬' },\n { code: 'CD', dialCode: '+243', name: 'Congo (DRC)', flag: '🇨🇩' },\n { code: 'CR', dialCode: '+506', name: 'Costa Rica', flag: '🇨🇷' },\n { code: 'HR', dialCode: '+385', name: 'Croatia', flag: '🇭🇷' },\n { code: 'CU', dialCode: '+53', name: 'Cuba', flag: '🇨🇺' },\n { code: 'CY', dialCode: '+357', name: 'Cyprus', flag: '🇨🇾' },\n { code: 'CZ', dialCode: '+420', name: 'Czechia', flag: '🇨🇿' },\n { code: 'CI', dialCode: '+225', name: \"Cote d'Ivoire\", flag: '🇨🇮' },\n { code: 'DK', dialCode: '+45', name: 'Denmark', flag: '🇩🇰' },\n { code: 'DJ', dialCode: '+253', name: 'Djibouti', flag: '🇩🇯' },\n { code: 'DM', dialCode: '+1', name: 'Dominica', flag: '🇩🇲' },\n { code: 'DO', dialCode: '+1', name: 'Dominican Republic', flag: '🇩🇴' },\n { code: 'EC', dialCode: '+593', name: 'Ecuador', flag: '🇪🇨' },\n { code: 'EG', dialCode: '+20', name: 'Egypt', flag: '🇪🇬' },\n { code: 'SV', dialCode: '+503', name: 'El Salvador', flag: '🇸🇻' },\n { code: 'GQ', dialCode: '+240', name: 'Equatorial Guinea', flag: '🇬🇶' },\n { code: 'ER', dialCode: '+291', name: 'Eritrea', flag: '🇪🇷' },\n { code: 'EE', dialCode: '+372', name: 'Estonia', flag: '🇪🇪' },\n { code: 'SZ', dialCode: '+268', name: 'Eswatini', flag: '🇸🇿' },\n { code: 'ET', dialCode: '+251', name: 'Ethiopia', flag: '🇪🇹' },\n { code: 'FJ', dialCode: '+679', name: 'Fiji', flag: '🇫🇯' },\n { code: 'FI', dialCode: '+358', name: 'Finland', flag: '🇫🇮' },\n { code: 'FR', dialCode: '+33', name: 'France', flag: '🇫🇷' },\n { code: 'GA', dialCode: '+241', name: 'Gabon', flag: '🇬🇦' },\n { code: 'GM', dialCode: '+220', name: 'Gambia', flag: '🇬🇲' },\n { code: 'GE', dialCode: '+995', name: 'Georgia', flag: '🇬🇪' },\n { code: 'DE', dialCode: '+49', name: 'Germany', flag: '🇩🇪' },\n { code: 'GH', dialCode: '+233', name: 'Ghana', flag: '🇬🇭' },\n { code: 'GR', dialCode: '+30', name: 'Greece', flag: '🇬🇷' },\n { code: 'GD', dialCode: '+1', name: 'Grenada', flag: '🇬🇩' },\n { code: 'GT', dialCode: '+502', name: 'Guatemala', flag: '🇬🇹' },\n { code: 'GN', dialCode: '+224', name: 'Guinea', flag: '🇬🇳' },\n { code: 'GW', dialCode: '+245', name: 'Guinea-Bissau', flag: '🇬🇼' },\n { code: 'GY', dialCode: '+592', name: 'Guyana', flag: '🇬🇾' },\n { code: 'HT', dialCode: '+509', name: 'Haiti', flag: '🇭🇹' },\n { code: 'HN', dialCode: '+504', name: 'Honduras', flag: '🇭🇳' },\n { code: 'HK', dialCode: '+852', name: 'Hong Kong', flag: '🇭🇰' },\n { code: 'HU', dialCode: '+36', name: 'Hungary', flag: '🇭🇺' },\n { code: 'IS', dialCode: '+354', name: 'Iceland', flag: '🇮🇸' },\n { code: 'IN', dialCode: '+91', name: 'India', flag: '🇮🇳' },\n { code: 'ID', dialCode: '+62', name: 'Indonesia', flag: '🇮🇩' },\n { code: 'IR', dialCode: '+98', name: 'Iran', flag: '🇮🇷' },\n { code: 'IQ', dialCode: '+964', name: 'Iraq', flag: '🇮🇶' },\n { code: 'IE', dialCode: '+353', name: 'Ireland', flag: '🇮🇪' },\n { code: 'IL', dialCode: '+972', name: 'Israel', flag: '🇮🇱' },\n { code: 'IT', dialCode: '+39', name: 'Italy', flag: '🇮🇹' },\n { code: 'JM', dialCode: '+1', name: 'Jamaica', flag: '🇯🇲' },\n { code: 'JP', dialCode: '+81', name: 'Japan', flag: '🇯🇵' },\n { code: 'JO', dialCode: '+962', name: 'Jordan', flag: '🇯🇴' },\n { code: 'KZ', dialCode: '+7', name: 'Kazakhstan', flag: '🇰🇿' },\n { code: 'KE', dialCode: '+254', name: 'Kenya', flag: '🇰🇪' },\n { code: 'KI', dialCode: '+686', name: 'Kiribati', flag: '🇰🇮' },\n { code: 'KW', dialCode: '+965', name: 'Kuwait', flag: '🇰🇼' },\n { code: 'KG', dialCode: '+996', name: 'Kyrgyzstan', flag: '🇰🇬' },\n { code: 'LA', dialCode: '+856', name: 'Laos', flag: '🇱🇦' },\n { code: 'LV', dialCode: '+371', name: 'Latvia', flag: '🇱🇻' },\n { code: 'LB', dialCode: '+961', name: 'Lebanon', flag: '🇱🇧' },\n { code: 'LS', dialCode: '+266', name: 'Lesotho', flag: '🇱🇸' },\n { code: 'LR', dialCode: '+231', name: 'Liberia', flag: '🇱🇷' },\n { code: 'LY', dialCode: '+218', name: 'Libya', flag: '🇱🇾' },\n { code: 'LI', dialCode: '+423', name: 'Liechtenstein', flag: '🇱🇮' },\n { code: 'LT', dialCode: '+370', name: 'Lithuania', flag: '🇱🇹' },\n { code: 'LU', dialCode: '+352', name: 'Luxembourg', flag: '🇱🇺' },\n { code: 'MO', dialCode: '+853', name: 'Macao', flag: '🇲🇴' },\n { code: 'MG', dialCode: '+261', name: 'Madagascar', flag: '🇲🇬' },\n { code: 'MW', dialCode: '+265', name: 'Malawi', flag: '🇲🇼' },\n { code: 'MY', dialCode: '+60', name: 'Malaysia', flag: '🇲🇾' },\n { code: 'MV', dialCode: '+960', name: 'Maldives', flag: '🇲🇻' },\n { code: 'ML', dialCode: '+223', name: 'Mali', flag: '🇲🇱' },\n { code: 'MT', dialCode: '+356', name: 'Malta', flag: '🇲🇹' },\n { code: 'MH', dialCode: '+692', name: 'Marshall Islands', flag: '🇲🇭' },\n { code: 'MR', dialCode: '+222', name: 'Mauritania', flag: '🇲🇷' },\n { code: 'MU', dialCode: '+230', name: 'Mauritius', flag: '🇲🇺' },\n { code: 'MX', dialCode: '+52', name: 'Mexico', flag: '🇲🇽' },\n { code: 'FM', dialCode: '+691', name: 'Micronesia', flag: '🇫🇲' },\n { code: 'MD', dialCode: '+373', name: 'Moldova', flag: '🇲🇩' },\n { code: 'MC', dialCode: '+377', name: 'Monaco', flag: '🇲🇨' },\n { code: 'MN', dialCode: '+976', name: 'Mongolia', flag: '🇲🇳' },\n { code: 'ME', dialCode: '+382', name: 'Montenegro', flag: '🇲🇪' },\n { code: 'MA', dialCode: '+212', name: 'Morocco', flag: '🇲🇦' },\n { code: 'MZ', dialCode: '+258', name: 'Mozambique', flag: '🇲🇿' },\n { code: 'MM', dialCode: '+95', name: 'Myanmar', flag: '🇲🇲' },\n { code: 'NA', dialCode: '+264', name: 'Namibia', flag: '🇳🇦' },\n { code: 'NR', dialCode: '+674', name: 'Nauru', flag: '🇳🇷' },\n { code: 'NP', dialCode: '+977', name: 'Nepal', flag: '🇳🇵' },\n { code: 'NL', dialCode: '+31', name: 'Netherlands', flag: '🇳🇱' },\n { code: 'NZ', dialCode: '+64', name: 'New Zealand', flag: '🇳🇿' },\n { code: 'NI', dialCode: '+505', name: 'Nicaragua', flag: '🇳🇮' },\n { code: 'NE', dialCode: '+227', name: 'Niger', flag: '🇳🇪' },\n { code: 'NG', dialCode: '+234', name: 'Nigeria', flag: '🇳🇬' },\n { code: 'KP', dialCode: '+850', name: 'North Korea', flag: '🇰🇵' },\n { code: 'MK', dialCode: '+389', name: 'North Macedonia', flag: '🇲🇰' },\n { code: 'NO', dialCode: '+47', name: 'Norway', flag: '🇳🇴' },\n { code: 'OM', dialCode: '+968', name: 'Oman', flag: '🇴🇲' },\n { code: 'PK', dialCode: '+92', name: 'Pakistan', flag: '🇵🇰' },\n { code: 'PW', dialCode: '+680', name: 'Palau', flag: '🇵🇼' },\n { code: 'PS', dialCode: '+970', name: 'Palestine', flag: '🇵🇸' },\n { code: 'PA', dialCode: '+507', name: 'Panama', flag: '🇵🇦' },\n { code: 'PG', dialCode: '+675', name: 'Papua New Guinea', flag: '🇵🇬' },\n { code: 'PY', dialCode: '+595', name: 'Paraguay', flag: '🇵🇾' },\n { code: 'PE', dialCode: '+51', name: 'Peru', flag: '🇵🇪' },\n { code: 'PH', dialCode: '+63', name: 'Philippines', flag: '🇵🇭' },\n { code: 'PL', dialCode: '+48', name: 'Poland', flag: '🇵🇱' },\n { code: 'PT', dialCode: '+351', name: 'Portugal', flag: '🇵🇹' },\n { code: 'PR', dialCode: '+1', name: 'Puerto Rico', flag: '🇵🇷' },\n { code: 'QA', dialCode: '+974', name: 'Qatar', flag: '🇶🇦' },\n { code: 'RO', dialCode: '+40', name: 'Romania', flag: '🇷🇴' },\n { code: 'RU', dialCode: '+7', name: 'Russia', flag: '🇷🇺' },\n { code: 'RW', dialCode: '+250', name: 'Rwanda', flag: '🇷🇼' },\n { code: 'KN', dialCode: '+1', name: 'Saint Kitts and Nevis', flag: '🇰🇳' },\n { code: 'LC', dialCode: '+1', name: 'Saint Lucia', flag: '🇱🇨' },\n {\n code: 'VC',\n dialCode: '+1',\n name: 'Saint Vincent and the Grenadines',\n flag: '🇻🇨',\n },\n { code: 'WS', dialCode: '+685', name: 'Samoa', flag: '🇼🇸' },\n { code: 'SM', dialCode: '+378', name: 'San Marino', flag: '🇸🇲' },\n { code: 'ST', dialCode: '+239', name: 'Sao Tome and Principe', flag: '🇸🇹' },\n { code: 'SA', dialCode: '+966', name: 'Saudi Arabia', flag: '🇸🇦' },\n { code: 'SN', dialCode: '+221', name: 'Senegal', flag: '🇸🇳' },\n { code: 'RS', dialCode: '+381', name: 'Serbia', flag: '🇷🇸' },\n { code: 'SC', dialCode: '+248', name: 'Seychelles', flag: '🇸🇨' },\n { code: 'SL', dialCode: '+232', name: 'Sierra Leone', flag: '🇸🇱' },\n { code: 'SG', dialCode: '+65', name: 'Singapore', flag: '🇸🇬' },\n { code: 'SK', dialCode: '+421', name: 'Slovakia', flag: '🇸🇰' },\n { code: 'SI', dialCode: '+386', name: 'Slovenia', flag: '🇸🇮' },\n { code: 'SB', dialCode: '+677', name: 'Solomon Islands', flag: '🇸🇧' },\n { code: 'SO', dialCode: '+252', name: 'Somalia', flag: '🇸🇴' },\n { code: 'ZA', dialCode: '+27', name: 'South Africa', flag: '🇿🇦' },\n { code: 'KR', dialCode: '+82', name: 'South Korea', flag: '🇰🇷' },\n { code: 'SS', dialCode: '+211', name: 'South Sudan', flag: '🇸🇸' },\n { code: 'ES', dialCode: '+34', name: 'Spain', flag: '🇪🇸' },\n { code: 'LK', dialCode: '+94', name: 'Sri Lanka', flag: '🇱🇰' },\n { code: 'SD', dialCode: '+249', name: 'Sudan', flag: '🇸🇩' },\n { code: 'SR', dialCode: '+597', name: 'Suriname', flag: '🇸🇷' },\n { code: 'SE', dialCode: '+46', name: 'Sweden', flag: '🇸🇪' },\n { code: 'CH', dialCode: '+41', name: 'Switzerland', flag: '🇨🇭' },\n { code: 'SY', dialCode: '+963', name: 'Syria', flag: '🇸🇾' },\n { code: 'TW', dialCode: '+886', name: 'Taiwan', flag: '🇹🇼' },\n { code: 'TJ', dialCode: '+992', name: 'Tajikistan', flag: '🇹🇯' },\n { code: 'TZ', dialCode: '+255', name: 'Tanzania', flag: '🇹🇿' },\n { code: 'TH', dialCode: '+66', name: 'Thailand', flag: '🇹🇭' },\n { code: 'TL', dialCode: '+670', name: 'Timor-Leste', flag: '🇹🇱' },\n { code: 'TG', dialCode: '+228', name: 'Togo', flag: '🇹🇬' },\n { code: 'TO', dialCode: '+676', name: 'Tonga', flag: '🇹🇴' },\n { code: 'TT', dialCode: '+1', name: 'Trinidad and Tobago', flag: '🇹🇹' },\n { code: 'TN', dialCode: '+216', name: 'Tunisia', flag: '🇹🇳' },\n { code: 'TR', dialCode: '+90', name: 'Turkey', flag: '🇹🇷' },\n { code: 'TM', dialCode: '+993', name: 'Turkmenistan', flag: '🇹🇲' },\n { code: 'TV', dialCode: '+688', name: 'Tuvalu', flag: '🇹🇻' },\n { code: 'UG', dialCode: '+256', name: 'Uganda', flag: '🇺🇬' },\n { code: 'UA', dialCode: '+380', name: 'Ukraine', flag: '🇺🇦' },\n { code: 'AE', dialCode: '+971', name: 'United Arab Emirates', flag: '🇦🇪' },\n { code: 'GB', dialCode: '+44', name: 'United Kingdom', flag: '🇬🇧' },\n { code: 'US', dialCode: '+1', name: 'United States', flag: '🇺🇸' },\n { code: 'UY', dialCode: '+598', name: 'Uruguay', flag: '🇺🇾' },\n { code: 'UZ', dialCode: '+998', name: 'Uzbekistan', flag: '🇺🇿' },\n { code: 'VU', dialCode: '+678', name: 'Vanuatu', flag: '🇻🇺' },\n { code: 'VA', dialCode: '+39', name: 'Vatican City', flag: '🇻🇦' },\n { code: 'VE', dialCode: '+58', name: 'Venezuela', flag: '🇻🇪' },\n { code: 'VN', dialCode: '+84', name: 'Vietnam', flag: '🇻🇳' },\n { code: 'YE', dialCode: '+967', name: 'Yemen', flag: '🇾🇪' },\n { code: 'ZM', dialCode: '+260', name: 'Zambia', flag: '🇿🇲' },\n { code: 'ZW', dialCode: '+263', name: 'Zimbabwe', flag: '🇿🇼' },\n];\n\n// ---------------------------------------------------------------------------\n// Country lookup helpers\n// ---------------------------------------------------------------------------\n\nconst byCode = new Map(countries.map((c) => [c.code, c]));\n\n/** Common IANA timezone → country code mapping. */\nconst timezoneToCountry: Record<string, string> = {\n 'America/New_York': 'US',\n 'America/Chicago': 'US',\n 'America/Denver': 'US',\n 'America/Los_Angeles': 'US',\n 'America/Anchorage': 'US',\n 'Pacific/Honolulu': 'US',\n 'America/Phoenix': 'US',\n 'America/Indiana/Indianapolis': 'US',\n 'America/Toronto': 'CA',\n 'America/Vancouver': 'CA',\n 'America/Edmonton': 'CA',\n 'America/Winnipeg': 'CA',\n 'America/Halifax': 'CA',\n 'America/St_Johns': 'CA',\n 'Europe/London': 'GB',\n 'Europe/Dublin': 'IE',\n 'Europe/Paris': 'FR',\n 'Europe/Berlin': 'DE',\n 'Europe/Madrid': 'ES',\n 'Europe/Rome': 'IT',\n 'Europe/Amsterdam': 'NL',\n 'Europe/Brussels': 'BE',\n 'Europe/Zurich': 'CH',\n 'Europe/Vienna': 'AT',\n 'Europe/Stockholm': 'SE',\n 'Europe/Oslo': 'NO',\n 'Europe/Copenhagen': 'DK',\n 'Europe/Helsinki': 'FI',\n 'Europe/Warsaw': 'PL',\n 'Europe/Prague': 'CZ',\n 'Europe/Bucharest': 'RO',\n 'Europe/Budapest': 'HU',\n 'Europe/Athens': 'GR',\n 'Europe/Istanbul': 'TR',\n 'Europe/Moscow': 'RU',\n 'Europe/Kiev': 'UA',\n 'Europe/Lisbon': 'PT',\n 'Europe/Belgrade': 'RS',\n 'Europe/Zagreb': 'HR',\n 'Europe/Bratislava': 'SK',\n 'Europe/Ljubljana': 'SI',\n 'Europe/Tallinn': 'EE',\n 'Europe/Riga': 'LV',\n 'Europe/Vilnius': 'LT',\n 'Asia/Tokyo': 'JP',\n 'Asia/Seoul': 'KR',\n 'Asia/Shanghai': 'CN',\n 'Asia/Hong_Kong': 'HK',\n 'Asia/Taipei': 'TW',\n 'Asia/Singapore': 'SG',\n 'Asia/Kolkata': 'IN',\n 'Asia/Karachi': 'PK',\n 'Asia/Dhaka': 'BD',\n 'Asia/Bangkok': 'TH',\n 'Asia/Jakarta': 'ID',\n 'Asia/Manila': 'PH',\n 'Asia/Kuala_Lumpur': 'MY',\n 'Asia/Ho_Chi_Minh': 'VN',\n 'Asia/Riyadh': 'SA',\n 'Asia/Dubai': 'AE',\n 'Asia/Tehran': 'IR',\n 'Asia/Baghdad': 'IQ',\n 'Asia/Beirut': 'LB',\n 'Asia/Jerusalem': 'IL',\n 'Asia/Amman': 'JO',\n 'Asia/Almaty': 'KZ',\n 'Asia/Tashkent': 'UZ',\n 'Asia/Colombo': 'LK',\n 'Asia/Kathmandu': 'NP',\n 'Asia/Yangon': 'MM',\n 'Australia/Sydney': 'AU',\n 'Australia/Melbourne': 'AU',\n 'Australia/Brisbane': 'AU',\n 'Australia/Perth': 'AU',\n 'Australia/Adelaide': 'AU',\n 'Pacific/Auckland': 'NZ',\n 'Pacific/Fiji': 'FJ',\n 'Africa/Cairo': 'EG',\n 'Africa/Lagos': 'NG',\n 'Africa/Nairobi': 'KE',\n 'Africa/Johannesburg': 'ZA',\n 'Africa/Casablanca': 'MA',\n 'Africa/Accra': 'GH',\n 'Africa/Addis_Ababa': 'ET',\n 'Africa/Dar_es_Salaam': 'TZ',\n 'Africa/Kampala': 'UG',\n 'America/Mexico_City': 'MX',\n 'America/Bogota': 'CO',\n 'America/Lima': 'PE',\n 'America/Santiago': 'CL',\n 'America/Buenos_Aires': 'AR',\n 'America/Sao_Paulo': 'BR',\n 'America/Caracas': 'VE',\n 'America/Guatemala': 'GT',\n 'America/Havana': 'CU',\n 'America/Panama': 'PA',\n 'America/Jamaica': 'JM',\n};\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Detect the user's country from their timezone.\n * Falls back to `'US'` if the timezone can't be mapped.\n */\nexport function detectCountry(): string {\n try {\n const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;\n return timezoneToCountry[tz] ?? 'US';\n } catch {\n return 'US';\n }\n}\n\n/**\n * Format an E.164 phone number for display.\n *\n * US/CA numbers: `+1 (555) 123-4567`\n * Others: `+{dialCode} {rest}`\n */\nexport function format(e164: string): string {\n if (!e164.startsWith('+')) {\n return e164;\n }\n\n const digits = e164.slice(1);\n\n // US/CA: +1 followed by 10 digits\n if (digits.startsWith('1') && digits.length === 11) {\n const area = digits.slice(1, 4);\n const prefix = digits.slice(4, 7);\n const line = digits.slice(7);\n return `+1 (${area}) ${prefix}-${line}`;\n }\n\n // Find matching dial code (try longest match first)\n for (let len = 4; len >= 1; len--) {\n const candidate = '+' + digits.slice(0, len);\n const match = countries.find((c) => c.dialCode === candidate);\n if (match) {\n const rest = digits.slice(len);\n return `${match.dialCode} ${rest}`;\n }\n }\n\n return e164;\n}\n\n/**\n * Convert a national phone number to E.164 format.\n *\n * @param national - Phone number with or without formatting (e.g. \"(555) 123-4567\")\n * @param countryCode - ISO 3166-1 alpha-2 code (e.g. \"US\")\n * @returns E.164 formatted number (e.g. \"+15551234567\")\n */\nexport function toE164(national: string, countryCode: string): string {\n const digits = national.replace(/\\D/g, '');\n const country = byCode.get(countryCode);\n if (!country) {\n return '+' + digits;\n }\n const dialDigits = country.dialCode.slice(1); // remove +\n // If the number already starts with the dial code, don't double-add\n if (digits.startsWith(dialDigits)) {\n return '+' + digits;\n }\n return country.dialCode + digits;\n}\n\n/**\n * Check if a string is a valid E.164 phone number.\n * Must start with + followed by 7-15 digits.\n */\nexport function isValid(phone: string): boolean {\n return /^\\+[1-9]\\d{6,14}$/.test(phone);\n}\n","/**\n * Email validation helper for auth flows.\n */\n\n/** Basic email format check. Not RFC 5322 exhaustive. */\nexport function isValid(email: string): boolean {\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email);\n}\n","/**\n * Auth — app-managed authentication for MindStudio v2 apps.\n *\n * Provides verification code flows (email + SMS), session state\n * management, and phone/email validation helpers. The platform\n * handles code delivery, cookie management, and user storage —\n * developers build their own login UI using these methods.\n *\n * ## How it works\n *\n * ```\n * // 1. Send a verification code\n * const { verificationId } = await auth.sendEmailCode('user@example.com');\n *\n * // 2. User enters the code in your UI\n * const user = await auth.verifyEmailCode(verificationId, '123456');\n *\n * // 3. Session is now active — all SDK calls use the authenticated token\n * const result = await api.getDashboard(); // uses authenticated session\n * auth.getCurrentUser(); // { id, email, phone, roles, createdAt }\n * ```\n *\n * Verify, confirm, and logout methods update `window.__MINDSTUDIO__`\n * in-place so all downstream calls (method invocation, agent chat,\n * uploads) immediately use the new session. No page refresh needed.\n *\n * @example\n * ```tsx\n * import { auth } from '@mindstudio-ai/interface';\n *\n * function LoginPage() {\n * const [email, setEmail] = useState('');\n * const [verificationId, setVerificationId] = useState('');\n * const [code, setCode] = useState('');\n *\n * const handleSend = async () => {\n * const { verificationId } = await auth.sendEmailCode(email);\n * setVerificationId(verificationId);\n * };\n *\n * const handleVerify = async () => {\n * await auth.verifyEmailCode(verificationId, code);\n * // Session updated in-place — navigate to your app\n * window.location.href = '/dashboard';\n * };\n * }\n * ```\n */\n\nimport { getConfig, updateConfig } from './config.js';\nimport { MindStudioInterfaceError } from './errors.js';\nimport type { AppUser, AuthSessionBundle } from './types.js';\nimport * as phoneHelpers from './auth-phone.js';\nimport * as emailHelpers from './auth-email.js';\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nasync function authFetch<T>(\n path: string,\n method: 'GET' | 'POST',\n body?: Record<string, unknown>,\n): Promise<T> {\n const config = getConfig();\n const headers: Record<string, string> = {\n Authorization: `Bearer ${config.token}`,\n };\n\n if (body !== undefined) {\n headers['Content-Type'] = 'application/json';\n }\n\n const res = await fetch(path, {\n method,\n headers,\n ...(body !== undefined && { body: JSON.stringify(body) }),\n });\n\n if (!res.ok) {\n let message = `Auth request failed: ${res.status} ${res.statusText}`;\n let code = 'auth_error';\n try {\n const err = (await res.json()) as { error?: string; code?: string };\n if (err.error) {\n message = err.error;\n }\n if (err.code) {\n code = err.code;\n }\n } catch {\n // Response wasn't JSON\n }\n throw new MindStudioInterfaceError(message, code, res.status);\n }\n\n return (await res.json()) as T;\n}\n\nconst authListeners: Set<(user: AppUser | null) => void> = new Set();\n\nfunction applySession(bundle: AuthSessionBundle): void {\n updateConfig({\n token: bundle.token,\n user: bundle.user,\n methods: bundle.methods,\n });\n authListeners.forEach((cb) => cb(bundle.user));\n}\n\nfunction requireUser(bundle: AuthSessionBundle): AppUser {\n if (!bundle.user) {\n throw new MindStudioInterfaceError(\n 'Verification succeeded but no user was returned',\n 'auth_error',\n );\n }\n return bundle.user;\n}\n\nfunction updateUserAndNotify(update: Partial<AppUser>): void {\n const config = getConfig();\n if (config.user) {\n Object.assign(config.user, update);\n authListeners.forEach((cb) => cb(config.user));\n }\n}\n\n// ---------------------------------------------------------------------------\n// Auth interface\n// ---------------------------------------------------------------------------\n\n/**\n * The auth namespace — authentication flows, state, and helpers.\n *\n * Auth methods throw {@link MindStudioInterfaceError} on failure.\n * Common error codes:\n *\n * | Code | Status | Meaning |\n * |------|--------|---------|\n * | `rate_limited` | 429 | Too many code requests (max 5 per 15 min per identifier) |\n * | `invalid_code` | 400 | Wrong verification code |\n * | `verification_expired` | 400 | Code expired (10 min TTL) — request a new one |\n * | `max_attempts_exceeded` | 400 | Too many incorrect attempts (max 3) — request a new code |\n * | `not_authenticated` | 401 | Auth cookie missing (change/logout endpoints) |\n * | `invalid_session` | 401 | Auth cookie expired or invalid |\n */\nexport interface Auth {\n // -- State --\n\n /** The current authenticated user, or `null` if not authenticated. */\n readonly currentUser: AppUser | null;\n\n /** Get the current authenticated user, or `null` if not authenticated. */\n getCurrentUser(): AppUser | null;\n\n /** Whether the current session is authenticated. */\n isAuthenticated(): boolean;\n\n // -- Email code flow --\n\n /** Send a 6-digit verification code to an email address. */\n sendEmailCode(email: string): Promise<{ verificationId: string }>;\n\n /**\n * Verify an email code. On success, updates the session in-place\n * and returns the authenticated user.\n */\n verifyEmailCode(verificationId: string, code: string): Promise<AppUser>;\n\n // -- SMS code flow --\n\n /** Send a 6-digit verification code via SMS. Phone must be E.164. */\n sendSmsCode(phone: string): Promise<{ verificationId: string }>;\n\n /**\n * Verify an SMS code. On success, updates the session in-place\n * and returns the authenticated user.\n */\n verifySmsCode(verificationId: string, code: string): Promise<AppUser>;\n\n // -- Email/phone change (requires authentication) --\n\n /** Request an email change. Sends a code to the new email. */\n requestEmailChange(newEmail: string): Promise<void>;\n\n /** Confirm an email change with the verification code. */\n confirmEmailChange(newEmail: string, code: string): Promise<AppUser>;\n\n /** Request a phone change. Sends a code to the new phone (E.164). */\n requestPhoneChange(newPhone: string): Promise<void>;\n\n /** Confirm a phone change with the verification code. */\n confirmPhoneChange(newPhone: string, code: string): Promise<AppUser>;\n\n // -- Session --\n\n /** Log out. Clears the cookie and updates the session to unauthenticated. */\n logout(): Promise<void>;\n\n // -- API keys --\n\n /**\n * Generate an API key for the current user. Returns the full key\n * (shown once). The user's `apiKey` field updates to the masked\n * value and `onAuthStateChanged` fires.\n *\n * @throws `not_authenticated` (401) if no session\n * @throws `not_supported` (400) if api-key auth is not enabled\n */\n createApiKey(): Promise<{ key: string }>;\n\n /**\n * Revoke the current user's API key. The user's `apiKey` field\n * becomes `null` and `onAuthStateChanged` fires.\n *\n * @throws `not_authenticated` (401) if no session\n */\n revokeApiKey(): Promise<void>;\n\n /**\n * Subscribe to auth state changes. Fires immediately with the\n * current state, then again whenever verify, confirm, or logout\n * updates the session.\n *\n * @returns An unsubscribe function.\n *\n * @example\n * ```ts\n * // React hook\n * function useAuth() {\n * const [user, setUser] = useState<AppUser | null>(null);\n * useEffect(() => auth.onAuthStateChanged(setUser), []);\n * return user;\n * }\n * ```\n */\n onAuthStateChanged(callback: (user: AppUser | null) => void): () => void;\n\n // -- Helpers --\n\n /** Phone number utilities — countries, formatting, validation. */\n phone: {\n /** All countries with dial codes, sorted alphabetically. */\n countries: readonly phoneHelpers.Country[];\n /** Detect the user's country from their timezone. Falls back to `'US'`. */\n detectCountry(): string;\n /** Format an E.164 number for display (e.g. `+1 (555) 123-4567`). */\n format(e164: string): string;\n /** Convert a national number to E.164 (e.g. `('5551234567', 'US') → '+15551234567'`). */\n toE164(national: string, countryCode: string): string;\n /** Check if a string is a valid E.164 phone number. */\n isValid(phone: string): boolean;\n };\n\n /** Email validation. */\n email: {\n /** Basic email format check. */\n isValid(email: string): boolean;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Implementation\n// ---------------------------------------------------------------------------\n\nexport const auth: Auth = {\n // -- State --\n\n get currentUser() {\n return getConfig().user;\n },\n\n getCurrentUser() {\n return getConfig().user;\n },\n\n isAuthenticated() {\n return getConfig().user !== null;\n },\n\n // -- Email code flow --\n\n sendEmailCode(email: string) {\n return authFetch<{ verificationId: string }>('/_/auth/email/send', 'POST', {\n email,\n });\n },\n\n async verifyEmailCode(verificationId: string, code: string) {\n const bundle = await authFetch<AuthSessionBundle>(\n '/_/auth/email/verify',\n 'POST',\n { verificationId, code },\n );\n applySession(bundle);\n return requireUser(bundle);\n },\n\n // -- SMS code flow --\n\n sendSmsCode(phone: string) {\n return authFetch<{ verificationId: string }>('/_/auth/sms/send', 'POST', {\n phone,\n });\n },\n\n async verifySmsCode(verificationId: string, code: string) {\n const bundle = await authFetch<AuthSessionBundle>(\n '/_/auth/sms/verify',\n 'POST',\n { verificationId, code },\n );\n applySession(bundle);\n return requireUser(bundle);\n },\n\n // -- Email/phone change --\n\n async requestEmailChange(newEmail: string) {\n await authFetch('/_/auth/email/change', 'POST', { newEmail });\n },\n\n async confirmEmailChange(newEmail: string, code: string) {\n const bundle = await authFetch<AuthSessionBundle>(\n '/_/auth/email/change/confirm',\n 'POST',\n { newEmail, code },\n );\n applySession(bundle);\n return requireUser(bundle);\n },\n\n async requestPhoneChange(newPhone: string) {\n await authFetch('/_/auth/phone/change', 'POST', { newPhone });\n },\n\n async confirmPhoneChange(newPhone: string, code: string) {\n const bundle = await authFetch<AuthSessionBundle>(\n '/_/auth/phone/change/confirm',\n 'POST',\n { newPhone, code },\n );\n applySession(bundle);\n return requireUser(bundle);\n },\n\n // -- Session --\n\n async logout() {\n const bundle = await authFetch<AuthSessionBundle>(\n '/_/auth/logout',\n 'POST',\n {},\n );\n applySession(bundle);\n },\n\n async createApiKey() {\n const result = await authFetch<{ key: string; apiKey: string }>(\n '/_/auth/api-key/create',\n 'POST',\n {},\n );\n updateUserAndNotify({ apiKey: result.apiKey });\n return { key: result.key };\n },\n\n async revokeApiKey() {\n await authFetch('/_/auth/api-key/revoke', 'POST', {});\n updateUserAndNotify({ apiKey: null });\n },\n\n onAuthStateChanged(callback: (user: AppUser | null) => void) {\n authListeners.add(callback);\n callback(getConfig().user);\n return () => {\n authListeners.delete(callback);\n };\n },\n\n // -- Helpers --\n\n phone: {\n countries: phoneHelpers.countries,\n detectCountry: phoneHelpers.detectCountry,\n format: phoneHelpers.format,\n toE164: phoneHelpers.toE164,\n isValid: phoneHelpers.isValid,\n },\n\n email: {\n isValid: emailHelpers.isValid,\n },\n};\n"],"mappings":"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","names":["MindStudioInterfaceError","message","code","status","_config","getConfig","raw","MindStudioInterfaceError","missing","k","updateConfig","updates","config","createClient","_","methodName","input","options","config","getConfig","methodId","MindStudioInterfaceError","url","wantsStream","res","errorMessage","errorCode","body","reader","decoder","buffer","finalOutput","done","value","lines","line","json","event","AGENT_BASE","request","path","method","body","headers","getConfig","res","errorMessage","errorCode","err","MindStudioInterfaceError","dispatchEvent","event","callbacks","createAgentChatClient","cursor","query","threadId","title","content","options","controller","cb","abortable","config","url","reader","decoder","buffer","result","done","value","lines","line","json","platform","file","options","config","getConfig","onProgress","signal","presignRes","MindStudioInterfaceError","uploadUrl","uploadFields","publicUrl","formData","key","value","xhrUpload","uploadRes","url","resolve","reject","xhr","e","countries","byCode","c","timezoneToCountry","detectCountry","tz","format","e164","digits","area","prefix","line","len","candidate","match","rest","toE164","national","countryCode","country","dialDigits","isValid","phone","isValid","email","authFetch","path","method","body","headers","getConfig","res","message","code","err","MindStudioInterfaceError","authListeners","applySession","bundle","updateConfig","cb","requireUser","updateUserAndNotify","update","config","auth","email","verificationId","phone","newEmail","newPhone","result","callback","countries","detectCountry","format","toE164","isValid"]}
|