@pagelines/sdk 1.0.470 → 1.0.471

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/dist/api.d.ts CHANGED
@@ -1,5 +1,10 @@
1
1
  import { Hono } from 'hono';
2
2
  import { hc } from 'hono/client';
3
+ export interface RefreshFetchHooks {
4
+ getDeviceId: () => string | null;
5
+ onAccessTokenRefreshed: (token: string) => void;
6
+ onTerminalFailure: () => void;
7
+ }
3
8
  export interface ApiClientSettings {
4
9
  isDev: boolean;
5
10
  apiBase?: string;
@@ -25,4 +30,4 @@ export declare function resolveApiBase(apiBase?: string, isDev?: boolean): strin
25
30
  * const response = await client.api.auth['check-email'].$post({ json: { email } })
26
31
  * ```
27
32
  */
28
- export declare function createApiClient<TAppType extends Hono = any>(settings: ApiClientSettings, responseHandler?: (response: any) => void): ReturnType<typeof hc<TAppType>>;
33
+ export declare function createApiClient<TAppType extends Hono = any>(settings: ApiClientSettings, responseHandler?: (response: any) => void, refreshHooks?: RefreshFetchHooks): ReturnType<typeof hc<TAppType>>;
@@ -496,6 +496,7 @@ export declare class PageLinesSDK extends SettingsObject<PageLinesSDKSettings> {
496
496
  }[] | undefined;
497
497
  } | undefined>;
498
498
  token: import('vue').Ref<string | null, string | null>;
499
+ deviceId: import('vue').Ref<string | null, string | null>;
499
500
  loading: import('vue').Ref<boolean, boolean>;
500
501
  error: import('vue').Ref<string | null, string | null>;
501
502
  apiBase: string | undefined;
@@ -654,6 +655,8 @@ export declare class PageLinesSDK extends SettingsObject<PageLinesSDKSettings> {
654
655
  readonly user: UserClient;
655
656
  constructor(settings?: PageLinesSDKSettings);
656
657
  processApiResponse(response: ApiResponse<any>): void;
658
+ private authRefs;
659
+ private persistAuth;
657
660
  clearSession(): void;
658
661
  clear(): void;
659
662
  sendCode(email: string): Promise<void>;
package/dist/sdkClient.js CHANGED
@@ -1,70 +1,79 @@
1
- var q = Object.defineProperty;
2
- var X = (n, e, t) => e in n ? q(n, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[e] = t;
3
- var l = (n, e) => q(n, "name", { value: e, configurable: !0 });
4
- var a = (n, e, t) => X(n, typeof e != "symbol" ? e + "" : e, t);
5
- import { APP_PORT as Y, APP_PROD_URL as Z, cookieUtil as x, createLogger as ee, objectId as $, SettingsObject as te } from "@pagelines/core";
6
- import { watch as J, ref as k, computed as K } from "vue";
7
- import { hc as re } from "hono/client";
8
- function g(n, e) {
9
- return n || (e ? `http://localhost:${Y}` : Z);
1
+ var Q = Object.defineProperty;
2
+ var Y = (c, e, t) => e in c ? Q(c, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : c[e] = t;
3
+ var l = (c, e) => Q(c, "name", { value: e, configurable: !0 });
4
+ var i = (c, e, t) => Y(c, typeof e != "symbol" ? e + "" : e, t);
5
+ import { APP_PORT as Z, APP_PROD_URL as ee, createRefreshingFetch as te, cookieUtil as x, createLogger as re, objectId as B, SettingsObject as oe } from "@pagelines/core";
6
+ import { watch as $, ref as k, computed as V } from "vue";
7
+ import { hc as se } from "hono/client";
8
+ function f(c, e) {
9
+ return c || (e ? `http://localhost:${Z}` : ee);
10
10
  }
11
- l(g, "resolveApiBase");
12
- function oe(n, e) {
13
- const t = g(n.apiBase, n.isDev);
14
- return re(t, {
15
- fetch: /* @__PURE__ */ l(async (o, s) => {
16
- const i = x.getAuthToken(), h = await fetch(o, {
17
- ...s,
11
+ l(f, "resolveApiBase");
12
+ function ie(c, e, t) {
13
+ const r = f(c.apiBase, c.isDev), o = t ? te({
14
+ fetch: globalThis.fetch.bind(globalThis),
15
+ getDeviceId: t.getDeviceId,
16
+ refreshUrl: `${r}/api/auth/refresh`,
17
+ onAccessTokenRefreshed: t.onAccessTokenRefreshed,
18
+ onTerminalFailure: t.onTerminalFailure
19
+ }) : globalThis.fetch.bind(globalThis);
20
+ return se(r, {
21
+ fetch: /* @__PURE__ */ l(async (n, u) => {
22
+ const a = x.getAuthToken(), d = await o(n, {
23
+ ...u,
18
24
  headers: {
19
- ...s?.headers,
25
+ ...u?.headers,
20
26
  "Content-Type": "application/json",
21
27
  // Only include Authorization header if token exists
22
- ...i && { Authorization: `Bearer ${i}` }
28
+ ...a && { Authorization: `Bearer ${a}` }
23
29
  },
24
- // Use 'omit' for Bearer tokens (not cookies) to allow CORS wildcard origin
25
- credentials: "omit"
30
+ // 'include' so the browser attaches the HttpOnly pl-refresh-token
31
+ // cookie when /refresh is hit. Server allows credentials per origin
32
+ // (no CORS wildcard) so iOS/Android-WebView and same-origin web both
33
+ // work; embeds on third-party sites must be on a CORS-allowed origin.
34
+ credentials: "include"
26
35
  });
27
36
  if (e) {
28
- const p = h.json.bind(h);
29
- h.json = async () => {
30
- const c = await p();
31
- return typeof c == "object" && c !== null && "ok" in c && ("user" in c || "token" in c) && e(c), c;
37
+ const p = d.json.bind(d);
38
+ d.json = async () => {
39
+ const g = await p();
40
+ return typeof g == "object" && g !== null && "ok" in g && ("user" in g || "token" in g) && e(g), g;
32
41
  };
33
42
  }
34
- return h;
43
+ return d;
35
44
  }, "fetch")
36
45
  });
37
46
  }
38
- l(oe, "createApiClient");
39
- let se = /* @__PURE__ */ Symbol("clean"), d = [], f = 0;
40
- const A = 4, V = /* @__PURE__ */ l(/* @__NO_SIDE_EFFECTS__ */ (n) => {
47
+ l(ie, "createApiClient");
48
+ let ae = /* @__PURE__ */ Symbol("clean"), v = [], y = 0;
49
+ const b = 4, L = /* @__PURE__ */ l(/* @__NO_SIDE_EFFECTS__ */ (c) => {
41
50
  let e = [], t = {
42
51
  get() {
43
52
  return t.lc || t.listen(() => {
44
53
  })(), t.value;
45
54
  },
46
- init: n,
55
+ init: c,
47
56
  lc: 0,
48
57
  listen(r) {
49
58
  return t.lc = e.push(r), () => {
50
- for (let s = f + A; s < d.length; )
51
- d[s] === r ? d.splice(s, A) : s += A;
59
+ for (let s = y + b; s < v.length; )
60
+ v[s] === r ? v.splice(s, b) : s += b;
52
61
  let o = e.indexOf(r);
53
62
  ~o && (e.splice(o, 1), --t.lc || t.off());
54
63
  };
55
64
  },
56
65
  notify(r, o) {
57
- let s = !d.length;
58
- for (let i of e)
59
- d.push(i, t.value, r, o);
66
+ let s = !v.length;
67
+ for (let n of e)
68
+ v.push(n, t.value, r, o);
60
69
  if (s) {
61
- for (f = 0; f < d.length; f += A)
62
- d[f](
63
- d[f + 1],
64
- d[f + 2],
65
- d[f + 3]
70
+ for (y = 0; y < v.length; y += b)
71
+ v[y](
72
+ v[y + 1],
73
+ v[y + 2],
74
+ v[y + 3]
66
75
  );
67
- d.length = 0;
76
+ v.length = 0;
68
77
  }
69
78
  },
70
79
  /* It will be called on last listener unsubscribing.
@@ -79,14 +88,14 @@ const A = 4, V = /* @__PURE__ */ l(/* @__NO_SIDE_EFFECTS__ */ (n) => {
79
88
  let o = t.listen(r);
80
89
  return r(t.value), o;
81
90
  },
82
- value: n
91
+ value: c
83
92
  };
84
- return process.env.NODE_ENV !== "production" && (t[se] = () => {
93
+ return process.env.NODE_ENV !== "production" && (t[ae] = () => {
85
94
  e = [], t.lc = 0, t.off();
86
95
  }), t;
87
- }, "atom"), y = globalThis, b = y.__PL_AUTH_USER__ ?? (y.__PL_AUTH_USER__ = /* @__PURE__ */ V(void 0)), U = y.__PL_AUTH_TOKEN__ ?? (y.__PL_AUTH_TOKEN__ = /* @__PURE__ */ V(null)), F = class F {
96
+ }, "atom"), m = globalThis, A = m.__PL_AUTH_USER__ ?? (m.__PL_AUTH_USER__ = /* @__PURE__ */ L(void 0)), U = m.__PL_AUTH_TOKEN__ ?? (m.__PL_AUTH_TOKEN__ = /* @__PURE__ */ L(null)), E = m.__PL_AUTH_DEVICE_ID__ ?? (m.__PL_AUTH_DEVICE_ID__ = /* @__PURE__ */ L(null)), N = class N {
88
97
  constructor() {
89
- a(this, "logger", ee("SDKStorage"));
98
+ i(this, "logger", re("SDKStorage"));
90
99
  }
91
100
  /**
92
101
  * Check if localStorage is fully functional (some test environments provide partial mocks)
@@ -95,48 +104,52 @@ const A = 4, V = /* @__PURE__ */ l(/* @__NO_SIDE_EFFECTS__ */ (n) => {
95
104
  return typeof window < "u" && typeof localStorage?.getItem == "function" && typeof localStorage?.setItem == "function" && typeof localStorage?.removeItem == "function";
96
105
  }
97
106
  /**
98
- * Sync Vue reactive refs with global nanostores for cross-page persistence
107
+ * Sync Vue reactive refs with global nanostores for cross-bundle persistence.
99
108
  */
100
- syncWithGlobalStores(e, t) {
101
- const r = b.get(), o = U.get();
102
- r && (e.value = r), o && (t.value = o), J(e, (s) => {
103
- b.set(s);
104
- }, { immediate: !0 }), J(t, (s) => {
105
- U.set(s);
106
- }, { immediate: !0 }), b.subscribe((s) => {
107
- s !== e.value && (e.value = s);
108
- }), U.subscribe((s) => {
109
- s !== t.value && (t.value = s);
109
+ syncWithGlobalStores(e) {
110
+ const { activeUser: t, token: r, deviceId: o } = e, s = A.get(), n = U.get(), u = E.get();
111
+ s && (t.value = s), n && (r.value = n), u && (o.value = u), $(t, (a) => A.set(a), { immediate: !0 }), $(r, (a) => U.set(a), { immediate: !0 }), $(o, (a) => E.set(a), { immediate: !0 }), A.subscribe((a) => {
112
+ a !== t.value && (t.value = a);
113
+ }), U.subscribe((a) => {
114
+ a !== r.value && (r.value = a);
115
+ }), E.subscribe((a) => {
116
+ a !== o.value && (o.value = a);
110
117
  });
111
118
  }
112
119
  /**
113
- * Load user and token from browser storage on initialization
120
+ * Load user and token from browser storage on initialization.
121
+ * deviceId comes from a server-set non-HttpOnly cookie (read-only for JS).
114
122
  */
115
- loadFromStorage(e, t) {
123
+ loadFromStorage(e) {
116
124
  if (typeof window > "u")
117
125
  return;
118
- const r = x.getAuthToken();
119
- if (r && (t.value = r), this.isLocalStorageFunctional())
126
+ const t = x.getAuthToken();
127
+ t && (e.token.value = t);
128
+ const r = x.getDeviceId();
129
+ if (r && (e.deviceId.value = r), this.isLocalStorageFunctional())
120
130
  try {
121
131
  const o = localStorage.getItem("pagelines-user");
122
- o && (e.value = JSON.parse(o));
132
+ o && (e.activeUser.value = JSON.parse(o));
123
133
  } catch (o) {
124
134
  this.logger.error("Failed to load user from localStorage", { data: o });
125
135
  }
126
136
  }
127
137
  /**
128
- * Save current user and token to browser storage
138
+ * Save current user and access token to browser storage.
139
+ * deviceId is server-owned (Set-Cookie) — JS doesn't write it.
129
140
  */
130
- saveToStorage(e, t) {
131
- if (!(typeof window > "u") && (t.value ? x.setAuthToken(t.value) : x.removeAuthToken(), this.isLocalStorageFunctional()))
141
+ saveToStorage(e) {
142
+ if (!(typeof window > "u") && (e.token.value ? x.setAuthToken(e.token.value) : x.removeAuthToken(), this.isLocalStorageFunctional()))
132
143
  try {
133
- e.value ? localStorage.setItem("pagelines-user", JSON.stringify(e.value)) : localStorage.removeItem("pagelines-user");
134
- } catch (r) {
135
- this.logger.error("Failed to save user to localStorage", { data: r });
144
+ e.activeUser.value ? localStorage.setItem("pagelines-user", JSON.stringify(e.activeUser.value)) : localStorage.removeItem("pagelines-user");
145
+ } catch (t) {
146
+ this.logger.error("Failed to save user to localStorage", { data: t });
136
147
  }
137
148
  }
138
149
  /**
139
- * Clear all stored user data and tokens
150
+ * Clear local stored user data and JS-owned tokens. Server-owned cookies
151
+ * (pl-refresh-token, pl-device-id) are cleared by /api/auth/logout via
152
+ * Set-Cookie max-age=0 — JS can't touch them.
140
153
  */
141
154
  clearStorage() {
142
155
  if (!(typeof window > "u")) {
@@ -146,7 +159,7 @@ const A = 4, V = /* @__PURE__ */ l(/* @__NO_SIDE_EFFECTS__ */ (n) => {
146
159
  } catch (e) {
147
160
  this.logger.error("Failed to clear user from localStorage", { data: e });
148
161
  }
149
- b.set(void 0), U.set(null);
162
+ A.set(void 0), U.set(null), E.set(null);
150
163
  }
151
164
  }
152
165
  /**
@@ -173,20 +186,20 @@ const A = 4, V = /* @__PURE__ */ l(/* @__NO_SIDE_EFFECTS__ */ (n) => {
173
186
  }
174
187
  }
175
188
  };
176
- l(F, "SDKStorage");
177
- let B = F;
189
+ l(N, "SDKStorage");
190
+ let R = N;
178
191
  const H = [
179
192
  "Deploying your server...",
180
193
  "Setting up your workspace...",
181
194
  "Installing tools...",
182
195
  "Almost ready..."
183
- ], L = class L {
196
+ ], G = class G {
184
197
  constructor(e) {
185
- a(this, "ctx");
198
+ i(this, "ctx");
186
199
  this.ctx = e;
187
200
  }
188
201
  async create(e) {
189
- const t = e.orgId || this.resolveOrgId(), r = g(this.ctx.apiBase, this.ctx.isDev), s = await (await fetch(`${r}/api/agent`, {
202
+ const t = e.orgId || this.resolveOrgId(), r = f(this.ctx.apiBase, this.ctx.isDev), s = await (await fetch(`${r}/api/agent`, {
190
203
  method: "POST",
191
204
  headers: {
192
205
  "Content-Type": "application/json",
@@ -195,13 +208,13 @@ const H = [
195
208
  body: JSON.stringify({ name: e.name, orgId: t })
196
209
  })).json();
197
210
  if (!s.ok || !s.data?.[0]) {
198
- const i = s.error || "Failed to create agent";
199
- throw this.ctx.error.value = i, new Error(i);
211
+ const n = s.error || "Failed to create agent";
212
+ throw this.ctx.error.value = n, new Error(n);
200
213
  }
201
214
  return this.ctx.processApiResponse(s), s.data[0];
202
215
  }
203
216
  async getStatus(e) {
204
- const t = g(this.ctx.apiBase, this.ctx.isDev), o = await (await fetch(`${t}/api/agent/${e.agentId}/status`, {
217
+ const t = f(this.ctx.apiBase, this.ctx.isDev), o = await (await fetch(`${t}/api/agent/${e.agentId}/status`, {
205
218
  headers: {
206
219
  ...this.ctx.token.value && { Authorization: `Bearer ${this.ctx.token.value}` }
207
220
  }
@@ -209,23 +222,23 @@ const H = [
209
222
  return !o.ok || !o.data ? { status: "unknown", ready: !1, error: "Failed to check status" } : o.data;
210
223
  }
211
224
  async waitUntilReady(e) {
212
- const { agentId: t, onStatus: r, timeoutMs: o = 3e5, pollIntervalMs: s = 3e3 } = e, i = Date.now();
213
- let h = 0;
214
- for (; Date.now() - i < o; ) {
215
- const p = await this.getStatus({ agentId: t });
216
- if (p.ready) {
225
+ const { agentId: t, onStatus: r, timeoutMs: o = 3e5, pollIntervalMs: s = 3e3 } = e, n = Date.now();
226
+ let u = 0;
227
+ for (; Date.now() - n < o; ) {
228
+ const a = await this.getStatus({ agentId: t });
229
+ if (a.ready) {
217
230
  r?.("Ready!");
218
231
  return;
219
232
  }
220
- if (p.status === "error")
221
- throw new Error(p.error || "Provisioning failed");
222
- r && h < H.length && (r(H[h]), h++), await new Promise((c) => setTimeout(c, s));
233
+ if (a.status === "error")
234
+ throw new Error(a.error || "Provisioning failed");
235
+ r && u < H.length && (r(H[u]), u++), await new Promise((d) => setTimeout(d, s));
223
236
  }
224
237
  throw new Error("Agent provisioning timed out — please try again");
225
238
  }
226
239
  /** Send a typed webhook event to a bot agent. No auth required — the proxy is public. */
227
240
  async webhook(e) {
228
- const r = `${g(this.ctx.apiBase, this.ctx.isDev)}/api/bot-api/agents/${e.agentId}/webhook`, o = { type: e.type, data: e.data };
241
+ const r = `${f(this.ctx.apiBase, this.ctx.isDev)}/api/bot-api/agents/${e.agentId}/webhook`, o = { type: e.type, data: e.data };
229
242
  e.meta && (o.meta = e.meta);
230
243
  const s = await fetch(r, {
231
244
  method: "POST",
@@ -233,8 +246,8 @@ const H = [
233
246
  body: JSON.stringify(o)
234
247
  });
235
248
  if (!s.ok) {
236
- const i = await s.text().catch(() => "Unknown error");
237
- throw new Error(`Webhook delivery failed (${s.status}): ${i.slice(0, 200)}`);
249
+ const n = await s.text().catch(() => "Unknown error");
250
+ throw new Error(`Webhook delivery failed (${s.status}): ${n.slice(0, 200)}`);
238
251
  }
239
252
  return s.json();
240
253
  }
@@ -245,24 +258,24 @@ const H = [
245
258
  return t;
246
259
  }
247
260
  };
248
- l(L, "AgentClient");
249
- let D = L;
250
- async function m(n, e) {
251
- n.loading.value = !0, n.error.value = null;
261
+ l(G, "AgentClient");
262
+ let P = G;
263
+ async function w(c, e) {
264
+ c.loading.value = !0, c.error.value = null;
252
265
  try {
253
266
  return await e();
254
267
  } finally {
255
- n.loading.value = !1;
268
+ c.loading.value = !1;
256
269
  }
257
270
  }
258
- l(m, "withLoadingState");
259
- const _ = class _ {
271
+ l(w, "withLoadingState");
272
+ const M = class M {
260
273
  constructor(e) {
261
- a(this, "ctx");
274
+ i(this, "ctx");
262
275
  this.ctx = e;
263
276
  }
264
277
  async sendCode(e) {
265
- return m(this.ctx, async () => {
278
+ return w(this.ctx, async () => {
266
279
  try {
267
280
  const r = await (await this.ctx.api.auth["check-email"].$post({
268
281
  json: { email: e }
@@ -277,7 +290,7 @@ const _ = class _ {
277
290
  });
278
291
  }
279
292
  async verifyCode(e, t) {
280
- return m(this.ctx, async () => {
293
+ return w(this.ctx, async () => {
281
294
  try {
282
295
  const o = await (await this.ctx.api.auth["verify-code"].$post({
283
296
  json: { email: e, code: t }
@@ -292,7 +305,7 @@ const _ = class _ {
292
305
  });
293
306
  }
294
307
  async logout() {
295
- return m(this.ctx, async () => {
308
+ return w(this.ctx, async () => {
296
309
  try {
297
310
  await this.ctx.api.auth.logout.$post();
298
311
  } catch (e) {
@@ -303,7 +316,7 @@ const _ = class _ {
303
316
  }
304
317
  async getCurrentUser() {
305
318
  if (this.ctx.token.value)
306
- return m(this.ctx, async () => {
319
+ return w(this.ctx, async () => {
307
320
  try {
308
321
  const t = await (await this.ctx.api.auth.me.$get()).json();
309
322
  if (!t.ok) {
@@ -318,7 +331,7 @@ const _ = class _ {
318
331
  });
319
332
  }
320
333
  async requestAuthCode(e) {
321
- return m(this.ctx, async () => {
334
+ return w(this.ctx, async () => {
322
335
  try {
323
336
  const r = await (await this.ctx.api.auth["check-email"].$post({
324
337
  json: { email: e.email }
@@ -330,7 +343,7 @@ const _ = class _ {
330
343
  });
331
344
  }
332
345
  async loginWithCode(e) {
333
- return m(this.ctx, async () => {
346
+ return w(this.ctx, async () => {
334
347
  try {
335
348
  const r = await (await this.ctx.api.auth["verify-code"].$post({
336
349
  json: { email: e.email, code: e.code }
@@ -346,45 +359,45 @@ const _ = class _ {
346
359
  this.ctx.logger.error("loginWithGoogle: Only available in browser");
347
360
  return;
348
361
  }
349
- const t = g(this.ctx.apiBase, this.ctx.isDev), r = window.location.origin, o = `${t}/auth/google-popup?origin=${encodeURIComponent(r)}`, s = 500, i = 600, h = window.screenX + (window.outerWidth - s) / 2, p = window.screenY + (window.outerHeight - i) / 2, c = window.open(
362
+ const t = f(this.ctx.apiBase, this.ctx.isDev), r = window.location.origin, o = `${t}/auth/google-popup?origin=${encodeURIComponent(r)}`, s = 500, n = 600, u = window.screenX + (window.outerWidth - s) / 2, a = window.screenY + (window.outerHeight - n) / 2, d = window.open(
350
363
  o,
351
364
  "google-auth",
352
- `width=${s},height=${i},left=${h},top=${p},popup=yes`
365
+ `width=${s},height=${n},left=${u},top=${a},popup=yes`
353
366
  );
354
- if (!c) {
355
- const u = "Popup was blocked. Please allow popups for this site.";
356
- this.ctx.error.value = u, e?.onError?.(u);
367
+ if (!d) {
368
+ const h = "Popup was blocked. Please allow popups for this site.";
369
+ this.ctx.error.value = h, e?.onError?.(h);
357
370
  return;
358
371
  }
359
- const v = /* @__PURE__ */ l((u) => {
372
+ const p = /* @__PURE__ */ l((h) => {
360
373
  const S = new URL(t).origin;
361
- if (u.origin === S) {
362
- if (u.data?.type === "auth-success") {
363
- window.removeEventListener("message", v);
364
- const { token: w, user: z } = u.data;
365
- this.ctx.processApiResponse({ ok: !0, data: {}, token: w, user: z }), this.ctx.logger.info("Google login successful"), e?.onSuccess?.(z);
366
- } else if (u.data?.type === "auth-error") {
367
- window.removeEventListener("message", v);
368
- const w = u.data.error || "Google authentication failed";
369
- this.ctx.error.value = w, this.ctx.logger.error("Google login failed", { error: w }), e?.onError?.(w);
374
+ if (h.origin === S) {
375
+ if (h.data?.type === "auth-success") {
376
+ window.removeEventListener("message", p);
377
+ const { token: I, user: K } = h.data;
378
+ this.ctx.processApiResponse({ ok: !0, data: {}, token: I, user: K }), this.ctx.logger.info("Google login successful"), e?.onSuccess?.(K);
379
+ } else if (h.data?.type === "auth-error") {
380
+ window.removeEventListener("message", p);
381
+ const I = h.data.error || "Google authentication failed";
382
+ this.ctx.error.value = I, this.ctx.logger.error("Google login failed", { error: I }), e?.onError?.(I);
370
383
  }
371
384
  }
372
385
  }, "handler");
373
- window.addEventListener("message", v);
374
- const I = setInterval(() => {
375
- c.closed && (clearInterval(I), window.removeEventListener("message", v));
386
+ window.addEventListener("message", p);
387
+ const g = setInterval(() => {
388
+ d.closed && (clearInterval(g), window.removeEventListener("message", p));
376
389
  }, 500);
377
390
  }
378
391
  };
379
- l(_, "AuthClient");
380
- let j = _;
381
- const N = class N {
392
+ l(M, "AuthClient");
393
+ let j = M;
394
+ const W = class W {
382
395
  constructor(e) {
383
- a(this, "ctx");
396
+ i(this, "ctx");
384
397
  this.ctx = e;
385
398
  }
386
399
  async startTrial(e) {
387
- const t = this.resolveOrgId(), r = g(this.ctx.apiBase, this.ctx.isDev), s = await (await fetch(`${r}/api/billing/checkout/create`, {
400
+ const t = this.resolveOrgId(), r = f(this.ctx.apiBase, this.ctx.isDev), s = await (await fetch(`${r}/api/billing/checkout/create`, {
388
401
  method: "POST",
389
402
  headers: {
390
403
  "Content-Type": "application/json",
@@ -397,8 +410,8 @@ const N = class N {
397
410
  })
398
411
  })).json();
399
412
  if (!s.ok || !s.data?.url) {
400
- const i = s.error || "Failed to create checkout session";
401
- throw this.ctx.error.value = i, new Error(i);
413
+ const n = s.error || "Failed to create checkout session";
414
+ throw this.ctx.error.value = n, new Error(n);
402
415
  }
403
416
  window.location.href = s.data.url;
404
417
  }
@@ -406,7 +419,7 @@ const N = class N {
406
419
  return this.getStatus();
407
420
  }
408
421
  async getStatus() {
409
- const e = this.resolveOrgId(), t = g(this.ctx.apiBase, this.ctx.isDev), o = await (await fetch(`${t}/api/billing/details/${e}`, {
422
+ const e = this.resolveOrgId(), t = f(this.ctx.apiBase, this.ctx.isDev), o = await (await fetch(`${t}/api/billing/details/${e}`, {
410
423
  headers: {
411
424
  ...this.ctx.token.value && { Authorization: `Bearer ${this.ctx.token.value}` }
412
425
  }
@@ -435,15 +448,15 @@ const N = class N {
435
448
  return t;
436
449
  }
437
450
  };
438
- l(N, "BillingClient");
439
- let P = N;
440
- const G = class G {
451
+ l(W, "BillingClient");
452
+ let C = W;
453
+ const z = class z {
441
454
  constructor(e) {
442
- a(this, "ctx");
455
+ i(this, "ctx");
443
456
  this.ctx = e;
444
457
  }
445
458
  async chatStream(e) {
446
- const r = `${g(this.ctx.apiBase, this.ctx.isDev)}/api/agent/public/${encodeURIComponent(e.handle)}/chat/stream`;
459
+ const r = `${f(this.ctx.apiBase, this.ctx.isDev)}/api/agent/public/${encodeURIComponent(e.handle)}/chat/stream`;
447
460
  return this._streamChat({
448
461
  url: r,
449
462
  headers: { "Content-Type": "application/json" },
@@ -463,7 +476,7 @@ const G = class G {
463
476
  });
464
477
  }
465
478
  async chatStreamAuthenticated(e) {
466
- const r = `${g(this.ctx.apiBase, this.ctx.isDev)}/api/agent/${encodeURIComponent(e.agentId)}/chat/stream`;
479
+ const r = `${f(this.ctx.apiBase, this.ctx.isDev)}/api/agent/${encodeURIComponent(e.agentId)}/chat/stream`;
467
480
  return this._streamChat({
468
481
  url: r,
469
482
  headers: {
@@ -492,8 +505,8 @@ const G = class G {
492
505
  body: JSON.stringify(e.body)
493
506
  });
494
507
  if (!t.ok) {
495
- const h = await t.json().catch(() => ({ error: "Request failed" }));
496
- e.onError(h.error || `HTTP ${t.status}`);
508
+ const u = await t.json().catch(() => ({ error: "Request failed" }));
509
+ e.onError(u.error || `HTTP ${t.status}`);
497
510
  return;
498
511
  }
499
512
  const r = t.body?.getReader();
@@ -502,43 +515,43 @@ const G = class G {
502
515
  return;
503
516
  }
504
517
  const o = new TextDecoder();
505
- let s = "", i = e.conversationId || "";
518
+ let s = "", n = e.conversationId || "";
506
519
  for (; ; ) {
507
- const { done: h, value: p } = await r.read();
508
- if (h)
520
+ const { done: u, value: a } = await r.read();
521
+ if (u)
509
522
  break;
510
- s += o.decode(p, { stream: !0 });
511
- const c = s.split(`
523
+ s += o.decode(a, { stream: !0 });
524
+ const d = s.split(`
512
525
  `);
513
- s = c.pop() || "";
514
- for (const v of c) {
515
- if (!v.startsWith("data: "))
526
+ s = d.pop() || "";
527
+ for (const p of d) {
528
+ if (!p.startsWith("data: "))
516
529
  continue;
517
- const I = v.slice(6).trim();
518
- if (I === "[DONE]") {
519
- e.onDone(i);
530
+ const g = p.slice(6).trim();
531
+ if (g === "[DONE]") {
532
+ e.onDone(n);
520
533
  return;
521
534
  }
522
535
  try {
523
- const u = JSON.parse(I);
524
- if (u.pl_status) {
525
- e.onStatus?.(u.pl_status);
536
+ const h = JSON.parse(g);
537
+ if (h.pl_status) {
538
+ e.onStatus?.(h.pl_status);
526
539
  continue;
527
540
  }
528
- u.pl_metadata?.conversationId && (i = u.pl_metadata.conversationId);
529
- const S = u.choices?.[0]?.delta;
541
+ h.pl_metadata?.conversationId && (n = h.pl_metadata.conversationId);
542
+ const S = h.choices?.[0]?.delta;
530
543
  S?.content && e.onDelta(S.content);
531
544
  } catch {
532
545
  }
533
546
  }
534
547
  }
535
- e.onDone(i);
548
+ e.onDone(n);
536
549
  } catch (t) {
537
550
  e.onError(t instanceof Error ? t.message : "Stream failed");
538
551
  }
539
552
  }
540
553
  async chatMessage(e) {
541
- const r = `${g(this.ctx.apiBase, this.ctx.isDev)}/api/agent/public/${encodeURIComponent(e.handle)}/chat`;
554
+ const r = `${f(this.ctx.apiBase, this.ctx.isDev)}/api/agent/public/${encodeURIComponent(e.handle)}/chat`;
542
555
  try {
543
556
  const s = await (await fetch(r, {
544
557
  method: "POST",
@@ -564,11 +577,11 @@ const G = class G {
564
577
  }
565
578
  }
566
579
  };
567
- l(G, "ChatClient");
568
- let C = G;
569
- const M = class M {
580
+ l(z, "ChatClient");
581
+ let F = z;
582
+ const q = class q {
570
583
  constructor(e) {
571
- a(this, "ctx");
584
+ i(this, "ctx");
572
585
  this.ctx = e;
573
586
  }
574
587
  async getPublicAgent(e) {
@@ -610,7 +623,7 @@ const M = class M {
610
623
  generateAnonId() {
611
624
  const e = "pagelinesAnonId";
612
625
  let t = this.ctx.storage.getItem(e);
613
- return t || (t = $({ prefix: "anon" }), this.ctx.storage.setItem(e, t)), t;
626
+ return t || (t = B({ prefix: "anon" }), this.ctx.storage.setItem(e, t)), t;
614
627
  }
615
628
  track(e) {
616
629
  try {
@@ -625,11 +638,11 @@ const M = class M {
625
638
  }
626
639
  }
627
640
  };
628
- l(M, "UserClient");
629
- let O = M;
630
- const W = class W {
641
+ l(q, "UserClient");
642
+ let O = q;
643
+ const J = class J {
631
644
  constructor() {
632
- a(this, "key", "__PAGELINES_SDK__");
645
+ i(this, "key", "__PAGELINES_SDK__");
633
646
  }
634
647
  get() {
635
648
  if (!(typeof window > "u"))
@@ -642,29 +655,33 @@ const W = class W {
642
655
  typeof window < "u" && delete globalThis[this.key];
643
656
  }
644
657
  };
645
- l(W, "SDKGlobal");
646
- let R = W;
647
- const E = new R(), T = class T extends te {
658
+ l(J, "SDKGlobal");
659
+ let _ = J;
660
+ const T = new _(), D = class D extends oe {
648
661
  constructor(t = {}) {
649
- const r = E.get();
662
+ const r = T.get();
650
663
  if (r)
651
664
  return console.debug("[PageLinesSDK] Returning existing singleton instance"), r;
652
665
  super("PageLinesSDK", t);
653
666
  // Vue reactive state
654
- a(this, "activeUser", k());
655
- a(this, "token", k(null));
656
- a(this, "loading", k(!1));
657
- a(this, "error", k(null));
658
- a(this, "apiBase", this.settings.apiBase || void 0);
667
+ i(this, "activeUser", k());
668
+ i(this, "token", k(null));
669
+ // Refresh credential lives in HttpOnly pl-refresh-token cookie — JS never
670
+ // holds it, so no reactive ref. /api/auth/refresh reads the cookie via the
671
+ // browser's automatic credentials: 'include' attach.
672
+ i(this, "deviceId", k(null));
673
+ i(this, "loading", k(!1));
674
+ i(this, "error", k(null));
675
+ i(this, "apiBase", this.settings.apiBase || void 0);
659
676
  // Storage handler for persistence
660
- a(this, "storage", new B());
677
+ i(this, "storage", new R());
661
678
  // Auto-managed session ID for usage tracking
662
- a(this, "sessionId", $({ prefix: "ses" }));
679
+ i(this, "sessionId", B({ prefix: "ses" }));
663
680
  // Typed Hono RPC client - uses SDKAppType (auth/self/usage routes only)
664
681
  // Initialized in constructor (definite assignment via singleton pattern)
665
- a(this, "apiClient");
682
+ i(this, "apiClient");
666
683
  // Computed properties derived from activeUser (matches UserClient pattern)
667
- a(this, "currentAgent", K(() => {
684
+ i(this, "currentAgent", V(() => {
668
685
  const t = this.activeUser.value;
669
686
  if (!t?.agents)
670
687
  return;
@@ -672,7 +689,7 @@ const E = new R(), T = class T extends te {
672
689
  if (r)
673
690
  return t.agents.find((o) => o.agentId === r);
674
691
  }));
675
- a(this, "currentOrg", K(() => {
692
+ i(this, "currentOrg", V(() => {
676
693
  const t = this.currentAgent.value;
677
694
  if (!t?.orgId)
678
695
  return;
@@ -681,17 +698,26 @@ const E = new R(), T = class T extends te {
681
698
  return r.orgs.find((o) => o.orgId === t.orgId);
682
699
  }));
683
700
  // Initialization state
684
- a(this, "initialized");
685
- a(this, "resolveUser");
701
+ i(this, "initialized");
702
+ i(this, "resolveUser");
686
703
  // Sub-clients (new preferred API surface)
687
- a(this, "agent");
688
- a(this, "auth");
689
- a(this, "billing");
690
- a(this, "chat");
691
- a(this, "user");
692
- E.set(this), this.apiClient = oe(
704
+ i(this, "agent");
705
+ i(this, "auth");
706
+ i(this, "billing");
707
+ i(this, "chat");
708
+ i(this, "user");
709
+ T.set(this), this.apiClient = ie(
693
710
  { isDev: this.isDev, apiBase: this.apiBase },
694
- this.processApiResponse.bind(this)
711
+ this.processApiResponse.bind(this),
712
+ {
713
+ getDeviceId: /* @__PURE__ */ l(() => this.deviceId.value, "getDeviceId"),
714
+ onAccessTokenRefreshed: /* @__PURE__ */ l((s) => {
715
+ this.token.value = s, this.persistAuth();
716
+ }, "onAccessTokenRefreshed"),
717
+ onTerminalFailure: /* @__PURE__ */ l(() => {
718
+ this.clearSession();
719
+ }, "onTerminalFailure")
720
+ }
695
721
  );
696
722
  const o = {
697
723
  api: this.api,
@@ -707,7 +733,7 @@ const E = new R(), T = class T extends te {
707
733
  logger: this.logger,
708
734
  processApiResponse: this.processApiResponse.bind(this)
709
735
  };
710
- this.agent = new D(o), this.auth = new j(o), this.billing = new P(o), this.chat = new C(o), this.user = new O(o), this.logger.info("PageLinesSDK initialized"), this.storage.loadFromStorage(this.activeUser, this.token), this.storage.syncWithGlobalStores(this.activeUser, this.token), this.initialized = new Promise((s) => {
736
+ this.agent = new P(o), this.auth = new j(o), this.billing = new C(o), this.chat = new F(o), this.user = new O(o), this.logger.info("PageLinesSDK initialized"), this.storage.loadFromStorage(this.authRefs()), this.storage.syncWithGlobalStores(this.authRefs()), this.initialized = new Promise((s) => {
711
737
  this.resolveUser = s;
712
738
  }), this.token.value && !this.activeUser.value ? this.getCurrentUser().then((s) => {
713
739
  this.resolveUser && (this.resolveUser(s), this.resolveUser = void 0);
@@ -721,7 +747,7 @@ const E = new R(), T = class T extends te {
721
747
  * Recommended: Use this instead of constructor for shared state
722
748
  */
723
749
  static getInstance(t = {}) {
724
- return E.get() || new T(t);
750
+ return T.get() || new D(t);
725
751
  }
726
752
  get isDev() {
727
753
  return this.settings.isDev ?? (typeof window < "u" ? window.location.hostname === "localhost" || window.location.hostname.includes("127.0.0.1") : !1);
@@ -733,15 +759,29 @@ const E = new R(), T = class T extends te {
733
759
  }
734
760
  // Process ApiResponse for automatic user/token updates - public for dependency injection
735
761
  processApiResponse(t) {
736
- t.ok && t.user && (this.activeUser.value = t.user, this.logger.info("User updated from API response", { data: t.user })), t.ok && t.token && (this.token.value = t.token, this.storage.saveToStorage(this.activeUser, this.token), this.logger.info("Token updated from API response")), this.resolveUser && t.ok && (this.resolveUser(t.user), this.resolveUser = void 0);
762
+ if (!t.ok) return;
763
+ let r = !1;
764
+ t.user && (this.activeUser.value = t.user, this.logger.info("User updated from API response", { data: t.user }), r = !0), t.token && (this.token.value = t.token, this.logger.info("Token updated from API response"), r = !0);
765
+ const o = t.data?.deviceId;
766
+ o && (this.deviceId.value = o, r = !0), r && this.persistAuth(), this.resolveUser && (this.resolveUser(t.user), this.resolveUser = void 0);
767
+ }
768
+ authRefs() {
769
+ return {
770
+ activeUser: this.activeUser,
771
+ token: this.token,
772
+ deviceId: this.deviceId
773
+ };
774
+ }
775
+ persistAuth() {
776
+ this.storage.saveToStorage(this.authRefs());
737
777
  }
738
778
  // Clear all user data and tokens
739
779
  clearSession() {
740
- this.logger.info("Clearing session"), this.activeUser.value = void 0, this.token.value = null, this.error.value = null, this.storage.clearStorage();
780
+ this.logger.info("Clearing session"), this.activeUser.value = void 0, this.token.value = null, this.deviceId.value = null, this.error.value = null, this.storage.clearStorage();
741
781
  }
742
782
  // Full reset - clears session + state + destroys singleton
743
783
  clear() {
744
- this.logger.info("Clearing SDK completely"), this.clearSession(), this.loading.value = !1, this.sessionId = $({ prefix: "ses" }), E.delete();
784
+ this.logger.info("Clearing SDK completely"), this.clearSession(), this.loading.value = !1, this.sessionId = B({ prefix: "ses" }), T.delete();
745
785
  }
746
786
  // Backward-compatible delegates — these forward to sub-clients
747
787
  // Can be removed in a future breaking change
@@ -788,14 +828,14 @@ const E = new R(), T = class T extends te {
788
828
  return this.user.track(t);
789
829
  }
790
830
  };
791
- l(T, "PageLinesSDK");
792
- let Q = T;
831
+ l(D, "PageLinesSDK");
832
+ let X = D;
793
833
  export {
794
- D as A,
795
- C,
796
- Q as P,
834
+ P as A,
835
+ F as C,
836
+ X as P,
797
837
  O as U,
798
838
  j as a,
799
- g as r
839
+ f as r
800
840
  };
801
841
  //# sourceMappingURL=sdkClient.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sdkClient.js","sources":["../api.ts","../../../node_modules/.pnpm/nanostores@1.2.0/node_modules/nanostores/clean-stores/index.js","../../../node_modules/.pnpm/nanostores@1.2.0/node_modules/nanostores/atom/index.js","../sdkStorage.ts","../clients/AgentClient.ts","../clients/AuthClient.ts","../clients/BillingClient.ts","../clients/ChatClient.ts","../clients/UserClient.ts","../sdkClient.ts"],"sourcesContent":["import type { Hono } from 'hono'\nimport { APP_PORT, APP_PROD_URL } from '@pagelines/core'\nimport { hc } from 'hono/client'\nimport { cookieUtil } from '@pagelines/core'\n\nexport interface ApiClientSettings {\n isDev: boolean\n apiBase?: string\n [key: string]: unknown\n}\n\n/**\n * Resolve API base URL from settings.\n * Centralizes the isDev/apiBase/production URL logic used across SDK clients.\n */\nexport function resolveApiBase(apiBase?: string, isDev?: boolean): string {\n return apiBase || (isDev ? `http://localhost:${APP_PORT}` : APP_PROD_URL)\n}\n\n/**\n * Create fully typed Hono RPC client for PageLines SDK\n *\n * @template TAppType - The Hono app type from the server (enables full type safety)\n * @param settings - Configuration for API base URL and environment\n * @param responseHandler - Optional handler to process ApiResponse for auto user/token updates\n * @returns Typed Hono client with response interceptor\n *\n * @example\n * ```typescript\n * import type { SDKAppType } from '@/modules/main/server'\n * const client = createApiClient<SDKAppType>({ isDev: true })\n * const response = await client.api.auth['check-email'].$post({ json: { email } })\n * ```\n */\nexport function createApiClient<TAppType extends Hono = any>(\n settings: ApiClientSettings,\n responseHandler?: (response: any) => void,\n): ReturnType<typeof hc<TAppType>> {\n const baseUrl = resolveApiBase(settings.apiBase, settings.isDev)\n\n // Create typed Hono RPC client with response interceptor\n const client = hc<TAppType>(baseUrl, {\n fetch: async (input: RequestInfo | URL, init?: RequestInit) => {\n const token = cookieUtil.getAuthToken()\n\n const response = await fetch(input, {\n ...init,\n headers: {\n ...init?.headers,\n 'Content-Type': 'application/json',\n // Only include Authorization header if token exists\n ...(token && { 'Authorization': `Bearer ${token}` }),\n },\n // Use 'omit' for Bearer tokens (not cookies) to allow CORS wildcard origin\n credentials: 'omit',\n })\n\n // Intercept response to process ApiResponse pattern\n if (responseHandler) {\n // Wrap the original response's json method directly\n const originalJson = response.json.bind(response)\n\n // Override json method on the response object itself\n response.json = async () => {\n const result = await originalJson()\n\n // Process ApiResponse pattern if it has user/token fields\n if (typeof result === 'object' && result !== null) {\n if ('ok' in result && ('user' in result || 'token' in result)) {\n responseHandler(result)\n }\n }\n\n return result\n }\n }\n\n return response\n },\n })\n\n return client\n}\n","import { cleanTasks } from '../task/index.js'\n\nexport let clean = Symbol('clean')\n\nexport let cleanStores = (...stores) => {\n if (process.env.NODE_ENV === 'production') {\n throw new Error(\n 'cleanStores() can be used only during development or tests'\n )\n }\n cleanTasks()\n for (let $store of stores) {\n if ($store) {\n if ($store.mocked) delete $store.mocked\n if ($store[clean]) $store[clean]()\n }\n }\n}\n","import { clean } from '../clean-stores/index.js'\n\nlet listenerQueue = []\nlet lqIndex = 0\nconst QUEUE_ITEMS_PER_LISTENER = 4\nexport let epoch = 0\n\n/* @__NO_SIDE_EFFECTS__ */\nexport const atom = initialValue => {\n let listeners = []\n let $atom = {\n get() {\n if (!$atom.lc) {\n $atom.listen(() => {})()\n }\n return $atom.value\n },\n init: initialValue,\n lc: 0,\n listen(listener) {\n $atom.lc = listeners.push(listener)\n\n return () => {\n for (\n let i = lqIndex + QUEUE_ITEMS_PER_LISTENER;\n i < listenerQueue.length;\n\n ) {\n if (listenerQueue[i] === listener) {\n listenerQueue.splice(i, QUEUE_ITEMS_PER_LISTENER)\n } else {\n i += QUEUE_ITEMS_PER_LISTENER\n }\n }\n\n let index = listeners.indexOf(listener)\n if (~index) {\n listeners.splice(index, 1)\n if (!--$atom.lc) $atom.off()\n }\n }\n },\n notify(oldValue, changedKey) {\n epoch++\n let runListenerQueue = !listenerQueue.length\n for (let listener of listeners) {\n listenerQueue.push(listener, $atom.value, oldValue, changedKey)\n }\n\n if (runListenerQueue) {\n for (\n lqIndex = 0;\n lqIndex < listenerQueue.length;\n lqIndex += QUEUE_ITEMS_PER_LISTENER\n ) {\n listenerQueue[lqIndex](\n listenerQueue[lqIndex + 1],\n listenerQueue[lqIndex + 2],\n listenerQueue[lqIndex + 3]\n )\n }\n listenerQueue.length = 0\n }\n },\n /* It will be called on last listener unsubscribing.\n We will redefine it in onMount and onStop. */\n off() {},\n set(newValue) {\n let oldValue = $atom.value\n if (oldValue !== newValue) {\n $atom.value = newValue\n $atom.notify(oldValue)\n }\n },\n subscribe(listener) {\n let unbind = $atom.listen(listener)\n listener($atom.value)\n return unbind\n },\n value: initialValue\n }\n\n if (process.env.NODE_ENV !== 'production') {\n $atom[clean] = () => {\n listeners = []\n $atom.lc = 0\n $atom.off()\n }\n }\n\n return $atom\n}\n\nexport const readonlyType = store => store\n","import type { Ref } from 'vue'\nimport type { EnrichedUser } from '@pagelines/core'\nimport { atom } from 'nanostores'\nimport { watch } from 'vue'\nimport { cookieUtil, createLogger } from '@pagelines/core'\n\n// Global nanostores shared via globalThis so SDK and app bundles use the same atoms\nconst _g = globalThis as Record<string, any>\nconst $globalActiveUser = (_g.__PL_AUTH_USER__ ??= atom<EnrichedUser | undefined>(undefined)) as ReturnType<typeof atom<EnrichedUser | undefined>>\nconst $globalToken = (_g.__PL_AUTH_TOKEN__ ??= atom<string | null>(null)) as ReturnType<typeof atom<string | null>>\n\n/**\n * SDKStorage - Handles all storage, sync, and persistence for PageLinesSDK\n *\n * Extracted from PageLinesSDK to keep the main class focused on public API methods.\n * Manages localStorage, cookies, and nanostor synchronization for state persistence.\n */\nexport class SDKStorage {\n private logger = createLogger('SDKStorage')\n\n /**\n * Check if localStorage is fully functional (some test environments provide partial mocks)\n */\n private isLocalStorageFunctional(): boolean {\n return typeof window !== 'undefined'\n && typeof localStorage?.getItem === 'function'\n && typeof localStorage?.setItem === 'function'\n && typeof localStorage?.removeItem === 'function'\n }\n\n /**\n * Sync Vue reactive refs with global nanostores for cross-page persistence\n */\n syncWithGlobalStores(activeUser: Ref<EnrichedUser | undefined>, token: Ref<string | null>): void {\n // 1. Restore from global store on init\n const storedUser = $globalActiveUser.get()\n const storedToken = $globalToken.get()\n\n if (storedUser) {\n activeUser.value = storedUser\n }\n if (storedToken) {\n token.value = storedToken\n }\n\n // 2. Vue refs → global stores (for persistence)\n watch(activeUser, (newUser) => {\n $globalActiveUser.set(newUser)\n }, { immediate: true })\n\n watch(token, (newToken) => {\n $globalToken.set(newToken)\n }, { immediate: true })\n\n // 3. Global stores → Vue refs (for cross-page updates)\n $globalActiveUser.subscribe((newUser) => {\n if (newUser !== activeUser.value) {\n activeUser.value = newUser\n }\n })\n\n $globalToken.subscribe((newToken) => {\n if (newToken !== token.value) {\n token.value = newToken\n }\n })\n }\n\n /**\n * Load user and token from browser storage on initialization\n */\n loadFromStorage(activeUser: Ref<EnrichedUser | undefined>, token: Ref<string | null>): void {\n if (typeof window === 'undefined')\n return\n\n // Load token from cookie\n const savedToken = cookieUtil.getAuthToken()\n if (savedToken) {\n token.value = savedToken\n }\n\n // Try to load user from localStorage for immediate availability\n if (this.isLocalStorageFunctional()) {\n try {\n const savedUser = localStorage.getItem('pagelines-user')\n if (savedUser) {\n activeUser.value = JSON.parse(savedUser)\n }\n } catch (error) {\n this.logger.error('Failed to load user from localStorage', { data: error })\n }\n }\n }\n\n /**\n * Save current user and token to browser storage\n */\n saveToStorage(activeUser: Ref<EnrichedUser | undefined>, token: Ref<string | null>): void {\n if (typeof window === 'undefined')\n return\n\n // Save token to cookie using app's cookie utility\n if (token.value) {\n cookieUtil.setAuthToken(token.value)\n } else {\n cookieUtil.removeAuthToken()\n }\n\n // Save user to localStorage for quick loading\n if (this.isLocalStorageFunctional()) {\n try {\n if (activeUser.value) {\n localStorage.setItem('pagelines-user', JSON.stringify(activeUser.value))\n } else {\n localStorage.removeItem('pagelines-user')\n }\n } catch (error) {\n this.logger.error('Failed to save user to localStorage', { data: error })\n }\n }\n }\n\n /**\n * Clear all stored user data and tokens\n */\n clearStorage(): void {\n if (typeof window === 'undefined')\n return\n\n cookieUtil.removeAuthToken()\n\n if (this.isLocalStorageFunctional()) {\n try {\n localStorage.removeItem('pagelines-user')\n } catch (error) {\n this.logger.error('Failed to clear user from localStorage', { data: error })\n }\n }\n\n // Clear global stores\n $globalActiveUser.set(undefined)\n $globalToken.set(null)\n }\n\n /**\n * Generic localStorage getter\n */\n getItem(key: string): string | null {\n if (!this.isLocalStorageFunctional())\n return null\n\n try {\n return localStorage.getItem(key)\n } catch (error) {\n this.logger.error('Failed to get item from localStorage', { key, error })\n return null\n }\n }\n\n /**\n * Generic localStorage setter\n */\n setItem(key: string, value: string): void {\n if (!this.isLocalStorageFunctional())\n return\n\n try {\n localStorage.setItem(key, value)\n } catch (error) {\n this.logger.error('Failed to set item in localStorage', { key, error })\n }\n }\n}\n","import type { AgentConfig } from '@pagelines/core'\nimport type { SDKContext } from './types'\nimport { resolveApiBase } from '../api'\n\nconst STATUS_MESSAGES = [\n 'Deploying your server...',\n 'Setting up your workspace...',\n 'Installing tools...',\n 'Almost ready...',\n]\n\nexport class AgentClient {\n constructor(private ctx: SDKContext) {}\n\n async create(args: { name: string, orgId?: string }): Promise<AgentConfig> {\n const orgId = args.orgId || this.resolveOrgId()\n const apiBase = resolveApiBase(this.ctx.apiBase, this.ctx.isDev)\n\n const response = await fetch(`${apiBase}/api/agent`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(this.ctx.token.value && { Authorization: `Bearer ${this.ctx.token.value}` }),\n },\n body: JSON.stringify({ name: args.name, orgId }),\n })\n\n const data = await response.json() as { ok: boolean, data?: AgentConfig[], error?: string }\n\n if (!data.ok || !data.data?.[0]) {\n const msg = data.error || 'Failed to create agent'\n this.ctx.error.value = msg\n throw new Error(msg)\n }\n\n this.ctx.processApiResponse(data as any)\n return data.data[0]\n }\n\n async getStatus(args: { agentId: string }): Promise<{\n status: string\n ready: boolean\n error?: string\n }> {\n const apiBase = resolveApiBase(this.ctx.apiBase, this.ctx.isDev)\n\n const response = await fetch(`${apiBase}/api/agent/${args.agentId}/status`, {\n headers: {\n ...(this.ctx.token.value && { Authorization: `Bearer ${this.ctx.token.value}` }),\n },\n })\n\n const data = await response.json() as { ok: boolean, data?: { status: string, ready: boolean, error?: string } }\n\n if (!data.ok || !data.data) {\n return { status: 'unknown', ready: false, error: 'Failed to check status' }\n }\n\n return data.data\n }\n\n async waitUntilReady(args: {\n agentId: string\n onStatus?: (message: string) => void\n timeoutMs?: number\n pollIntervalMs?: number\n }): Promise<void> {\n const { agentId, onStatus, timeoutMs = 300_000, pollIntervalMs = 3_000 } = args\n const start = Date.now()\n let messageIndex = 0\n\n while (Date.now() - start < timeoutMs) {\n const status = await this.getStatus({ agentId })\n\n if (status.ready) {\n onStatus?.('Ready!')\n return\n }\n\n if (status.status === 'error') {\n throw new Error(status.error || 'Provisioning failed')\n }\n\n if (onStatus && messageIndex < STATUS_MESSAGES.length) {\n onStatus(STATUS_MESSAGES[messageIndex]!)\n messageIndex++\n }\n\n await new Promise(r => setTimeout(r, pollIntervalMs))\n }\n\n throw new Error('Agent provisioning timed out — please try again')\n }\n\n /** Send a typed webhook event to a bot agent. No auth required — the proxy is public. */\n async webhook<T = Record<string, unknown>>(args: {\n agentId: string\n type: string\n data: T\n meta?: { source?: string, timestamp?: string, correlationId?: string, [key: string]: unknown }\n }): Promise<{ ok: boolean, error?: string }> {\n const apiBase = resolveApiBase(this.ctx.apiBase, this.ctx.isDev)\n const url = `${apiBase}/api/bot-api/agents/${args.agentId}/webhook`\n\n const body: Record<string, unknown> = { type: args.type, data: args.data }\n if (args.meta) body.meta = args.meta\n\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n })\n\n if (!res.ok) {\n const text = await res.text().catch(() => 'Unknown error')\n throw new Error(`Webhook delivery failed (${res.status}): ${text.slice(0, 200)}`)\n }\n\n return res.json() as Promise<{ ok: boolean, error?: string }>\n }\n\n private resolveOrgId(): string {\n const user = this.ctx.activeUser.value\n const orgId = user?.orgs?.[0]?.orgId\n if (!orgId) {\n throw new Error('No organization found. Please sign in first.')\n }\n return orgId\n }\n}\n","import type { EnrichedUser } from '@pagelines/core'\nimport type { SDKContext } from './types'\nimport { resolveApiBase } from '../api'\n\n/**\n * Run an async operation with loading/error state management.\n * Sets loading=true and error=null before, loading=false in finally.\n */\nasync function withLoadingState<T>(ctx: SDKContext, fn: () => Promise<T>): Promise<T> {\n ctx.loading.value = true\n ctx.error.value = null\n try {\n return await fn()\n } finally {\n ctx.loading.value = false\n }\n}\n\nexport class AuthClient {\n constructor(private ctx: SDKContext) {}\n\n async sendCode(email: string): Promise<void> {\n return withLoadingState(this.ctx, async () => {\n try {\n const response = await this.ctx.api.auth['check-email'].$post({\n json: { email },\n })\n const data = await response.json()\n if (!data.ok) {\n this.ctx.error.value = data.error\n throw new Error(data.error)\n }\n } catch (err) {\n this.ctx.logger.error('Send code error', { data: err })\n const errorMessage = err instanceof Error ? err.message : 'Failed to send verification code'\n this.ctx.error.value = errorMessage\n throw err\n }\n })\n }\n\n async verifyCode(email: string, code: string): Promise<void> {\n return withLoadingState(this.ctx, async () => {\n try {\n const response = await this.ctx.api.auth['verify-code'].$post({\n json: { email, code },\n })\n const data = await response.json()\n if (!data.ok) {\n this.ctx.error.value = data.error\n throw new Error(data.error)\n }\n } catch (err) {\n this.ctx.logger.error('Verify code error', { data: err })\n const errorMessage = err instanceof Error ? err.message : 'Failed to verify code'\n this.ctx.error.value = errorMessage\n throw err\n }\n })\n }\n\n async logout(): Promise<void> {\n return withLoadingState(this.ctx, async () => {\n try {\n await this.ctx.api.auth.logout.$post()\n } catch (err) {\n this.ctx.logger.error('Logout error (user still logged out locally)', { data: err })\n }\n // Always clear local state regardless of API success\n this.ctx.activeUser.value = undefined\n this.ctx.token.value = null\n this.ctx.storage.clearStorage()\n })\n }\n\n async getCurrentUser(): Promise<EnrichedUser | undefined> {\n if (!this.ctx.token.value) {\n return undefined\n }\n\n return withLoadingState(this.ctx, async () => {\n try {\n const response = await this.ctx.api.auth.me.$get()\n const data = await response.json()\n\n if (!data.ok) {\n this.ctx.error.value = data.error\n if (data.error.includes('Authentication')) {\n this.ctx.activeUser.value = undefined\n this.ctx.token.value = null\n this.ctx.storage.clearStorage()\n }\n return undefined\n }\n\n return data.user\n } catch (err) {\n this.ctx.logger.error('Get current user error', { data: err })\n this.ctx.error.value = err instanceof Error ? err.message : 'Failed to get user info'\n return undefined\n }\n })\n }\n\n async requestAuthCode(args: { email: string }): Promise<boolean> {\n return withLoadingState(this.ctx, async () => {\n try {\n const response = await this.ctx.api.auth['check-email'].$post({\n json: { email: args.email },\n })\n const data = await response.json()\n if (!data.ok) {\n this.ctx.error.value = data.error\n this.ctx.logger.error('Failed to request auth code', { email: args.email, error: data.error })\n return false\n }\n this.ctx.logger.info('Auth code requested successfully', { email: args.email })\n return true\n } catch (err) {\n this.ctx.logger.error('Request auth code error', { email: args.email, error: err })\n this.ctx.error.value = err instanceof Error ? err.message : 'Failed to request auth code'\n return false\n }\n })\n }\n\n async loginWithCode(args: {\n email: string\n code: string\n orgId?: string\n autoCreateContact?: boolean\n }): Promise<boolean> {\n return withLoadingState(this.ctx, async () => {\n try {\n const response = await this.ctx.api.auth['verify-code'].$post({\n json: { email: args.email, code: args.code },\n })\n const data = await response.json()\n if (!data.ok) {\n this.ctx.error.value = data.error\n this.ctx.logger.error('Login failed', { email: args.email, error: data.error })\n return false\n }\n this.ctx.logger.info('Login successful', { email: args.email })\n return true\n } catch (err) {\n this.ctx.logger.error('Login with code error', { email: args.email, error: err })\n this.ctx.error.value = err instanceof Error ? err.message : 'Login failed'\n return false\n }\n })\n }\n\n loginWithGoogle(args?: { onSuccess?: (user: EnrichedUser) => void, onError?: (error: string) => void }): void {\n if (typeof window === 'undefined') {\n this.ctx.logger.error('loginWithGoogle: Only available in browser')\n return\n }\n\n const apiBase = resolveApiBase(this.ctx.apiBase, this.ctx.isDev)\n const origin = window.location.origin\n const popupUrl = `${apiBase}/auth/google-popup?origin=${encodeURIComponent(origin)}`\n\n // Open centered popup\n const width = 500\n const height = 600\n const left = window.screenX + (window.outerWidth - width) / 2\n const top = window.screenY + (window.outerHeight - height) / 2\n const popup = window.open(\n popupUrl,\n 'google-auth',\n `width=${width},height=${height},left=${left},top=${top},popup=yes`,\n )\n\n if (!popup) {\n const msg = 'Popup was blocked. Please allow popups for this site.'\n this.ctx.error.value = msg\n args?.onError?.(msg)\n return\n }\n\n // Listen for postMessage from popup\n const handler = (event: MessageEvent) => {\n // Validate origin -- must be our API base\n const expectedOrigin = new URL(apiBase).origin\n if (event.origin !== expectedOrigin) return\n\n if (event.data?.type === 'auth-success') {\n window.removeEventListener('message', handler)\n const { token, user } = event.data\n\n // Process the auth response the same way as other login methods\n this.ctx.processApiResponse({ ok: true, data: {}, token, user })\n\n this.ctx.logger.info('Google login successful')\n args?.onSuccess?.(user)\n } else if (event.data?.type === 'auth-error') {\n window.removeEventListener('message', handler)\n const errorMsg = event.data.error || 'Google authentication failed'\n this.ctx.error.value = errorMsg\n this.ctx.logger.error('Google login failed', { error: errorMsg })\n args?.onError?.(errorMsg)\n }\n }\n\n window.addEventListener('message', handler)\n\n // Clean up listener if popup is closed without completing auth\n const checkClosed = setInterval(() => {\n if (popup.closed) {\n clearInterval(checkClosed)\n window.removeEventListener('message', handler)\n }\n }, 500)\n }\n}\n","import type { SDKContext } from './types'\nimport { resolveApiBase } from '../api'\n\nexport interface BillingStatus {\n plan?: string\n status: string\n hasActiveBilling: boolean\n maxAgents: number\n trialEnd?: string\n trialDaysRemaining?: number\n}\n\nexport class BillingClient {\n constructor(private ctx: SDKContext) {}\n\n async startTrial(args?: { returnUrl?: string, planKey?: string }): Promise<void> {\n const orgId = this.resolveOrgId()\n const apiBase = resolveApiBase(this.ctx.apiBase, this.ctx.isDev)\n\n const response = await fetch(`${apiBase}/api/billing/checkout/create`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(this.ctx.token.value && { Authorization: `Bearer ${this.ctx.token.value}` }),\n },\n body: JSON.stringify({\n orgId,\n ...(args?.returnUrl && { returnUrl: args.returnUrl }),\n ...(args?.planKey && { planKey: args.planKey }),\n }),\n })\n\n const data = await response.json() as { ok: boolean, data?: { url: string }, error?: string }\n\n if (!data.ok || !data.data?.url) {\n const msg = data.error || 'Failed to create checkout session'\n this.ctx.error.value = msg\n throw new Error(msg)\n }\n\n window.location.href = data.data.url\n }\n\n async confirmCheckout(_args?: { sessionId?: string }): Promise<BillingStatus> {\n return this.getStatus()\n }\n\n async getStatus(): Promise<BillingStatus> {\n const orgId = this.resolveOrgId()\n const apiBase = resolveApiBase(this.ctx.apiBase, this.ctx.isDev)\n\n const response = await fetch(`${apiBase}/api/billing/details/${orgId}`, {\n headers: {\n ...(this.ctx.token.value && { Authorization: `Bearer ${this.ctx.token.value}` }),\n },\n })\n\n const data = await response.json() as {\n ok: boolean\n data?: { plan: string, status: string, maxAgents: number, trialEnd?: string, trialDaysRemaining?: number }\n error?: string\n }\n\n if (!data.ok || !data.data) {\n return {\n plan: undefined,\n status: 'none',\n hasActiveBilling: false,\n maxAgents: 0,\n }\n }\n\n const ACTIVE_STATUSES = ['active', 'trialing']\n\n return {\n plan: data.data.plan,\n status: data.data.status,\n hasActiveBilling: ACTIVE_STATUSES.includes(data.data.status),\n maxAgents: data.data.maxAgents,\n ...(data.data.trialEnd && { trialEnd: data.data.trialEnd }),\n ...(data.data.trialDaysRemaining !== undefined && { trialDaysRemaining: data.data.trialDaysRemaining }),\n }\n }\n\n private resolveOrgId(): string {\n const user = this.ctx.activeUser.value\n const orgId = user?.orgs?.[0]?.orgId\n if (!orgId) {\n throw new Error('No organization found. Please sign in first.')\n }\n return orgId\n }\n}\n","import type { ApiResponse } from '@pagelines/core'\nimport type { SDKContext } from './types'\nimport { resolveApiBase } from '../api'\n\nexport class ChatClient {\n constructor(private ctx: SDKContext) {}\n\n async chatStream(args: {\n handle: string\n message: string\n attachments?: Array<{ type: string, url: string, name: string, mimeType: string, mediaId?: string }>\n conversationId?: string\n history?: Array<{ role: 'user' | 'assistant', content: string }>\n visitorId?: string\n context?: string\n onDelta: (text: string) => void\n onDone: (conversationId: string) => void\n onError: (error: string) => void\n onStatus?: (status: string) => void\n }): Promise<void> {\n const apiBase = resolveApiBase(this.ctx.apiBase, this.ctx.isDev)\n const url = `${apiBase}/api/agent/public/${encodeURIComponent(args.handle)}/chat/stream`\n\n return this._streamChat({\n url,\n headers: { 'Content-Type': 'application/json' },\n body: {\n message: args.message,\n conversationId: args.conversationId,\n history: args.history,\n visitorId: args.visitorId,\n context: args.context,\n attachments: args.attachments,\n },\n conversationId: args.conversationId,\n onDelta: args.onDelta,\n onDone: args.onDone,\n onError: args.onError,\n onStatus: args.onStatus,\n })\n }\n\n async chatStreamAuthenticated(args: {\n agentId: string\n message: string\n attachments?: Array<{ type: string, url: string, name: string, mimeType: string, mediaId?: string }>\n conversationId?: string\n history?: Array<{ role: 'user' | 'assistant', content: string }>\n onDelta: (text: string) => void\n onDone: (conversationId: string) => void\n onError: (error: string) => void\n onStatus?: (status: string) => void\n }): Promise<void> {\n const apiBase = resolveApiBase(this.ctx.apiBase, this.ctx.isDev)\n const url = `${apiBase}/api/agent/${encodeURIComponent(args.agentId)}/chat/stream`\n\n return this._streamChat({\n url,\n headers: {\n 'Content-Type': 'application/json',\n ...(this.ctx.token.value && { 'Authorization': `Bearer ${this.ctx.token.value}` }),\n },\n body: {\n message: args.message,\n conversationId: args.conversationId,\n history: args.history,\n attachments: args.attachments,\n },\n conversationId: args.conversationId,\n onDelta: args.onDelta,\n onDone: args.onDone,\n onError: args.onError,\n onStatus: args.onStatus,\n })\n }\n\n /** Shared SSE streaming logic for both public and authenticated chat */\n private async _streamChat(args: {\n url: string\n headers: Record<string, string>\n body: Record<string, unknown>\n conversationId?: string\n onDelta: (text: string) => void\n onDone: (conversationId: string) => void\n onError: (error: string) => void\n onStatus?: (status: string) => void\n }): Promise<void> {\n try {\n const response = await fetch(args.url, {\n method: 'POST',\n headers: args.headers,\n body: JSON.stringify(args.body),\n })\n\n if (!response.ok) {\n const errorBody = await response.json().catch(() => ({ error: 'Request failed' })) as { error?: string }\n args.onError(errorBody.error || `HTTP ${response.status}`)\n return\n }\n\n const reader = response.body?.getReader()\n if (!reader) {\n args.onError('No response stream')\n return\n }\n\n const decoder = new TextDecoder()\n let buffer = ''\n let resolvedConversationId = args.conversationId || ''\n\n while (true) {\n const { done, value } = await reader.read()\n if (done)\n break\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 data = line.slice(6).trim()\n if (data === '[DONE]') {\n args.onDone(resolvedConversationId)\n return\n }\n\n try {\n const chunk = JSON.parse(data) as {\n choices?: Array<{ delta?: { content?: string } }>\n pl_metadata?: { conversationId?: string }\n pl_status?: string\n }\n\n // Handle status events (e.g. \"Waking up...\")\n if (chunk.pl_status) {\n args.onStatus?.(chunk.pl_status)\n continue\n }\n\n if (chunk.pl_metadata?.conversationId) {\n resolvedConversationId = chunk.pl_metadata.conversationId\n }\n\n const delta = chunk.choices?.[0]?.delta\n if (delta?.content) {\n args.onDelta(delta.content)\n }\n } catch {\n // Skip malformed chunks\n }\n }\n }\n\n // Stream ended without [DONE]\n args.onDone(resolvedConversationId)\n } catch (error) {\n args.onError(error instanceof Error ? error.message : 'Stream failed')\n }\n }\n\n async chatMessage(args: {\n handle: string\n message: string\n conversationId?: string\n visitorId?: string\n context?: string\n }): Promise<{ conversationId: string, content: string } | undefined> {\n const apiBase = resolveApiBase(this.ctx.apiBase, this.ctx.isDev)\n const url = `${apiBase}/api/agent/public/${encodeURIComponent(args.handle)}/chat`\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n message: args.message,\n conversationId: args.conversationId,\n visitorId: args.visitorId,\n context: args.context,\n }),\n })\n\n const data = await response.json() as ApiResponse<{\n conversationId: string\n message: { role: 'assistant', content: string }\n }>\n\n if (!data.ok || !data.data) {\n this.ctx.logger.error('chatMessage failed', { error: !data.ok && 'error' in data ? data.error : 'Unknown' })\n return undefined\n }\n\n return {\n conversationId: data.data.conversationId,\n content: data.data.message.content,\n }\n } catch (err) {\n this.ctx.logger.error('chatMessage error', { error: err })\n return undefined\n }\n }\n}\n","import type { AgentConfig } from '@pagelines/core'\nimport { objectId } from '@pagelines/core'\nimport type { SDKContext } from './types'\n\nexport class UserClient {\n constructor(private ctx: SDKContext) {}\n\n async getPublicAgent(args: { handle: string }): Promise<AgentConfig | undefined> {\n this.ctx.loading.value = true\n this.ctx.error.value = null\n\n try {\n const response = await this.ctx.api.agent.public[':handle'].$get({\n param: { handle: args.handle },\n })\n\n const data = await response.json()\n\n if (!data.ok) {\n this.ctx.error.value = data.error\n this.ctx.logger.error('Failed to fetch public agent', { handle: args.handle, error: data.error })\n return undefined\n }\n\n return data.data\n } catch (err) {\n this.ctx.logger.error('Get public agent error', { handle: args.handle, error: err })\n this.ctx.error.value = err instanceof Error ? err.message : 'Failed to fetch agent'\n return undefined\n } finally {\n this.ctx.loading.value = false\n }\n }\n\n async getAgentByEmail(args: { email: string }): Promise<AgentConfig | undefined> {\n this.ctx.loading.value = true\n this.ctx.error.value = null\n\n try {\n const response = await this.ctx.api.agent['by-email'][':email'].$get({\n param: { email: args.email },\n })\n\n const data = await response.json()\n\n if (!data.ok) {\n this.ctx.error.value = data.error\n this.ctx.logger.error('Failed to fetch agent by email', { email: args.email, error: data.error })\n return undefined\n }\n\n return data.data\n } catch (err) {\n this.ctx.logger.error('Get agent by email error', { email: args.email, error: err })\n this.ctx.error.value = err instanceof Error ? err.message : 'Failed to fetch agent'\n return undefined\n } finally {\n this.ctx.loading.value = false\n }\n }\n\n generateAnonId(): string {\n const storageKey = 'pagelinesAnonId'\n let anonId = this.ctx.storage.getItem(storageKey)\n\n if (!anonId) {\n anonId = objectId({ prefix: 'anon' })\n this.ctx.storage.setItem(storageKey, anonId)\n }\n\n return anonId\n }\n\n track(args: {\n event: 'view_profile' | 'profile_interaction'\n agentId: string\n properties?: Record<string, any>\n }): void {\n try {\n // Track event via postMessage to parent window if embedded\n if (typeof window !== 'undefined' && window.parent !== window) {\n window.parent.postMessage({\n type: 'pagelines_track',\n event: args.event,\n agentId: args.agentId,\n properties: args.properties || {},\n }, '*')\n }\n\n this.ctx.logger.info('SDK event tracked', { event: args.event, agentId: args.agentId })\n } catch (err) {\n this.ctx.logger.error('Track event error', { error: err, args })\n }\n }\n}\n","import type { hc } from 'hono/client'\n// Use stub type for production builds (aliased in vite.config.sdk.ts)\n// Dev uses real SDKAppType from server via alias\nimport type { SDKAppType } from '@/modules/main/server'\nimport type { AgentConfig, EnrichedUser } from '@pagelines/core'\nimport type { ApiResponse } from '@pagelines/core'\nimport { objectId, SettingsObject } from '@pagelines/core'\nimport { computed, ref } from 'vue'\nimport { createApiClient } from './api'\nimport { SDKStorage } from './sdkStorage'\nimport { AgentClient } from './clients/AgentClient'\nimport { AuthClient } from './clients/AuthClient'\nimport { BillingClient } from './clients/BillingClient'\nimport { ChatClient } from './clients/ChatClient'\nimport { UserClient } from './clients/UserClient'\nimport type { SDKContext } from './clients/types'\n\nexport interface PageLinesSDKSettings {\n apiBase?: string\n isDev?: boolean\n [key: string]: unknown\n}\n\n/**\n * Browser-only singleton manager\n * Browser: Uses globalThis for cross-bundle singleton (www + widget)\n * Node.js SSR: No singleton - each request gets new instance (prevents request bleeding)\n */\nclass SDKGlobal {\n private key = '__PAGELINES_SDK__'\n\n get(): PageLinesSDK | undefined {\n if (typeof window === 'undefined')\n return undefined\n return (globalThis as any)[this.key]\n }\n\n set(instance: PageLinesSDK): void {\n if (typeof window !== 'undefined')\n (globalThis as any)[this.key] = instance\n }\n\n delete(): void {\n if (typeof window !== 'undefined')\n delete (globalThis as any)[this.key]\n }\n}\n\n// Module-scoped singleton manager\nconst sdkGlobal = new SDKGlobal()\n\nexport class PageLinesSDK extends SettingsObject<PageLinesSDKSettings> {\n /**\n * Get singleton instance in browser (creates if doesn't exist)\n * Node.js: Always creates new instance (no singleton)\n * Recommended: Use this instead of constructor for shared state\n */\n static getInstance(settings: PageLinesSDKSettings = {}): PageLinesSDK {\n // Browser: return singleton or create\n // Node: always create new (no singleton)\n return sdkGlobal.get() || new PageLinesSDK(settings)\n }\n\n // Vue reactive state\n activeUser = ref<EnrichedUser | undefined>()\n token = ref<string | null>(null)\n loading = ref(false)\n error = ref<string | null>(null)\n apiBase = this.settings.apiBase || undefined\n\n // Storage handler for persistence\n private storage = new SDKStorage()\n\n // Auto-managed session ID for usage tracking\n private sessionId = objectId({ prefix: 'ses' })\n\n get isDev() {\n return this.settings.isDev ?? (\n typeof window !== 'undefined'\n ? window.location.hostname === 'localhost' || window.location.hostname.includes('127.0.0.1')\n : false\n )\n }\n\n // Typed Hono RPC client - uses SDKAppType (auth/self/usage routes only)\n // Initialized in constructor (definite assignment via singleton pattern)\n private apiClient!: ReturnType<typeof hc<SDKAppType>>\n\n // Bypass stub typing for route access (production builds use SDKAppType stub)\n // Runtime types are validated via Zod at API boundaries\n private get api() {\n return (this.apiClient as any).api\n }\n\n // Computed properties derived from activeUser (matches UserClient pattern)\n currentAgent = computed(() => {\n const user = this.activeUser.value\n if (!user?.agents)\n return undefined\n\n const agentId = user.primaryAgentId || user.agents[0]?.agentId\n if (!agentId)\n return undefined\n\n return user.agents.find((a) => a.agentId === agentId)\n })\n\n currentOrg = computed(() => {\n const agent = this.currentAgent.value\n if (!agent?.orgId)\n return undefined\n\n const user = this.activeUser.value\n if (!user?.orgs)\n return undefined\n\n return user.orgs.find((org) => org.orgId === agent.orgId)\n })\n\n // Initialization state\n initialized?: Promise<EnrichedUser | undefined>\n resolveUser?: (value: EnrichedUser | undefined) => void\n\n // Sub-clients (new preferred API surface)\n readonly agent!: AgentClient\n readonly auth!: AuthClient\n readonly billing!: BillingClient\n readonly chat!: ChatClient\n readonly user!: UserClient\n\n constructor(settings: PageLinesSDKSettings = {}) {\n // Browser: return existing singleton\n // Node: always create new\n const existing = sdkGlobal.get()\n if (existing) {\n console.debug('[PageLinesSDK] Returning existing singleton instance')\n return existing\n }\n\n super('PageLinesSDK', settings)\n\n // Browser: set singleton reference (no-op in Node)\n sdkGlobal.set(this)\n\n // Create typed Hono RPC client with response handler\n this.apiClient = createApiClient<SDKAppType>(\n { isDev: this.isDev, apiBase: this.apiBase },\n this.processApiResponse.bind(this),\n )\n\n // Build shared context for sub-clients\n const ctx: SDKContext = {\n api: this.api,\n apiBase: this.apiBase,\n isDev: this.isDev,\n activeUser: this.activeUser,\n token: this.token,\n loading: this.loading,\n error: this.error,\n currentAgent: this.currentAgent,\n storage: this.storage,\n sessionId: this.sessionId,\n logger: this.logger,\n processApiResponse: this.processApiResponse.bind(this),\n }\n\n // Initialize sub-clients\n this.agent = new AgentClient(ctx)\n this.auth = new AuthClient(ctx)\n this.billing = new BillingClient(ctx)\n this.chat = new ChatClient(ctx)\n this.user = new UserClient(ctx)\n\n this.logger.info('PageLinesSDK initialized')\n\n // Initialize from storage using handler\n this.storage.loadFromStorage(this.activeUser, this.token)\n\n // Sync with global stores for persistence across navigation\n this.storage.syncWithGlobalStores(this.activeUser, this.token)\n\n // Set up initialization promise (same pattern as UserClient)\n this.initialized = new Promise((resolve) => {\n this.resolveUser = resolve\n })\n\n // Auto-fetch user if token exists (mirrors UserClient pattern)\n if (this.token.value && !this.activeUser.value) {\n this.getCurrentUser().then((user) => {\n if (this.resolveUser) {\n this.resolveUser(user)\n this.resolveUser = undefined\n }\n }).catch((err) => {\n this.logger.error('Auto user fetch failed', { data: err })\n if (this.resolveUser) {\n this.resolveUser(undefined)\n this.resolveUser = undefined\n }\n })\n } else if (this.activeUser.value) {\n // Resolve immediately if we already have a user from storage\n this.resolveUser?.(this.activeUser.value)\n } else {\n // No token, resolve with undefined\n this.resolveUser?.(undefined)\n }\n }\n\n // Process ApiResponse for automatic user/token updates - public for dependency injection\n processApiResponse(response: ApiResponse<any>): void {\n // Handle user updates\n if (response.ok && response.user) {\n this.activeUser.value = response.user\n this.logger.info('User updated from API response', { data: response.user })\n }\n\n // Handle token updates\n if (response.ok && response.token) {\n this.token.value = response.token\n this.storage.saveToStorage(this.activeUser, this.token)\n this.logger.info('Token updated from API response')\n }\n\n // Resolve initialization promise\n if (this.resolveUser && response.ok) {\n this.resolveUser(response.user)\n this.resolveUser = undefined\n }\n }\n\n // Clear all user data and tokens\n clearSession(): void {\n this.logger.info('Clearing session')\n this.activeUser.value = undefined\n this.token.value = null\n this.error.value = null\n this.storage.clearStorage()\n }\n\n // Full reset - clears session + state + destroys singleton\n clear(): void {\n this.logger.info('Clearing SDK completely')\n\n // 1. Clear session data\n this.clearSession()\n\n // 2. Reset other state\n this.loading.value = false\n this.sessionId = objectId({ prefix: 'ses' })\n\n // 3. Destroy singleton (no-op in Node)\n sdkGlobal.delete()\n }\n\n // Backward-compatible delegates — these forward to sub-clients\n // Can be removed in a future breaking change\n async sendCode(email: string): Promise<void> { return this.auth.sendCode(email) }\n async verifyCode(email: string, code: string): Promise<void> { return this.auth.verifyCode(email, code) }\n async logout(): Promise<void> { return this.auth.logout() }\n async getCurrentUser(): Promise<EnrichedUser | undefined> { return this.auth.getCurrentUser() }\n async requestAuthCode(args: { email: string }): Promise<boolean> { return this.auth.requestAuthCode(args) }\n async loginWithCode(args: { email: string, code: string, orgId?: string, autoCreateContact?: boolean }): Promise<boolean> { return this.auth.loginWithCode(args) }\n loginWithGoogle(args?: { onSuccess?: (user: EnrichedUser) => void, onError?: (error: string) => void }): void { return this.auth.loginWithGoogle(args) }\n\n async chatStream(args: Parameters<ChatClient['chatStream']>[0]): Promise<void> { return this.chat.chatStream(args) }\n async chatStreamAuthenticated(args: Parameters<ChatClient['chatStreamAuthenticated']>[0]): Promise<void> { return this.chat.chatStreamAuthenticated(args) }\n async chatMessage(args: Parameters<ChatClient['chatMessage']>[0]): Promise<{ conversationId: string, content: string } | undefined> { return this.chat.chatMessage(args) }\n\n async getPublicAgent(args: { handle: string }): Promise<AgentConfig | undefined> { return this.user.getPublicAgent(args) }\n async getAgentByEmail(args: { email: string }): Promise<AgentConfig | undefined> { return this.user.getAgentByEmail(args) }\n generateAnonId(): string { return this.user.generateAnonId() }\n track(args: Parameters<UserClient['track']>[0]): void { return this.user.track(args) }\n}\n"],"names":["resolveApiBase","apiBase","isDev","APP_PORT","APP_PROD_URL","__name","createApiClient","settings","responseHandler","baseUrl","hc","input","init","token","cookieUtil","response","originalJson","result","clean","listenerQueue","lqIndex","QUEUE_ITEMS_PER_LISTENER","atom","initialValue","listeners","$atom","listener","i","index","oldValue","changedKey","runListenerQueue","newValue","unbind","_g","$globalActiveUser","$globalToken","_SDKStorage","__publicField","createLogger","activeUser","storedUser","storedToken","watch","newUser","newToken","savedToken","savedUser","error","key","value","SDKStorage","STATUS_MESSAGES","_AgentClient","ctx","args","orgId","data","msg","agentId","onStatus","timeoutMs","pollIntervalMs","start","messageIndex","status","r","url","body","res","text","AgentClient","withLoadingState","fn","_AuthClient","email","err","errorMessage","code","origin","popupUrl","width","height","left","top","popup","handler","event","expectedOrigin","user","errorMsg","checkClosed","AuthClient","_BillingClient","_args","ACTIVE_STATUSES","BillingClient","_ChatClient","errorBody","reader","decoder","buffer","resolvedConversationId","done","lines","line","chunk","delta","ChatClient","_UserClient","storageKey","anonId","objectId","UserClient","_SDKGlobal","instance","SDKGlobal","sdkGlobal","_PageLinesSDK","SettingsObject","existing","ref","computed","a","agent","org","resolve","PageLinesSDK"],"mappings":";;;;;;;AAeO,SAASA,EAAeC,GAAkBC,GAAyB;AACxE,SAAOD,MAAYC,IAAQ,oBAAoBC,CAAQ,KAAKC;AAC9D;AAFgBC,EAAAL,GAAA;AAmBT,SAASM,GACdC,GACAC,GACiC;AACjC,QAAMC,IAAUT,EAAeO,EAAS,SAASA,EAAS,KAAK;AA2C/D,SAxCeG,GAAaD,GAAS;AAAA,IACnC,OAAO,gBAAAJ,EAAA,OAAOM,GAA0BC,MAAuB;AAC7D,YAAMC,IAAQC,EAAW,aAAA,GAEnBC,IAAW,MAAM,MAAMJ,GAAO;AAAA,QAClC,GAAGC;AAAA,QACH,SAAS;AAAA,UACP,GAAGA,GAAM;AAAA,UACT,gBAAgB;AAAA;AAAA,UAEhB,GAAIC,KAAS,EAAE,eAAiB,UAAUA,CAAK,GAAA;AAAA,QAAG;AAAA;AAAA,QAGpD,aAAa;AAAA,MAAA,CACd;AAGD,UAAIL,GAAiB;AAEnB,cAAMQ,IAAeD,EAAS,KAAK,KAAKA,CAAQ;AAGhD,QAAAA,EAAS,OAAO,YAAY;AAC1B,gBAAME,IAAS,MAAMD,EAAA;AAGrB,iBAAI,OAAOC,KAAW,YAAYA,MAAW,QACvC,QAAQA,MAAW,UAAUA,KAAU,WAAWA,MACpDT,EAAgBS,CAAM,GAInBA;AAAA,QACT;AAAA,MACF;AAEA,aAAOF;AAAA,IACT,GApCO;AAAA,EAoCP,CACD;AAGH;AAhDgBV,EAAAC,IAAA;AChCT,IAAIY,KAAQ,uBAAO,OAAO,GCA7BC,IAAgB,CAAA,GAChBC,IAAU;AACd,MAAMC,IAA2B,GAIpBC,IAAO,gBAAAjB,6BAAA,CAAAkB,MAAgB;AAClC,MAAIC,IAAY,CAAA,GACZC,IAAQ;AAAA,IACV,MAAM;AACJ,aAAKA,EAAM,MACTA,EAAM,OAAO,MAAM;AAAA,MAAC,CAAC,EAAC,GAEjBA,EAAM;AAAA,IACf;AAAA,IACA,MAAMF;AAAA,IACN,IAAI;AAAA,IACJ,OAAOG,GAAU;AACf,aAAAD,EAAM,KAAKD,EAAU,KAAKE,CAAQ,GAE3B,MAAM;AACX,iBACMC,IAAIP,IAAUC,GAClBM,IAAIR,EAAc;AAGlB,UAAIA,EAAcQ,CAAC,MAAMD,IACvBP,EAAc,OAAOQ,GAAGN,CAAwB,IAEhDM,KAAKN;AAIT,YAAIO,IAAQJ,EAAU,QAAQE,CAAQ;AACtC,QAAI,CAACE,MACHJ,EAAU,OAAOI,GAAO,CAAC,GACpB,EAAEH,EAAM,MAAIA,EAAM,IAAG;AAAA,MAE9B;AAAA,IACF;AAAA,IACA,OAAOI,GAAUC,GAAY;AAE3B,UAAIC,IAAmB,CAACZ,EAAc;AACtC,eAASO,KAAYF;AACnB,QAAAL,EAAc,KAAKO,GAAUD,EAAM,OAAOI,GAAUC,CAAU;AAGhE,UAAIC,GAAkB;AACpB,aACEX,IAAU,GACVA,IAAUD,EAAc,QACxBC,KAAWC;AAEX,UAAAF,EAAcC,CAAO;AAAA,YACnBD,EAAcC,IAAU,CAAC;AAAA,YACzBD,EAAcC,IAAU,CAAC;AAAA,YACzBD,EAAcC,IAAU,CAAC;AAAA,UACrC;AAEQ,QAAAD,EAAc,SAAS;AAAA,MACzB;AAAA,IACF;AAAA;AAAA;AAAA,IAGA,MAAM;AAAA,IAAC;AAAA,IACP,IAAIa,GAAU;AACZ,UAAIH,IAAWJ,EAAM;AACrB,MAAII,MAAaG,MACfP,EAAM,QAAQO,GACdP,EAAM,OAAOI,CAAQ;AAAA,IAEzB;AAAA,IACA,UAAUH,GAAU;AAClB,UAAIO,IAASR,EAAM,OAAOC,CAAQ;AAClC,aAAAA,EAASD,EAAM,KAAK,GACbQ;AAAA,IACT;AAAA,IACA,OAAOV;AAAA,EACX;AAEE,SAAI,QAAQ,IAAI,aAAa,iBAC3BE,EAAMP,EAAK,IAAI,MAAM;AACnB,IAAAM,IAAY,CAAA,GACZC,EAAM,KAAK,GACXA,EAAM,IAAG;AAAA,EACX,IAGKA;AACT,GAnFoB,SCDdS,IAAK,YACLC,IAAqBD,EAAG,qBAAHA,EAAG,mBAAqB,gBAAAZ,EAA+B,MAAS,IACrFc,IAAgBF,EAAG,sBAAHA,EAAG,oBAAsB,gBAAAZ,EAAoB,IAAI,IAQ1De,IAAN,MAAMA,EAAW;AAAA,EAAjB;AACG,IAAAC,EAAA,gBAASC,GAAa,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA,EAKlC,2BAAoC;AAC1C,WAAO,OAAO,SAAW,OACpB,OAAO,cAAc,WAAY,cACjC,OAAO,cAAc,WAAY,cACjC,OAAO,cAAc,cAAe;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,qBAAqBC,GAA2C3B,GAAiC;AAE/F,UAAM4B,IAAaN,EAAkB,IAAA,GAC/BO,IAAcN,EAAa,IAAA;AAEjC,IAAIK,MACFD,EAAW,QAAQC,IAEjBC,MACF7B,EAAM,QAAQ6B,IAIhBC,EAAMH,GAAY,CAACI,MAAY;AAC7B,MAAAT,EAAkB,IAAIS,CAAO;AAAA,IAC/B,GAAG,EAAE,WAAW,IAAM,GAEtBD,EAAM9B,GAAO,CAACgC,MAAa;AACzB,MAAAT,EAAa,IAAIS,CAAQ;AAAA,IAC3B,GAAG,EAAE,WAAW,IAAM,GAGtBV,EAAkB,UAAU,CAACS,MAAY;AACvC,MAAIA,MAAYJ,EAAW,UACzBA,EAAW,QAAQI;AAAA,IAEvB,CAAC,GAEDR,EAAa,UAAU,CAACS,MAAa;AACnC,MAAIA,MAAahC,EAAM,UACrBA,EAAM,QAAQgC;AAAA,IAElB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgBL,GAA2C3B,GAAiC;AAC1F,QAAI,OAAO,SAAW;AACpB;AAGF,UAAMiC,IAAahC,EAAW,aAAA;AAM9B,QALIgC,MACFjC,EAAM,QAAQiC,IAIZ,KAAK;AACP,UAAI;AACF,cAAMC,IAAY,aAAa,QAAQ,gBAAgB;AACvD,QAAIA,MACFP,EAAW,QAAQ,KAAK,MAAMO,CAAS;AAAA,MAE3C,SAASC,GAAO;AACd,aAAK,OAAO,MAAM,yCAAyC,EAAE,MAAMA,GAAO;AAAA,MAC5E;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA,EAKA,cAAcR,GAA2C3B,GAAiC;AACxF,QAAI,SAAO,SAAW,SAIlBA,EAAM,QACRC,EAAW,aAAaD,EAAM,KAAK,IAEnCC,EAAW,gBAAA,GAIT,KAAK;AACP,UAAI;AACF,QAAI0B,EAAW,QACb,aAAa,QAAQ,kBAAkB,KAAK,UAAUA,EAAW,KAAK,CAAC,IAEvE,aAAa,WAAW,gBAAgB;AAAA,MAE5C,SAASQ,GAAO;AACd,aAAK,OAAO,MAAM,uCAAuC,EAAE,MAAMA,GAAO;AAAA,MAC1E;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA,EAKA,eAAqB;AACnB,QAAI,SAAO,SAAW,MAKtB;AAAA,UAFAlC,EAAW,gBAAA,GAEP,KAAK;AACP,YAAI;AACF,uBAAa,WAAW,gBAAgB;AAAA,QAC1C,SAASkC,GAAO;AACd,eAAK,OAAO,MAAM,0CAA0C,EAAE,MAAMA,GAAO;AAAA,QAC7E;AAIF,MAAAb,EAAkB,IAAI,MAAS,GAC/BC,EAAa,IAAI,IAAI;AAAA;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQa,GAA4B;AAClC,QAAI,CAAC,KAAK,yBAAA;AACR,aAAO;AAET,QAAI;AACF,aAAO,aAAa,QAAQA,CAAG;AAAA,IACjC,SAASD,GAAO;AACd,kBAAK,OAAO,MAAM,wCAAwC,EAAE,KAAAC,GAAK,OAAAD,GAAO,GACjE;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQC,GAAaC,GAAqB;AACxC,QAAK,KAAK,yBAAA;AAGV,UAAI;AACF,qBAAa,QAAQD,GAAKC,CAAK;AAAA,MACjC,SAASF,GAAO;AACd,aAAK,OAAO,MAAM,sCAAsC,EAAE,KAAAC,GAAK,OAAAD,GAAO;AAAA,MACxE;AAAA,EACF;AACF;AA3JwB3C,EAAAgC,GAAA;AAAjB,IAAMc,IAANd;ACbP,MAAMe,IAAkB;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAEaC,IAAN,MAAMA,EAAY;AAAA,EACvB,YAAoBC,GAAiB;AAAjB,IAAAhB,EAAA;AAAA,SAAA,MAAAgB;AAAA,EAAkB;AAAA,EAEtC,MAAM,OAAOC,GAA8D;AACzE,UAAMC,IAAQD,EAAK,SAAS,KAAK,aAAA,GAC3BtD,IAAUD,EAAe,KAAK,IAAI,SAAS,KAAK,IAAI,KAAK,GAWzDyD,IAAO,OATI,MAAM,MAAM,GAAGxD,CAAO,cAAc;AAAA,MACnD,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,GAAI,KAAK,IAAI,MAAM,SAAS,EAAE,eAAe,UAAU,KAAK,IAAI,MAAM,KAAK,GAAA;AAAA,MAAG;AAAA,MAEhF,MAAM,KAAK,UAAU,EAAE,MAAMsD,EAAK,MAAM,OAAAC,GAAO;AAAA,IAAA,CAChD,GAE2B,KAAA;AAE5B,QAAI,CAACC,EAAK,MAAM,CAACA,EAAK,OAAO,CAAC,GAAG;AAC/B,YAAMC,IAAMD,EAAK,SAAS;AAC1B,iBAAK,IAAI,MAAM,QAAQC,GACjB,IAAI,MAAMA,CAAG;AAAA,IACrB;AAEA,gBAAK,IAAI,mBAAmBD,CAAW,GAChCA,EAAK,KAAK,CAAC;AAAA,EACpB;AAAA,EAEA,MAAM,UAAUF,GAIb;AACD,UAAMtD,IAAUD,EAAe,KAAK,IAAI,SAAS,KAAK,IAAI,KAAK,GAQzDyD,IAAO,OANI,MAAM,MAAM,GAAGxD,CAAO,cAAcsD,EAAK,OAAO,WAAW;AAAA,MAC1E,SAAS;AAAA,QACP,GAAI,KAAK,IAAI,MAAM,SAAS,EAAE,eAAe,UAAU,KAAK,IAAI,MAAM,KAAK,GAAA;AAAA,MAAG;AAAA,IAChF,CACD,GAE2B,KAAA;AAE5B,WAAI,CAACE,EAAK,MAAM,CAACA,EAAK,OACb,EAAE,QAAQ,WAAW,OAAO,IAAO,OAAO,yBAAA,IAG5CA,EAAK;AAAA,EACd;AAAA,EAEA,MAAM,eAAeF,GAKH;AAChB,UAAM,EAAE,SAAAI,GAAS,UAAAC,GAAU,WAAAC,IAAY,KAAS,gBAAAC,IAAiB,QAAUP,GACrEQ,IAAQ,KAAK,IAAA;AACnB,QAAIC,IAAe;AAEnB,WAAO,KAAK,QAAQD,IAAQF,KAAW;AACrC,YAAMI,IAAS,MAAM,KAAK,UAAU,EAAE,SAAAN,GAAS;AAE/C,UAAIM,EAAO,OAAO;AAChB,QAAAL,IAAW,QAAQ;AACnB;AAAA,MACF;AAEA,UAAIK,EAAO,WAAW;AACpB,cAAM,IAAI,MAAMA,EAAO,SAAS,qBAAqB;AAGvD,MAAIL,KAAYI,IAAeZ,EAAgB,WAC7CQ,EAASR,EAAgBY,CAAY,CAAE,GACvCA,MAGF,MAAM,IAAI,QAAQ,CAAAE,MAAK,WAAWA,GAAGJ,CAAc,CAAC;AAAA,IACtD;AAEA,UAAM,IAAI,MAAM,iDAAiD;AAAA,EACnE;AAAA;AAAA,EAGA,MAAM,QAAqCP,GAKE;AAE3C,UAAMY,IAAM,GADInE,EAAe,KAAK,IAAI,SAAS,KAAK,IAAI,KAAK,CACzC,uBAAuBuD,EAAK,OAAO,YAEnDa,IAAgC,EAAE,MAAMb,EAAK,MAAM,MAAMA,EAAK,KAAA;AACpE,IAAIA,EAAK,SAAMa,EAAK,OAAOb,EAAK;AAEhC,UAAMc,IAAM,MAAM,MAAMF,GAAK;AAAA,MAC3B,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAA;AAAA,MAC3B,MAAM,KAAK,UAAUC,CAAI;AAAA,IAAA,CAC1B;AAED,QAAI,CAACC,EAAI,IAAI;AACX,YAAMC,IAAO,MAAMD,EAAI,OAAO,MAAM,MAAM,eAAe;AACzD,YAAM,IAAI,MAAM,4BAA4BA,EAAI,MAAM,MAAMC,EAAK,MAAM,GAAG,GAAG,CAAC,EAAE;AAAA,IAClF;AAEA,WAAOD,EAAI,KAAA;AAAA,EACb;AAAA,EAEQ,eAAuB;AAE7B,UAAMb,IADO,KAAK,IAAI,WAAW,OACb,OAAO,CAAC,GAAG;AAC/B,QAAI,CAACA;AACH,YAAM,IAAI,MAAM,8CAA8C;AAEhE,WAAOA;AAAA,EACT;AACF;AAtHyBnD,EAAAgD,GAAA;AAAlB,IAAMkB,IAANlB;ACHP,eAAemB,EAAoBlB,GAAiBmB,GAAkC;AACpF,EAAAnB,EAAI,QAAQ,QAAQ,IACpBA,EAAI,MAAM,QAAQ;AAClB,MAAI;AACF,WAAO,MAAMmB,EAAA;AAAA,EACf,UAAA;AACE,IAAAnB,EAAI,QAAQ,QAAQ;AAAA,EACtB;AACF;AARejD,EAAAmE,GAAA;AAUR,MAAME,IAAN,MAAMA,EAAW;AAAA,EACtB,YAAoBpB,GAAiB;AAAjB,IAAAhB,EAAA;AAAA,SAAA,MAAAgB;AAAA,EAAkB;AAAA,EAEtC,MAAM,SAASqB,GAA8B;AAC3C,WAAOH,EAAiB,KAAK,KAAK,YAAY;AAC5C,UAAI;AAIF,cAAMf,IAAO,OAHI,MAAM,KAAK,IAAI,IAAI,KAAK,aAAa,EAAE,MAAM;AAAA,UAC5D,MAAM,EAAE,OAAAkB,EAAA;AAAA,QAAM,CACf,GAC2B,KAAA;AAC5B,YAAI,CAAClB,EAAK;AACR,qBAAK,IAAI,MAAM,QAAQA,EAAK,OACtB,IAAI,MAAMA,EAAK,KAAK;AAAA,MAE9B,SAASmB,GAAK;AACZ,aAAK,IAAI,OAAO,MAAM,mBAAmB,EAAE,MAAMA,GAAK;AACtD,cAAMC,IAAeD,aAAe,QAAQA,EAAI,UAAU;AAC1D,mBAAK,IAAI,MAAM,QAAQC,GACjBD;AAAA,MACR;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,WAAWD,GAAeG,GAA6B;AAC3D,WAAON,EAAiB,KAAK,KAAK,YAAY;AAC5C,UAAI;AAIF,cAAMf,IAAO,OAHI,MAAM,KAAK,IAAI,IAAI,KAAK,aAAa,EAAE,MAAM;AAAA,UAC5D,MAAM,EAAE,OAAAkB,GAAO,MAAAG,EAAA;AAAA,QAAK,CACrB,GAC2B,KAAA;AAC5B,YAAI,CAACrB,EAAK;AACR,qBAAK,IAAI,MAAM,QAAQA,EAAK,OACtB,IAAI,MAAMA,EAAK,KAAK;AAAA,MAE9B,SAASmB,GAAK;AACZ,aAAK,IAAI,OAAO,MAAM,qBAAqB,EAAE,MAAMA,GAAK;AACxD,cAAMC,IAAeD,aAAe,QAAQA,EAAI,UAAU;AAC1D,mBAAK,IAAI,MAAM,QAAQC,GACjBD;AAAA,MACR;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,SAAwB;AAC5B,WAAOJ,EAAiB,KAAK,KAAK,YAAY;AAC5C,UAAI;AACF,cAAM,KAAK,IAAI,IAAI,KAAK,OAAO,MAAA;AAAA,MACjC,SAASI,GAAK;AACZ,aAAK,IAAI,OAAO,MAAM,gDAAgD,EAAE,MAAMA,GAAK;AAAA,MACrF;AAEA,WAAK,IAAI,WAAW,QAAQ,QAC5B,KAAK,IAAI,MAAM,QAAQ,MACvB,KAAK,IAAI,QAAQ,aAAA;AAAA,IACnB,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,iBAAoD;AACxD,QAAK,KAAK,IAAI,MAAM;AAIpB,aAAOJ,EAAiB,KAAK,KAAK,YAAY;AAC5C,YAAI;AAEF,gBAAMf,IAAO,OADI,MAAM,KAAK,IAAI,IAAI,KAAK,GAAG,KAAA,GAChB,KAAA;AAE5B,cAAI,CAACA,EAAK,IAAI;AACZ,iBAAK,IAAI,MAAM,QAAQA,EAAK,OACxBA,EAAK,MAAM,SAAS,gBAAgB,MACtC,KAAK,IAAI,WAAW,QAAQ,QAC5B,KAAK,IAAI,MAAM,QAAQ,MACvB,KAAK,IAAI,QAAQ,aAAA;AAEnB;AAAA,UACF;AAEA,iBAAOA,EAAK;AAAA,QACd,SAASmB,GAAK;AACZ,eAAK,IAAI,OAAO,MAAM,0BAA0B,EAAE,MAAMA,GAAK,GAC7D,KAAK,IAAI,MAAM,QAAQA,aAAe,QAAQA,EAAI,UAAU;AAC5D;AAAA,QACF;AAAA,MACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,gBAAgBrB,GAA2C;AAC/D,WAAOiB,EAAiB,KAAK,KAAK,YAAY;AAC5C,UAAI;AAIF,cAAMf,IAAO,OAHI,MAAM,KAAK,IAAI,IAAI,KAAK,aAAa,EAAE,MAAM;AAAA,UAC5D,MAAM,EAAE,OAAOF,EAAK,MAAA;AAAA,QAAM,CAC3B,GAC2B,KAAA;AAC5B,eAAKE,EAAK,MAKV,KAAK,IAAI,OAAO,KAAK,oCAAoC,EAAE,OAAOF,EAAK,OAAO,GACvE,OALL,KAAK,IAAI,MAAM,QAAQE,EAAK,OAC5B,KAAK,IAAI,OAAO,MAAM,+BAA+B,EAAE,OAAOF,EAAK,OAAO,OAAOE,EAAK,MAAA,CAAO,GACtF;AAAA,MAIX,SAASmB,GAAK;AACZ,oBAAK,IAAI,OAAO,MAAM,2BAA2B,EAAE,OAAOrB,EAAK,OAAO,OAAOqB,EAAA,CAAK,GAClF,KAAK,IAAI,MAAM,QAAQA,aAAe,QAAQA,EAAI,UAAU,+BACrD;AAAA,MACT;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,cAAcrB,GAKC;AACnB,WAAOiB,EAAiB,KAAK,KAAK,YAAY;AAC5C,UAAI;AAIF,cAAMf,IAAO,OAHI,MAAM,KAAK,IAAI,IAAI,KAAK,aAAa,EAAE,MAAM;AAAA,UAC5D,MAAM,EAAE,OAAOF,EAAK,OAAO,MAAMA,EAAK,KAAA;AAAA,QAAK,CAC5C,GAC2B,KAAA;AAC5B,eAAKE,EAAK,MAKV,KAAK,IAAI,OAAO,KAAK,oBAAoB,EAAE,OAAOF,EAAK,OAAO,GACvD,OALL,KAAK,IAAI,MAAM,QAAQE,EAAK,OAC5B,KAAK,IAAI,OAAO,MAAM,gBAAgB,EAAE,OAAOF,EAAK,OAAO,OAAOE,EAAK,MAAA,CAAO,GACvE;AAAA,MAIX,SAASmB,GAAK;AACZ,oBAAK,IAAI,OAAO,MAAM,yBAAyB,EAAE,OAAOrB,EAAK,OAAO,OAAOqB,EAAA,CAAK,GAChF,KAAK,IAAI,MAAM,QAAQA,aAAe,QAAQA,EAAI,UAAU,gBACrD;AAAA,MACT;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,gBAAgBrB,GAA8F;AAC5G,QAAI,OAAO,SAAW,KAAa;AACjC,WAAK,IAAI,OAAO,MAAM,4CAA4C;AAClE;AAAA,IACF;AAEA,UAAMtD,IAAUD,EAAe,KAAK,IAAI,SAAS,KAAK,IAAI,KAAK,GACzD+E,IAAS,OAAO,SAAS,QACzBC,IAAW,GAAG/E,CAAO,6BAA6B,mBAAmB8E,CAAM,CAAC,IAG5EE,IAAQ,KACRC,IAAS,KACTC,IAAO,OAAO,WAAW,OAAO,aAAaF,KAAS,GACtDG,IAAM,OAAO,WAAW,OAAO,cAAcF,KAAU,GACvDG,IAAQ,OAAO;AAAA,MACnBL;AAAA,MACA;AAAA,MACA,SAASC,CAAK,WAAWC,CAAM,SAASC,CAAI,QAAQC,CAAG;AAAA,IAAA;AAGzD,QAAI,CAACC,GAAO;AACV,YAAM3B,IAAM;AACZ,WAAK,IAAI,MAAM,QAAQA,GACvBH,GAAM,UAAUG,CAAG;AACnB;AAAA,IACF;AAGA,UAAM4B,IAAU,gBAAAjF,EAAA,CAACkF,MAAwB;AAEvC,YAAMC,IAAiB,IAAI,IAAIvF,CAAO,EAAE;AACxC,UAAIsF,EAAM,WAAWC;AAErB,YAAID,EAAM,MAAM,SAAS,gBAAgB;AACvC,iBAAO,oBAAoB,WAAWD,CAAO;AAC7C,gBAAM,EAAE,OAAAzE,GAAO,MAAA4E,EAAA,IAASF,EAAM;AAG9B,eAAK,IAAI,mBAAmB,EAAE,IAAI,IAAM,MAAM,CAAA,GAAI,OAAA1E,GAAO,MAAA4E,GAAM,GAE/D,KAAK,IAAI,OAAO,KAAK,yBAAyB,GAC9ClC,GAAM,YAAYkC,CAAI;AAAA,QACxB,WAAWF,EAAM,MAAM,SAAS,cAAc;AAC5C,iBAAO,oBAAoB,WAAWD,CAAO;AAC7C,gBAAMI,IAAWH,EAAM,KAAK,SAAS;AACrC,eAAK,IAAI,MAAM,QAAQG,GACvB,KAAK,IAAI,OAAO,MAAM,uBAAuB,EAAE,OAAOA,GAAU,GAChEnC,GAAM,UAAUmC,CAAQ;AAAA,QAC1B;AAAA;AAAA,IACF,GArBgB;AAuBhB,WAAO,iBAAiB,WAAWJ,CAAO;AAG1C,UAAMK,IAAc,YAAY,MAAM;AACpC,MAAIN,EAAM,WACR,cAAcM,CAAW,GACzB,OAAO,oBAAoB,WAAWL,CAAO;AAAA,IAEjD,GAAG,GAAG;AAAA,EACR;AACF;AArMwBjF,EAAAqE,GAAA;AAAjB,IAAMkB,IAANlB;ACNA,MAAMmB,IAAN,MAAMA,EAAc;AAAA,EACzB,YAAoBvC,GAAiB;AAAjB,IAAAhB,EAAA;AAAA,SAAA,MAAAgB;AAAA,EAAkB;AAAA,EAEtC,MAAM,WAAWC,GAAgE;AAC/E,UAAMC,IAAQ,KAAK,aAAA,GACbvD,IAAUD,EAAe,KAAK,IAAI,SAAS,KAAK,IAAI,KAAK,GAezDyD,IAAO,OAbI,MAAM,MAAM,GAAGxD,CAAO,gCAAgC;AAAA,MACrE,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,GAAI,KAAK,IAAI,MAAM,SAAS,EAAE,eAAe,UAAU,KAAK,IAAI,MAAM,KAAK,GAAA;AAAA,MAAG;AAAA,MAEhF,MAAM,KAAK,UAAU;AAAA,QACnB,OAAAuD;AAAA,QACA,GAAID,GAAM,aAAa,EAAE,WAAWA,EAAK,UAAA;AAAA,QACzC,GAAIA,GAAM,WAAW,EAAE,SAASA,EAAK,QAAA;AAAA,MAAQ,CAC9C;AAAA,IAAA,CACF,GAE2B,KAAA;AAE5B,QAAI,CAACE,EAAK,MAAM,CAACA,EAAK,MAAM,KAAK;AAC/B,YAAMC,IAAMD,EAAK,SAAS;AAC1B,iBAAK,IAAI,MAAM,QAAQC,GACjB,IAAI,MAAMA,CAAG;AAAA,IACrB;AAEA,WAAO,SAAS,OAAOD,EAAK,KAAK;AAAA,EACnC;AAAA,EAEA,MAAM,gBAAgBqC,GAAwD;AAC5E,WAAO,KAAK,UAAA;AAAA,EACd;AAAA,EAEA,MAAM,YAAoC;AACxC,UAAMtC,IAAQ,KAAK,aAAA,GACbvD,IAAUD,EAAe,KAAK,IAAI,SAAS,KAAK,IAAI,KAAK,GAQzDyD,IAAO,OANI,MAAM,MAAM,GAAGxD,CAAO,wBAAwBuD,CAAK,IAAI;AAAA,MACtE,SAAS;AAAA,QACP,GAAI,KAAK,IAAI,MAAM,SAAS,EAAE,eAAe,UAAU,KAAK,IAAI,MAAM,KAAK,GAAA;AAAA,MAAG;AAAA,IAChF,CACD,GAE2B,KAAA;AAM5B,QAAI,CAACC,EAAK,MAAM,CAACA,EAAK;AACpB,aAAO;AAAA,QACL,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,kBAAkB;AAAA,QAClB,WAAW;AAAA,MAAA;AAIf,UAAMsC,IAAkB,CAAC,UAAU,UAAU;AAE7C,WAAO;AAAA,MACL,MAAMtC,EAAK,KAAK;AAAA,MAChB,QAAQA,EAAK,KAAK;AAAA,MAClB,kBAAkBsC,EAAgB,SAAStC,EAAK,KAAK,MAAM;AAAA,MAC3D,WAAWA,EAAK,KAAK;AAAA,MACrB,GAAIA,EAAK,KAAK,YAAY,EAAE,UAAUA,EAAK,KAAK,SAAA;AAAA,MAChD,GAAIA,EAAK,KAAK,uBAAuB,UAAa,EAAE,oBAAoBA,EAAK,KAAK,mBAAA;AAAA,IAAmB;AAAA,EAEzG;AAAA,EAEQ,eAAuB;AAE7B,UAAMD,IADO,KAAK,IAAI,WAAW,OACb,OAAO,CAAC,GAAG;AAC/B,QAAI,CAACA;AACH,YAAM,IAAI,MAAM,8CAA8C;AAEhE,WAAOA;AAAA,EACT;AACF;AAhF2BnD,EAAAwF,GAAA;AAApB,IAAMG,IAANH;ACRA,MAAMI,IAAN,MAAMA,EAAW;AAAA,EACtB,YAAoB3C,GAAiB;AAAjB,IAAAhB,EAAA;AAAA,SAAA,MAAAgB;AAAA,EAAkB;AAAA,EAEtC,MAAM,WAAWC,GAYC;AAEhB,UAAMY,IAAM,GADInE,EAAe,KAAK,IAAI,SAAS,KAAK,IAAI,KAAK,CACzC,qBAAqB,mBAAmBuD,EAAK,MAAM,CAAC;AAE1E,WAAO,KAAK,YAAY;AAAA,MACtB,KAAAY;AAAA,MACA,SAAS,EAAE,gBAAgB,mBAAA;AAAA,MAC3B,MAAM;AAAA,QACJ,SAASZ,EAAK;AAAA,QACd,gBAAgBA,EAAK;AAAA,QACrB,SAASA,EAAK;AAAA,QACd,WAAWA,EAAK;AAAA,QAChB,SAASA,EAAK;AAAA,QACd,aAAaA,EAAK;AAAA,MAAA;AAAA,MAEpB,gBAAgBA,EAAK;AAAA,MACrB,SAASA,EAAK;AAAA,MACd,QAAQA,EAAK;AAAA,MACb,SAASA,EAAK;AAAA,MACd,UAAUA,EAAK;AAAA,IAAA,CAChB;AAAA,EACH;AAAA,EAEA,MAAM,wBAAwBA,GAUZ;AAEhB,UAAMY,IAAM,GADInE,EAAe,KAAK,IAAI,SAAS,KAAK,IAAI,KAAK,CACzC,cAAc,mBAAmBuD,EAAK,OAAO,CAAC;AAEpE,WAAO,KAAK,YAAY;AAAA,MACtB,KAAAY;AAAA,MACA,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,GAAI,KAAK,IAAI,MAAM,SAAS,EAAE,eAAiB,UAAU,KAAK,IAAI,MAAM,KAAK,GAAA;AAAA,MAAG;AAAA,MAElF,MAAM;AAAA,QACJ,SAASZ,EAAK;AAAA,QACd,gBAAgBA,EAAK;AAAA,QACrB,SAASA,EAAK;AAAA,QACd,aAAaA,EAAK;AAAA,MAAA;AAAA,MAEpB,gBAAgBA,EAAK;AAAA,MACrB,SAASA,EAAK;AAAA,MACd,QAAQA,EAAK;AAAA,MACb,SAASA,EAAK;AAAA,MACd,UAAUA,EAAK;AAAA,IAAA,CAChB;AAAA,EACH;AAAA;AAAA,EAGA,MAAc,YAAYA,GASR;AAChB,QAAI;AACF,YAAMxC,IAAW,MAAM,MAAMwC,EAAK,KAAK;AAAA,QACrC,QAAQ;AAAA,QACR,SAASA,EAAK;AAAA,QACd,MAAM,KAAK,UAAUA,EAAK,IAAI;AAAA,MAAA,CAC/B;AAED,UAAI,CAACxC,EAAS,IAAI;AAChB,cAAMmF,IAAY,MAAMnF,EAAS,KAAA,EAAO,MAAM,OAAO,EAAE,OAAO,iBAAA,EAAmB;AACjF,QAAAwC,EAAK,QAAQ2C,EAAU,SAAS,QAAQnF,EAAS,MAAM,EAAE;AACzD;AAAA,MACF;AAEA,YAAMoF,IAASpF,EAAS,MAAM,UAAA;AAC9B,UAAI,CAACoF,GAAQ;AACX,QAAA5C,EAAK,QAAQ,oBAAoB;AACjC;AAAA,MACF;AAEA,YAAM6C,IAAU,IAAI,YAAA;AACpB,UAAIC,IAAS,IACTC,IAAyB/C,EAAK,kBAAkB;AAEpD,iBAAa;AACX,cAAM,EAAE,MAAAgD,GAAM,OAAArD,EAAA,IAAU,MAAMiD,EAAO,KAAA;AACrC,YAAII;AACF;AAEF,QAAAF,KAAUD,EAAQ,OAAOlD,GAAO,EAAE,QAAQ,IAAM;AAChD,cAAMsD,IAAQH,EAAO,MAAM;AAAA,CAAI;AAC/B,QAAAA,IAASG,EAAM,SAAS;AAExB,mBAAWC,KAAQD,GAAO;AACxB,cAAI,CAACC,EAAK,WAAW,QAAQ;AAC3B;AAEF,gBAAMhD,IAAOgD,EAAK,MAAM,CAAC,EAAE,KAAA;AAC3B,cAAIhD,MAAS,UAAU;AACrB,YAAAF,EAAK,OAAO+C,CAAsB;AAClC;AAAA,UACF;AAEA,cAAI;AACF,kBAAMI,IAAQ,KAAK,MAAMjD,CAAI;AAO7B,gBAAIiD,EAAM,WAAW;AACnB,cAAAnD,EAAK,WAAWmD,EAAM,SAAS;AAC/B;AAAA,YACF;AAEA,YAAIA,EAAM,aAAa,mBACrBJ,IAAyBI,EAAM,YAAY;AAG7C,kBAAMC,IAAQD,EAAM,UAAU,CAAC,GAAG;AAClC,YAAIC,GAAO,WACTpD,EAAK,QAAQoD,EAAM,OAAO;AAAA,UAE9B,QAAQ;AAAA,UAER;AAAA,QACF;AAAA,MACF;AAGA,MAAApD,EAAK,OAAO+C,CAAsB;AAAA,IACpC,SAAStD,GAAO;AACd,MAAAO,EAAK,QAAQP,aAAiB,QAAQA,EAAM,UAAU,eAAe;AAAA,IACvE;AAAA,EACF;AAAA,EAEA,MAAM,YAAYO,GAMmD;AAEnE,UAAMY,IAAM,GADInE,EAAe,KAAK,IAAI,SAAS,KAAK,IAAI,KAAK,CACzC,qBAAqB,mBAAmBuD,EAAK,MAAM,CAAC;AAE1E,QAAI;AAYF,YAAME,IAAO,OAXI,MAAM,MAAMU,GAAK;AAAA,QAChC,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAA;AAAA,QAC3B,MAAM,KAAK,UAAU;AAAA,UACnB,SAASZ,EAAK;AAAA,UACd,gBAAgBA,EAAK;AAAA,UACrB,WAAWA,EAAK;AAAA,UAChB,SAASA,EAAK;AAAA,QAAA,CACf;AAAA,MAAA,CACF,GAE2B,KAAA;AAK5B,UAAI,CAACE,EAAK,MAAM,CAACA,EAAK,MAAM;AAC1B,aAAK,IAAI,OAAO,MAAM,sBAAsB,EAAE,OAAO,CAACA,EAAK,MAAM,WAAWA,IAAOA,EAAK,QAAQ,WAAW;AAC3G;AAAA,MACF;AAEA,aAAO;AAAA,QACL,gBAAgBA,EAAK,KAAK;AAAA,QAC1B,SAASA,EAAK,KAAK,QAAQ;AAAA,MAAA;AAAA,IAE/B,SAASmB,GAAK;AACZ,WAAK,IAAI,OAAO,MAAM,qBAAqB,EAAE,OAAOA,GAAK;AACzD;AAAA,IACF;AAAA,EACF;AACF;AAxMwBvE,EAAA4F,GAAA;AAAjB,IAAMW,IAANX;ACAA,MAAMY,IAAN,MAAMA,EAAW;AAAA,EACtB,YAAoBvD,GAAiB;AAAjB,IAAAhB,EAAA;AAAA,SAAA,MAAAgB;AAAA,EAAkB;AAAA,EAEtC,MAAM,eAAeC,GAA4D;AAC/E,SAAK,IAAI,QAAQ,QAAQ,IACzB,KAAK,IAAI,MAAM,QAAQ;AAEvB,QAAI;AAKF,YAAME,IAAO,OAJI,MAAM,KAAK,IAAI,IAAI,MAAM,OAAO,SAAS,EAAE,KAAK;AAAA,QAC/D,OAAO,EAAE,QAAQF,EAAK,OAAA;AAAA,MAAO,CAC9B,GAE2B,KAAA;AAE5B,UAAI,CAACE,EAAK,IAAI;AACZ,aAAK,IAAI,MAAM,QAAQA,EAAK,OAC5B,KAAK,IAAI,OAAO,MAAM,gCAAgC,EAAE,QAAQF,EAAK,QAAQ,OAAOE,EAAK,MAAA,CAAO;AAChG;AAAA,MACF;AAEA,aAAOA,EAAK;AAAA,IACd,SAASmB,GAAK;AACZ,WAAK,IAAI,OAAO,MAAM,0BAA0B,EAAE,QAAQrB,EAAK,QAAQ,OAAOqB,EAAA,CAAK,GACnF,KAAK,IAAI,MAAM,QAAQA,aAAe,QAAQA,EAAI,UAAU;AAC5D;AAAA,IACF,UAAA;AACE,WAAK,IAAI,QAAQ,QAAQ;AAAA,IAC3B;AAAA,EACF;AAAA,EAEA,MAAM,gBAAgBrB,GAA2D;AAC/E,SAAK,IAAI,QAAQ,QAAQ,IACzB,KAAK,IAAI,MAAM,QAAQ;AAEvB,QAAI;AAKF,YAAME,IAAO,OAJI,MAAM,KAAK,IAAI,IAAI,MAAM,UAAU,EAAE,QAAQ,EAAE,KAAK;AAAA,QACnE,OAAO,EAAE,OAAOF,EAAK,MAAA;AAAA,MAAM,CAC5B,GAE2B,KAAA;AAE5B,UAAI,CAACE,EAAK,IAAI;AACZ,aAAK,IAAI,MAAM,QAAQA,EAAK,OAC5B,KAAK,IAAI,OAAO,MAAM,kCAAkC,EAAE,OAAOF,EAAK,OAAO,OAAOE,EAAK,MAAA,CAAO;AAChG;AAAA,MACF;AAEA,aAAOA,EAAK;AAAA,IACd,SAASmB,GAAK;AACZ,WAAK,IAAI,OAAO,MAAM,4BAA4B,EAAE,OAAOrB,EAAK,OAAO,OAAOqB,EAAA,CAAK,GACnF,KAAK,IAAI,MAAM,QAAQA,aAAe,QAAQA,EAAI,UAAU;AAC5D;AAAA,IACF,UAAA;AACE,WAAK,IAAI,QAAQ,QAAQ;AAAA,IAC3B;AAAA,EACF;AAAA,EAEA,iBAAyB;AACvB,UAAMkC,IAAa;AACnB,QAAIC,IAAS,KAAK,IAAI,QAAQ,QAAQD,CAAU;AAEhD,WAAKC,MACHA,IAASC,EAAS,EAAE,QAAQ,OAAA,CAAQ,GACpC,KAAK,IAAI,QAAQ,QAAQF,GAAYC,CAAM,IAGtCA;AAAA,EACT;AAAA,EAEA,MAAMxD,GAIG;AACP,QAAI;AAEF,MAAI,OAAO,SAAW,OAAe,OAAO,WAAW,UACrD,OAAO,OAAO,YAAY;AAAA,QACxB,MAAM;AAAA,QACN,OAAOA,EAAK;AAAA,QACZ,SAASA,EAAK;AAAA,QACd,YAAYA,EAAK,cAAc,CAAA;AAAA,MAAC,GAC/B,GAAG,GAGR,KAAK,IAAI,OAAO,KAAK,qBAAqB,EAAE,OAAOA,EAAK,OAAO,SAASA,EAAK,QAAA,CAAS;AAAA,IACxF,SAASqB,GAAK;AACZ,WAAK,IAAI,OAAO,MAAM,qBAAqB,EAAE,OAAOA,GAAK,MAAArB,GAAM;AAAA,IACjE;AAAA,EACF;AACF;AA1FwBlD,EAAAwG,GAAA;AAAjB,IAAMI,IAANJ;ACwBP,MAAMK,IAAN,MAAMA,EAAU;AAAA,EAAhB;AACU,IAAA5E,EAAA,aAAM;AAAA;AAAA,EAEd,MAAgC;AAC9B,QAAI,SAAO,SAAW;AAEtB,aAAQ,WAAmB,KAAK,GAAG;AAAA,EACrC;AAAA,EAEA,IAAI6E,GAA8B;AAChC,IAAI,OAAO,SAAW,QACnB,WAAmB,KAAK,GAAG,IAAIA;AAAA,EACpC;AAAA,EAEA,SAAe;AACb,IAAI,OAAO,SAAW,OACpB,OAAQ,WAAmB,KAAK,GAAG;AAAA,EACvC;AACF;AAlBgB9G,EAAA6G,GAAA;AAAhB,IAAME,IAANF;AAqBA,MAAMG,IAAY,IAAID,EAAA,GAETE,IAAN,MAAMA,UAAqBC,GAAqC;AAAA,EA+ErE,YAAYhH,IAAiC,IAAI;AAG/C,UAAMiH,IAAWH,EAAU,IAAA;AAC3B,QAAIG;AACF,qBAAQ,MAAM,sDAAsD,GAC7DA;AAGT,UAAM,gBAAgBjH,CAAQ;AA3EhC;AAAA,IAAA+B,EAAA,oBAAamF,EAAA;AACb,IAAAnF,EAAA,eAAQmF,EAAmB,IAAI;AAC/B,IAAAnF,EAAA,iBAAUmF,EAAI,EAAK;AACnB,IAAAnF,EAAA,eAAQmF,EAAmB,IAAI;AAC/B,IAAAnF,EAAA,iBAAU,KAAK,SAAS,WAAW;AAG3B;AAAA,IAAAA,EAAA,iBAAU,IAAIa,EAAA;AAGd;AAAA,IAAAb,EAAA,mBAAY0E,EAAS,EAAE,QAAQ,OAAO;AAYtC;AAAA;AAAA,IAAA1E,EAAA;AASR;AAAA,IAAAA,EAAA,sBAAeoF,EAAS,MAAM;AAC5B,YAAMjC,IAAO,KAAK,WAAW;AAC7B,UAAI,CAACA,GAAM;AACT;AAEF,YAAM9B,IAAU8B,EAAK,kBAAkBA,EAAK,OAAO,CAAC,GAAG;AACvD,UAAK9B;AAGL,eAAO8B,EAAK,OAAO,KAAK,CAACkC,MAAMA,EAAE,YAAYhE,CAAO;AAAA,IACtD,CAAC;AAED,IAAArB,EAAA,oBAAaoF,EAAS,MAAM;AAC1B,YAAME,IAAQ,KAAK,aAAa;AAChC,UAAI,CAACA,GAAO;AACV;AAEF,YAAMnC,IAAO,KAAK,WAAW;AAC7B,UAAKA,GAAM;AAGX,eAAOA,EAAK,KAAK,KAAK,CAACoC,MAAQA,EAAI,UAAUD,EAAM,KAAK;AAAA,IAC1D,CAAC;AAGD;AAAA,IAAAtF,EAAA;AACA,IAAAA,EAAA;AAGS;AAAA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAcP,IAAA+E,EAAU,IAAI,IAAI,GAGlB,KAAK,YAAY/G;AAAA,MACf,EAAE,OAAO,KAAK,OAAO,SAAS,KAAK,QAAA;AAAA,MACnC,KAAK,mBAAmB,KAAK,IAAI;AAAA,IAAA;AAInC,UAAMgD,IAAkB;AAAA,MACtB,KAAK,KAAK;AAAA,MACV,SAAS,KAAK;AAAA,MACd,OAAO,KAAK;AAAA,MACZ,YAAY,KAAK;AAAA,MACjB,OAAO,KAAK;AAAA,MACZ,SAAS,KAAK;AAAA,MACd,OAAO,KAAK;AAAA,MACZ,cAAc,KAAK;AAAA,MACnB,SAAS,KAAK;AAAA,MACd,WAAW,KAAK;AAAA,MAChB,QAAQ,KAAK;AAAA,MACb,oBAAoB,KAAK,mBAAmB,KAAK,IAAI;AAAA,IAAA;AAIvD,SAAK,QAAQ,IAAIiB,EAAYjB,CAAG,GAChC,KAAK,OAAO,IAAIsC,EAAWtC,CAAG,GAC9B,KAAK,UAAU,IAAI0C,EAAc1C,CAAG,GACpC,KAAK,OAAO,IAAIsD,EAAWtD,CAAG,GAC9B,KAAK,OAAO,IAAI2D,EAAW3D,CAAG,GAE9B,KAAK,OAAO,KAAK,0BAA0B,GAG3C,KAAK,QAAQ,gBAAgB,KAAK,YAAY,KAAK,KAAK,GAGxD,KAAK,QAAQ,qBAAqB,KAAK,YAAY,KAAK,KAAK,GAG7D,KAAK,cAAc,IAAI,QAAQ,CAACwE,MAAY;AAC1C,WAAK,cAAcA;AAAA,IACrB,CAAC,GAGG,KAAK,MAAM,SAAS,CAAC,KAAK,WAAW,QACvC,KAAK,eAAA,EAAiB,KAAK,CAACrC,MAAS;AACnC,MAAI,KAAK,gBACP,KAAK,YAAYA,CAAI,GACrB,KAAK,cAAc;AAAA,IAEvB,CAAC,EAAE,MAAM,CAACb,MAAQ;AAChB,WAAK,OAAO,MAAM,0BAA0B,EAAE,MAAMA,GAAK,GACrD,KAAK,gBACP,KAAK,YAAY,MAAS,GAC1B,KAAK,cAAc;AAAA,IAEvB,CAAC,IACQ,KAAK,WAAW,QAEzB,KAAK,cAAc,KAAK,WAAW,KAAK,IAGxC,KAAK,cAAc,MAAS;AAAA,EAEhC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAtJA,OAAO,YAAYrE,IAAiC,IAAkB;AAGpE,WAAO8G,EAAU,IAAA,KAAS,IAAIC,EAAa/G,CAAQ;AAAA,EACrD;AAAA,EAeA,IAAI,QAAQ;AACV,WAAO,KAAK,SAAS,UACnB,OAAO,SAAW,MACd,OAAO,SAAS,aAAa,eAAe,OAAO,SAAS,SAAS,SAAS,WAAW,IACzF;AAAA,EAER;AAAA;AAAA;AAAA,EAQA,IAAY,MAAM;AAChB,WAAQ,KAAK,UAAkB;AAAA,EACjC;AAAA;AAAA,EAsHA,mBAAmBQ,GAAkC;AAEnD,IAAIA,EAAS,MAAMA,EAAS,SAC1B,KAAK,WAAW,QAAQA,EAAS,MACjC,KAAK,OAAO,KAAK,kCAAkC,EAAE,MAAMA,EAAS,MAAM,IAIxEA,EAAS,MAAMA,EAAS,UAC1B,KAAK,MAAM,QAAQA,EAAS,OAC5B,KAAK,QAAQ,cAAc,KAAK,YAAY,KAAK,KAAK,GACtD,KAAK,OAAO,KAAK,iCAAiC,IAIhD,KAAK,eAAeA,EAAS,OAC/B,KAAK,YAAYA,EAAS,IAAI,GAC9B,KAAK,cAAc;AAAA,EAEvB;AAAA;AAAA,EAGA,eAAqB;AACnB,SAAK,OAAO,KAAK,kBAAkB,GACnC,KAAK,WAAW,QAAQ,QACxB,KAAK,MAAM,QAAQ,MACnB,KAAK,MAAM,QAAQ,MACnB,KAAK,QAAQ,aAAA;AAAA,EACf;AAAA;AAAA,EAGA,QAAc;AACZ,SAAK,OAAO,KAAK,yBAAyB,GAG1C,KAAK,aAAA,GAGL,KAAK,QAAQ,QAAQ,IACrB,KAAK,YAAYiG,EAAS,EAAE,QAAQ,OAAO,GAG3CK,EAAU,OAAA;AAAA,EACZ;AAAA;AAAA;AAAA,EAIA,MAAM,SAAS1C,GAA8B;AAAE,WAAO,KAAK,KAAK,SAASA,CAAK;AAAA,EAAE;AAAA,EAChF,MAAM,WAAWA,GAAeG,GAA6B;AAAE,WAAO,KAAK,KAAK,WAAWH,GAAOG,CAAI;AAAA,EAAE;AAAA,EACxG,MAAM,SAAwB;AAAE,WAAO,KAAK,KAAK,OAAA;AAAA,EAAS;AAAA,EAC1D,MAAM,iBAAoD;AAAE,WAAO,KAAK,KAAK,eAAA;AAAA,EAAiB;AAAA,EAC9F,MAAM,gBAAgBvB,GAA2C;AAAE,WAAO,KAAK,KAAK,gBAAgBA,CAAI;AAAA,EAAE;AAAA,EAC1G,MAAM,cAAcA,GAAsG;AAAE,WAAO,KAAK,KAAK,cAAcA,CAAI;AAAA,EAAE;AAAA,EACjK,gBAAgBA,GAA8F;AAAE,WAAO,KAAK,KAAK,gBAAgBA,CAAI;AAAA,EAAE;AAAA,EAEvJ,MAAM,WAAWA,GAA8D;AAAE,WAAO,KAAK,KAAK,WAAWA,CAAI;AAAA,EAAE;AAAA,EACnH,MAAM,wBAAwBA,GAA2E;AAAE,WAAO,KAAK,KAAK,wBAAwBA,CAAI;AAAA,EAAE;AAAA,EAC1J,MAAM,YAAYA,GAAkH;AAAE,WAAO,KAAK,KAAK,YAAYA,CAAI;AAAA,EAAE;AAAA,EAEzK,MAAM,eAAeA,GAA4D;AAAE,WAAO,KAAK,KAAK,eAAeA,CAAI;AAAA,EAAE;AAAA,EACzH,MAAM,gBAAgBA,GAA2D;AAAE,WAAO,KAAK,KAAK,gBAAgBA,CAAI;AAAA,EAAE;AAAA,EAC1H,iBAAyB;AAAE,WAAO,KAAK,KAAK,eAAA;AAAA,EAAiB;AAAA,EAC7D,MAAMA,GAAgD;AAAE,WAAO,KAAK,KAAK,MAAMA,CAAI;AAAA,EAAE;AACvF;AA9NuElD,EAAAiH,GAAA;AAAhE,IAAMS,IAANT;","x_google_ignoreList":[1,2]}
1
+ {"version":3,"file":"sdkClient.js","sources":["../api.ts","../../../node_modules/.pnpm/nanostores@1.2.0/node_modules/nanostores/clean-stores/index.js","../../../node_modules/.pnpm/nanostores@1.2.0/node_modules/nanostores/atom/index.js","../sdkStorage.ts","../clients/AgentClient.ts","../clients/AuthClient.ts","../clients/BillingClient.ts","../clients/ChatClient.ts","../clients/UserClient.ts","../sdkClient.ts"],"sourcesContent":["import type { Hono } from 'hono'\nimport { APP_PORT, APP_PROD_URL, createRefreshingFetch } from '@pagelines/core'\nimport { hc } from 'hono/client'\nimport { cookieUtil } from '@pagelines/core'\n\nexport interface RefreshFetchHooks {\n getDeviceId: () => string | null\n onAccessTokenRefreshed: (token: string) => void\n onTerminalFailure: () => void\n}\n\nexport interface ApiClientSettings {\n isDev: boolean\n apiBase?: string\n [key: string]: unknown\n}\n\n/**\n * Resolve API base URL from settings.\n * Centralizes the isDev/apiBase/production URL logic used across SDK clients.\n */\nexport function resolveApiBase(apiBase?: string, isDev?: boolean): string {\n return apiBase || (isDev ? `http://localhost:${APP_PORT}` : APP_PROD_URL)\n}\n\n/**\n * Create fully typed Hono RPC client for PageLines SDK\n *\n * @template TAppType - The Hono app type from the server (enables full type safety)\n * @param settings - Configuration for API base URL and environment\n * @param responseHandler - Optional handler to process ApiResponse for auto user/token updates\n * @returns Typed Hono client with response interceptor\n *\n * @example\n * ```typescript\n * import type { SDKAppType } from '@/modules/main/server'\n * const client = createApiClient<SDKAppType>({ isDev: true })\n * const response = await client.api.auth['check-email'].$post({ json: { email } })\n * ```\n */\nexport function createApiClient<TAppType extends Hono = any>(\n settings: ApiClientSettings,\n responseHandler?: (response: any) => void,\n refreshHooks?: RefreshFetchHooks,\n): ReturnType<typeof hc<TAppType>> {\n const baseUrl = resolveApiBase(settings.apiBase, settings.isDev)\n\n // Wrap raw fetch with single-flight 401→refresh→retry behavior. Without\n // this, embed users get logged out every 15 min when the access JWT expires\n // (PR-S2 split tokens; SDK only tracked the access half).\n const baseFetch: typeof globalThis.fetch = refreshHooks\n ? createRefreshingFetch({\n fetch: globalThis.fetch.bind(globalThis),\n getDeviceId: refreshHooks.getDeviceId,\n refreshUrl: `${baseUrl}/api/auth/refresh`,\n onAccessTokenRefreshed: refreshHooks.onAccessTokenRefreshed,\n onTerminalFailure: refreshHooks.onTerminalFailure,\n })\n : globalThis.fetch.bind(globalThis)\n\n // Create typed Hono RPC client with response interceptor\n const client = hc<TAppType>(baseUrl, {\n fetch: async (input: RequestInfo | URL, init?: RequestInit) => {\n const token = cookieUtil.getAuthToken()\n\n const response = await baseFetch(input, {\n ...init,\n headers: {\n ...init?.headers,\n 'Content-Type': 'application/json',\n // Only include Authorization header if token exists\n ...(token && { 'Authorization': `Bearer ${token}` }),\n },\n // 'include' so the browser attaches the HttpOnly pl-refresh-token\n // cookie when /refresh is hit. Server allows credentials per origin\n // (no CORS wildcard) so iOS/Android-WebView and same-origin web both\n // work; embeds on third-party sites must be on a CORS-allowed origin.\n credentials: 'include',\n })\n\n // Intercept response to process ApiResponse pattern\n if (responseHandler) {\n // Wrap the original response's json method directly\n const originalJson = response.json.bind(response)\n\n // Override json method on the response object itself\n response.json = async () => {\n const result = await originalJson()\n\n // Process ApiResponse pattern if it has user or token fields.\n // refreshToken is no longer a body field (HttpOnly cookie).\n if (typeof result === 'object' && result !== null) {\n if ('ok' in result && ('user' in result || 'token' in result)) {\n responseHandler(result)\n }\n }\n\n return result\n }\n }\n\n return response\n },\n })\n\n return client\n}\n","import { cleanTasks } from '../task/index.js'\n\nexport let clean = Symbol('clean')\n\nexport let cleanStores = (...stores) => {\n if (process.env.NODE_ENV === 'production') {\n throw new Error(\n 'cleanStores() can be used only during development or tests'\n )\n }\n cleanTasks()\n for (let $store of stores) {\n if ($store) {\n if ($store.mocked) delete $store.mocked\n if ($store[clean]) $store[clean]()\n }\n }\n}\n","import { clean } from '../clean-stores/index.js'\n\nlet listenerQueue = []\nlet lqIndex = 0\nconst QUEUE_ITEMS_PER_LISTENER = 4\nexport let epoch = 0\n\n/* @__NO_SIDE_EFFECTS__ */\nexport const atom = initialValue => {\n let listeners = []\n let $atom = {\n get() {\n if (!$atom.lc) {\n $atom.listen(() => {})()\n }\n return $atom.value\n },\n init: initialValue,\n lc: 0,\n listen(listener) {\n $atom.lc = listeners.push(listener)\n\n return () => {\n for (\n let i = lqIndex + QUEUE_ITEMS_PER_LISTENER;\n i < listenerQueue.length;\n\n ) {\n if (listenerQueue[i] === listener) {\n listenerQueue.splice(i, QUEUE_ITEMS_PER_LISTENER)\n } else {\n i += QUEUE_ITEMS_PER_LISTENER\n }\n }\n\n let index = listeners.indexOf(listener)\n if (~index) {\n listeners.splice(index, 1)\n if (!--$atom.lc) $atom.off()\n }\n }\n },\n notify(oldValue, changedKey) {\n epoch++\n let runListenerQueue = !listenerQueue.length\n for (let listener of listeners) {\n listenerQueue.push(listener, $atom.value, oldValue, changedKey)\n }\n\n if (runListenerQueue) {\n for (\n lqIndex = 0;\n lqIndex < listenerQueue.length;\n lqIndex += QUEUE_ITEMS_PER_LISTENER\n ) {\n listenerQueue[lqIndex](\n listenerQueue[lqIndex + 1],\n listenerQueue[lqIndex + 2],\n listenerQueue[lqIndex + 3]\n )\n }\n listenerQueue.length = 0\n }\n },\n /* It will be called on last listener unsubscribing.\n We will redefine it in onMount and onStop. */\n off() {},\n set(newValue) {\n let oldValue = $atom.value\n if (oldValue !== newValue) {\n $atom.value = newValue\n $atom.notify(oldValue)\n }\n },\n subscribe(listener) {\n let unbind = $atom.listen(listener)\n listener($atom.value)\n return unbind\n },\n value: initialValue\n }\n\n if (process.env.NODE_ENV !== 'production') {\n $atom[clean] = () => {\n listeners = []\n $atom.lc = 0\n $atom.off()\n }\n }\n\n return $atom\n}\n\nexport const readonlyType = store => store\n","import type { Ref } from 'vue'\nimport type { EnrichedUser } from '@pagelines/core'\nimport { atom } from 'nanostores'\nimport { watch } from 'vue'\nimport { cookieUtil, createLogger } from '@pagelines/core'\n\n// Global nanostores shared via globalThis so SDK and app bundles use the same\n// atoms when both run on the same page (Astro multi-island, dashboard preview\n// of a widget, etc.). Each bundle has its own Vue instance — without these\n// globals, signing in to one wouldn't reflect in the other.\n//\n// Refresh credential is NOT in nanostores — it lives in an HttpOnly cookie\n// the browser owns. JS cannot read or write it.\nconst _g = globalThis as Record<string, any>\nconst $globalActiveUser = (_g.__PL_AUTH_USER__ ??= atom<EnrichedUser | undefined>(undefined)) as ReturnType<typeof atom<EnrichedUser | undefined>>\nconst $globalToken = (_g.__PL_AUTH_TOKEN__ ??= atom<string | null>(null)) as ReturnType<typeof atom<string | null>>\nconst $globalDeviceId = (_g.__PL_AUTH_DEVICE_ID__ ??= atom<string | null>(null)) as ReturnType<typeof atom<string | null>>\n\nexport interface AuthRefs {\n activeUser: Ref<EnrichedUser | undefined>\n token: Ref<string | null>\n deviceId: Ref<string | null>\n}\n\n/**\n * SDKStorage - Handles all storage, sync, and persistence for PageLinesSDK\n *\n * Three storage layers, each with a clear job:\n * - Vue refs — runtime source of truth (in-memory)\n * - cookies — survive reload, JS-readable for headers (access token + deviceId)\n * - nanostores — bridge SDK widget bundle ↔ main app bundle on same page\n * - localStorage — UX optimization for cold-load (user object only, never tokens)\n *\n * The refresh credential lives in an HttpOnly cookie the server owns — JS\n * has no access to it, so it never touches any of these layers.\n */\nexport class SDKStorage {\n private logger = createLogger('SDKStorage')\n\n /**\n * Check if localStorage is fully functional (some test environments provide partial mocks)\n */\n private isLocalStorageFunctional(): boolean {\n return typeof window !== 'undefined'\n && typeof localStorage?.getItem === 'function'\n && typeof localStorage?.setItem === 'function'\n && typeof localStorage?.removeItem === 'function'\n }\n\n /**\n * Sync Vue reactive refs with global nanostores for cross-bundle persistence.\n */\n syncWithGlobalStores(refs: AuthRefs): void {\n const { activeUser, token, deviceId } = refs\n\n // 1. Restore from global store on init\n const storedUser = $globalActiveUser.get()\n const storedToken = $globalToken.get()\n const storedDevice = $globalDeviceId.get()\n\n if (storedUser) activeUser.value = storedUser\n if (storedToken) token.value = storedToken\n if (storedDevice) deviceId.value = storedDevice\n\n // 2. Vue refs → global stores (for persistence)\n watch(activeUser, (v) => $globalActiveUser.set(v), { immediate: true })\n watch(token, (v) => $globalToken.set(v), { immediate: true })\n watch(deviceId, (v) => $globalDeviceId.set(v), { immediate: true })\n\n // 3. Global stores → Vue refs (for cross-page updates)\n $globalActiveUser.subscribe((v) => { if (v !== activeUser.value) activeUser.value = v })\n $globalToken.subscribe((v) => { if (v !== token.value) token.value = v })\n $globalDeviceId.subscribe((v) => { if (v !== deviceId.value) deviceId.value = v })\n }\n\n /**\n * Load user and token from browser storage on initialization.\n * deviceId comes from a server-set non-HttpOnly cookie (read-only for JS).\n */\n loadFromStorage(refs: AuthRefs): void {\n if (typeof window === 'undefined')\n return\n\n const savedToken = cookieUtil.getAuthToken()\n if (savedToken) refs.token.value = savedToken\n\n const savedDevice = cookieUtil.getDeviceId()\n if (savedDevice) refs.deviceId.value = savedDevice\n\n // Try to load user from localStorage for immediate availability\n if (this.isLocalStorageFunctional()) {\n try {\n const savedUser = localStorage.getItem('pagelines-user')\n if (savedUser) {\n refs.activeUser.value = JSON.parse(savedUser)\n }\n } catch (error) {\n this.logger.error('Failed to load user from localStorage', { data: error })\n }\n }\n }\n\n /**\n * Save current user and access token to browser storage.\n * deviceId is server-owned (Set-Cookie) — JS doesn't write it.\n */\n saveToStorage(refs: AuthRefs): void {\n if (typeof window === 'undefined')\n return\n\n if (refs.token.value) cookieUtil.setAuthToken(refs.token.value)\n else cookieUtil.removeAuthToken()\n\n // Save user to localStorage for quick loading\n if (this.isLocalStorageFunctional()) {\n try {\n if (refs.activeUser.value) {\n localStorage.setItem('pagelines-user', JSON.stringify(refs.activeUser.value))\n } else {\n localStorage.removeItem('pagelines-user')\n }\n } catch (error) {\n this.logger.error('Failed to save user to localStorage', { data: error })\n }\n }\n }\n\n /**\n * Clear local stored user data and JS-owned tokens. Server-owned cookies\n * (pl-refresh-token, pl-device-id) are cleared by /api/auth/logout via\n * Set-Cookie max-age=0 — JS can't touch them.\n */\n clearStorage(): void {\n if (typeof window === 'undefined')\n return\n\n cookieUtil.removeAuthToken()\n\n if (this.isLocalStorageFunctional()) {\n try {\n localStorage.removeItem('pagelines-user')\n } catch (error) {\n this.logger.error('Failed to clear user from localStorage', { data: error })\n }\n }\n\n // Clear global stores\n $globalActiveUser.set(undefined)\n $globalToken.set(null)\n $globalDeviceId.set(null)\n }\n\n /**\n * Generic localStorage getter\n */\n getItem(key: string): string | null {\n if (!this.isLocalStorageFunctional())\n return null\n\n try {\n return localStorage.getItem(key)\n } catch (error) {\n this.logger.error('Failed to get item from localStorage', { key, error })\n return null\n }\n }\n\n /**\n * Generic localStorage setter\n */\n setItem(key: string, value: string): void {\n if (!this.isLocalStorageFunctional())\n return\n\n try {\n localStorage.setItem(key, value)\n } catch (error) {\n this.logger.error('Failed to set item in localStorage', { key, error })\n }\n }\n}\n","import type { AgentConfig } from '@pagelines/core'\nimport type { SDKContext } from './types'\nimport { resolveApiBase } from '../api'\n\nconst STATUS_MESSAGES = [\n 'Deploying your server...',\n 'Setting up your workspace...',\n 'Installing tools...',\n 'Almost ready...',\n]\n\nexport class AgentClient {\n constructor(private ctx: SDKContext) {}\n\n async create(args: { name: string, orgId?: string }): Promise<AgentConfig> {\n const orgId = args.orgId || this.resolveOrgId()\n const apiBase = resolveApiBase(this.ctx.apiBase, this.ctx.isDev)\n\n const response = await fetch(`${apiBase}/api/agent`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(this.ctx.token.value && { Authorization: `Bearer ${this.ctx.token.value}` }),\n },\n body: JSON.stringify({ name: args.name, orgId }),\n })\n\n const data = await response.json() as { ok: boolean, data?: AgentConfig[], error?: string }\n\n if (!data.ok || !data.data?.[0]) {\n const msg = data.error || 'Failed to create agent'\n this.ctx.error.value = msg\n throw new Error(msg)\n }\n\n this.ctx.processApiResponse(data as any)\n return data.data[0]\n }\n\n async getStatus(args: { agentId: string }): Promise<{\n status: string\n ready: boolean\n error?: string\n }> {\n const apiBase = resolveApiBase(this.ctx.apiBase, this.ctx.isDev)\n\n const response = await fetch(`${apiBase}/api/agent/${args.agentId}/status`, {\n headers: {\n ...(this.ctx.token.value && { Authorization: `Bearer ${this.ctx.token.value}` }),\n },\n })\n\n const data = await response.json() as { ok: boolean, data?: { status: string, ready: boolean, error?: string } }\n\n if (!data.ok || !data.data) {\n return { status: 'unknown', ready: false, error: 'Failed to check status' }\n }\n\n return data.data\n }\n\n async waitUntilReady(args: {\n agentId: string\n onStatus?: (message: string) => void\n timeoutMs?: number\n pollIntervalMs?: number\n }): Promise<void> {\n const { agentId, onStatus, timeoutMs = 300_000, pollIntervalMs = 3_000 } = args\n const start = Date.now()\n let messageIndex = 0\n\n while (Date.now() - start < timeoutMs) {\n const status = await this.getStatus({ agentId })\n\n if (status.ready) {\n onStatus?.('Ready!')\n return\n }\n\n if (status.status === 'error') {\n throw new Error(status.error || 'Provisioning failed')\n }\n\n if (onStatus && messageIndex < STATUS_MESSAGES.length) {\n onStatus(STATUS_MESSAGES[messageIndex]!)\n messageIndex++\n }\n\n await new Promise(r => setTimeout(r, pollIntervalMs))\n }\n\n throw new Error('Agent provisioning timed out — please try again')\n }\n\n /** Send a typed webhook event to a bot agent. No auth required — the proxy is public. */\n async webhook<T = Record<string, unknown>>(args: {\n agentId: string\n type: string\n data: T\n meta?: { source?: string, timestamp?: string, correlationId?: string, [key: string]: unknown }\n }): Promise<{ ok: boolean, error?: string }> {\n const apiBase = resolveApiBase(this.ctx.apiBase, this.ctx.isDev)\n const url = `${apiBase}/api/bot-api/agents/${args.agentId}/webhook`\n\n const body: Record<string, unknown> = { type: args.type, data: args.data }\n if (args.meta) body.meta = args.meta\n\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n })\n\n if (!res.ok) {\n const text = await res.text().catch(() => 'Unknown error')\n throw new Error(`Webhook delivery failed (${res.status}): ${text.slice(0, 200)}`)\n }\n\n return res.json() as Promise<{ ok: boolean, error?: string }>\n }\n\n private resolveOrgId(): string {\n const user = this.ctx.activeUser.value\n const orgId = user?.orgs?.[0]?.orgId\n if (!orgId) {\n throw new Error('No organization found. Please sign in first.')\n }\n return orgId\n }\n}\n","import type { EnrichedUser } from '@pagelines/core'\nimport type { SDKContext } from './types'\nimport { resolveApiBase } from '../api'\n\n/**\n * Run an async operation with loading/error state management.\n * Sets loading=true and error=null before, loading=false in finally.\n */\nasync function withLoadingState<T>(ctx: SDKContext, fn: () => Promise<T>): Promise<T> {\n ctx.loading.value = true\n ctx.error.value = null\n try {\n return await fn()\n } finally {\n ctx.loading.value = false\n }\n}\n\nexport class AuthClient {\n constructor(private ctx: SDKContext) {}\n\n async sendCode(email: string): Promise<void> {\n return withLoadingState(this.ctx, async () => {\n try {\n const response = await this.ctx.api.auth['check-email'].$post({\n json: { email },\n })\n const data = await response.json()\n if (!data.ok) {\n this.ctx.error.value = data.error\n throw new Error(data.error)\n }\n } catch (err) {\n this.ctx.logger.error('Send code error', { data: err })\n const errorMessage = err instanceof Error ? err.message : 'Failed to send verification code'\n this.ctx.error.value = errorMessage\n throw err\n }\n })\n }\n\n async verifyCode(email: string, code: string): Promise<void> {\n return withLoadingState(this.ctx, async () => {\n try {\n const response = await this.ctx.api.auth['verify-code'].$post({\n json: { email, code },\n })\n const data = await response.json()\n if (!data.ok) {\n this.ctx.error.value = data.error\n throw new Error(data.error)\n }\n } catch (err) {\n this.ctx.logger.error('Verify code error', { data: err })\n const errorMessage = err instanceof Error ? err.message : 'Failed to verify code'\n this.ctx.error.value = errorMessage\n throw err\n }\n })\n }\n\n async logout(): Promise<void> {\n return withLoadingState(this.ctx, async () => {\n try {\n await this.ctx.api.auth.logout.$post()\n } catch (err) {\n this.ctx.logger.error('Logout error (user still logged out locally)', { data: err })\n }\n // Always clear local state regardless of API success\n this.ctx.activeUser.value = undefined\n this.ctx.token.value = null\n this.ctx.storage.clearStorage()\n })\n }\n\n async getCurrentUser(): Promise<EnrichedUser | undefined> {\n if (!this.ctx.token.value) {\n return undefined\n }\n\n return withLoadingState(this.ctx, async () => {\n try {\n const response = await this.ctx.api.auth.me.$get()\n const data = await response.json()\n\n if (!data.ok) {\n this.ctx.error.value = data.error\n if (data.error.includes('Authentication')) {\n this.ctx.activeUser.value = undefined\n this.ctx.token.value = null\n this.ctx.storage.clearStorage()\n }\n return undefined\n }\n\n return data.user\n } catch (err) {\n this.ctx.logger.error('Get current user error', { data: err })\n this.ctx.error.value = err instanceof Error ? err.message : 'Failed to get user info'\n return undefined\n }\n })\n }\n\n async requestAuthCode(args: { email: string }): Promise<boolean> {\n return withLoadingState(this.ctx, async () => {\n try {\n const response = await this.ctx.api.auth['check-email'].$post({\n json: { email: args.email },\n })\n const data = await response.json()\n if (!data.ok) {\n this.ctx.error.value = data.error\n this.ctx.logger.error('Failed to request auth code', { email: args.email, error: data.error })\n return false\n }\n this.ctx.logger.info('Auth code requested successfully', { email: args.email })\n return true\n } catch (err) {\n this.ctx.logger.error('Request auth code error', { email: args.email, error: err })\n this.ctx.error.value = err instanceof Error ? err.message : 'Failed to request auth code'\n return false\n }\n })\n }\n\n async loginWithCode(args: {\n email: string\n code: string\n orgId?: string\n autoCreateContact?: boolean\n }): Promise<boolean> {\n return withLoadingState(this.ctx, async () => {\n try {\n const response = await this.ctx.api.auth['verify-code'].$post({\n json: { email: args.email, code: args.code },\n })\n const data = await response.json()\n if (!data.ok) {\n this.ctx.error.value = data.error\n this.ctx.logger.error('Login failed', { email: args.email, error: data.error })\n return false\n }\n this.ctx.logger.info('Login successful', { email: args.email })\n return true\n } catch (err) {\n this.ctx.logger.error('Login with code error', { email: args.email, error: err })\n this.ctx.error.value = err instanceof Error ? err.message : 'Login failed'\n return false\n }\n })\n }\n\n loginWithGoogle(args?: { onSuccess?: (user: EnrichedUser) => void, onError?: (error: string) => void }): void {\n if (typeof window === 'undefined') {\n this.ctx.logger.error('loginWithGoogle: Only available in browser')\n return\n }\n\n const apiBase = resolveApiBase(this.ctx.apiBase, this.ctx.isDev)\n const origin = window.location.origin\n const popupUrl = `${apiBase}/auth/google-popup?origin=${encodeURIComponent(origin)}`\n\n // Open centered popup\n const width = 500\n const height = 600\n const left = window.screenX + (window.outerWidth - width) / 2\n const top = window.screenY + (window.outerHeight - height) / 2\n const popup = window.open(\n popupUrl,\n 'google-auth',\n `width=${width},height=${height},left=${left},top=${top},popup=yes`,\n )\n\n if (!popup) {\n const msg = 'Popup was blocked. Please allow popups for this site.'\n this.ctx.error.value = msg\n args?.onError?.(msg)\n return\n }\n\n // Listen for postMessage from popup\n const handler = (event: MessageEvent) => {\n // Validate origin -- must be our API base\n const expectedOrigin = new URL(apiBase).origin\n if (event.origin !== expectedOrigin) return\n\n if (event.data?.type === 'auth-success') {\n window.removeEventListener('message', handler)\n const { token, user } = event.data\n\n // Process the auth response the same way as other login methods\n this.ctx.processApiResponse({ ok: true, data: {}, token, user })\n\n this.ctx.logger.info('Google login successful')\n args?.onSuccess?.(user)\n } else if (event.data?.type === 'auth-error') {\n window.removeEventListener('message', handler)\n const errorMsg = event.data.error || 'Google authentication failed'\n this.ctx.error.value = errorMsg\n this.ctx.logger.error('Google login failed', { error: errorMsg })\n args?.onError?.(errorMsg)\n }\n }\n\n window.addEventListener('message', handler)\n\n // Clean up listener if popup is closed without completing auth\n const checkClosed = setInterval(() => {\n if (popup.closed) {\n clearInterval(checkClosed)\n window.removeEventListener('message', handler)\n }\n }, 500)\n }\n}\n","import type { SDKContext } from './types'\nimport { resolveApiBase } from '../api'\n\nexport interface BillingStatus {\n plan?: string\n status: string\n hasActiveBilling: boolean\n maxAgents: number\n trialEnd?: string\n trialDaysRemaining?: number\n}\n\nexport class BillingClient {\n constructor(private ctx: SDKContext) {}\n\n async startTrial(args?: { returnUrl?: string, planKey?: string }): Promise<void> {\n const orgId = this.resolveOrgId()\n const apiBase = resolveApiBase(this.ctx.apiBase, this.ctx.isDev)\n\n const response = await fetch(`${apiBase}/api/billing/checkout/create`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(this.ctx.token.value && { Authorization: `Bearer ${this.ctx.token.value}` }),\n },\n body: JSON.stringify({\n orgId,\n ...(args?.returnUrl && { returnUrl: args.returnUrl }),\n ...(args?.planKey && { planKey: args.planKey }),\n }),\n })\n\n const data = await response.json() as { ok: boolean, data?: { url: string }, error?: string }\n\n if (!data.ok || !data.data?.url) {\n const msg = data.error || 'Failed to create checkout session'\n this.ctx.error.value = msg\n throw new Error(msg)\n }\n\n window.location.href = data.data.url\n }\n\n async confirmCheckout(_args?: { sessionId?: string }): Promise<BillingStatus> {\n return this.getStatus()\n }\n\n async getStatus(): Promise<BillingStatus> {\n const orgId = this.resolveOrgId()\n const apiBase = resolveApiBase(this.ctx.apiBase, this.ctx.isDev)\n\n const response = await fetch(`${apiBase}/api/billing/details/${orgId}`, {\n headers: {\n ...(this.ctx.token.value && { Authorization: `Bearer ${this.ctx.token.value}` }),\n },\n })\n\n const data = await response.json() as {\n ok: boolean\n data?: { plan: string, status: string, maxAgents: number, trialEnd?: string, trialDaysRemaining?: number }\n error?: string\n }\n\n if (!data.ok || !data.data) {\n return {\n plan: undefined,\n status: 'none',\n hasActiveBilling: false,\n maxAgents: 0,\n }\n }\n\n const ACTIVE_STATUSES = ['active', 'trialing']\n\n return {\n plan: data.data.plan,\n status: data.data.status,\n hasActiveBilling: ACTIVE_STATUSES.includes(data.data.status),\n maxAgents: data.data.maxAgents,\n ...(data.data.trialEnd && { trialEnd: data.data.trialEnd }),\n ...(data.data.trialDaysRemaining !== undefined && { trialDaysRemaining: data.data.trialDaysRemaining }),\n }\n }\n\n private resolveOrgId(): string {\n const user = this.ctx.activeUser.value\n const orgId = user?.orgs?.[0]?.orgId\n if (!orgId) {\n throw new Error('No organization found. Please sign in first.')\n }\n return orgId\n }\n}\n","import type { ApiResponse } from '@pagelines/core'\nimport type { SDKContext } from './types'\nimport { resolveApiBase } from '../api'\n\nexport class ChatClient {\n constructor(private ctx: SDKContext) {}\n\n async chatStream(args: {\n handle: string\n message: string\n attachments?: Array<{ type: string, url: string, name: string, mimeType: string, mediaId?: string }>\n conversationId?: string\n history?: Array<{ role: 'user' | 'assistant', content: string }>\n visitorId?: string\n context?: string\n onDelta: (text: string) => void\n onDone: (conversationId: string) => void\n onError: (error: string) => void\n onStatus?: (status: string) => void\n }): Promise<void> {\n const apiBase = resolveApiBase(this.ctx.apiBase, this.ctx.isDev)\n const url = `${apiBase}/api/agent/public/${encodeURIComponent(args.handle)}/chat/stream`\n\n return this._streamChat({\n url,\n headers: { 'Content-Type': 'application/json' },\n body: {\n message: args.message,\n conversationId: args.conversationId,\n history: args.history,\n visitorId: args.visitorId,\n context: args.context,\n attachments: args.attachments,\n },\n conversationId: args.conversationId,\n onDelta: args.onDelta,\n onDone: args.onDone,\n onError: args.onError,\n onStatus: args.onStatus,\n })\n }\n\n async chatStreamAuthenticated(args: {\n agentId: string\n message: string\n attachments?: Array<{ type: string, url: string, name: string, mimeType: string, mediaId?: string }>\n conversationId?: string\n history?: Array<{ role: 'user' | 'assistant', content: string }>\n onDelta: (text: string) => void\n onDone: (conversationId: string) => void\n onError: (error: string) => void\n onStatus?: (status: string) => void\n }): Promise<void> {\n const apiBase = resolveApiBase(this.ctx.apiBase, this.ctx.isDev)\n const url = `${apiBase}/api/agent/${encodeURIComponent(args.agentId)}/chat/stream`\n\n return this._streamChat({\n url,\n headers: {\n 'Content-Type': 'application/json',\n ...(this.ctx.token.value && { 'Authorization': `Bearer ${this.ctx.token.value}` }),\n },\n body: {\n message: args.message,\n conversationId: args.conversationId,\n history: args.history,\n attachments: args.attachments,\n },\n conversationId: args.conversationId,\n onDelta: args.onDelta,\n onDone: args.onDone,\n onError: args.onError,\n onStatus: args.onStatus,\n })\n }\n\n /** Shared SSE streaming logic for both public and authenticated chat */\n private async _streamChat(args: {\n url: string\n headers: Record<string, string>\n body: Record<string, unknown>\n conversationId?: string\n onDelta: (text: string) => void\n onDone: (conversationId: string) => void\n onError: (error: string) => void\n onStatus?: (status: string) => void\n }): Promise<void> {\n try {\n const response = await fetch(args.url, {\n method: 'POST',\n headers: args.headers,\n body: JSON.stringify(args.body),\n })\n\n if (!response.ok) {\n const errorBody = await response.json().catch(() => ({ error: 'Request failed' })) as { error?: string }\n args.onError(errorBody.error || `HTTP ${response.status}`)\n return\n }\n\n const reader = response.body?.getReader()\n if (!reader) {\n args.onError('No response stream')\n return\n }\n\n const decoder = new TextDecoder()\n let buffer = ''\n let resolvedConversationId = args.conversationId || ''\n\n while (true) {\n const { done, value } = await reader.read()\n if (done)\n break\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 data = line.slice(6).trim()\n if (data === '[DONE]') {\n args.onDone(resolvedConversationId)\n return\n }\n\n try {\n const chunk = JSON.parse(data) as {\n choices?: Array<{ delta?: { content?: string } }>\n pl_metadata?: { conversationId?: string }\n pl_status?: string\n }\n\n // Handle status events (e.g. \"Waking up...\")\n if (chunk.pl_status) {\n args.onStatus?.(chunk.pl_status)\n continue\n }\n\n if (chunk.pl_metadata?.conversationId) {\n resolvedConversationId = chunk.pl_metadata.conversationId\n }\n\n const delta = chunk.choices?.[0]?.delta\n if (delta?.content) {\n args.onDelta(delta.content)\n }\n } catch {\n // Skip malformed chunks\n }\n }\n }\n\n // Stream ended without [DONE]\n args.onDone(resolvedConversationId)\n } catch (error) {\n args.onError(error instanceof Error ? error.message : 'Stream failed')\n }\n }\n\n async chatMessage(args: {\n handle: string\n message: string\n conversationId?: string\n visitorId?: string\n context?: string\n }): Promise<{ conversationId: string, content: string } | undefined> {\n const apiBase = resolveApiBase(this.ctx.apiBase, this.ctx.isDev)\n const url = `${apiBase}/api/agent/public/${encodeURIComponent(args.handle)}/chat`\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n message: args.message,\n conversationId: args.conversationId,\n visitorId: args.visitorId,\n context: args.context,\n }),\n })\n\n const data = await response.json() as ApiResponse<{\n conversationId: string\n message: { role: 'assistant', content: string }\n }>\n\n if (!data.ok || !data.data) {\n this.ctx.logger.error('chatMessage failed', { error: !data.ok && 'error' in data ? data.error : 'Unknown' })\n return undefined\n }\n\n return {\n conversationId: data.data.conversationId,\n content: data.data.message.content,\n }\n } catch (err) {\n this.ctx.logger.error('chatMessage error', { error: err })\n return undefined\n }\n }\n}\n","import type { AgentConfig } from '@pagelines/core'\nimport { objectId } from '@pagelines/core'\nimport type { SDKContext } from './types'\n\nexport class UserClient {\n constructor(private ctx: SDKContext) {}\n\n async getPublicAgent(args: { handle: string }): Promise<AgentConfig | undefined> {\n this.ctx.loading.value = true\n this.ctx.error.value = null\n\n try {\n const response = await this.ctx.api.agent.public[':handle'].$get({\n param: { handle: args.handle },\n })\n\n const data = await response.json()\n\n if (!data.ok) {\n this.ctx.error.value = data.error\n this.ctx.logger.error('Failed to fetch public agent', { handle: args.handle, error: data.error })\n return undefined\n }\n\n return data.data\n } catch (err) {\n this.ctx.logger.error('Get public agent error', { handle: args.handle, error: err })\n this.ctx.error.value = err instanceof Error ? err.message : 'Failed to fetch agent'\n return undefined\n } finally {\n this.ctx.loading.value = false\n }\n }\n\n async getAgentByEmail(args: { email: string }): Promise<AgentConfig | undefined> {\n this.ctx.loading.value = true\n this.ctx.error.value = null\n\n try {\n const response = await this.ctx.api.agent['by-email'][':email'].$get({\n param: { email: args.email },\n })\n\n const data = await response.json()\n\n if (!data.ok) {\n this.ctx.error.value = data.error\n this.ctx.logger.error('Failed to fetch agent by email', { email: args.email, error: data.error })\n return undefined\n }\n\n return data.data\n } catch (err) {\n this.ctx.logger.error('Get agent by email error', { email: args.email, error: err })\n this.ctx.error.value = err instanceof Error ? err.message : 'Failed to fetch agent'\n return undefined\n } finally {\n this.ctx.loading.value = false\n }\n }\n\n generateAnonId(): string {\n const storageKey = 'pagelinesAnonId'\n let anonId = this.ctx.storage.getItem(storageKey)\n\n if (!anonId) {\n anonId = objectId({ prefix: 'anon' })\n this.ctx.storage.setItem(storageKey, anonId)\n }\n\n return anonId\n }\n\n track(args: {\n event: 'view_profile' | 'profile_interaction'\n agentId: string\n properties?: Record<string, any>\n }): void {\n try {\n // Track event via postMessage to parent window if embedded\n if (typeof window !== 'undefined' && window.parent !== window) {\n window.parent.postMessage({\n type: 'pagelines_track',\n event: args.event,\n agentId: args.agentId,\n properties: args.properties || {},\n }, '*')\n }\n\n this.ctx.logger.info('SDK event tracked', { event: args.event, agentId: args.agentId })\n } catch (err) {\n this.ctx.logger.error('Track event error', { error: err, args })\n }\n }\n}\n","import type { hc } from 'hono/client'\n// Use stub type for production builds (aliased in vite.config.sdk.ts)\n// Dev uses real SDKAppType from server via alias\nimport type { SDKAppType } from '@/modules/main/server'\nimport type { AgentConfig, EnrichedUser } from '@pagelines/core'\nimport type { ApiResponse } from '@pagelines/core'\nimport { objectId, SettingsObject } from '@pagelines/core'\nimport { computed, ref } from 'vue'\nimport { createApiClient } from './api'\nimport { SDKStorage } from './sdkStorage'\nimport { AgentClient } from './clients/AgentClient'\nimport { AuthClient } from './clients/AuthClient'\nimport { BillingClient } from './clients/BillingClient'\nimport { ChatClient } from './clients/ChatClient'\nimport { UserClient } from './clients/UserClient'\nimport type { SDKContext } from './clients/types'\n\nexport interface PageLinesSDKSettings {\n apiBase?: string\n isDev?: boolean\n [key: string]: unknown\n}\n\n/**\n * Browser-only singleton manager\n * Browser: Uses globalThis for cross-bundle singleton (www + widget)\n * Node.js SSR: No singleton - each request gets new instance (prevents request bleeding)\n */\nclass SDKGlobal {\n private key = '__PAGELINES_SDK__'\n\n get(): PageLinesSDK | undefined {\n if (typeof window === 'undefined')\n return undefined\n return (globalThis as any)[this.key]\n }\n\n set(instance: PageLinesSDK): void {\n if (typeof window !== 'undefined')\n (globalThis as any)[this.key] = instance\n }\n\n delete(): void {\n if (typeof window !== 'undefined')\n delete (globalThis as any)[this.key]\n }\n}\n\n// Module-scoped singleton manager\nconst sdkGlobal = new SDKGlobal()\n\nexport class PageLinesSDK extends SettingsObject<PageLinesSDKSettings> {\n /**\n * Get singleton instance in browser (creates if doesn't exist)\n * Node.js: Always creates new instance (no singleton)\n * Recommended: Use this instead of constructor for shared state\n */\n static getInstance(settings: PageLinesSDKSettings = {}): PageLinesSDK {\n // Browser: return singleton or create\n // Node: always create new (no singleton)\n return sdkGlobal.get() || new PageLinesSDK(settings)\n }\n\n // Vue reactive state\n activeUser = ref<EnrichedUser | undefined>()\n token = ref<string | null>(null)\n // Refresh credential lives in HttpOnly pl-refresh-token cookie — JS never\n // holds it, so no reactive ref. /api/auth/refresh reads the cookie via the\n // browser's automatic credentials: 'include' attach.\n deviceId = ref<string | null>(null)\n loading = ref(false)\n error = ref<string | null>(null)\n apiBase = this.settings.apiBase || undefined\n\n // Storage handler for persistence\n private storage = new SDKStorage()\n\n // Auto-managed session ID for usage tracking\n private sessionId = objectId({ prefix: 'ses' })\n\n get isDev() {\n return this.settings.isDev ?? (\n typeof window !== 'undefined'\n ? window.location.hostname === 'localhost' || window.location.hostname.includes('127.0.0.1')\n : false\n )\n }\n\n // Typed Hono RPC client - uses SDKAppType (auth/self/usage routes only)\n // Initialized in constructor (definite assignment via singleton pattern)\n private apiClient!: ReturnType<typeof hc<SDKAppType>>\n\n // Bypass stub typing for route access (production builds use SDKAppType stub)\n // Runtime types are validated via Zod at API boundaries\n private get api() {\n return (this.apiClient as any).api\n }\n\n // Computed properties derived from activeUser (matches UserClient pattern)\n currentAgent = computed(() => {\n const user = this.activeUser.value\n if (!user?.agents)\n return undefined\n\n const agentId = user.primaryAgentId || user.agents[0]?.agentId\n if (!agentId)\n return undefined\n\n return user.agents.find((a) => a.agentId === agentId)\n })\n\n currentOrg = computed(() => {\n const agent = this.currentAgent.value\n if (!agent?.orgId)\n return undefined\n\n const user = this.activeUser.value\n if (!user?.orgs)\n return undefined\n\n return user.orgs.find((org) => org.orgId === agent.orgId)\n })\n\n // Initialization state\n initialized?: Promise<EnrichedUser | undefined>\n resolveUser?: (value: EnrichedUser | undefined) => void\n\n // Sub-clients (new preferred API surface)\n readonly agent!: AgentClient\n readonly auth!: AuthClient\n readonly billing!: BillingClient\n readonly chat!: ChatClient\n readonly user!: UserClient\n\n constructor(settings: PageLinesSDKSettings = {}) {\n // Browser: return existing singleton\n // Node: always create new\n const existing = sdkGlobal.get()\n if (existing) {\n console.debug('[PageLinesSDK] Returning existing singleton instance')\n return existing\n }\n\n super('PageLinesSDK', settings)\n\n // Browser: set singleton reference (no-op in Node)\n sdkGlobal.set(this)\n\n // Create typed Hono RPC client with response handler + auto-refresh on 401.\n // Refresh credential is in the HttpOnly cookie; the browser attaches it\n // automatically when /refresh is hit with credentials: 'include'.\n this.apiClient = createApiClient<SDKAppType>(\n { isDev: this.isDev, apiBase: this.apiBase },\n this.processApiResponse.bind(this),\n {\n getDeviceId: () => this.deviceId.value,\n onAccessTokenRefreshed: (token) => {\n this.token.value = token\n this.persistAuth()\n },\n onTerminalFailure: () => {\n this.clearSession()\n },\n },\n )\n\n // Build shared context for sub-clients\n const ctx: SDKContext = {\n api: this.api,\n apiBase: this.apiBase,\n isDev: this.isDev,\n activeUser: this.activeUser,\n token: this.token,\n loading: this.loading,\n error: this.error,\n currentAgent: this.currentAgent,\n storage: this.storage,\n sessionId: this.sessionId,\n logger: this.logger,\n processApiResponse: this.processApiResponse.bind(this),\n }\n\n // Initialize sub-clients\n this.agent = new AgentClient(ctx)\n this.auth = new AuthClient(ctx)\n this.billing = new BillingClient(ctx)\n this.chat = new ChatClient(ctx)\n this.user = new UserClient(ctx)\n\n this.logger.info('PageLinesSDK initialized')\n\n // Initialize from storage using handler\n this.storage.loadFromStorage(this.authRefs())\n\n // Sync with global stores for persistence across navigation\n this.storage.syncWithGlobalStores(this.authRefs())\n\n // Set up initialization promise (same pattern as UserClient)\n this.initialized = new Promise((resolve) => {\n this.resolveUser = resolve\n })\n\n // Auto-fetch user if token exists (mirrors UserClient pattern)\n if (this.token.value && !this.activeUser.value) {\n this.getCurrentUser().then((user) => {\n if (this.resolveUser) {\n this.resolveUser(user)\n this.resolveUser = undefined\n }\n }).catch((err) => {\n this.logger.error('Auto user fetch failed', { data: err })\n if (this.resolveUser) {\n this.resolveUser(undefined)\n this.resolveUser = undefined\n }\n })\n } else if (this.activeUser.value) {\n // Resolve immediately if we already have a user from storage\n this.resolveUser?.(this.activeUser.value)\n } else {\n // No token, resolve with undefined\n this.resolveUser?.(undefined)\n }\n }\n\n // Process ApiResponse for automatic user/token updates - public for dependency injection\n processApiResponse(response: ApiResponse<any>): void {\n if (!response.ok) return\n\n let dirty = false\n\n if (response.user) {\n this.activeUser.value = response.user\n this.logger.info('User updated from API response', { data: response.user })\n dirty = true\n }\n\n if (response.token) {\n this.token.value = response.token\n this.logger.info('Token updated from API response')\n dirty = true\n }\n\n // deviceId rides inside data.* on /verify-code and Apple/Google routes.\n // Server ALSO sets it as a non-HttpOnly cookie — we mirror to the ref\n // so the rest of the SDK can observe \"we're paired\" reactively.\n const incomingDeviceId = (response.data as { deviceId?: string } | undefined)?.deviceId\n if (incomingDeviceId) {\n this.deviceId.value = incomingDeviceId\n dirty = true\n }\n\n if (dirty) this.persistAuth()\n\n // Resolve initialization promise\n if (this.resolveUser) {\n this.resolveUser(response.user)\n this.resolveUser = undefined\n }\n }\n\n private authRefs() {\n return {\n activeUser: this.activeUser,\n token: this.token,\n deviceId: this.deviceId,\n }\n }\n\n private persistAuth() {\n this.storage.saveToStorage(this.authRefs())\n }\n\n // Clear all user data and tokens\n clearSession(): void {\n this.logger.info('Clearing session')\n this.activeUser.value = undefined\n this.token.value = null\n this.deviceId.value = null\n this.error.value = null\n this.storage.clearStorage()\n }\n\n // Full reset - clears session + state + destroys singleton\n clear(): void {\n this.logger.info('Clearing SDK completely')\n\n // 1. Clear session data\n this.clearSession()\n\n // 2. Reset other state\n this.loading.value = false\n this.sessionId = objectId({ prefix: 'ses' })\n\n // 3. Destroy singleton (no-op in Node)\n sdkGlobal.delete()\n }\n\n // Backward-compatible delegates — these forward to sub-clients\n // Can be removed in a future breaking change\n async sendCode(email: string): Promise<void> { return this.auth.sendCode(email) }\n async verifyCode(email: string, code: string): Promise<void> { return this.auth.verifyCode(email, code) }\n async logout(): Promise<void> { return this.auth.logout() }\n async getCurrentUser(): Promise<EnrichedUser | undefined> { return this.auth.getCurrentUser() }\n async requestAuthCode(args: { email: string }): Promise<boolean> { return this.auth.requestAuthCode(args) }\n async loginWithCode(args: { email: string, code: string, orgId?: string, autoCreateContact?: boolean }): Promise<boolean> { return this.auth.loginWithCode(args) }\n loginWithGoogle(args?: { onSuccess?: (user: EnrichedUser) => void, onError?: (error: string) => void }): void { return this.auth.loginWithGoogle(args) }\n\n async chatStream(args: Parameters<ChatClient['chatStream']>[0]): Promise<void> { return this.chat.chatStream(args) }\n async chatStreamAuthenticated(args: Parameters<ChatClient['chatStreamAuthenticated']>[0]): Promise<void> { return this.chat.chatStreamAuthenticated(args) }\n async chatMessage(args: Parameters<ChatClient['chatMessage']>[0]): Promise<{ conversationId: string, content: string } | undefined> { return this.chat.chatMessage(args) }\n\n async getPublicAgent(args: { handle: string }): Promise<AgentConfig | undefined> { return this.user.getPublicAgent(args) }\n async getAgentByEmail(args: { email: string }): Promise<AgentConfig | undefined> { return this.user.getAgentByEmail(args) }\n generateAnonId(): string { return this.user.generateAnonId() }\n track(args: Parameters<UserClient['track']>[0]): void { return this.user.track(args) }\n}\n"],"names":["resolveApiBase","apiBase","isDev","APP_PORT","APP_PROD_URL","__name","createApiClient","settings","responseHandler","refreshHooks","baseUrl","baseFetch","createRefreshingFetch","hc","input","init","token","cookieUtil","response","originalJson","result","clean","listenerQueue","lqIndex","QUEUE_ITEMS_PER_LISTENER","atom","initialValue","listeners","$atom","listener","i","index","oldValue","changedKey","runListenerQueue","newValue","unbind","_g","$globalActiveUser","$globalToken","$globalDeviceId","_SDKStorage","__publicField","createLogger","refs","activeUser","deviceId","storedUser","storedToken","storedDevice","watch","v","savedToken","savedDevice","savedUser","error","key","value","SDKStorage","STATUS_MESSAGES","_AgentClient","ctx","args","orgId","data","msg","agentId","onStatus","timeoutMs","pollIntervalMs","start","messageIndex","status","r","url","body","res","text","AgentClient","withLoadingState","fn","_AuthClient","email","err","errorMessage","code","origin","popupUrl","width","height","left","top","popup","handler","event","expectedOrigin","user","errorMsg","checkClosed","AuthClient","_BillingClient","_args","ACTIVE_STATUSES","BillingClient","_ChatClient","errorBody","reader","decoder","buffer","resolvedConversationId","done","lines","line","chunk","delta","ChatClient","_UserClient","storageKey","anonId","objectId","UserClient","_SDKGlobal","instance","SDKGlobal","sdkGlobal","_PageLinesSDK","SettingsObject","existing","ref","computed","a","agent","org","resolve","dirty","incomingDeviceId","PageLinesSDK"],"mappings":"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","x_google_ignoreList":[1,2]}
@@ -1,10 +1,21 @@
1
1
  import { Ref } from 'vue';
2
2
  import { EnrichedUser } from '@pagelines/core';
3
+ export interface AuthRefs {
4
+ activeUser: Ref<EnrichedUser | undefined>;
5
+ token: Ref<string | null>;
6
+ deviceId: Ref<string | null>;
7
+ }
3
8
  /**
4
9
  * SDKStorage - Handles all storage, sync, and persistence for PageLinesSDK
5
10
  *
6
- * Extracted from PageLinesSDK to keep the main class focused on public API methods.
7
- * Manages localStorage, cookies, and nanostor synchronization for state persistence.
11
+ * Three storage layers, each with a clear job:
12
+ * - Vue refs — runtime source of truth (in-memory)
13
+ * - cookies — survive reload, JS-readable for headers (access token + deviceId)
14
+ * - nanostores — bridge SDK widget bundle ↔ main app bundle on same page
15
+ * - localStorage — UX optimization for cold-load (user object only, never tokens)
16
+ *
17
+ * The refresh credential lives in an HttpOnly cookie the server owns — JS
18
+ * has no access to it, so it never touches any of these layers.
8
19
  */
9
20
  export declare class SDKStorage {
10
21
  private logger;
@@ -13,19 +24,23 @@ export declare class SDKStorage {
13
24
  */
14
25
  private isLocalStorageFunctional;
15
26
  /**
16
- * Sync Vue reactive refs with global nanostores for cross-page persistence
27
+ * Sync Vue reactive refs with global nanostores for cross-bundle persistence.
17
28
  */
18
- syncWithGlobalStores(activeUser: Ref<EnrichedUser | undefined>, token: Ref<string | null>): void;
29
+ syncWithGlobalStores(refs: AuthRefs): void;
19
30
  /**
20
- * Load user and token from browser storage on initialization
31
+ * Load user and token from browser storage on initialization.
32
+ * deviceId comes from a server-set non-HttpOnly cookie (read-only for JS).
21
33
  */
22
- loadFromStorage(activeUser: Ref<EnrichedUser | undefined>, token: Ref<string | null>): void;
34
+ loadFromStorage(refs: AuthRefs): void;
23
35
  /**
24
- * Save current user and token to browser storage
36
+ * Save current user and access token to browser storage.
37
+ * deviceId is server-owned (Set-Cookie) — JS doesn't write it.
25
38
  */
26
- saveToStorage(activeUser: Ref<EnrichedUser | undefined>, token: Ref<string | null>): void;
39
+ saveToStorage(refs: AuthRefs): void;
27
40
  /**
28
- * Clear all stored user data and tokens
41
+ * Clear local stored user data and JS-owned tokens. Server-owned cookies
42
+ * (pl-refresh-token, pl-device-id) are cleared by /api/auth/logout via
43
+ * Set-Cookie max-age=0 — JS can't touch them.
29
44
  */
30
45
  clearStorage(): void;
31
46
  /**
@@ -0,0 +1,14 @@
1
+ /**
2
+ * SDK token capture — asserts the SDK persists the same fields the web
3
+ * UserClient does. Mirrors the real server response from `/verify-code`:
4
+ *
5
+ * { ok, data: { deviceId, ... }, token, user }
6
+ *
7
+ * The refresh credential is set by the server as an HttpOnly cookie
8
+ * (`pl-refresh-token`) — never present in the response body, never visible to
9
+ * JS. JS only owns the access token + deviceId at the body level.
10
+ *
11
+ * This test fails the moment the SDK regresses on capturing access token or
12
+ * deviceId.
13
+ */
14
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pagelines/sdk",
3
- "version": "1.0.470",
3
+ "version": "1.0.471",
4
4
  "description": "PageLines SDK for agent management, auth, and billing",
5
5
  "type": "module",
6
6
  "main": "./dist/sdk.js",