@promte/app-library 0.1.3 → 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/dist/index.d.ts CHANGED
@@ -97,6 +97,9 @@ export declare type PromteClient = {
97
97
  stt(req: AudioSttRequest): Promise<AudioSttResponse>;
98
98
  voices(req?: AudioVoicesRequest): Promise<AudioVoiceInfo[]>;
99
99
  };
100
+ web: {
101
+ scrapeUrl(req: ScrapeUrlRequest): Promise<ScrapeUrlResponse>;
102
+ };
100
103
  data(scope?: AppDataScope): AppDataRef;
101
104
  };
102
105
 
@@ -145,6 +148,29 @@ export declare type PromteUser = {
145
148
 
146
149
  export declare type ReasoningEffort = "minimal" | "low" | "medium" | "high";
147
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
+
148
174
  export declare function usePromte(): PromteCtxValue;
149
175
 
150
176
  export declare function usePromteClient(): PromteClient;
package/dist/index.mjs CHANGED
@@ -1,133 +1,133 @@
1
- import { jsx as B } from "react/jsx-runtime";
2
- import { createContext as L, useState as j, useMemo as P, useCallback as M, useEffect as S, useContext as D } from "react";
3
- const U = L(null);
4
- function z({
5
- children: f,
6
- expectedParentOrigin: p,
7
- initTargetOrigin: E,
8
- retryInit: d = { enabled: !0, intervalMs: 500, maxAttempts: 20 }
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
+ initTargetOrigin: v,
8
+ retryInit: l = { enabled: !0, intervalMs: 500, maxAttempts: 20 }
9
9
  }) {
10
- const [m, x] = j(null), [h, g] = j(null), [k, b] = j(null), [t, r] = j(null), [n, e] = j(null), o = P(() => n ? "booting" : m ? h ? "ready" : "waiting_for_token" : "waiting_for_settings", [m, h, n]), u = o === "ready", s = P(() => E || p || "*", [E, p]), i = M(() => {
11
- var v;
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
13
  const w = { type: "init" };
14
- (v = window.parent) == null || v.postMessage(w, s);
14
+ (o = window.parent) == null || o.postMessage(w, c);
15
15
  } catch (w) {
16
- e((w == null ? void 0 : w.message) || "Failed to post init");
16
+ n((w == null ? void 0 : w.message) || "Failed to post init");
17
17
  }
18
- }, [s]);
19
- S(() => {
20
- i();
21
- }, [i]), S(() => {
22
- if (!(d != null && d.enabled) || m) return;
23
- const v = d.intervalMs ?? 500, w = d.maxAttempts ?? 20;
24
- let c = 0;
25
- const l = window.setInterval(() => {
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
26
  if (m) {
27
- window.clearInterval(l);
27
+ window.clearInterval(f);
28
28
  return;
29
29
  }
30
- if (c += 1, c > w) {
31
- window.clearInterval(l);
30
+ if (i += 1, i > w) {
31
+ window.clearInterval(f);
32
32
  return;
33
33
  }
34
- i();
35
- }, v);
36
- return () => window.clearInterval(l);
37
- }, [d, m, i]), S(() => {
38
- const v = (w) => {
39
- if (p && w.origin !== p) return;
40
- const c = w.data;
41
- if (!(!c || typeof c != "object")) {
42
- if (c.type === "set-settings") {
43
- const l = c.value;
44
- if (!(l != null && l.backendUrl) || l.parentOrigin && p && l.parentOrigin !== p)
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
- x(l), l != null && l.user && r(l.user), e(null);
46
+ $(f), f != null && f.user && t(f.user), n(null);
47
47
  return;
48
48
  }
49
- if (c.type === "set-token" && typeof c.value == "string") {
50
- g(c.value), e(null);
49
+ if (i.type === "set-token" && typeof i.value == "string") {
50
+ x(i.value), n(null);
51
51
  return;
52
52
  }
53
- if (c.type === "set-dark-mode" && typeof c.value == "boolean") {
54
- b(c.value);
53
+ if (i.type === "set-dark-mode" && typeof i.value == "boolean") {
54
+ E(i.value);
55
55
  return;
56
56
  }
57
- if (c.type === "set-user" && typeof c.value == "object") {
58
- r(c.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", v), () => window.removeEventListener("message", v);
64
- }, [p]);
65
- const y = P(() => O(
63
+ return window.addEventListener("message", o), () => window.removeEventListener("message", o);
64
+ }, [d]);
65
+ const u = S(() => _(
66
66
  () => m,
67
- () => h
68
- ), [m, h]), a = P(
67
+ () => y
68
+ ), [m, y]), g = S(
69
69
  () => ({
70
70
  settings: m,
71
- token: h,
72
- isDarkMode: k,
73
- user: t,
74
- ready: u,
75
- state: o,
76
- error: n,
77
- client: y
71
+ token: y,
72
+ isDarkMode: h,
73
+ user: b,
74
+ ready: s,
75
+ state: e,
76
+ error: r,
77
+ client: u
78
78
  }),
79
- [m, h, k, t, u, o, n, y]
79
+ [m, y, h, b, s, e, r, u]
80
80
  );
81
- return /* @__PURE__ */ B(U.Provider, { value: a, children: f });
81
+ return /* @__PURE__ */ L(B.Provider, { value: g, children: p });
82
82
  }
83
- function $() {
84
- const f = D(U);
85
- if (!f)
83
+ function j() {
84
+ const p = D(B);
85
+ if (!p)
86
86
  throw new Error("usePromte must be used inside <PromteAppProvider>");
87
- return f;
87
+ return p;
88
88
  }
89
- function J() {
90
- return $().settings;
91
- }
92
- function N() {
93
- return $().token;
89
+ function z() {
90
+ return j().settings;
94
91
  }
95
92
  function V() {
96
- return $().isDarkMode;
93
+ return j().token;
94
+ }
95
+ function W() {
96
+ return j().isDarkMode;
97
97
  }
98
98
  function I() {
99
- return $().user;
99
+ return j().user;
100
100
  }
101
101
  function F() {
102
- return $().client;
102
+ return j().client;
103
103
  }
104
- function K(f = {}) {
105
- const { ready: p } = $(), E = F(), [d, m] = j([]), [x, h] = j(!1), [g, k] = j(null), b = P(() => (Array.isArray(f.type) ? f.type : f.type ? [f.type] : []).filter(Boolean).map((o) => String(o)).join(","), [f.type]), t = f.configuredOnly === !0, r = f.auto !== !1, n = M(async () => {
106
- if (!p) return [];
107
- h(!0), k(null);
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
108
  try {
109
- const e = b ? b.split(",").filter(Boolean) : void 0, o = await E.models({ type: e, configuredOnly: t });
110
- return m(o), o;
111
- } catch (e) {
112
- const o = e instanceof Error ? e.message : String(e);
113
- throw k(o), e;
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
114
  } finally {
115
- h(!1);
115
+ y(!1);
116
116
  }
117
- }, [E, t, p, b]);
118
- return S(() => {
119
- !r || !p || n().catch(() => {
117
+ }, [v, b, d, E]);
118
+ return P(() => {
119
+ !t || !d || r().catch(() => {
120
120
  });
121
- }, [r, p, n]), { models: d, loading: x, error: g, reload: n };
121
+ }, [t, d, r]), { models: l, loading: $, error: x, reload: r };
122
122
  }
123
- function O(f, p) {
124
- const E = (t) => typeof t == "string" && t.startsWith("gpt-5");
125
- async function d(t, r) {
126
- const n = f(), e = p();
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();
127
127
  if (!n) throw new Error("Promte settings not received yet");
128
128
  if (!e) throw new Error("Promte token not received yet");
129
- const o = n.backendUrl.replace(/\/+$/, ""), u = String(t || "").replace(/^\/+/, ""), s = `${o}/${u}`;
130
- return await fetch(s, {
129
+ const s = n.backendUrl.replace(/\/+$/, ""), c = String(t || "").replace(/^\/+/, ""), a = `${s}/${c}`;
130
+ return await fetch(a, {
131
131
  ...r,
132
132
  headers: {
133
133
  ...r.headers || {},
@@ -136,7 +136,7 @@ function O(f, p) {
136
136
  });
137
137
  }
138
138
  async function m(t, r) {
139
- const n = await d(`/app-api/data/${t}`, {
139
+ const n = await l(`/app-api/data/${t}`, {
140
140
  method: "POST",
141
141
  headers: { "Content-Type": "application/json" },
142
142
  body: JSON.stringify(r)
@@ -147,129 +147,137 @@ function O(f, p) {
147
147
  );
148
148
  return e == null ? void 0 : e.value;
149
149
  }
150
- async function x(t) {
150
+ async function $(t) {
151
151
  const r = new URLSearchParams();
152
152
  t.scope && r.set("scope", t.scope), t.path && r.set("path", t.path);
153
- const n = await d(`/app-api/data?${r.toString()}`, {
153
+ const n = await l(`/app-api/data?${r.toString()}`, {
154
154
  method: "GET"
155
155
  }), e = await n.json().catch(() => ({}));
156
156
  if (!n.ok)
157
157
  throw new Error((e == null ? void 0 : e.error) || `Request failed (${n.status})`);
158
158
  return e == null ? void 0 : e.value;
159
159
  }
160
- async function h(t) {
160
+ async function y(t) {
161
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
162
  n.length > 0 && r.set("type", n.join(",")), t != null && t.configuredOnly && r.set("configuredOnly", "true");
163
- const e = await d(
163
+ const e = await l(
164
164
  `/app-api/models${r.toString() ? `?${r.toString()}` : ""}`,
165
165
  { method: "GET" }
166
- ), o = await e.json().catch(() => ({}));
166
+ ), s = await e.json().catch(() => ({}));
167
167
  if (!e.ok)
168
- throw new Error((o == null ? void 0 : o.error) || `Request failed (${e.status})`);
169
- return (Array.isArray(o == null ? void 0 : o.models) ? o.models : []).map((s) => {
170
- if (!s || typeof s != "object") return null;
171
- const i = typeof s.id == "string" ? s.id.trim() : "", y = typeof s.label == "string" ? s.label.trim() : i, a = s.type, v = s.configured === !0, w = typeof s.source == "string" && s.source.trim() ? s.source.trim() : void 0;
172
- return !i || a !== "llm" && a !== "embedding" && a !== "image" && a !== "stt" && a !== "tts" ? null : {
173
- id: i,
174
- label: y || i,
175
- type: a,
176
- configured: v,
177
- source: w
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
178
  };
179
179
  }).filter(
180
- (s) => !!s
180
+ (a) => !!a
181
181
  );
182
182
  }
183
- const g = (t) => t ? t.split("/").map((r) => r.trim()).filter(Boolean).join("/") : "", k = (t, r) => {
184
- const n = g(t), e = g(r);
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);
185
193
  return n ? e ? `${n}/${e}` : n : e;
186
194
  }, b = (t, r) => {
187
195
  const n = { scope: t };
188
196
  return {
189
197
  async get() {
190
- const e = g(r);
191
- return x({ ...n, path: e || void 0 });
198
+ const e = h(r);
199
+ return $({ ...n, path: e || void 0 });
192
200
  },
193
201
  async set(e) {
194
- const o = g(r);
202
+ const s = h(r);
195
203
  return m("set", {
196
204
  ...n,
197
- path: o || void 0,
205
+ path: s || void 0,
198
206
  value: e
199
207
  });
200
208
  },
201
209
  async update(e) {
202
210
  if (!e || typeof e != "object")
203
211
  throw new Error("update requires an object");
204
- const o = {};
205
- for (const [u, s] of Object.entries(e)) {
206
- const i = k(r, u);
207
- if (!i)
212
+ const s = {};
213
+ for (const [c, a] of Object.entries(e)) {
214
+ const u = E(r, c);
215
+ if (!u)
208
216
  throw new Error("update paths must be non-empty");
209
- o[i] = s;
217
+ s[u] = a;
210
218
  }
211
- return m("update", { ...n, updates: o });
219
+ return m("update", { ...n, updates: s });
212
220
  },
213
221
  async remove() {
214
- const e = g(r);
222
+ const e = h(r);
215
223
  return m("remove", { ...n, path: e || void 0 });
216
224
  },
217
225
  async push(e) {
218
- const o = g(r);
219
- if (!o) throw new Error("push requires a path");
220
- return m("array-push", { ...n, path: o, value: 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 });
221
229
  },
222
230
  ref(e) {
223
- const o = k(r, e);
224
- if (!o) throw new Error("ref requires a path");
225
- return b(t, o);
231
+ const s = E(r, e);
232
+ if (!s) throw new Error("ref requires a path");
233
+ return b(t, s);
226
234
  }
227
235
  };
228
236
  };
229
237
  return {
230
238
  isReady() {
231
- return !!f() && !!p();
239
+ return !!p() && !!d();
232
240
  },
233
241
  getBackendUrl() {
234
242
  var t;
235
- return ((t = f()) == null ? void 0 : t.backendUrl) ?? null;
243
+ return ((t = p()) == null ? void 0 : t.backendUrl) ?? null;
236
244
  },
237
245
  async models(t) {
238
- return h(t);
246
+ return y(t);
239
247
  },
240
248
  async chatCompletions(t) {
241
- var a;
249
+ var o;
242
250
  const {
243
251
  reasoningEffort: r,
244
252
  reasoning_effort: n,
245
253
  ...e
246
- } = t, o = r ?? n, u = {
254
+ } = t, s = r ?? n, c = {
247
255
  ...e,
248
256
  stream: !1
249
257
  };
250
- o && E(t.model) && (u.reasoning_effort = o);
251
- const s = await d("/openai/chat/completions", {
258
+ s && v(t.model) && (c.reasoning_effort = s);
259
+ const a = await l("/openai/chat/completions", {
252
260
  method: "POST",
253
261
  headers: { "Content-Type": "application/json" },
254
- body: JSON.stringify(u)
255
- }), y = (s.headers.get("content-type") || "").includes("application/json") ? await s.json() : await s.text();
256
- if (!s.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)
257
265
  throw new Error(
258
- typeof y == "string" ? y : ((a = y == null ? void 0 : y.error) == null ? void 0 : a.message) || `Request failed (${s.status})`
266
+ typeof g == "string" ? g : ((o = g == null ? void 0 : g.error) == null ? void 0 : o.message) || `Request failed (${a.status})`
259
267
  );
260
- return y;
268
+ return g;
261
269
  },
262
270
  async chatText(t) {
263
- var n, e, o;
271
+ var n, e, s;
264
272
  const r = await this.chatCompletions(t);
265
- return ((o = (e = (n = r == null ? void 0 : r.choices) == null ? void 0 : n[0]) == null ? void 0 : e.message) == null ? void 0 : o.content) ?? "";
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) ?? "";
266
274
  },
267
275
  audio: {
268
276
  async tts(t) {
269
- var o;
270
- const r = (o = t == null ? void 0 : t.text) == null ? void 0 : o.trim();
277
+ var s;
278
+ const r = (s = t == null ? void 0 : t.text) == null ? void 0 : s.trim();
271
279
  if (!r) throw new Error("audio.tts requires non-empty text");
272
- const n = await d("/app-api/audio/tts", {
280
+ const n = await l("/app-api/audio/tts", {
273
281
  method: "POST",
274
282
  headers: { "Content-Type": "application/json" },
275
283
  body: JSON.stringify({
@@ -279,8 +287,8 @@ function O(f, p) {
279
287
  })
280
288
  });
281
289
  if (!n.ok) {
282
- const u = await n.text();
283
- throw new Error(u || `Request failed (${n.status})`);
290
+ const c = await n.text();
291
+ throw new Error(c || `Request failed (${n.status})`);
284
292
  }
285
293
  return {
286
294
  audio: await n.arrayBuffer(),
@@ -288,35 +296,35 @@ function O(f, p) {
288
296
  };
289
297
  },
290
298
  async stt(t) {
291
- var w, c, l;
299
+ var i, f, T;
292
300
  if (!(t != null && t.file)) throw new Error("audio.stt requires a file");
293
301
  const r = (R) => {
294
302
  if (!R) return;
295
- const T = R.trim();
296
- if (!T) return;
297
- const A = T.toLowerCase(), C = A.split("-")[0];
298
- return C.length === 2 ? C : A;
299
- }, n = typeof File < "u" && t.file instanceof File, e = n && t.file.name.split(".").pop() || "webm", o = t.ext || e, u = new FormData();
300
- n ? u.set("file", t.file) : u.set("file", t.file, `audio.${o}`);
301
- const s = r(t.language);
302
- s && u.set("language", s), t.prompt && u.set("prompt", t.prompt);
303
- const i = await d(
304
- `/app-api/audio/stt?ext=${encodeURIComponent(o)}`,
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)}`,
305
313
  {
306
314
  method: "POST",
307
- body: u
315
+ body: c
308
316
  }
309
- ), a = (i.headers.get("content-type") || "").includes("application/json") ? await i.json() : await i.text();
310
- if (!i.ok)
317
+ ), o = (u.headers.get("content-type") || "").includes("application/json") ? await u.json() : await u.text();
318
+ if (!u.ok)
311
319
  throw new Error(
312
- typeof a == "string" ? a : ((w = a == null ? void 0 : a.error) == null ? void 0 : w.message) || `Request failed (${i.status})`
320
+ typeof o == "string" ? o : ((i = o == null ? void 0 : o.error) == null ? void 0 : i.message) || `Request failed (${u.status})`
313
321
  );
314
- return { text: typeof a == "string" ? a : (a == null ? void 0 : a.text) || (a == null ? void 0 : a.original) || ((l = (c = a == null ? void 0 : a.results) == null ? void 0 : c[0]) == null ? void 0 : l.text) || "", raw: a };
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 };
315
323
  },
316
324
  async voices(t) {
317
325
  const r = new URLSearchParams();
318
326
  t != null && t.locale && r.set("locale", t.locale);
319
- const n = await d(
327
+ const n = await l(
320
328
  `/app-api/audio/tts/voices${r.toString() ? `?${r}` : ""}`,
321
329
  { method: "GET" }
322
330
  ), e = await n.json().catch(() => []);
@@ -327,18 +335,36 @@ function O(f, p) {
327
335
  return Array.isArray(e) ? e : (e == null ? void 0 : e.voices) || [];
328
336
  }
329
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
+ );
354
+ }
355
+ },
330
356
  data(t = "private") {
331
357
  return b(t, "");
332
358
  }
333
359
  };
334
360
  }
335
361
  export {
336
- z as PromteAppProvider,
337
- $ as usePromte,
362
+ N as PromteAppProvider,
363
+ j as usePromte,
338
364
  F as usePromteClient,
339
- V as usePromteDarkMode,
365
+ W as usePromteDarkMode,
340
366
  K as usePromteModels,
341
- J as usePromteSettings,
342
- N as usePromteToken,
367
+ z as usePromteSettings,
368
+ V as usePromteToken,
343
369
  I as usePromteUser
344
370
  };
@@ -1 +1 @@
1
- (function(y,M){typeof exports=="object"&&typeof module<"u"?M(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],M):(y=typeof globalThis<"u"?globalThis:y||self,M(y.PromteAppLibrary={},y.jsxRuntime,y.react))})(this,function(y,M,i){"use strict";const T=i.createContext(null);function L({children:p,expectedParentOrigin:d,initTargetOrigin:P,retryInit:m={enabled:!0,intervalMs:500,maxAttempts:20}}){const[w,$]=i.useState(null),[v,E]=i.useState(null),[b,S]=i.useState(null),[t,s]=i.useState(null),[n,e]=i.useState(null),o=i.useMemo(()=>n?"booting":w?v?"ready":"waiting_for_token":"waiting_for_settings",[w,v,n]),f=o==="ready",r=i.useMemo(()=>P||d||"*",[P,d]),u=i.useCallback(()=>{var k;try{const h={type:"init"};(k=window.parent)==null||k.postMessage(h,r)}catch(h){e((h==null?void 0:h.message)||"Failed to post init")}},[r]);i.useEffect(()=>{u()},[u]),i.useEffect(()=>{if(!(m!=null&&m.enabled)||w)return;const k=m.intervalMs??500,h=m.maxAttempts??20;let c=0;const l=window.setInterval(()=>{if(w){window.clearInterval(l);return}if(c+=1,c>h){window.clearInterval(l);return}u()},k);return()=>window.clearInterval(l)},[m,w,u]),i.useEffect(()=>{const k=h=>{if(d&&h.origin!==d)return;const c=h.data;if(!(!c||typeof c!="object")){if(c.type==="set-settings"){const l=c.value;if(!(l!=null&&l.backendUrl)||l.parentOrigin&&d&&l.parentOrigin!==d)return;$(l),l!=null&&l.user&&s(l.user),e(null);return}if(c.type==="set-token"&&typeof c.value=="string"){E(c.value),e(null);return}if(c.type==="set-dark-mode"&&typeof c.value=="boolean"){S(c.value);return}if(c.type==="set-user"&&typeof c.value=="object"){s(c.value);return}}};return window.addEventListener("message",k),()=>window.removeEventListener("message",k)},[d]);const g=i.useMemo(()=>G(()=>w,()=>v),[w,v]),a=i.useMemo(()=>({settings:w,token:v,isDarkMode:b,user:t,ready:f,state:o,error:n,client:g}),[w,v,b,t,f,o,n,g]);return M.jsx(T.Provider,{value:a,children:p})}function j(){const p=i.useContext(T);if(!p)throw new Error("usePromte must be used inside <PromteAppProvider>");return p}function B(){return j().settings}function D(){return j().token}function O(){return j().isDarkMode}function F(){return j().user}function R(){return j().client}function _(p={}){const{ready:d}=j(),P=R(),[m,w]=i.useState([]),[$,v]=i.useState(!1),[E,b]=i.useState(null),S=i.useMemo(()=>(Array.isArray(p.type)?p.type:p.type?[p.type]:[]).filter(Boolean).map(o=>String(o)).join(","),[p.type]),t=p.configuredOnly===!0,s=p.auto!==!1,n=i.useCallback(async()=>{if(!d)return[];v(!0),b(null);try{const e=S?S.split(",").filter(Boolean):void 0,o=await P.models({type:e,configuredOnly:t});return w(o),o}catch(e){const o=e instanceof Error?e.message:String(e);throw b(o),e}finally{v(!1)}},[P,t,d,S]);return i.useEffect(()=>{!s||!d||n().catch(()=>{})},[s,d,n]),{models:m,loading:$,error:E,reload:n}}function G(p,d){const P=t=>typeof t=="string"&&t.startsWith("gpt-5");async function m(t,s){const n=p(),e=d();if(!n)throw new Error("Promte settings not received yet");if(!e)throw new Error("Promte token not received yet");const o=n.backendUrl.replace(/\/+$/,""),f=String(t||"").replace(/^\/+/,""),r=`${o}/${f}`;return await fetch(r,{...s,headers:{...s.headers||{},Authorization:`Bearer ${e}`}})}async function w(t,s){const n=await m(`/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){const s=new URLSearchParams;t.scope&&s.set("scope",t.scope),t.path&&s.set("path",t.path);const n=await m(`/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 m(`/app-api/models${s.toString()?`?${s.toString()}`:""}`,{method:"GET"}),o=await e.json().catch(()=>({}));if(!e.ok)throw new Error((o==null?void 0:o.error)||`Request failed (${e.status})`);return(Array.isArray(o==null?void 0:o.models)?o.models:[]).map(r=>{if(!r||typeof r!="object")return null;const u=typeof r.id=="string"?r.id.trim():"",g=typeof r.label=="string"?r.label.trim():u,a=r.type,k=r.configured===!0,h=typeof r.source=="string"&&r.source.trim()?r.source.trim():void 0;return!u||a!=="llm"&&a!=="embedding"&&a!=="image"&&a!=="stt"&&a!=="tts"?null:{id:u,label:g||u,type:a,configured:k,source:h}}).filter(r=>!!r)}const E=t=>t?t.split("/").map(s=>s.trim()).filter(Boolean).join("/"):"",b=(t,s)=>{const n=E(t),e=E(s);return n?e?`${n}/${e}`:n:e},S=(t,s)=>{const n={scope:t};return{async get(){const e=E(s);return $({...n,path:e||void 0})},async set(e){const o=E(s);return w("set",{...n,path:o||void 0,value:e})},async update(e){if(!e||typeof e!="object")throw new Error("update requires an object");const o={};for(const[f,r]of Object.entries(e)){const u=b(s,f);if(!u)throw new Error("update paths must be non-empty");o[u]=r}return w("update",{...n,updates:o})},async remove(){const e=E(s);return w("remove",{...n,path:e||void 0})},async push(e){const o=E(s);if(!o)throw new Error("push requires a path");return w("array-push",{...n,path:o,value:e})},ref(e){const o=b(s,e);if(!o)throw new Error("ref requires a path");return S(t,o)}}};return{isReady(){return!!p()&&!!d()},getBackendUrl(){var t;return((t=p())==null?void 0:t.backendUrl)??null},async models(t){return v(t)},async chatCompletions(t){var a;const{reasoningEffort:s,reasoning_effort:n,...e}=t,o=s??n,f={...e,stream:!1};o&&P(t.model)&&(f.reasoning_effort=o);const r=await m("/openai/chat/completions",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(f)}),g=(r.headers.get("content-type")||"").includes("application/json")?await r.json():await r.text();if(!r.ok)throw new Error(typeof g=="string"?g:((a=g==null?void 0:g.error)==null?void 0:a.message)||`Request failed (${r.status})`);return g},async chatText(t){var n,e,o;const s=await this.chatCompletions(t);return((o=(e=(n=s==null?void 0:s.choices)==null?void 0:n[0])==null?void 0:e.message)==null?void 0:o.content)??""},audio:{async tts(t){var o;const s=(o=t==null?void 0:t.text)==null?void 0:o.trim();if(!s)throw new Error("audio.tts requires non-empty text");const n=await m("/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 f=await n.text();throw new Error(f||`Request failed (${n.status})`)}return{audio:await n.arrayBuffer(),contentType:n.headers.get("content-type")}},async stt(t){var h,c,l;if(!(t!=null&&t.file))throw new Error("audio.stt requires a file");const s=x=>{if(!x)return;const A=x.trim();if(!A)return;const C=A.toLowerCase(),U=C.split("-")[0];return U.length===2?U:C},n=typeof File<"u"&&t.file instanceof File,e=n&&t.file.name.split(".").pop()||"webm",o=t.ext||e,f=new FormData;n?f.set("file",t.file):f.set("file",t.file,`audio.${o}`);const r=s(t.language);r&&f.set("language",r),t.prompt&&f.set("prompt",t.prompt);const u=await m(`/app-api/audio/stt?ext=${encodeURIComponent(o)}`,{method:"POST",body:f}),a=(u.headers.get("content-type")||"").includes("application/json")?await u.json():await u.text();if(!u.ok)throw new Error(typeof a=="string"?a:((h=a==null?void 0:a.error)==null?void 0:h.message)||`Request failed (${u.status})`);return{text:typeof a=="string"?a:(a==null?void 0:a.text)||(a==null?void 0:a.original)||((l=(c=a==null?void 0:a.results)==null?void 0:c[0])==null?void 0:l.text)||"",raw:a}},async voices(t){const s=new URLSearchParams;t!=null&&t.locale&&s.set("locale",t.locale);const n=await m(`/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)||[]}},data(t="private"){return S(t,"")}}}y.PromteAppProvider=L,y.usePromte=j,y.usePromteClient=R,y.usePromteDarkMode=O,y.usePromteModels=_,y.usePromteSettings=B,y.usePromteToken=D,y.usePromteUser=F,Object.defineProperty(y,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.3",
3
+ "version": "0.1.4",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "files": [