@promte/app-library 0.1.5 → 0.1.6

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 CHANGED
@@ -105,6 +105,29 @@ const response = await client.embeddings.create({
105
105
  const vectors = response.data.map((item) => item.embedding);
106
106
  ```
107
107
 
108
+ ## Knowledge search
109
+
110
+ Apps can search an assistant/workspace knowledge base directly:
111
+
112
+ ```ts
113
+ const client = usePromteClient();
114
+
115
+ const response = await client.knowledge.search({
116
+ workspaceId: "assistant-workspace-id",
117
+ query: "Hvad gælder for carporte i BR18?",
118
+ maxResults: 8,
119
+ generateSearchQuery: true,
120
+ });
121
+
122
+ for (const result of response.results) {
123
+ console.log(result.title, result.text, result.sourceUrl);
124
+ }
125
+ ```
126
+
127
+ If `workspaceId` is omitted, the search uses the current app workspace. Searching
128
+ another workspace requires that the current user has access to that workspace.
129
+ Public app tokens can only search their own workspace.
130
+
108
131
  ## Return behavior
109
132
 
110
133
  - `get()` returns the value at the current path, or `null` if missing.
package/dist/index.d.ts CHANGED
@@ -99,6 +99,41 @@ export declare type EmbeddingsResponse = {
99
99
  [key: string]: any;
100
100
  };
101
101
 
102
+ export declare type KnowledgeSearchRequest = {
103
+ workspaceId?: string;
104
+ query: string;
105
+ maxResults?: number;
106
+ generateSearchQuery?: boolean;
107
+ sourceId?: string;
108
+ includeSourceUrls?: boolean;
109
+ queries?: string[];
110
+ };
111
+
112
+ export declare type KnowledgeSearchResponse = {
113
+ workspaceId: string;
114
+ workspaceName?: string;
115
+ query: string;
116
+ searchQueries: string[];
117
+ maxResults: number;
118
+ results: KnowledgeSearchResult[];
119
+ sourceIds: string[];
120
+ chunkIds: string[];
121
+ };
122
+
123
+ export declare type KnowledgeSearchResult = {
124
+ index: number;
125
+ id: string;
126
+ chunkId: string;
127
+ sourceWorkspaceId: string;
128
+ sourceId: string;
129
+ sourceName?: string;
130
+ title: string;
131
+ text: string;
132
+ relevance?: number;
133
+ link?: string;
134
+ sourceUrl?: string;
135
+ };
136
+
102
137
  export declare function PromteAppProvider({ children, expectedParentOrigin, initTargetOrigin, retryInit, }: PromteAppProviderProps): JSX_2.Element;
103
138
 
104
139
  export declare type PromteAppProviderProps = {
@@ -129,6 +164,9 @@ export declare type PromteClient = {
129
164
  web: {
130
165
  scrapeUrl(req: ScrapeUrlRequest): Promise<ScrapeUrlResponse>;
131
166
  };
167
+ knowledge: {
168
+ search(req: KnowledgeSearchRequest): Promise<KnowledgeSearchResponse>;
169
+ };
132
170
  data(scope?: AppDataScope): AppDataRef;
133
171
  };
134
172
 
package/dist/index.mjs CHANGED
@@ -1,13 +1,13 @@
1
1
  import { jsx as B } from "react/jsx-runtime";
2
- import { createContext as L, useState as k, useMemo as x, useCallback as U, useEffect as T, useContext as D } from "react";
2
+ import { createContext as L, useState as k, useMemo as T, useCallback as M, useEffect as $, useContext as D } from "react";
3
3
  const O = L(null);
4
- function N({
4
+ function _({
5
5
  children: p,
6
6
  expectedParentOrigin: d,
7
7
  initTargetOrigin: v,
8
8
  retryInit: l = { enabled: !0, intervalMs: 500, maxAttempts: 20 }
9
9
  }) {
10
- const [m, $] = k(null), [y, j] = k(null), [h, b] = k(null), [E, t] = k(null), [r, e] = k(null), n = x(() => r ? "booting" : m ? y ? "ready" : "waiting_for_token" : "waiting_for_settings", [m, y, r]), s = n === "ready", c = x(() => v || d || "*", [v, d]), a = U(() => {
10
+ const [m, x] = k(null), [h, S] = k(null), [y, b] = k(null), [E, t] = k(null), [r, e] = k(null), n = T(() => r ? "booting" : m ? h ? "ready" : "waiting_for_token" : "waiting_for_settings", [m, h, r]), s = n === "ready", c = T(() => v || d || "*", [v, d]), a = M(() => {
11
11
  var o;
12
12
  try {
13
13
  const w = { type: "init" };
@@ -16,9 +16,9 @@ function N({
16
16
  e((w == null ? void 0 : w.message) || "Failed to post init");
17
17
  }
18
18
  }, [c]);
19
- T(() => {
19
+ $(() => {
20
20
  a();
21
- }, [a]), T(() => {
21
+ }, [a]), $(() => {
22
22
  if (!(l != null && l.enabled) || m) return;
23
23
  const o = l.intervalMs ?? 500, w = l.maxAttempts ?? 20;
24
24
  let i = 0;
@@ -34,7 +34,7 @@ function N({
34
34
  a();
35
35
  }, o);
36
36
  return () => window.clearInterval(f);
37
- }, [l, m, a]), T(() => {
37
+ }, [l, m, a]), $(() => {
38
38
  const o = (w) => {
39
39
  if (d && w.origin !== d) return;
40
40
  const i = w.data;
@@ -43,11 +43,11 @@ function N({
43
43
  const f = i.value;
44
44
  if (!(f != null && f.backendUrl) || f.parentOrigin && d && f.parentOrigin !== d)
45
45
  return;
46
- $(f), f != null && f.user && t(f.user), e(null);
46
+ x(f), f != null && f.user && t(f.user), e(null);
47
47
  return;
48
48
  }
49
49
  if (i.type === "set-token" && typeof i.value == "string") {
50
- j(i.value), e(null);
50
+ S(i.value), e(null);
51
51
  return;
52
52
  }
53
53
  if (i.type === "set-dark-mode" && typeof i.value == "boolean") {
@@ -62,65 +62,65 @@ function N({
62
62
  };
63
63
  return window.addEventListener("message", o), () => window.removeEventListener("message", o);
64
64
  }, [d]);
65
- const u = x(() => _(
65
+ const u = T(() => F(
66
66
  () => m,
67
- () => y
68
- ), [m, y]), g = x(
67
+ () => h
68
+ ), [m, h]), g = T(
69
69
  () => ({
70
70
  settings: m,
71
- token: y,
72
- isDarkMode: h,
71
+ token: h,
72
+ isDarkMode: y,
73
73
  user: E,
74
74
  ready: s,
75
75
  state: n,
76
76
  error: r,
77
77
  client: u
78
78
  }),
79
- [m, y, h, E, s, n, r, u]
79
+ [m, h, y, E, s, n, r, u]
80
80
  );
81
81
  return /* @__PURE__ */ B(O.Provider, { value: g, children: p });
82
82
  }
83
- function S() {
83
+ function j() {
84
84
  const p = D(O);
85
85
  if (!p)
86
86
  throw new Error("usePromte must be used inside <PromteAppProvider>");
87
87
  return p;
88
88
  }
89
- function z() {
90
- return S().settings;
89
+ function G() {
90
+ return j().settings;
91
91
  }
92
- function I() {
93
- return S().token;
92
+ function z() {
93
+ return j().token;
94
94
  }
95
95
  function V() {
96
- return S().isDarkMode;
96
+ return j().isDarkMode;
97
97
  }
98
- function W() {
99
- return S().user;
98
+ function Q() {
99
+ return j().user;
100
100
  }
101
- function F() {
102
- return S().client;
101
+ function I() {
102
+ return j().client;
103
103
  }
104
- function K(p = {}) {
105
- const { ready: d } = S(), v = F(), [l, m] = k([]), [$, y] = k(!1), [j, h] = k(null), b = x(() => (Array.isArray(p.type) ? p.type : p.type ? [p.type] : []).filter(Boolean).map((n) => String(n)).join(","), [p.type]), E = p.configuredOnly === !0, t = p.auto !== !1, r = U(async () => {
104
+ function W(p = {}) {
105
+ const { ready: d } = j(), v = I(), [l, m] = k([]), [x, h] = k(!1), [S, y] = k(null), b = T(() => (Array.isArray(p.type) ? p.type : p.type ? [p.type] : []).filter(Boolean).map((n) => String(n)).join(","), [p.type]), E = p.configuredOnly === !0, t = p.auto !== !1, r = M(async () => {
106
106
  if (!d) return [];
107
- y(!0), h(null);
107
+ h(!0), y(null);
108
108
  try {
109
109
  const e = b ? b.split(",").filter(Boolean) : void 0, n = await v.models({ type: e, configuredOnly: E });
110
110
  return m(n), n;
111
111
  } catch (e) {
112
112
  const n = e instanceof Error ? e.message : String(e);
113
- throw h(n), e;
113
+ throw y(n), e;
114
114
  } finally {
115
- y(!1);
115
+ h(!1);
116
116
  }
117
117
  }, [v, E, d, b]);
118
- return T(() => {
118
+ return $(() => {
119
119
  !t || !d || r().catch(() => {
120
120
  });
121
- }, [t, d, r]), { models: l, loading: $, error: j, reload: r };
121
+ }, [t, d, r]), { models: l, loading: x, error: S, reload: r };
122
122
  }
123
- function _(p, d) {
123
+ function F(p, d) {
124
124
  const v = (t) => typeof t == "string" && t.startsWith("gpt-5");
125
125
  async function l(t, r) {
126
126
  const e = p(), n = d();
@@ -147,7 +147,7 @@ function _(p, d) {
147
147
  );
148
148
  return n == null ? void 0 : n.value;
149
149
  }
150
- async function $(t) {
150
+ async function x(t) {
151
151
  const r = new URLSearchParams();
152
152
  t.scope && r.set("scope", t.scope), t.path && r.set("path", t.path);
153
153
  const e = await l(`/app-api/data?${r.toString()}`, {
@@ -157,7 +157,7 @@ function _(p, d) {
157
157
  throw new Error((n == null ? void 0 : n.error) || `Request failed (${e.status})`);
158
158
  return n == null ? void 0 : n.value;
159
159
  }
160
- async function y(t) {
160
+ async function h(t) {
161
161
  const r = new URLSearchParams(), e = Array.isArray(t == null ? void 0 : t.type) ? t == null ? void 0 : t.type : t != null && t.type ? [t.type] : [];
162
162
  e.length > 0 && r.set("type", e.join(",")), t != null && t.configuredOnly && r.set("configuredOnly", "true");
163
163
  const n = await l(
@@ -180,7 +180,7 @@ function _(p, d) {
180
180
  (a) => !!a
181
181
  );
182
182
  }
183
- async function j(t, r) {
183
+ async function S(t, r) {
184
184
  const e = await l(t, r), s = (e.headers.get("content-type") || "").includes("application/json") ? await e.json().catch(() => ({})) : await e.text();
185
185
  if (!e.ok)
186
186
  throw new Error(
@@ -188,18 +188,18 @@ function _(p, d) {
188
188
  );
189
189
  return s;
190
190
  }
191
- const h = (t) => t ? t.split("/").map((r) => r.trim()).filter(Boolean).join("/") : "", b = (t, r) => {
192
- const e = h(t), n = h(r);
191
+ const y = (t) => t ? t.split("/").map((r) => r.trim()).filter(Boolean).join("/") : "", b = (t, r) => {
192
+ const e = y(t), n = y(r);
193
193
  return e ? n ? `${e}/${n}` : e : n;
194
194
  }, E = (t, r) => {
195
195
  const e = { scope: t };
196
196
  return {
197
197
  async get() {
198
- const n = h(r);
199
- return $({ ...e, path: n || void 0 });
198
+ const n = y(r);
199
+ return x({ ...e, path: n || void 0 });
200
200
  },
201
201
  async set(n) {
202
- const s = h(r);
202
+ const s = y(r);
203
203
  return m("set", {
204
204
  ...e,
205
205
  path: s || void 0,
@@ -219,11 +219,11 @@ function _(p, d) {
219
219
  return m("update", { ...e, updates: s });
220
220
  },
221
221
  async remove() {
222
- const n = h(r);
222
+ const n = y(r);
223
223
  return m("remove", { ...e, path: n || void 0 });
224
224
  },
225
225
  async push(n) {
226
- const s = h(r);
226
+ const s = y(r);
227
227
  if (!s) throw new Error("push requires a path");
228
228
  return m("array-push", { ...e, path: s, value: n });
229
229
  },
@@ -243,7 +243,7 @@ function _(p, d) {
243
243
  return ((t = p()) == null ? void 0 : t.backendUrl) ?? null;
244
244
  },
245
245
  async models(t) {
246
- return y(t);
246
+ return h(t);
247
247
  },
248
248
  async chatCompletions(t) {
249
249
  var o;
@@ -282,7 +282,7 @@ function _(p, d) {
282
282
  throw new Error(
283
283
  "embeddings.create requires input as a string or string[]"
284
284
  );
285
- return j("/openai/embeddings", {
285
+ return S("/openai/embeddings", {
286
286
  method: "POST",
287
287
  headers: { "Content-Type": "application/json" },
288
288
  body: JSON.stringify({
@@ -323,8 +323,8 @@ function _(p, d) {
323
323
  if (!R) return;
324
324
  const C = R.trim();
325
325
  if (!C) return;
326
- const A = C.toLowerCase(), M = A.split("-")[0];
327
- return M.length === 2 ? M : A;
326
+ const A = C.toLowerCase(), U = A.split("-")[0];
327
+ return U.length === 2 ? U : A;
328
328
  }, e = typeof File < "u" && t.file instanceof File, n = e && t.file.name.split(".").pop() || "webm", s = t.ext || n, c = new FormData();
329
329
  e ? c.set("file", t.file) : c.set("file", t.file, `audio.${s}`);
330
330
  const a = r(t.language);
@@ -361,7 +361,7 @@ function _(p, d) {
361
361
  var e;
362
362
  const r = (e = t == null ? void 0 : t.url) == null ? void 0 : e.trim();
363
363
  if (!r) throw new Error("web.scrapeUrl requires a url");
364
- return j(
364
+ return S(
365
365
  "/app-api/web/scrape-url",
366
366
  {
367
367
  method: "POST",
@@ -374,18 +374,41 @@ function _(p, d) {
374
374
  );
375
375
  }
376
376
  },
377
+ knowledge: {
378
+ async search(t) {
379
+ var e;
380
+ const r = (e = t == null ? void 0 : t.query) == null ? void 0 : e.trim();
381
+ if (!r) throw new Error("knowledge.search requires a query");
382
+ return S(
383
+ "/app-api/knowledge/search",
384
+ {
385
+ method: "POST",
386
+ headers: { "Content-Type": "application/json" },
387
+ body: JSON.stringify({
388
+ workspaceId: t.workspaceId,
389
+ query: r,
390
+ maxResults: t.maxResults,
391
+ generateSearchQuery: t.generateSearchQuery,
392
+ sourceId: t.sourceId,
393
+ includeSourceUrls: t.includeSourceUrls,
394
+ queries: t.queries
395
+ })
396
+ }
397
+ );
398
+ }
399
+ },
377
400
  data(t = "private") {
378
401
  return E(t, "");
379
402
  }
380
403
  };
381
404
  }
382
405
  export {
383
- N as PromteAppProvider,
384
- S as usePromte,
385
- F as usePromteClient,
406
+ _ as PromteAppProvider,
407
+ j as usePromte,
408
+ I as usePromteClient,
386
409
  V as usePromteDarkMode,
387
- K as usePromteModels,
388
- z as usePromteSettings,
389
- I as usePromteToken,
390
- W as usePromteUser
410
+ W as usePromteModels,
411
+ G as usePromteSettings,
412
+ z as usePromteToken,
413
+ Q as usePromteUser
391
414
  };
@@ -1 +1 @@
1
- (function(w,T){typeof exports=="object"&&typeof module<"u"?T(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],T):(w=typeof globalThis<"u"?globalThis:w||self,T(w.PromteAppLibrary={},w.jsxRuntime,w.react))})(this,function(w,T,a){"use strict";const M=a.createContext(null);function L({children:d,expectedParentOrigin:m,initTargetOrigin:E,retryInit:l={enabled:!0,intervalMs:500,maxAttempts:20}}){const[y,$]=a.useState(null),[v,j]=a.useState(null),[g,S]=a.useState(null),[P,t]=a.useState(null),[s,e]=a.useState(null),n=a.useMemo(()=>s?"booting":y?v?"ready":"waiting_for_token":"waiting_for_settings",[y,v,s]),r=n==="ready",c=a.useMemo(()=>E||m||"*",[E,m]),i=a.useCallback(()=>{var o;try{const h={type:"init"};(o=window.parent)==null||o.postMessage(h,c)}catch(h){e((h==null?void 0:h.message)||"Failed to post init")}},[c]);a.useEffect(()=>{i()},[i]),a.useEffect(()=>{if(!(l!=null&&l.enabled)||y)return;const o=l.intervalMs??500,h=l.maxAttempts??20;let u=0;const p=window.setInterval(()=>{if(y){window.clearInterval(p);return}if(u+=1,u>h){window.clearInterval(p);return}i()},o);return()=>window.clearInterval(p)},[l,y,i]),a.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;$(p),p!=null&&p.user&&t(p.user),e(null);return}if(u.type==="set-token"&&typeof u.value=="string"){j(u.value),e(null);return}if(u.type==="set-dark-mode"&&typeof u.value=="boolean"){S(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=a.useMemo(()=>J(()=>y,()=>v),[y,v]),b=a.useMemo(()=>({settings:y,token:v,isDarkMode:g,user:P,ready:r,state:n,error:s,client:f}),[y,v,g,P,r,n,s,f]);return T.jsx(M.Provider,{value:b,children:d})}function k(){const d=a.useContext(M);if(!d)throw new Error("usePromte must be used inside <PromteAppProvider>");return d}function B(){return k().settings}function D(){return k().token}function F(){return k().isDarkMode}function _(){return k().user}function C(){return k().client}function G(d={}){const{ready:m}=k(),E=C(),[l,y]=a.useState([]),[$,v]=a.useState(!1),[j,g]=a.useState(null),S=a.useMemo(()=>(Array.isArray(d.type)?d.type:d.type?[d.type]:[]).filter(Boolean).map(n=>String(n)).join(","),[d.type]),P=d.configuredOnly===!0,t=d.auto!==!1,s=a.useCallback(async()=>{if(!m)return[];v(!0),g(null);try{const e=S?S.split(",").filter(Boolean):void 0,n=await E.models({type:e,configuredOnly:P});return y(n),n}catch(e){const n=e instanceof Error?e.message:String(e);throw g(n),e}finally{v(!1)}},[E,P,m,S]);return a.useEffect(()=>{!t||!m||s().catch(()=>{})},[t,m,s]),{models:l,loading:$,error:j,reload:s}}function J(d,m){const E=t=>typeof t=="string"&&t.startsWith("gpt-5");async function l(t,s){const e=d(),n=m();if(!e)throw new Error("Promte settings not received yet");if(!n)throw new Error("Promte token not received yet");const r=e.backendUrl.replace(/\/+$/,""),c=String(t||"").replace(/^\/+/,""),i=`${r}/${c}`;return await fetch(i,{...s,headers:{...s.headers||{},Authorization:`Bearer ${n}`}})}async function y(t,s){const e=await l(`/app-api/data/${t}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)}),n=await e.json().catch(()=>({}));if(!e.ok)throw new Error((n==null?void 0:n.error)||`Request failed (${e.status})`);return n==null?void 0:n.value}async function $(t){const s=new URLSearchParams;t.scope&&s.set("scope",t.scope),t.path&&s.set("path",t.path);const e=await l(`/app-api/data?${s.toString()}`,{method:"GET"}),n=await e.json().catch(()=>({}));if(!e.ok)throw new Error((n==null?void 0:n.error)||`Request failed (${e.status})`);return n==null?void 0:n.value}async function v(t){const s=new URLSearchParams,e=Array.isArray(t==null?void 0:t.type)?t==null?void 0:t.type:t!=null&&t.type?[t.type]:[];e.length>0&&s.set("type",e.join(",")),t!=null&&t.configuredOnly&&s.set("configuredOnly","true");const n=await l(`/app-api/models${s.toString()?`?${s.toString()}`:""}`,{method:"GET"}),r=await n.json().catch(()=>({}));if(!n.ok)throw new Error((r==null?void 0:r.error)||`Request failed (${n.status})`);return(Array.isArray(r==null?void 0:r.models)?r.models:[]).map(i=>{if(!i||typeof i!="object")return null;const f=typeof i.id=="string"?i.id.trim():"",b=typeof i.label=="string"?i.label.trim():f,o=i.type,h=i.configured===!0,u=typeof i.source=="string"&&i.source.trim()?i.source.trim():void 0;return!f||o!=="llm"&&o!=="embedding"&&o!=="image"&&o!=="stt"&&o!=="tts"?null:{id:f,label:b||f,type:o,configured:h,source:u}}).filter(i=>!!i)}async function j(t,s){const e=await l(t,s),r=(e.headers.get("content-type")||"").includes("application/json")?await e.json().catch(()=>({})):await e.text();if(!e.ok)throw new Error(typeof r=="string"?r||`Request failed (${e.status})`:(r==null?void 0:r.error)||(r==null?void 0:r.message)||`Request failed (${e.status})`);return r}const g=t=>t?t.split("/").map(s=>s.trim()).filter(Boolean).join("/"):"",S=(t,s)=>{const e=g(t),n=g(s);return e?n?`${e}/${n}`:e:n},P=(t,s)=>{const e={scope:t};return{async get(){const n=g(s);return $({...e,path:n||void 0})},async set(n){const r=g(s);return y("set",{...e,path:r||void 0,value:n})},async update(n){if(!n||typeof n!="object")throw new Error("update requires an object");const r={};for(const[c,i]of Object.entries(n)){const f=S(s,c);if(!f)throw new Error("update paths must be non-empty");r[f]=i}return y("update",{...e,updates:r})},async remove(){const n=g(s);return y("remove",{...e,path:n||void 0})},async push(n){const r=g(s);if(!r)throw new Error("push requires a path");return y("array-push",{...e,path:r,value:n})},ref(n){const r=S(s,n);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:e,...n}=t,r=s??e,c={...n,stream:!1};r&&E(t.model)&&(c.reasoning_effort=r);const i=await l("/openai/chat/completions",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(c)}),b=(i.headers.get("content-type")||"").includes("application/json")?await i.json():await i.text();if(!i.ok)throw new Error(typeof b=="string"?b:((o=b==null?void 0:b.error)==null?void 0:o.message)||`Request failed (${i.status})`);return b},async chatText(t){var e,n,r;const s=await this.chatCompletions(t);return((r=(n=(e=s==null?void 0:s.choices)==null?void 0:e[0])==null?void 0:n.message)==null?void 0:r.content)??""},embeddings:{async create(t){var r;const s=(r=t==null?void 0:t.model)==null?void 0:r.trim();if(!s)throw new Error("embeddings.create requires a model");const e=t==null?void 0:t.input;if(!(typeof e=="string"?e.length>0:Array.isArray(e)&&e.length>0&&e.every(c=>typeof c=="string")))throw new Error("embeddings.create requires input as a string or string[]");return j("/openai/embeddings",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({...t,model:s,input:e})})}},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 e=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(!e.ok){const c=await e.text();throw new Error(c||`Request failed (${e.status})`)}return{audio:await e.arrayBuffer(),contentType:e.headers.get("content-type")}},async stt(t){var u,p,R;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 U=A.toLowerCase(),O=U.split("-")[0];return O.length===2?O:U},e=typeof File<"u"&&t.file instanceof File,n=e&&t.file.name.split(".").pop()||"webm",r=t.ext||n,c=new FormData;e?c.set("file",t.file):c.set("file",t.file,`audio.${r}`);const i=s(t.language);i&&c.set("language",i),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)||((R=(p=o==null?void 0:o.results)==null?void 0:p[0])==null?void 0:R.text)||"",raw:o}},async voices(t){const s=new URLSearchParams;t!=null&&t.locale&&s.set("locale",t.locale);const e=await l(`/app-api/audio/tts/voices${s.toString()?`?${s}`:""}`,{method:"GET"}),n=await e.json().catch(()=>[]);if(!e.ok)throw new Error((n==null?void 0:n.error)||`Request failed (${e.status})`);return Array.isArray(n)?n:(n==null?void 0:n.voices)||[]}},web:{async scrapeUrl(t){var e;const s=(e=t==null?void 0:t.url)==null?void 0:e.trim();if(!s)throw new Error("web.scrapeUrl requires a url");return j("/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,"")}}}w.PromteAppProvider=L,w.usePromte=k,w.usePromteClient=C,w.usePromteDarkMode=F,w.usePromteModels=G,w.usePromteSettings=B,w.usePromteToken=D,w.usePromteUser=_,Object.defineProperty(w,Symbol.toStringTag,{value:"Module"})});
1
+ (function(h,T){typeof exports=="object"&&typeof module<"u"?T(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],T):(h=typeof globalThis<"u"?globalThis:h||self,T(h.PromteAppLibrary={},h.jsxRuntime,h.react))})(this,function(h,T,i){"use strict";const R=i.createContext(null);function L({children:d,expectedParentOrigin:m,initTargetOrigin:S,retryInit:f={enabled:!0,intervalMs:500,maxAttempts:20}}){const[y,$]=i.useState(null),[v,j]=i.useState(null),[g,E]=i.useState(null),[k,t]=i.useState(null),[s,e]=i.useState(null),n=i.useMemo(()=>s?"booting":y?v?"ready":"waiting_for_token":"waiting_for_settings",[y,v,s]),r=n==="ready",c=i.useMemo(()=>S||m||"*",[S,m]),a=i.useCallback(()=>{var o;try{const w={type:"init"};(o=window.parent)==null||o.postMessage(w,c)}catch(w){e((w==null?void 0:w.message)||"Failed to post init")}},[c]);i.useEffect(()=>{a()},[a]),i.useEffect(()=>{if(!(f!=null&&f.enabled)||y)return;const o=f.intervalMs??500,w=f.maxAttempts??20;let u=0;const p=window.setInterval(()=>{if(y){window.clearInterval(p);return}if(u+=1,u>w){window.clearInterval(p);return}a()},o);return()=>window.clearInterval(p)},[f,y,a]),i.useEffect(()=>{const o=w=>{if(m&&w.origin!==m)return;const u=w.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;$(p),p!=null&&p.user&&t(p.user),e(null);return}if(u.type==="set-token"&&typeof u.value=="string"){j(u.value),e(null);return}if(u.type==="set-dark-mode"&&typeof u.value=="boolean"){E(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 l=i.useMemo(()=>N(()=>y,()=>v),[y,v]),b=i.useMemo(()=>({settings:y,token:v,isDarkMode:g,user:k,ready:r,state:n,error:s,client:l}),[y,v,g,k,r,n,s,l]);return T.jsx(R.Provider,{value:b,children:d})}function P(){const d=i.useContext(R);if(!d)throw new Error("usePromte must be used inside <PromteAppProvider>");return d}function B(){return P().settings}function D(){return P().token}function I(){return P().isDarkMode}function F(){return P().user}function x(){return P().client}function J(d={}){const{ready:m}=P(),S=x(),[f,y]=i.useState([]),[$,v]=i.useState(!1),[j,g]=i.useState(null),E=i.useMemo(()=>(Array.isArray(d.type)?d.type:d.type?[d.type]:[]).filter(Boolean).map(n=>String(n)).join(","),[d.type]),k=d.configuredOnly===!0,t=d.auto!==!1,s=i.useCallback(async()=>{if(!m)return[];v(!0),g(null);try{const e=E?E.split(",").filter(Boolean):void 0,n=await S.models({type:e,configuredOnly:k});return y(n),n}catch(e){const n=e instanceof Error?e.message:String(e);throw g(n),e}finally{v(!1)}},[S,k,m,E]);return i.useEffect(()=>{!t||!m||s().catch(()=>{})},[t,m,s]),{models:f,loading:$,error:j,reload:s}}function N(d,m){const S=t=>typeof t=="string"&&t.startsWith("gpt-5");async function f(t,s){const e=d(),n=m();if(!e)throw new Error("Promte settings not received yet");if(!n)throw new Error("Promte token not received yet");const r=e.backendUrl.replace(/\/+$/,""),c=String(t||"").replace(/^\/+/,""),a=`${r}/${c}`;return await fetch(a,{...s,headers:{...s.headers||{},Authorization:`Bearer ${n}`}})}async function y(t,s){const e=await f(`/app-api/data/${t}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)}),n=await e.json().catch(()=>({}));if(!e.ok)throw new Error((n==null?void 0:n.error)||`Request failed (${e.status})`);return n==null?void 0:n.value}async function $(t){const s=new URLSearchParams;t.scope&&s.set("scope",t.scope),t.path&&s.set("path",t.path);const e=await f(`/app-api/data?${s.toString()}`,{method:"GET"}),n=await e.json().catch(()=>({}));if(!e.ok)throw new Error((n==null?void 0:n.error)||`Request failed (${e.status})`);return n==null?void 0:n.value}async function v(t){const s=new URLSearchParams,e=Array.isArray(t==null?void 0:t.type)?t==null?void 0:t.type:t!=null&&t.type?[t.type]:[];e.length>0&&s.set("type",e.join(",")),t!=null&&t.configuredOnly&&s.set("configuredOnly","true");const n=await f(`/app-api/models${s.toString()?`?${s.toString()}`:""}`,{method:"GET"}),r=await n.json().catch(()=>({}));if(!n.ok)throw new Error((r==null?void 0:r.error)||`Request failed (${n.status})`);return(Array.isArray(r==null?void 0:r.models)?r.models:[]).map(a=>{if(!a||typeof a!="object")return null;const l=typeof a.id=="string"?a.id.trim():"",b=typeof a.label=="string"?a.label.trim():l,o=a.type,w=a.configured===!0,u=typeof a.source=="string"&&a.source.trim()?a.source.trim():void 0;return!l||o!=="llm"&&o!=="embedding"&&o!=="image"&&o!=="stt"&&o!=="tts"?null:{id:l,label:b||l,type:o,configured:w,source:u}}).filter(a=>!!a)}async function j(t,s){const e=await f(t,s),r=(e.headers.get("content-type")||"").includes("application/json")?await e.json().catch(()=>({})):await e.text();if(!e.ok)throw new Error(typeof r=="string"?r||`Request failed (${e.status})`:(r==null?void 0:r.error)||(r==null?void 0:r.message)||`Request failed (${e.status})`);return r}const g=t=>t?t.split("/").map(s=>s.trim()).filter(Boolean).join("/"):"",E=(t,s)=>{const e=g(t),n=g(s);return e?n?`${e}/${n}`:e:n},k=(t,s)=>{const e={scope:t};return{async get(){const n=g(s);return $({...e,path:n||void 0})},async set(n){const r=g(s);return y("set",{...e,path:r||void 0,value:n})},async update(n){if(!n||typeof n!="object")throw new Error("update requires an object");const r={};for(const[c,a]of Object.entries(n)){const l=E(s,c);if(!l)throw new Error("update paths must be non-empty");r[l]=a}return y("update",{...e,updates:r})},async remove(){const n=g(s);return y("remove",{...e,path:n||void 0})},async push(n){const r=g(s);if(!r)throw new Error("push requires a path");return y("array-push",{...e,path:r,value:n})},ref(n){const r=E(s,n);if(!r)throw new Error("ref requires a path");return k(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:e,...n}=t,r=s??e,c={...n,stream:!1};r&&S(t.model)&&(c.reasoning_effort=r);const a=await f("/openai/chat/completions",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(c)}),b=(a.headers.get("content-type")||"").includes("application/json")?await a.json():await a.text();if(!a.ok)throw new Error(typeof b=="string"?b:((o=b==null?void 0:b.error)==null?void 0:o.message)||`Request failed (${a.status})`);return b},async chatText(t){var e,n,r;const s=await this.chatCompletions(t);return((r=(n=(e=s==null?void 0:s.choices)==null?void 0:e[0])==null?void 0:n.message)==null?void 0:r.content)??""},embeddings:{async create(t){var r;const s=(r=t==null?void 0:t.model)==null?void 0:r.trim();if(!s)throw new Error("embeddings.create requires a model");const e=t==null?void 0:t.input;if(!(typeof e=="string"?e.length>0:Array.isArray(e)&&e.length>0&&e.every(c=>typeof c=="string")))throw new Error("embeddings.create requires input as a string or string[]");return j("/openai/embeddings",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({...t,model:s,input:e})})}},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 e=await f("/app-api/audio/tts",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({text:s,voice:t.voice,lang:t.lang})});if(!e.ok){const c=await e.text();throw new Error(c||`Request failed (${e.status})`)}return{audio:await e.arrayBuffer(),contentType:e.headers.get("content-type")}},async stt(t){var u,p,C;if(!(t!=null&&t.file))throw new Error("audio.stt requires a file");const s=M=>{if(!M)return;const A=M.trim();if(!A)return;const U=A.toLowerCase(),O=U.split("-")[0];return O.length===2?O:U},e=typeof File<"u"&&t.file instanceof File,n=e&&t.file.name.split(".").pop()||"webm",r=t.ext||n,c=new FormData;e?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 l=await f(`/app-api/audio/stt?ext=${encodeURIComponent(r)}`,{method:"POST",body:c}),o=(l.headers.get("content-type")||"").includes("application/json")?await l.json():await l.text();if(!l.ok)throw new Error(typeof o=="string"?o:((u=o==null?void 0:o.error)==null?void 0:u.message)||`Request failed (${l.status})`);return{text:typeof o=="string"?o:(o==null?void 0:o.text)||(o==null?void 0:o.original)||((C=(p=o==null?void 0:o.results)==null?void 0:p[0])==null?void 0:C.text)||"",raw:o}},async voices(t){const s=new URLSearchParams;t!=null&&t.locale&&s.set("locale",t.locale);const e=await f(`/app-api/audio/tts/voices${s.toString()?`?${s}`:""}`,{method:"GET"}),n=await e.json().catch(()=>[]);if(!e.ok)throw new Error((n==null?void 0:n.error)||`Request failed (${e.status})`);return Array.isArray(n)?n:(n==null?void 0:n.voices)||[]}},web:{async scrapeUrl(t){var e;const s=(e=t==null?void 0:t.url)==null?void 0:e.trim();if(!s)throw new Error("web.scrapeUrl requires a url");return j("/app-api/web/scrape-url",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:s,maxChars:t.maxChars})})}},knowledge:{async search(t){var e;const s=(e=t==null?void 0:t.query)==null?void 0:e.trim();if(!s)throw new Error("knowledge.search requires a query");return j("/app-api/knowledge/search",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({workspaceId:t.workspaceId,query:s,maxResults:t.maxResults,generateSearchQuery:t.generateSearchQuery,sourceId:t.sourceId,includeSourceUrls:t.includeSourceUrls,queries:t.queries})})}},data(t="private"){return k(t,"")}}}h.PromteAppProvider=L,h.usePromte=P,h.usePromteClient=x,h.usePromteDarkMode=I,h.usePromteModels=J,h.usePromteSettings=B,h.usePromteToken=D,h.usePromteUser=F,Object.defineProperty(h,Symbol.toStringTag,{value:"Module"})});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@promte/app-library",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "files": [