@promte/app-library 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +109 -0
- package/dist/index.d.ts +104 -0
- package/dist/index.mjs +296 -97
- package/dist/index.umd.cjs +1 -1
- package/package.json +1 -1
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
|
@@ -1,11 +1,69 @@
|
|
|
1
1
|
import { default as default_2 } from 'react';
|
|
2
2
|
import { JSX as JSX_2 } from 'react/jsx-runtime';
|
|
3
3
|
|
|
4
|
+
export declare type AppDataRef = {
|
|
5
|
+
get(): Promise<any>;
|
|
6
|
+
set(value: any): Promise<any>;
|
|
7
|
+
update(updates: AppDataUpdateMap): Promise<any>;
|
|
8
|
+
remove(): Promise<any>;
|
|
9
|
+
push(value: any): Promise<any>;
|
|
10
|
+
ref(path: string): AppDataRef;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export declare type AppDataScope = "private" | "public";
|
|
14
|
+
|
|
15
|
+
export declare type AppDataUpdateMap = Record<string, any>;
|
|
16
|
+
|
|
17
|
+
export declare type AudioSttRequest = {
|
|
18
|
+
file: File | Blob;
|
|
19
|
+
language?: string;
|
|
20
|
+
prompt?: string;
|
|
21
|
+
ext?: string;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export declare type AudioSttResponse = {
|
|
25
|
+
text: string;
|
|
26
|
+
raw: any;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export declare type AudioTtsRequest = {
|
|
30
|
+
text: string;
|
|
31
|
+
voice?: string;
|
|
32
|
+
lang?: string;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export declare type AudioTtsResponse = {
|
|
36
|
+
audio: ArrayBuffer;
|
|
37
|
+
contentType: string | null;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export declare type AudioVoiceInfo = {
|
|
41
|
+
short_name?: string;
|
|
42
|
+
locale?: string;
|
|
43
|
+
local_name?: string;
|
|
44
|
+
locale_english_name?: string;
|
|
45
|
+
locale_native_name?: string;
|
|
46
|
+
gender?: string;
|
|
47
|
+
voice_type?: string;
|
|
48
|
+
name?: string;
|
|
49
|
+
display_name?: string;
|
|
50
|
+
style_list?: string[];
|
|
51
|
+
sample_rate_hertz?: string;
|
|
52
|
+
status?: string;
|
|
53
|
+
words_per_minute?: string;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export declare type AudioVoicesRequest = {
|
|
57
|
+
locale?: string;
|
|
58
|
+
};
|
|
59
|
+
|
|
4
60
|
export declare type ChatCompletionsRequest = {
|
|
5
61
|
model: string;
|
|
6
62
|
messages: ChatMessage[];
|
|
7
63
|
stream?: false;
|
|
8
64
|
temperature?: number;
|
|
65
|
+
reasoningEffort?: ReasoningEffort;
|
|
66
|
+
reasoning_effort?: ReasoningEffort;
|
|
9
67
|
};
|
|
10
68
|
|
|
11
69
|
export declare type ChatCompletionsResponse = any;
|
|
@@ -31,14 +89,22 @@ export declare type PromteAppProviderProps = {
|
|
|
31
89
|
export declare type PromteClient = {
|
|
32
90
|
isReady(): boolean;
|
|
33
91
|
getBackendUrl(): string | null;
|
|
92
|
+
models(req?: PromteModelsRequest): Promise<PromteModelInfo[]>;
|
|
34
93
|
chatCompletions(req: ChatCompletionsRequest): Promise<ChatCompletionsResponse>;
|
|
35
94
|
chatText(req: ChatCompletionsRequest): Promise<string>;
|
|
95
|
+
audio: {
|
|
96
|
+
tts(req: AudioTtsRequest): Promise<AudioTtsResponse>;
|
|
97
|
+
stt(req: AudioSttRequest): Promise<AudioSttResponse>;
|
|
98
|
+
voices(req?: AudioVoicesRequest): Promise<AudioVoiceInfo[]>;
|
|
99
|
+
};
|
|
100
|
+
data(scope?: AppDataScope): AppDataRef;
|
|
36
101
|
};
|
|
37
102
|
|
|
38
103
|
declare type PromteCtxValue = {
|
|
39
104
|
settings: PromteSettings | null;
|
|
40
105
|
token: string | null;
|
|
41
106
|
isDarkMode: boolean | null;
|
|
107
|
+
user: PromteUser | null;
|
|
42
108
|
ready: boolean;
|
|
43
109
|
state: PromteHandshakeState;
|
|
44
110
|
error: string | null;
|
|
@@ -47,21 +113,59 @@ declare type PromteCtxValue = {
|
|
|
47
113
|
|
|
48
114
|
export declare type PromteHandshakeState = "booting" | "waiting_for_settings" | "waiting_for_token" | "ready";
|
|
49
115
|
|
|
116
|
+
export declare type PromteModelInfo = {
|
|
117
|
+
id: string;
|
|
118
|
+
label: string;
|
|
119
|
+
type: PromteModelType;
|
|
120
|
+
configured: boolean;
|
|
121
|
+
source?: string;
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
export declare type PromteModelsRequest = {
|
|
125
|
+
type?: PromteModelType | PromteModelType[];
|
|
126
|
+
configuredOnly?: boolean;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
export declare type PromteModelType = "llm" | "embedding" | "image" | "stt" | "tts";
|
|
130
|
+
|
|
50
131
|
export declare type PromteSettings = {
|
|
51
132
|
workspaceId: string;
|
|
52
133
|
version: number;
|
|
53
134
|
backendUrl: string;
|
|
54
135
|
parentOrigin?: string;
|
|
136
|
+
user?: PromteUser;
|
|
55
137
|
};
|
|
56
138
|
|
|
139
|
+
export declare type PromteUser = {
|
|
140
|
+
email?: string;
|
|
141
|
+
isAdmin?: boolean;
|
|
142
|
+
role?: string;
|
|
143
|
+
workspaceId?: string;
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
export declare type ReasoningEffort = "minimal" | "low" | "medium" | "high";
|
|
147
|
+
|
|
57
148
|
export declare function usePromte(): PromteCtxValue;
|
|
58
149
|
|
|
59
150
|
export declare function usePromteClient(): PromteClient;
|
|
60
151
|
|
|
61
152
|
export declare function usePromteDarkMode(): boolean;
|
|
62
153
|
|
|
154
|
+
export declare function usePromteModels(options?: UsePromteModelsOptions): {
|
|
155
|
+
models: PromteModelInfo[];
|
|
156
|
+
loading: boolean;
|
|
157
|
+
error: string;
|
|
158
|
+
reload: () => Promise<PromteModelInfo[]>;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
export declare type UsePromteModelsOptions = PromteModelsRequest & {
|
|
162
|
+
auto?: boolean;
|
|
163
|
+
};
|
|
164
|
+
|
|
63
165
|
export declare function usePromteSettings(): PromteSettings;
|
|
64
166
|
|
|
65
167
|
export declare function usePromteToken(): string;
|
|
66
168
|
|
|
169
|
+
export declare function usePromteUser(): PromteUser;
|
|
170
|
+
|
|
67
171
|
export { }
|
package/dist/index.mjs
CHANGED
|
@@ -1,145 +1,344 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { createContext as
|
|
3
|
-
const
|
|
4
|
-
function
|
|
5
|
-
children:
|
|
6
|
-
expectedParentOrigin:
|
|
7
|
-
initTargetOrigin:
|
|
8
|
-
retryInit:
|
|
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 }
|
|
9
9
|
}) {
|
|
10
|
-
const [
|
|
11
|
-
var
|
|
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;
|
|
12
12
|
try {
|
|
13
|
-
const
|
|
14
|
-
(
|
|
15
|
-
} catch (
|
|
16
|
-
|
|
13
|
+
const w = { type: "init" };
|
|
14
|
+
(v = window.parent) == null || v.postMessage(w, s);
|
|
15
|
+
} catch (w) {
|
|
16
|
+
e((w == null ? void 0 : w.message) || "Failed to post init");
|
|
17
17
|
}
|
|
18
|
-
}, [
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}, [
|
|
22
|
-
if (!(
|
|
23
|
-
const
|
|
24
|
-
let
|
|
25
|
-
const
|
|
26
|
-
if (
|
|
27
|
-
window.clearInterval(
|
|
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(() => {
|
|
26
|
+
if (m) {
|
|
27
|
+
window.clearInterval(l);
|
|
28
28
|
return;
|
|
29
29
|
}
|
|
30
|
-
if (
|
|
31
|
-
window.clearInterval(
|
|
30
|
+
if (c += 1, c > w) {
|
|
31
|
+
window.clearInterval(l);
|
|
32
32
|
return;
|
|
33
33
|
}
|
|
34
|
-
|
|
35
|
-
},
|
|
36
|
-
return () => window.clearInterval(
|
|
37
|
-
}, [
|
|
38
|
-
const
|
|
39
|
-
if (
|
|
40
|
-
const
|
|
41
|
-
if (!(!
|
|
42
|
-
if (
|
|
43
|
-
const
|
|
44
|
-
if (!(
|
|
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)
|
|
45
45
|
return;
|
|
46
|
-
|
|
46
|
+
x(l), l != null && l.user && r(l.user), e(null);
|
|
47
47
|
return;
|
|
48
48
|
}
|
|
49
|
-
if (
|
|
50
|
-
|
|
49
|
+
if (c.type === "set-token" && typeof c.value == "string") {
|
|
50
|
+
g(c.value), e(null);
|
|
51
51
|
return;
|
|
52
52
|
}
|
|
53
|
-
if (
|
|
54
|
-
|
|
53
|
+
if (c.type === "set-dark-mode" && typeof c.value == "boolean") {
|
|
54
|
+
b(c.value);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (c.type === "set-user" && typeof c.value == "object") {
|
|
58
|
+
r(c.value);
|
|
55
59
|
return;
|
|
56
60
|
}
|
|
57
61
|
}
|
|
58
62
|
};
|
|
59
|
-
return window.addEventListener("message",
|
|
60
|
-
}, [
|
|
61
|
-
const
|
|
62
|
-
() =>
|
|
63
|
-
() =>
|
|
64
|
-
), [
|
|
63
|
+
return window.addEventListener("message", v), () => window.removeEventListener("message", v);
|
|
64
|
+
}, [p]);
|
|
65
|
+
const y = P(() => O(
|
|
66
|
+
() => m,
|
|
67
|
+
() => h
|
|
68
|
+
), [m, h]), a = P(
|
|
65
69
|
() => ({
|
|
66
|
-
settings:
|
|
67
|
-
token:
|
|
68
|
-
isDarkMode:
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
settings: m,
|
|
71
|
+
token: h,
|
|
72
|
+
isDarkMode: k,
|
|
73
|
+
user: t,
|
|
74
|
+
ready: u,
|
|
75
|
+
state: o,
|
|
76
|
+
error: n,
|
|
77
|
+
client: y
|
|
73
78
|
}),
|
|
74
|
-
[
|
|
79
|
+
[m, h, k, t, u, o, n, y]
|
|
75
80
|
);
|
|
76
|
-
return /* @__PURE__ */
|
|
81
|
+
return /* @__PURE__ */ B(U.Provider, { value: a, children: f });
|
|
77
82
|
}
|
|
78
|
-
function
|
|
79
|
-
const
|
|
80
|
-
if (!
|
|
83
|
+
function $() {
|
|
84
|
+
const f = D(U);
|
|
85
|
+
if (!f)
|
|
81
86
|
throw new Error("usePromte must be used inside <PromteAppProvider>");
|
|
82
|
-
return
|
|
87
|
+
return f;
|
|
83
88
|
}
|
|
84
|
-
function
|
|
85
|
-
return
|
|
89
|
+
function J() {
|
|
90
|
+
return $().settings;
|
|
86
91
|
}
|
|
87
|
-
function
|
|
88
|
-
return
|
|
92
|
+
function N() {
|
|
93
|
+
return $().token;
|
|
94
|
+
}
|
|
95
|
+
function V() {
|
|
96
|
+
return $().isDarkMode;
|
|
97
|
+
}
|
|
98
|
+
function I() {
|
|
99
|
+
return $().user;
|
|
89
100
|
}
|
|
90
101
|
function F() {
|
|
91
|
-
return
|
|
102
|
+
return $().client;
|
|
92
103
|
}
|
|
93
|
-
function
|
|
94
|
-
|
|
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);
|
|
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;
|
|
114
|
+
} finally {
|
|
115
|
+
h(!1);
|
|
116
|
+
}
|
|
117
|
+
}, [E, t, p, b]);
|
|
118
|
+
return S(() => {
|
|
119
|
+
!r || !p || n().catch(() => {
|
|
120
|
+
});
|
|
121
|
+
}, [r, p, n]), { models: d, loading: x, error: g, reload: n };
|
|
95
122
|
}
|
|
96
|
-
function
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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();
|
|
127
|
+
if (!n) throw new Error("Promte settings not received yet");
|
|
100
128
|
if (!e) throw new Error("Promte token not received yet");
|
|
101
|
-
const
|
|
102
|
-
return await fetch(
|
|
103
|
-
...
|
|
129
|
+
const o = n.backendUrl.replace(/\/+$/, ""), u = String(t || "").replace(/^\/+/, ""), s = `${o}/${u}`;
|
|
130
|
+
return await fetch(s, {
|
|
131
|
+
...r,
|
|
104
132
|
headers: {
|
|
105
|
-
...
|
|
133
|
+
...r.headers || {},
|
|
106
134
|
Authorization: `Bearer ${e}`
|
|
107
135
|
}
|
|
108
136
|
});
|
|
109
137
|
}
|
|
138
|
+
async function m(t, r) {
|
|
139
|
+
const n = await d(`/app-api/data/${t}`, {
|
|
140
|
+
method: "POST",
|
|
141
|
+
headers: { "Content-Type": "application/json" },
|
|
142
|
+
body: JSON.stringify(r)
|
|
143
|
+
}), e = await n.json().catch(() => ({}));
|
|
144
|
+
if (!n.ok)
|
|
145
|
+
throw new Error(
|
|
146
|
+
(e == null ? void 0 : e.error) || `Request failed (${n.status})`
|
|
147
|
+
);
|
|
148
|
+
return e == null ? void 0 : e.value;
|
|
149
|
+
}
|
|
150
|
+
async function x(t) {
|
|
151
|
+
const r = new URLSearchParams();
|
|
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()}`, {
|
|
154
|
+
method: "GET"
|
|
155
|
+
}), e = await n.json().catch(() => ({}));
|
|
156
|
+
if (!n.ok)
|
|
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 h(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 d(
|
|
164
|
+
`/app-api/models${r.toString() ? `?${r.toString()}` : ""}`,
|
|
165
|
+
{ method: "GET" }
|
|
166
|
+
), o = await e.json().catch(() => ({}));
|
|
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
|
|
178
|
+
};
|
|
179
|
+
}).filter(
|
|
180
|
+
(s) => !!s
|
|
181
|
+
);
|
|
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);
|
|
185
|
+
return n ? e ? `${n}/${e}` : n : e;
|
|
186
|
+
}, b = (t, r) => {
|
|
187
|
+
const n = { scope: t };
|
|
188
|
+
return {
|
|
189
|
+
async get() {
|
|
190
|
+
const e = g(r);
|
|
191
|
+
return x({ ...n, path: e || void 0 });
|
|
192
|
+
},
|
|
193
|
+
async set(e) {
|
|
194
|
+
const o = g(r);
|
|
195
|
+
return m("set", {
|
|
196
|
+
...n,
|
|
197
|
+
path: o || void 0,
|
|
198
|
+
value: e
|
|
199
|
+
});
|
|
200
|
+
},
|
|
201
|
+
async update(e) {
|
|
202
|
+
if (!e || typeof e != "object")
|
|
203
|
+
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)
|
|
208
|
+
throw new Error("update paths must be non-empty");
|
|
209
|
+
o[i] = s;
|
|
210
|
+
}
|
|
211
|
+
return m("update", { ...n, updates: o });
|
|
212
|
+
},
|
|
213
|
+
async remove() {
|
|
214
|
+
const e = g(r);
|
|
215
|
+
return m("remove", { ...n, path: e || void 0 });
|
|
216
|
+
},
|
|
217
|
+
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 });
|
|
221
|
+
},
|
|
222
|
+
ref(e) {
|
|
223
|
+
const o = k(r, e);
|
|
224
|
+
if (!o) throw new Error("ref requires a path");
|
|
225
|
+
return b(t, o);
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
};
|
|
110
229
|
return {
|
|
111
230
|
isReady() {
|
|
112
|
-
return !!
|
|
231
|
+
return !!f() && !!p();
|
|
113
232
|
},
|
|
114
233
|
getBackendUrl() {
|
|
115
|
-
var
|
|
116
|
-
return ((
|
|
234
|
+
var t;
|
|
235
|
+
return ((t = f()) == null ? void 0 : t.backendUrl) ?? null;
|
|
117
236
|
},
|
|
118
|
-
async
|
|
119
|
-
|
|
120
|
-
|
|
237
|
+
async models(t) {
|
|
238
|
+
return h(t);
|
|
239
|
+
},
|
|
240
|
+
async chatCompletions(t) {
|
|
241
|
+
var a;
|
|
242
|
+
const {
|
|
243
|
+
reasoningEffort: r,
|
|
244
|
+
reasoning_effort: n,
|
|
245
|
+
...e
|
|
246
|
+
} = t, o = r ?? n, u = {
|
|
247
|
+
...e,
|
|
248
|
+
stream: !1
|
|
249
|
+
};
|
|
250
|
+
o && E(t.model) && (u.reasoning_effort = o);
|
|
251
|
+
const s = await d("/openai/chat/completions", {
|
|
121
252
|
method: "POST",
|
|
122
253
|
headers: { "Content-Type": "application/json" },
|
|
123
|
-
body: JSON.stringify(
|
|
124
|
-
}),
|
|
125
|
-
if (!
|
|
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)
|
|
126
257
|
throw new Error(
|
|
127
|
-
typeof
|
|
258
|
+
typeof y == "string" ? y : ((a = y == null ? void 0 : y.error) == null ? void 0 : a.message) || `Request failed (${s.status})`
|
|
128
259
|
);
|
|
129
|
-
return
|
|
260
|
+
return y;
|
|
261
|
+
},
|
|
262
|
+
async chatText(t) {
|
|
263
|
+
var n, e, o;
|
|
264
|
+
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) ?? "";
|
|
266
|
+
},
|
|
267
|
+
audio: {
|
|
268
|
+
async tts(t) {
|
|
269
|
+
var o;
|
|
270
|
+
const r = (o = t == null ? void 0 : t.text) == null ? void 0 : o.trim();
|
|
271
|
+
if (!r) throw new Error("audio.tts requires non-empty text");
|
|
272
|
+
const n = await d("/app-api/audio/tts", {
|
|
273
|
+
method: "POST",
|
|
274
|
+
headers: { "Content-Type": "application/json" },
|
|
275
|
+
body: JSON.stringify({
|
|
276
|
+
text: r,
|
|
277
|
+
voice: t.voice,
|
|
278
|
+
lang: t.lang
|
|
279
|
+
})
|
|
280
|
+
});
|
|
281
|
+
if (!n.ok) {
|
|
282
|
+
const u = await n.text();
|
|
283
|
+
throw new Error(u || `Request failed (${n.status})`);
|
|
284
|
+
}
|
|
285
|
+
return {
|
|
286
|
+
audio: await n.arrayBuffer(),
|
|
287
|
+
contentType: n.headers.get("content-type")
|
|
288
|
+
};
|
|
289
|
+
},
|
|
290
|
+
async stt(t) {
|
|
291
|
+
var w, c, l;
|
|
292
|
+
if (!(t != null && t.file)) throw new Error("audio.stt requires a file");
|
|
293
|
+
const r = (R) => {
|
|
294
|
+
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)}`,
|
|
305
|
+
{
|
|
306
|
+
method: "POST",
|
|
307
|
+
body: u
|
|
308
|
+
}
|
|
309
|
+
), a = (i.headers.get("content-type") || "").includes("application/json") ? await i.json() : await i.text();
|
|
310
|
+
if (!i.ok)
|
|
311
|
+
throw new Error(
|
|
312
|
+
typeof a == "string" ? a : ((w = a == null ? void 0 : a.error) == null ? void 0 : w.message) || `Request failed (${i.status})`
|
|
313
|
+
);
|
|
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 };
|
|
315
|
+
},
|
|
316
|
+
async voices(t) {
|
|
317
|
+
const r = new URLSearchParams();
|
|
318
|
+
t != null && t.locale && r.set("locale", t.locale);
|
|
319
|
+
const n = await d(
|
|
320
|
+
`/app-api/audio/tts/voices${r.toString() ? `?${r}` : ""}`,
|
|
321
|
+
{ method: "GET" }
|
|
322
|
+
), e = await n.json().catch(() => []);
|
|
323
|
+
if (!n.ok)
|
|
324
|
+
throw new Error(
|
|
325
|
+
(e == null ? void 0 : e.error) || `Request failed (${n.status})`
|
|
326
|
+
);
|
|
327
|
+
return Array.isArray(e) ? e : (e == null ? void 0 : e.voices) || [];
|
|
328
|
+
}
|
|
130
329
|
},
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const t = await this.chatCompletions(n);
|
|
134
|
-
return ((i = (e = (c = t == null ? void 0 : t.choices) == null ? void 0 : c[0]) == null ? void 0 : e.message) == null ? void 0 : i.content) ?? "";
|
|
330
|
+
data(t = "private") {
|
|
331
|
+
return b(t, "");
|
|
135
332
|
}
|
|
136
333
|
};
|
|
137
334
|
}
|
|
138
335
|
export {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
336
|
+
z as PromteAppProvider,
|
|
337
|
+
$ as usePromte,
|
|
338
|
+
F as usePromteClient,
|
|
339
|
+
V as usePromteDarkMode,
|
|
340
|
+
K as usePromteModels,
|
|
341
|
+
J as usePromteSettings,
|
|
342
|
+
N as usePromteToken,
|
|
343
|
+
I as usePromteUser
|
|
145
344
|
};
|
package/dist/index.umd.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(
|
|
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"})});
|