@promte/app-library 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,109 @@
1
+ # @promte/app-library
2
+
3
+ Docs for using the app DB API in embedded apps.
4
+
5
+ ## What "DB" means here
6
+
7
+ In this library, DB access is exposed as:
8
+
9
+ ```ts
10
+ const client = usePromteClient();
11
+ const db = client.data(); // default scope: "private"
12
+ ```
13
+
14
+ ## Scopes
15
+
16
+ - `private` (default): data is scoped per user.
17
+ - `public`: shared for the whole workspace.
18
+ - Reads are allowed for users with workspace access.
19
+ - Writes (`set`, `update`, `remove`, `push`) require workspace admin/owner.
20
+
21
+ ```ts
22
+ const privateDb = client.data(); // same as client.data("private")
23
+ const publicDb = client.data("public");
24
+ ```
25
+
26
+ ## Paths and refs
27
+
28
+ Use slash-separated paths:
29
+
30
+ ```ts
31
+ const settingsRef = client.data("public").ref("translator/settings");
32
+ ```
33
+
34
+ Path normalization trims spaces and removes extra slashes, so `" /a//b/ "` becomes `"a/b"`.
35
+
36
+ ## Core operations
37
+
38
+ ```ts
39
+ // Read
40
+ const settings = await client.data("public").ref("translator/settings").get();
41
+
42
+ // Set/replace value at path
43
+ await client.data("public").ref("translator/settings").set({
44
+ temperature: 0.2,
45
+ });
46
+
47
+ // Update multiple child paths relative to current ref
48
+ await client.data("public").ref("translator").update({
49
+ "settings/temperature": 0.3,
50
+ "features/context": true,
51
+ });
52
+
53
+ // Remove path
54
+ await client.data("public").ref("translator/features").remove();
55
+
56
+ // Push into array at path (creates array if missing/not array)
57
+ await client.data().ref("sessions/session-1/events").push({
58
+ type: "message",
59
+ at: Date.now(),
60
+ });
61
+ ```
62
+
63
+ ## Models/capabilities
64
+
65
+ You can fetch configured models/capabilities from backend:
66
+
67
+ ```ts
68
+ const client = usePromteClient();
69
+ const allModels = await client.models();
70
+ const llmsOnly = await client.models({ type: "llm", configuredOnly: true });
71
+ ```
72
+
73
+ Or use the built-in hook:
74
+
75
+ ```ts
76
+ const { models, loading, error, reload } = usePromteModels({
77
+ type: "llm",
78
+ configuredOnly: true,
79
+ });
80
+ ```
81
+
82
+ Each model includes `id`, `label`, `type` (`llm` | `embedding` | `image` | `stt` | `tts`) and `configured`.
83
+
84
+ ## Return behavior
85
+
86
+ - `get()` returns the value at the current path, or `null` if missing.
87
+ - Mutations (`set`, `update`, `remove`, `push`) return the updated scope object.
88
+
89
+ ## Common patterns
90
+
91
+ ```ts
92
+ // Save one record by id
93
+ await client.data().ref(`sessions/${sessionId}`).set(session);
94
+
95
+ // List records under a collection-like object
96
+ const sessionsObj = await client.data().ref("sessions").get();
97
+ const sessions = sessionsObj ? Object.values(sessionsObj) : [];
98
+ ```
99
+
100
+ ## Errors to expect
101
+
102
+ - `Promte settings not received yet` / `Promte token not received yet`:
103
+ provider handshake not ready.
104
+ - `Admin only`:
105
+ trying to write to `public` scope without admin rights.
106
+ - `update requires an object`:
107
+ `ref.update(...)` got a non-object input.
108
+ - `push requires a path`:
109
+ attempted `client.data().push(...)` without a ref path.
package/dist/index.d.ts CHANGED
@@ -89,6 +89,7 @@ export declare type PromteAppProviderProps = {
89
89
  export declare type PromteClient = {
90
90
  isReady(): boolean;
91
91
  getBackendUrl(): string | null;
92
+ models(req?: PromteModelsRequest): Promise<PromteModelInfo[]>;
92
93
  chatCompletions(req: ChatCompletionsRequest): Promise<ChatCompletionsResponse>;
93
94
  chatText(req: ChatCompletionsRequest): Promise<string>;
94
95
  audio: {
@@ -96,6 +97,9 @@ export declare type PromteClient = {
96
97
  stt(req: AudioSttRequest): Promise<AudioSttResponse>;
97
98
  voices(req?: AudioVoicesRequest): Promise<AudioVoiceInfo[]>;
98
99
  };
100
+ web: {
101
+ scrapeUrl(req: ScrapeUrlRequest): Promise<ScrapeUrlResponse>;
102
+ };
99
103
  data(scope?: AppDataScope): AppDataRef;
100
104
  };
101
105
 
@@ -112,6 +116,21 @@ declare type PromteCtxValue = {
112
116
 
113
117
  export declare type PromteHandshakeState = "booting" | "waiting_for_settings" | "waiting_for_token" | "ready";
114
118
 
119
+ export declare type PromteModelInfo = {
120
+ id: string;
121
+ label: string;
122
+ type: PromteModelType;
123
+ configured: boolean;
124
+ source?: string;
125
+ };
126
+
127
+ export declare type PromteModelsRequest = {
128
+ type?: PromteModelType | PromteModelType[];
129
+ configuredOnly?: boolean;
130
+ };
131
+
132
+ export declare type PromteModelType = "llm" | "embedding" | "image" | "stt" | "tts";
133
+
115
134
  export declare type PromteSettings = {
116
135
  workspaceId: string;
117
136
  version: number;
@@ -129,12 +148,46 @@ export declare type PromteUser = {
129
148
 
130
149
  export declare type ReasoningEffort = "minimal" | "low" | "medium" | "high";
131
150
 
151
+ export declare type ScrapeUrlRequest = {
152
+ url: string;
153
+ maxChars?: number;
154
+ };
155
+
156
+ export declare type ScrapeUrlResponse = {
157
+ requestedUrl: string;
158
+ url: string;
159
+ label: string;
160
+ text: string;
161
+ title?: string;
162
+ status?: number;
163
+ extractor?: string;
164
+ warning?: string;
165
+ cached?: boolean;
166
+ fallback?: {
167
+ provider?: string;
168
+ enabled?: boolean;
169
+ attempted?: boolean;
170
+ used?: boolean;
171
+ };
172
+ };
173
+
132
174
  export declare function usePromte(): PromteCtxValue;
133
175
 
134
176
  export declare function usePromteClient(): PromteClient;
135
177
 
136
178
  export declare function usePromteDarkMode(): boolean;
137
179
 
180
+ export declare function usePromteModels(options?: UsePromteModelsOptions): {
181
+ models: PromteModelInfo[];
182
+ loading: boolean;
183
+ error: string;
184
+ reload: () => Promise<PromteModelInfo[]>;
185
+ };
186
+
187
+ export declare type UsePromteModelsOptions = PromteModelsRequest & {
188
+ auto?: boolean;
189
+ };
190
+
138
191
  export declare function usePromteSettings(): PromteSettings;
139
192
 
140
193
  export declare function usePromteToken(): string;
package/dist/index.mjs CHANGED
@@ -1,298 +1,370 @@
1
- import { jsx as M } from "react/jsx-runtime";
2
- import { createContext as A, useState as E, useMemo as j, useCallback as D, useEffect as R, useContext as L } from "react";
3
- const U = A(null);
4
- function z({
5
- children: y,
6
- expectedParentOrigin: h,
1
+ import { jsx as L } from "react/jsx-runtime";
2
+ import { createContext as O, useState as k, useMemo as S, useCallback as U, useEffect as P, useContext as D } from "react";
3
+ const B = O(null);
4
+ function N({
5
+ children: p,
6
+ expectedParentOrigin: d,
7
7
  initTargetOrigin: v,
8
- retryInit: f = { enabled: !0, intervalMs: 500, maxAttempts: 20 }
8
+ retryInit: l = { enabled: !0, intervalMs: 500, maxAttempts: 20 }
9
9
  }) {
10
- const [u, P] = E(null), [p, x] = E(null), [k, e] = E(null), [r, n] = E(null), [t, o] = E(null), i = j(() => t ? "booting" : u ? p ? "ready" : "waiting_for_token" : "waiting_for_settings", [u, p, t]), l = i === "ready", w = j(() => v || h || "*", [v, h]), d = D(() => {
11
- var g;
10
+ const [m, $] = k(null), [y, x] = k(null), [h, E] = k(null), [b, t] = k(null), [r, n] = k(null), e = S(() => r ? "booting" : m ? y ? "ready" : "waiting_for_token" : "waiting_for_settings", [m, y, r]), s = e === "ready", c = S(() => v || d || "*", [v, d]), a = U(() => {
11
+ var o;
12
12
  try {
13
- const m = { type: "init" };
14
- (g = window.parent) == null || g.postMessage(m, w);
15
- } catch (m) {
16
- o((m == null ? void 0 : m.message) || "Failed to post init");
13
+ const w = { type: "init" };
14
+ (o = window.parent) == null || o.postMessage(w, c);
15
+ } catch (w) {
16
+ n((w == null ? void 0 : w.message) || "Failed to post init");
17
17
  }
18
- }, [w]);
19
- R(() => {
20
- d();
21
- }, [d]), R(() => {
22
- if (!(f != null && f.enabled) || u) return;
23
- const g = f.intervalMs ?? 500, m = f.maxAttempts ?? 20;
24
- let a = 0;
25
- const c = window.setInterval(() => {
26
- if (u) {
27
- window.clearInterval(c);
18
+ }, [c]);
19
+ P(() => {
20
+ a();
21
+ }, [a]), P(() => {
22
+ if (!(l != null && l.enabled) || m) return;
23
+ const o = l.intervalMs ?? 500, w = l.maxAttempts ?? 20;
24
+ let i = 0;
25
+ const f = window.setInterval(() => {
26
+ if (m) {
27
+ window.clearInterval(f);
28
28
  return;
29
29
  }
30
- if (a += 1, a > m) {
31
- window.clearInterval(c);
30
+ if (i += 1, i > w) {
31
+ window.clearInterval(f);
32
32
  return;
33
33
  }
34
- d();
35
- }, g);
36
- return () => window.clearInterval(c);
37
- }, [f, u, d]), R(() => {
38
- const g = (m) => {
39
- if (h && m.origin !== h) return;
40
- const a = m.data;
41
- if (!(!a || typeof a != "object")) {
42
- if (a.type === "set-settings") {
43
- const c = a.value;
44
- if (!(c != null && c.backendUrl) || c.parentOrigin && h && c.parentOrigin !== h)
34
+ a();
35
+ }, o);
36
+ return () => window.clearInterval(f);
37
+ }, [l, m, a]), P(() => {
38
+ const o = (w) => {
39
+ if (d && w.origin !== d) return;
40
+ const i = w.data;
41
+ if (!(!i || typeof i != "object")) {
42
+ if (i.type === "set-settings") {
43
+ const f = i.value;
44
+ if (!(f != null && f.backendUrl) || f.parentOrigin && d && f.parentOrigin !== d)
45
45
  return;
46
- P(c), c != null && c.user && n(c.user), o(null);
46
+ $(f), f != null && f.user && t(f.user), n(null);
47
47
  return;
48
48
  }
49
- if (a.type === "set-token" && typeof a.value == "string") {
50
- x(a.value), o(null);
49
+ if (i.type === "set-token" && typeof i.value == "string") {
50
+ x(i.value), n(null);
51
51
  return;
52
52
  }
53
- if (a.type === "set-dark-mode" && typeof a.value == "boolean") {
54
- e(a.value);
53
+ if (i.type === "set-dark-mode" && typeof i.value == "boolean") {
54
+ E(i.value);
55
55
  return;
56
56
  }
57
- if (a.type === "set-user" && typeof a.value == "object") {
58
- n(a.value);
57
+ if (i.type === "set-user" && typeof i.value == "object") {
58
+ t(i.value);
59
59
  return;
60
60
  }
61
61
  }
62
62
  };
63
- return window.addEventListener("message", g), () => window.removeEventListener("message", g);
64
- }, [h]);
65
- const s = j(() => F(
66
- () => u,
67
- () => p
68
- ), [u, p]), T = j(
63
+ return window.addEventListener("message", o), () => window.removeEventListener("message", o);
64
+ }, [d]);
65
+ const u = S(() => _(
66
+ () => m,
67
+ () => y
68
+ ), [m, y]), g = S(
69
69
  () => ({
70
- settings: u,
71
- token: p,
72
- isDarkMode: k,
73
- user: r,
74
- ready: l,
75
- state: i,
76
- error: t,
77
- client: s
70
+ settings: m,
71
+ token: y,
72
+ isDarkMode: h,
73
+ user: b,
74
+ ready: s,
75
+ state: e,
76
+ error: r,
77
+ client: u
78
78
  }),
79
- [u, p, k, r, l, i, t, s]
79
+ [m, y, h, b, s, e, r, u]
80
80
  );
81
- return /* @__PURE__ */ M(U.Provider, { value: T, children: y });
81
+ return /* @__PURE__ */ L(B.Provider, { value: g, children: p });
82
82
  }
83
- function b() {
84
- const y = L(U);
85
- if (!y)
83
+ function j() {
84
+ const p = D(B);
85
+ if (!p)
86
86
  throw new Error("usePromte must be used inside <PromteAppProvider>");
87
- return y;
87
+ return p;
88
88
  }
89
- function G() {
90
- return b().settings;
89
+ function z() {
90
+ return j().settings;
91
91
  }
92
- function J() {
93
- return b().token;
92
+ function V() {
93
+ return j().token;
94
94
  }
95
- function N() {
96
- return b().isDarkMode;
97
- }
98
- function O() {
99
- return b().user;
95
+ function W() {
96
+ return j().isDarkMode;
100
97
  }
101
98
  function I() {
102
- return b().client;
99
+ return j().user;
100
+ }
101
+ function F() {
102
+ return j().client;
103
+ }
104
+ function K(p = {}) {
105
+ const { ready: d } = j(), v = F(), [l, m] = k([]), [$, y] = k(!1), [x, h] = k(null), E = S(() => (Array.isArray(p.type) ? p.type : p.type ? [p.type] : []).filter(Boolean).map((e) => String(e)).join(","), [p.type]), b = p.configuredOnly === !0, t = p.auto !== !1, r = U(async () => {
106
+ if (!d) return [];
107
+ y(!0), h(null);
108
+ try {
109
+ const n = E ? E.split(",").filter(Boolean) : void 0, e = await v.models({ type: n, configuredOnly: b });
110
+ return m(e), e;
111
+ } catch (n) {
112
+ const e = n instanceof Error ? n.message : String(n);
113
+ throw h(e), n;
114
+ } finally {
115
+ y(!1);
116
+ }
117
+ }, [v, b, d, E]);
118
+ return P(() => {
119
+ !t || !d || r().catch(() => {
120
+ });
121
+ }, [t, d, r]), { models: l, loading: $, error: x, reload: r };
103
122
  }
104
- function F(y, h) {
105
- const v = (e) => typeof e == "string" && e.startsWith("gpt-5");
106
- async function f(e, r) {
107
- const n = y(), t = h();
123
+ function _(p, d) {
124
+ const v = (t) => typeof t == "string" && t.startsWith("gpt-5");
125
+ async function l(t, r) {
126
+ const n = p(), e = d();
108
127
  if (!n) throw new Error("Promte settings not received yet");
109
- if (!t) throw new Error("Promte token not received yet");
110
- const o = new URL(n.backendUrl + "/" + e).toString();
111
- return await fetch(o, {
128
+ if (!e) throw new Error("Promte token not received yet");
129
+ const s = n.backendUrl.replace(/\/+$/, ""), c = String(t || "").replace(/^\/+/, ""), a = `${s}/${c}`;
130
+ return await fetch(a, {
112
131
  ...r,
113
132
  headers: {
114
133
  ...r.headers || {},
115
- Authorization: `Bearer ${t}`
134
+ Authorization: `Bearer ${e}`
116
135
  }
117
136
  });
118
137
  }
119
- async function u(e, r) {
120
- const n = await f(`/app-api/data/${e}`, {
138
+ async function m(t, r) {
139
+ const n = await l(`/app-api/data/${t}`, {
121
140
  method: "POST",
122
141
  headers: { "Content-Type": "application/json" },
123
142
  body: JSON.stringify(r)
124
- }), t = await n.json().catch(() => ({}));
143
+ }), e = await n.json().catch(() => ({}));
125
144
  if (!n.ok)
126
145
  throw new Error(
127
- (t == null ? void 0 : t.error) || `Request failed (${n.status})`
146
+ (e == null ? void 0 : e.error) || `Request failed (${n.status})`
128
147
  );
129
- return t == null ? void 0 : t.value;
148
+ return e == null ? void 0 : e.value;
130
149
  }
131
- async function P(e) {
150
+ async function $(t) {
132
151
  const r = new URLSearchParams();
133
- e.scope && r.set("scope", e.scope), e.path && r.set("path", e.path);
134
- const n = await f(`/app-api/data?${r.toString()}`, {
152
+ t.scope && r.set("scope", t.scope), t.path && r.set("path", t.path);
153
+ const n = await l(`/app-api/data?${r.toString()}`, {
135
154
  method: "GET"
136
- }), t = await n.json().catch(() => ({}));
155
+ }), e = await n.json().catch(() => ({}));
137
156
  if (!n.ok)
138
- throw new Error((t == null ? void 0 : t.error) || `Request failed (${n.status})`);
139
- return t == null ? void 0 : t.value;
157
+ throw new Error((e == null ? void 0 : e.error) || `Request failed (${n.status})`);
158
+ return e == null ? void 0 : e.value;
159
+ }
160
+ async function y(t) {
161
+ const r = new URLSearchParams(), n = Array.isArray(t == null ? void 0 : t.type) ? t == null ? void 0 : t.type : t != null && t.type ? [t.type] : [];
162
+ n.length > 0 && r.set("type", n.join(",")), t != null && t.configuredOnly && r.set("configuredOnly", "true");
163
+ const e = await l(
164
+ `/app-api/models${r.toString() ? `?${r.toString()}` : ""}`,
165
+ { method: "GET" }
166
+ ), s = await e.json().catch(() => ({}));
167
+ if (!e.ok)
168
+ throw new Error((s == null ? void 0 : s.error) || `Request failed (${e.status})`);
169
+ return (Array.isArray(s == null ? void 0 : s.models) ? s.models : []).map((a) => {
170
+ if (!a || typeof a != "object") return null;
171
+ const u = typeof a.id == "string" ? a.id.trim() : "", g = typeof a.label == "string" ? a.label.trim() : u, o = a.type, w = a.configured === !0, i = typeof a.source == "string" && a.source.trim() ? a.source.trim() : void 0;
172
+ return !u || o !== "llm" && o !== "embedding" && o !== "image" && o !== "stt" && o !== "tts" ? null : {
173
+ id: u,
174
+ label: g || u,
175
+ type: o,
176
+ configured: w,
177
+ source: i
178
+ };
179
+ }).filter(
180
+ (a) => !!a
181
+ );
140
182
  }
141
- const p = (e) => e ? e.split("/").map((r) => r.trim()).filter(Boolean).join("/") : "", x = (e, r) => {
142
- const n = p(e), t = p(r);
143
- return n ? t ? `${n}/${t}` : n : t;
144
- }, k = (e, r) => {
145
- const n = { scope: e };
183
+ async function x(t, r) {
184
+ const n = await l(t, r), s = (n.headers.get("content-type") || "").includes("application/json") ? await n.json().catch(() => ({})) : await n.text();
185
+ if (!n.ok)
186
+ throw new Error(
187
+ typeof s == "string" ? s || `Request failed (${n.status})` : (s == null ? void 0 : s.error) || (s == null ? void 0 : s.message) || `Request failed (${n.status})`
188
+ );
189
+ return s;
190
+ }
191
+ const h = (t) => t ? t.split("/").map((r) => r.trim()).filter(Boolean).join("/") : "", E = (t, r) => {
192
+ const n = h(t), e = h(r);
193
+ return n ? e ? `${n}/${e}` : n : e;
194
+ }, b = (t, r) => {
195
+ const n = { scope: t };
146
196
  return {
147
197
  async get() {
148
- const t = p(r);
149
- return P({ ...n, path: t || void 0 });
198
+ const e = h(r);
199
+ return $({ ...n, path: e || void 0 });
150
200
  },
151
- async set(t) {
152
- const o = p(r);
153
- return u("set", {
201
+ async set(e) {
202
+ const s = h(r);
203
+ return m("set", {
154
204
  ...n,
155
- path: o || void 0,
156
- value: t
205
+ path: s || void 0,
206
+ value: e
157
207
  });
158
208
  },
159
- async update(t) {
160
- if (!t || typeof t != "object")
209
+ async update(e) {
210
+ if (!e || typeof e != "object")
161
211
  throw new Error("update requires an object");
162
- const o = {};
163
- for (const [i, l] of Object.entries(t)) {
164
- const w = x(r, i);
165
- if (!w)
212
+ const s = {};
213
+ for (const [c, a] of Object.entries(e)) {
214
+ const u = E(r, c);
215
+ if (!u)
166
216
  throw new Error("update paths must be non-empty");
167
- o[w] = l;
217
+ s[u] = a;
168
218
  }
169
- return u("update", { ...n, updates: o });
219
+ return m("update", { ...n, updates: s });
170
220
  },
171
221
  async remove() {
172
- const t = p(r);
173
- return u("remove", { ...n, path: t || void 0 });
222
+ const e = h(r);
223
+ return m("remove", { ...n, path: e || void 0 });
174
224
  },
175
- async push(t) {
176
- const o = p(r);
177
- if (!o) throw new Error("push requires a path");
178
- return u("array-push", { ...n, path: o, value: t });
225
+ async push(e) {
226
+ const s = h(r);
227
+ if (!s) throw new Error("push requires a path");
228
+ return m("array-push", { ...n, path: s, value: e });
179
229
  },
180
- ref(t) {
181
- const o = x(r, t);
182
- if (!o) throw new Error("ref requires a path");
183
- return k(e, o);
230
+ ref(e) {
231
+ const s = E(r, e);
232
+ if (!s) throw new Error("ref requires a path");
233
+ return b(t, s);
184
234
  }
185
235
  };
186
236
  };
187
237
  return {
188
238
  isReady() {
189
- return !!y() && !!h();
239
+ return !!p() && !!d();
190
240
  },
191
241
  getBackendUrl() {
192
- var e;
193
- return ((e = y()) == null ? void 0 : e.backendUrl) ?? null;
242
+ var t;
243
+ return ((t = p()) == null ? void 0 : t.backendUrl) ?? null;
244
+ },
245
+ async models(t) {
246
+ return y(t);
194
247
  },
195
- async chatCompletions(e) {
196
- var s;
248
+ async chatCompletions(t) {
249
+ var o;
197
250
  const {
198
251
  reasoningEffort: r,
199
252
  reasoning_effort: n,
200
- ...t
201
- } = e, o = r ?? n, i = {
202
- ...t,
253
+ ...e
254
+ } = t, s = r ?? n, c = {
255
+ ...e,
203
256
  stream: !1
204
257
  };
205
- o && v(e.model) && (i.reasoning_effort = o);
206
- const l = await f("/openai/chat/completions", {
258
+ s && v(t.model) && (c.reasoning_effort = s);
259
+ const a = await l("/openai/chat/completions", {
207
260
  method: "POST",
208
261
  headers: { "Content-Type": "application/json" },
209
- body: JSON.stringify(i)
210
- }), d = (l.headers.get("content-type") || "").includes("application/json") ? await l.json() : await l.text();
211
- if (!l.ok)
262
+ body: JSON.stringify(c)
263
+ }), g = (a.headers.get("content-type") || "").includes("application/json") ? await a.json() : await a.text();
264
+ if (!a.ok)
212
265
  throw new Error(
213
- typeof d == "string" ? d : ((s = d == null ? void 0 : d.error) == null ? void 0 : s.message) || `Request failed (${l.status})`
266
+ typeof g == "string" ? g : ((o = g == null ? void 0 : g.error) == null ? void 0 : o.message) || `Request failed (${a.status})`
214
267
  );
215
- return d;
268
+ return g;
216
269
  },
217
- async chatText(e) {
218
- var n, t, o;
219
- const r = await this.chatCompletions(e);
220
- return ((o = (t = (n = r == null ? void 0 : r.choices) == null ? void 0 : n[0]) == null ? void 0 : t.message) == null ? void 0 : o.content) ?? "";
270
+ async chatText(t) {
271
+ var n, e, s;
272
+ const r = await this.chatCompletions(t);
273
+ return ((s = (e = (n = r == null ? void 0 : r.choices) == null ? void 0 : n[0]) == null ? void 0 : e.message) == null ? void 0 : s.content) ?? "";
221
274
  },
222
275
  audio: {
223
- async tts(e) {
224
- var o;
225
- const r = (o = e == null ? void 0 : e.text) == null ? void 0 : o.trim();
276
+ async tts(t) {
277
+ var s;
278
+ const r = (s = t == null ? void 0 : t.text) == null ? void 0 : s.trim();
226
279
  if (!r) throw new Error("audio.tts requires non-empty text");
227
- const n = await f("/app-api/audio/tts", {
280
+ const n = await l("/app-api/audio/tts", {
228
281
  method: "POST",
229
282
  headers: { "Content-Type": "application/json" },
230
283
  body: JSON.stringify({
231
284
  text: r,
232
- voice: e.voice,
233
- lang: e.lang
285
+ voice: t.voice,
286
+ lang: t.lang
234
287
  })
235
288
  });
236
289
  if (!n.ok) {
237
- const i = await n.text();
238
- throw new Error(i || `Request failed (${n.status})`);
290
+ const c = await n.text();
291
+ throw new Error(c || `Request failed (${n.status})`);
239
292
  }
240
293
  return {
241
294
  audio: await n.arrayBuffer(),
242
295
  contentType: n.headers.get("content-type")
243
296
  };
244
297
  },
245
- async stt(e) {
246
- var g, m, a;
247
- if (!(e != null && e.file)) throw new Error("audio.stt requires a file");
248
- const r = (c) => {
249
- if (!c) return;
250
- const $ = c.trim();
251
- if (!$) return;
252
- const C = $.toLowerCase(), S = C.split("-")[0];
253
- return S.length === 2 ? S : C;
254
- }, n = typeof File < "u" && e.file instanceof File, t = n && e.file.name.split(".").pop() || "webm", o = e.ext || t, i = new FormData();
255
- n ? i.set("file", e.file) : i.set("file", e.file, `audio.${o}`);
256
- const l = r(e.language);
257
- l && i.set("language", l), e.prompt && i.set("prompt", e.prompt);
258
- const w = await f(
259
- `/app-api/audio/stt?ext=${encodeURIComponent(o)}`,
298
+ async stt(t) {
299
+ var i, f, T;
300
+ if (!(t != null && t.file)) throw new Error("audio.stt requires a file");
301
+ const r = (R) => {
302
+ if (!R) return;
303
+ const C = R.trim();
304
+ if (!C) return;
305
+ const A = C.toLowerCase(), M = A.split("-")[0];
306
+ return M.length === 2 ? M : A;
307
+ }, n = typeof File < "u" && t.file instanceof File, e = n && t.file.name.split(".").pop() || "webm", s = t.ext || e, c = new FormData();
308
+ n ? c.set("file", t.file) : c.set("file", t.file, `audio.${s}`);
309
+ const a = r(t.language);
310
+ a && c.set("language", a), t.prompt && c.set("prompt", t.prompt);
311
+ const u = await l(
312
+ `/app-api/audio/stt?ext=${encodeURIComponent(s)}`,
260
313
  {
261
314
  method: "POST",
262
- body: i
315
+ body: c
263
316
  }
264
- ), s = (w.headers.get("content-type") || "").includes("application/json") ? await w.json() : await w.text();
265
- if (!w.ok)
317
+ ), o = (u.headers.get("content-type") || "").includes("application/json") ? await u.json() : await u.text();
318
+ if (!u.ok)
266
319
  throw new Error(
267
- typeof s == "string" ? s : ((g = s == null ? void 0 : s.error) == null ? void 0 : g.message) || `Request failed (${w.status})`
320
+ typeof o == "string" ? o : ((i = o == null ? void 0 : o.error) == null ? void 0 : i.message) || `Request failed (${u.status})`
268
321
  );
269
- return { text: typeof s == "string" ? s : (s == null ? void 0 : s.text) || (s == null ? void 0 : s.original) || ((a = (m = s == null ? void 0 : s.results) == null ? void 0 : m[0]) == null ? void 0 : a.text) || "", raw: s };
322
+ return { text: typeof o == "string" ? o : (o == null ? void 0 : o.text) || (o == null ? void 0 : o.original) || ((T = (f = o == null ? void 0 : o.results) == null ? void 0 : f[0]) == null ? void 0 : T.text) || "", raw: o };
270
323
  },
271
- async voices(e) {
324
+ async voices(t) {
272
325
  const r = new URLSearchParams();
273
- e != null && e.locale && r.set("locale", e.locale);
274
- const n = await f(
326
+ t != null && t.locale && r.set("locale", t.locale);
327
+ const n = await l(
275
328
  `/app-api/audio/tts/voices${r.toString() ? `?${r}` : ""}`,
276
329
  { method: "GET" }
277
- ), t = await n.json().catch(() => []);
330
+ ), e = await n.json().catch(() => []);
278
331
  if (!n.ok)
279
332
  throw new Error(
280
- (t == null ? void 0 : t.error) || `Request failed (${n.status})`
333
+ (e == null ? void 0 : e.error) || `Request failed (${n.status})`
281
334
  );
282
- return Array.isArray(t) ? t : (t == null ? void 0 : t.voices) || [];
335
+ return Array.isArray(e) ? e : (e == null ? void 0 : e.voices) || [];
336
+ }
337
+ },
338
+ web: {
339
+ async scrapeUrl(t) {
340
+ var n;
341
+ const r = (n = t == null ? void 0 : t.url) == null ? void 0 : n.trim();
342
+ if (!r) throw new Error("web.scrapeUrl requires a url");
343
+ return x(
344
+ "/app-api/web/scrape-url",
345
+ {
346
+ method: "POST",
347
+ headers: { "Content-Type": "application/json" },
348
+ body: JSON.stringify({
349
+ url: r,
350
+ maxChars: t.maxChars
351
+ })
352
+ }
353
+ );
283
354
  }
284
355
  },
285
- data(e = "private") {
286
- return k(e, "");
356
+ data(t = "private") {
357
+ return b(t, "");
287
358
  }
288
359
  };
289
360
  }
290
361
  export {
291
- z as PromteAppProvider,
292
- b as usePromte,
293
- I as usePromteClient,
294
- N as usePromteDarkMode,
295
- G as usePromteSettings,
296
- J as usePromteToken,
297
- O as usePromteUser
362
+ N as PromteAppProvider,
363
+ j as usePromte,
364
+ F as usePromteClient,
365
+ W as usePromteDarkMode,
366
+ K as usePromteModels,
367
+ z as usePromteSettings,
368
+ V as usePromteToken,
369
+ I as usePromteUser
298
370
  };
@@ -1 +1 @@
1
- (function(f,P){typeof exports=="object"&&typeof module<"u"?P(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],P):(f=typeof globalThis<"u"?globalThis:f||self,P(f.PromteAppLibrary={},f.jsxRuntime,f.react))})(this,function(f,P,c){"use strict";const x=c.createContext(null);function U({children:k,expectedParentOrigin:y,initTargetOrigin:j,retryInit:l={enabled:!0,intervalMs:500,maxAttempts:20}}){const[p,T]=c.useState(null),[m,S]=c.useState(null),[b,e]=c.useState(null),[o,n]=c.useState(null),[t,r]=c.useState(null),a=c.useMemo(()=>t?"booting":p?m?"ready":"waiting_for_token":"waiting_for_settings",[p,m,t]),d=a==="ready",h=c.useMemo(()=>j||y||"*",[j,y]),g=c.useCallback(()=>{var v;try{const w={type:"init"};(v=window.parent)==null||v.postMessage(w,h)}catch(w){r((w==null?void 0:w.message)||"Failed to post init")}},[h]);c.useEffect(()=>{g()},[g]),c.useEffect(()=>{if(!(l!=null&&l.enabled)||p)return;const v=l.intervalMs??500,w=l.maxAttempts??20;let i=0;const u=window.setInterval(()=>{if(p){window.clearInterval(u);return}if(i+=1,i>w){window.clearInterval(u);return}g()},v);return()=>window.clearInterval(u)},[l,p,g]),c.useEffect(()=>{const v=w=>{if(y&&w.origin!==y)return;const i=w.data;if(!(!i||typeof i!="object")){if(i.type==="set-settings"){const u=i.value;if(!(u!=null&&u.backendUrl)||u.parentOrigin&&y&&u.parentOrigin!==y)return;T(u),u!=null&&u.user&&n(u.user),r(null);return}if(i.type==="set-token"&&typeof i.value=="string"){S(i.value),r(null);return}if(i.type==="set-dark-mode"&&typeof i.value=="boolean"){e(i.value);return}if(i.type==="set-user"&&typeof i.value=="object"){n(i.value);return}}};return window.addEventListener("message",v),()=>window.removeEventListener("message",v)},[y]);const s=c.useMemo(()=>B(()=>p,()=>m),[p,m]),R=c.useMemo(()=>({settings:p,token:m,isDarkMode:b,user:o,ready:d,state:a,error:t,client:s}),[p,m,b,o,d,a,t,s]);return P.jsx(x.Provider,{value:R,children:k})}function E(){const k=c.useContext(x);if(!k)throw new Error("usePromte must be used inside <PromteAppProvider>");return k}function A(){return E().settings}function D(){return E().token}function L(){return E().isDarkMode}function F(){return E().user}function _(){return E().client}function B(k,y){const j=e=>typeof e=="string"&&e.startsWith("gpt-5");async function l(e,o){const n=k(),t=y();if(!n)throw new Error("Promte settings not received yet");if(!t)throw new Error("Promte token not received yet");const r=new URL(n.backendUrl+"/"+e).toString();return await fetch(r,{...o,headers:{...o.headers||{},Authorization:`Bearer ${t}`}})}async function p(e,o){const n=await l(`/app-api/data/${e}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(o)}),t=await n.json().catch(()=>({}));if(!n.ok)throw new Error((t==null?void 0:t.error)||`Request failed (${n.status})`);return t==null?void 0:t.value}async function T(e){const o=new URLSearchParams;e.scope&&o.set("scope",e.scope),e.path&&o.set("path",e.path);const n=await l(`/app-api/data?${o.toString()}`,{method:"GET"}),t=await n.json().catch(()=>({}));if(!n.ok)throw new Error((t==null?void 0:t.error)||`Request failed (${n.status})`);return t==null?void 0:t.value}const m=e=>e?e.split("/").map(o=>o.trim()).filter(Boolean).join("/"):"",S=(e,o)=>{const n=m(e),t=m(o);return n?t?`${n}/${t}`:n:t},b=(e,o)=>{const n={scope:e};return{async get(){const t=m(o);return T({...n,path:t||void 0})},async set(t){const r=m(o);return p("set",{...n,path:r||void 0,value:t})},async update(t){if(!t||typeof t!="object")throw new Error("update requires an object");const r={};for(const[a,d]of Object.entries(t)){const h=S(o,a);if(!h)throw new Error("update paths must be non-empty");r[h]=d}return p("update",{...n,updates:r})},async remove(){const t=m(o);return p("remove",{...n,path:t||void 0})},async push(t){const r=m(o);if(!r)throw new Error("push requires a path");return p("array-push",{...n,path:r,value:t})},ref(t){const r=S(o,t);if(!r)throw new Error("ref requires a path");return b(e,r)}}};return{isReady(){return!!k()&&!!y()},getBackendUrl(){var e;return((e=k())==null?void 0:e.backendUrl)??null},async chatCompletions(e){var s;const{reasoningEffort:o,reasoning_effort:n,...t}=e,r=o??n,a={...t,stream:!1};r&&j(e.model)&&(a.reasoning_effort=r);const d=await l("/openai/chat/completions",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)}),g=(d.headers.get("content-type")||"").includes("application/json")?await d.json():await d.text();if(!d.ok)throw new Error(typeof g=="string"?g:((s=g==null?void 0:g.error)==null?void 0:s.message)||`Request failed (${d.status})`);return g},async chatText(e){var n,t,r;const o=await this.chatCompletions(e);return((r=(t=(n=o==null?void 0:o.choices)==null?void 0:n[0])==null?void 0:t.message)==null?void 0:r.content)??""},audio:{async tts(e){var r;const o=(r=e==null?void 0:e.text)==null?void 0:r.trim();if(!o)throw new Error("audio.tts requires non-empty text");const n=await l("/app-api/audio/tts",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({text:o,voice:e.voice,lang:e.lang})});if(!n.ok){const a=await n.text();throw new Error(a||`Request failed (${n.status})`)}return{audio:await n.arrayBuffer(),contentType:n.headers.get("content-type")}},async stt(e){var v,w,i;if(!(e!=null&&e.file))throw new Error("audio.stt requires a file");const o=u=>{if(!u)return;const C=u.trim();if(!C)return;const M=C.toLowerCase(),$=M.split("-")[0];return $.length===2?$:M},n=typeof File<"u"&&e.file instanceof File,t=n&&e.file.name.split(".").pop()||"webm",r=e.ext||t,a=new FormData;n?a.set("file",e.file):a.set("file",e.file,`audio.${r}`);const d=o(e.language);d&&a.set("language",d),e.prompt&&a.set("prompt",e.prompt);const h=await l(`/app-api/audio/stt?ext=${encodeURIComponent(r)}`,{method:"POST",body:a}),s=(h.headers.get("content-type")||"").includes("application/json")?await h.json():await h.text();if(!h.ok)throw new Error(typeof s=="string"?s:((v=s==null?void 0:s.error)==null?void 0:v.message)||`Request failed (${h.status})`);return{text:typeof s=="string"?s:(s==null?void 0:s.text)||(s==null?void 0:s.original)||((i=(w=s==null?void 0:s.results)==null?void 0:w[0])==null?void 0:i.text)||"",raw:s}},async voices(e){const o=new URLSearchParams;e!=null&&e.locale&&o.set("locale",e.locale);const n=await l(`/app-api/audio/tts/voices${o.toString()?`?${o}`:""}`,{method:"GET"}),t=await n.json().catch(()=>[]);if(!n.ok)throw new Error((t==null?void 0:t.error)||`Request failed (${n.status})`);return Array.isArray(t)?t:(t==null?void 0:t.voices)||[]}},data(e="private"){return b(e,"")}}}f.PromteAppProvider=U,f.usePromte=E,f.usePromteClient=_,f.usePromteDarkMode=L,f.usePromteSettings=A,f.usePromteToken=D,f.usePromteUser=F,Object.defineProperty(f,Symbol.toStringTag,{value:"Module"})});
1
+ (function(y,j){typeof exports=="object"&&typeof module<"u"?j(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],j):(y=typeof globalThis<"u"?globalThis:y||self,j(y.PromteAppLibrary={},y.jsxRuntime,y.react))})(this,function(y,j,i){"use strict";const M=i.createContext(null);function O({children:d,expectedParentOrigin:m,initTargetOrigin:b,retryInit:l={enabled:!0,intervalMs:500,maxAttempts:20}}){const[w,T]=i.useState(null),[v,$]=i.useState(null),[g,k]=i.useState(null),[P,t]=i.useState(null),[s,n]=i.useState(null),e=i.useMemo(()=>s?"booting":w?v?"ready":"waiting_for_token":"waiting_for_settings",[w,v,s]),r=e==="ready",c=i.useMemo(()=>b||m||"*",[b,m]),a=i.useCallback(()=>{var o;try{const h={type:"init"};(o=window.parent)==null||o.postMessage(h,c)}catch(h){n((h==null?void 0:h.message)||"Failed to post init")}},[c]);i.useEffect(()=>{a()},[a]),i.useEffect(()=>{if(!(l!=null&&l.enabled)||w)return;const o=l.intervalMs??500,h=l.maxAttempts??20;let u=0;const p=window.setInterval(()=>{if(w){window.clearInterval(p);return}if(u+=1,u>h){window.clearInterval(p);return}a()},o);return()=>window.clearInterval(p)},[l,w,a]),i.useEffect(()=>{const o=h=>{if(m&&h.origin!==m)return;const u=h.data;if(!(!u||typeof u!="object")){if(u.type==="set-settings"){const p=u.value;if(!(p!=null&&p.backendUrl)||p.parentOrigin&&m&&p.parentOrigin!==m)return;T(p),p!=null&&p.user&&t(p.user),n(null);return}if(u.type==="set-token"&&typeof u.value=="string"){$(u.value),n(null);return}if(u.type==="set-dark-mode"&&typeof u.value=="boolean"){k(u.value);return}if(u.type==="set-user"&&typeof u.value=="object"){t(u.value);return}}};return window.addEventListener("message",o),()=>window.removeEventListener("message",o)},[m]);const f=i.useMemo(()=>J(()=>w,()=>v),[w,v]),E=i.useMemo(()=>({settings:w,token:v,isDarkMode:g,user:P,ready:r,state:e,error:s,client:f}),[w,v,g,P,r,e,s,f]);return j.jsx(M.Provider,{value:E,children:d})}function S(){const d=i.useContext(M);if(!d)throw new Error("usePromte must be used inside <PromteAppProvider>");return d}function B(){return S().settings}function D(){return S().token}function F(){return S().isDarkMode}function _(){return S().user}function R(){return S().client}function G(d={}){const{ready:m}=S(),b=R(),[l,w]=i.useState([]),[T,v]=i.useState(!1),[$,g]=i.useState(null),k=i.useMemo(()=>(Array.isArray(d.type)?d.type:d.type?[d.type]:[]).filter(Boolean).map(e=>String(e)).join(","),[d.type]),P=d.configuredOnly===!0,t=d.auto!==!1,s=i.useCallback(async()=>{if(!m)return[];v(!0),g(null);try{const n=k?k.split(",").filter(Boolean):void 0,e=await b.models({type:n,configuredOnly:P});return w(e),e}catch(n){const e=n instanceof Error?n.message:String(n);throw g(e),n}finally{v(!1)}},[b,P,m,k]);return i.useEffect(()=>{!t||!m||s().catch(()=>{})},[t,m,s]),{models:l,loading:T,error:$,reload:s}}function J(d,m){const b=t=>typeof t=="string"&&t.startsWith("gpt-5");async function l(t,s){const n=d(),e=m();if(!n)throw new Error("Promte settings not received yet");if(!e)throw new Error("Promte token not received yet");const r=n.backendUrl.replace(/\/+$/,""),c=String(t||"").replace(/^\/+/,""),a=`${r}/${c}`;return await fetch(a,{...s,headers:{...s.headers||{},Authorization:`Bearer ${e}`}})}async function w(t,s){const n=await l(`/app-api/data/${t}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)}),e=await n.json().catch(()=>({}));if(!n.ok)throw new Error((e==null?void 0:e.error)||`Request failed (${n.status})`);return e==null?void 0:e.value}async function T(t){const s=new URLSearchParams;t.scope&&s.set("scope",t.scope),t.path&&s.set("path",t.path);const n=await l(`/app-api/data?${s.toString()}`,{method:"GET"}),e=await n.json().catch(()=>({}));if(!n.ok)throw new Error((e==null?void 0:e.error)||`Request failed (${n.status})`);return e==null?void 0:e.value}async function v(t){const s=new URLSearchParams,n=Array.isArray(t==null?void 0:t.type)?t==null?void 0:t.type:t!=null&&t.type?[t.type]:[];n.length>0&&s.set("type",n.join(",")),t!=null&&t.configuredOnly&&s.set("configuredOnly","true");const e=await l(`/app-api/models${s.toString()?`?${s.toString()}`:""}`,{method:"GET"}),r=await e.json().catch(()=>({}));if(!e.ok)throw new Error((r==null?void 0:r.error)||`Request failed (${e.status})`);return(Array.isArray(r==null?void 0:r.models)?r.models:[]).map(a=>{if(!a||typeof a!="object")return null;const f=typeof a.id=="string"?a.id.trim():"",E=typeof a.label=="string"?a.label.trim():f,o=a.type,h=a.configured===!0,u=typeof a.source=="string"&&a.source.trim()?a.source.trim():void 0;return!f||o!=="llm"&&o!=="embedding"&&o!=="image"&&o!=="stt"&&o!=="tts"?null:{id:f,label:E||f,type:o,configured:h,source:u}}).filter(a=>!!a)}async function $(t,s){const n=await l(t,s),r=(n.headers.get("content-type")||"").includes("application/json")?await n.json().catch(()=>({})):await n.text();if(!n.ok)throw new Error(typeof r=="string"?r||`Request failed (${n.status})`:(r==null?void 0:r.error)||(r==null?void 0:r.message)||`Request failed (${n.status})`);return r}const g=t=>t?t.split("/").map(s=>s.trim()).filter(Boolean).join("/"):"",k=(t,s)=>{const n=g(t),e=g(s);return n?e?`${n}/${e}`:n:e},P=(t,s)=>{const n={scope:t};return{async get(){const e=g(s);return T({...n,path:e||void 0})},async set(e){const r=g(s);return w("set",{...n,path:r||void 0,value:e})},async update(e){if(!e||typeof e!="object")throw new Error("update requires an object");const r={};for(const[c,a]of Object.entries(e)){const f=k(s,c);if(!f)throw new Error("update paths must be non-empty");r[f]=a}return w("update",{...n,updates:r})},async remove(){const e=g(s);return w("remove",{...n,path:e||void 0})},async push(e){const r=g(s);if(!r)throw new Error("push requires a path");return w("array-push",{...n,path:r,value:e})},ref(e){const r=k(s,e);if(!r)throw new Error("ref requires a path");return P(t,r)}}};return{isReady(){return!!d()&&!!m()},getBackendUrl(){var t;return((t=d())==null?void 0:t.backendUrl)??null},async models(t){return v(t)},async chatCompletions(t){var o;const{reasoningEffort:s,reasoning_effort:n,...e}=t,r=s??n,c={...e,stream:!1};r&&b(t.model)&&(c.reasoning_effort=r);const a=await l("/openai/chat/completions",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(c)}),E=(a.headers.get("content-type")||"").includes("application/json")?await a.json():await a.text();if(!a.ok)throw new Error(typeof E=="string"?E:((o=E==null?void 0:E.error)==null?void 0:o.message)||`Request failed (${a.status})`);return E},async chatText(t){var n,e,r;const s=await this.chatCompletions(t);return((r=(e=(n=s==null?void 0:s.choices)==null?void 0:n[0])==null?void 0:e.message)==null?void 0:r.content)??""},audio:{async tts(t){var r;const s=(r=t==null?void 0:t.text)==null?void 0:r.trim();if(!s)throw new Error("audio.tts requires non-empty text");const n=await l("/app-api/audio/tts",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({text:s,voice:t.voice,lang:t.lang})});if(!n.ok){const c=await n.text();throw new Error(c||`Request failed (${n.status})`)}return{audio:await n.arrayBuffer(),contentType:n.headers.get("content-type")}},async stt(t){var u,p,x;if(!(t!=null&&t.file))throw new Error("audio.stt requires a file");const s=C=>{if(!C)return;const A=C.trim();if(!A)return;const U=A.toLowerCase(),L=U.split("-")[0];return L.length===2?L:U},n=typeof File<"u"&&t.file instanceof File,e=n&&t.file.name.split(".").pop()||"webm",r=t.ext||e,c=new FormData;n?c.set("file",t.file):c.set("file",t.file,`audio.${r}`);const a=s(t.language);a&&c.set("language",a),t.prompt&&c.set("prompt",t.prompt);const f=await l(`/app-api/audio/stt?ext=${encodeURIComponent(r)}`,{method:"POST",body:c}),o=(f.headers.get("content-type")||"").includes("application/json")?await f.json():await f.text();if(!f.ok)throw new Error(typeof o=="string"?o:((u=o==null?void 0:o.error)==null?void 0:u.message)||`Request failed (${f.status})`);return{text:typeof o=="string"?o:(o==null?void 0:o.text)||(o==null?void 0:o.original)||((x=(p=o==null?void 0:o.results)==null?void 0:p[0])==null?void 0:x.text)||"",raw:o}},async voices(t){const s=new URLSearchParams;t!=null&&t.locale&&s.set("locale",t.locale);const n=await l(`/app-api/audio/tts/voices${s.toString()?`?${s}`:""}`,{method:"GET"}),e=await n.json().catch(()=>[]);if(!n.ok)throw new Error((e==null?void 0:e.error)||`Request failed (${n.status})`);return Array.isArray(e)?e:(e==null?void 0:e.voices)||[]}},web:{async scrapeUrl(t){var n;const s=(n=t==null?void 0:t.url)==null?void 0:n.trim();if(!s)throw new Error("web.scrapeUrl requires a url");return $("/app-api/web/scrape-url",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:s,maxChars:t.maxChars})})}},data(t="private"){return P(t,"")}}}y.PromteAppProvider=O,y.usePromte=S,y.usePromteClient=R,y.usePromteDarkMode=F,y.usePromteModels=G,y.usePromteSettings=B,y.usePromteToken=D,y.usePromteUser=_,Object.defineProperty(y,Symbol.toStringTag,{value:"Module"})});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@promte/app-library",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "files": [